From a94e78479793722bc97b8771158d1acee3f55413 Mon Sep 17 00:00:00 2001 From: Cliff Brake Date: Fri, 17 Aug 2012 13:43:14 -0400 Subject: add node modules to git This is now the best practice for deployed apps --- .../node_modules/mimelib-noiconv/mime-functions.js | 486 +++++++++++++++++++++ 1 file changed, 486 insertions(+) create mode 100644 tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js (limited to 'tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js') 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 + * + * + * 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 bytes and try to fold it + while(line = str.substr(curpos, maxLength)){ + if(!!foldAnywhere){ + response += line; + if(curpos+maxLength=maxLength && lf>0){ + if(!!afterSpace){ + // move forward until line end or no more \s and \t + while(lf 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 + * + * + * 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; i76){ + 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 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]+)>/, 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 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 + * - keep_buffer (Boolean): If true, return buffer, otherwise UTF-8 string + * + * Converts a buffer in 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 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