web-dev-qa-db-ja.com

文字列がPHPでエンコードされたURLかどうかをテストします

文字列がURLエンコードされているかどうかをテストするにはどうすればよいですか?

次のアプローチのどれがより良いですか?

  • 文字列で、エンコードされる文字とエンコードされない文字を検索し、存在する場合はエンコードされない、または
  • 私が作ったこのようなものを使用してください:

function is_urlEncoded($string){
 $test_string = $string;
 while(urldecode($test_string) != $test_string){
  $test_string = urldecode($test_string);
 }
 return (urlencode($test_string) == $string)?True:False; 
}

$t = "Hello World > how are you?";
if(is_urlEncoded($sreq)){
 print "Was Encoded.\n";
}else{
 print "Not Encoded.\n";
 print "Should be ".urlencode($sreq)."\n";
}

上記のコードは機能しますが、次の例のように、文字列が二重にエンコードされている場合は機能しません。

  • $t = "Hello%2BWorld%2B%253E%2Bhow%2Bare%2Byou%253F";
  • $t = "Hello+World%2B%253E%2Bhow%2Bare%2Byou%253F";
20
Psytronic

文字列がURLエンコードされているかどうか、またはシーケンス%2B 初期化。代わりに、それはおそらく文字列がどこから来たのか、つまり、手作りであるか、何らかのアプリケーションからのものであるかによって異なります。

エンコードされる文字とエンコードされない文字を文字列で検索し、存在する場合はエンコードされない方が良いですか?.

プログラムで行われたことを処理するため、これはより良いアプローチだと思います(アプリケーションがエンコードされていない文字を残さないと仮定した場合)。

ここで混乱することの1つ...技術的には、%特殊文字であるため、最終値に存在する場合は「エンコード」する必要があります。エンコードすべき文字を探すためにアプローチを組み合わせる必要があります。また、文字列が見つからない場合に文字列が正常にデコードされることを検証する必要があります。

10
jheddings

私は1つのトリックがあります:

これにより、二重エンコードを防ぐことができます。最初にデコードするたびに、再度エンコードします。

$string = urldecode($string);

それからもう一度

$string = urlencode($string);

この方法を実行すると、二重エンコードを回避できます:)

33
Irfan

ここに私がまとめたものがあります。

if ( urlencode(urldecode($data)) === $data){
    echo 'string urlencoded';
} else {
    echo 'string is NOT urlencoded';
}
12
AMB

私はそれを行うための絶対確実な方法はないと思います。たとえば、次のことを考慮してください。

$t = "A+B";

URLは「A B」にエンコードされていますか、それとも「A%2BB」にエンコードする必要がありますか?

5
Kaivosukeltaja

どうですか:

if (urldecode(trim($url)) == trim($url)) { $url_form = 'decoded'; }
  else { $url_form = 'encoded'; }

ダブルエンコーディングでは動作しませんが、これはとにかく範囲外です?

3
Sebastian

まあ、「エンコードされたURL」という用語は少し曖昧です。おそらく、単純な正規表現チェックがトリックを行います

$is_encoded = preg_match('~%[0-9A-F]{2}~i', $string);
3
user187291

これを行うための信頼できる方法はありません。エンコードプロセス中に同じままの文字列があります。つまり、「abc」がエンコードされているかどうかです。明確な答えはありません。また、あなたが遭遇したように、いくつかの文字は複数のエンコーディングを持っています...しかし...

いくつかの文字が複数の方法でエンコードされている可能性があるため、decode-check-encode-checkスキームは失敗します。ただし、関数へのわずかな変更はかなり信頼できるはずです。デコードによって文字列が変更されているかどうかを確認してください。変更されている場合は、エンコードされています。

もちろん、「10 + 20 = 30」がtrueを返す(+がスペースに変換される)ので、だまされないわけではありませんが、実際には単に算術演算を行っています。私はこれがあなたがスキームが対抗しようとしているものだと思う、私は完璧な解決策があるとは思わないと言って申し訳ありません。

HTH。

編集:
自分のコメントで述べたように(わかりやすくするためにここで繰り返します)、適切な妥協点は、おそらくURLの無効な文字(スペースなど)をチェックし、ある場合はエンコードされないことです。ない場合は、デコードして、文字列が変更されるかどうかを確認してください。これでも上記の算術演算を処理することはできません(不可能です)が、うまくいけば十分です。

3
falstro

@ user187291コードは機能し、+がエンコードされていない場合にのみ失敗します。

これは非常に古い記事です。しかし、これは私にはうまくいきました。

$is_encoded = preg_match('~%[0-9A-F]{2}~i', $string);
if($is_encoded) {
 $string  = urlencode(urldecode(str_replace(['+','='], ['%2B','%3D'], $string)));
} else {
  $string = urlencode($string);
}
2
B L Praveen

すでにURLからデータを取得しているときに、デコードにフラグを立てる変数を送信します。

?path=folder/new%20file.txt&decode=1
1
phpBananas

見つけた。
URLはFor Forapaple: https://example.com/xD?foo=bar&uri=https%3A%2F%2Fexample.com%2FxD
Found $ _GET ['uri']がエンコードされているかどうかが必要です:

preg_match("/.*uri=(.*)&?.*/", $_SERVER['REQUEST_URI'], $r);
if (isset($_GET['uri']) && urldecode($r['1']) === $r['1']) {
  // Code Here if url is not encoded
}
0
MDReal

次のテストを使用して、文字列がurlencodeされているかどうかを確認しています。

if(urlencode($str) != str_replace(['%','+'], ['%25','%2B'], $str))

文字列がすでにurlencodedである場合、ダブルエンコーディングによって変更される文字は、%(すべてのエンコードされた文字列を開始する)と+(スペースを置き換える)のみです。それらを元に戻すと、元の文字列が得られます。

これがうまくいくかどうかを教えてください。

0
Hoytman