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