Có một số câu trả lời thực sự tốt và cố gắng trả lời câu hỏi của bạn ở đây. Tôi không phải là bậc thầy về mã hóa, nhưng tôi hiểu mong muốn của bạn là có một ngăn xếp UTF-8 thuần túy cho đến cơ sở dữ liệu của bạn. Tôi đã sử dụng utf8mb4
mã hóa của MySQL cho các bảng, trường và kết nối.
Tình huống của tôi trở nên sôi nổi "Tôi chỉ muốn các nhà vệ sinh, trình xác nhận, logic kinh doanh và các tuyên bố đã chuẩn bị của mình để đối phó với UTF-8 khi dữ liệu đến từ các biểu mẫu HTML hoặc liên kết đăng ký email." Vì vậy, theo cách đơn giản của tôi, tôi bắt đầu với ý tưởng này:
- Cố gắng phát hiện mã hóa:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- Nếu mã hóa không thể được phát hiện,
throw new RuntimeException
- Nếu đầu vào là
UTF-8
, tiếp tục.
Khác, nếu nó là ISO-8859-1
hoặcASCII
a. Cố gắng chuyển đổi sang UTF-8 (chờ, chưa kết thúc)
b. Phát hiện mã hóa của giá trị chuyển đổi
c. Nếu mã hóa được báo cáo và giá trị chuyển đổi là cả hai UTF-8
, hãy tiếp tục.
d. Khác,throw new RuntimeException
Từ lớp trừu tượng của tôi Sanitizer
private function isUTF8($encoding, $value)
{
return (($encoding === 'UTF-8') && (utf8_encode(utf8_decode($value)) === $value));
}
private function utf8tify(&$value)
{
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
mb_internal_encoding('UTF-8');
mb_substitute_character(0xfffd); //REPLACEMENT CHARACTER
mb_detect_order($encodings);
$stringEncoding = mb_detect_encoding($value, $encodings, true);
if (!$stringEncoding) {
$value = null;
throw new \RuntimeException("Unable to identify character encoding in sanitizer.");
}
if ($this->isUTF8($stringEncoding, $value)) {
return;
} else {
$value = mb_convert_encoding($value, 'UTF-8', $stringEncoding);
$stringEncoding = mb_detect_encoding($value, $encodings, true);
if ($this->isUTF8($stringEncoding, $value)) {
return;
} else {
$value = null;
throw new \RuntimeException("Unable to convert character encoding from ISO-8859-1, or ASCII, to UTF-8 in Sanitizer.");
}
}
return;
}
Người ta có thể đưa ra một lập luận rằng tôi nên tách các mối quan tâm mã hóa khỏi Sanitizer
lớp trừu tượng của mình và chỉ cần đưa một Encoder
đối tượng vào một thể hiện con cụ thể của Sanitizer
. Tuy nhiên, vấn đề chính với cách tiếp cận của tôi là, không có thêm kiến thức, tôi chỉ đơn giản từ chối các loại mã hóa mà tôi không muốn (và tôi đang dựa vào các hàm mb_ * của PHP). Nếu không nghiên cứu thêm, tôi không thể biết liệu điều đó có làm tổn thương một số quần thể hay không (hoặc, nếu tôi bị mất thông tin quan trọng). Vì vậy, tôi cần tìm hiểu thêm. Tôi tìm thấy bài viết này.
Điều mà mọi lập trình viên hoàn toàn, tích cực cần biết về mã hóa và bộ ký tự để làm việc với văn bản
Hơn nữa, điều gì xảy ra khi dữ liệu được mã hóa được thêm vào liên kết đăng ký email của tôi (sử dụng OpenSSL
hoặc mcrypt
)? Điều này có thể can thiệp vào giải mã? Còn Windows-1252 thì sao? Điều gì về ý nghĩa bảo mật? Việc sử dụng utf8_decode()
và utf8_encode()
trong Sanitizer::isUTF8
là đáng ngờ.
Mọi người đã chỉ ra các tính năng ngắn trong các hàm mb_ * của PHP. Tôi không bao giờ mất thời gian để điều tra iconv
, nhưng nếu nó hoạt động tốt hơn các hàm mb_ *, hãy cho tôi biết.