Inspektor procentuálního kódování

Procentní kódování není jedno pravidlo, ale několik a na asi tuctu znaků se neshodují. Tato stránka prožene týž text přes encodeURIComponent, encodeURI a serializaci application/x-www-form-urlencoded vedle sebe, označí znaky, kde se neshodují, vypíše řádek na znak s jeho bajty UTF-8 a třídou RFC 3986 a řekne, kolikrát byl řetězec zakódován. Dekódovací strana čte řetězec podle pravidla přísného nebo volného a řekne, která escape je rozbitá a kde, místo aby vrátila tiše špatný výsledek.
Veškeré zpracování probíhá lokálně ve vašem prohlížeči — vaše data se nikdy nenahrávají na žádný server.

Nejste si jisti, co je procentní kódování? Procentní kódování vysvětleno prostě — co to je, proč se mezera změní na %20 nebo +, a co znamená, když URL ukazuje %25.
Co to dělá:
Jak číst escapy:
encodeURIComponent
encodeURI
formulář (application/x-www-form-urlencoded)
Ctrl+Enter ve vstupu spustí aktivní režim.
Vyberte režim a klikněte na jeho akční tlačítko. Kódovat a prozkoumat ukáže tři kódování vašeho textu plus řádek na znak; Dekódovat přečte escapy zpět a spočítá vrstvy. Tlačítko Samotest znovu spustí každou zdokumentovanou ukázku, každý tisknutelný znak ASCII a řetězce vrstev zaznamenané v datovém souboru této stránky, a zde uvede počet.
Kde se enkodéry neshodují:jen níže uvedené znaky se třemi metodami zacházejí různě. Vše ostatní projde všemi třemi nezměněno, nebo je všemi třemi escapováno stejně.
Každý znak, jeden řádek na znak:bajty UTF-8, do nichž se znak převede, třída, kterou mu přiřazuje RFC 3986, a escape, který každý kontext zapíše. Čtyři sloupce kontextů jsou procentní sady WHATWG, které prohlížeč používá při sestavování cesty, dotazu nebo fragmentu; zastíněný řádek je znak, se kterým tři enkodéry zacházejí různě.
Přesná sada, kterou tato stránka escapuje pro každou část URL:vytištěno přímo z enkodéru, takže tato tabulka a kód, který naplňuje výše uvedené sloupce, se nemohou rozejít. Každá sada také escapuje řídicí znaky C0 (U+0000 až U+001F) a každý kódový bod nad U+007E, a proto se text mimo ASCII v každém kontextu vždy escapuje.
Tyto sady jsou odvozeny z procentních sad WHATWG a liší se od nich ve dvou záměrných místech, a obě dělají ruční sestavování bezpečným: hash se escapuje uvnitř dotazu, protože surový by začal fragment; a sada komponent je ukotvena přesně na znacích, které escapuje encodeURIComponent, včetně apostrofu, zatímco sada formuláře je ukotvena na tom, co escapuje URLSearchParams. Dva sloupce v tabulce výše jsou tedy vlastním chováním platformy, ne jeho znovuvytvořením. Tento seznam vysvětluje i výsledek, který lidi překvapuje: znak procenta escapuje encodeURIComponent i encodeURI, ale není v žádné sadě kontextu WHATWG, takže sloupce cesty, dotazu a fragmentu tabulky po znacích ho nechávají být. Surové procento v URL, které jste sestavili ručně, je pořád riziko, protože standard očekává, že vstup byl nejprve ověřen: %41 uvnitř dotazu je pro mnoho serverových frameworků jediné A a přísné čtení této stránky zachází s osamoceným % jako s rozbitým escapem. Escapovat je ručně jako %25 je bezpečnější zvyk a tabulka po znacích ukazuje oba zápisy vedle sebe.
Kolikrát byl tento řetězec zakódován:každé kolo dekódování je jedna vrstva. Hodnota, která byla zakódována dvakrát, začíná%25kde by jediné kódování zanechalo%20a hodnota, která byla zakódována třikrát, začíná%2525.
Znaky, které URL smí nést tak, jak jsou:RFC 3986 rozděluje rozsah ASCII do tří skupin a pravidla escapování dávají smysl jen vůči tomuto rozdělení.
Rezervované znaky nejsou zakázané, jsou obsazené: něco znamenají pro analyzátor URL. Pravidlo, které z toho seznamu plyne, je krátké — pokud je znak rezervovaný a myslíte jím data, escapujte ho; pokud je neřízený, escapovat nikdy nemusíte.
Tři metody a co každá nechává být:
Seznamy jsou přesné sady, které každá metoda v rozsahu ASCII nechává neescapované; Samotest je proti nim ověřuje každý tisknutelný znak ASCII, takže tabulka se nemůže odchýlit od enkodérů, které popisuje.
Jak velký vstup tato stránka přijme a proč:Procentní kódování je jediný průchod textem, takže na rozdíl od převodníků číselných soustav na tomto webu náklady rostou přímo úměrně, ne kvadraticky: neexistuje délka, při které by samotná aritmetika byla problémem. Níže uvedené limity existují, protože tabulka po znacích se kreslí v dokumentu, a tabulka s milionem řádků je přesně to, co prohlížeč zastaví.
Co je procentní kódování?

Procentní kódování — nazývané také kódování URL, a ve starších dokumentech escapování — je pravidlo, které umožňuje URL nést znaky, které nesmí obsahovat. Procentní escape jsou tři znaky ASCII: znak procenta a dvě hexadecimální číslice, které označují jeden bajt. %20 je bajt 0x20, což je mezera. %2F je bajt 0x2F, což je lomítko. Nic jiného do toho nevstupuje: escape pojmenovává bajt, ne znak.

Protože pojmenovává bajty, musí být text nejprve převeden na bajty a kódování bajtů je UTF-8. Odtud pocházejí dlouhé escapy: jeden čínský znak jsou tři bajty UTF-8, a tedy tři escapy, a jeden emotikon jsou čtyři bajty, tedy dvanáct znaků ASCII.

Verze na 30 sekund: mezera je %20 jako hodnota URL, ale + v datech formuláře; # je %23; doslovné procento je %25. Tři kodéry na této stránce se shodují na písmenech, číslicích a -_., a neshodují se na asi tuctu interpunkčních znaků, mezi nimi na vlnovce — právě proto encodeURIComponent a encodeURI dávají pro týž text různé řetězce a právě proto může špatná z těchto dvou rozdělit hodnotu na dva parametry dotazu.
Proč to URL vůbec potřebuje

URI je definováno jako posloupnost znaků ASCII (RFC 3986, oddíl 2.1) a v tomto rozsahu ASCII jsou některé znaky rezervované: jsou to interpunkční znaky, které dávají URL strukturu. Dvojtečka a dvě lomítka oddělují schéma, zavináč odděluje uživatelské údaje od hostitele, otazník začíná dotaz, křížek začíná fragment, ampersand odděluje parametry dotazu a znak procenta uvádí escape.

To vytváří jeden problém a jednu mezeru. Problém: hodnota, která sama obsahuje některý z těchto znaků — vyhledávací pole s "a&b", název souboru s lomítkem, heslo s dvojtečkou — by jinak změnila strukturu URL, ve které putuje. Mezera: samotné procento, takže enkodér může jednoduše rozšířit svou vlastní abecedu. % se zapisuje jako %25 a dvě hexadecimální číslice za ním jsou obyčejné neřízené znaky.

Propracované příklady

Toto jsou přesné výstupy tří enkodérů, které tato stránka spouští, na vstupech vybraných proto, že se navzájem chovají různě. Stránka je přepočítá přímo před vámi a její Samotest znovu ověří každý řádek proti vlastním implementacím platformy.

Tři metody a kdy je která správná

Krátká verze, která ušetří většinu chyb: cokoli, co jde do jedné hodnoty parametru, prochází přes encodeURIComponent (nebo přes serializátor formuláře, který dělá stejnou práci s jinou bezpečnou sadou), a hotová URL, která je už sestavena, prochází přes encodeURI, pokud vůbec potřebuje escapování. Sáhnout po špatné z těchto dvou je nejčastější chyba procentního kódování ve webovém kódu.

Znaky, které URL smějí nést, úplně
Dvě plus, dva významy

Mezera je jediný znak, jehož kódování závisí na tom, kam text půjde, a příčinou je znaménko plus.

Past je uprostřed této tabulky. V datech formuláře znamená znaménko plus mezeru, takže hodnota, která opravdu obsahuje znaménko plus — telefonní číslo zapsané jako +44 20 7946 0958, aritmetický výraz, e-mailová adresa se značkou plus — musí putovat jako %2B. Pokud putuje jako doslovné znaménko plus, příjemce ho přečte jako mezeru a +44 dorazí jako " 44".

Zakódováno dvakrát a jak to poznat

K dvojitému kódování dojde, když je řetězec už escapovaný a escapuje se znovu. Znak procenta z prvního escapu je jako každý jiný znak, takže se změní na %25 a vrstva pod ním přežije jako viditelný text.

Rozpoznání je otázka počítání: dekódujte řetězec jednou a podívejte se na výsledek. Pokud stále obsahuje escapy, které vypadají záměrně — platné %XX nebo znaménko plus formuláře tam, kde se čeká mezera — existuje další vrstva. Pokud obsahuje %25 následované dvěma hexadecimálními číslicemi, další vrstva je určitě escape.

Dvě praktické poznámky. Za prvé: dekódovat dvakrát není neškodné — je to dobře známý způsob, jak donutit bezpečnostní filtr a kód za ním vidět různé řetězce, takže filtr, který běží před druhým dekódováním, filtruje špatný text. Za druhé: počet vrstev zde je vlastností řetězce, ne slibem o záměru; oprávněná hodnota může být hluboká jednu vrstvu a rozbitá může být dvě.

Chyby, na které je tato stránka postavena, aby je zachytila
  • Hodnota kódovaná pomocí encodeURI. Oddělovače přežijí, takže hodnota obsahující & nebo = se na druhé straně rozdělí na více parametrů. Porovnejte dva sloupce nahoře na této stránce pro vstup a&b=c: sloupec komponenty escapuje oba znaky, sloupec encodeURI je ponechá.
  • Doslovné znaménko plus odeslané jako data formuláře. Dorazí jako mezera. Použijte %2B.
  • Hodnota escapovaná dvakrát "pro jistotu". Není to bezpečnější. Příjemce dekóduje jednou a dostane řetězec, který stále obsahuje escape procenta, což je tatáž chyba jako špatná znaková sada, o vrstvu níž.
  • Dekódování něčeho, co nebylo nikdy zakódováno. Doslovné procento v textu — 100% sure — není escape. Při přísném čtení je to rozbitý escape na pozici, kterou tato stránka hlásí; při volném čtení přežije, a proto je zde výchozí volné čtení a ne opačně.
  • Předpoklad, že escape musí být velkými písmeny. Dekódování bere %2f a %2F jako stejný bajt a obě jsou platné. Velká písmena jsou jen kanonický zápis, který doporučuje RFC 3986 a který budou produkovat jiné nástroje.
  • Předpoklad, že procentní kódování text zabezpečí. Dělá text jednoznačným uvnitř URL. Nezastaví injektáž, není to šifrování a není to sanitizér: escapování musí být posledním krokem před sestavením, pro kontext, do kterého text jde.
Rychlé odpovědi

“Je znaménko plus v URL mezerou?”

Jen v datech formuláře a jen v části dotazu odeslaného formuláře. V cestě, ve fragmentu a v dotazu prostého odkazu je znaménko plus doslovným znaménkem plus. Proto má tato stránka pro to přepínač a neodhaduje to.

“Proč můj odkaz ukazuje %25?”

Protože něco zakódovalo znak procenta. Buď doslovné procento prošlo enkodérem — 100% sure se změní na 100%25%20sure — nebo řetězec, který už escape obsahoval, byl zakódován podruhé. Dekódujte řetězec jednou a podívejte se, co se vrátí: pokud výsledek stále obsahuje %XX, existuje další vrstva.

“Záleží na tom, zda je lomítko uvnitř hodnoty dotazu %2F, nebo /?”

Pro analyzátor URL ne: obojí dorazí na server jako lomítko a sada dotazu WHATWG lomítko nechává být. Pro interoperabilitu někdy ano: mnoho serverových frameworků provádí vlastní dekódování nad surovým řetězcem dotazu a několik z nich se neshoduje na znacích, které nikdy nebyly zakódovány. Když hodnotu skládáte ručně místo serializátorem, je bezpečnější zvyk explicitně escapovat rezervované znaky.

“Proč sloupec formuláře escapuje vlnovku, kterou ostatní dva nechávají být?”

Protože bezpečná sada enkodéru formuláře je užší: jen písmena, číslice a -_.*. Enkodér formuláře WHATWG escapuje ~ ! ' ( ), ačkoli RFC 3986 uvádí ~ mezi neřízenými. Oba zápisy se dekódují na stejnou hodnotu; rozdíl je důležitý jen při porovnávání řetězců bajt po bajtu.

“Mohou se stejné znaky objevit neescapované v adresním řádku prohlížeče?”

Ano, a to je adresní řádek, ne URL. Prohlížeče zobrazují čitelnou podobu URL a při odeslání ji kódují, takže 中文 v odkazu se na drátě stane %E4%B8%AD%E6%96%87. Když URL zkopírujete z adresního řádku, můžete dostat kteroukoli podobu podle prohlížeče.

“Každý escape tu vypadá správně, ale vyjde jiný znak, než jsem čekal. Proč?”

Za větou "dekódovalo se to špatně" se skrývají dvě různá selhání a stránka je hlásí různě. Prvním je rozbitý escape: znak procenta, za nímž nenásledují dvě hexadecimální číslice, jako koncové 100% nebo %zz. To je problém syntaxe; přísné čtení jej odmítne a řekne, kde je, zatímco volné čtení jej ponechá jako doslovný text a vypíše jej. Druhým je escape, jehož bajt je zcela legální, ale jehož bajty nevytvářejí platný znak UTF-8, jako samotné %FF nebo tříbajtový znak useknutý jako %E4%B8. To není problém syntaxe, takže obě čtení vrátí text, bajty, které nelze dekódovat, nahradí náhradním znakem U+FFFD ("�") a vypíšou varování, které to říká. Právě to varování je užitečné: text, který přijde jako náhradní znaky, obvykle znamená, že odesílatel použil jinou znakovou sadu, nebo že řetězec byl zakódován o jednu vrstvu víc. Procentní kódování pojmenovává bajty a tato stránka, stejně jako standard URL, tyto bajty vždy čte jako UTF-8.

“Co tato stránka nedělá?”

Nerozděluje URL na schéma, hostitele, cestu a dotaz — k tomu slouží analyzátor URL. Nekontroluje, zda je odkaz bezpečné otevřít, nic nekontaktuje a neodhaduje znakovou sadu bajtů za escapem: vždy je čte jako UTF-8, jak to vyžaduje standard URL.

“Jaké záložní řešení dekódování potřebuje a jak poznám, že je správné?”

Stiskněte Samotest. Porovná vlastní enkodéry stránky s encodeURIComponent, encodeURI a URLSearchParams platformy pro každý tisknutelný znak ASCII, znovu spustí každý příklad v tabulkách výše, znovu ověří zaznamenané řetězce vrstev a počet kontrol zde uvede.

Normy a rozsah

Procentní kódování je specifikováno v RFC 3986, oddíl 2.1; definice rezervovaných a neřízených znaků je v oddílech 2.2 a 2.3 a pravidlo velikosti písmen v oddílu 6.2.2.1. Sady, které prohlížeč skutečně používá při sestavování URL, jsou ve standardu URL WHATWG, který je rozděluje podle kontextu: jedna sada pro fragment, jedna pro dotaz, jedna pro speciální dotaz, jedna pro cestu, jedna pro uživatelské údaje a užší pro jednu komponentu. Odeslání formuláře včetně znaménka plus je v HTML Standard pod application/x-www-form-urlencoded. Dvě funkce encodeURI a encodeURIComponent jsou součástí samotného ECMAScriptu.

Tato stránka vyplňuje sloupce cesty, dotazu a fragmentu z vlastních sad pro jednotlivé kontexty a vedle výsledku vypíše přesný seznam pro každý kontext. Tyto sady jsou odvozeny z těch WHATWG a liší se od nich ve dvou záměrných místech: hash se uvnitř dotazu escapuje, protože by surový hash začínal fragment, a sada komponent je ukotvena přesně na znacích, které escapuje encodeURIComponent. Tam, kde je funkce platformy definicí odpovědi — encodeURIComponent, encodeURI a serializace formuláře — je tato funkce volána přímo, takže tyto sloupce jsou vlastním chováním prohlížeče, ne jeho znovuvytvořením.

Text stránky byl napsán pro tento web. Každá hodnota v tabulkách výše je vytvořena vlastním kódem stránky při načtení a byla ověřena proti implementacím platformy v testovacích nástrojích tohoto webu; Samotest toto porovnání zopakuje ve vašem prohlížeči.