twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

mailto.js (7746B)


      1 import { pctEncChar, pctDecChars, unescapeComponent } from "../uri";
      2 import punycode from "punycode";
      3 import { merge, subexp, toUpperCase, toArray } from "../util";
      4 const O = {};
      5 const isIRI = true;
      6 //RFC 3986
      7 const UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + (isIRI ? "\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" : "") + "]";
      8 const HEXDIG$$ = "[0-9A-Fa-f]"; //case-insensitive
      9 const PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)); //expanded
     10 //RFC 5322, except these symbols as per RFC 6068: @ : / ? # [ ] & ; =
     11 //const ATEXT$$ = "[A-Za-z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
     12 //const WSP$$ = "[\\x20\\x09]";
     13 //const OBS_QTEXT$$ = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]";  //(%d1-8 / %d11-12 / %d14-31 / %d127)
     14 //const QTEXT$$ = merge("[\\x21\\x23-\\x5B\\x5D-\\x7E]", OBS_QTEXT$$);  //%d33 / %d35-91 / %d93-126 / obs-qtext
     15 //const VCHAR$$ = "[\\x21-\\x7E]";
     16 //const WSP$$ = "[\\x20\\x09]";
     17 //const OBS_QP$ = subexp("\\\\" + merge("[\\x00\\x0D\\x0A]", OBS_QTEXT$$));  //%d0 / CR / LF / obs-qtext
     18 //const FWS$ = subexp(subexp(WSP$$ + "*" + "\\x0D\\x0A") + "?" + WSP$$ + "+");
     19 //const QUOTED_PAIR$ = subexp(subexp("\\\\" + subexp(VCHAR$$ + "|" + WSP$$)) + "|" + OBS_QP$);
     20 //const QUOTED_STRING$ = subexp('\\"' + subexp(FWS$ + "?" + QCONTENT$) + "*" + FWS$ + "?" + '\\"');
     21 const ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]";
     22 const QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]";
     23 const VCHAR$$ = merge(QTEXT$$, "[\\\"\\\\]");
     24 const DOT_ATOM_TEXT$ = subexp(ATEXT$$ + "+" + subexp("\\." + ATEXT$$ + "+") + "*");
     25 const QUOTED_PAIR$ = subexp("\\\\" + VCHAR$$);
     26 const QCONTENT$ = subexp(QTEXT$$ + "|" + QUOTED_PAIR$);
     27 const QUOTED_STRING$ = subexp('\\"' + QCONTENT$ + "*" + '\\"');
     28 //RFC 6068
     29 const DTEXT_NO_OBS$$ = "[\\x21-\\x5A\\x5E-\\x7E]"; //%d33-90 / %d94-126
     30 const SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]";
     31 const QCHAR$ = subexp(UNRESERVED$$ + "|" + PCT_ENCODED$ + "|" + SOME_DELIMS$$);
     32 const DOMAIN$ = subexp(DOT_ATOM_TEXT$ + "|" + "\\[" + DTEXT_NO_OBS$$ + "*" + "\\]");
     33 const LOCAL_PART$ = subexp(DOT_ATOM_TEXT$ + "|" + QUOTED_STRING$);
     34 const ADDR_SPEC$ = subexp(LOCAL_PART$ + "\\@" + DOMAIN$);
     35 const TO$ = subexp(ADDR_SPEC$ + subexp("\\," + ADDR_SPEC$) + "*");
     36 const HFNAME$ = subexp(QCHAR$ + "*");
     37 const HFVALUE$ = HFNAME$;
     38 const HFIELD$ = subexp(HFNAME$ + "\\=" + HFVALUE$);
     39 const HFIELDS2$ = subexp(HFIELD$ + subexp("\\&" + HFIELD$) + "*");
     40 const HFIELDS$ = subexp("\\?" + HFIELDS2$);
     41 const MAILTO_URI = new RegExp("^mailto\\:" + TO$ + "?" + HFIELDS$ + "?$");
     42 const UNRESERVED = new RegExp(UNRESERVED$$, "g");
     43 const PCT_ENCODED = new RegExp(PCT_ENCODED$, "g");
     44 const NOT_LOCAL_PART = new RegExp(merge("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g");
     45 const NOT_DOMAIN = new RegExp(merge("[^]", ATEXT$$, "[\\.]", "[\\[]", DTEXT_NO_OBS$$, "[\\]]"), "g");
     46 const NOT_HFNAME = new RegExp(merge("[^]", UNRESERVED$$, SOME_DELIMS$$), "g");
     47 const NOT_HFVALUE = NOT_HFNAME;
     48 const TO = new RegExp("^" + TO$ + "$");
     49 const HFIELDS = new RegExp("^" + HFIELDS2$ + "$");
     50 function decodeUnreserved(str) {
     51     const decStr = pctDecChars(str);
     52     return (!decStr.match(UNRESERVED) ? str : decStr);
     53 }
     54 const handler = {
     55     scheme: "mailto",
     56     parse: function (components, options) {
     57         const mailtoComponents = components;
     58         const to = mailtoComponents.to = (mailtoComponents.path ? mailtoComponents.path.split(",") : []);
     59         mailtoComponents.path = undefined;
     60         if (mailtoComponents.query) {
     61             let unknownHeaders = false;
     62             const headers = {};
     63             const hfields = mailtoComponents.query.split("&");
     64             for (let x = 0, xl = hfields.length; x < xl; ++x) {
     65                 const hfield = hfields[x].split("=");
     66                 switch (hfield[0]) {
     67                     case "to":
     68                         const toAddrs = hfield[1].split(",");
     69                         for (let x = 0, xl = toAddrs.length; x < xl; ++x) {
     70                             to.push(toAddrs[x]);
     71                         }
     72                         break;
     73                     case "subject":
     74                         mailtoComponents.subject = unescapeComponent(hfield[1], options);
     75                         break;
     76                     case "body":
     77                         mailtoComponents.body = unescapeComponent(hfield[1], options);
     78                         break;
     79                     default:
     80                         unknownHeaders = true;
     81                         headers[unescapeComponent(hfield[0], options)] = unescapeComponent(hfield[1], options);
     82                         break;
     83                 }
     84             }
     85             if (unknownHeaders)
     86                 mailtoComponents.headers = headers;
     87         }
     88         mailtoComponents.query = undefined;
     89         for (let x = 0, xl = to.length; x < xl; ++x) {
     90             const addr = to[x].split("@");
     91             addr[0] = unescapeComponent(addr[0]);
     92             if (!options.unicodeSupport) {
     93                 //convert Unicode IDN -> ASCII IDN
     94                 try {
     95                     addr[1] = punycode.toASCII(unescapeComponent(addr[1], options).toLowerCase());
     96                 }
     97                 catch (e) {
     98                     mailtoComponents.error = mailtoComponents.error || "Email address's domain name can not be converted to ASCII via punycode: " + e;
     99                 }
    100             }
    101             else {
    102                 addr[1] = unescapeComponent(addr[1], options).toLowerCase();
    103             }
    104             to[x] = addr.join("@");
    105         }
    106         return mailtoComponents;
    107     },
    108     serialize: function (mailtoComponents, options) {
    109         const components = mailtoComponents;
    110         const to = toArray(mailtoComponents.to);
    111         if (to) {
    112             for (let x = 0, xl = to.length; x < xl; ++x) {
    113                 const toAddr = String(to[x]);
    114                 const atIdx = toAddr.lastIndexOf("@");
    115                 const localPart = (toAddr.slice(0, atIdx)).replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_LOCAL_PART, pctEncChar);
    116                 let domain = toAddr.slice(atIdx + 1);
    117                 //convert IDN via punycode
    118                 try {
    119                     domain = (!options.iri ? punycode.toASCII(unescapeComponent(domain, options).toLowerCase()) : punycode.toUnicode(domain));
    120                 }
    121                 catch (e) {
    122                     components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
    123                 }
    124                 to[x] = localPart + "@" + domain;
    125             }
    126             components.path = to.join(",");
    127         }
    128         const headers = mailtoComponents.headers = mailtoComponents.headers || {};
    129         if (mailtoComponents.subject)
    130             headers["subject"] = mailtoComponents.subject;
    131         if (mailtoComponents.body)
    132             headers["body"] = mailtoComponents.body;
    133         const fields = [];
    134         for (const name in headers) {
    135             if (headers[name] !== O[name]) {
    136                 fields.push(name.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFNAME, pctEncChar) +
    137                     "=" +
    138                     headers[name].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFVALUE, pctEncChar));
    139             }
    140         }
    141         if (fields.length) {
    142             components.query = fields.join("&");
    143         }
    144         return components;
    145     }
    146 };
    147 export default handler;
    148 //# sourceMappingURL=mailto.js.map