Inšpektor percent kódovania

Percentové kódovanie nie je jedno pravidlo, ale viacero, a na asi tucte znakov sa nezhodujú. Táto stránka spracuje ten istý text cez encodeURIComponent, encodeURI a serializáciu application/x-www-form-urlencoded vedľa seba, označí znaky, v ktorých sa nezhodujú, vypíše riadok na každý znak s jeho bajtmi UTF-8 a triedou RFC 3986 a uvedie, koľkokrát bol reťazec zakódovaný. Dekódovacia strana číta reťazec podľa prísneho alebo voľného pravidla a hovorí, ktorá únikova sekvencia je pokazená a kde, namiesto toho, aby vrátila potichu nesprávny výsledok.
Všetko sa spracúva lokálne v prehliadači — údaje sa nikdy nenahrávajú na žiadny server.

Nie je jasné, čo je percentové kódovanie? Percentové kódovanie vysvetlené jednoducho — čo to je, prečo sa medzera zmení na %20 alebo +, a čo znamená, keď URL zobrazuje %25.
Čo toto robí:
Ako čítať úniky:
encodeURIComponent
encodeURI
formulár (application/x-www-form-urlencoded)
Ctrl+Enter vo vstupe spustí aktívny režim.
Vyberie sa režim a stlačí sa jeho tlačidlo akcie. Kódovať a skontrolovať zobrazí tri kódovania textu a riadok na každý znak; Dekódovať prečíta únikové sekvencie späť a spočíta vrstvy. Tlačidlo Samotest znova spustí každú zdokumentovanú vzorku, každý tlačiteľný znak ASCII a reťazce vrstiev zaznamenané v dátovom súbore tejto stránky, a výsledok sa uvedie tu.
Kde sa kodéry nezhodujú:iba znaky nižšie sa tromi metódami zaobchádza rozdielne. Všetko ostatné prejde všetkými tromi nezmenené alebo je escapované rovnako všetkými tromi.
Každý znak, jeden riadok na znak:bajty UTF-8, do ktorých sa znak mení, trieda, ktorú mu RFC 3986 priraďuje, a únik, ktorý každý kontext zapíše. Štyri stĺpce kontextu sú množiny percent-encode WHATWG, ktoré prehliadač používa pri zostavovaní cesty, dotazu alebo fragmentu; zatienený riadok označuje znak, s ktorým tri kodéry zaobchádzajú rozdielne.
Presná množina, ktorú táto stránka escapuje pre každú časť URL:vypísané priamo z kodéra, takže táto tabuľka a kód, ktorý vypĺňa stĺpce vyššie, sa nemôžu odchýliť. Každá množina tiež escapuje riadiace znaky C0 (U+0000 až U+001F) a každý bod kódu nad U+007E, preto sa text mimo ASCII escapuje vždy vo všetkých kontextoch.
Tieto množiny sú odvodené z množín percent-encode WHATWG a odlišujú sa od nich na dvoch zámerných miestach, ktoré obe robia ručné zostavovanie bezpečným: mriežka sa escapuje v dotaze, pretože surová by začala fragment; a množina komponentu je pevne daná presne na znaky, ktoré escapuje encodeURIComponent, vrátane apostrofu, zatiaľ čo množina formulára je pevne daná na to, čo escapuje URLSearchParams. Dva stĺpce v tabuľke vyššie sú teda správanie samotnej platformy, nie jeho znovuimplementácia. Ten zoznam tiež vysvetľuje výsledok, ktorý ľudia považujú za prekvapivý: percento escapuje encodeURIComponent aj encodeURI, ale nie je v žiadnej z množín kontextu WHATWG, takže stĺpce cesty, dotazu a fragmentu v tabuľke po znakoch ho nechajú na pokoji. Surové percento v URL zostavenej ručne je stále riziko, pretože štandard očakáva, že vstup bol najprv overený: %41 v dotaze je pre mnohé serverové frameworky jedno A a voľné čítanie tejto stránky zaobchádza so samostatným % ako s pokazeným únikom. Zapísať ho ručne ako %25 je bezpečnejší zvyk a tabuľka po znakoch zobrazuje obe podoby vedľa seba.
Koľkokrát bol tento reťazec zakódovaný:každé kolo dekódovania je jedna vrstva. Hodnota zakódovaná dvakrát začína%25kde by jediné kódovanie zanechalo%20, a hodnota zakódovaná trikrát začína%2525.
Znaky, ktoré môže URL niesť tak, ako sú:RFC 3986 rozdeľuje rozsah ASCII na tri skupiny a pravidlá escapovania dávajú zmysel iba oproti tomuto rozdeleniu.
Vyhradené znaky nie sú zakázané, sú obsadené: pre analyzátor URL niečo znamenajú. Pravidlo, ktoré z toho zoznamu vyplýva, je krátke — ak je znak vyhradený a myslí sa ako údaj, escapuje sa; ak je nevyhradený, escapovanie sa nikdy nepotrebuje.
Tri metódy a čo každá z nich nechá na pokoji:
Zoznamy sú presné množiny, ktoré každá metóda v rozsahu ASCII nechá nezakódované; samotest overuje každý tlačiteľný znak ASCII oproti nim, takže tabuľka sa nemôže odchýliť od kodérov, ktoré opisuje.
Aký veľký vstup táto stránka prijíma a prečo:Percentové kódovanie je jeden prechod textom, takže na rozdiel od konvertorov sústav na tejto stránke rastú náklady priamočiaro, nie štvorcovo: neexistuje dĺžka, pri ktorej by samotná aritmetika bola problémom. Limity nižšie existujú preto, že tabuľka po znakoch sa kreslí v dokumente, a tabuľka s miliónom riadkov je presne to, čo prehliadač skutočne zastaví.
Čo je percentové kódovanie?

Percentové kódovanie — nazývané tiež kódovanie URL a v starších dokumentoch escapovanie — je pravidlo, ktoré umožňuje URL niesť znaky, ktoré nesmie obsahovať. Percentný únik sú tri znaky ASCII: znak percenta a dve hexadecimálne číslice, ktoré znamenajú jeden bajt. %20 je bajt 0x20, čo je medzera. %2F je bajt 0x2F, čo je lomka. Nič iné do toho nevstupuje: únik pomenúva bajt, nie znak.

Keďže pomenúva bajty, text sa najprv musí previesť na bajty a kódovanie bajtov je UTF-8. Odtiaľ pochádzajú dlhé úniky: jeden čínsky znak sú tri bajty UTF-8, a teda tri úniky, a jeden emoji sú štyri bajty, teda dvanásť znakov ASCII.

Verzia na 30 sekúnd: medzera je %20 ako hodnota URL, ale + v údajoch formulára; # je %23; doslovné percento je %25. Tri kodéry na tejto stránke sa zhodujú na písmenách, číslicach a -_. a nezhodujú sa asi na tucte interpunkčných znakov, medzi nimi aj na vlnovke — práve preto encodeURIComponent a encodeURI vytvoria pre ten istý text rozdielne reťazce a nesprávna z nich dvoch môže rozdeliť hodnotu na dva parametre dotazu.
Prečo URL vôbec potrebuje kódovanie

URI je definovaný ako postupnosť znakov ASCII (RFC 3986, oddiel 2.1) a v tomto rozsahu ASCII sú niektoré znaky vyhradené: sú to interpunkčné znaky, ktoré dávajú URL štruktúru. Dvojbodka a dve lomky oddeľujú schému, zavináč oddeľuje používateľské údaje od hostiteľa, otáznik začína dotaz, mriežka začína fragment, ampersand oddeľuje parametre dotazu a percento uvádza únik.

To vytvára jeden problém a jednu medzeru. Problém: hodnota, ktorá sama obsahuje jeden z týchto znakov — vyhľadávacie pole s „a&b“, názov súboru s lomkou, heslo s dvojbodkou — by inak zmenila štruktúru URL, ktorou putuje. Medzera: samotné percento, takže kodér môže jednoducho rozšíriť vlastnú abecedu. % sa zapíše ako %25 a dve hexadecimálne číslice za ním sú obyčajné nevyhradené znaky.

Prepracované príklady

Toto sú presné výstupy troch kodérov, ktoré táto stránka spúšťa, pre vstupy vybrané preto, lebo sa správajú navzájom odlišne. Stránka ich prepočíta priamo pred očami a jej samotest znova overí každý riadok oproti implementáciám platformy.

Tri metódy a kedy je každá správna

Krátka verzia, ktorá ušetrí väčšinu chýb: všetko, čo ide do jednej hodnoty parametra, prechádza cez encodeURIComponent (alebo cez serializátor formulára, ktorý robí to isté s inou bezpečnou množinou) a úplná už zložená URL prechádza cez encodeURI, ak vôbec potrebuje escapovanie. Siahnuť po nesprávnej z týchto dvoch je najčastejšia chyba pri percentovom kódovaní vo webovom kóde.

Znaky, ktoré môže URL niesť, úplne
Dve znamienka plus, dva významy

Medzera je jediný znak, ktorého kódovanie závisí od toho, kam text smeruje, a za to môže znamienko plus.

Pasca je v strede tej tabuľky. V údajoch formulára znamienko plus znamená medzeru, takže hodnota, ktorá skutočne obsahuje znamienko plus — telefónne číslo zapísané ako +44 20 7946 0958, aritmetický výraz, e-mailová adresa s plus značkou — musí putovať ako %2B. Ak putuje ako doslovné znamienko plus, príjemca ho prečíta ako medzeru a +44 dorazí ako „ 44“.

Dvakrát zakódované a ako ich spoznať

Dvojité kódovanie nastane, keď je reťazec už escapovaný a escapuje sa znova. Percento prvého úniku je znak ako každý iný, takže sa zmení na %25 a vrstva pod ním zostane viditeľná ako text.

Rozpoznanie je otázka počítania: reťazec sa dekóduje raz a pozrie sa na výsledok. Ak stále obsahuje úniky, ktoré vyzerajú zámerne — platné %XX alebo znamienko plus formulára tam, kde sa čaká medzera — je tam ďalšia vrstva. Ak obsahuje %25 nasledované dvoma hexadecimálnymi číslicami, ďalšia vrstva je určite únik.

Dve praktické poznámky. Po prvé, dekódovať dvakrát nie je neškodné: je to dobre známy spôsob, ako dosiahnuť, že bezpečnostný filter a kód za ním uvidia rozdielne reťazce, takže filter, ktorý beží pred druhým dekódovaním, filtruje nesprávny text. Po druhé, počet vrstiev tu je vlastnosťou reťazca, nie sľubom o zámere: oprávnená hodnota môže mať jednu vrstvu a pokazená dve.

Chyby, na ktoré je táto stránka navrhnutá
  • Hodnota zakódovaná cez encodeURI. Oddeľovače zostanú zachované, takže hodnota obsahujúca & alebo = sa na druhej strane rozdelí na viac parametrov. Pri vstupe a&b=c stojí za porovnanie dva stĺpce hore na tejto stránke: stĺpec komponentu escapuje oba znaky, stĺpec encodeURI ich ponechá.
  • Doslovné znamienko plus odoslané ako údaje formulára. Prijme sa ako medzera. Použije sa %2B.
  • Hodnota escapovaná dvakrát „pre istotu“. Nie je to bezpečnejšie. Príjemca dekóduje raz a dostane reťazec, ktorý stále obsahuje percentové úniky; je to rovnaká chyba ako pri nesprávnej znakovej sade, o jednu vrstvu nižšie.
  • Dekódovanie toho, čo nikdy nebolo zakódované. Doslovné percento v texte — 100% sure — nie je únik. V prísnom čítaní je to pokazený únik na pozícii, ktorú táto stránka hlási; vo voľnom čítaní prežije, preto je voľné čítanie tu predvolené, a nie naopak.
  • Predpoklad, že únikový znak musí byť veľkými písmenami. Dekódovanie berie %2f a %2F ako ten istý bajt a obe sú platné. Veľké písmená sú iba kanonický zápis, ktorý odporúča RFC 3986 a ktorý ostatné nástroje vytvárajú.
  • Predpoklad, že percentové kódovanie robí text bezpečným. Robí text jednoznačným v rámci URL. Nezastaví injekciu, nie je to šifrovanie a nie je to sanitizér: escapovanie musí byť posledným krokom pred zložením, pre kontext, do ktorého text ide.
Rýchle odpovede

„Je znamienko plus v URL medzera?“

Iba v údajoch formulára a iba v časti dotazu odoslania formulára. V ceste, vo fragmente a v dotaze obyčajného odkazu je znamienko plus doslovné znamienko plus. Preto má táto stránka prepínač pre to namiesto hádania.

„Prečo odkaz zobrazuje %25?“

Pretože niečo zakódovalo znak percenta. Buď doslovné percento prešlo kodérom — 100% sure sa zmení na 100%25%20sure — alebo reťazec, ktorý už obsahoval únik, bol zakódovaný znova. Reťazec sa dekóduje raz a pozrie sa na výsledok: ak stále obsahuje %XX, je tam ďalšia vrstva.

„Záleží na tom, či je lomka vo vnútri hodnoty dotazu %2F alebo /?“

Pre analyzátor URL nie: obe sa na server dostanú ako lomka a množina dotazu WHATWG lomku nechá tak. Pre interoperabilitu niekedy áno: veľa serverových frameworkov spúšťa vlastné dekódovanie nad surovým reťazcom dotazu a niektoré sa nezhodujú v znakoch, ktoré nikdy neboli escapované. Ak sa hodnota zostavuje ručne a nie serializátorom, je bezpečnejší zvyk vyhradené znaky escapovať explicitne.

„Prečo stĺpec formulára escapuje vlnovku, ktorú ostatné dva nechávajú na pokoji?“

Pretože bezpečná množina kodéra formulára je užšia: iba písmená, číslice a -_.*. Kodér formulára WHATWG escapuje ~ ! ' ( ), hoci RFC 3986 uvádza ~ ako nevyhradený. Obe podoby sa dekódujú na tú istú hodnotu; rozdiel je dôležitý iba pri porovnávaní reťazcov bajt po bajte.

„Môžu sa tie isté znaky objaviť nezakódované v adresnom riadku prehliadača?“

Áno, a to je adresný riadok, nie URL. Prehliadače zobrazujú čitateľnú podobu URL a pri odoslaní ju kódujú, takže 中文 v odkaze sa na drôte zmení na %E4%B8%AD%E6%96%87. Ak sa URL skopíruje z adresného riadka, podľa prehliadača sa môže dostať ktorákoľvek z oboch podôb.

„Každý únik tu vyzerá platne, ale znak, ktorý vyjde, nie je ten, ktorý som čakal. Prečo?“

Za frázou „dekódovalo sa to zle“ sa skrývajú dve rôzne chyby a táto stránka ich hlási odlišne. Prvou je pokazený únik: percento, za ktorým nenasledujú dve hexadecimálne číslice, napríklad koncové 100% alebo %zz. To je syntaktický problém; prísne čítanie ho odmietne a uvedie, kde sa nachádza, kým voľné čítanie ho ponechá ako doslovný text a vypíše ho. Druhou je únik, ktorého bajt je úplne platný, ale bajty nevytvárajú platný znak UTF-8, napríklad samotný %FF alebo trojbajtový znak skrátený na %E4%B8. To nie je syntaktický problém, takže obe čítania vrátia text, bajty, ktoré sa nedajú dekódovať, nahradia náhradným znakom U+FFFD („�“) a vypíšu varovanie, ktoré to hovorí. Práve to varovanie je užitočná časť: text, ktorý prichádza ako náhradné znaky, zvyčajne znamená, že odosielateľ použil inú znakovú sadu alebo že reťazec bol escapovaný o jednu vrstvu veľa. Percentové kódovanie pomenúva bajty a táto stránka ich, rovnako ako štandard URL, vždy číta ako UTF-8.

„Čo táto stránka nerobí?“

Nerozdeľuje URL na schému, hostiteľa, cestu a dotaz — na to slúži Analyzátor URL. Nekontroluje, či je bezpečné odkaz otvoriť, nič nekontaktuje a neodhaduje znakovú sadu bajtov za únikom: vždy ich číta ako UTF-8, ako to vyžaduje štandard URL.

„Aký záložný postup potrebuje dekódovanie a ako sa dá overiť, že je správny?“

Stlačí sa Samotest. Porovná kodéry tejto stránky s encodeURIComponent, encodeURI a URLSearchParams platformy pre každý tlačiteľný znak ASCII, znova spustí každý príklad z tabuliek vyššie, znova skontroluje zaznamenané reťazce vrstiev a počet kontrol uvedie tu.

Normy a rozsah

Percentové kódovanie je špecifikované v RFC 3986, oddiel 2.1; definícia vyhradených a nevyhradených znakov je v oddieloch 2.2 a 2.3 a pravidlo veľkých písmen v oddiele 6.2.2.1. Množiny, ktoré prehliadač naozaj používa pri zostavovaní URL, sú v štandarde WHATWG URL, ktorý ich rozdeľuje podľa kontextu: jedna množina pre fragment, jedna pre dotaz, jedna pre špeciálny dotaz, jedna pre cestu, jedna pre používateľské údaje a užšia množina pre jednotlivú zložku. Odoslanie formulára vrátane znamienka plus je v štandarde HTML pod application/x-www-form-urlencoded. Funkcie encodeURI a encodeURIComponent sú súčasťou samotného ECMAScriptu.

Táto stránka vypĺňa stĺpce cesty, dotazu a fragmentu vlastnými množinami pre každý kontext a vypisuje presný zoznam pre každý kontext vedľa výsledku. Tieto množiny sú odvodené z množín WHATWG a odlišujú sa od nich na dvoch zámerných miestach: mriežka sa escapuje v dotaze, pretože surová mriežka by začala fragment, a množina komponentu je pevne daná presne na znaky, ktoré escapuje encodeURIComponent. Tam, kde je funkcia platformy definíciou odpovede — encodeURIComponent, encodeURI a serializácia formulára — sa táto funkcia volá priamo, takže tieto stĺpce sú správanie prehliadača samotného a nie jeho znovuimplementácia.

Text stránky bol napísaný pre túto stránku. Každá hodnota v tabuľkách vyššie vzniká vlastným kódom stránky pri načítaní a bola overená oproti implementáciám platformy v testovacích nástrojoch tejto stránky; samotest toto porovnanie zopakuje priamo v prehliadači.