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 sebuah tag. Bahasa itu memecahkannya dengan entitas: urutan escape pendek yang mewakili sebuah 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 browser Anda. Itu lebih penting di sini daripada bagi kebanyakan alat, karena teks yang orang tempel ke sebuah pendekode entitas biasanya adalah halaman yang di-scrape, sebuah surel pelanggan, atau kolom basis data yang seseorang coba pahami.

Lima karakter yang penting

Ribuan entitas ada, 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 sendiri dibaca ulang sebagai sebuah entitas.
  • Tanda kurang-dari menjadi < — karakter yang bisa memulai sebuah 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 sebuah 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 dari himpunan HTML 4 saat mendekode — huruf Latin-1, alfabet Yunani, tanda panah, simbol matematis, dan tanda baca tipografis, yang di antaranya mencakup pada dasarnya semua yang muncul dalam teks nyata. HTML 5 mendefinisikan sekitar 2200 lebih, hampir semuanya simbol matematis yang obskur; membawa tabel itu akan menambah puluhan kilobita ke setiap pemuatan halaman sebagai ganti nama yang hampir tak pernah dipakai dokumen. Sebuah nama di luar himpunan dilaporkan ketimbang dibuang, jadi biayanya sebuah 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 sebuah dokumen UTF-8.

Escape bukan satu aturan melainkan empat

Tergoda 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 sebuah spasi dalam nilai mengakhiri atribut dan escape-nya tak memberi Anda apa pun.
  • Di dalam sebuah blok script. Escape string JavaScript berlaku, bukan entitas — browser tak mendekode entitas di sana, jadi sebuah kutip ter-escape tiba sebagai karakter harfiah ".
  • Atribut URL seperti href dan src. Escape entitas tak menghentikan sebuah URL javascript:, karena bahayanya ada di skema, bukan di karakter mana pun yang akan diganti sebuah entitas.

Aturan praktisnya: escape di titik saat teks disisipkan ke dalam sebuah 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 sebuah 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 dalam kasus mana Anda berada. Jika keluarannya masih mengandung entitas, ada lebih dari satu lapisan. Perbaikannya hampir tak pernah membuang entitas saat tampilan — melainkan menemukan dan membuang langkah escape ganda, karena bug yang sama diam-diam merusak data yang tersimpan.

Non-ASCII, dan opsi untuknya

Sebuah 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 menjaga sumbernya terbaca dan berkasnya lebih kecil. Itu default di sini.

Opsi itu ada karena beberapa tujuan masih bersikeras ASCII polos: templat surel lama, sistem yang merusak bita di atas 127, atau kolom basis data yang pengodeannya tak ada yang bersedia mengubah. Menyalakannya menulis setiap karakter demikian sebagai sebuah rujukan desimal — é menjadi é, א menjadi א.

Emoji layak dicatat. Sebuah 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 format secara khusus mensyaratkan sebuah emoji dipecah menjadi dua escape \u. Karakter yang sama, dua jawaban yang benar, karena kedua format mendefinisikan escape atas unit yang berbeda.

Ketika sebuah rujukan tak bisa didekode

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

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

Sebuah 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 sebuah dokumen ditulis dalam Windows-1252, tempat angka yang sama adalah kutip pintar, tanda pisah, dan tanda euro. Browser 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 sebuah 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 sebuah entitas XML yang HTML 4 tak pernah mendefinisikannya. Pengurai yang mendahului HTML 5 membiarkannya sebagai teks harfiah, jadi sebuah apostrof yang Anda kira ter-escape tidak. Bentuk numerik bekerja di setiap pengurai, itulah sebabnya ia default yang aman.
Halaman saya menampilkan & alih-alih sebuah ampersand. Apa yang terjadi?
Teksnya di-escape dua kali. Dekode di sini: satu lintasan mengubah & menjadi &, memastikan 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 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 sebuah karakter kontrol tak terlihat, bukan tanda kutip yang Anda lihat. Dokumen yang memakainya ditulis dalam Windows-1252, tempat 147 adalah sebuah kutip pintar — browser membacanya begitu dan begitu pula alat ini. Peringatan memberi tahu Anda bahwa sebuah penggantian terjadi, jadi Anda bisa memperbaiki pengodean sumber jika itu milik Anda untuk diperbaiki.
Apakah teks saya dikirim ke mana pun?
Tidak. Pengodean dan pendekodean keduanya berjalan sepenuhnya di browser Anda; tidak ada yang Anda tempel meninggalkan perangkat Anda.