簡體   English   中英

如何獲取使條件為 TRUE 的 if 條件的值

[英]How to get the value of if condition that make the condition TRUE

我正在嘗試獲取使條件為 TRUE 的 if 條件的值,我有以下示例:

(代碼.php)

<?php

$a = 'USERNAME';
$b = 'LASTNAME';
if(substr($a, 0, strlen("<SCRIPT"))=== "<SCRIPT Abdalla $a " ) {
    }

?>

在上面的例子中,我試圖在沒有雙引號的情況下獲得<SCRIPT值。 我嘗試了一些步驟,但它仍然得到帶有值的雙引號( <SCRIPT )。 然后我計划將值<SCRIPT分配給另一個變量。 下一個代碼顯示了我的代碼以獲取結果,但它仍然無法正常工作:

(測試.php)


<?php

$file='';
$handle = fopen('code.php','r+');
if ($handle) {
    while (($buffer=fgets($handle, 4096)) !== false) {
        $file.=$buffer."\n";
    }
    if (!feof($handle)) {
       die('error');
    }
    fclose($handle);
}

//take note of the use of single quotes to wrap this regex, as we do not want PHP parser to eval the $ in the regex string
preg_match_all('/\s*?(\$[\S]+?)\s*?\=(\"?[\S]+?\"?);/',$file,$matches, PREG_SET_ORDER);
$varval=array();
foreach($matches as $match){
    $tmp=$match[2];
    if(substr($tmp,0,1)=='"' && substr($tmp,-1,1)=='"'){    
        //evaluate variables in string. we can evaluate with the current object as the variable should be declared first as of proper PHP syntax
        $tmp=substr($tmp, 1,-1); //remove quotes
        $tmp=replaceFromObject($tmp, $varval);
    }
    $varval[$match[1]]=$tmp; //we do not need to check if exists, because we should replace with the latest value.
}

/* 
The below stores all quoted text and replace them with our own special variable %var0%, %var1%, %var2%.... %varN%. 
This is because there could be cases like if("test == 3" == $a) or even worse if("if(test=3)" == $a), which will make regex/parsing tricky if we do not substitute these quoted text out just like a parser/compiler would.

Note: Something I didn't do. We should really first scan the whole text using preg_match to find if there are any text using this format of variables as well, to prevent collisions! 
If there are, we can set a loop to check and append some character to our own special variable like %varrN%, %varrrN%, %varrrrN%... 
until we find no collisions and it is safe to use. I will leave this simple regex exercise for you to do on your own. Create the regex to find the file for %varN%...
*/
preg_match_all("/\"([\s\S]*?)\"/", $file, $matches, PREG_SET_ORDER);
$stringvars=array();
$key="%var";
$count=0;
foreach($matches as $match){
    if(!in_array($match[1], $stringvars)){
        $stringvars[$key.$count.'%']=$match[1];
        $file=preg_replace("/\"".preg_quote($match[1])."\"/", $key.$count.'%', $file); //take note of the change to preg_quote
        $count++;
    }
}


// now we parse the whole text for if(subject anycomparator value)
preg_match_all("/if\s*?\(([\s\S]*?)([\=|\>|\<][\=]{0,2})\s*?([\S\s]*?)\s*?\)/", $file, $matches,PREG_SET_ORDER);
$conditionals=array();
foreach($matches as $match){
    $conditionals[]=array(
        'subject'=>replaceFromObject(replaceFromObject(trim($match[1]),$stringvars),$varval), 
        //the order does matter, we replace the string first, then the variables, as there might be variables in the double quoted strings which we should evaluate
        'comparator'=>$match[2],
        'value'=>replaceFromObject(replaceFromObject(trim($match[3]),$stringvars),$varval),
    );
}

foreach ($conditionals as $c){
   // echo htmlspecialchars($c['subject']).' ';    
   // echo htmlspecialchars($c['comparator']).' ';        
    echo htmlspecialchars($c['value']); 
    echo "<br/>";
}


/* now this function can be used to replace both the quoted strings AND the variables */
function replaceFromObject($s, $obj){
    foreach($obj as $key=>$value){
        $s=preg_replace('/'.preg_quote($key).'/', $value, $s); //take note of the preg_quote as the string may contain regex keywords
    }
    return $s;
}


?>

我想要一種打印使 if 條件為 TRUE 的值的方法,即 (

  • 注意:我知道這里的條件不是 TRUE,所以我想獲得使條件為 TRUE 的值,即<SCRIPT
  • 目的是我想知道使條件為TRUE的值是什么,然后稍后將使用該值對基於該值的代碼進行測試用例。

您的目標似乎奇怪地具體,但這里有一個解決您的問題的方法。

  1. 您不應該使用file_get_contents來讀取 php 文件的實際源代碼。 您將獲得生成的 html 等價物。 如果您正在獲取源代碼,則意味着您已將allow_url_fopen設置為true 這會使您的 Web 應用程序面臨潛在的極具破壞性的腳本注入可能性,除非您知道自己在做什么並且小心並與您的代碼保持一致。 您應該嘗試使用fgets代替。 此代碼基本上與您的file_get_contents相同。
$file='';
$handle = fopen('code.php','r+');
if ($handle) {
    while (($buffer=fgets($handle, 4096)) !== false) {
        $file.=$buffer."\n";
    }
    if (!feof($handle)) {
       die('error');
    }
    fclose($handle);
}
  1. 您的代碼中存在錯誤。 if(strpos($value, 'if') != false)會將位置 0 呈現為 false,在您的情況下應該是 true,就if在位置 0。比較器應該是嚴格的if(strpos($value, 'if') !== false)
  2. 它正在返回引用,因為這是您的代碼告訴它的。 $pos1 = strpos($value, '==') + 2指向第一個=之后的 2 個字符,這在技術上是您的===最后一個= 事實上,使用您當前的代碼,您將得到= "<SCRIPT"作為結果。

現在的解決方案

為了僅針對您的情況解決它,您只需調整substr的位置即可。 進行上述修改后(尤其是 2),您將通過更改這兩行來獲得沒有引號的條件

$pos1 =  strpos($value, '===') + 5; // 5 includes the 3 equal signs, a space and the quote
$pos2 =  strrpos($value, ')') - 2; // 2 includes the space and the quote

雖然這會得到您想要的結果,但它可能不適用於所有用例,因為有時您可能會添加一個空格,有時您可能不會。 更強大的解決方案是使用正則表達式。 在你的情況下,這將是這樣的:

foreach ($lines as $line) {
    if(preg_match("/if\s*?\([\s\S]*?\=\=\s*?[\"|']([\S\s]*?)[\"|']\s*?\)/", $line, $matches)){
        echo htmlspecialchars($matches[1]);     
    }
}

這個正則表達式字符串/if\\s*?\\([\\s\\S]*?\\=\\=\\s*?[\\"|']([\\S\\s]*?)[\\"|']\\s*?\\)/做什么你的代碼的目標做的,但在一個更加穩健的方式=發現一個字符串if可能的空間,一個(一些文字,比較==並且無論是在引號之間-無論是'"

為了讓它更健壯地選擇其他條件,嚴格相等, <><=>= ,你可以做這樣的事情。

$conditionals=array();
foreach ($lines as $line) {
    if(preg_match("/if\s*?\([\s\S]*?([\=|\>|\<][\=]{0,2})\s*?[\"|']([\S\s]*?)[\"|']\s*?\)/", $line, $matches)){
        $conditionals[]=array(
            'comparator'=>$matches[1],
            'value'=>$matches[2]
        );
    }
}

foreach ($conditionals as $c){
    echo htmlspecialchars($c['comparator']).' ';        
    echo htmlspecialchars($c['value']); 
    echo "<br/>";
}

這將適用於可能如下所示的 code.php 文件:

//code.php
<?php

$a = 'Data';
if(substr($a, 0, strlen("<SCRIPT"))=== "<SCRIPT" ) {
   echo TRUE;
}


if(substr($a, 0, strlen("<SCRIPT"))== "equal" ) {
   echo TRUE;
}

if(substr($a, 0, strlen("<SCRIPT"))<= "lesser or equal" ) {
   echo TRUE;
}

if(substr($a, 0, strlen("<SCRIPT"))>= "greater or equal" ) {
   echo TRUE;
}

if(substr($a, 0, strlen("<SCRIPT"))< "lesser" ) {
   echo TRUE;
}

if(substr($a, 0, strlen("<SCRIPT"))>"greater" ) {
   echo TRUE;
}

並將返回

=== <SCRIPT
== equal
<= lesser or equal
>= greater or equal
< lesser
> greater

編輯為非引用值提供更健壯的代碼......另一個編輯以捕獲變量值並將它們轉儲回。另一個編輯單引號變量和變量之間的空間

注意:捕獲字符串或變量的順序首先很重要,如果我們不小心可能會陷入一個粘性循環->變量中有字符串,字符串中有變量,變量中有字符串變量的字符串等...

這個想法是我們應該首先捕獲變量,評估這些變量中的任何變量(如果它們是雙引號字符串),我們不需要擔心 string-var inception 問題。

然后我們捕獲字符串 -> 然后替換字符串 THEN 替換變量。

更多注釋我們真正應該檢查的內容: 由於 PHP 只計算雙引號中的變量,我們應該在決定計算之前檢查字符串是否包含在雙引號和單引號中。 我已經為變量做了它。 它也可以很容易地轉換為字符串 - 通過捕獲引號,然后測試引號是單引號還是雙引號(或任何引號)。 我將把它作為正則表達式練習留給你。

另一個注意事項是我是故意這樣做的。 :p 當前用於捕獲變量的正則表達式適用於$a=3; , $a =3; 但不是$a = 3; $a = 3 ; $a= 3 ; , 很快。 添加它很容易,我把它留在了這里,所以你有機會通過添加這個簡單的條件來練習你的正則表達式技能。(編輯添加這個)希望這會有所幫助..

$file='';
$handle = fopen('code.php','r+');
if ($handle) {
    while (($buffer=fgets($handle, 4096)) !== false) {
        $file.=$buffer."\n";
    }
    if (!feof($handle)) {
       die('error');
    }
    fclose($handle);
}

//take note of the use of single quotes to wrap this regex, as we do not want PHP parser to eval the $ in the regex string
preg_match_all('/\s*?(\$[\S]+?)\s*?\=\s*?(\"?[\S]+?\"?);/',$file,$matches, PREG_SET_ORDER);
$varval=array();
foreach($matches as $match){
    $tmp=trim($match[2]);
    if(substr($tmp,0,1)=='"' && substr($tmp,-1,1)=='"'){    
        //evaluate variables in string. we can evaluate with the current object as the variable should be declared first as of proper PHP syntax
        $tmp=substr($tmp, 1,-1); //remove quotes
        $tmp=replaceFromObject($tmp, $varval);
    }else if(substr($tmp,0,1)=='\'' && substr($tmp,-1,1)=='\''){ // remove single quotes
        $tmp=substr($tmp, 1,-1);
        //no substitution of variables in single quotes just as PHP syntax
    }
    $varval[$match[1]]=$tmp; //we do not need to check if exists, because we should replace with the latest value.
}


/* 
The below stores all quoted text and replace them with our own special variable %var0%, %var1%, %var2%.... %varN%. 
This is because there could be cases like if("test == 3" == $a) or even worse if("if(test=3)" == $a), which will make regex/parsing tricky if we do not substitute these quoted text out just like a parser/compiler would.

Note: Something I didn't do. We should really first scan the whole text using preg_match to find if there are any text using this format of variables as well, to prevent collisions! 
If there are, we can set a loop to check and append some character to our own special variable like %varrN%, %varrrN%, %varrrrN%... 
until we find no collisions and it is safe to use. I will leave this simple regex exercise for you to do on your own. Create the regex to find the file for %varN%...
*/
preg_match_all("/\"([\s\S]*?)\"/", $file, $matches, PREG_SET_ORDER);
$stringvars=array();
$key="%var";
$count=0;
foreach($matches as $match){
    if(!in_array($match[1], $stringvars)){
        $stringvars[$key.$count.'%']=$match[1];
        $file=preg_replace("/\"".preg_quote($match[1])."\"/", $key.$count.'%', $file); //take note of the change to preg_quote
        $count++;
    }
}


// now we parse the whole text for if(subject anycomparator value)
preg_match_all("/if\s*?\(([\s\S]*?)([\=|\>|\<][\=]{0,2})\s*?([\S\s]*?)\s*?\)/", $file, $matches,PREG_SET_ORDER);
$conditionals=array();
foreach($matches as $match){
    $conditionals[]=array(
        'subject'=>replaceFromObject(replaceFromObject(trim($match[1]),$stringvars),$varval), 
        //the order does matter, we replace the string first, then the variables, as there might be variables in the double quoted strings which we should evaluate
        'comparator'=>$match[2],
        'value'=>replaceFromObject(replaceFromObject(trim($match[3]),$stringvars),$varval),
    );
}

foreach ($conditionals as $c){
    echo htmlspecialchars($c['subject']).' ';    
    echo htmlspecialchars($c['comparator']).' ';        
    echo htmlspecialchars($c['value']); 
    echo "<br/>";
}


/* now this function can be used to replace both the quoted strings AND the variables */
function replaceFromObject($s, $obj){
    foreach($obj as $key=>$value){
        $s=preg_replace('/'.preg_quote($key).'/', $value, $s); //take note of the preg_quote as the string may contain regex keywords
    }
    return $s;
}

所以實際上你的代碼在我的服務器上沒有輸出任何東西(test.php)。 因此,我嘗試了另一種至少適用於您的 code.php 的方法,但是,它不像您自己的代碼那樣非常穩定,因為它沒有考慮以下幾點。

沒有想到的邏輯運算符:

  • < , <= , > , >= , ===

如果支持,則沒有多行

我的方法實際上不會拆分字符串,也不會剝離任何內容,但是它唯一要做的就是替換字符串文字。

<?php
    $file = file_get_contents("test.php");
    $curIdx = 0; 

    while($curIdx < strlen($file))
    {
        $ifIndex = strpos($file,"if", $curIdx);


        if($ifIndex === false)
        {
            break;
        }

        $curIdx = $ifIndex+1;

        $equalsIdx = strpos($file,"=",$curIdx);

        if($equalsIdx === false)
        {
            break;
        }

        $curIdx = $equalsIdx+1;

        for($i = $curIdx; $i<strlen($file); $i++)
        {
            if($file[$i] !== "=" && $file[$i] !== " ")
            {
                $curIdx = $i;
                break;
            }
        }


        $condition = substr($file,$curIdx,strpos($file,")",$curIdx)-$curIdx);
        $condition = str_replace('"','',$condition);
        echo htmlspecialchars($condition);
    }

這輸出: <SCRIPT

對於您的腳本,我發現了幾個問題:

if(strpos($value, 'if') !== false) 

必須有一個雙 ==

這樣一來,您將獲得以下輸出:

= "<SCRIPT"

要擺脫這種情況,只需檢查pos1之后的字符是否是另一個=

        if($value[$pos1] === "=")
        {
            $pos1++;
        }

然后我們實際上可以完全刪除對sanitize_recursive的調用,因為substr從不返回數組。

現在擺脫,只需between字符串between調用str_replace

        $between = substr($value, $startIndex, $length);
        $between = str_replace('"','',$between);

        echo htmlspecialchars($between);

我們有一個&lt;SCRIPT的輸出 - 需要調用htmlspecialchars ,否則您的瀏覽器將開始解釋這個標簽。

這給我們留下了以下文件:

<?php
$file = file_get_contents("test.php"); // Code.php the page that include the if condition 
$lines = explode("\n", $file); // get each line of source code and store it in array ($lines)

foreach ($lines as $key => &$value) {
    if(strpos($value, 'if') !== false) // check if the line have if statement 
    {
        if(strpos($value, '==') !== false )  // check if the line compare two values
        {
            $pos1 =  strpos($value, '==') + 2; // get the existence position of '==' + 2 

            if($value[$pos1] === "=")
            {
                $pos1++;
            }

            $pos2 =  strrpos($value, ')'); // get the position of last ) in the line

            $startIndex = min($pos1, $pos2);
            $length = abs($pos1 - $pos2);

            $between = substr($value, $startIndex, $length);
            $between = str_replace('"','',$between);

            echo htmlspecialchars($between); // will print: "<SCRIPT" with double quotation
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM