1
0
mirror of https://github.com/mgerb/mywebsite synced 2026-01-12 18:52:50 +00:00

updated bunch of file paths and changed the way posts are loaded

This commit is contained in:
2016-01-05 12:28:04 -06:00
parent 719ae331ae
commit c96a84d0ff
13249 changed files with 317868 additions and 2101398 deletions

4
node_modules/libmime/.npmignore generated vendored Normal file
View File

@@ -0,0 +1,4 @@
.travis.yml
.jshintrc
Gruntfile.js
test

28
node_modules/libmime/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,28 @@
# Changelog
## v1.2.0 2015-10-05
Added support for emojis in header params (eg. filenames)
## v1.1.0 2015-09-24
Updated encoded word encoding with quoted printable, should be more like required in https://tools.ietf.org/html/rfc2047#section-5
## v1.0.0 2015-04-15
Changed versioning scheme to use 1.x instead of 0.x versions. Bumped dependency versions, no actual code changes.
## v0.1.7 2015-01-19
Updated unicode filename handling only revert to parameter continuation if the value actually includes
non-ascii characters or is too long. Previously filenames were encoded if they included anything
besides letters, numbers, dot or space.
## v0.1.6 2014-10-25
Fixed an issue with `encodeWords` where a trailing space was invalidly included in a word if the word
ended with an non-ascii character.
## v0.1.5 2014-09-12
Do not use quotes for continuation encoded filename parts. Fixes an issue with Gmail where the Gmail webmail keeps the charset as part of the filename.

19
node_modules/libmime/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2014-2015 Andris Reinman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

224
node_modules/libmime/README.md generated vendored Normal file
View File

@@ -0,0 +1,224 @@
# libmime
`libmime` provides useful MIME related functions. For Quoted-Printable and Base64 encoding and decoding see [libqp](https://github.com/andris9/libqp) and [libbase64](https://github.com/andris9/libabase64).
## Installation
### [npm](https://www.npmjs.org/):
npm install libmime
## Usage
var libmime = require('libmime');
## Methods
### Encoded Words
#### #encodeWord
Encodes a string into mime [encoded word](http://en.wikipedia.org/wiki/MIME#Encoded-Word) format.
libmime.encodeWord(str [, mimeWordEncoding[, maxLength]]) → String
* **str** - String or Buffer to be encoded
* **mimeWordEncoding** - Encoding for the mime word, either Q or B (default is 'Q')
* **maxLength** - If set, split mime words into several chunks if needed
**Example**
libmime.encodeWord('See on õhin test', 'Q');
Becomes with UTF-8 and Quoted-printable encoding
=?UTF-8?Q?See_on_=C3=B5hin_test?=
#### #decodeWord
Decodes a string from mime encoded word format.
libmime.decodeWord(str) → String
* **str** - String to be decoded
**Example**
libmime.decodeWord('=?UTF-8?Q?See_on_=C3=B5hin_test?=');
will become
See on õhin test
#### #encodeWords
Encodes non ascii sequences in a string to mime words.
libmime.encodeWords(str[, mimeWordEncoding[, maxLength]) → String
* **str** - String or Buffer to be encoded
* **mimeWordEncoding** - Encoding for the mime word, either Q or B (default is 'Q')
* **maxLength** - If set, split mime words into several chunks if needed
#### #decodeWords
Decodes a string that might include one or several mime words. If no mime words are found from the string, the original string is returned
libmime.decodeWords(str) → String
* **str** - String to be decoded
### Folding
#### #foldLines
Folds a long line according to the [RFC 5322](http://tools.ietf.org/html/rfc5322#section-2.1.1). Mostly needed for folding header lines.
libmime.foldLines(str [, lineLength[, afterSpace]]) → String
* **str** - String to be folded
* **lineLength** - Maximum length of a line (defaults to 76)
* **afterSpace** - If true, leave a space in the end of a line
**Example**
libmime.foldLines('Content-Type: multipart/alternative; boundary="----zzzz----"')
results in
Content-Type: multipart/alternative;
boundary="----zzzz----"
#### #encodeFlowed
Adds soft line breaks to content marked with `format=flowed` options to ensure that no line in the message is never longer than lineLength.
libmime.encodeFlowed(str [, lineLength]) → String
* **str** Plaintext string that requires wrapping
* **lineLength** (defaults to 76) Maximum length of a line
#### #decodeFlowed
Unwraps a plaintext string in format=flowed wrapping.
libmime.decodeFlowed(str [, delSp]) → String
* **str** Plaintext string with format=flowed to decode
* **delSp** If true, delete leading spaces (delsp=yes)
### Headers
#### #decodeHeader
Unfolds a header line and splits it to key and value pair. The return value is in the form of `{key: 'subject', value: 'test'}`. The value is not mime word decoded, you need to do your own decoding based on the rules for the specific header key.
libmime.decodeHeader(headerLine) → Object
* **headerLine** - Single header line, might include linebreaks as well if folded
#### #decodeHeaders
Parses a block of header lines. Does not decode mime words as every header might have its own rules (eg. formatted email addresses and such).
Return value is an object of headers, where header keys are object keys and values are arrays.
libmime.decodeHeaders(headers) → Object
* **headers** - Headers string
#### #parseHeaderValue
Parses a header value with `key=value` arguments into a structured object. Useful when dealing with
`content-type` and such. Continuation encoded params are joined into mime encoded words.
parseHeaderValue(valueString) → Object
* **valueString** - a header value without the key
**Example**
```javascript
parseHeaderValue('content-type: text/plain; CHARSET="UTF-8"');
```
Outputs
```json
{
"value": "text/plain",
"params": {
"charset": "UTF-8"
}
}
```
#### #buildHeaderValue
Joins structured header value together as 'value; param1=value1; param2=value2'
buildHeaderValue(structuredHeader) → String
* **structuredHeader** - a header value formatted with `parseHeaderValue`
`filename` argument is encoded with continuation encoding if needed
#### #buildHeaderParam
Encodes and splits a header param value according to [RFC2231](https://tools.ietf.org/html/rfc2231#section-3) Parameter Value Continuations.
libmime.buildHeaderParam(key, str, maxLength) → Array
* **key** - Parameter key (eg. `filename`)
* **str** - String or an Buffer value to encode
* **maxLength** - Maximum length of the encoded string part (not line length). Defaults to 50
The method returns an array of encoded parts with the following structure: `[{key:'...', value: '...'}]`
**Example**
```
libmime.buildHeaderParam('filename', 'filename õäöü.txt', 20);
[ { key: 'filename*0*', value: 'utf-8\'\'filename%20' },
{ key: 'filename*1*', value: '%C3%B5%C3%A4%C3%B6' },
{ key: 'filename*2*', value: '%C3%BC.txt' } ]
```
This can be combined into a properly formatted header:
```
Content-disposition: attachment; filename*0*=utf-8''filename%20
filename*1*=%C3%B5%C3%A4%C3%B6; filename*2*=%C3%BC.txt
```
### MIME Types
#### #detectExtension
Returns file extension for a content type string. If no suitable extensions are found, 'bin' is used as the default extension.
libmime.detectExtension(mimeType) → String
* **mimeType** - Content type to be checked for
**Example**
libmime.detectExtension('image/jpeg') // returns 'jpeg'
#### #detectMimeType
Returns content type for a file extension. If no suitable content types are found, 'application/octet-stream' is used as the default content type
libmime.detectMimeType(extension) → String
* **extension** Extension (or filename) to be checked for
**Example**
libmime.detectExtension('logo.jpg') // returns 'image/jpeg'
## License
**MIT**

89
node_modules/libmime/package.json generated vendored Normal file
View File

@@ -0,0 +1,89 @@
{
"_args": [
[
"libmime@^1.2.0",
"/home/mitchell/Desktop/test-mywebsite/mywebsite/node_modules/nodemailer"
]
],
"_from": "libmime@>=1.2.0 <2.0.0",
"_id": "libmime@1.2.0",
"_inCache": true,
"_installable": true,
"_location": "/libmime",
"_nodeVersion": "4.1.0",
"_npmUser": {
"email": "andris@kreata.ee",
"name": "andris"
},
"_npmVersion": "2.14.3",
"_phantomChildren": {},
"_requested": {
"name": "libmime",
"raw": "libmime@^1.2.0",
"rawSpec": "^1.2.0",
"scope": null,
"spec": ">=1.2.0 <2.0.0",
"type": "range"
},
"_requiredBy": [
"/buildmail",
"/mailcomposer",
"/nodemailer"
],
"_resolved": "https://registry.npmjs.org/libmime/-/libmime-1.2.0.tgz",
"_shasum": "8d84b4f3b225b3704410236ef494906436ba742b",
"_shrinkwrap": null,
"_spec": "libmime@^1.2.0",
"_where": "/home/mitchell/Desktop/test-mywebsite/mywebsite/node_modules/nodemailer",
"author": {
"email": "andris@kreata.ee",
"name": "Andris Reinman"
},
"bugs": {
"url": "https://github.com/andris9/libmime/issues"
},
"dependencies": {
"iconv-lite": "^0.4.13",
"libbase64": "^0.1.0",
"libqp": "^1.1.0"
},
"description": "Encode and decode quoted printable and base64 strings",
"devDependencies": {
"chai": "^3.3.0",
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.11.3",
"grunt-mocha-test": "^0.12.7",
"mocha": "^2.3.3"
},
"directories": {},
"dist": {
"shasum": "8d84b4f3b225b3704410236ef494906436ba742b",
"tarball": "http://registry.npmjs.org/libmime/-/libmime-1.2.0.tgz"
},
"gitHead": "93620c8a6b6f7a6ddee9277fa5f3b9d48f639b34",
"homepage": "https://github.com/andris9/libmime",
"keywords": [
"Base64",
"MIME",
"Quoted-Printable"
],
"license": "MIT",
"main": "src/libmime",
"maintainers": [
{
"name": "andris",
"email": "andris@node.ee"
}
],
"name": "libmime",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git://github.com/andris9/libmime.git"
},
"scripts": {
"test": "grunt"
},
"version": "1.2.0"
}

85
node_modules/libmime/src/charset.js generated vendored Normal file
View File

@@ -0,0 +1,85 @@
'use strict';
var iconv = require('iconv-lite');
/**
* Character set encoding and decoding functions
*/
var charset = module.exports = {
/**
* Encodes an unicode string into an Buffer object as UTF-8
*
* We force UTF-8 here, no strange encodings allowed.
*
* @param {String} str String to be encoded
* @return {Buffer} UTF-8 encoded typed array
*/
encode: function(str) {
return new Buffer(str, 'utf-8');
},
/**
* Decodes a string from Buffer to an unicode string using specified encoding
*
* @param {Buffer} buf Binary data to be decoded
* @param {String} [fromCharset='UTF-8'] Binary data is decoded into string using this charset
* @return {String} Decded string
*/
decode: function(buf, fromCharset) {
fromCharset = charset.normalizeCharset(fromCharset || 'UTF-8');
if (/^(us\-)?ascii|utf\-8|7bit$/i.test(fromCharset)) {
return buf.toString('utf-8');
}
return iconv.decode(buf, fromCharset);
},
/**
* Convert a string from specific encoding to UTF-8 Buffer
*
* @param {String|Buffer} str String to be encoded
* @param {String} [fromCharset='UTF-8'] Source encoding for the string
* @return {Buffer} UTF-8 encoded typed array
*/
convert: function(data, fromCharset) {
fromCharset = charset.normalizeCharset(fromCharset || 'UTF-8');
var bufString;
if (typeof data !== 'string') {
if (/^(us\-)?ascii|utf\-8|7bit$/i.test(fromCharset)) {
return data;
}
bufString = charset.decode(data, fromCharset);
return charset.encode(bufString);
}
return charset.encode(data);
},
/**
* Converts well known invalid character set names to proper names.
* eg. win-1257 will be converted to WINDOWS-1257
*
* @param {String} charset Charset name to convert
* @return {String} Canoninicalized charset name
*/
normalizeCharset: function(charset) {
var match;
if ((match = charset.match(/^utf[\-_]?(\d+)$/i))) {
return 'UTF-' + match[1];
}
if ((match = charset.match(/^win[\-_]?(\d+)$/i))) {
return 'WINDOWS-' + match[1];
}
if ((match = charset.match(/^latin[\-_]?(\d+)$/i))) {
return 'ISO-8859-' + match[1];
}
return charset;
}
};

783
node_modules/libmime/src/libmime.js generated vendored Normal file
View File

@@ -0,0 +1,783 @@
'use strict';
var libcharset = require('./charset');
var libbase64 = require('libbase64');
var libqp = require('libqp');
var mimetypes = require('./mimetypes');
var libmime = module.exports = {
/**
* Checks if a value is plaintext string (uses only printable 7bit chars)
*
* @param {String} value String to be tested
* @returns {Boolean} true if it is a plaintext string
*/
isPlainText: function(value) {
if (typeof value !== 'string' || /[\x00-\x08\x0b\x0c\x0e-\x1f\u0080-\uFFFF]/.test(value)) {
return false;
} else {
return true;
}
},
/**
* Checks if a multi line string containes lines longer than the selected value.
*
* Useful when detecting if a mail message needs any processing at all
* if only plaintext characters are used and lines are short, then there is
* no need to encode the values in any way. If the value is plaintext but has
* longer lines then allowed, then use format=flowed
*
* @param {Number} lineLength Max line length to check for
* @returns {Boolean} Returns true if there is at least one line longer than lineLength chars
*/
hasLongerLines: function(str, lineLength) {
return new RegExp('^.{' + (lineLength + 1) + ',}', 'm').test(str);
},
/**
* Decodes a string from a format=flowed soft wrapping.
*
* @param {String} str Plaintext string with format=flowed to decode
* @param {Boolean} [delSp] If true, delete leading spaces (delsp=yes)
* @return {String} Mime decoded string
*/
decodeFlowed: function(str, delSp) {
str = (str || '').toString();
return str.
split(/\r?\n/).
// remove soft linebreaks
// soft linebreaks are added after space symbols
reduce(function(previousValue, currentValue, index) {
var body = previousValue;
if (delSp) {
// delsp adds spaces to text to be able to fold it
// these spaces can be removed once the text is unfolded
body = body.replace(/[ ]+$/, '');
}
if (/ $/.test(previousValue) && !/(^|\n)\-\- $/.test(previousValue) || index === 1) {
return body + currentValue;
} else {
return body + '\n' + currentValue;
}
}).
// remove whitespace stuffing
// http://tools.ietf.org/html/rfc3676#section-4.4
replace(/^ /gm, '');
},
/**
* Adds soft line breaks to content marked with format=flowed to
* ensure that no line in the message is never longer than lineLength
*
* @param {String} str Plaintext string that requires wrapping
* @param {Number} [lineLength=76] Maximum length of a line
* @return {String} String with forced line breaks
*/
encodeFlowed: function(str, lineLength) {
lineLength = lineLength || 76;
var flowed = [];
str.split(/\r?\n/).forEach(function(line) {
flowed.push(libmime.foldLines(line.
// space stuffing http://tools.ietf.org/html/rfc3676#section-4.2
replace(/^( |From|>)/igm, ' $1'),
lineLength, true));
});
return flowed.join('\r\n');
},
/**
* Encodes a string or an Buffer to an UTF-8 MIME Word (rfc2047)
*
* @param {String|Buffer} data String to be encoded
* @param {String} mimeWordEncoding='Q' Encoding for the mime word, either Q or B
* @param {Number} [maxLength=0] If set, split mime words into several chunks if needed
* @return {String} Single or several mime words joined together
*/
encodeWord: function(data, mimeWordEncoding, maxLength) {
mimeWordEncoding = (mimeWordEncoding || 'Q').toString().toUpperCase().trim().charAt(0);
maxLength = maxLength || 0;
var encodedStr,
toCharset = 'UTF-8',
i, len, parts;
if (maxLength && maxLength > 7 + toCharset.length) {
maxLength -= (7 + toCharset.length);
}
if (mimeWordEncoding === 'Q') {
// https://tools.ietf.org/html/rfc2047#section-5 rule (3)
encodedStr = libqp.encode(data).replace(/[^a-z0-9!*+\-\/=]/ig, function(chr) {
var ord = chr.charCodeAt(0).toString(16).toUpperCase();
if (chr === ' ') {
return '_';
} else {
return '=' + (ord.length === 1 ? '0' + ord : ord);
}
});
} else if (mimeWordEncoding === 'B') {
encodedStr = typeof data === 'string' ? data : libbase64.encode(data);
maxLength = Math.max(3, (maxLength - maxLength % 4) / 4 * 3);
}
if (maxLength && encodedStr.length > maxLength) {
if (mimeWordEncoding === 'Q') {
encodedStr = splitMimeEncodedString(encodedStr, maxLength).join('?= =?' + toCharset + '?' + mimeWordEncoding + '?');
} else {
// RFC2047 6.3 (2) states that encoded-word must include an integral number of characters, so no chopping unicode sequences
parts = [];
for (i = 0, len = encodedStr.length; i < len; i += maxLength) {
parts.push(libbase64.encode(encodedStr.substr(i, maxLength)));
}
if (parts.length > 1) {
encodedStr = parts.join('?= =?' + toCharset + '?' + mimeWordEncoding + '?');
} else {
encodedStr = parts.join('');
}
}
} else if (mimeWordEncoding === 'B') {
encodedStr = libbase64.encode(data);
}
return '=?' + toCharset + '?' + mimeWordEncoding + '?' + encodedStr + (encodedStr.substr(-2) === '?=' ? '' : '?=');
},
/**
* Decode a complete mime word encoded string
*
* @param {String} str Mime word encoded string
* @return {String} Decoded unicode string
*/
decodeWord: function(str) {
str = (str || '').toString().trim();
var fromCharset, encoding, match;
match = str.match(/^\=\?([\w_\-\*]+)\?([QqBb])\?([^\?]+)\?\=$/i);
if (!match) {
return str;
}
// RFC2231 added language tag to the encoding
// see: https://tools.ietf.org/html/rfc2231#section-5
// this implementation silently ignores this tag
fromCharset = match[1].split('*').shift();
encoding = (match[2] || 'Q').toString().toUpperCase();
str = (match[3] || '').replace(/_/g, ' ').replace(/ $/, '=20');
if (encoding === 'B') {
return libcharset.decode(libbase64.decode(str), fromCharset);
} else if (encoding === 'Q') {
return libcharset.decode(libqp.decode(str), fromCharset);
} else {
return str;
}
},
/**
* Finds word sequences with non ascii text and converts these to mime words
*
* @param {String|Buffer} data String to be encoded
* @param {String} mimeWordEncoding='Q' Encoding for the mime word, either Q or B
* @param {Number} [maxLength=0] If set, split mime words into several chunks if needed
* @param {String} [fromCharset='UTF-8'] Source sharacter set
* @return {String} String with possible mime words
*/
encodeWords: function(data, mimeWordEncoding, maxLength, fromCharset) {
if (!fromCharset && typeof maxLength === 'string' && !maxLength.match(/^[0-9]+$/)) {
fromCharset = maxLength;
maxLength = undefined;
}
maxLength = maxLength || 0;
var decodedValue = libcharset.decode(libcharset.convert((data || ''), fromCharset)),
encodedValue;
encodedValue = decodedValue.replace(/([^\s\u0080-\uFFFF]*[\u0080-\uFFFF]+[^\s\u0080-\uFFFF]*(?:\s+[^\s\u0080-\uFFFF]*[\u0080-\uFFFF]+[^\s\u0080-\uFFFF]*\s*)?)+(?=\s|$)/g, function(match) {
return match.length ? libmime.encodeWord(match, mimeWordEncoding || 'Q', maxLength) : '';
});
return encodedValue;
},
/**
* Decode a string that might include one or several mime words
*
* @param {String} str String including some mime words that will be encoded
* @return {String} Decoded unicode string
*/
decodeWords: function(str) {
str = (str || '').toString();
str = str.
replace(/(=\?[^?]+\?[QqBb]\?[^?]+\?=)\s+(?==\?[^?]+\?[QqBb]\?[^?]+\?=)/g, '$1').
replace(/\=\?([\w_\-\*]+)\?([QqBb])\?[^\?]+\?\=/g, function(mimeWord) {
return libmime.decodeWord(mimeWord);
});
return str;
},
/**
* Splits a string by :
* The result is not mime word decoded, you need to do your own decoding based
* on the rules for the specific header key
*
* @param {String} headerLine Single header line, might include linebreaks as well if folded
* @return {Object} And object of {key, value}
*/
decodeHeader: function(headerLine) {
var line = (headerLine || '').toString().replace(/(?:\r?\n|\r)[ \t]*/g, ' ').trim(),
match = line.match(/^\s*([^:]+):(.*)$/),
key = (match && match[1] || '').trim().toLowerCase(),
value = (match && match[2] || '').trim();
return {
key: key,
value: value
};
},
/**
* Parses a block of header lines. Does not decode mime words as every
* header might have its own rules (eg. formatted email addresses and such)
*
* @param {String} headers Headers string
* @return {Object} An object of headers, where header keys are object keys. NB! Several values with the same key make up an Array
*/
decodeHeaders: function(headers) {
var lines = headers.split(/\r?\n|\r/),
headersObj = {},
header,
i, len;
for (i = lines.length - 1; i >= 0; i--) {
if (i && lines[i].match(/^\s/)) {
lines[i - 1] += '\r\n' + lines[i];
lines.splice(i, 1);
}
}
for (i = 0, len = lines.length; i < len; i++) {
header = libmime.decodeHeader(lines[i]);
if (!headersObj[header.key]) {
headersObj[header.key] = [header.value];
} else {
headersObj[header.key].push(header.value);
}
}
return headersObj;
},
/**
* Joins parsed header value together as 'value; param1=value1; param2=value2'
*
* @param {Object} structured Parsed header value
* @return {String} joined header value
*/
buildHeaderValue: function(structured) {
var paramsArray = [];
Object.keys(structured.params || {}).forEach(function(param) {
// filename might include unicode characters so it is a special case
var value = structured.params[param];
if (!libmime.isPlainText(value) || value.length >= 75) {
libmime.buildHeaderParam(param, value, 50).forEach(function(encodedParam) {
if (!/[\s"\\;\/=]|^[\-']|'$/.test(encodedParam.value)) {
paramsArray.push(encodedParam.key + '=' + encodedParam.value);
} else {
paramsArray.push(encodedParam.key + '=' + JSON.stringify(encodedParam.value));
}
});
} else {
if (/[\s'"\\;\/=]|^\-/.test(value)) {
paramsArray.push(param + '=' + JSON.stringify(value));
} else {
paramsArray.push(param + '=' + value);
}
}
}.bind(this));
return structured.value + (paramsArray.length ? '; ' + paramsArray.join('; ') : '');
},
/**
* Parses a header value with key=value arguments into a structured
* object.
*
* parseHeaderValue('content-type: text/plain; CHARSET='UTF-8'') ->
* {
* 'value': 'text/plain',
* 'params': {
* 'charset': 'UTF-8'
* }
* }
*
* @param {String} str Header value
* @return {Object} Header value as a parsed structure
*/
parseHeaderValue: function(str) {
var response = {
value: false,
params: {}
},
key = false,
value = '',
type = 'value',
quote = false,
escaped = false,
chr;
for (var i = 0, len = str.length; i < len; i++) {
chr = str.charAt(i);
if (type === 'key') {
if (chr === '=') {
key = value.trim().toLowerCase();
type = 'value';
value = '';
continue;
}
value += chr;
} else {
if (escaped) {
value += chr;
} else if (chr === '\\') {
escaped = true;
continue;
} else if (quote && chr === quote) {
quote = false;
} else if (!quote && chr === '"') {
quote = chr;
} else if (!quote && chr === ';') {
if (key === false) {
response.value = value.trim();
} else {
response.params[key] = value.trim();
}
type = 'key';
value = '';
} else {
value += chr;
}
escaped = false;
}
}
if (type === 'value') {
if (key === false) {
response.value = value.trim();
} else {
response.params[key] = value.trim();
}
} else if (value.trim()) {
response.params[value.trim().toLowerCase()] = '';
}
// handle parameter value continuations
// https://tools.ietf.org/html/rfc2231#section-3
// preprocess values
Object.keys(response.params).forEach(function(key) {
var actualKey, nr, match, value;
if ((match = key.match(/(\*(\d+)|\*(\d+)\*|\*)$/))) {
actualKey = key.substr(0, match.index);
nr = Number(match[2] || match[3]) || 0;
if (!response.params[actualKey] || typeof response.params[actualKey] !== 'object') {
response.params[actualKey] = {
charset: false,
values: []
};
}
value = response.params[key];
if (nr === 0 && match[0].substr(-1) === '*' && (match = value.match(/^([^']*)'[^']*'(.*)$/))) {
response.params[actualKey].charset = match[1] || 'iso-8859-1';
value = match[2];
}
response.params[actualKey].values[nr] = value;
// remove the old reference
delete response.params[key];
}
});
// concatenate split rfc2231 strings and convert encoded strings to mime encoded words
Object.keys(response.params).forEach(function(key) {
var value;
if (response.params[key] && Array.isArray(response.params[key].values)) {
value = response.params[key].values.map(function(val) {
return val || '';
}).join('');
if (response.params[key].charset) {
// convert "%AB" to "=?charset?Q?=AB?="
response.params[key] = '=?' +
response.params[key].charset +
'?Q?' +
value.
// fix invalidly encoded chars
replace(/[=\?_\s]/g, function(s) {
var c = s.charCodeAt(0).toString(16);
if (s === ' ') {
return '_';
} else {
return '%' + (c.length < 2 ? '0' : '') + c;
}
}).
// change from urlencoding to percent encoding
replace(/%/g, '=') +
'?=';
} else {
response.params[key] = value;
}
}
}.bind(this));
return response;
},
/**
* Encodes a string or an Buffer to an UTF-8 Parameter Value Continuation encoding (rfc2231)
* Useful for splitting long parameter values.
*
* For example
* title="unicode string"
* becomes
* title*0*=utf-8''unicode
* title*1*=%20string
*
* @param {String|Buffer} data String to be encoded
* @param {Number} [maxLength=50] Max length for generated chunks
* @param {String} [fromCharset='UTF-8'] Source sharacter set
* @return {Array} A list of encoded keys and headers
*/
buildHeaderParam: function(key, data, maxLength, fromCharset) {
var list = [];
var encodedStr = typeof data === 'string' ? data : libmime.decode(data, fromCharset);
var encodedStrArr;
var chr, ord;
var line;
var startPos = 0;
var isEncoded = false;
var i, len;
maxLength = maxLength || 50;
// process ascii only text
if (libmime.isPlainText(data)) {
// check if conversion is even needed
if (encodedStr.length <= maxLength) {
return [{
key: key,
value: encodedStr
}];
}
encodedStr = encodedStr.replace(new RegExp('.{' + maxLength + '}', 'g'), function(str) {
list.push({
line: str
});
return '';
});
if (encodedStr) {
list.push({
line: encodedStr
});
}
} else {
if (/[\uD800-\uDBFF]/.test(encodedStr)) {
// string containts surrogate pairs, so normalize it to an array of bytes
encodedStrArr = [];
for (i = 0, len = encodedStr.length; i < len; i++) {
chr = encodedStr.charAt(i);
ord = chr.charCodeAt(0);
if (ord >= 0xD800 && ord <= 0xDBFF && i < len - 1) {
chr += encodedStr.charAt(i + 1);
encodedStrArr.push(chr);
i++;
} else {
encodedStrArr.push(chr);
}
}
encodedStr = encodedStrArr;
}
// first line includes the charset and language info and needs to be encoded
// even if it does not contain any unicode characters
line = 'utf-8\'\'';
isEncoded = true;
startPos = 0;
// process text with unicode or special chars
for (i = 0, len = encodedStr.length; i < len; i++) {
chr = encodedStr[i];
if (isEncoded) {
chr = safeEncodeURIComponent(chr);
} else {
// try to urlencode current char
chr = chr === ' ' ? chr : safeEncodeURIComponent(chr);
// By default it is not required to encode a line, the need
// only appears when the string contains unicode or special chars
// in this case we start processing the line over and encode all chars
if (chr !== encodedStr[i]) {
// Check if it is even possible to add the encoded char to the line
// If not, there is no reason to use this line, just push it to the list
// and start a new line with the char that needs encoding
if ((safeEncodeURIComponent(line) + chr).length >= maxLength) {
list.push({
line: line,
encoded: isEncoded
});
line = '';
startPos = i - 1;
} else {
isEncoded = true;
i = startPos;
line = '';
continue;
}
}
}
// if the line is already too long, push it to the list and start a new one
if ((line + chr).length >= maxLength) {
list.push({
line: line,
encoded: isEncoded
});
line = chr = encodedStr[i] === ' ' ? ' ' : safeEncodeURIComponent(encodedStr[i]);
if (chr === encodedStr[i]) {
isEncoded = false;
startPos = i - 1;
} else {
isEncoded = true;
}
} else {
line += chr;
}
}
if (line) {
list.push({
line: line,
encoded: isEncoded
});
}
}
return list.map(function(item, i) {
return {
// encoded lines: {name}*{part}*
// unencoded lines: {name}*{part}
// if any line needs to be encoded then the first line (part==0) is always encoded
key: key + '*' + i + (item.encoded ? '*' : ''),
value: item.line
};
});
},
/**
* Returns file extension for a content type string. If no suitable extensions
* are found, 'bin' is used as the default extension
*
* @param {String} mimeType Content type to be checked for
* @return {String} File extension
*/
detectExtension: function(mimeType) {
mimeType = (mimeType || '').toString().toLowerCase().replace(/\s/g, '');
if (!(mimeType in mimetypes.list)) {
return 'bin';
}
if (typeof mimetypes.list[mimeType] === 'string') {
return mimetypes.list[mimeType];
}
var mimeParts = mimeType.split('/');
// search for name match
for (var i = 0, len = mimetypes.list[mimeType].length; i < len; i++) {
if (mimeParts[1] === mimetypes.list[mimeType][i]) {
return mimetypes.list[mimeType][i];
}
}
// use the first one
return mimetypes.list[mimeType][0] !== '*' ? mimetypes.list[mimeType][0] : 'bin';
},
/**
* Returns content type for a file extension. If no suitable content types
* are found, 'application/octet-stream' is used as the default content type
*
* @param {String} extension Extension to be checked for
* @return {String} File extension
*/
detectMimeType: function(extension) {
extension = (extension || '').toString().toLowerCase().replace(/\s/g, '').replace(/^\./g, '').split('.').pop();
if (!(extension in mimetypes.extensions)) {
return 'application/octet-stream';
}
if (typeof mimetypes.extensions[extension] === 'string') {
return mimetypes.extensions[extension];
}
var mimeParts;
// search for name match
for (var i = 0, len = mimetypes.extensions[extension].length; i < len; i++) {
mimeParts = mimetypes.extensions[extension][i].split('/');
if (mimeParts[1] === extension) {
return mimetypes.extensions[extension][i];
}
}
// use the first one
return mimetypes.extensions[extension][0];
},
/**
* Folds long lines, useful for folding header lines (afterSpace=false) and
* flowed text (afterSpace=true)
*
* @param {String} str String to be folded
* @param {Number} [lineLength=76] Maximum length of a line
* @param {Boolean} afterSpace If true, leave a space in th end of a line
* @return {String} String with folded lines
*/
foldLines: function(str, lineLength, afterSpace) {
str = (str || '').toString();
lineLength = lineLength || 76;
var pos = 0,
len = str.length,
result = '',
line, match;
while (pos < len) {
line = str.substr(pos, lineLength);
if (line.length < lineLength) {
result += line;
break;
}
if ((match = line.match(/^[^\n\r]*(\r?\n|\r)/))) {
line = match[0];
result += line;
pos += line.length;
continue;
} else if ((match = line.match(/(\s+)[^\s]*$/)) && match[0].length - (afterSpace ? (match[1] || '').length : 0) < line.length) {
line = line.substr(0, line.length - (match[0].length - (afterSpace ? (match[1] || '').length : 0)));
} else if ((match = str.substr(pos + line.length).match(/^[^\s]+(\s*)/))) {
line = line + match[0].substr(0, match[0].length - (!afterSpace ? (match[1] || '').length : 0));
}
result += line;
pos += line.length;
if (pos < len) {
result += '\r\n';
}
}
return result;
}
};
/**
* Splits a mime encoded string. Needed for dividing mime words into smaller chunks
*
* @param {String} str Mime encoded string to be split up
* @param {Number} maxlen Maximum length of characters for one part (minimum 12)
* @return {Array} Split string
*/
function splitMimeEncodedString(str, maxlen) {
var curLine, match, chr, done,
lines = [];
// require at least 12 symbols to fit possible 4 octet UTF-8 sequences
maxlen = Math.max(maxlen || 0, 12);
while (str.length) {
curLine = str.substr(0, maxlen);
// move incomplete escaped char back to main
if ((match = curLine.match(/\=[0-9A-F]?$/i))) {
curLine = curLine.substr(0, match.index);
}
done = false;
while (!done) {
done = true;
// check if not middle of a unicode char sequence
if ((match = str.substr(curLine.length).match(/^\=([0-9A-F]{2})/i))) {
chr = parseInt(match[1], 16);
// invalid sequence, move one char back anc recheck
if (chr < 0xC2 && chr > 0x7F) {
curLine = curLine.substr(0, curLine.length - 3);
done = false;
}
}
}
if (curLine.length) {
lines.push(curLine);
}
str = str.substr(curLine.length);
}
return lines;
}
function encodeURICharComponent(chr) {
var i, len, ord;
var res = '';
ord = chr.charCodeAt(0).toString(16).toUpperCase();
if (ord.length % 2) {
ord = '0' + ord;
}
if (ord.length > 2) {
for (i = 0, len = ord.length / 2; i < len; i++) {
res += '%' + ord.substr(i, 2);
}
} else {
res += '%' + ord;
}
return res;
}
function safeEncodeURIComponent(str) {
str = (str || '').toString();
try {
// might throw if we try to encode invalid sequences, eg. partial emoji
str = encodeURIComponent(str);
} catch (E) {
// should never run
return str.replace(/[^\x00-\x1F *'()<>@,;:\\"\[\]?=\u007F-\uFFFF]+/g, '');
}
// ensure chars that are not handled by encodeURICompent are converted as well
return str.replace(/[\x00-\x1F *'()<>@,;:\\"\[\]?=\u007F-\uFFFF]/g, encodeURICharComponent);
}

2013
node_modules/libmime/src/mimetypes.js generated vendored Normal file

File diff suppressed because it is too large Load Diff