2010-05-20 17 views
8

Ich versuche, die json_encode Bitmaske flags in PHP 5.3.0 implementiert zu imitieren, hier ist die Zeichenfolge ich habe:Escaping Escape-Zeichen

$s = addslashes('O\'Rei"lly'); // O\'Rei\"lly 

json_encode($s, JSON_HEX_APOS | JSON_HEX_QUOT) Doing gibt der folgende:

"O\\\u0027Rei\\\u0022lly" 

und ich mache das derzeit in PHP-Versionen älter als 5.3.0:

str_replace(array('\\"', "\\'"), array('\\u0022', '\\\u0027'), json_encode($s)) 
or 
str_replace(array('\\"', '\\\''), array('\\u0022', '\\\u0027'), json_encode($s)) 

Welche richtig das gleiche Ergebnis ausgibt:

"O\\\u0027Rei\\\u0022lly" 

Ich habe Probleme zu verstehen, warum ich Sie ('\\\'' oder sogar "\\'" [umschließenden Anführungszeichen ausgeschlossen]) mit '\\\u0027' und nicht nur '\\u0027' ersetzen müssen .


Hier ist der Code, den ich habe Probleme zu PHP < 5.3 Portierung mit:

if (get_magic_quotes_gpc() && version_compare(PHP_VERSION, '6.0.0', '<')) 
{ 
    /* JSON_HEX_APOS and JSON_HEX_QUOT are availiable */ 
    if (version_compare(PHP_VERSION, '5.3.0', '>=') === true) 
    { 
     $_GET = json_encode($_GET, JSON_HEX_APOS | JSON_HEX_QUOT); 
     $_POST = json_encode($_POST, JSON_HEX_APOS | JSON_HEX_QUOT); 
     $_COOKIE = json_encode($_COOKIE, JSON_HEX_APOS | JSON_HEX_QUOT); 
     $_REQUEST = json_encode($_REQUEST, JSON_HEX_APOS | JSON_HEX_QUOT); 
    } 

    /* mimic the behaviour of JSON_HEX_APOS and JSON_HEX_QUOT */ 
    else if (extension_loaded('json') === true) 
    { 
     $_GET = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_GET)); 
     $_POST = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_POST)); 
     $_COOKIE = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_COOKIE)); 
     $_REQUEST = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_REQUEST)); 
    } 

    $_GET = json_decode(stripslashes($_GET)); 
    $_POST = json_decode(stripslashes($_POST)); 
    $_COOKIE = json_decode(stripslashes($_COOKIE)); 
    $_REQUEST = json_decode(stripslashes($_REQUEST)); 
} 
+0

Warum die downvote? –

Antwort

13

Der PHP-String

'O\'Rei"lly' 

ist j Wie PHP den Literalwert

O'Rei"lly 

in eine Zeichenfolge erhält, die verwendet werden kann. Aufruf addslashes auf dieser Zeichenkette ändert es buchstäblich die folgenden 11 Zeichen

O\'Rei\"lly 

d.h. strlen(addslashes('O\'Rei"lly')) == 11

Dies ist der Wert zu sein, der an json_escape gesendet wird.

In JSON Backslash ist ein Escape-Zeichen, so dass zu entkommen muss das heißt

\\\

Auch einfache und doppelte Anführungszeichen zu Problemen führen kann zu sein. Sie werden also in einer Weise in ihre Unicode-Äquivalente konvertiert, um Probleme zu vermeiden.So später verions von json_encode Änderung des PHP

'\u0027

zu sein und

" sein \u0022

Also diese drei Regeln zu

O\'Rei\"lly 

Anwendung gibt uns

O\\\u0027Rei\\\u0022lly 

Diese Zeichenfolge wird dann in doppelte Anführungszeichen gesetzt, um sie zu einer JSON-Zeichenfolge zu machen. Ihre Ersetzungsausdrücke enthalten die führenden Schrägstriche. Entweder aus Versehen oder absichtlich bedeutet dies, dass das führende und nachfolgende doppelte Zitat, das von json_encode zurückgegeben wird, nicht der Flucht unterliegt, was nicht sein sollte.

So in früheren Versionen von PHP

$s = addslashes('O\'Rei"lly'); 
print json_encode($s); 

würde drucken

"O\\'Rei\\\"lly" 

und wir wollen ' ändern sein \u0027 und wir wollen \" ändern sein \u0022 weil die \ in \" ist nur die " in die Zeichenfolge zu bekommen, weil es beginnt und endet mit doppelten Anführungszeichen.

Also, warum wir

"O\\\u0027Rei\\\u0022lly" 
+1

Macht Sinn. Also wird 'str_replace (array ('\' ',' \ ''), array ('\ u0022', '\' u0027 '), json_encode (addslashes (' O \ 'Rei" lly'))) liefert immer genau die gleiche Ausgabe wie 'json_encode (addslashes ('O \' Rei" lly '), JSON_HEX_APOS | JSON_HEX_QUOT) ', richtig? –

+0

Scheint nicht zu funktionieren, wenn eine Zeichenkette mit einem Schrägstrich endet. –

2

Es ist Flucht aus dem umgekehrten Schrägstrich als auch das Zitat. Es ist schwierig, mit entflohenen Fluchten umzugehen, wie Sie es hier tun, da es sich schnell in Backslash-Zählspiele verwandelt. : -/

+0

Aber ich glaube, ich mache die Mathematik richtig. Der Ersatz für einfache Anführungszeichen sollte nur zwei umgekehrte Schrägstriche benötigen, nein? –

+0

Es ist nicht so einfach, weil einige Ihrer String-Konstanten in Anführungszeichen stehen, die keine einfachen Anführungszeichen benötigen, und einige in einfachen Anführungszeichen. Hinzu kommt die Komplikation, * eine gültige String-Konstante * generieren zu müssen. Für eine andere Sprache. Das hat fast identische Zitationsregeln. (Kopfschmerz noch? :-) – staticsan

+0

Außerdem startet Ihr Beispielstring * mit explizitem Escaping * in der Zeichenkette *. Du fragst also 'json_encode()', um auch der Flucht zu entkommen. Und zu guter Letzt denke ich, dass die Notwendigkeit von 'json_encode()' zur Erzeugung von UTF-Entitäten fraglich ist (ich habe Fehler in dieser Funktion schon einmal gefunden). – staticsan

1

Da Sie zu json_encode die Zeichenfolge \' gehen, müssen Sie zuerst die \ dann die ' kodieren. So haben Sie \\ und \u0027. Verkettung dieser Ergebnisse \\\u0027.

+0

Ich folge immer noch nicht. Warum sollte '\ u0027' entkommen? 'Json_encode ('"', JSON_HEX_QUOT); // "\ u0022" 'und' json_encode ("'", JSON_HEX_APOS) // "\ u0027" 'ähnliche Ausgabe zurückkehren, doch die erste benötigt keine zusätzlichen Schrägstriche –

+0

. Ihr ursprünglicher String ist 'O \' Rei 'lly' (alle in Anführungszeichen). In einfachen Anführungszeichen ist das \ kein Escape-Zeichen. In diesem Fall wird es auch codiert. Wenn Sie "O'Rei" schreiben, erhalten Sie das gewünschte Ergebnis. – Zsolti

+0

In einfachen Anführungszeichen "**" ist ** ein Escape-Zeichen. Trotzdem habe ich Ihren Vorschlag ausprobiert und es funktioniert immer noch nicht mit '\ –

0

Die \ generiert von addslashes() erhalten wieder von json_encode(). Sie wollten wahrscheinlich sagen Doing json_encode($s, JSON_HEX_APOS | JSON_HEX_QUOT) outputs the following, aber Sie haben $str anstelle von , die alle verwirrt.

Wenn Sie die Zeichenfolge "O\\\u0027Rei\\\u0022lly" in JavaScript zu bewerten, werden Sie "O\'rei\"lly" bekommen, und ich bin ziemlich sicher, dass nicht was Sie wollen. Wenn Sie es auswerten, müssen Sie wahrscheinlich alle Steuercodes entfernt haben. Mach weiter, stecke das in eine Datei: alert("O\\\u0027Rei\\\u0022lly").

Fazit: Sie entgehen den Anführungszeichen zweimal, was wahrscheinlich nicht das ist, was Sie brauchen. json_encode entzieht bereits alles, was benötigt wird, damit jeder JavaScript-Parser die ursprüngliche Datenstruktur zurückgibt. In Ihrem Fall ist das die Zeichenfolge, die Sie nach dem Aufruf an erhalten haben.


Beweis:

<?php $out = json_encode(array(10, "h'ello", addslashes("h'ello re-escaped"))); ?> 
<script type="text/javascript"> 
    var out = <?php echo $out; ?>; 
    alert(out[0]); 
    alert(out[1]); 
    alert(out[2]); 
</script> 
+0

Ich "brauche" die Zeichenfolge zweimal zu entkommen, da ich bereits die Zeichenfolge mit zusätzlichen Schrägstrichen im Fall "magic_quotes" in "On" erhalten habe. Dennoch beantwortet meine Antwort nicht mein Problem mit dem Ersetzen von erkannten Zeichen. –

+1

Du hast nicht sorgfältig genug gelesen, du musst das nicht tun, eigentlich solltest du das nicht tun. Es ist genau das, was wegen addslashes() passiert betrachtet zu einem Teil der Zeichenfolge, die Sie wollen als ausgegeben. Was Sie tun sollten, ist zu deaktivieren 'Magie quotes' (oder zwingen' array_walk_recursive ($ _ REQUEST ‚strip‘) ') und alles wird klar sein. – Tom

+1

und die Welt wäre ein viel sicherer ohne Atomwaffen, aber das heißt nicht, dass es keine gibt. Meine ursprüngliche Zeichenfolge hat Schrägstriche und der Grund dieser Frage ist, rekursive Aufrufe in 'PHP> = 5.2 <5.3' zu vermeiden, um 'magic_quotes' zu beheben (siehe meine PHP 5.3 Lösung unter http://www.php.net/manual/en/function.get) -magic-quotes-gpc.php # 95697). –

2

Wenn ich richtig verstehe, wollen Sie nur wissen, warum Sie

'\\\u0027' verwenden müssen, und zwar nicht nur '\\u0027'

Sie‘ Re entkommen den Schrägstrich und das Zeichen Unicode Val Ue. Damit sagen Sie json, dass es dort einen Apostroph geben sollte, aber es benötigt den Backslash und die u, um zu wissen, dass ein hexadezimaler Unicode-Zeichencode als nächstes kommt.

Da Sie diese Zeichenfolge sind auf der Flucht:

$s = addslashes('O\'Rei"lly'); // O\'Rei\"lly 

die erste Schrägstrich vor dem Apostroph den umgekehrten Schrägstrich tatsächlich zu entkommen. Dann wird der nächste Schrägstrich verwendet, um den von json verwendeten Backslash zu umgehen, um das Zeichen als Unicode-Zeichen zu identifizieren.

Wenn Sie die algorythm zu O'Reilly wurden appplying statt O \ 'Rei \ "lly dann würde diese ausreichen.

Ich hoffe, dass Sie diese nützlich finden. Ich Ihnen diesen Link nur verlassen, so dass Sie lesen können mehr darüber, wie json ist so konstruiert, da sie offensichtlich, dass du bereits PHP verstehen:

http://www.json.org/fatfree.html

2

bekommen Wenn Sie eine Zeichenfolge für json kodieren, haben einige Dinge, unabhängig von den Optionen entgangen sein. Wie andere darauf hingewiesen haben, enthält das "\", so dass jeder Backslash-Lauf durch json_encode verdoppelt wird. Da Sie Ihre Zeichenfolge zuerst über addslashes ausführen, die auch Anführungszeichen Backslashes hinzufügen, fügen Sie viele zusätzliche Backslashes hinzu. Die folgende Funktion emuliert, wie json_encode eine Zeichenfolge codiert. Wenn der Zeichenfolge bereits umgekehrte Schrägstriche hinzugefügt wurden, werden sie verdoppelt.

function json_encode_string($encode , $options) { 
    $escape = '\\\0..\37'; 
    $needle = array(); 
    $replace = array(); 

    if ($options & JSON_HEX_APOS) { 
     $needle[] = "'"; 
     $replace[] = '\u0027'; 
    } else { 
     $escape .= "'"; 
    } 

    if ($options & JSON_HEX_QUOT) { 
     $needle[] = '"'; 
     $replace[] = '\u0022'; 
    } else { 
     $escape .= '"'; 
    } 

    if ($options & JSON_HEX_AMP) { 
     $needle[] = '&'; 
     $replace[] = '\u0026'; 
    } 

    if ($options & JSON_HEX_TAG) { 
     $needle[] = '<'; 
     $needle[] = '>'; 
     $replace[] = '\u003C'; 
     $replace[] = '\u003E'; 
    } 

    $encode = addcslashes($encode , $escape); 
    $encode = str_replace($needle , $replace , $encode); 

    return $encode; 
} 
+1

+1 für Erwähnung andere problematische Zeichen. – Eldros