Pengode / pendekode entitas HTML

Escape teks agar aman di dalam HTML, atau dekode entitas bernama dan numerik kembali ke karakter yang diwakilinya.

Teks
Terkodekan

Keluaran akan muncul di sini

Apa yang dilakukan alat ini

HTML tak punya cara membedakan tanda kurang-dari yang Anda maksudkan sebagai teks dari yang membuka tag. Bahasa itu memecahkannya dengan entitas: urutan escape pendek yang mewakili karakter tanpa dibaca sebagai markup. Alat ini mengonversi di kedua arah — teks polos menjadi bentuk ter-escape-nya, dan HTML ter-escape kembali menjadi karakter yang diwakilinya.

Kedua arah berjalan sepenuhnya di peramban Anda. Itu lebih penting di sini daripada bagi kebanyakan alat, karena teks yang orang tempel ke pendekode entitas biasanya adalah halaman yang di-scrape, surel pelanggan, atau kolom basis data yang seseorang coba pahami.

Lima karakter yang penting

Ada ribuan entitas, tetapi hanya segelintir yang dibutuhkan untuk membuat teks aman. Pengodean di sini mengganti persis lima karakter dan membiarkan yang lain terbaca:

  • Ampersand menjadi & — yang ini dulu, atau setiap penggantian lain akan ikut dibaca ulang sebagai entitas.
  • Tanda kurang-dari menjadi < — karakter yang bisa memulai tag.
  • Tanda lebih-dari menjadi > — kurang berbahaya sendirian, di-escape demi kesimetrisan dan untuk bertahan dari pengurai yang ceroboh.
  • Kutip ganda menjadi " — dibutuhkan di dalam nilai atribut yang ditulis dengan kutip ganda.
  • Apostrof menjadi ' — dibutuhkan di dalam nilai atribut yang ditulis dengan kutip tunggal.

Yang terakhir itu sengaja ditulis numerik. Ada nama untuknya, ', tetapi ia datang dari XML dan HTML 4 tak pernah mendefinisikannya, jadi pengurai lama meneruskannya sebagai teks harfiah dan escape-nya diam-diam gagal. Bentuk numerik selalu bekerja di mana-mana, itulah sebabnya pustaka escape yang serius memancarkannya.

Bernama, desimal, dan heksadesimal

Karakter apa pun bisa ditulis tiga cara, dan pendekodean menerima semuanya. Tanda pisah em adalah contoh yang baik:

named     —      the readable form, but only for characters that have a name
decimal   —      the code point in base 10
hex       —     the same code point in base 16, the notation Unicode charts use

Alat ini mengenali 255 nama saat mendekode: semua nama yang didefinisikan HTML 4, ditambah tiga yang tidak didefinisikannya — ', yang berasal dari XML, serta Zcaron dan zcaron, dua karakter Windows-1252 yang dibiarkan HTML 4 tanpa nama. Bersama-sama semuanya mencakup huruf Latin-1, alfabet Yunani, tanda panah, simbol matematis, dan tanda baca tipografis, pada dasarnya semua yang muncul dalam teks nyata. HTML 5 mendefinisikan sekitar 2100 nama seluruhnya, dan sisanya hampir semuanya simbol matematis yang jarang terpakai; membawa tabel itu akan menambah puluhan kilobita ke setiap pemuatan halaman sebagai ganti nama yang hampir tak pernah dipakai dokumen. Nama di luar himpunan dilaporkan ketimbang dibuang, jadi biayanya peringatan, tak pernah jawaban yang salah.

Pengodean berjalan ke arah lain dan tetap sengaja polos: nama untuk lima karakter di atas, angka desimal untuk yang lain. Tak ada yang diubah menjadi … atau ’ ketika karakter itu sendiri sangat valid dalam dokumen UTF-8.

Escape bukan satu aturan melainkan empat

Ada godaan untuk memperlakukan escape entitas sebagai jawaban atas injeksi, dan di dalam konten elemen ia benar-benar begitu. Tetapi HTML sesungguhnya adalah empat bahasa yang bersarang satu di dalam yang lain, dan masing-masing punya aturannya sendiri. Escape entitas benar di dua tempat pertama ini dan tak berguna di sisanya:

  • Konten elemen — teks di antara tag. Escape entitas persis tepat.
  • Nilai atribut berkutip. Escape entitas tepat, asalkan atributnya benar-benar dikutip; tanpa kutip spasi dalam nilai mengakhiri atribut dan escape-nya tak memberi Anda apa pun.
  • Di dalam blok script. Escape string JavaScript berlaku, bukan entitas — peramban tak mendekode entitas di sana, jadi kutip ter-escape tiba sebagai karakter harfiah ".
  • Atribut URL seperti href dan src. Escape entitas tak menghentikan URL javascript:, karena bahayanya ada di skema, bukan di karakter mana pun yang akan diganti entitas.

Aturan praktisnya: escape di titik saat teks disisipkan ke dalam dokumen, memakai aturan konteks persis tempat ia mendarat — bukan sekali, lebih awal, dengan harapan ia akan bertahan di mana-mana kemudian.

Mengapa Anda kadang melihat &

Ini adalah alasan tunggal paling umum untuk meraih pendekode entitas. Teks di-escape, lalu di-escape lagi — biasanya sekali oleh kode aplikasi dan sekali oleh mesin templat atau kerangka kerja yang sudah meng-escape keluarannya:

original     Fish & Chips
escaped      Fish & Chips        renders as: Fish & Chips
escaped x2   Fish & Chips    renders as: Fish & Chips

Pendekodean membuang persis satu lapisan, jadi menjalankannya sekali memberi tahu Anda kasus mana yang Anda hadapi. Jika keluarannya masih mengandung entitas, ada lebih dari satu lapisan. Perbaikannya hampir tak pernah membuang entitas saat ditampilkan — melainkan menemukan dan membuang langkah escape ganda, karena bug yang sama diam-diam merusak data yang tersimpan.

Non-ASCII, dan opsi untuknya

Halaman yang disajikan sebagai UTF-8 tak butuh entitas untuk huruf beraksen, aksara Ibrani, Arab, Tionghoa, atau emoji. Karakter itu valid apa adanya, dan membiarkannya terbaca membuat sumbernya tetap mudah dibaca dan berkasnya lebih kecil. Itu default di sini.

Opsi itu ada karena beberapa tujuan masih bersikeras pada ASCII polos: templat surel lama, sistem yang merusak bita di atas 127, atau kolom basis data yang pengodeannya tak seorang pun bersedia mengubah. Menyalakannya menulis karakter demikian sebagai rujukan desimal di mana pun rujukan itu terbaca kembali sebagai karakter yang sama persis — é menjadi é, א menjadi א. Di tempat tak ada rujukan yang bisa melakukannya dengan andal, karakter dibiarkan persis apa adanya alih-alih diganti rujukan yang bermakna lain: angka 128 sampai 159, yang dibaca HTML sebagai karakter Windows-1252 yang dijelaskan di bawah atau ditandainya sebagai galat, tak pernah sebagai karakter kontrol yang dinamainya, serta separuh tunggal dari pasangan yang tersisa dari teks yang sudah rusak saat tiba, yang tak dinamai rujukan mana pun.

Emoji layak dicatat. Emoji ditulis sebagai satu rujukan untuk seluruh titik kodenya, misalnya 🙂, tak pernah sebagai dua paruh. Jika Anda pernah memakai alat escape JSON, ini kebalikan dari yang terjadi di sana, tempat formatnya secara khusus mensyaratkan emoji dipecah menjadi dua escape \u. Karakter yang sama, dua jawaban yang benar, karena kedua format mendefinisikan escape atas unit yang berbeda.

Ketika rujukan tak bisa didekode

Pendekodean di sini tak pernah gagal dan tak pernah menghapus apa pun. Rujukan yang tak bisa didekode dibiarkan persis seperti ditemukan dan didaftar di atas keluaran dengan baris dan kolomnya. Tiga hal dilaporkan:

  • Nama tak dikenal, seperti &nbps; — hampir selalu salah ketik untuk  . Ini adalah peringatan yang layak ditindaklanjuti: ia berarti spasi hilang dari konten Anda dan tak ada yang menyadarinya.
  • Angka yang bukan karakter, seperti � atau nilai di atas rentang Unicode. Tak ada karakter yang bisa menjadi hasil dekodenya, jadi ia tetap teks.
  • Angka antara 128 dan 159. Lihat di bawah.

Ampersand tunggal tak dilaporkan sama sekali. Dalam HTML, R&D dan Q&A adalah teks biasa, dan memperlakukan setiap ampersand tersasar sebagai galat akan mengubur peringatan yang penting di bawah derau dari prosa.

Rentang 128-sampai-159 adalah keganjilan sejati. Angka itu menamai karakter kontrol tak terlihat yang tak pernah dimaksudkan orang untuk ditulis; mereka muncul karena dokumen ditulis dalam Windows-1252, tempat angka yang sama adalah kutip pintar, tanda pisah, dan tanda euro. Peramban diam-diam membacanya sebagai Windows-1252 persis karena alasan itu, dan alat ini menyamai perilaku itu sehingga hasilnya sama dengan yang akan benar-benar ditampilkan halaman — tetapi ia mengatakannya dalam peringatan, karena penggantian senyap yang tak Anda minta lebih buruk daripada yang berisik.

Pertanyaan yang sering diajukan

Apakah meng-escape lima karakter ini cukup untuk menghentikan XSS?
Dalam konten elemen dan nilai atribut berkutip, ya — persis untuk itulah ia. Ia tidak cukup di dalam blok script atau style, dalam atribut tanpa kutip, atau dalam atribut URL seperti href, yang masing-masing butuh aturan escape-nya sendiri. Escape adalah sifat dari tempat teks mendarat, bukan dari teksnya.
Mengapa apostrof dikodekan sebagai ' dan bukan '?
Karena ' adalah entitas XML yang tak pernah didefinisikan HTML 4. Pengurai yang mendahului HTML 5 membiarkannya sebagai teks harfiah, jadi apostrof yang Anda kira ter-escape tidak. Bentuk numerik bekerja di setiap pengurai, itulah sebabnya ia default yang aman.
Halaman saya menampilkan & alih-alih ampersand. Apa yang terjadi?
Teksnya di-escape dua kali. Dekode di sini: satu lintasan mengubah & menjadi &, menegaskan adanya lapisan tambahan. Perbaiki salurannya ketimbang teksnya — biasanya kode Anda meng-escape keluaran yang sudah di-escape mesin templat.
Apakah saya perlu mengodekan aksara Ibrani, Arab, atau emoji?
Tidak untuk halaman modern yang disajikan sebagai UTF-8; mereka valid apa adanya. Nyalakan opsi non-ASCII hanya ketika sesuatu di hilir bersikeras pada ASCII polos, seperti templat surel lama. Tiap emoji lalu ditulis sebagai satu rujukan numerik.
Mengapa alat memperingatkan tentang “ padahal ia mendekodenya baik-baik?
Karena 147 menamai karakter kontrol tak terlihat, bukan tanda kutip yang Anda lihat. Dokumen yang memakainya ditulis dalam Windows-1252, tempat 147 adalah kutip pintar — peramban membacanya begitu dan begitu pula alat ini. Peringatan memberi tahu Anda bahwa penggantian terjadi, jadi Anda bisa memperbaiki pengodean sumber jika itu milik Anda untuk diperbaiki.
Apakah teks saya dikirim ke server?
Tidak. Pengodean dan pendekodean keduanya berjalan sepenuhnya di peramban Anda; tidak ada yang Anda tempel meninggalkan perangkat Anda.

Alat terkait