3

serialize()外部ソースから取得した PHPの文字列があります。

s:4:"0.00";s:4:"type";s:5:"price";s:3:"$20";s:12:"Foo "Bar" Baz";s:1:"y";

を正常に行うに"Bar"は、に置き換える必要があります。"Bar"unserialize()

preg_replace()これを達成するためにどのように使用できますか?

を試し(?<!s:\d{1,4}:)("[0-9a-zA-Z ]+")ましたが、PHP が後読みエラーをスローします。後読みアサーションはオフセット 14 で固定長ではありません

更新: これは私が作ったダミー文字列です。文字数を間違って数えました...カウントが正しいと仮定しても安全です...文字列は実際には次のようになります。

s:4:"0.00";s:4:"type";s:5:"price";s:3:"$20";s:13:"Foo "Bar" Baz";s:1:"y";

4

3 に答える 3

3

文字列を逆シリアル化できる場合は、逆シリアル化してから、引用符 (およびと) を HTML エンティティhtmlspecialcharsに置き換えます。引用符のみを置き換えたい場合は、 を使用します。<>str_replace


あなたのコードの問題は、引用符があるという事実ではありません! 実際、引用符をエスケープしても問題は解決しません。

あなたが持っているシリアル化された文字列の表現を見てみましょう:s:12:"Foo "Bar" Baz";
これは、文字を含む文字列があることを意味します - 引用符はそこでエスケープする必要はまったくありません。12

あなたが持っているシリアル化されたデータの問題は何ですか?

s:12:"Foo "Bar" Baz";
      1234567890123

ご覧のとおり、パーサーは 12 文字しか想定していませんが、13 文字あります。これが、シリアル化を解除できない理由です。ただし、これは、修正するには12toを変更する必要があることを意味します。13

これは実際にはどういう意味ですか?正規表現を使用してデータを修正することは不可能です! 実際に行う必要があるのは、無効なデータを送信するソースを修正することです!

于 2013-02-24T12:15:32.087 に答える
1
$string = preg_replace_callback('/(s:\d+:\")(.*?)(\";)/i', function($matches){
  return $matches[1] . htmlspecialchars($matches[2], ENT_QUOTES) . $matches[3];
}, $string);

( のように、文字列の引用符の後にセミコロンがある場合、これは失敗しますFoo "Bar"; Foo)


@ThiefMasterは正しいです。文字列を完全に修正する試み:

$keys = 0;
$string = preg_replace_callback('/s:(\d+):\"(.*?)\";/i',
  function($matches) use(&$keys){
    return sprintf('i:%d;s:%d:"%s";', ++$keys, strlen($matches[2]), $matches[2]);
  }, $string);

$string = sprintf('a:%d:{%s}', $keys, $string);
$result = unserialize($string);

これを配列でラップしました。そこにあるものをシリアル化解除すると、最初の要素の値しか取得できないためです...

于 2013-02-24T12:01:11.237 に答える
-1
preg_replace('|( "[0-9A-Z]+" )|ei', " stripslashes(htmlentities('$1')) ", $str)
于 2013-02-24T11:48:34.507 に答える