UNPKG

3.37 kBJavaScriptView Raw
1'use strict';
2
3const { isUtf8 } = require('buffer');
4
5//
6// Allowed token characters:
7//
8// '!', '#', '$', '%', '&', ''', '*', '+', '-',
9// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
10//
11// tokenChars[32] === 0 // ' '
12// tokenChars[33] === 1 // '!'
13// tokenChars[34] === 0 // '"'
14// ...
15//
16// prettier-ignore
17const tokenChars = [
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
20 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
21 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
22 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
23 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
24 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
25 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
26];
27
28/**
29 * Checks if a status code is allowed in a close frame.
30 *
31 * @param {Number} code The status code
32 * @return {Boolean} `true` if the status code is valid, else `false`
33 * @public
34 */
35function isValidStatusCode(code) {
36 return (
37 (code >= 1000 &&
38 code <= 1014 &&
39 code !== 1004 &&
40 code !== 1005 &&
41 code !== 1006) ||
42 (code >= 3000 && code <= 4999)
43 );
44}
45
46/**
47 * Checks if a given buffer contains only correct UTF-8.
48 * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
49 * Markus Kuhn.
50 *
51 * @param {Buffer} buf The buffer to check
52 * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
53 * @public
54 */
55function _isValidUTF8(buf) {
56 const len = buf.length;
57 let i = 0;
58
59 while (i < len) {
60 if ((buf[i] & 0x80) === 0) {
61 // 0xxxxxxx
62 i++;
63 } else if ((buf[i] & 0xe0) === 0xc0) {
64 // 110xxxxx 10xxxxxx
65 if (
66 i + 1 === len ||
67 (buf[i + 1] & 0xc0) !== 0x80 ||
68 (buf[i] & 0xfe) === 0xc0 // Overlong
69 ) {
70 return false;
71 }
72
73 i += 2;
74 } else if ((buf[i] & 0xf0) === 0xe0) {
75 // 1110xxxx 10xxxxxx 10xxxxxx
76 if (
77 i + 2 >= len ||
78 (buf[i + 1] & 0xc0) !== 0x80 ||
79 (buf[i + 2] & 0xc0) !== 0x80 ||
80 (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong
81 (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)
82 ) {
83 return false;
84 }
85
86 i += 3;
87 } else if ((buf[i] & 0xf8) === 0xf0) {
88 // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
89 if (
90 i + 3 >= len ||
91 (buf[i + 1] & 0xc0) !== 0x80 ||
92 (buf[i + 2] & 0xc0) !== 0x80 ||
93 (buf[i + 3] & 0xc0) !== 0x80 ||
94 (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong
95 (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||
96 buf[i] > 0xf4 // > U+10FFFF
97 ) {
98 return false;
99 }
100
101 i += 4;
102 } else {
103 return false;
104 }
105 }
106
107 return true;
108}
109
110module.exports = {
111 isValidStatusCode,
112 isValidUTF8: _isValidUTF8,
113 tokenChars
114};
115
116if (isUtf8) {
117 module.exports.isValidUTF8 = function (buf) {
118 return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
119 };
120} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {
121 try {
122 const isValidUTF8 = require('utf-8-validate');
123
124 module.exports.isValidUTF8 = function (buf) {
125 return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
126 };
127 } catch (e) {
128 // Continue regardless of the error.
129 }
130}