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.
Related
I want to display a specific value from key value list..
here is my code:
if (isset($_POST) && count($_POST)>0 )
{
foreach($_POST as $paramName => $paramValue) {
echo "<br/>" . $paramName . " = " . $paramValue;
}
}
ouput
ORDERID = ORDS3700373
TXNAMOUNT = 200.00
CURRENCY = INR
TXNID = 32221284
BANKTXNID = 475815
STATUS = TXN_SUCCESS
RESPCODE = 01
RESPMSG = Txn Successful.
TXNDATE = 2017-01-10 18:13:25.0
GATEWAYNAME = WALLET
BANKNAME =
PAYMENTMODE = PPI
CHECKSUMHASH =
here I want to display only ORDERID and TXNID.. How do I get that value?
You can easily access post values by it's field name instead of looping through all post elements. Simply access that elements directly as below:
if(isset($_POST['ORDERID'])) {
echo 'ORDERID = '.$_POST['ORDERID'];
}
if(isset($_POST['TXNID'])) {
echo 'TXNID= '.$_POST['TXNID'];
}
Moving comments to an answer.
You do not need to loop post it is just a global array. You can access the values at any of the keys like any associative array because that is what it is. Likewise these value can be used like any other
if(isset($_POST['ORDERID'])){
$orderid = $_POST['ORDERID'];
}
if(isset($_POST['TXNID'])){
$txnid = $_POST['TXNID'];
}
// Should use htmlspecialchars() or htmlentities() here
// but didn't want to confuse OP. It is for security.
echo "ORDERID is: " . $orderid . " and TXNID is: " . $txnid;
A note for security never trust user input and sanitize all $_POST variables before echoing or persisting. There are far better article out on the internet than I can summarize here.
You can use if condition in the loop like this
if (isset($_POST) && count($_POST)>0 )
{
foreach($_POST as $paramName => $paramValue) {
if($paramName == 'ORDERID' || $paramName == 'TXNID')
echo "<br/>" . $paramName . " = " . $paramValue;
}
}
add an if like
if($paramName == "ORDERID" || $paramName == "TXNID") {
after foreach, remeber to close it after echo statement line
Don't overcomplicate a trivial task with a loop.
Just drop the loop and echo the two values directly:
// Assuming the two values are expected to come in pair:
if(isset($_POST['ORDERID']) && isset($_POST['TXNID'])) {
echo "<br/>ORDERID = " . $_POST['ORDERID'];
echo "<br/>TXNID = " . $_POST['TXNID'];
}
If you insist on having a loop, then you can go through the property names which you need
foreach(array('ORDERID', 'TXNID') as $paramName) {
if(isset($_POST[$paramName])) {
echo "<br/>" . $paramName . " = " . $_POST[$paramName];
}
}
i need help again.
I have to code a function that gets me the cookie. but i only knows part of the cookie name. I got a JavaScript-Function that's working very well:
function readCookie(cookiePart){
var results = document.cookie.match(cookiePart + '(.*)=(.*?)(;|$)');
if(results){
var result = results[0].replace(cookiePart,'');
var cookie= result.split("=");
return(cookie[0])
}else{
return null
}
}
alert(readCookie("cookie_"));
I try to code the same for PHP. But still stuck:
$cookie_name = "cookie_";
if(!isset($_COOKIE["$cookie_name" . "/^*$/"])) {
echo "Cookie named '" . $cookie_name . "' is not set!";
} else {
echo "Cookie '" . $cookie_name . "' is set!<br>";
}
i think i do the regex part wrong. maybe you can help me where to add it? i tried on the varaiablename when define or match, but nothing works.
thx for any hint my friends!
Problem
The thing is, that in JavaScript you used a method .match() for regexp, but you didn't use anything for regexp in PHP.
And you cannot that easily match keys, you can only do this when iterating over entire array.
But you don't have to use regexp to achieve what you need.
Solution
I recommend this:
$set = false;
$cookie_name = 'cookie_';
foreach ($_COOKIE as $name => $value) {
if (stripos($name,$cookie_name) === 0) {
echo "Cookie named '$name' is set with value '$value'!";
$set = true;
}
}
if (!$set) {
echo 'No cookie found :(';
}
Will list all valid cookies (having names beginning with "cookie_"), or display sad message.
And I think that if you can achieve something relatively easy without regex, you should.
If you need to use cookie names afterwards
Use this modified code:
$cookie_name = 'cookie_';
foreach ($_COOKIE as $name => $value) {
if (stripos($name,$cookie_name) === 0) {
$cookies[] = $name;
}
}
And you have now table $cookies that contains names of every valid cookie set. If you need only part that's after _ then use this line instead:
$cookies[] = str_replace('cookie_','',$name);
function keyLike(array $arr, $like)
{
foreach (array_keys($arr) as $k) {
if (preg_match($like, $k)) {
return true;
}
}
return false;
}
...
if (keyLike($_COOKIE, '/^cookie_.+/')) { ...
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
}
I'm new to programming and I'm having to teach myself. But, I can't figure out what I'm doing wrong in this project. This project is for myself, to make shortcuts in PHP so I don't have to program so many lines of code; when I program, sometimes I use the same 20 lines for different applications.
Here is my script:
function writeDir($directory = null, $link = null, $exception = null) {
if (!isset($directory)) {
$directory = './';
}
if (!isset($link)) {
$link = false;
}
if (!isset($exception)) {
$exception = null;
}
// now...
if ($link==true&&$exception!=null) { // do a link and exception(s)
$directoryList = scandir($directory); // get an array of all directory items
$directoryLength = count($directoryList); // count $directoryList array length
if (is_string($exception)) { // if one (1) exception
for ($i=2; $i<$directoryLength; $i++) { // cycle through all directory items
if ($directoryList[$i] == $exception) { // if we hit that one (1) exception
echo ''; // do nothing
} else {
echo ' ' . $directoryList[$i] . ' <br />' . "\n";
}
}
}
if (is_array($exception)) { // if multiple exceptions
$exceptionList = count($exception); // count $exception array length
for ($i=2; $i<$directoryList; $i++) { // cycle through all directory items
for ($j=0; $j<$exceptionList; $j++) { // cycle through all exceptions
if ($directoryList[$i] == $exceptionList[$j]) { // if we hit one of the multiple exceptions
echo ''; // do nothing
} else {
echo ' ' . $directoryList[$i] . ' <br />' . "\n";
}
}
}
}
}
if ($link==true&&$exception==null) {
$directoryList = scandir($directory);
$directoryLength = count($directoryList);
for ($i=2; $i<$directoryLength; $i++) {
echo ' ' . $directoryList[$i] . ' <br />' . "\n";
}
}
if ($link==false&&$exception!=null) { // do only exception(s) without links
$directoryList = scandir($directory); // get an array of all directory items
$directoryLength = count($directoryList); // count $directoryList array length
if (is_string($exception)) { // if one (1) exception
for ($i=2; $i<$directoryLength; $i++) { // cycle through all directory items
if ($directoryList[$i] == $exception) { // if we hit that one (1) exception
echo ''; // do nothing
} else {
echo $directoryList[$i] . '<br />' . "\n";
}
}
}
if (is_array($exception)) { // if multiple exceptions
$exceptionList = count($exception); // count $exception array length
for ($i=2; $i<$directoryList; $i++) {
for ($j=0; $j<$exceptionList; $j++) {
if ($directoryList[$i] == $exceptionList[$j]) {
echo '';
} else {
echo $directoryList[$i] . '<br />' . "\n";
}
}
}
}
}
if ($link==false&&$exception==null) {
$directoryList = scandir($directory);
$directoryLength = count($directoryList);
for ($i=2; $i<$directoryLength; $i++) {
echo $directoryList[$i] . '<br />' . "\n";
}
}
}
I know it looks like a lot. But, I'm trying to make my life simpler when programming.
Basically, the syntax for this when called in a PHP file is:
writeDir(); // at the very least :OR: writeDir('./', true, 'index.php');
The second one writes files in the current directory with corresponding links to them, but skips over the index.php file.
The third (3rd) argument can be either a single omitted page (as a string) or an array of multiple omitted pages. Or, at least that's what I'm trying to achieve.
Of course an include to this source file would be required on all pages I use it for. Before, when IT WAS working, I could only format the list of directory items with the exclusion of one (1) file. So, I tried to allow for an array of files as well. Now, it loads for ever. I finally had to use a set_time_limit() function to quit the script.
Now, one last thing. When I used the set_time_limit() function, it displayed my directory items, but for some reason two (2) of everything... What have I done wrong?
Are there too many if-statements, or have I overlooked something? Should I just start over?
I've only programmed (unprofessionally) for about 5 years so I don't really know what it is I'm doing. Any guidance would be greatly appreciated.
Hope I've given enough information and details.
JDot
P.S.
Anybody who wants to use this script is more than welcome to (if it's even worth using).
use esle if
if($a==1)
{
echo $a;
}
elseif($b==1)
{
echo $b;
}
else
{
echo "c";
}
and there is ternary operator fo single if else statement: learn it
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?