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.

172 lines
4.3 KiB

  1. var jsencoding = require('../deps/encoding/encoding');
  2. var RE_ENCODED = /%([a-fA-F0-9]{2})/g;
  3. function encodedReplacer(match, byte) {
  4. return String.fromCharCode(parseInt(byte, 16));
  5. }
  6. function parseParams(str) {
  7. var res = [],
  8. state = 'key',
  9. charset = '',
  10. inquote = false,
  11. escaping = false,
  12. p = 0,
  13. tmp = '';
  14. for (var i = 0, len = str.length; i < len; ++i) {
  15. if (str[i] === '\\' && inquote) {
  16. if (escaping)
  17. escaping = false;
  18. else {
  19. escaping = true;
  20. continue;
  21. }
  22. } else if (str[i] === '"') {
  23. if (!escaping) {
  24. if (inquote) {
  25. inquote = false;
  26. state = 'key';
  27. } else
  28. inquote = true;
  29. continue;
  30. } else
  31. escaping = false;
  32. } else {
  33. if (escaping && inquote)
  34. tmp += '\\';
  35. escaping = false;
  36. if ((state === 'charset' || state === 'lang') && str[i] === "'") {
  37. if (state === 'charset') {
  38. state = 'lang';
  39. charset = tmp.substring(1);
  40. } else
  41. state = 'value';
  42. tmp = '';
  43. continue;
  44. } else if (state === 'key'
  45. && (str[i] === '*' || str[i] === '=')
  46. && res.length) {
  47. if (str[i] === '*')
  48. state = 'charset';
  49. else
  50. state = 'value';
  51. res[p] = [tmp, undefined];
  52. tmp = '';
  53. continue;
  54. } else if (!inquote && str[i] === ';') {
  55. state = 'key';
  56. if (charset) {
  57. if (tmp.length) {
  58. tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
  59. 'binary',
  60. charset);
  61. }
  62. charset = '';
  63. }
  64. if (res[p] === undefined)
  65. res[p] = tmp;
  66. else
  67. res[p][1] = tmp;
  68. tmp = '';
  69. ++p;
  70. continue;
  71. } else if (!inquote && (str[i] === ' ' || str[i] === '\t'))
  72. continue;
  73. }
  74. tmp += str[i];
  75. }
  76. if (charset && tmp.length) {
  77. tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
  78. 'binary',
  79. charset);
  80. }
  81. if (res[p] === undefined) {
  82. if (tmp)
  83. res[p] = tmp;
  84. } else
  85. res[p][1] = tmp;
  86. return res;
  87. };
  88. exports.parseParams = parseParams;
  89. function decodeText(text, textEncoding, destEncoding) {
  90. var ret;
  91. if (text && jsencoding.encodingExists(destEncoding)) {
  92. try {
  93. ret = jsencoding.TextDecoder(destEncoding)
  94. .decode(Buffer.from(text, textEncoding));
  95. } catch(e) {}
  96. }
  97. return (typeof ret === 'string' ? ret : text);
  98. }
  99. exports.decodeText = decodeText;
  100. var HEX = [
  101. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  102. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  103. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  104. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
  105. 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  106. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  107. 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  108. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  109. ], RE_PLUS = /\+/g;
  110. function Decoder() {
  111. this.buffer = undefined;
  112. }
  113. Decoder.prototype.write = function(str) {
  114. // Replace '+' with ' ' before decoding
  115. str = str.replace(RE_PLUS, ' ');
  116. var res = '';
  117. var i = 0, p = 0, len = str.length;
  118. for (; i < len; ++i) {
  119. if (this.buffer !== undefined) {
  120. if (!HEX[str.charCodeAt(i)]) {
  121. res += '%' + this.buffer;
  122. this.buffer = undefined;
  123. --i; // retry character
  124. } else {
  125. this.buffer += str[i];
  126. ++p;
  127. if (this.buffer.length === 2) {
  128. res += String.fromCharCode(parseInt(this.buffer, 16));
  129. this.buffer = undefined;
  130. }
  131. }
  132. } else if (str[i] === '%') {
  133. if (i > p) {
  134. res += str.substring(p, i);
  135. p = i;
  136. }
  137. this.buffer = '';
  138. ++p;
  139. }
  140. }
  141. if (p < len && this.buffer === undefined)
  142. res += str.substring(p);
  143. return res;
  144. };
  145. Decoder.prototype.reset = function() {
  146. this.buffer = undefined;
  147. };
  148. exports.Decoder = Decoder;
  149. function basename(path) {
  150. if (typeof path !== 'string')
  151. return '';
  152. for (var i = path.length - 1; i >= 0; --i) {
  153. switch (path.charCodeAt(i)) {
  154. case 0x2F: // '/'
  155. case 0x5C: // '\'
  156. path = path.slice(i + 1);
  157. return (path === '..' || path === '.' ? '' : path);
  158. }
  159. }
  160. return (path === '..' || path === '.' ? '' : path);
  161. }
  162. exports.basename = basename;