Exiting a foreach loop and retrieve result

独自空忆成欢 提交于 2020-01-16 11:53:07

问题


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"; ?>


回答1:


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);



回答2:


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;
}



回答3:


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.



来源:https://stackoverflow.com/questions/17494154/exiting-a-foreach-loop-and-retrieve-result

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!