Rốt cuộc những dấu bằng (=) này là gì?
(lars.ingebrigtsen.no)- Gần đây, các trích dẫn từ email cũ lan truyền trên Twitter đã làm dấy lên thắc mắc về việc vì sao lại xuất hiện dấu bằng (=) ở cuối câu
- Ký hiệu này xuất hiện do quá trình mã hóa ‘quoted-printable’, được dùng để đánh dấu rằng dòng vẫn còn tiếp tục khi các dòng dài bị buộc phải tách ra
- Khi truyền email, CRLF (carriage return + line feed) được dùng làm ký tự xuống dòng; nếu thuật toán giải mã hoạt động sai khi chuyển nó sang NL của Unix, dấu bằng có thể bị giữ lại hoặc làm mất ký tự
- Ngoài việc dùng cho xuống dòng, dấu bằng còn được dùng để biểu diễn ký tự không phải ASCII (ví dụ: =C2=A0); bộ giải mã lỗi có thể thay thế chúng một cách đơn giản và gây ra sai sót
- Nguyên nhân của vấn đề là logic giải mã có lỗi và xử lý chuyển đổi không phù hợp, cho thấy người đã xử lý email đó thiếu vững vàng về mặt kỹ thuật
Bản chất của dấu bằng (=) trong các trích dẫn email
-
Trong vài ngày gần đây, nhiều trích dẫn từ email cũ được chia sẻ trên Twitter, khiến hiện tượng dấu bằng ở cuối câu trở nên dễ nhận thấy
- Tác giả phản bác những ý kiến cho rằng đây là mã hoặc lỗi OCR (nhận dạng ký tự quang học)
- Thực tế, đây là lỗi xử lý mã hóa phát sinh trong quá trình chuyển đổi email sang dạng dễ đọc hơn
-
Trước đây email chỉ là văn bản thuần, nhưng để xử lý các dòng dài hoặc ký tự đặc biệt, mã hóa ‘quoted-printable’ đã được đưa vào sử dụng
- Khi tách các dòng dài, người ta thêm dấu bằng (=) ở cuối dòng để biểu thị rằng “dòng này vẫn còn tiếp tục”
- Lúc này, sau dấu bằng sẽ là CRLF (carriage return + line feed)
Lỗi mã hóa xuống dòng và giải mã
-
Máy chủ email dùng CRLF làm chuẩn xuống dòng, còn hệ thống Unix chỉ dùng NL
- Trong quá trình chuyển đổi, bị mất một byte; nếu bộ giải mã xử lý sai, dấu bằng có thể bị giữ lại hoặc ký tự bị rơi mất
- Ví dụ, nếu “non- =CRLF cloven” được xử lý sai thì có thể thành “non- loven”, làm biến mất chữ ‘c’
-
Một số triển khai xử lý bằng cách xóa hai ký tự khi gặp dấu bằng ở cuối dòng
- Thuật toán này hoạt động sai với tệp theo định dạng Unix, khiến dấu bằng vẫn bị giữ nguyên
Một công dụng khác của dấu bằng: mã hóa ký tự không phải ASCII
-
Dấu bằng còn được dùng cho mã hóa ký tự không phải ASCII, không chỉ cho xuống dòng
- Ví dụ: “=C2=A0” có nghĩa là non-breaking space (khoảng trắng không ngắt dòng)
- Nó thường xuất hiện khi biểu diễn thụt lề hoặc ký tự đặc biệt trong thân email
-
Tác giả cho rằng một số bộ chuyển đổi chỉ search-replace đơn giản với các chuỗi như =C2, =A0 mà không dùng bộ giải mã chuẩn
Bối cảnh kỹ thuật và tiêu chuẩn
-
Chuẩn RFC 2045 định nghĩa mã hóa quoted-printable là cơ chế transport
- Sau khi nhận, nó phải được giải mã và lưu dưới dạng văn bản sạch
- Tuy nhiên, trong nhiều triển khai thực tế, bước này bị bỏ qua nên lỗi xử lý xuống dòng xảy ra thường xuyên
-
Trong ví dụ mã,
(quoted-printable-decode-string "he=\nllo")được khôi phục đúng thành"hello"- Đó là vì thuật toán được tái sử dụng từ ngữ cảnh máy chủ SMTP, nơi giả định có CRLF
- Nó hoạt động bình thường trên tệp kiểu Windows nhưng thất bại trên hệ Unix
Kết luận
- Dấu bằng trong các trích dẫn email là tàn dư của mã hóa quoted-printable, và là kết quả của việc kết hợp giữa
lỗi xử lý xuống dòng và lỗi giải mã ký tự không phải ASCII - Căn nguyên của vấn đề là việc triển khai bộ giải mã thiếu chính xác và sai sót trong chuyển đổi mã hóa
- Tác giả tóm lược đây là “một vấn đề kỹ thuật, đồng thời là kết quả của cách xử lý sai”,
đồng thời nhấn mạnh sự cần thiết phải tuân thủ chặt chẽ các tiêu chuẩn chi tiết trong quá trình chuyển đổi email
1 bình luận
Ý kiến trên Hacker News
Nhân vật chính của bài viết này là Lars Ingebrigtsen, người đã viết tài liệu hướng dẫn cho Gnus, gói trình đọc email/Usenet của Emacs
Tài liệu của ông vừa dí dỏm vừa hữu ích, và ông hiểu về việc phân tích email sâu hơn rất nhiều so với đa số mọi người
Có thể xem tài liệu tại đây, và một phiên bản khác ở liên kết này
Tôi còn nhớ thời ông lần đầu tạo ra Gnus ở Đại học Oslo (UiO)
Ông là một ngôi sao lập trình viên nho nhỏ trong giới sinh viên khoa tin học của chúng tôi, và mọi người đều dùng Emacs cùng Gnus
Vụ việc này là ví dụ điển hình của kiểu người “biết quá nhiều đến mức nguy hiểm”
Ai cũng biết email không phải chỉ là văn bản thuần túy, nhưng không phải ai cũng biết không thể xử lý giải mã quoted-printable bằng phép thay thế đơn giản
Nó cùng loại với lỗi tự parse HTML bằng regex: lúc đầu có vẻ chạy được, nhưng rồi về sau lại dẫn tới cảnh hồ sơ chứng cứ trước quốc hội đầy các ký hiệu ‘=’
Có câu hỏi rằng “tại sao máy chủ mail lại ghét các dòng quá dài”
Máy chủ phải parse header nên không thể chỉ coi nó như một khối nhị phân đơn giản
IMAP yêu cầu máy chủ phải parse hoàn chỉnh, còn POP3 vốn dành cho một thiết bị duy nhất nên ngày nay không còn phù hợp
RFC 821 giới hạn độ dài dòng tối đa 1000 byte, và để tương thích thì việc ngắt ở dưới 80 ký tự là rất phổ biến
Vì vậy mã hóa Base64 cũng chèn ngắt dòng sau mỗi 76 ký tự
Ví dụ PDP-11 có khoảng 512KB, VAX-11 khoảng 2MB, và lập trình viên khi đó tính toán bộ nhớ đến từng byte
HELO,MAIL FROM,RCPT TO,DATAv.v.Có thể xem tài liệu liên quan trên tài liệu chính thức của IBM và Wikipedia
Ban đầu tôi tưởng bài này sẽ nói về ý nghĩa của các toán tử như
= == === .=. <== ==> <<== ==>> (==) => =~=Cá nhân tôi từng tự viết phần mềm lưu trữ email
Phần khó nhất là xử lý các trường hợp biên trong những file .eml tích lũy suốt hơn 20 năm
Ý tưởng thì đơn giản nhưng email lại phức tạp đến ngạc nhiên
Việc kiểm tra tính hợp lệ của địa chỉ email trên thực tế gần như bất khả thi
Trong vài năm có một nhóm nhỏ người dùng, nhưng xử lý MIME là nỗi đau lớn nhất
Điều tôi thấy thú vị không phải bản thân dấu ‘=’, mà là hiện tượng các ký tự xung quanh nó biến mất
Nó giống như lỗi off-by-one: thay vì xóa dấu ‘=’ thì một phần văn bản thật lại bị mất
Có lẽ việc chuyển đổi CRLF/LF có liên quan
Có người thắc mắc vì sao vấn đề này lại xuất hiện ngay bây giờ
Mấy ngày gần đây người ta liên tục đăng các email cũ lên Twitter, nên tự hỏi nguyên nhân là gì
Một số người nêu khả năng nguyên nhân không phải Gmail mà là quá trình chuyển đổi ở máy chủ trung gian
Ngoài việc đổi CRLF→LF, nếu áp dụng quoted-printable hai lần thì hiện tượng còn sót lại dấu ‘=’ cũng có thể xuất hiện, nên có thể đã có hai máy chủ mail tham gia
Trên thực tế thường là thực tập sinh không chuyên gom dữ liệu bằng công cụ đơn giản, qua nhiều lần chuyển đổi khiến định dạng bị hỏng
Bản gốc thì đã bị xóa, và thứ còn lại chỉ là dữ liệu mảnh vỡ chỉ còn hình dạng bên ngoài
Bài trên archive.today cũng cho thấy cùng hiện tượng quoted-printable bị vỡ
Các liên kết liên quan là pastes.io/correspond và chuỗi HN
Có người nói rằng khi xem email tải về từ Outlook, sẽ rất tiện nếu có một trình xem .eml tự động giải mã quoted-printable