diff options
author | Cliff Brake <cbrake@bec-systems.com> | 2012-08-17 13:43:14 -0400 |
---|---|---|
committer | Cliff Brake <cbrake@bec-systems.com> | 2012-08-17 13:43:14 -0400 |
commit | a94e78479793722bc97b8771158d1acee3f55413 (patch) | |
tree | bf8f79959febb472513b299df99774de524f5fd1 /tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js | |
parent | c11f922b0bfa023a4cf49f26e55aec6a1413344b (diff) | |
download | openembedded-admin-a94e78479793722bc97b8771158d1acee3f55413.tar.gz |
add node modules to git
This is now the best practice for deployed apps
Diffstat (limited to 'tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js')
-rw-r--r-- | tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js new file mode 100644 index 0000000..9a93c7b --- /dev/null +++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js @@ -0,0 +1,486 @@ + +try{ + // see http://github.com/bnoordhuis/node-iconv for more info + var Iconv = require("iconv").Iconv; +}catch(E){ + // convert nothing + Iconv = function(){} + Iconv.prototype.convert = function(buf){return buf;}; +} + +/* mime related functions - encoding/decoding etc*/ +/* TODO: Only UTF-8 and Latin1 are allowed with encodeQuotedPrintable */ +/* TODO: Check if the input string even needs encoding */ + +/** + * mime.foldLine(str, maxLength, foldAnywhere) -> String + * - str (String): mime string that might need folding + * - maxLength (Number): max length for a line, defaults to 78 + * - foldAnywhere (Boolean): can fold at any location (ie. in base64) + * - afterSpace (Boolean): If [true] fold after the space + * + * Folds a long line according to the RFC 5322 + * <http://tools.ietf.org/html/rfc5322#section-2.1.1> + * + * For example: + * Content-Type: multipart/alternative; boundary="----bd_n3-lunchhour1283962663300----" + * will become + * Content-Type: multipart/alternative; + * boundary="----bd_n3-lunchhour1283962663300----" + * + **/ +this.foldLine = function(str, maxLength, foldAnywhere, afterSpace){ + var line=false, curpos=0, response="", lf; + maxLength = maxLength || 78; + + // return original if no need to fold + if(str.length<=maxLength) + return str; + + // read in <maxLength> bytes and try to fold it + while(line = str.substr(curpos, maxLength)){ + if(!!foldAnywhere){ + response += line; + if(curpos+maxLength<str.length){ + response+="\r\n"; + } + }else{ + lf = line.lastIndexOf(" "); + if(lf<=0) + lf = line.lastIndexOf("\t"); + if(line.length>=maxLength && lf>0){ + if(!!afterSpace){ + // move forward until line end or no more \s and \t + while(lf<line.length && (line.charAt(lf)==" " || line.charAt(lf)=="\t")){ + lf++; + } + } + response += line.substr(0,lf)+"\r\n"+(!foldAnywhere && !afterSpace && " " || ""); + curpos -= line.substr(lf).length; + }else{ + response += line; + //line = line.replace(/=[a-f0-9]?$/i, ""); + //response+=line + "\r\n"; + } + } + curpos += line.length; + } + + // return folded string + return response; +} + + +/** + * mime.encodeMimeWord(str, encoding, charset) -> String + * - str (String): String to be encoded + * - encoding (String): Encoding Q for quoted printable or B (def.) for base64 + * - charset (String): Charset to be used + * + * Encodes a string into mime encoded word format + * <http://en.wikipedia.org/wiki/MIME#Encoded-Word> + * + * For example: + * See on õhin test + * Becomes with UTF-8 and Quoted-printable encoding + * =?UTF-8?q?See_on_=C3=B5hin_test?= + * + **/ +this.encodeMimeWord = function(str, encoding, charset){ + charset = charset || "UTF-8"; + encoding = encoding && encoding.toUpperCase() || "B"; + + if(encoding=="Q"){ + str = this.encodeQuotedPrintable(str, true, charset); + } + + if(encoding=="B"){ + str = this.encodeBase64(str); + } + + return "=?"+charset+"?"+encoding+"?"+str+"?="; +} + +/** + * mime.decodeMimeWord(str, encoding, charset) -> String + * - str (String): String to be encoded + * - encoding (String): Encoding Q for quoted printable or B (def.) for base64 + * - charset (String): Charset to be used, defaults to UTF-8 + * + * Decodes a string from mime encoded word format, see [[encodeMimeWord]] + * + **/ + +this.decodeMimeWord = function(str){ + var parts = str.split("?"), + charset = parts && parts[1], + encoding = parts && parts[2], + text = parts && parts[3]; + if(!charset || !encoding || !text) + return str; + if(encoding.toUpperCase()=="Q"){ + return this.decodeQuotedPrintable(text, true, charset); + } + + if(encoding.toUpperCase()=="B"){ + return this.decodeBase64(text); + } + + return text; +} + + +/** + * mime.encodeQuotedPrintable(str, mimeWord, charset) -> String + * - str (String): String to be encoded into Quoted-printable + * - mimeWord (Boolean): Use mime-word mode (defaults to false) + * - charset (String): Destination charset, defaults to UTF-8 + * TODO: Currently only allowed charsets: UTF-8, LATIN1 + * + * Encodes a string into Quoted-printable format. + **/ +this.encodeQuotedPrintable = function(str, mimeWord, charset){ + charset = charset || "UTF-8"; + + /* + * Characters from 33-126 OK (except for =; and ?_ when in mime word mode) + * Spaces + tabs OK (except for line beginnings and endings) + * \n + \r OK + */ + + str = str.replace(/(?:[\ud800-\udbff][\udc00-\udfff])|[^\sa-zA-Z\d]/gm,function(c){ + if(!!mimeWord){ + if(c=="?")return "=3F"; + if(c=="_")return "=5F"; + } + if(c!=="=" && c.charCodeAt(0)>=33 && c.charCodeAt(0)<=126) + return c; + return c=="="?"=3D":(charset=="UTF-8"?encodeURIComponent(c):escape(c)).replace(/%/g,'='); + }); + + str = lineEdges(str); + + if(!mimeWord){ + // lines might not be longer than 76 bytes, soft break: "=\r\n" + var lines = str.split(/\r?\n/); + str.replace(/(.{73}(?!\r?\n))/,"$&=\r\n") + for(var i=0, len = lines.length; i<len; i++){ + if(lines[i].length>76){ + lines[i] = this.foldLine(lines[i],76, false, true).replace(/\r\n/g,"=\r\n"); + } + } + str = lines.join("\r\n"); + }else{ + str = str.replace(/\s/g, function(a){ + if(a==" ")return "_"; + if(a=="\t")return "=09"; + return a=="\r"?"=0D":"=0A"; + }); + } + + return str; +} + +/** + * mime.deccodeQuotedPrintable(str, mimeWord, charset) -> String + * - str (String): String to be decoded + * - mimeWord (Boolean): Use mime-word mode (defaults to false) + * - charset (String): Charset to be used, defaults to UTF-8 + * + * Decodes a string from Quoted-printable format. + **/ +this.decodeQuotedPrintable = function(str, mimeWord, charset){ + charset = charset && charset.toUpperCase() || "UTF-8"; + + if(mimeWord){ + str = str.replace(/_/g," "); + }else{ + str = str.replace(/=\r\n/gm,''); + str = str.replace(/=$/,""); + } + if(charset == "UTF-8") + str = decodeURIComponent(str.replace(/%/g,'%25').replace(/=/g,"%")); + else{ + str = str.replace(/%/g,'%25').replace(/=/g,"%"); + if(charset=="ISO-8859-1" || charset=="LATIN1") + str = unescape(str); + else{ + str = decodeBytestreamUrlencoding(str); + str = fromCharset(charset, str); + } + } + return str; +} + +/** + * mime.encodeBase64(str) -> String + * - str (String): String to be encoded into Base64 + * - charset (String): Destination charset, defaults to UTF-8 + * + * Encodes a string into Base64 format. Base64 is mime-word safe. + **/ +this.encodeBase64 = function(str, charset){ + var buffer; + if(charset && charset.toUpperCase()!="UTF-8") + buffer = toCharset(charset, str); + else + buffer = new Buffer(str, "UTF-8"); + return buffer.toString("base64"); +} + +/** + * mime.decodeBase64(str) -> String + * - str (String): String to be decoded from Base64 + * - charset (String): Source charset, defaults to UTF-8 + * + * Decodes a string from Base64 format. Base64 is mime-word safe. + * NB! Always returns UTF-8 + **/ +this.decodeBase64 = function(str, charset){ + var buffer = new Buffer(str, "base64"); + + if(charset && charset.toUpperCase()!="UTF-8"){ + return fromCharset(charset, buffer); + } + + // defaults to utf-8 + return buffer.toString("UTF-8"); +} + +/** + * mime.parseHeaders(headers) -> Array + * - headers (String): header section of the e-mail + * + * Parses header lines into an array of objects (see [[parseHeaderLine]]) + * FIXME: This should probably not be here but in "envelope" instead + **/ +this.parseHeaders = function(headers){ + var text, lines, line, i, name, value, cmd, header_lines = {}; + // unfold + headers = headers.replace(/\r?\n([ \t])/gm," "); + + // split lines + lines = headers.split(/\r?\n/); + for(i=0; i<lines.length;i++){ + if(!lines[i]) // no more header lines + break; + cmd = lines[i].match(/[^\:]+/); + if(cmd && (cmd = cmd[0])){ + name = cmd; + value = lines[i].substr(name.length+1); + if(!header_lines[name.toLowerCase().trim()])header_lines[name.toLowerCase().trim()] = []; + header_lines[name.toLowerCase()].push(value.trim()); + } + } + + return header_lines; +} + +/** + * mime.parseAddresses(addresses) -> Array + * - addresses (String): string with comma separated e-mail addresses + * + * Parses names and addresses from a from, to, cc or bcc line + **/ +this.parseAddresses = function(addresses){ + if(!addresses) + return []; + + addresses = addresses.replace(/\=\?[^?]+\?[QqBb]\?[^?]+\?=/g, (function(a){return this.decodeMimeWord(a);}).bind(this)); + + // not sure if it's even needed - urlencode escaped \\ and \" and \' + addresses = addresses.replace(/\\\\/g,function(a){return escape(a.charAt(1));}); + addresses = addresses.replace(/\\["']/g,function(a){return escape(a.charAt(1));}); + + // find qutoed strings + + var parts = addresses.split(','), curStr, + curQuote, lastPos, remainder="", str, list = [], + curAddress, address, addressArr = [], name, email, i, len; + var rightEnd; + + // separate quoted text from text parts + for(i=0, len=parts.length; i<len; i++){ + str = ""; + + curStr = (remainder+parts[i]).trim(); + + curQuote = curStr.charAt(0); + if(curQuote == "'" || curQuote == '"'){ + rightEnd= curStr.indexOf("<"); + if(rightEnd == -1)rightEnd= curStr.length-1; + lastPos = curStr.lastIndexOf(curQuote,rightEnd); + + if(!lastPos){ + remainder = remainder+parts[i]+","; + continue; + }else{ + remainder = ""; + str = curStr.substring(1, lastPos).trim(); + address = curStr.substr(lastPos+1).trim(); + } + + }else{ + address = curStr; + } + + list.push({name: str, address: address, original: curStr}); + } + + // find e-mail addresses and user names + for(i=0, len=list.length; i<len; i++){ + curAddress = list[i]; + + email = false; + name = false; + + name = curAddress.name; + + address = curAddress.address.replace(/<([^>]+)>/, function(original, addr){ + email = addr.indexOf("@")>=0 && addr; + return email ? "" : original; + }).trim(); + + if(!email){ + address = address.replace(/(\S+@\S+)/, function(original, m){ + email = m; + return email ? "" : original; + }); + } + + if(!name){ + if(email){ + email = email.replace(/\(([^)]+)\)/,function(original, n){ + name = n; + return ""; + }); + } + if(!name){ + name = address.replace(/"/g,"").trim(); + } + } + + // just in case something got mixed up + if(!email && name.indexOf("@")>=0){ + email = name; + name = false; + } + + if(name || email){ + name = (name || "").replace(/%27/g, "'").replace(/%22/g, "\""); + email = (email || "").replace(/%27/g, "'").replace(/%22/g, "\""); + addressArr.push({address: email, name: name}); + + } + } + return addressArr; +}; + +/** + * mime.parseMimeWords(str) -> String + * - str (String): string to be parsed + * + * Parses mime-words into UTF-8 strings + **/ +this.parseMimeWords = function(str){ + return str.replace(/=\?[^?]+\?[QqBb]\?[^?]+\?=/g, (function(a){ + return this.decodeMimeWord(a); + }).bind(this)); +} + +/** + * mime.parseHeaderLine(line) -> Object + * - line (String): a line from a message headers + * + * Parses a header line to search for additional parameters. + * For example with "text/plain; charset=utf-8" the output would be + * - defaultValue = text/plain + * - charset = utf-8 + **/ +this.parseHeaderLine = function(line){ + if(!line) + return {}; + var result = {}, parts = line.split(";"), pos; + for(var i=0, len = parts.length; i<len; i++){ + pos = parts[i].indexOf("="); + if(pos<0){ + result[!i?"defaultValue":"i-"+i] = parts[i].trim(); + }else{ + result[parts[i].substr(0,pos).trim().toLowerCase()] = parts[i].substr(pos+1).trim(); + } + } + return result; +} + + +/* Helper functions */ + +/** + * lineEdges(str) -> String + * - str (String): String to be processed + * + * Replaces all spaces and tabs in the beginning and end of the string + * with quoted printable encoded chars. Needed by [[encodeQuotedPrintable]] + **/ +function lineEdges(str){ + str = str.replace(/^[ \t]+/gm, function(wsc){ + return wsc.replace(/ /g,"=20").replace(/\t/g,"=09"); + }); + + str = str.replace(/[ \t]+$/gm, function(wsc){ + return wsc.replace(/ /g,"=20").replace(/\t/g,"=09"); + }); + return str; +} + +/** + * fromCharset(charset, buffer, keep_buffer) -> String | Buffer + * - charset (String): Source charset + * - buffer (Buffer): Buffer in <charset> + * - keep_buffer (Boolean): If true, return buffer, otherwise UTF-8 string + * + * Converts a buffer in <charset> codepage into UTF-8 string + **/ +function fromCharset(charset, buffer, keep_buffer){ + var iconv = new Iconv(charset,'UTF-8'), + buffer = iconv.convert(buffer); + return keep_buffer?buffer:buffer.toString("utf-8"); +} + +/** + * toCharset(charset, buffer) -> Buffer + * - charset (String): Source charset + * - buffer (Buffer): Buffer in UTF-8 or string + * + * Converts a string or buffer to <charset> codepage + **/ +function toCharset(charset, buffer){ + var iconv = new Iconv('UTF-8',charset); + return iconv.convert(buffer); +} + +/** + * decodeBytestreamUrlencoding(encoded_string) -> Buffer + * - encoded_string (String): String in urlencode coding + * + * Converts an urlencoded string into a bytestream buffer. If the used + * charset is known the resulting string can be converted to UTF-8 with + * [[fromCharset]]. + * NB! For UTF-8 use decodeURIComponent and for Latin 1 decodeURL instead + **/ +function decodeBytestreamUrlencoding(encoded_string){ + var c, i, j=0, prcnts = encoded_string.match(/%/g) || "", + buffer_length = encoded_string.length - (prcnts.length*2), + buffer = new Buffer(buffer_length); + + for(var i=0; i<encoded_string.length; i++){ + c = encoded_string.charCodeAt(i); + if(c=="37"){ // % + c = parseInt(encoded_string.substr(i+1,2), 16); + i+=2; + } + buffer[j++] = c; + } + return buffer; +} + |