-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathvalidation.js
143 lines (138 loc) · 4.47 KB
/
validation.js
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'use strict';
const QuestDBMaxFileNameLength = 127;
/**
* Validates a table name. <br>
* Throws an error if table name is invalid.
*
* @param {string} name - The table name to validate.
*/
function validateTableName(name) {
const len = name.length;
if (len > QuestDBMaxFileNameLength) {
throw new Error(`Table name is too long, max length is ${QuestDBMaxFileNameLength}`);
}
if (len === 0) {
throw new Error("Empty string is not allowed as table name");
}
for (let i = 0; i < len; i++) {
let ch = name[i];
switch (ch) {
case '.':
if (i === 0 || i === len - 1 || name[i - 1] === '.')
// single dot is allowed in the middle only
// starting with a dot hides directory in Linux
// ending with a dot can be trimmed by some Windows versions / file systems
// double or triple dot looks suspicious
// single dot allowed as compatibility,
// when someone uploads 'file_name.csv' the file name used as the table name
throw new Error("Table name cannot start or end with a dot and only a single dot allowed");
break;
case '?':
case ',':
case '\'':
case '"':
case '\\':
case '/':
case ':':
case ')':
case '(':
case '+':
case '*':
case '%':
case '~':
case '\u0000':
case '\u0001':
case '\u0002':
case '\u0003':
case '\u0004':
case '\u0005':
case '\u0006':
case '\u0007':
case '\u0008':
case '\u0009': // control characters, except \n.
case '\u000B': // new line allowed for compatibility, there are tests to make sure it works
case '\u000c':
case '\r':
case '\n':
case '\u000e':
case '\u000f':
case '\u007f':
case '\ufeff': // UTF-8 BOM (Byte Order Mark) can appear at the beginning of a character stream
throw new Error(`Invalid character in table name: ${ch}`);
}
}
}
/**
* Validates a column name. <br>
* Throws an error if column name is invalid.
*
* @param {string} name - The column name to validate.
*/
function validateColumnName(name) {
const len = name.length;
if (len > QuestDBMaxFileNameLength) {
throw new Error(`Column name is too long, max length is ${QuestDBMaxFileNameLength}`);
}
if (len === 0) {
throw new Error("Empty string is not allowed as column name");
}
for (const ch of name) {
switch (ch) {
case '?':
case '.':
case ',':
case '\'':
case '"':
case '\\':
case '/':
case ':':
case ')':
case '(':
case '+':
case '-':
case '*':
case '%':
case '~':
case '\u0000':
case '\u0001':
case '\u0002':
case '\u0003':
case '\u0004':
case '\u0005':
case '\u0006':
case '\u0007':
case '\u0008':
case '\u0009': // control characters, except \n
case '\u000B':
case '\u000c':
case '\r':
case '\n':
case '\u000e':
case '\u000f':
case '\u007f':
case '\ufeff': // UTF-8 BOM (Byte Order Mark) can appear at the beginning of a character stream
throw new Error(`Invalid character in column name: ${ch}`);
}
}
}
/**
* Validates a designated timestamp. The value must contain only digits.<br>
* Throws an error if the value is invalid.
*
* @param {string} timestamp - The table name to validate.
*/
function validateDesignatedTimestamp(timestamp) {
const len = timestamp.length;
if (len === 0) {
throw new Error("Empty string is not allowed as designated timestamp");
}
for (let i = 0; i < len; i++) {
let ch = timestamp[i];
if (ch < '0' || ch > '9') {
throw new Error(`Invalid character in designated timestamp: ${ch}`);
}
}
}
exports.validateTableName = validateTableName;
exports.validateColumnName = validateColumnName;
exports.validateDesignatedTimestamp = validateDesignatedTimestamp;