You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							186 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							186 lines
						
					
					
						
							4.9 KiB
						
					
					
				| var jsencoding = require('../deps/encoding/encoding');
 | |
| 
 | |
| var RE_ENCODED = /%([a-fA-F0-9]{2})/g;
 | |
| function encodedReplacer(match, byte) {
 | |
|   return String.fromCharCode(parseInt(byte, 16));
 | |
| }
 | |
| function parseParams(str) {
 | |
|   var res = [],
 | |
|       state = 'key',
 | |
|       charset = '',
 | |
|       inquote = false,
 | |
|       escaping = false,
 | |
|       p = 0,
 | |
|       tmp = '';
 | |
| 
 | |
|   for (var i = 0, len = str.length; i < len; ++i) {
 | |
|     if (str[i] === '\\' && inquote) {
 | |
|       if (escaping)
 | |
|         escaping = false;
 | |
|       else {
 | |
|         escaping = true;
 | |
|         continue;
 | |
|       }
 | |
|     } else if (str[i] === '"') {
 | |
|       if (!escaping) {
 | |
|         if (inquote) {
 | |
|           inquote = false;
 | |
|           state = 'key';
 | |
|         } else
 | |
|           inquote = true;
 | |
|         continue;
 | |
|       } else
 | |
|         escaping = false;
 | |
|     } else {
 | |
|       if (escaping && inquote)
 | |
|         tmp += '\\';
 | |
|       escaping = false;
 | |
|       if ((state === 'charset' || state === 'lang') && str[i] === "'") {
 | |
|         if (state === 'charset') {
 | |
|           state = 'lang';
 | |
|           charset = tmp.substring(1);
 | |
|         } else
 | |
|           state = 'value';
 | |
|         tmp = '';
 | |
|         continue;
 | |
|       } else if (state === 'key'
 | |
|                  && (str[i] === '*' || str[i] === '=')
 | |
|                  && res.length) {
 | |
|         if (str[i] === '*')
 | |
|           state = 'charset';
 | |
|         else
 | |
|           state = 'value';
 | |
|         res[p] = [tmp, undefined];
 | |
|         tmp = '';
 | |
|         continue;
 | |
|       } else if (!inquote && str[i] === ';') {
 | |
|         state = 'key';
 | |
|         if (charset) {
 | |
|           if (tmp.length) {
 | |
|             tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
 | |
|                              'binary',
 | |
|                              charset);
 | |
|           }
 | |
|           charset = '';
 | |
|         }
 | |
|         if (res[p] === undefined)
 | |
|           res[p] = tmp;
 | |
|         else
 | |
|           res[p][1] = tmp;
 | |
|         tmp = '';
 | |
|         ++p;
 | |
|         continue;
 | |
|       } else if (!inquote && (str[i] === ' ' || str[i] === '\t'))
 | |
|         continue;
 | |
|     }
 | |
|     tmp += str[i];
 | |
|   }
 | |
|   if (charset && tmp.length) {
 | |
|     tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
 | |
|                      'binary',
 | |
|                      charset);
 | |
|   }
 | |
| 
 | |
|   if (res[p] === undefined) {
 | |
|     if (tmp)
 | |
|       res[p] = tmp;
 | |
|   } else
 | |
|     res[p][1] = tmp;
 | |
| 
 | |
|   return res;
 | |
| };
 | |
| exports.parseParams = parseParams;
 | |
| 
 | |
| 
 | |
| function decodeText(text, textEncoding, destEncoding) {
 | |
|   var ret;
 | |
|   if (text && jsencoding.encodingExists(destEncoding)) {
 | |
|     try {
 | |
|       ret = jsencoding.TextDecoder(destEncoding)
 | |
|                       .decode(new Buffer(text, textEncoding));
 | |
|     } catch(e) {}
 | |
|   }
 | |
|   return (typeof ret === 'string' ? ret : text);
 | |
| }
 | |
| exports.decodeText = decodeText;
 | |
| 
 | |
| 
 | |
| var HEX = [
 | |
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
 | |
|   0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|   0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | |
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 | |
| ], RE_PLUS = /\+/g;
 | |
| function Decoder() {
 | |
|   this.buffer = undefined;
 | |
| }
 | |
| Decoder.prototype.write = function(str) {
 | |
|   // Replace '+' with ' ' before decoding
 | |
|   str = str.replace(RE_PLUS, ' ');
 | |
|   var res = '';
 | |
|   var i = 0, p = 0, len = str.length;
 | |
|   for (; i < len; ++i) {
 | |
|     if (this.buffer !== undefined) {
 | |
|       if (!HEX[str.charCodeAt(i)]) {
 | |
|         res += '%' + this.buffer;
 | |
|         this.buffer = undefined;
 | |
|         --i; // retry character
 | |
|       } else {
 | |
|         this.buffer += str[i];
 | |
|         ++p;
 | |
|         if (this.buffer.length === 2) {
 | |
|           res += String.fromCharCode(parseInt(this.buffer, 16));
 | |
|           this.buffer = undefined;
 | |
|         }
 | |
|       }
 | |
|     } else if (str[i] === '%') {
 | |
|       if (i > p) {
 | |
|         res += str.substring(p, i);
 | |
|         p = i;
 | |
|       }
 | |
|       this.buffer = '';
 | |
|       ++p;
 | |
|     }
 | |
|   }
 | |
|   if (p < len && this.buffer === undefined)
 | |
|     res += str.substring(p);
 | |
|   return res;
 | |
| };
 | |
| Decoder.prototype.reset = function() {
 | |
|   this.buffer = undefined;
 | |
| };
 | |
| exports.Decoder = Decoder;
 | |
| 
 | |
| 
 | |
| var RE_SPLIT_POSIX =
 | |
|       /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,
 | |
|     RE_SPLIT_DEVICE =
 | |
|       /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/,
 | |
|     RE_SPLIT_WINDOWS =
 | |
|       /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/;
 | |
| function splitPathPosix(filename) {
 | |
|   return RE_SPLIT_POSIX.exec(filename).slice(1);
 | |
| }
 | |
| function splitPathWindows(filename) {
 | |
|   // Separate device+slash from tail
 | |
|   var result = RE_SPLIT_DEVICE.exec(filename),
 | |
|       device = (result[1] || '') + (result[2] || ''),
 | |
|       tail = result[3] || '';
 | |
|   // Split the tail into dir, basename and extension
 | |
|   var result2 = RE_SPLIT_WINDOWS.exec(tail),
 | |
|       dir = result2[1],
 | |
|       basename = result2[2],
 | |
|       ext = result2[3];
 | |
|   return [device, dir, basename, ext];
 | |
| }
 | |
| function basename(path) {
 | |
|   var f = splitPathPosix(path)[2];
 | |
|   if (f === path)
 | |
|     f = splitPathWindows(path)[2];
 | |
|   return f;
 | |
| }
 | |
| exports.basename = basename; |