Saya memiliki aplikasi yang berhubungan dengan klien dari seluruh dunia, dan, tentu saja, saya ingin semuanya masuk ke basis data saya untuk disandikan UTF-8.
Masalah utama bagi saya adalah bahwa saya tidak tahu apa pengkodean sumber dari string apa pun yang akan terjadi - bisa dari kotak teks (menggunakan <form accept-charset="utf-8">
hanya berguna jika pengguna benar-benar mengirimkan formulir), atau bisa juga dari file teks yang diunggah, jadi saya benar-benar tidak memiliki kendali atas input.
Yang saya butuhkan adalah fungsi atau kelas yang memastikan barang-barang masuk ke database saya, sejauh mungkin, disandikan UTF-8. Saya sudah mencoba iconv(mb_detect_encoding($text), "UTF-8", $text);
tetapi ada masalah (jika inputnya adalah 'tunangan', ia mengembalikan 'tunangan'). Saya sudah mencoba banyak hal = /
Untuk unggahan file, saya menyukai gagasan meminta pengguna akhir untuk menentukan pengkodean yang mereka gunakan, dan menunjukkan kepada mereka pratinjau seperti apa bentuk outputnya, tetapi ini tidak membantu melawan peretas jahat (pada kenyataannya, itu bisa membuat hidup mereka sedikit lebih mudah).
Saya sudah membaca pertanyaan SO lainnya tentang masalah ini, tetapi semuanya tampaknya memiliki perbedaan yang halus seperti "Saya perlu menguraikan RSS feed" atau "Saya mengorek data dari situs web" (atau, memang, "Anda tidak bisa").
Tetapi pasti ada sesuatu yang paling tidak patut dicoba !
sumber
UTF-8//IGNORE
sebagai param 2 diiconv
?Jawaban:
Apa yang Anda minta sangat sulit. Jika memungkinkan, meminta pengguna untuk menentukan pengkodean adalah yang terbaik. Mencegah serangan seharusnya tidak semudah atau sesulit itu.
Namun, Anda dapat mencoba melakukan ini:
Menetapkannya dengan ketat mungkin membantu Anda mendapatkan hasil yang lebih baik.
sumber
mb_detect_encoding
kode sumber di distro php Anda (di suatu tempat di sini: ext / mbstring / libmbfl / mbfl / mbfl_ident.c). Fungsi ini sama sekali tidak berfungsi dengan baik. Untuk beberapa pengkodean bahkan "kembali benar", lol. Lainnya ada di fungsi Ctrl + c Ctrl + v. Itu karena Anda tidak dapat mendeteksi penyandian tanpa semacam kamus atau pendekatan statistik (seperti milik saya).mb_detect_encoding
menelusuri daftar pengkodean yang disediakan, dan menerima yang pertama yang tidak memiliki urutan byte yang tidak valid dalam string ... Untuk pengkodean yang tidak memiliki urutan byte yang tidak valid seperti ISO-8859-1, itu selalu benar . Tidak ada heuristik "pintar", dan hasil sangat bervariasi dengan daftar (dan urutan) pengkodean yang Anda berikan.mb_detect_order()
walaupun itu adalah nilai default untuk param ini, karena ia ingin mengatur deteksi pengkodean yang ketat menjadi true (the 3rd param) :)Di Rusia, kami memiliki 4 penyandian populer, jadi pertanyaan Anda sangat diminati di sini.
Hanya dengan kode simbol char Anda tidak dapat mendeteksi pengkodean, karena halaman kode berpotongan. Beberapa codepage dalam berbagai bahasa bahkan memiliki persimpangan penuh. Jadi, kita perlu pendekatan lain .
Satu-satunya cara untuk bekerja dengan penyandian yang tidak diketahui adalah bekerja dengan probabilitas. Jadi, kami tidak ingin menjawab pertanyaan "apa penyandian teks ini?", Kami mencoba memahami " apa yang paling mungkin penyandian teks ini? ".
Seorang pria di sini di blog teknologi Rusia populer menciptakan pendekatan ini:
Buat rentang probabilitas kode char di setiap penyandian yang ingin Anda dukung. Anda dapat membangunnya menggunakan beberapa teks besar dalam bahasa Anda (misalnya beberapa fiksi, gunakan Shakespeare untuk bahasa Inggris dan Tolstoy untuk bahasa Rusia, lol). Anda akan mendapatkan sesuatu seperti ini:
Lanjut. Anda mengambil teks dalam pengkodean yang tidak dikenal dan untuk setiap pengkodean dalam "kamus probabilitas" Anda mencari frekuensi setiap simbol dalam teks yang dikodekan tidak dikenal. Jumlah probabilitas simbol. Pengkodean dengan peringkat yang lebih besar kemungkinan adalah pemenangnya. Hasil yang lebih baik untuk teks yang lebih besar.
Jika Anda tertarik , saya dengan senang hati dapat membantu Anda dengan tugas ini. Kami dapat sangat meningkatkan akurasi dengan membangun daftar probabilitas dua-kode.
Btw. mb_detect_encoding pasti tidak berfungsi. Ya, sama sekali. Silakan, lihat kode sumber mb_detect_encoding di "ext / mbstring / libmbfl / mbfl / mbfl_ident.c".
sumber
Anda mungkin sudah mencobanya, tetapi mengapa tidak menggunakan fungsi mb_convert_encoding? Ini akan mencoba untuk mendeteksi secara otomatis kumpulan karakter dari teks yang disediakan atau Anda dapat memberikannya daftar.
Juga, saya mencoba menjalankan:
dan hasilnya sama untuk keduanya. Bagaimana Anda melihat bahwa teks Anda terpotong ke 'tunangan'? apakah itu di DB atau di browser?
sumber
iconv
. Saya mencoba melakukan cara mb_ * hampir murni. Apa yang kamu pikirkan?Tidak ada cara untuk mengidentifikasi charset dari string yang sepenuhnya akurat. Ada beberapa cara untuk mencoba menebak charset. Salah satu cara ini, dan mungkin / saat ini yang terbaik di PHP, adalah mb_detect_encoding (). Ini akan memindai string Anda dan mencari kemunculan hal-hal unik untuk rangkaian karakter tertentu. Tergantung pada string Anda, mungkin tidak ada kejadian yang dapat dibedakan.
Ambil ISO-8859-1 vs ISO-8859-15 ( http://en.wikipedia.org/wiki/ISO/IEC_8859-15#Changes_from_ISO-8859-1 )
Hanya ada beberapa karakter yang berbeda, dan untuk membuatnya lebih buruk, mereka diwakili oleh byte yang sama. Tidak ada cara untuk mendeteksi, diberi string tanpa mengetahui pengkodeannya, apakah byte 0xA4 seharusnya menandakan ¤ atau € di string Anda, jadi tidak ada cara untuk mengetahui itu charset yang tepat.
(Catatan: Anda dapat menambahkan faktor manusia, atau teknik pemindaian yang bahkan lebih maju (misalnya apa yang disarankan Oroboros102), untuk mencoba mencari tahu berdasarkan konteks sekitarnya, jika karakter harus ¤ atau €, meskipun ini seperti jembatan terlalu jauh)
Ada perbedaan yang lebih dapat dibedakan antara misalnya UTF-8 dan ISO-8859-1, jadi masih ada baiknya mencoba mencari tahu ketika Anda tidak yakin, meskipun Anda bisa dan tidak boleh mengandalkan itu benar.
Menarik dibaca: http://kore-nordmann.de/blog/php_charset_encoding_FAQ.html#how-do-i-determine-the-charset-encoding-of-a-string
Ada beberapa cara lain untuk memastikan charset yang benar. Mengenai formulir, cobalah untuk menegakkan UTF-8 sebanyak mungkin (periksa manusia salju untuk memastikan bahwa pengiriman Anda akan menjadi UTF-8 di setiap browser: http://intertwingly.net/blog/2010/07/29/Rails-and -Snowmen ) Itu sedang dilakukan, setidaknya Anda dapat yakin bahwa setiap teks yang dikirim melalui formulir Anda adalah utf_8. Mengenai file yang diunggah, coba jalankan perintah unix 'file -i' di atasnya melalui mis exec () (jika mungkin di server Anda) untuk membantu pendeteksian (menggunakan BOM dokumen.) Mengenai data pengikisan, Anda dapat membaca header HTTP, yang biasanya menentukan charset. Saat mem-parsing file XML, lihat apakah meta-data XML berisi definisi charset.
Alih-alih mencoba menebak charset secara otomatis, Anda harus terlebih dahulu mencoba memastikan charset tertentu sendiri, atau mencoba mengambil definisi dari sumber yang Anda dapatkan (jika berlaku) sebelum beralih ke deteksi.
sumber
Ada beberapa jawaban dan upaya yang sangat bagus untuk menjawab pertanyaan Anda di sini. Saya bukan master encoding, tapi saya mengerti keinginan Anda untuk memiliki setumpuk UTF-8 murni sampai ke database Anda. Saya telah menggunakan
utf8mb4
pengkodean MySQL untuk tabel, bidang, dan koneksi.Situasi saya berubah menjadi "Saya hanya ingin pembersih saya, validator, logika bisnis, dan menyiapkan pernyataan untuk berurusan dengan UTF-8 ketika data berasal dari formulir HTML, atau tautan pendaftaran email." Jadi, dengan cara sederhana saya, saya mulai dengan ide ini:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
throw new RuntimeException
UTF-8
, lanjutkan.Lain, jika itu
ISO-8859-1
atauASCII
Sebuah. Coba konversi ke UTF-8 (tunggu, belum selesai)
b. Mendeteksi penyandian nilai yang dikonversi
c. Jika pengkodean yang dilaporkan dan nilai yang dikonversi keduanya
UTF-8
, lanjutkan.d. Lain,
throw new RuntimeException
Dari kelas abstrak saya
Sanitizer
Orang bisa membuat argumen bahwa saya harus memisahkan masalah pengkodean dari
Sanitizer
kelas abstrak saya dan cukup menyuntikkanEncoder
objek ke turunan anak konkretSanitizer
. Namun, masalah utama dengan pendekatan saya adalah bahwa, tanpa lebih banyak pengetahuan, saya hanya menolak jenis penyandian yang tidak saya inginkan (dan saya mengandalkan fungsi PHP mb_ *). Tanpa studi lebih lanjut, saya tidak bisa tahu apakah itu menyakitkan sebagian populasi atau tidak (atau, jika saya kehilangan informasi penting). Jadi, saya perlu belajar lebih banyak. Saya menemukan artikel ini.Apa yang mutlak perlu diketahui oleh setiap programmer, tentang penyandian dan rangkaian karakter untuk bekerja dengan teks
Selain itu, apa yang terjadi ketika data terenkripsi ditambahkan ke tautan pendaftaran email saya (menggunakan
OpenSSL
ataumcrypt
)? Mungkinkah ini mengganggu decoding? Bagaimana dengan Windows-1252? Bagaimana dengan implikasi keamanan? Penggunaanutf8_decode()
danutf8_encode()
dalamSanitizer::isUTF8
meragukan.Orang-orang telah menunjukkan kekurangan dalam fungsi PHP mb_ *. Saya tidak pernah meluangkan waktu untuk menyelidiki
iconv
, tetapi jika berfungsi lebih baik daripada fungsi mb_ *, beri tahu saya.sumber
Saya tidak berpikir itu masalah. Aplikasi mengetahui sumber input. Jika itu dari formulir, gunakan pengkodean UTF-8 dalam kasus Anda. Itu bekerja. Cukup verifikasi data yang diberikan telah disandikan dengan benar (validasi). Perlu diingat bahwa tidak semua database mendukung UTF-8 dalam jangkauan penuhnya.
Jika itu file, Anda tidak akan menyimpannya UTF-8 yang disandikan ke dalam basis data tetapi dalam bentuk biner. Saat Anda meng-output file lagi, gunakan output biner juga, maka ini benar-benar transparan.
Ide Anda bagus agar pengguna dapat mengetahui enkode, baik ia dapat mengetahui setelah mengunduh file, karena itu biner.
Jadi saya harus mengakui bahwa saya tidak melihat masalah spesifik yang Anda ajukan dengan pertanyaan Anda. Tapi mungkin Anda bisa menambahkan beberapa detail apa masalah Anda.
sumber
Anda dapat menyiapkan serangkaian metrik untuk mencoba menebak penyandian mana yang sedang digunakan. Sekali lagi, tidak sempurna, tetapi bisa menangkap beberapa kesalahan dari mb_detect_encoding ().
sumber
mb_detect_encoding()
soal rindu, apakah menurut Anda jawaban saya memiliki peluang bola salju di musim panas di Sahara?Jika Anda bersedia "membawa ini ke konsol", saya sarankan
enca
. Berbeda dengan yang agak sederhanamb_detect_encoding
, ini menggunakan "campuran parsing, analisis statistik, menebak dan ilmu hitam untuk menentukan pengkodean mereka" (lol - lihat halaman manual ). Namun, Anda biasanya harus melewati bahasa file input jika Anda ingin mendeteksi pengkodean khusus negara tersebut. (Namun,mb_detect_encoding
pada dasarnya memiliki persyaratan yang sama, karena pengkodean harus muncul "di tempat yang tepat" dalam daftar penyandian yang disahkan agar dapat dideteksi sama sekali.)enca
juga muncul di sini: Cara menemukan penyandian file di Unix melalui skripsumber
Tampaknya pertanyaan Anda cukup dijawab, tetapi saya memiliki pendekatan yang dapat menyederhanakan kasus Anda:
Saya memiliki masalah serupa yang mencoba mengembalikan data string dari mysql, bahkan mengkonfigurasi database dan php untuk mengembalikan string yang diformat ke utf-8. Satu-satunya cara saya mendapatkan kesalahan sebenarnya mengembalikan mereka dari database.
Akhirnya, berlayar melalui web saya menemukan cara yang sangat mudah untuk menghadapinya:
Memberikan bahwa Anda dapat menyimpan semua jenis data string di mysql Anda dalam berbagai format dan susunan, yang hanya perlu Anda lakukan adalah, tepat di file koneksi php Anda, atur susunan ke utf-8, seperti ini:
Wich berarti pertama-tama Anda menyimpan data dalam format atau pemeriksaan apa pun dan Anda mengonversinya hanya dengan kembali ke file php Anda.
Semoga bermanfaat!
sumber
Jika teks diambil dari database mysql Anda dapat mencoba menambahkan ini setelah koneksi BD.
mysqli_set_charset ($ con, "utf8");
https://www.php.net/manual/en/mysqli.set-charset.php
sumber
Opsi default CURL:
Saya mencoba sesuatu seperti ini. Itu membantu saya. Jika ditemukan di info meta charset, saya mengonversi, jika tidak melakukan apa-apa.
sumber