Post messages in quoted-printable instead of base64, just like WebCit Classic does...
[citadel] / webcit-ng / static / js / view_forum.js
index c669a0b..93772de 100644 (file)
@@ -270,21 +270,14 @@ function save_message(div_name, reply_to_msgnum) {
 
        url = "/ctdl/r/" + escapeHTMLURI(current_room) + "/dummy_name_for_new_message";
        boundary = randomString(20);
-
-       // This converts the message to base64, then splits it into 76-character chunks
-       encoded_msg_lines =
-               btoa("<html><body>" + document.getElementById("ctdl-editor-body").innerHTML + "</body></html>")
-               .match(/.{1,76}/g);
-
        body_text =
                "--" + boundary + "\r\n"
                + "Content-type: text/html\r\n"
-               + "Content-transfer-encoding: base64\r\n"
-               + "\r\n";
-       for (var i=0; i<encoded_msg_lines.length; ++i) {
-               body_text += encoded_msg_lines[i] + "\r\n";
-       }
-       body_text += "\r\n"
+               + "Content-transfer-encoding: quoted-printable\r\n"
+               + "\r\n"
+               + quoted_printable_encode(
+                       "<html><body>" + document.getElementById("ctdl-editor-body").innerHTML + "</body></html>"
+               ) + "\r\n"
                + "--" + boundary + "--\r\n"
        ;
 
@@ -309,3 +302,40 @@ function save_message(div_name, reply_to_msgnum) {
        };
        request.send(body_text);
 }
+
+
+// Function to encode data in quoted-printable format
+//  discuss at: https://locutus.io/php/quoted_printable_encode/
+// original by: Theriault (https://github.com/Theriault)
+// improved by: Brett Zamir (https://brett-zamir.me)
+// improved by: Theriault (https://github.com/Theriault)
+function quoted_printable_encode (str) { // eslint-disable-line camelcase
+       const hexChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
+       const RFC2045Encode1IN = / \r\n|\r\n|[^!-<>-~ ]/gm
+       const RFC2045Encode1OUT = function (sMatch) {
+               // Encode space before CRLF sequence to prevent spaces from being stripped
+               // Keep hard line breaks intact; CRLF sequences
+               if (sMatch.length > 1) {
+                       return sMatch.replace(' ', '=20')
+               }
+               // Encode matching character
+               const chr = sMatch.charCodeAt(0)
+               return '=' + hexChars[((chr >>> 4) & 15)] + hexChars[(chr & 15)]
+       }
+       // Split lines to 75 characters; the reason it's 75 and not 76 is because softline breaks are
+       // preceeded by an equal sign; which would be the 76th character. However, if the last line/string
+       // was exactly 76 characters, then a softline would not be needed. PHP currently softbreaks
+       // anyway; so this function replicates PHP.
+       const RFC2045Encode2IN = /.{1,72}(?!\r\n)[^=]{0,3}/g
+       const RFC2045Encode2OUT = function (sMatch) {
+               if (sMatch.substr(sMatch.length - 2) === '\r\n') {
+                       return sMatch
+               }
+               return sMatch + '=\r\n'
+       }
+       str = str
+               .replace(RFC2045Encode1IN, RFC2045Encode1OUT)
+               .replace(RFC2045Encode2IN, RFC2045Encode2OUT)
+       // Strip last softline break
+       return str.substr(0, str.length - 3)
+}