URL shortner, preg_match not validating - php

Here we go again, I need some help with this.
the preg_match is not working as I want it, it is not validating any of site links. I need a 2nd pair of eyes to help me see what is wrong with my code.
if (!empty($_POST["url"]))
{
if (filter_var($_POST["url"], FILTER_VALIDATE_URL))
{
if (!preg_match('/^http(s)?:\/\/(?:[a-z\d-]+\.)*mysite.com(?:(?=\/)|$)/i', $url))
{
echo "<strong>Error</strong>: Not a valid Mysite.com link or could shorten link";
} else {
$result = $sql->query("SELECT `id` FROM `shortcuts` WHERE `url`='{$_POST["url"]}'");
$id = $result[0]["id"];
if (empty($id))
{
$result = $sql->query("INSERT INTO `shortcuts` (`url`) VALUES ('{$_POST["url"]}')");
if ($result)
{
$id = $sql->get_increment();
if (empty($id))
{
echo "FAILED ENCODE";
exit(1);
}
}
$shorturl = "http://mysite.com/".encode($id);
}
}
}
}

Since you've already validated the URL, why not just use parse_url() on it to extract the host name?
if (false === stristr(parse_url($_POST['url'], PHP_URL_HOST), 'mysite.com')) {
// not valid url
}
Or, if 'mysite.com` must be the last bit of the hostname:
if (0 !== substr_compare(parse_url($_POST['url'], PHP_URL_HOST), 'mysite.com', -10, 10, true)) {
// invalid url
}

Make yourself the code less complicated, so it is easier to debug. You are concerned about a specific problem here if I understood you right:
if (matches_shorturl_pattern($url) {
// go on ...
}
Create yourself a function. Good thing about is, you can test it isolated without submitting something or hitting the database.
/**
* is URL a valid shorturl by syntax?
*
* #param string $url
* #return bool
*/
function matches_shorturl_pattern($url) {
$pattern = '/^http(s)?:\/\/(?:[a-z\d-]+\.)*mysite.com(?:(?=\/)|$)/i';
$result = preg_match($pattern, $url);
if ($result === FALSE) {
throw new Exception('The regex did a poop.');
}
return (bool) $result;
}
It's much easier to test this function alone with the inputs you want to test it again. Also you're properly checking for error conditions then. Good luck.

I found it!,
if (!preg_match('/^http(s)?:\/\/(?:[a-z\d-]+\.)*mysite.com(?:(?=\/)|$)/i', **$url**))
new
if (!preg_match('/^http(s)?:\/\/(?:[a-z\d-]+\.)*mysite.com(?:(?=\/)|$)/i', **$_POST["url"]**))

Related

Comparison of words from the database and output of the result

I need to check the words received from the database with the user's entered word and if there is a match, then output its value from the database, and if not, then output what the user entered.
The code below works fine if there is a match.
function d_typeplace_morf($d_typeplace)
{
global $wpdb;
$typeplace_results = $wpdb->get_results('SELECT vozmozhnyi_variant_mesta, ego_slovoforma_v_predlozhnom_padezhe FROM dEzpra_jet_cct_tip_mest_obrabotki');
if ($typeplace_results) {
foreach ($typeplace_results as $typeplace_result) {
$d_typeplace_raw = mb_strtolower($typeplace_result->vozmozhnyi_variant_mesta);
$d_typeplace_morf = mb_strtolower($typeplace_result->ego_slovoforma_v_predlozhnom_padezhe);
$d_typeplace = mb_strtolower($d_typeplace);
if (stripos($d_typeplace, $d_typeplace_raw) !== false) {
echo $d_typeplace_morf;
}
}
}
}
I'm an amateur in PHP, just learning. And I can't figure out how to output $d_typeplace if no match is found.
I tried to add
else {
echo $d_typeplace;
}
, but I get an array of words from the user entered.
I will be grateful for any help. Also for any suggestions for improving this code.
---Addition---
I apologize for my English. This is a problem in the Russian language, I need to take into account the morphology. To do this, the database has a list of words and their analog, for example, X = Y. I get these words and compare what the user entered. If he entered X, then we output Y. If he led Z, which is not in the database, then we output Z.
Thus, we check $d_typeplace with $d_typeplace_raw and if there is a match, we output $d_typeplace_morf, which is equal to $d_typeplace_raw. And if not, then $d_typeplace (it contains the value that the user entered).
Oh, I'm sorry, I understand myself that I'm explaining stupidly)
I cannot quite understand what you are asking: you need to output the string entered by the user, but you can only print an array?
If this is the case, I think you parsed the string before, in order to therefore you need to do join again the values contained in the array.
Try with:
else {
echo implode(" ", $d_typeplace);
}
--- EDITED ---
Try with:
function d_typeplace_morf($d_typeplace)
{
global $wpdb;
$typeplace_results = $wpdb->get_results('SELECT vozmozhnyi_variant_mesta, ego_slovoforma_v_predlozhnom_padezhe FROM dEzpra_jet_cct_tip_mest_obrabotki');
if ($typeplace_results) {
$found = false;
foreach ($typeplace_results as $typeplace_result) {
$d_typeplace_raw = mb_strtolower($typeplace_result->vozmozhnyi_variant_mesta);
$d_typeplace_morf = mb_strtolower($typeplace_result->ego_slovoforma_v_predlozhnom_padezhe);
$d_typeplace = mb_strtolower($d_typeplace);
if (stripos($d_typeplace, $d_typeplace_raw) !== false) {
echo $d_typeplace_morf;
$found = true;
break;
}
}
if (!$found) {
echo $d_typeplace;
}
}
}
But I think it would be more efficient, if you implemented the second code snippet written by #Luke.T
I'm presuming you were trying to add the else like this?
function d_typeplace_morf($d_typeplace)
{
global $wpdb;
$typeplace_results = $wpdb->get_results('SELECT vozmozhnyi_variant_mesta, ego_slovoforma_v_predlozhnom_padezhe FROM dEzpra_jet_cct_tip_mest_obrabotki');
if ($typeplace_results) {
foreach ($typeplace_results as $typeplace_result) {
$d_typeplace_raw = mb_strtolower($typeplace_result->vozmozhnyi_variant_mesta);
$d_typeplace_morf = mb_strtolower($typeplace_result->ego_slovoforma_v_predlozhnom_padezhe);
$d_typeplace = mb_strtolower($d_typeplace);
if (stripos($d_typeplace, $d_typeplace_raw) !== false) {
echo $d_typeplace_morf;
} else {
echo $d_typeplace;
}
}
}
}
Which was outputting an array because the for loop was continuing, if you add a break like so...
echo $d_typeplace;
break;
It should stop outputting an array. Depending on your use case you could however perform similar functionality directly in your sql query using LIKE ...
function d_typeplace_morf($d_typeplace)
{
global $wpdb;
$typeplace_results = $wpdb->get_results('
SELECT ego_slovoforma_v_predlozhnom_padezhe
FROM dEzpra_jet_cct_tip_mest_obrabotki
WHERE vozmozhnyi_variant_mesta LIKE %' . $d_typeplace . '%');
if ($typeplace_results) {
//Echo result
} else {
echo $d_typeplace;
}
}

PHP: How can i make so non valid users gets another zipfile?

I am really new at php and i came across this code.
Right now it checks for the hwid of a user and grants permission to a zip file if the hwid is in the valid users.
How can i make so the non valid users gets another zipfile to download?
Code:
`
$VALID_USERS = [
'BB12313-25DC-5132-BCEA-B23123123123',
''
];
$IS_REQUEST_ALLOWED = false;
if(!isset($_POST['hwid']) && !isset($_GET['hwid'])) { die(); }
$USER_HWID = '0';
if(isset($_POST['hwid'])) {
$USER_HWID = $_POST['hwid'];
} else {
$USER_HWID = $_GET['hwid'];
}
$USER_HWID = trim($USER_HWID);
$USER_HWID = strtoupper($USER_HWID);
foreach($VALID_USERS as $USER) {
$USER = strtolower($USER);
$HWID = strtolower($USER_HWID);
if($HWID === $USER) {
readfile('./ZIPFILE.zip'); die();
}
}
`
Assuming other code functions properly, your if clause at the end should look like this:
if($HWID === $USER) {
readfile('./ZIPFILE.zip'); die();
} else {
readfile('OtherFile.zip'); die();
}
After you compare $HWID === $USER, offer a different file in the ELSE added below.
foreach($VALID_USERS as $USER) {
$USER = strtolower($USER);
$HWID = strtolower($USER_HWID);
if($HWID === $USER) {
readfile('./ZIPFILE.zip'); die();
} else { //not a valid user
readfile("./invalid_file.zip");die();
}
}
Note that this will give "invalid_file.zip" to anyone who doesn't meet the criteria ($HWID===$USER) (maybe, see below).
Also, die() is rather a nasty way to exit (it doesn't even tell the user why it's leaving ...).
Please also take a look at your $VALID_USERS array. Surely you don't mean to have a null value in there?
Finally, what about the case of someone else who isn't null or "BB12313-25DC-5132-BCEA-B23123123123"?
You might wish to reconsider the use of this code.
Replace your entire foreach loop with this one if block. Since you are keeping your VALID_USERS in an array, you can use in_array() to quickly check if you user is there, the loop is unnecessary.
This:
foreach($VALID_USERS as $USER) {
$USER = strtolower($USER);
$HWID = strtolower($USER_HWID);
if($HWID === $USER) {
readfile('./ZIPFILE.zip'); die();
}
}
Becomes:
if (in_array($USER_HWID, $VALID_USERS, true)) {
readfile('./ZIPFILE.zip'); die();
} else {
readfile('./SomeOtherZIPFILE.zip'); die();
}
You will also notice that the 3rd paramter to in_array() has been set true in this example. This enables strict type comparison, to match the original codes '===' check.

PHP reading lines from file and compare them

I am trying to read all lines from a file and than see if a given string contains any of these lines.
My code
$mails = file('blacklist.txt');
$email = "hendrik#anonbox.net";
$fail = false;
foreach($mails as $mail) {
if(strpos($email, $mail) > 0) {
$fail = true;
}
}
if($fail) {
echo "Fail";
} else {
echo "you can use that";
}
The blacklist.txt can be found here http://pastebin.com/aJyVkcNx.
I would expect strpos return a position for at least one string in the blacklist, but it does not. I am guessing that somehow I am generating not the kind of values within the $mails as I am expecting.
EDIT this is print_r($mails) http://pastebin.com/83ZqVwHx
EDIT2 some clarification: I want to see if a domain is within an email, even if the mail contains subdomain.domain.tld. And I tried to use !== false instead of my > 0 which yielded the same result.
You need to parse the email well since you're checking the domain of the email address if its inside the blacklist. Example:
$email = "hendrik#foo.anonbox.net";
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
preg_match('/#.*?([^.]+[.]\w{3}|[^.])$/', $email, $matches);
if(!empty($matches) && isset($matches[1])) {
$domain = $matches[1];
} else {
// not good email
exit;
}
// THIS IS FOR SAMPLES SAKE, i know youre using file()
$blacklist = explode("\n", file_get_contents('http://pastebin.com/raw.php?i=aJyVkcNx'));
foreach($blacklist as $email) {
if(stripos($email, $domain) !== false) {
echo 'you are blacklisted';
exit;
}
}
}
// his/her email is ok continue
strpos returns FALSE if the string was not found.'
Simply use this :
$fail = false;
foreach($mails as $mail) {
if(strpos($email, $mail) === false) {
$fail = true;
}
}
Or even better use this:
$blacklist = file_get_contents('blacklist.txt');
$email = "hendrik#anonbox.net";
if(strpos($email, $blacklist) === false){
echo "fail";
} else {
echo "This email is not blacklisted";
}
You have found the common pitfall with the strpos function. The return value of the strpos function refers to the position at which it found the string. In this instance, if the string begins at the first character, it will return 0. Note that 0 !== false.
The correct way to use the function is:
if(strpos($email, $mail) !== false){
// the string was found, potentially at position 0
}
However, this function may not be necessary at all; if you are simply checking if $mail is the same as $email, instead of seeing if the string exists within a larger string, then just use:
if($mail == $email){
// they are the same
}
Though you might still use foreach, that’s array reduce pattern:
function check_against($carry, $mail, $blacklisted) {
return $carry ||= strpos($mail, $blacklisted) !== false;
};
var_dump(array_reduce($mails, "check_against", $email_to_check));
Hope it helps.
Yet another way to solve this. Works fine:
$blacklist = file_get_contents('blacklist.txt');
$email = "hendrik#x.ip6.li";
$domain = substr(trim($email), strpos($email, '#')+1);
if(strpos($blacklist, $domain)){
echo "Your email has been blacklisted!";
}else{
echo "You are all good to go! not blacklisted :-)";
}
Goodluck!

Php backlink checker on another website

I am trying to make a script to check if a webpage has a back link to my page. I have found this script but the problem is that it returns the error message "No back link found" even if there is a backlink. Could someone tell me what is wrong with this script?
Here is the script I am using:
require('simple_html_dom.php');
function CheckReciprocal( $targetUrl, $checkLinkUrl, $checkNofollow = true )
{
$html = file_get_html($targetUrl);
if (empty($html))
{
//# Could not load file
return false;
}
$link = $html->find('a[href^='.$checkLinkUrl.']',0);
if (empty($link))
{
//# Link not found
return false;
}
if ( $checkNofollow && $link->hasAttribute('rel') )
{
$attr = $link->getAttribute('rel');
return (preg_match("/\bnofollow\b/is", $attr) ? false : true);
}
return true;
}
$targetUrl = 'http://example.com/test.html';
$checkLinkUrl = 'http://mysite.com';
if ( CheckReciprocal($test, $checkLinkUrl) )
{
echo 'Link found';
}
else { echo 'Link not found or marked as nofollow'; }
Thank you!
I don't know how does that simple_html_dom.php's $html->find() works cos never used it, but it seems that your problem is there. I would trust the good ol' DOMDocument + regex.
Just wrote a function and tested it, just use on the $url the plain domain + whatever you want, don't worry about the http(s) or www and stuff like that:
function checkBackLink($link, $url, $checkNoFollow = true){
$dom = new DOMDocument();
$dom->loadHTMLFile($link);
foreach($dom->getElementsByTagName('a') as $item){
if($checkNoFollow){
if(preg_match('/nofollow/is', $item->getAttribute('rel'))) continue;
}
if($item->hasAttribute('href') === false) continue;
if(preg_match("#^(https?\://)?(www\.)?$url.*#i", $item->getAttribute('href'))) return true;
}
}
if(checkBacklink('the link', 'example.com')){
echo "link found";
} else {
echo "Link not found or marked as nofollow";
}
If you don't like it and still want to use the simple_html_dom just make sure how that find() works, because if it only match exact values that could be troublesome.

How to determine if file text search returns no matches?

I have created a piece of code that checks files for a user-submitted string within a set of files. The code searches a directory, returns the file, then searches for the string in the file. The user will input the custom string through an input field and then clicking a submit button.
I have successfully been able to create a condition where, if the user does not enter any information, the output will say, "Your search produced no results". However, I have not been able to figure out how to create a condition where, if the user enters a string that isn't found within the files, that the output will also be, "Your search produced no results".
The code for the existing conditional I have as of now is this:
if ((isset($query)) && (empty($query))) {
echo "Your search produced no results";
}
The code that searches for the files and also searches for the string is found here (this is the entire PHP file, actually, and it includes the conditional I posted above.) I need help on how to create another conditional that throws a message if the user-input isn't found in any of the files.
If this seems unclear, I apologize and will clarify any information you need if you think it will help.
Calling Code
$query = $_POST['query'];
if ((isset($query)) && (empty($query))) {
echo "Your search produced no results.";
}
else {
find_files('.');
}
find_files()
function find_files($seed)
{
if (! is_dir($seed))
return false;
$files = array();
$dirs = array($seed);
while(NULL !== ($dir = array_pop($dirs)))
{
if($dh = opendir($dir))
{
while( false !== ($file = readdir($dh)))
{
if($file == '.' || $file == '..') continue;
$path = $dir . '/' . $file;
if (is_dir($path)) {
$dirs[] = $path;
}
else {
if (preg_match('/^.*\.(php[\d]?|js|txt)$/i', $path)) {
check_files($path);
}
}
}
}
closedir($dh);
}
}
check_files()
function check_files($this_file)
{
$query = $_POST['query'];
$str_to_find = $query;
if(!($content = file_get_contents($this_file))) {
echo("Could not check $this_file");
}
else {
if (stristr($content, $str_to_find)) {
echo("$this_file -> contains $str_to_find");
}
}
unset($content);
}
If the query is not empty the find_files function is simply executed with no instructions of doing something if it returns false, hence you need to evaluate the result of calling find_files. For example you could do:
if ((isset($query)) && (empty($query))) {
echo "<p style=\"color:darkgray; font-family:arial\">Your search produced no results</p>";
}
elseif (!find_files('.'))
{
echo "<p style=\"color:darkgray; font-family:arial\">Your search produced no results</p>";
}
with the condition that you update you find_files function to return false for all cases that fail.
or you could update the find_files function to return a string in case of errors and a string empty for succesful execution
if ((isset($query)) && (empty($query))) {
echo "<p style=\"color:darkgray; font-family:arial\">Your search produced no results</p>";
}
else
{
$result = find_files('.');
if (!empty($result))
{
echo "<p style=\"color:darkgray; font-family:arial\">".$result."</p>";
}
}
A couple of notes regarding your code that will improve the readability and code quality:
proper indentation will save a lot of time spent in maintenance;
when using if else imbrications ALWAYS use curly braces even if it is only one instructions. Improves readability and avoids errors.
when accessing a variable declared outside a function (in procedural code) use global keyword. For example for accessing the query variable inside the check_files function use global $query; instead of retrieving the variable again from the post.
use $_REQUEST instead of $_POST or $_GET unless there is a special reason for doing otherwise. Unifies code, makes for more readable code and changing from GET to POST or vice-versa can be done without changing code.
You may make your find_files function to return a boolean value: true if at least one matching file was found, false otherwise. Then update your if condition:
if ((isset($query)) && (empty($query)) && !find_files('.')) {
echo "<p style=\"color:darkgray...";
}
Because && is lazily evaluated, find_files will be called only if $query isn't empty.

Categories