How do you find images with a name similar to a variable? - php

So far, I wrote a script which finds if a certain file exists in an external website.
<?php
if (isset($_GET['user'])){
if ($_GET['user'] != ""){
$userloc = "http://somesite.com/images/" . htmlspecialchars($_GET["user"]) . ".png";
$user = htmlspecialchars($_GET['user']);
if (getimagesize($userloc) !== false) {
echo $user . "exists!" ;
echo "<img src=\"" . $userloc . "\" height=\"100px\" />";
} else {
echo $username . "\" does not exist.";
$suggest = /* Code to find an image with a similar name */
echo "Did you mean: ";
}
}
?>
Basically, I would like to expand the code so it will display image suggestions.
I am a complete newbie when it comes to PHP code. Any help would be much appreciated. :)

The levenshtein function is useful for finding similarities in strings.
Assuming that you have correctly checked to see that a file exists or not, then you can use this function to make suggestions.
/**
* #param string $inputName
* #param string[] $knownNames
*
* #return string[]
*/
function getNameSuggestions($inputName, array $knownNames = array())
{
$candidates = array();
foreach ($knownNames as $candidate) {
$lev = levenshtein($inputName, $candidate);
if ($lev <= strlen($inputName) / 3 || false !== strpos($candidate, $inputName)) {
$candidates[] = $candidate;
}
}
return $candidates;
}
Then call the function
$suggestions = getNameSuggestions((string) $_GET['user'], array(
// a list of known users
));

Your script does not test if a file exist on a remote website. What it does it assumes that the filename $_GET['user'] . 'png'; exists at http://somesite.com/images/ if it's not ""
What you should do is something like this:
$remote = 'http://somesite.com/images/' . urlencode($_GET["user"]) . '.png';
if (file_get_contents($remote) !== false) {
echo 'Exists!';
} else {
echo 'Does not exist!';
// try something else or start bruteforce :P
}

Related

Correct syntax to either pass a variable into an object or modify object to include preg_replace

Apologies if the title is not correctly worded but I can currently output what I am after with:-
$noescape = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($this->_queryText));
And then by var dumping the following:-
$noescape
The final output in the existing function is:-
return $this->_queryText;
I need to modify _queryText to use either $noescape or include the preg_replace above...
I'm unsure whether I can syntactically modify return $this->_queryText; along the lines of:-
return $this->preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($this->_queryText));
or
return $noescape($this->_queryText);
Or whether I'd need to look at modifying another section of the function (entire function below):-
/**
* Retrieve search query text
*
* #return string
*/
public function getQueryText()
{
if (!isset($this->_queryText)) {
$this->_queryText = $this->_getRequest()->getParam($this->getQueryParamName());
if ($this->_queryText === null) {
$this->_queryText = '';
} else {
/* #var $stringHelper Mage_Core_Helper_String */
$stringHelper = Mage::helper('core/string');
$this->_queryText = is_array($this->_queryText) ? ''
: $stringHelper->cleanString(trim($this->_queryText));
$noescape = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($this->_queryText));
echo '<span style="display: none;">';
echo '<pre>';
var_dump (
//$this->rawurldecode($this->getQueryText())
$noescape
);
echo '</pre>';
echo '</span>';
$maxQueryLength = $this->getMaxQueryLength();
if ($maxQueryLength !== '' && $stringHelper->strlen($this->_queryText) > $maxQueryLength) {
$this->_queryText = $stringHelper->substr($this->_queryText, 0, $maxQueryLength);
$this->_isMaxLength = true;
}
}
}
return $this->_queryText;
//return $this->preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($this->_queryText));
//return $noescape($this->_queryText);
}
Hope that makes sense...
Okay, someone else has managed to point this out for me now...
return $this->_queryText = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($this->_queryText));
Working perfectly.

Exiting a foreach loop and retrieve result

I'm working on a little project and I've gone brain dead, so I'm hoping someone here can help me defeat my coders block.
I'm trying to create a page using php that changes its content display depending on what (if any) value is passed to the page (Locations). I have created a safelist array which I've stored the different locations. First I check any value passed against the safe list, if its a match I display one set of content.
If it doesn't match I'm running a similarity test to check if theres maybe a simple typo and can still navigate people to the page I think they wanted but this is where I'm getting stuck.
I'm hoping that someone could type
www.example.co.uk/location.php <---- to load a generic location page
www.example.co.uk/location.php?loc=Bishops-Stortford <---- to load a targeted location page
www.example.co.uk/location.php?loc=Bishop-Stortford <---- to load a targeted location page despite mispelling providing its a 90% or more match
www.example.co.uk/location.php?loc=?php echo "I hacked your site"; ?> ---- hopefully my system will disarm nasty code injection
I'll post my code below so you can see what I've got.
<?php
$loc = "";
$safelist = array("Bishops Stortford", "Braintree", "Chelmsford", "Dunmow", "Harlow", "Hertford", "Saffron Walden", "Sawbridgeworth", "Stansted", "Ware",
"Essex", "Hertfordshire");
if(isset($_GET["loc"])) {
/* Gets the value of loc if set, replaces hyphens with spaces and capitalises first letters of words converting the rest to lowercase. */
$loc = ucwords(strtolower(str_replace("-", " ", $_GET["loc"])));
}
/* Is word in safelist */
if (in_array($loc, $safelist)) {
/* Yes */
if (($loc == "Essex") or ($loc == "Hertfordshire")) {
$county = True;
} else {
$county = False;
}
if ($county == False) {
echo "\"" . $loc . "\" is not a county";
}else{
echo "\"" . $loc . "\" is a county";
}
} else {
/* No, Is string 90% similar to any entry within the safelist? */
foreach ($safelist as $safeword) {
similar_text($safeword, $loc, $percent);
echo $safeword . " " . $loc . " " . $percent . "<br />";
if ($percent >= 90) {
}
}
?>
I can't think what to do for the if ($percent >=90). I know I want to exit the loop and get the result from the first 90% or more match I find but am not 100% sure how to do this.
Also whats the best way to deal with code injection like www.example.co.uk/location.php?loc=?php echo "I hacked your site"; ?>
I think this is what you want:
foreach ($safelist as $safeword) {
similar_text($safeword, $loc, $percent);
echo $safeword . " " . $loc . " " . $percent . "<br />";
if ($percent >= 90) {
$loc = $safeword;
$county = true;
break;
}
}
As long as you don't call eval() on user input, you don't have to worry about them injecting PHP statements. When you echo something, it's sent to the browser, it's not executed again by PHP. However, you should still sanitize the output, because it might contain HTML markup, perhaps even Javascript, which could hijack the user's browser. When displaying output on the page, use htmlentities() to encode it:
echo "Greetings, " . htmlentities($first_name);
To answer the second part of your question, I use htmlentities to output data directly to the screen from input and something like this function on the data before a save to a database:
function escape_value($value)
{
if($this->real_escape_string_exists)
{
if($this->magic_quotes_active){$value = stripslashes($value);}
$value = mysql_real_escape_string($value);
}
else
{
if(!$this->magic_quotes_active){$value = addslashes($value);}
}
return $value;
}
I think I would restructure it, something like this:
$loc = "";
$safelist = array("Bishops Stortford", "Braintree", "Chelmsford", "Dunmow", "Harlow", "Hertford", "Saffron Walden", "Sawbridgeworth", "Stansted", "Ware",
"Essex", "Hertfordshire");
if(isset($_GET["loc"])) {
/* Gets the value of loc if set, replaces hyphens with spaces and capitalises first letters of words converting the rest to lowercase. */
$loc = ucwords(strtolower(str_replace("-", " ", $_GET["loc"])));
}
$good = '';
if (in_array($loc, $safelist)) {
$good = $loc;
} else {
foreach ($safelist as $safeword) {
similar_text($safeword, $loc, $percent);
echo $safeword . " " . $loc . " " . $percent . "<br />";
if ($percent >= 90) {
$good = $safeword;
}
}
}
if ( ! empty($good)){
/* Yes */
if (($good == "Essex") or ($good == "Hertfordshire")) {
$county = True;
} else {
$county = False;
}
if ($county == False) {
echo "\"" . $good . "\" is not a county";
}else{
echo "\"" . $good . "\" is a county";
}
//And whatever else you want to do with the good location...
}
Like Barmar said, since you're not doing anything with the input value except for comparing it to an array, there's no risk of an attack in that way.

PHP variables randomly becomes NULL

For quite a while now we experience a very weird problem with our hosting server. Once a while (seems randomly) variables in PHP become NULLs.
In general everything works perfectly fine, but once a while it happens. All accounts on the server are affected and all PHP apps (including PHPMyAdmin, Wordpress our own scripts). We contacted our hosting company, but they are unable to find any solution.
I had few ideas, the most promising one was an issue with Suhosin. But I do not get any message in the log directly from it.
We made a simplest possible script to reproduce the error:
<?php
class Example
{
protected $stringVar = 'this is a string value';
public function accessParameter()
{
$error = false;
if (isset($this->stringVar) && !is_null($this->stringVar)) {
echo "string var : " . $this->toStringWithType($this->stringVar) . "\n";
} else {
echo "string var is not set\n";
$error = true;
}
if ($error) {
$logfile = dirname(__FILE__)."/random_bug_log.log";
file_put_contents($logfile, date('Y-m-d H:i:s')."\n", FILE_APPEND);
file_put_contents($logfile, $this->toStringWithType($this->stringVar) . "\n", FILE_APPEND);
}
}
public function toStringWithType($var)
{
$type = gettype($var);
return "($type) '$var'";
}
}
$e = new Example();
$e->accessParameter();
Normal output:
string var : (string) 'this is a string value'
Output when the weird thing happens:
string var is not set
I open to any ideas or suggestions how to solve this problem. I guess the ultimate solution is to change the hosting company. I did not manage to create this issue on localhost or any other server.
Test piece that have been made, including your suggestions:
<?php
class Example
{
protected $stringVar = 'this is a string value';
public function accessParameter() {
$error = false;
if(isset($this->stringVar) && !is_null($this->stringVar)) {
echo "string var : "
.$this->toStringWithType($this->stringVar)
."\n";
} else {
echo "string var is not set\n";
$error = true;
}
if($error) {
$logfile = dirname(__FILE__)."/random_bug_log.log";
file_put_contents($logfile, date('Y-m-d H:i:s')." ", FILE_APPEND);
file_put_contents($logfile,
$this->toStringWithType($this->stringVar) . "\n",
FILE_APPEND);
}
}
public function writeParameter() {
$this->stringVar="variable assigned";
if(isset($this->stringVar) && !is_null($this->stringVar)) {
echo "string var : "
.$this->toStringWithType($this->stringVar)
."\n";
} else {
echo "string var is not set\n";
$error = true;
}
}
public function toStringWithType($var)
{
$type = gettype($var);
return "($type) '$var'";
}
}
$e = new Example();
$e->accessParameter();
$e->writeParameter();
The output while the thing happens:
string var is not set
string var is not set
it is very strange problem.
it may not be a solution but worth to try;
protected $stringVar;
function __construct() {
$this->stringVar = 'this is a string value';
}
I would recommend to use !== instead of is_null to see if the variable is actually null.
if (isset($this->stringVar) && ($this->stringVar !== null)) {
or
if (isset($this->stringVar) && (!empty($this->stringVar)) {
should do the work too.
In case of theses type of issues check with the value that you have in if condition and do what you want in else. Like in your situation do like:
if(isset($this->stringVar) && ($this->stringVar == "this is a string value")) {
}else{
// your code here...
}

Javascript confirm() function cannot pass parameters properly

I'm using PHP and JavaScript, and I got a problem when deal with the confirm() function in JavaScript.
Say I have a page add.php, firstly I receive some parameters passed from another page, and I check to see if they are valid or not. If yes, I just insert the data into db and return to another page, if they are not valid, there'll be a confirm() window popped up and let the user to choose whether to continue or not. If the user still choose to continue, I want the page to be reloaded with all the parameters sent again. But the problems is that I cannot get the parameter the second time add.php is loaded.
Previously I didn't use a window.onload function and confirm() pop up, but an < a href> link instead, everything worked fine (Please see the attached code at the end). But when I tried to use the following code, the same url stopped working
echo "<script type=\"text/javascript\">";
echo "window.onload = function() {
var v = confirm(\"$name is not alive, do you want to add it into system?\");
if (v) {
window.location.href= \"add.php?type=room&name=$name&area\"
+ \"=$area&description=$description&\"
+ \"capacity=$capacity&confirm=Y\";
} else {
window.location.href= \"admin.php?area=$area\";
}
}";
echo "</script>";
Following is the previous version, instead of using window.onload(), I used < a href="..." /> link, everything worked fine at that time. get_form_var is a function in functions.inc, which is to get the parameter using $_GET arrays.
<?php
require_once "functions.inc";
// Get non-standard form variables
$name = get_form_var('name', 'string');
$description = get_form_var('description', 'string');
$capacity = get_form_var('capacity', 'string');
$type = get_form_var('type', 'string');
$confirm = get_form_var('confirm','string');
$error = '';
// First of all check that we've got an area or room name
if (!isset($name) || ($name === ''))
{
$error = "empty_name";
$returl = "admin.php?area=$area"
. (!empty($error) ? "&error=$error" : "");
header("Location: $returl");
}
// we need to do different things depending on if its a room
// or an area
elseif ($type == "area")
{
$area = mrbsAddArea($name, $error);
$returl = "admin.php?area=$area"
. (!empty($error) ? "&error=$error" : "");
header("Location: $returl");
}
elseif ($type == "room")
{
if (isset($confirm)){
$dca_osi = getOsiVersion($name);
$room = mrbsAddRoom(
$name,
$area,
$error,
$description,
$capacity,
$dca_osi,
1
);
$returl = "admin.php?area=$area"
. (!empty($error) ? "&error=$error" : "");
header("Location:$returl");
}
else {
$dca_status= pingAddress($name);
$dca_osi = getOsiVersion($name);
if( $dca_status == 0){
$room = mrbsAddRoom(
$name,
$area,
$error,
$description,
$capacity,
$dca_osi,
0
);
$returl = "admin.php?area=$area"
. (!empty($error) ? "&error=$error" : "");
header("Location:$returl");
}
else {
print_header(
$day,
$month,
$year,
$area,
isset($room) ? $room : ""
);
echo "<div id=\"del_room_confirm\">\n";
echo "<p>\n";
echo "$name is not alive, are you sure to add it into system?";
echo "\n</p>\n";
echo "<div id=\"del_room_confirm_links\">\n";
echo "<a href=\"add.php?type=room&name"
. "=$name&area=$area&description"
. "=$description&capacity=$capacity&confirm"
. "=Y\"><span id=\"del_yes\">"
. get_vocab("YES") . "!</span></a>\n";
echo "<a href=\"admin.php?area=$area\"><span id=\"del_no\">"
. get_vocab("NO") . "!</span></a>\n";
echo "</div>\n";
echo "</div>\n";
}
}
}
function pingAddress($host)
{
$pingresult = exec("/bin/ping -c 1 $host", $outcome, $status);
if ($status==0) {
return $status;
}
else {
return 1;
}
}
function getOsiVersion($host)
{
$community = 'public';
$oid = '.1.3.6.1.4.1.1139.23.1.1.2.4';
$sysdesc = exec("snmpwalk -v 2c -c $community $host $oid");
$start = strpos($sysdesc, '"');
if ($start!==false) {
$sysdesc = substr($sysdesc, $start+1,$sysdesc.length-1);
return $sysdesc;
}
else {
return "not available";
}
}
I've solved the problem, just simply by using "&" instead of " & amp;" in the url link... it works fine now...
You try location.reload() javascript call?

How to get innermost directory name

I am trying to output a class based on the name of innermost directory name, but can't get it right. Any help would be very much appreciated. It's a php_file_tree, please see section numbered #39 below:
function php_file_tree_dir($directory, $return_link, $extensions = array(), $first_call = TRUE) {
// Get and sort directories/files
if (function_exists("scandir")) {
$file = scandir($directory);
}
else {
$file = php4_scandir($directory);
}
natcasesort($file);
// Make directories first
$files = $dirs = array();
foreach ($file as $this_file) {
if (is_dir("$directory/$this_file")) {
$dirs[] = $this_file;
}
else $files[] = $this_file;
}
$file = array_merge($dirs, $files);
// Filter unwanted extensions
if (!empty($extensions)) {
foreach (array_keys($file) as $key) {
if (!is_dir("$directory/$file[$key]")) {
$ext = substr($file[$key], strrpos($file[$key], ".") + 1);
if (!in_array($ext, $extensions))unset($file[$key]);
}
}
}
// Use 2 instead of 0 to account for . and .. "directories"
if (count($file) > 2) {
$php_file_tree = "<ul";
if ($first_call) {
$php_file_tree .= " class=\"php-file-tree clearfix\"";
$first_call = FALSE;
}
// #39, Here needs to output a class based on innermost directory name
/*
else {
$php_file_tree .= " class=\"innertree ". htmlspecialchars(basename(rtrim($directory, '/'))) ." clearfix\"";
}
*/
$php_file_tree .= ">";
foreach ($file as $this_file) {
if ($this_file != "." && $this_file != "..") {
if (is_dir("$directory/$this_file")) {
// Directory
$php_file_tree .= "<li class=\"pft-directory\"><a class=\"folder \" href=\"#\">". htmlspecialchars($this_file) ."</a>";
$php_file_tree .= php_file_tree_dir("$directory/$this_file", $return_link, $extensions, FALSE);
$php_file_tree .= "</li>";
}
else {
//$ext = "ext-". substr($this_file, strrpos($this_file, ".") + 1); // need to compare speed with native
$ext = "ext-". pathinfo($this_file, PATHINFO_EXTENSION);
$link = str_replace("[link]", base_path() ."$directory/". urlencode($this_file), $return_link);
$php_file_tree .= "<li class=\"pft-file ". strtolower($ext) ."\"><a class=\"screenshot\" title=". htmlspecialchars($this_file) ." href=\"$link\">". htmlspecialchars($this_file) ."</a></li>";
}
}
}
$php_file_tree .= "</ul>";
}
return $php_file_tree;
}
The topmost directory will always have a class "php-file-tree", while the subsequent/ following directories underneath will have their classes based on their own folder names.
Geez, actually it was okay already. Seems the problem was cache or something as I placed it inside modal dialog with AJAX call. I have tried several possibilities before, including "$first_call = FALSE;" to no avail. But when I revisited the directory again, added "$first_call = FALSE;", and clear everything, it now output the folder name correctly.
Sorry to bother, anyone. Thanks

Categories