react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / node_modules / commoner / node_modules / iconv-lite / encodings / utf7.js
81169 views"use strict"12// UTF-7 codec, according to https://tools.ietf.org/html/rfc21523// See also below a UTF-7-IMAP codec, according to http://tools.ietf.org/html/rfc3501#section-5.1.345exports.utf7 = Utf7Codec;6exports.unicode11utf7 = 'utf7'; // Alias UNICODE-1-1-UTF-77function Utf7Codec(codecOptions, iconv) {8this.iconv = iconv;9};1011Utf7Codec.prototype.encoder = Utf7Encoder;12Utf7Codec.prototype.decoder = Utf7Decoder;13Utf7Codec.prototype.bomAware = true;141516// -- Encoding1718var nonDirectChars = /[^A-Za-z0-9'\(\),-\.\/:\? \n\r\t]+/g;1920function Utf7Encoder(options, codec) {21this.iconv = codec.iconv;22}2324Utf7Encoder.prototype.write = function(str) {25// Naive implementation.26// Non-direct chars are encoded as "+<base64>-"; single "+" char is encoded as "+-".27return new Buffer(str.replace(nonDirectChars, function(chunk) {28return "+" + (chunk === '+' ? '' :29this.iconv.encode(chunk, 'utf16-be').toString('base64').replace(/=+$/, ''))30+ "-";31}.bind(this)));32}3334Utf7Encoder.prototype.end = function() {35}363738// -- Decoding3940function Utf7Decoder(options, codec) {41this.iconv = codec.iconv;42this.inBase64 = false;43this.base64Accum = '';44}4546var base64Regex = /[A-Za-z0-9\/+]/;47var base64Chars = [];48for (var i = 0; i < 256; i++)49base64Chars[i] = base64Regex.test(String.fromCharCode(i));5051var plusChar = '+'.charCodeAt(0),52minusChar = '-'.charCodeAt(0),53andChar = '&'.charCodeAt(0);5455Utf7Decoder.prototype.write = function(buf) {56var res = "", lastI = 0,57inBase64 = this.inBase64,58base64Accum = this.base64Accum;5960// The decoder is more involved as we must handle chunks in stream.6162for (var i = 0; i < buf.length; i++) {63if (!inBase64) { // We're in direct mode.64// Write direct chars until '+'65if (buf[i] == plusChar) {66res += this.iconv.decode(buf.slice(lastI, i), "ascii"); // Write direct chars.67lastI = i+1;68inBase64 = true;69}70} else { // We decode base64.71if (!base64Chars[buf[i]]) { // Base64 ended.72if (i == lastI && buf[i] == minusChar) {// "+-" -> "+"73res += "+";74} else {75var b64str = base64Accum + buf.slice(lastI, i).toString();76res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be");77}7879if (buf[i] != minusChar) // Minus is absorbed after base64.80i--;8182lastI = i+1;83inBase64 = false;84base64Accum = '';85}86}87}8889if (!inBase64) {90res += this.iconv.decode(buf.slice(lastI), "ascii"); // Write direct chars.91} else {92var b64str = base64Accum + buf.slice(lastI).toString();9394var canBeDecoded = b64str.length - (b64str.length % 8); // Minimal chunk: 2 quads -> 2x3 bytes -> 3 chars.95base64Accum = b64str.slice(canBeDecoded); // The rest will be decoded in future.96b64str = b64str.slice(0, canBeDecoded);9798res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be");99}100101this.inBase64 = inBase64;102this.base64Accum = base64Accum;103104return res;105}106107Utf7Decoder.prototype.end = function() {108var res = "";109if (this.inBase64 && this.base64Accum.length > 0)110res = this.iconv.decode(new Buffer(this.base64Accum, 'base64'), "utf16-be");111112this.inBase64 = false;113this.base64Accum = '';114return res;115}116117118// UTF-7-IMAP codec.119// RFC3501 Sec. 5.1.3 Modified UTF-7 (http://tools.ietf.org/html/rfc3501#section-5.1.3)120// Differences:121// * Base64 part is started by "&" instead of "+"122// * Direct characters are 0x20-0x7E, except "&" (0x26)123// * In Base64, "," is used instead of "/"124// * Base64 must not be used to represent direct characters.125// * No implicit shift back from Base64 (should always end with '-')126// * String must end in non-shifted position.127// * "-&" while in base64 is not allowed.128129130exports.utf7imap = Utf7IMAPCodec;131function Utf7IMAPCodec(codecOptions, iconv) {132this.iconv = iconv;133};134135Utf7IMAPCodec.prototype.encoder = Utf7IMAPEncoder;136Utf7IMAPCodec.prototype.decoder = Utf7IMAPDecoder;137Utf7IMAPCodec.prototype.bomAware = true;138139140// -- Encoding141142function Utf7IMAPEncoder(options, codec) {143this.iconv = codec.iconv;144this.inBase64 = false;145this.base64Accum = new Buffer(6);146this.base64AccumIdx = 0;147}148149Utf7IMAPEncoder.prototype.write = function(str) {150var inBase64 = this.inBase64,151base64Accum = this.base64Accum,152base64AccumIdx = this.base64AccumIdx,153buf = new Buffer(str.length*5 + 10), bufIdx = 0;154155for (var i = 0; i < str.length; i++) {156var uChar = str.charCodeAt(i);157if (0x20 <= uChar && uChar <= 0x7E) { // Direct character or '&'.158if (inBase64) {159if (base64AccumIdx > 0) {160bufIdx += buf.write(base64Accum.slice(0, base64AccumIdx).toString('base64').replace(/\//g, ',').replace(/=+$/, ''), bufIdx);161base64AccumIdx = 0;162}163164buf[bufIdx++] = minusChar; // Write '-', then go to direct mode.165inBase64 = false;166}167168if (!inBase64) {169buf[bufIdx++] = uChar; // Write direct character170171if (uChar === andChar) // Ampersand -> '&-'172buf[bufIdx++] = minusChar;173}174175} else { // Non-direct character176if (!inBase64) {177buf[bufIdx++] = andChar; // Write '&', then go to base64 mode.178inBase64 = true;179}180if (inBase64) {181base64Accum[base64AccumIdx++] = uChar >> 8;182base64Accum[base64AccumIdx++] = uChar & 0xFF;183184if (base64AccumIdx == base64Accum.length) {185bufIdx += buf.write(base64Accum.toString('base64').replace(/\//g, ','), bufIdx);186base64AccumIdx = 0;187}188}189}190}191192this.inBase64 = inBase64;193this.base64AccumIdx = base64AccumIdx;194195return buf.slice(0, bufIdx);196}197198Utf7IMAPEncoder.prototype.end = function() {199var buf = new Buffer(10), bufIdx = 0;200if (this.inBase64) {201if (this.base64AccumIdx > 0) {202bufIdx += buf.write(this.base64Accum.slice(0, this.base64AccumIdx).toString('base64').replace(/\//g, ',').replace(/=+$/, ''), bufIdx);203this.base64AccumIdx = 0;204}205206buf[bufIdx++] = minusChar; // Write '-', then go to direct mode.207this.inBase64 = false;208}209210return buf.slice(0, bufIdx);211}212213214// -- Decoding215216function Utf7IMAPDecoder(options, codec) {217this.iconv = codec.iconv;218this.inBase64 = false;219this.base64Accum = '';220}221222var base64IMAPChars = base64Chars.slice();223base64IMAPChars[','.charCodeAt(0)] = true;224225Utf7IMAPDecoder.prototype.write = function(buf) {226var res = "", lastI = 0,227inBase64 = this.inBase64,228base64Accum = this.base64Accum;229230// The decoder is more involved as we must handle chunks in stream.231// It is forgiving, closer to standard UTF-7 (for example, '-' is optional at the end).232233for (var i = 0; i < buf.length; i++) {234if (!inBase64) { // We're in direct mode.235// Write direct chars until '&'236if (buf[i] == andChar) {237res += this.iconv.decode(buf.slice(lastI, i), "ascii"); // Write direct chars.238lastI = i+1;239inBase64 = true;240}241} else { // We decode base64.242if (!base64IMAPChars[buf[i]]) { // Base64 ended.243if (i == lastI && buf[i] == minusChar) { // "&-" -> "&"244res += "&";245} else {246var b64str = base64Accum + buf.slice(lastI, i).toString().replace(/,/g, '/');247res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be");248}249250if (buf[i] != minusChar) // Minus may be absorbed after base64.251i--;252253lastI = i+1;254inBase64 = false;255base64Accum = '';256}257}258}259260if (!inBase64) {261res += this.iconv.decode(buf.slice(lastI), "ascii"); // Write direct chars.262} else {263var b64str = base64Accum + buf.slice(lastI).toString().replace(/,/g, '/');264265var canBeDecoded = b64str.length - (b64str.length % 8); // Minimal chunk: 2 quads -> 2x3 bytes -> 3 chars.266base64Accum = b64str.slice(canBeDecoded); // The rest will be decoded in future.267b64str = b64str.slice(0, canBeDecoded);268269res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be");270}271272this.inBase64 = inBase64;273this.base64Accum = base64Accum;274275return res;276}277278Utf7IMAPDecoder.prototype.end = function() {279var res = "";280if (this.inBase64 && this.base64Accum.length > 0)281res = this.iconv.decode(new Buffer(this.base64Accum, 'base64'), "utf16-be");282283this.inBase64 = false;284this.base64Accum = '';285return res;286}287288289290291