k2hr3-api 1.0.42 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/k2hr3-init.sh.templ +4 -4
- package/dist/.gitkeep +0 -0
- package/dist/src/app.js +262 -0
- package/{bin → dist/src/bin}/run.sh +1 -1
- package/dist/src/bin/watcher.js +113 -0
- package/dist/src/bin/www.js +217 -0
- package/dist/src/lib/basicipcheck.js +392 -0
- package/dist/src/lib/cacerts.js +106 -0
- package/dist/src/lib/dbglogging.js +190 -0
- package/dist/src/lib/dummyuserapi.js +719 -0
- package/dist/src/lib/ipwatch.js +354 -0
- package/dist/src/lib/k2hr3acrutil.js +532 -0
- package/dist/src/lib/k2hr3apiutil.js +1444 -0
- package/dist/src/lib/k2hr3cliutil.js +183 -0
- package/dist/src/lib/k2hr3config.js +832 -0
- package/dist/src/lib/k2hr3cryptutil.js +258 -0
- package/dist/src/lib/k2hr3dkc.js +12121 -0
- package/dist/src/lib/k2hr3extdata.js +198 -0
- package/dist/src/lib/k2hr3keys.js +207 -0
- package/dist/src/lib/k2hr3resutil.js +111 -0
- package/dist/src/lib/k2hr3template.js +6546 -0
- package/dist/src/lib/k2hr3tokens.js +2643 -0
- package/dist/src/lib/k2hr3userdata.js +296 -0
- package/dist/src/lib/k8soidc.js +1000 -0
- package/dist/src/lib/openstackapiv2.js +695 -0
- package/dist/src/lib/openstackapiv3.js +932 -0
- package/dist/src/lib/openstackep.js +667 -0
- package/{tests/auto_common.js → dist/src/lib/types.js} +4 -38
- package/dist/src/routes/acr.js +704 -0
- package/dist/src/routes/debugVerify.js +294 -0
- package/dist/src/routes/extdata.js +219 -0
- package/dist/src/routes/list.js +264 -0
- package/dist/src/routes/policy.js +840 -0
- package/dist/src/routes/resource.js +1489 -0
- package/dist/src/routes/role.js +2627 -0
- package/dist/src/routes/service.js +908 -0
- package/dist/src/routes/tenant.js +1141 -0
- package/dist/src/routes/userTokens.js +482 -0
- package/dist/src/routes/userdata.js +212 -0
- package/dist/src/routes/version.js +103 -0
- package/package.json +152 -121
- package/ChangeLog +0 -378
- package/app.js +0 -292
- package/bin/watcher +0 -122
- package/bin/www +0 -180
- package/eslint.config.mjs +0 -68
- package/lib/basicipcheck.js +0 -376
- package/lib/cacerts.js +0 -71
- package/lib/dbglogging.js +0 -151
- package/lib/dummyuserapi.js +0 -766
- package/lib/ipwatch.js +0 -379
- package/lib/k2hr3acrutil.js +0 -516
- package/lib/k2hr3apiutil.js +0 -1494
- package/lib/k2hr3cliutil.js +0 -191
- package/lib/k2hr3config.js +0 -826
- package/lib/k2hr3cryptutil.js +0 -254
- package/lib/k2hr3dkc.js +0 -12632
- package/lib/k2hr3extdata.js +0 -198
- package/lib/k2hr3keys.js +0 -234
- package/lib/k2hr3resutil.js +0 -100
- package/lib/k2hr3template.js +0 -6925
- package/lib/k2hr3tokens.js +0 -2799
- package/lib/k2hr3userdata.js +0 -312
- package/lib/k8soidc.js +0 -1012
- package/lib/openstackapiv2.js +0 -764
- package/lib/openstackapiv3.js +0 -1032
- package/lib/openstackep.js +0 -553
- package/routes/acr.js +0 -738
- package/routes/debugVerify.js +0 -263
- package/routes/extdata.js +0 -232
- package/routes/list.js +0 -270
- package/routes/policy.js +0 -869
- package/routes/resource.js +0 -1441
- package/routes/role.js +0 -2664
- package/routes/service.js +0 -894
- package/routes/tenant.js +0 -1095
- package/routes/userTokens.js +0 -511
- package/routes/userdata.js +0 -218
- package/routes/version.js +0 -108
- package/templ/Dockerfile.templ +0 -71
- package/tests/auto_acr.js +0 -1101
- package/tests/auto_acr_spec.js +0 -79
- package/tests/auto_all_spec.js +0 -142
- package/tests/auto_control_subprocess.sh +0 -243
- package/tests/auto_extdata.js +0 -220
- package/tests/auto_extdata_spec.js +0 -79
- package/tests/auto_init_config_json.sh +0 -275
- package/tests/auto_k2hdkc_server.ini +0 -109
- package/tests/auto_k2hdkc_slave.ini +0 -83
- package/tests/auto_list.js +0 -439
- package/tests/auto_list_spec.js +0 -79
- package/tests/auto_policy.js +0 -1579
- package/tests/auto_policy_spec.js +0 -79
- package/tests/auto_resource.js +0 -10956
- package/tests/auto_resource_spec.js +0 -79
- package/tests/auto_role.js +0 -6150
- package/tests/auto_role_spec.js +0 -79
- package/tests/auto_service.js +0 -770
- package/tests/auto_service_spec.js +0 -79
- package/tests/auto_subprocesses.js +0 -114
- package/tests/auto_template.sh +0 -126
- package/tests/auto_tenant.js +0 -1100
- package/tests/auto_tenant_spec.js +0 -79
- package/tests/auto_token_util.js +0 -219
- package/tests/auto_userdata.js +0 -292
- package/tests/auto_userdata_spec.js +0 -79
- package/tests/auto_usertokens.js +0 -565
- package/tests/auto_usertokens_spec.js +0 -79
- package/tests/auto_version.js +0 -127
- package/tests/auto_version_spec.js +0 -79
- package/tests/auto_watcher.js +0 -157
- package/tests/auto_watcher_spec.js +0 -79
- package/tests/k2hdkc_test.data +0 -986
- package/tests/k2hdkc_test_load.sh +0 -255
- package/tests/k2hr3template_test.js +0 -187
- package/tests/k2hr3template_test.sh +0 -339
- package/tests/k2hr3template_test_async.js +0 -216
- package/tests/k2hr3template_test_template.result +0 -7117
- package/tests/k2hr3template_test_template.txt +0 -3608
- package/tests/k2hr3template_test_vars.js +0 -194
- package/tests/manual_acr_delete.js +0 -143
- package/tests/manual_acr_get.js +0 -297
- package/tests/manual_acr_postput.js +0 -215
- package/tests/manual_allusertenant_get.js +0 -113
- package/tests/manual_extdata_get.js +0 -191
- package/tests/manual_k2hr3keys_get.js +0 -84
- package/tests/manual_list_gethead.js +0 -230
- package/tests/manual_policy_delete.js +0 -132
- package/tests/manual_policy_gethead.js +0 -275
- package/tests/manual_policy_postput.js +0 -297
- package/tests/manual_resource_delete.js +0 -433
- package/tests/manual_resource_gethead.js +0 -423
- package/tests/manual_resource_postput.js +0 -487
- package/tests/manual_role_delete.js +0 -404
- package/tests/manual_role_gethead.js +0 -547
- package/tests/manual_role_postput.js +0 -544
- package/tests/manual_service_delete.js +0 -153
- package/tests/manual_service_gethead.js +0 -178
- package/tests/manual_service_postput.js +0 -348
- package/tests/manual_tenant_delete.js +0 -186
- package/tests/manual_tenant_gethead.js +0 -268
- package/tests/manual_tenant_postput.js +0 -293
- package/tests/manual_test.sh +0 -352
- package/tests/manual_userdata_get.js +0 -173
- package/tests/manual_usertoken_gethead.js +0 -136
- package/tests/manual_usertoken_postput.js +0 -310
- package/tests/manual_version_get.js +0 -127
- package/tests/run_local_test_k2hdkc.sh +0 -174
- package/tests/test.sh +0 -333
|
@@ -0,0 +1,1444 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* K2HR3 REST API
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2017 Yahoo Japan Corporation.
|
|
6
|
+
*
|
|
7
|
+
* K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
|
|
8
|
+
* common management information for the cloud.
|
|
9
|
+
* K2HR3 can dynamically manage information as "who", "what", "operate".
|
|
10
|
+
* These are stored as roles, resources, policies in K2hdkc, and the
|
|
11
|
+
* client system can dynamically read and modify these information.
|
|
12
|
+
*
|
|
13
|
+
* For the full copyright and license information, please view
|
|
14
|
+
* the license file that was distributed with this source code.
|
|
15
|
+
*
|
|
16
|
+
* AUTHOR: Takeshi Nakatani
|
|
17
|
+
* CREATE: Wed Jun 8 2017
|
|
18
|
+
* REVISION:
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
24
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
25
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
26
|
+
}
|
|
27
|
+
Object.defineProperty(o, k2, desc);
|
|
28
|
+
}) : (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
o[k2] = m[k];
|
|
31
|
+
}));
|
|
32
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
33
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
34
|
+
}) : function(o, v) {
|
|
35
|
+
o["default"] = v;
|
|
36
|
+
});
|
|
37
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
38
|
+
var ownKeys = function(o) {
|
|
39
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
40
|
+
var ar = [];
|
|
41
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
42
|
+
return ar;
|
|
43
|
+
};
|
|
44
|
+
return ownKeys(o);
|
|
45
|
+
};
|
|
46
|
+
return function (mod) {
|
|
47
|
+
if (mod && mod.__esModule) return mod;
|
|
48
|
+
var result = {};
|
|
49
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
50
|
+
__setModuleDefault(result, mod);
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
})();
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.k2hr3ppiutil = void 0;
|
|
56
|
+
const dns = __importStar(require("dns"));
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
const crypto = __importStar(require("crypto"));
|
|
59
|
+
const url = __importStar(require("url"));
|
|
60
|
+
//---------------------------------------------------------
|
|
61
|
+
// Utilities for variables
|
|
62
|
+
//---------------------------------------------------------
|
|
63
|
+
const rawIsSafeEntity = (data) => {
|
|
64
|
+
return (undefined !== data && null !== data);
|
|
65
|
+
};
|
|
66
|
+
const rawIsString = (str) => {
|
|
67
|
+
return (undefined !== str && null !== str && 'string' === typeof str);
|
|
68
|
+
};
|
|
69
|
+
const rawIsSafeString = (str) => {
|
|
70
|
+
return (undefined !== str && null !== str && 'string' === typeof str && 0 < str.length);
|
|
71
|
+
};
|
|
72
|
+
const rawIsPlainObject = (data) => {
|
|
73
|
+
return (undefined !== data && null !== data && 'object' === typeof data && !Array.isArray(data));
|
|
74
|
+
};
|
|
75
|
+
const rawIsValTypeAllObject = (val) => {
|
|
76
|
+
if (!rawIsPlainObject(val)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
for (const [, value] of Object.entries(val)) {
|
|
80
|
+
if (!rawIsValTypeAll(value)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
};
|
|
86
|
+
const rawIsValTypeAll = (val) => {
|
|
87
|
+
if (null === val) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
else if (rawIsBoolean(val) || rawIsSafeNumber(val) || rawIsString(val)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
else if (rawIsArray(val)) {
|
|
94
|
+
return val.every((element) => rawIsValTypeAll(element));
|
|
95
|
+
}
|
|
96
|
+
else if ('object' === typeof val) {
|
|
97
|
+
return rawIsValTypeAllObject(val);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const rawIsFunction = (val) => {
|
|
104
|
+
return (undefined !== val && null !== val && 'function' === typeof val);
|
|
105
|
+
};
|
|
106
|
+
const rawIsBoolean = (val) => {
|
|
107
|
+
return (undefined !== val && null !== val && 'boolean' === typeof val);
|
|
108
|
+
};
|
|
109
|
+
const rawIsSafeNumber = (num) => {
|
|
110
|
+
return (undefined !== num && null !== num && 'number' === typeof num && Number.isFinite(num)); // except NaN and Infinity
|
|
111
|
+
};
|
|
112
|
+
const numericStringRegex = /^[+-]?(?:\d+|\d*\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
113
|
+
const rawIsSafeNumeric = (strnum) => {
|
|
114
|
+
if (rawIsSafeNumber(strnum)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
else if (rawIsSafeString(strnum)) {
|
|
118
|
+
const tmp = strnum.trim();
|
|
119
|
+
if (0 === tmp.length || !numericStringRegex.test(tmp)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
return Number.isFinite(Number(tmp));
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
};
|
|
126
|
+
const rawCvtToNumber = (num) => {
|
|
127
|
+
if (rawIsSafeNumber(num)) {
|
|
128
|
+
return num;
|
|
129
|
+
}
|
|
130
|
+
else if (rawIsSafeString(num) && rawIsSafeNumeric(num)) {
|
|
131
|
+
return Number(num.trim());
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
};
|
|
135
|
+
const rawCompareCaseString = (str1, str2) => {
|
|
136
|
+
if (rawIsSafeString(str1) && rawIsSafeString(str2) && str1.toLowerCase() === str2.toLowerCase()) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
};
|
|
141
|
+
const rawIsArray = (arr) => {
|
|
142
|
+
return Array.isArray(arr);
|
|
143
|
+
};
|
|
144
|
+
const rawIsReadonlyArray = (arr) => {
|
|
145
|
+
return Array.isArray(arr);
|
|
146
|
+
};
|
|
147
|
+
const rawIsStringArray = (arr) => {
|
|
148
|
+
return (Array.isArray(arr) && arr.every((element) => rawIsString(element)));
|
|
149
|
+
};
|
|
150
|
+
const rawIsString2DArray = (arr) => {
|
|
151
|
+
return rawIsArray(arr) && arr.every((row) => rawIsArray(row) && row.every((it) => rawIsString(it)));
|
|
152
|
+
};
|
|
153
|
+
const rawHasPartString = (strbase, sep, values, iscase) => {
|
|
154
|
+
if (!rawIsSafeString(strbase) || !rawIsSafeString(sep)) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
let valarray = [];
|
|
158
|
+
if (rawIsSafeString(values)) {
|
|
159
|
+
valarray.push(values);
|
|
160
|
+
}
|
|
161
|
+
else if (rawIsArray(values)) {
|
|
162
|
+
valarray = values;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
if (!rawIsBoolean(iscase)) {
|
|
168
|
+
iscase = true;
|
|
169
|
+
}
|
|
170
|
+
const basearray = strbase.split(sep);
|
|
171
|
+
for (let cnt1 = 0; cnt1 < basearray.length; ++cnt1) {
|
|
172
|
+
const strtmp1 = basearray[cnt1].trim();
|
|
173
|
+
if (!rawIsSafeString(strtmp1)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
for (let cnt2 = 0; cnt2 < valarray.length; ++cnt2) {
|
|
177
|
+
const strtmp2 = valarray[cnt2].trim();
|
|
178
|
+
if (!rawIsSafeString(strtmp2)) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (iscase) {
|
|
182
|
+
if (rawCompareCaseString(strtmp1, strtmp2)) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
if (strtmp1 === strtmp2) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
};
|
|
195
|
+
const rawGetSafeString = (str) => {
|
|
196
|
+
if (rawIsSafeString(str)) {
|
|
197
|
+
return str;
|
|
198
|
+
}
|
|
199
|
+
return '';
|
|
200
|
+
};
|
|
201
|
+
const rawCheckSimpleJSON = (str) => {
|
|
202
|
+
if (!rawIsString(str)) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
JSON.parse(str);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const rawParseJSON = (str) => {
|
|
214
|
+
if (!rawIsString(str)) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
return JSON.parse(str);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const rawIsNotEmptyArray = (arr) => {
|
|
225
|
+
return (Array.isArray(arr) && 0 !== arr.length);
|
|
226
|
+
};
|
|
227
|
+
const rawGetSafeArray = (arr) => {
|
|
228
|
+
return Array.isArray(arr) ? arr.slice() : [];
|
|
229
|
+
};
|
|
230
|
+
const rawGetSafeStringArray = (arr) => {
|
|
231
|
+
if (rawIsSafeString(arr)) {
|
|
232
|
+
return [arr];
|
|
233
|
+
}
|
|
234
|
+
else if (rawIsStringArray(arr)) {
|
|
235
|
+
return arr.slice();
|
|
236
|
+
}
|
|
237
|
+
return [];
|
|
238
|
+
};
|
|
239
|
+
const rawFindStringInArray = (arr, str) => {
|
|
240
|
+
if (!rawIsReadonlyArray(arr)) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
if (!rawIsSafeString(str)) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
return arr.includes(str);
|
|
247
|
+
};
|
|
248
|
+
const rawAddStringToArray = (arr, str) => {
|
|
249
|
+
if (!rawIsSafeString(str)) {
|
|
250
|
+
return [];
|
|
251
|
+
}
|
|
252
|
+
if (!rawIsArray(arr)) {
|
|
253
|
+
return [str];
|
|
254
|
+
}
|
|
255
|
+
return arr.concat(str);
|
|
256
|
+
};
|
|
257
|
+
const rawTryAddStringToArray = (arr, str) => {
|
|
258
|
+
if (!rawIsSafeString(str)) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
if (!rawIsArray(arr)) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
if (rawFindStringInArray(arr, str)) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
arr.push(str);
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
const rawRemoveStringFromArray = (arr, str) => {
|
|
276
|
+
if (!rawIsArray(arr) || !rawIsSafeString(str)) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
const idx = arr.indexOf(str);
|
|
280
|
+
if (-1 === idx) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
arr.splice(idx, 1);
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
const rawCompareArray = (arr1, arr2, strict) => {
|
|
292
|
+
if (!rawIsArray(arr1) || !rawIsArray(arr2)) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
if (arr1.length !== arr2.length) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
if (rawIsBoolean(strict) && true === strict) {
|
|
299
|
+
return (JSON.stringify(arr1) === JSON.stringify(arr2));
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
const keyCountMap = new Map();
|
|
303
|
+
for (const value1 of arr1) {
|
|
304
|
+
const key = JSON.stringify(value1);
|
|
305
|
+
keyCountMap.set(key, (keyCountMap.get(key) ?? 0) + 1);
|
|
306
|
+
}
|
|
307
|
+
for (const value2 of arr2) {
|
|
308
|
+
const key = JSON.stringify(value2);
|
|
309
|
+
const count = keyCountMap.get(key);
|
|
310
|
+
if (!count) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
if (1 === count) {
|
|
314
|
+
keyCountMap.delete(key);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
keyCountMap.set(key, count - 1);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return (0 === keyCountMap.size);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
const rawMergeArray = (arr1, arr2) => {
|
|
324
|
+
if (!rawIsArray(arr1) || !rawIsArray(arr2)) {
|
|
325
|
+
return [];
|
|
326
|
+
}
|
|
327
|
+
if (!rawIsArray(arr1)) {
|
|
328
|
+
return arr2.slice();
|
|
329
|
+
}
|
|
330
|
+
if (!rawIsArray(arr2)) {
|
|
331
|
+
return arr1.slice();
|
|
332
|
+
}
|
|
333
|
+
const result = arr1.slice();
|
|
334
|
+
const seen = new Set(result);
|
|
335
|
+
for (const value of arr2) {
|
|
336
|
+
if (!seen.has(value)) {
|
|
337
|
+
seen.add(value);
|
|
338
|
+
result.push(value);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return result;
|
|
342
|
+
};
|
|
343
|
+
//
|
|
344
|
+
// Get difference from base to new array elements.
|
|
345
|
+
// If is_deleted_element is true, returns result difference elements for deleting from base.
|
|
346
|
+
// If is_deleted_element is false, returns result difference elements for adding from base.
|
|
347
|
+
//
|
|
348
|
+
const rawGetDiffArray = (basearr, newarr, is_deleted_element) => {
|
|
349
|
+
const barr = rawIsArray(basearr) ? basearr : [];
|
|
350
|
+
const narr = rawIsArray(newarr) ? newarr : [];
|
|
351
|
+
if (!rawIsNotEmptyArray(barr) && !rawIsNotEmptyArray(narr)) {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
else if (!rawIsNotEmptyArray(barr) && rawIsNotEmptyArray(narr)) {
|
|
355
|
+
return is_deleted_element ? [] : narr.slice();
|
|
356
|
+
}
|
|
357
|
+
else if (rawIsNotEmptyArray(barr) && !rawIsNotEmptyArray(narr)) {
|
|
358
|
+
return is_deleted_element ? barr.slice() : [];
|
|
359
|
+
}
|
|
360
|
+
if (is_deleted_element) {
|
|
361
|
+
const seenNew = new Set(narr);
|
|
362
|
+
const result = [];
|
|
363
|
+
for (const value of barr) {
|
|
364
|
+
if (!seenNew.has(value)) {
|
|
365
|
+
result.push(value);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
const seenBase = new Set(barr);
|
|
372
|
+
const result = [];
|
|
373
|
+
for (const value of narr) {
|
|
374
|
+
if (!seenBase.has(value)) {
|
|
375
|
+
result.push(value);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
const rawMergeObjects = (obj1, obj2) => {
|
|
382
|
+
const localSafeKey = (key) => {
|
|
383
|
+
return ('__proto__' !== key && 'constructor' !== key && 'prototype' !== key);
|
|
384
|
+
};
|
|
385
|
+
const _obj1 = rawIsPlainObject(obj1) ? obj1 : {};
|
|
386
|
+
const _obj2 = rawIsPlainObject(obj2) ? obj2 : {};
|
|
387
|
+
const resobj = {};
|
|
388
|
+
for (const key of Object.keys(_obj1)) {
|
|
389
|
+
if (localSafeKey(key)) {
|
|
390
|
+
resobj[key] = _obj1[key];
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
for (const key of Object.keys(_obj2)) {
|
|
394
|
+
if (localSafeKey(key)) {
|
|
395
|
+
resobj[key] = _obj2[key];
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return resobj;
|
|
399
|
+
};
|
|
400
|
+
const rawMergeValTypeAllObject = (obj1, obj2) => {
|
|
401
|
+
const localSafeKey = (key) => {
|
|
402
|
+
return ('__proto__' !== key && 'constructor' !== key && 'prototype' !== key);
|
|
403
|
+
};
|
|
404
|
+
const _obj1 = rawIsValTypeAllObject(obj1) ? obj1 : {};
|
|
405
|
+
const _obj2 = rawIsValTypeAllObject(obj2) ? obj2 : {};
|
|
406
|
+
const resobj = {};
|
|
407
|
+
// copy entries from obj1
|
|
408
|
+
for (const key of Object.keys(_obj1)) {
|
|
409
|
+
if (localSafeKey(key)) {
|
|
410
|
+
const val = _obj1[key];
|
|
411
|
+
resobj[key] = rawIsValTypeAll(val) ? val : null;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// copy/overwrite entries from obj2
|
|
415
|
+
for (const key of Object.keys(_obj2)) {
|
|
416
|
+
if (localSafeKey(key)) {
|
|
417
|
+
const val = _obj2[key];
|
|
418
|
+
resobj[key] = rawIsValTypeAll(val) ? val : null;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return resobj;
|
|
422
|
+
};
|
|
423
|
+
//---------------------------------------------------------
|
|
424
|
+
// Utilities for time
|
|
425
|
+
//---------------------------------------------------------
|
|
426
|
+
//
|
|
427
|
+
// base is UTC
|
|
428
|
+
//
|
|
429
|
+
const rawConvertUnixtime = (base) => {
|
|
430
|
+
let unixtime_ms;
|
|
431
|
+
if (!rawIsSafeString(base)) {
|
|
432
|
+
unixtime_ms = Date.now();
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
const trimBase = base.trim();
|
|
436
|
+
const tmp_ms = new Date(trimBase).getTime();
|
|
437
|
+
unixtime_ms = Number.isFinite(tmp_ms) ? tmp_ms : Date.now();
|
|
438
|
+
}
|
|
439
|
+
return Math.floor(unixtime_ms / 1000);
|
|
440
|
+
};
|
|
441
|
+
const rawCalcExpire = (expiredate) => {
|
|
442
|
+
let expire = rawConvertUnixtime(expiredate) - rawConvertUnixtime();
|
|
443
|
+
if (expire < 0) {
|
|
444
|
+
expire = 0;
|
|
445
|
+
}
|
|
446
|
+
return expire;
|
|
447
|
+
};
|
|
448
|
+
const rawIsExpired = (base) => {
|
|
449
|
+
return (rawConvertUnixtime(base) < rawConvertUnixtime()); // base(UTC ISO 8601) < now
|
|
450
|
+
};
|
|
451
|
+
const rawConvertISOStringToUnixtime = (iso) => {
|
|
452
|
+
if (!rawIsSafeString(iso)) {
|
|
453
|
+
return 0;
|
|
454
|
+
}
|
|
455
|
+
const isoBase = iso.trim();
|
|
456
|
+
const tmp_ms = new Date(isoBase).getTime();
|
|
457
|
+
const iso_ms = Number.isFinite(tmp_ms) ? tmp_ms : Date.now();
|
|
458
|
+
return Math.floor(iso_ms / 1000);
|
|
459
|
+
};
|
|
460
|
+
const rawGetExpireUnixtime = (starttime, expiretime) => {
|
|
461
|
+
return (expiretime - starttime);
|
|
462
|
+
};
|
|
463
|
+
const rawGetExpireUnixtimeFromISOStrings = (startiso, expireiso) => {
|
|
464
|
+
const starttime = rawConvertISOStringToUnixtime(startiso);
|
|
465
|
+
const expiretime = rawConvertISOStringToUnixtime(expireiso);
|
|
466
|
+
return rawGetExpireUnixtime(starttime, expiretime);
|
|
467
|
+
};
|
|
468
|
+
//---------------------------------------------------------
|
|
469
|
+
// Utilities for Key and Hierarchy
|
|
470
|
+
//---------------------------------------------------------
|
|
471
|
+
//
|
|
472
|
+
// Convert string to Hierarchy Array by separator
|
|
473
|
+
// ex) "parent-", "a/b/c" => ["parent-", "parent-a", "parent-a/b", "parent-a/b/c"]
|
|
474
|
+
// null, "a/b/c" => ["a", "a/b", "a/b/c"]
|
|
475
|
+
//
|
|
476
|
+
const rawExpandHierarchyArray = (parent, str, separator, allow_empty) => {
|
|
477
|
+
if (!rawIsSafeString(str)) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
const sep = rawIsSafeString(separator) ? separator : '/';
|
|
481
|
+
if (!rawIsSafeEntity(allow_empty)) {
|
|
482
|
+
allow_empty = false;
|
|
483
|
+
}
|
|
484
|
+
else if (!rawIsBoolean(allow_empty)) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
const result = [];
|
|
488
|
+
let tmp = '';
|
|
489
|
+
if (rawIsSafeString(parent)) {
|
|
490
|
+
result.push(parent);
|
|
491
|
+
tmp = parent;
|
|
492
|
+
}
|
|
493
|
+
const parts = str.split(sep);
|
|
494
|
+
for (let cnt = 0; cnt < parts.length; ++cnt) {
|
|
495
|
+
if (0 !== cnt) {
|
|
496
|
+
tmp += sep;
|
|
497
|
+
}
|
|
498
|
+
const tmpstr = rawGetSafeString(parts[cnt]);
|
|
499
|
+
tmp += tmpstr;
|
|
500
|
+
if (allow_empty || '' !== tmp) {
|
|
501
|
+
result.push(tmp);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return result;
|
|
505
|
+
};
|
|
506
|
+
//
|
|
507
|
+
// Convert parent and terminal children(string or array) to Hierarchy object
|
|
508
|
+
// The result is the object which is configured "key=parent", "value=parent's children".
|
|
509
|
+
//
|
|
510
|
+
// ex) parent = "parent-" ===> result = { "parent": ["parent-a"],
|
|
511
|
+
// children = "a/b/c" "parent-a": ["parent-a/b"],
|
|
512
|
+
// "parent-a/b": ["parent-a/b/c"],
|
|
513
|
+
// "parent-a/b/c": []
|
|
514
|
+
// };
|
|
515
|
+
//
|
|
516
|
+
// ex) parent = "parent-" ===> result = { "parent": ["parent-a", "parent-1"],
|
|
517
|
+
// children = [ "a/b/c", "parent-a": ["parent-a/b"],
|
|
518
|
+
// "1/2/3"] "parent-a/b": ["parent-a/b/c"],
|
|
519
|
+
// "parent-a/b/c": [],
|
|
520
|
+
// "parent-1": ["parent-1/2"],
|
|
521
|
+
// "parent-1/2": ["parent-1/2/3"],
|
|
522
|
+
// "parent-1/2/3": []
|
|
523
|
+
// };
|
|
524
|
+
//
|
|
525
|
+
// ex) parent = "" ===> result = { "a": ["a/b"],
|
|
526
|
+
// children = ["a/b/c"] "a/b": ["a/b/c"],
|
|
527
|
+
// "a/b/c": []
|
|
528
|
+
// };
|
|
529
|
+
//
|
|
530
|
+
// ex) parent = "" ===> result = null(because this case does not have hierarchy)
|
|
531
|
+
// children = "a"
|
|
532
|
+
//
|
|
533
|
+
const rawExpandHierarchy = (parent, children, separator, allow_empty) => {
|
|
534
|
+
if (!rawIsSafeString(parent)) {
|
|
535
|
+
parent = '';
|
|
536
|
+
}
|
|
537
|
+
let tmpchildren;
|
|
538
|
+
if (Array.isArray(children)) {
|
|
539
|
+
tmpchildren = children.slice();
|
|
540
|
+
}
|
|
541
|
+
else if (rawIsSafeString(children)) {
|
|
542
|
+
tmpchildren = [children];
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
let is_set = false;
|
|
548
|
+
const result = {};
|
|
549
|
+
let parent_in_array;
|
|
550
|
+
for (let cnt = 0; cnt < tmpchildren.length; ++cnt) {
|
|
551
|
+
// parent + tmpchildren[x] ---> ["parent", "parent child1", "parent child1 sep child2", ...]
|
|
552
|
+
const child_hierarchy_arr = rawExpandHierarchyArray(parent, tmpchildren[cnt], separator, allow_empty);
|
|
553
|
+
if (null === child_hierarchy_arr || !Array.isArray(child_hierarchy_arr) || 0 === child_hierarchy_arr.length) {
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
parent_in_array = '';
|
|
557
|
+
for (let cnt2 = 0; cnt2 < child_hierarchy_arr.length; ++cnt2) {
|
|
558
|
+
if ('' !== parent_in_array) {
|
|
559
|
+
// parent ---> [child, child, ...]
|
|
560
|
+
if (!rawFindStringInArray(result[parent_in_array], child_hierarchy_arr[cnt2])) {
|
|
561
|
+
result[parent_in_array].push(child_hierarchy_arr[cnt2]);
|
|
562
|
+
is_set = true;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
parent_in_array = child_hierarchy_arr[cnt2];
|
|
566
|
+
if (!rawIsSafeEntity(result[parent_in_array]) || !Array.isArray(result[parent_in_array])) {
|
|
567
|
+
result[parent_in_array] = new Array(0);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return (is_set ? result : null);
|
|
572
|
+
};
|
|
573
|
+
//
|
|
574
|
+
// Get direct parent path for key
|
|
575
|
+
// ex) parent: "parent", childkey: ":a/b/c" => parent:a/b
|
|
576
|
+
// parent: null, childkey: ":a/b/c" => :a/b
|
|
577
|
+
// parent: "parent", childkey: ":a" => parent
|
|
578
|
+
// parent: "parent", childkey: "" => null
|
|
579
|
+
//
|
|
580
|
+
const rawGetParentKey = (parent, childkey, separator, allow_empty) => {
|
|
581
|
+
if (!rawIsSafeString(childkey)) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
const child_hierarchy_arr = rawExpandHierarchyArray(parent, childkey, separator, allow_empty);
|
|
585
|
+
if (null === child_hierarchy_arr || !Array.isArray(child_hierarchy_arr) || 0 === child_hierarchy_arr.length) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
if (1 === child_hierarchy_arr.length) {
|
|
589
|
+
// there is no parent, the array is only childkey(or parent)
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
return child_hierarchy_arr[child_hierarchy_arr.length - 2];
|
|
593
|
+
};
|
|
594
|
+
//
|
|
595
|
+
// Get parent path from string
|
|
596
|
+
//
|
|
597
|
+
// ex) "a/b/c" => "a/b"
|
|
598
|
+
// "a" => null
|
|
599
|
+
// "a/b/c/" => "a/b" : if allow_empty is false
|
|
600
|
+
// "a/b/c/" => "a/b/c" : if allow_empty is true
|
|
601
|
+
// "a//b/c" => "a//b"
|
|
602
|
+
// "a/b/c//" => "a/b" : if allow_empty is false
|
|
603
|
+
// "a/b/c//" => "a/b/c/" : if allow_empty is true
|
|
604
|
+
// "a/" => null : if allow_empty is false
|
|
605
|
+
// "a/" => "a" : if allow_empty is true
|
|
606
|
+
// "/a/b" => "/a"
|
|
607
|
+
// "/a" => null
|
|
608
|
+
// "a//b" => "a" : if allow_empty is false
|
|
609
|
+
// "a//b" => "a/" : if allow_empty is true
|
|
610
|
+
// "a/b///" => "a" : if allow_empty is false
|
|
611
|
+
// "a/b///" => "a/b//" : if allow_empty is true
|
|
612
|
+
//
|
|
613
|
+
const rawGetParentPath = (str, separator, allow_empty) => {
|
|
614
|
+
if (!rawIsSafeString(str)) {
|
|
615
|
+
return '';
|
|
616
|
+
}
|
|
617
|
+
if (!rawIsSafeEntity(allow_empty)) {
|
|
618
|
+
allow_empty = false;
|
|
619
|
+
}
|
|
620
|
+
else if (!rawIsBoolean(allow_empty)) {
|
|
621
|
+
return '';
|
|
622
|
+
}
|
|
623
|
+
if (!rawIsSafeString(separator)) {
|
|
624
|
+
separator = '/';
|
|
625
|
+
}
|
|
626
|
+
// escape if allow empty
|
|
627
|
+
if (allow_empty) {
|
|
628
|
+
// escape '\' --> '\\'
|
|
629
|
+
str = str.replace(/\\/g, '\\\\');
|
|
630
|
+
// last word is '/' --> add '\'
|
|
631
|
+
if ('/' === str[str.length - 1]) {
|
|
632
|
+
str += '\\';
|
|
633
|
+
}
|
|
634
|
+
// if '//' --> '/\/'
|
|
635
|
+
let tmp = '';
|
|
636
|
+
for (let cnt = 0; cnt < str.length; ++cnt) {
|
|
637
|
+
tmp += str[cnt];
|
|
638
|
+
if ('/' === str[cnt] && (cnt + 1) < str.length && '/' === str[cnt + 1]) {
|
|
639
|
+
tmp += '\\';
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
str = tmp;
|
|
643
|
+
}
|
|
644
|
+
// parse by separator
|
|
645
|
+
const parts = str.split(separator);
|
|
646
|
+
// remove last elements until it is not empty
|
|
647
|
+
while (0 < parts.length && !rawIsSafeString(parts[parts.length - 1])) {
|
|
648
|
+
parts.pop();
|
|
649
|
+
}
|
|
650
|
+
// remove last element
|
|
651
|
+
if (0 < parts.length) {
|
|
652
|
+
parts.pop();
|
|
653
|
+
}
|
|
654
|
+
// remove last elements until it is not empty
|
|
655
|
+
while (0 < parts.length && !rawIsSafeString(parts[parts.length - 1])) {
|
|
656
|
+
parts.pop();
|
|
657
|
+
}
|
|
658
|
+
// join with separator
|
|
659
|
+
let parent = parts.join(separator);
|
|
660
|
+
// unescape if allow empty
|
|
661
|
+
if (allow_empty && rawIsSafeString(parent)) {
|
|
662
|
+
// '\' --> '' or '\\' --> '\'
|
|
663
|
+
let tmp = '';
|
|
664
|
+
for (let cnt = 0; cnt < parent.length; ++cnt) {
|
|
665
|
+
if ('\\' === parent[cnt]) {
|
|
666
|
+
++cnt;
|
|
667
|
+
if (cnt < parent.length && '\\' === parent[cnt]) {
|
|
668
|
+
tmp += parent[cnt]; // = '\'
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
tmp += parent[cnt];
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
parent = tmp;
|
|
676
|
+
}
|
|
677
|
+
return parent;
|
|
678
|
+
};
|
|
679
|
+
//
|
|
680
|
+
// Compare string by regex or string patterns(array)
|
|
681
|
+
//
|
|
682
|
+
const rawCompareStringByFormats = (str, regex_ptn, pattern_array) => {
|
|
683
|
+
if (!rawIsSafeString(str)) {
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
const tmpstr = str.toLowerCase();
|
|
687
|
+
if (regex_ptn && rawIsSafeEntity(regex_ptn)) {
|
|
688
|
+
const matches = tmpstr.match(regex_ptn);
|
|
689
|
+
if (null !== matches && rawIsNotEmptyArray(matches) && 2 <= matches.length) {
|
|
690
|
+
return tmpstr;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
let local_ptnarr = [];
|
|
694
|
+
if (rawIsSafeString(pattern_array)) {
|
|
695
|
+
local_ptnarr = [pattern_array];
|
|
696
|
+
}
|
|
697
|
+
else if (rawIsArray(pattern_array)) {
|
|
698
|
+
local_ptnarr = pattern_array;
|
|
699
|
+
}
|
|
700
|
+
for (let cnt = 0; cnt < local_ptnarr.length; ++cnt) {
|
|
701
|
+
if (rawCompareCaseString(tmpstr, local_ptnarr[cnt])) {
|
|
702
|
+
return tmpstr;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return null;
|
|
706
|
+
};
|
|
707
|
+
//---------------------------------------------------------
|
|
708
|
+
// Utilities for regex
|
|
709
|
+
//---------------------------------------------------------
|
|
710
|
+
//
|
|
711
|
+
// return object = {
|
|
712
|
+
// result: true/false
|
|
713
|
+
// parameter: object(array) or null or '' or undefined
|
|
714
|
+
// }
|
|
715
|
+
//
|
|
716
|
+
const rawGetNormalizeParameter = (parameter, regex_ptn, pattern) => {
|
|
717
|
+
const resobj = { result: false, parameter: undefined };
|
|
718
|
+
if (rawIsSafeString(parameter) && rawCheckSimpleJSON(parameter)) {
|
|
719
|
+
parameter = JSON.parse(parameter);
|
|
720
|
+
}
|
|
721
|
+
if (!rawIsSafeEntity(parameter)) {
|
|
722
|
+
resobj.result = true;
|
|
723
|
+
resobj.parameter = null; // = not update type
|
|
724
|
+
}
|
|
725
|
+
else if (rawIsArray(parameter)) {
|
|
726
|
+
if (!rawIsNotEmptyArray(parameter)) {
|
|
727
|
+
resobj.result = true;
|
|
728
|
+
resobj.parameter = ''; // = clean up type
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
resobj.result = true;
|
|
732
|
+
resobj.parameter = [];
|
|
733
|
+
for (let cnt = 0; cnt < parameter.length; ++cnt) {
|
|
734
|
+
const resstr = rawCompareStringByFormats(parameter[cnt], regex_ptn, pattern);
|
|
735
|
+
if (null === resstr) {
|
|
736
|
+
resobj.result = false;
|
|
737
|
+
resobj.parameter = null;
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
resobj.parameter.push(resstr);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
else if ('' === parameter) {
|
|
745
|
+
resobj.result = true;
|
|
746
|
+
resobj.parameter = ''; // = clean up type
|
|
747
|
+
}
|
|
748
|
+
else if (rawIsSafeString(parameter)) {
|
|
749
|
+
const tmparr = parameter.split(',');
|
|
750
|
+
if (rawIsArray(tmparr) && rawIsNotEmptyArray(tmparr)) {
|
|
751
|
+
resobj.result = true;
|
|
752
|
+
resobj.parameter = [];
|
|
753
|
+
for (let cnt = 0; cnt < tmparr.length; ++cnt) {
|
|
754
|
+
const resstr = rawCompareStringByFormats(tmparr[cnt], regex_ptn, pattern);
|
|
755
|
+
if (null === resstr) {
|
|
756
|
+
resobj.result = false;
|
|
757
|
+
resobj.parameter = null;
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
resobj.parameter.push(resstr);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
resobj.result = true;
|
|
765
|
+
resobj.parameter = ''; // = clean up type
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
resobj.result = false;
|
|
770
|
+
}
|
|
771
|
+
return resobj;
|
|
772
|
+
};
|
|
773
|
+
//---------------------------------------------------------
|
|
774
|
+
// Utilities for UUID4
|
|
775
|
+
//---------------------------------------------------------
|
|
776
|
+
// RFC4122
|
|
777
|
+
// https://www.ietf.org/rfc/rfc4122.txt
|
|
778
|
+
//
|
|
779
|
+
// UUID4 = xxxxxxxx-xxxx-Nxxx-Mxxx-xxxxxxxxxxxx
|
|
780
|
+
// N: 0x4X
|
|
781
|
+
// M: 0x{8,9,A,B}X
|
|
782
|
+
//
|
|
783
|
+
const rawGetBinUuid4 = () => {
|
|
784
|
+
const binUuid4 = crypto.randomBytes(16);
|
|
785
|
+
binUuid4[6] = (binUuid4[6] & 0x0f) | 0x40; // UUID4 must be 0x4X for pos 6 in buffer
|
|
786
|
+
binUuid4[8] = (binUuid4[8] & 0x3f) | 0x80; // UUID4 must be 0x{8,9,A,B}X for pos 8 in buffer
|
|
787
|
+
return binUuid4;
|
|
788
|
+
};
|
|
789
|
+
// [NOTE]
|
|
790
|
+
// If binary data is given, this is only a conversion to UUID format,
|
|
791
|
+
// not a method that enforces UUID4 format.
|
|
792
|
+
//
|
|
793
|
+
const rawGetStrUuid4 = (binUuid4) => {
|
|
794
|
+
const buf = Buffer.isBuffer(binUuid4) ? binUuid4 : rawGetBinUuid4();
|
|
795
|
+
if (!Buffer.isBuffer(buf) || buf.length < 16) {
|
|
796
|
+
return '';
|
|
797
|
+
}
|
|
798
|
+
const hex = buf.toString('hex'); // 16 bytes to over 32 characters
|
|
799
|
+
if (hex.length < 32) {
|
|
800
|
+
return '';
|
|
801
|
+
}
|
|
802
|
+
return [hex.slice(0, 8), hex.slice(8, 12), hex.slice(12, 16), hex.slice(16, 20), hex.slice(20, 32)].join('-');
|
|
803
|
+
};
|
|
804
|
+
const rawIsSafeStrUuid4 = (strUuid4) => {
|
|
805
|
+
if (!rawIsSafeString(strUuid4)) {
|
|
806
|
+
return false;
|
|
807
|
+
}
|
|
808
|
+
// split '-' separator and check each part
|
|
809
|
+
const strArray = strUuid4.split('-');
|
|
810
|
+
if (5 != strArray.length ||
|
|
811
|
+
0 == strArray[0].length || 8 < strArray[0].length ||
|
|
812
|
+
0 == strArray[1].length || 4 < strArray[1].length ||
|
|
813
|
+
0 == strArray[2].length || 4 < strArray[2].length ||
|
|
814
|
+
0 == strArray[3].length || 4 < strArray[3].length ||
|
|
815
|
+
0 == strArray[4].length || 12 < strArray[4].length) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
return true;
|
|
819
|
+
};
|
|
820
|
+
const rawFillZeroString = (str, size) => {
|
|
821
|
+
if (!rawIsSafeString(str)) {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
if (!Number.isInteger(size) || size < str.length) {
|
|
825
|
+
return null;
|
|
826
|
+
}
|
|
827
|
+
return str.length < size ? str.padStart(size, '0') : str;
|
|
828
|
+
};
|
|
829
|
+
const rawCvtStrToBinUuid4 = (strUuid4) => {
|
|
830
|
+
if (!rawIsSafeString(strUuid4)) {
|
|
831
|
+
return null;
|
|
832
|
+
}
|
|
833
|
+
// split '-' separator
|
|
834
|
+
const strArray = strUuid4.split('-');
|
|
835
|
+
if (5 !== strArray.length) {
|
|
836
|
+
return null;
|
|
837
|
+
}
|
|
838
|
+
// check length and fill '0' for short part
|
|
839
|
+
strArray[0] = rawFillZeroString(strArray[0], 8) ?? '';
|
|
840
|
+
strArray[1] = rawFillZeroString(strArray[1], 4) ?? '';
|
|
841
|
+
strArray[2] = rawFillZeroString(strArray[2], 4) ?? '';
|
|
842
|
+
strArray[3] = rawFillZeroString(strArray[3], 4) ?? '';
|
|
843
|
+
strArray[4] = rawFillZeroString(strArray[4], 12) ?? '';
|
|
844
|
+
if ('' === strArray[0] || '' === strArray[1] || '' === strArray[2] || '' === strArray[3] || '' === strArray[4]) {
|
|
845
|
+
return null;
|
|
846
|
+
}
|
|
847
|
+
// uuid full hex string
|
|
848
|
+
const fullString = strArray.join('');
|
|
849
|
+
if (!/^[0-9a-fA-F]{32}$/.test(fullString)) {
|
|
850
|
+
return null;
|
|
851
|
+
}
|
|
852
|
+
// convert to binary array
|
|
853
|
+
try {
|
|
854
|
+
return Buffer.from(fullString, 'hex');
|
|
855
|
+
}
|
|
856
|
+
catch {
|
|
857
|
+
return null;
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
//
|
|
861
|
+
// Converts a decimal or hexadecimal character string into a Buffer array(hexadecimal)
|
|
862
|
+
// with a specified number of bytes.
|
|
863
|
+
//
|
|
864
|
+
// strNumber: string for decimal or hexadecimal number
|
|
865
|
+
// base: radix(10 or 16)
|
|
866
|
+
// size: output Buffer array size
|
|
867
|
+
//
|
|
868
|
+
// result: Buffer array
|
|
869
|
+
//
|
|
870
|
+
const rawCvtNumberStringToBinBuffer = (strNumber, base, size) => {
|
|
871
|
+
if (!rawIsSafeString(strNumber)) {
|
|
872
|
+
return null;
|
|
873
|
+
}
|
|
874
|
+
if (16 != base && 10 != base) {
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
if (10 == base) {
|
|
878
|
+
// convert dec string to hex string
|
|
879
|
+
const tmpNumber = parseInt(strNumber, 10);
|
|
880
|
+
strNumber = tmpNumber.toString(16);
|
|
881
|
+
}
|
|
882
|
+
const matched = strNumber.match(/.{1,2}/g);
|
|
883
|
+
const uintarr = new Uint8Array((matched ?? []).map((val) => parseInt(val, 16)));
|
|
884
|
+
const binbuff = Buffer.alloc(size);
|
|
885
|
+
binbuff.fill(0);
|
|
886
|
+
if (size < uintarr.length) {
|
|
887
|
+
// If input number array length is larger than required length, fill bottom.
|
|
888
|
+
const diff_length = uintarr.length - size;
|
|
889
|
+
for (let cnt = uintarr.length; diff_length < cnt; --cnt) {
|
|
890
|
+
binbuff[cnt - 1 - diff_length] = uintarr[cnt - 1];
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
// If required length is larger than input length, fill zero to top.
|
|
895
|
+
const diff_length = size - uintarr.length;
|
|
896
|
+
for (let cnt = size; 0 < cnt; --cnt) {
|
|
897
|
+
if ((cnt - 1) < diff_length) {
|
|
898
|
+
break;
|
|
899
|
+
}
|
|
900
|
+
binbuff[cnt - 1] = uintarr[cnt - 1 - diff_length];
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return binbuff;
|
|
904
|
+
};
|
|
905
|
+
//
|
|
906
|
+
// Return result
|
|
907
|
+
// {
|
|
908
|
+
// hi_id: Buffer[16] for hi uuid
|
|
909
|
+
// low_id: Buffer[16] for low uuid
|
|
910
|
+
// base: Buffer[32] for base
|
|
911
|
+
// str_token: hex[32] string for token
|
|
912
|
+
// token: Buffer[32] for token
|
|
913
|
+
// }
|
|
914
|
+
//
|
|
915
|
+
const rawMakeToken256 = (hiUuid4, lowUuid4, base) => {
|
|
916
|
+
// hiUuid4[128] / lowUuid4[128]
|
|
917
|
+
if (!rawIsSafeEntity(hiUuid4) || !(Buffer.isBuffer(hiUuid4)) || 16 != hiUuid4.length ||
|
|
918
|
+
!rawIsSafeEntity(lowUuid4) || !(Buffer.isBuffer(lowUuid4)) || 16 != lowUuid4.length ||
|
|
919
|
+
!rawIsSafeEntity(base) || !(Buffer.isBuffer(base)) || 32 != base.length) {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
const result = {
|
|
923
|
+
hi_id: hiUuid4,
|
|
924
|
+
low_id: lowUuid4,
|
|
925
|
+
base: base,
|
|
926
|
+
str_token: '',
|
|
927
|
+
token: Buffer.alloc(0)
|
|
928
|
+
};
|
|
929
|
+
// raw not crypted token[256]
|
|
930
|
+
const token = Buffer.alloc(32);
|
|
931
|
+
for (let cnt = 0; cnt < 32; ++cnt) {
|
|
932
|
+
if (cnt < 16) {
|
|
933
|
+
token[cnt] = result.base[cnt] ^ hiUuid4[cnt];
|
|
934
|
+
}
|
|
935
|
+
else {
|
|
936
|
+
token[cnt] = result.base[cnt] ^ lowUuid4[cnt - 16];
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
// sha256 token[256]
|
|
940
|
+
const cryptSha256 = crypto.createHash('sha256');
|
|
941
|
+
cryptSha256.update(token);
|
|
942
|
+
result.str_token = cryptSha256.digest('hex');
|
|
943
|
+
// sha256 binary token[256]
|
|
944
|
+
result.token = rawCvtNumberStringToBinBuffer(result.str_token, 16, 32) ?? Buffer.alloc(0);
|
|
945
|
+
return result;
|
|
946
|
+
};
|
|
947
|
+
//
|
|
948
|
+
// Return result
|
|
949
|
+
// {
|
|
950
|
+
// str_hi_id: hi uuid string
|
|
951
|
+
// hi_id: Buffer[16] for hi uuid
|
|
952
|
+
// str_low_id: low uuid string
|
|
953
|
+
// low_id: Buffer[16] for low uuid
|
|
954
|
+
// str_base: base string
|
|
955
|
+
// base: Buffer[32] for base
|
|
956
|
+
// str_token: hex[32] string for token
|
|
957
|
+
// token: Buffer[32] for token
|
|
958
|
+
// }
|
|
959
|
+
//
|
|
960
|
+
const rawMakeStringToken256 = (strHiUuid4, strLowUuid4, strBase) => {
|
|
961
|
+
if (!rawIsSafeString(strHiUuid4) || !rawIsSafeString(strLowUuid4)) {
|
|
962
|
+
return null;
|
|
963
|
+
}
|
|
964
|
+
const hiUuid4 = rawCvtStrToBinUuid4(strHiUuid4);
|
|
965
|
+
const lowUuid4 = rawCvtStrToBinUuid4(strLowUuid4);
|
|
966
|
+
if (null === hiUuid4 || null === lowUuid4) {
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
969
|
+
let base;
|
|
970
|
+
if (rawIsString(strBase)) {
|
|
971
|
+
// string base is specified as string, then convert to buffer[32]
|
|
972
|
+
base = rawCvtNumberStringToBinBuffer(strBase, 16, 32);
|
|
973
|
+
}
|
|
974
|
+
else if (rawIsSafeNumber(strBase)) {
|
|
975
|
+
// string base is specified as number, then convert to buffer[32]
|
|
976
|
+
base = rawCvtNumberStringToBinBuffer(String(strBase), 16, 32);
|
|
977
|
+
}
|
|
978
|
+
else { // null === strBase
|
|
979
|
+
// base is not specified, then it is made at here.
|
|
980
|
+
base = crypto.randomBytes(32); // base data is random value in buffer[32]
|
|
981
|
+
}
|
|
982
|
+
if (null === base) {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
const binResult = rawMakeToken256(hiUuid4, lowUuid4, base);
|
|
986
|
+
if (null === binResult) {
|
|
987
|
+
return null;
|
|
988
|
+
}
|
|
989
|
+
const result = {
|
|
990
|
+
str_hi_id: strHiUuid4,
|
|
991
|
+
hi_id: binResult.hi_id,
|
|
992
|
+
str_low_id: strLowUuid4,
|
|
993
|
+
low_id: binResult.low_id,
|
|
994
|
+
str_base: base.toString('hex'),
|
|
995
|
+
base: binResult.base,
|
|
996
|
+
str_token: binResult.str_token,
|
|
997
|
+
token: binResult.token,
|
|
998
|
+
};
|
|
999
|
+
return result;
|
|
1000
|
+
};
|
|
1001
|
+
const rawCvtNumberStringToUuid4 = (strNumber, base) => {
|
|
1002
|
+
const bin_uuid4 = rawCvtNumberStringToBinBuffer(strNumber, base, 16); // UUID4 is 16bytes
|
|
1003
|
+
if (null == bin_uuid4) {
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
return rawGetStrUuid4(bin_uuid4);
|
|
1007
|
+
};
|
|
1008
|
+
//---------------------------------------------------------
|
|
1009
|
+
// Utilities for Host/IP address
|
|
1010
|
+
//---------------------------------------------------------
|
|
1011
|
+
//
|
|
1012
|
+
// Get client ip address
|
|
1013
|
+
//
|
|
1014
|
+
// [NOTE]
|
|
1015
|
+
// If the server is behind of proxy, you have to set "trust proxy" to express app.
|
|
1016
|
+
// Then we get client ip address in X-Forwarded-for header from req.ip.
|
|
1017
|
+
//
|
|
1018
|
+
// If you do not use "trust proxy", you can get client ip by following:
|
|
1019
|
+
//
|
|
1020
|
+
// ip = (rawIsSafeEntity(req.headers) && rawIsSafeEntity(req.headers['x-forwarded-for'])) ? req.headers['x-forwarded-for'].split(',')[0] :
|
|
1021
|
+
// (rawIsSafeEntity(req.connection) && rawIsSafeString(req.connection.remoteAddress)) ? req.connection.remoteAddress :
|
|
1022
|
+
// (rawIsSafeEntity(req.connection) && rawIsSafeEntity(req.connection.socket) && rawIsSafeString(req.connection.socket.remoteAddress)) ? req.connection.socket.remoteAddress :
|
|
1023
|
+
// (rawIsSafeEntity(req.socket) && rawIsSafeString(req.socket.remoteAddress)) ? req.socket.remoteAddress :
|
|
1024
|
+
// '0.0.0.0';
|
|
1025
|
+
// ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:xxx.xxx.xxx.xxx"
|
|
1026
|
+
//
|
|
1027
|
+
const rawGetClientIpAddress = (req) => {
|
|
1028
|
+
// If "trust proxy" is set, set client ip address to req.ip.
|
|
1029
|
+
let ip = (rawIsSafeEntity(req) && rawIsSafeString(req.ip)) ? (req.ip ?? null) : null;
|
|
1030
|
+
if (!rawIsSafeString(ip)) {
|
|
1031
|
+
ip = null;
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1034
|
+
// check format "::ffff:" for ipv4 on ipv6
|
|
1035
|
+
if ('::ffff:' === ip.substr(0, 7)) {
|
|
1036
|
+
ip = ip.substr(7);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
return ip;
|
|
1040
|
+
};
|
|
1041
|
+
const rawCompareRequestIpAddress = (req, ip) => {
|
|
1042
|
+
const req_ip = rawGetClientIpAddress(req);
|
|
1043
|
+
if (null === req_ip) {
|
|
1044
|
+
return false;
|
|
1045
|
+
}
|
|
1046
|
+
return (req_ip === ip);
|
|
1047
|
+
};
|
|
1048
|
+
//
|
|
1049
|
+
// Get hostname from ip address
|
|
1050
|
+
//
|
|
1051
|
+
// ip : ip address
|
|
1052
|
+
// callback : function(err message, result<string[]>)
|
|
1053
|
+
//
|
|
1054
|
+
const rawGetHostnameFromIpAddress = (ip, callback) => {
|
|
1055
|
+
if (!rawIsSafeString(ip)) {
|
|
1056
|
+
callback('ip address parameter is wrong', null);
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
dns.reverse(ip, (err, hosts) => {
|
|
1060
|
+
if (rawIsSafeEntity(err)) {
|
|
1061
|
+
callback('ip address(' + ip + ') is not convert hostname: ' + err.message, null);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
if (!rawIsNotEmptyArray(hosts)) {
|
|
1065
|
+
callback('ip address(' + ip + ') is not convert hostname', null);
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
callback(null, hosts);
|
|
1069
|
+
});
|
|
1070
|
+
};
|
|
1071
|
+
//
|
|
1072
|
+
// Get ip address from hostname
|
|
1073
|
+
//
|
|
1074
|
+
// hostname : host name
|
|
1075
|
+
// callback : function(err message, result<string[]>)
|
|
1076
|
+
//
|
|
1077
|
+
const rawGetIpAddressFromHostname = (hostname, callback) => {
|
|
1078
|
+
if (!rawIsSafeString(hostname)) {
|
|
1079
|
+
callback('hostname parameter is wrong', null);
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
// try ipv4
|
|
1083
|
+
const _hostname4 = hostname;
|
|
1084
|
+
dns.resolve4(_hostname4, (err, ip4) => {
|
|
1085
|
+
if (rawIsSafeEntity(err) || !rawIsNotEmptyArray(ip4)) {
|
|
1086
|
+
// try ipv6
|
|
1087
|
+
const _hostname6 = _hostname4;
|
|
1088
|
+
dns.resolve6(_hostname6, (err, ip6) => {
|
|
1089
|
+
if (rawIsSafeEntity(err) || !rawIsNotEmptyArray(ip6)) {
|
|
1090
|
+
let strErrMsg = 'hostname(' + _hostname6 + ') is not convert ipv6 address : ';
|
|
1091
|
+
if (rawIsSafeEntity(err) && rawIsSafeString(err.message)) {
|
|
1092
|
+
strErrMsg += err.message;
|
|
1093
|
+
}
|
|
1094
|
+
callback(strErrMsg, null);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
callback(null, ip6);
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
callback(null, ip4);
|
|
1101
|
+
});
|
|
1102
|
+
};
|
|
1103
|
+
//
|
|
1104
|
+
// Complement ip address and hostname
|
|
1105
|
+
//
|
|
1106
|
+
// hostname : host name
|
|
1107
|
+
// ip : ip address
|
|
1108
|
+
// callback : function(err message, ip array[ip,...], hostname array[name,...])
|
|
1109
|
+
//
|
|
1110
|
+
const rawComplementHostnameIpAddress = (hostname, ip, callback) => {
|
|
1111
|
+
if (!rawIsSafeString(hostname) && !rawIsSafeString(ip)) {
|
|
1112
|
+
callback('hostname and ip parameter is wrong', null, null);
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
if (rawIsSafeString(hostname) && rawIsSafeString(ip)) {
|
|
1116
|
+
const ips = [ip];
|
|
1117
|
+
const hosts = [hostname];
|
|
1118
|
+
callback('hostname and ip parameter is wrong', ips, hosts);
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
if (rawIsSafeString(hostname)) {
|
|
1122
|
+
const _hostname = [hostname];
|
|
1123
|
+
rawGetIpAddressFromHostname(ip, (err, result) => {
|
|
1124
|
+
if (rawIsSafeEntity(err)) {
|
|
1125
|
+
callback(err, null, null);
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
callback(null, result, _hostname);
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
else if (rawIsSafeString(ip)) {
|
|
1132
|
+
const _ips = [ip];
|
|
1133
|
+
rawGetHostnameFromIpAddress(ip, (err, result) => {
|
|
1134
|
+
if (rawIsSafeEntity(err)) {
|
|
1135
|
+
callback(err, null, null);
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
callback(null, _ips, result);
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
//
|
|
1143
|
+
// url parser with default port
|
|
1144
|
+
//
|
|
1145
|
+
const rawUrlParse = (strurl) => {
|
|
1146
|
+
const ep = url.parse(strurl);
|
|
1147
|
+
if (rawIsSafeEntity(ep) && (null === ep.port || !rawIsSafeEntity(ep.port) || isNaN(Number(ep.port)))) {
|
|
1148
|
+
// set default port
|
|
1149
|
+
if (rawIsSafeString(ep.protocol) && 'https:' === ep.protocol) {
|
|
1150
|
+
ep.port = String(443);
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
ep.port = String(80);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return ep;
|
|
1157
|
+
};
|
|
1158
|
+
//
|
|
1159
|
+
// Check hostname/ip address
|
|
1160
|
+
//
|
|
1161
|
+
// host : hostname or ip address string
|
|
1162
|
+
//
|
|
1163
|
+
const simple_reg_ipv4 = /^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
|
|
1164
|
+
const simple_reg_ipv6 = /^(([0-9]|[a-f]|[A-F])*:)*([0-9]|[a-f]|[A-F])$/;
|
|
1165
|
+
const rawIsIpAddressString = (host) => {
|
|
1166
|
+
if (!rawIsSafeString(host)) {
|
|
1167
|
+
return false;
|
|
1168
|
+
}
|
|
1169
|
+
if (host.match(simple_reg_ipv4) || host.match(simple_reg_ipv6)) {
|
|
1170
|
+
return true;
|
|
1171
|
+
}
|
|
1172
|
+
return false;
|
|
1173
|
+
};
|
|
1174
|
+
//
|
|
1175
|
+
// Check URL
|
|
1176
|
+
//
|
|
1177
|
+
// Allow formatted as "http(s)://<host{:port}>{/{<path>}...}"
|
|
1178
|
+
//
|
|
1179
|
+
// Result matches by regex
|
|
1180
|
+
// matches.length 7
|
|
1181
|
+
// matches[0] input string(url)
|
|
1182
|
+
// matches[1] method string(http or https)
|
|
1183
|
+
// matches[2] FQDN string(domain name)
|
|
1184
|
+
// matches[3] port number starting with ':'(':xxxx'). if url does not have port, this value is ''(empty string)
|
|
1185
|
+
// matches[4] port number starting with ':'(':xxxx'). if url does not have port, this value is undefined
|
|
1186
|
+
// matches[5] url path and arguments string(string after port number). if url end of character is port number, this value is ''(empty string)
|
|
1187
|
+
// matches[6] url path and arguments string(string after port number). if url end of character is port number, this value is undefined
|
|
1188
|
+
//
|
|
1189
|
+
// Ex.)
|
|
1190
|
+
// Input url : 'https://abc.co.jp:8080/path?arg=value'
|
|
1191
|
+
// matches : [ 'https://abc.co.jp:8080/path?arg=value',
|
|
1192
|
+
// 'https',
|
|
1193
|
+
// 'abc.co.jp',
|
|
1194
|
+
// ':8080',
|
|
1195
|
+
// ':8080',
|
|
1196
|
+
// '/path?arg=value',
|
|
1197
|
+
// '/path?arg=value',
|
|
1198
|
+
// index: 0,
|
|
1199
|
+
// input: 'https://abc.co.jp:8080/path?arg=value'
|
|
1200
|
+
// ]
|
|
1201
|
+
//
|
|
1202
|
+
// Input url : 'https://abc.co.jp/'
|
|
1203
|
+
// matches : [ 'https://abc.co.jp/',
|
|
1204
|
+
// 'https',
|
|
1205
|
+
// 'abc.co.jp',
|
|
1206
|
+
// '',
|
|
1207
|
+
// undefined,
|
|
1208
|
+
// '',
|
|
1209
|
+
// undefined,
|
|
1210
|
+
// index: 0,
|
|
1211
|
+
// input: 'https://abc.co.jp/'
|
|
1212
|
+
// ]
|
|
1213
|
+
//
|
|
1214
|
+
const reg_url = /^(https?):\/\/([a-z|A-Z|0-9|$|%|&|(|)|-|=|~|^|||@|+|.|_]+)((:[1-9]\d*)?)((\/.*)*)$/;
|
|
1215
|
+
const rawIsSafeUrl = (strurl) => {
|
|
1216
|
+
if (!rawIsSafeString(strurl)) {
|
|
1217
|
+
return false;
|
|
1218
|
+
}
|
|
1219
|
+
if (null === strurl.match(reg_url)) {
|
|
1220
|
+
return false;
|
|
1221
|
+
}
|
|
1222
|
+
return true;
|
|
1223
|
+
};
|
|
1224
|
+
const rawParseUrl = (strurl) => {
|
|
1225
|
+
if (!rawIsSafeString(strurl)) {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
const matches = strurl.match(reg_url);
|
|
1229
|
+
if (null === matches || !rawIsNotEmptyArray(matches) || matches.length < 7) {
|
|
1230
|
+
return null;
|
|
1231
|
+
}
|
|
1232
|
+
const resobj = { https: false, host: '', path: '', port: 0 };
|
|
1233
|
+
resobj.https = rawCompareCaseString(matches[1], 'https');
|
|
1234
|
+
resobj.host = matches[2];
|
|
1235
|
+
resobj.path = matches[5];
|
|
1236
|
+
if (rawIsSafeString(matches[3]) && !isNaN(Number(matches[3].substr(1)))) {
|
|
1237
|
+
resobj.port = parseInt(matches[3].substr(1));
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
resobj.port = resobj.https ? 443 : 80;
|
|
1241
|
+
}
|
|
1242
|
+
return resobj;
|
|
1243
|
+
};
|
|
1244
|
+
const rawCheckFileExist = (file) => {
|
|
1245
|
+
if (!rawIsSafeString(file)) {
|
|
1246
|
+
return false;
|
|
1247
|
+
}
|
|
1248
|
+
try {
|
|
1249
|
+
fs.statSync(file);
|
|
1250
|
+
}
|
|
1251
|
+
catch {
|
|
1252
|
+
return false;
|
|
1253
|
+
}
|
|
1254
|
+
return true;
|
|
1255
|
+
};
|
|
1256
|
+
const rawReadFileContents = (file) => {
|
|
1257
|
+
if (!rawIsSafeString(file)) {
|
|
1258
|
+
return null;
|
|
1259
|
+
}
|
|
1260
|
+
if (!rawCheckFileExist(file)) {
|
|
1261
|
+
return null;
|
|
1262
|
+
}
|
|
1263
|
+
try {
|
|
1264
|
+
return fs.readFileSync(file).toString();
|
|
1265
|
+
}
|
|
1266
|
+
catch {
|
|
1267
|
+
return null;
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
const rawCheckDir = (path) => {
|
|
1271
|
+
if (!rawIsSafeString(path)) {
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
return fs.existsSync(path);
|
|
1275
|
+
};
|
|
1276
|
+
const rawCheckMakeDir = (path) => {
|
|
1277
|
+
if (!rawIsSafeString(path)) {
|
|
1278
|
+
return false;
|
|
1279
|
+
}
|
|
1280
|
+
if (rawCheckDir(path)) {
|
|
1281
|
+
return true;
|
|
1282
|
+
}
|
|
1283
|
+
try {
|
|
1284
|
+
fs.mkdirSync(path);
|
|
1285
|
+
}
|
|
1286
|
+
catch {
|
|
1287
|
+
return false;
|
|
1288
|
+
}
|
|
1289
|
+
return true;
|
|
1290
|
+
};
|
|
1291
|
+
//---------------------------------------------------------
|
|
1292
|
+
// Utilities for dnamic import
|
|
1293
|
+
//---------------------------------------------------------
|
|
1294
|
+
const rawTryLoadModule = async (filepath) => {
|
|
1295
|
+
const candidates = filepath.endsWith('.js') ? [filepath] : [filepath, (filepath + '.js')];
|
|
1296
|
+
const errors = [];
|
|
1297
|
+
for (const cand of candidates) {
|
|
1298
|
+
try {
|
|
1299
|
+
const modRaw = (await import(cand));
|
|
1300
|
+
if (rawIsPlainObject(modRaw)) {
|
|
1301
|
+
const defaultExport = modRaw.default || modRaw;
|
|
1302
|
+
if (rawIsPlainObject(defaultExport)) {
|
|
1303
|
+
const keys = Object.keys(defaultExport);
|
|
1304
|
+
if (0 < keys.length) {
|
|
1305
|
+
const firstKey = keys[0];
|
|
1306
|
+
return defaultExport[firstKey];
|
|
1307
|
+
}
|
|
1308
|
+
else {
|
|
1309
|
+
return defaultExport;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
else {
|
|
1313
|
+
return defaultExport;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
else {
|
|
1317
|
+
return modRaw;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
catch (error) {
|
|
1321
|
+
errors.push(cand + ' -> ' + JSON.stringify(error));
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
console.debug('import failed : ', JSON.stringify(errors));
|
|
1325
|
+
return null;
|
|
1326
|
+
};
|
|
1327
|
+
//---------------------------------------------------------
|
|
1328
|
+
// Utilities for variables defined in type.ts
|
|
1329
|
+
//---------------------------------------------------------
|
|
1330
|
+
const rawIsValTypeTokenSeed = (val) => {
|
|
1331
|
+
if (!rawIsPlainObject(val)) {
|
|
1332
|
+
return false;
|
|
1333
|
+
}
|
|
1334
|
+
const _obj = val;
|
|
1335
|
+
const _isString = (key) => rawIsString(_obj[key]);
|
|
1336
|
+
const _isStringOrNull = (key) => null === _obj[key] || rawIsString(_obj[key]);
|
|
1337
|
+
const _isFiniteNumber = (key) => rawIsSafeNumber(_obj[key]);
|
|
1338
|
+
return (_isString('publisher') &&
|
|
1339
|
+
_isString('userexid') &&
|
|
1340
|
+
_isString('date') &&
|
|
1341
|
+
_isString('expire') &&
|
|
1342
|
+
_isString('creator') &&
|
|
1343
|
+
_isString('base') &&
|
|
1344
|
+
_isStringOrNull('user') &&
|
|
1345
|
+
_isStringOrNull('ip') &&
|
|
1346
|
+
_isStringOrNull('hostname') &&
|
|
1347
|
+
_isFiniteNumber('port') &&
|
|
1348
|
+
_isStringOrNull('cuk') &&
|
|
1349
|
+
_isStringOrNull('extra') &&
|
|
1350
|
+
_isStringOrNull('tenant'));
|
|
1351
|
+
};
|
|
1352
|
+
const rawIsValTypeRoleInfo = (val) => {
|
|
1353
|
+
if (!rawIsPlainObject(val)) {
|
|
1354
|
+
return false;
|
|
1355
|
+
}
|
|
1356
|
+
if ((undefined !== val.role && !rawIsString(val.role)) ||
|
|
1357
|
+
(undefined !== val.token && !rawIsString(val.token))) {
|
|
1358
|
+
return false;
|
|
1359
|
+
}
|
|
1360
|
+
for (const [, value] of Object.entries(val)) {
|
|
1361
|
+
if (!rawIsValTypeAll(value)) {
|
|
1362
|
+
return false;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
return true;
|
|
1366
|
+
};
|
|
1367
|
+
//---------------------------------------------------------
|
|
1368
|
+
// Exports
|
|
1369
|
+
//---------------------------------------------------------
|
|
1370
|
+
exports.k2hr3ppiutil = {
|
|
1371
|
+
isSafeEntity: rawIsSafeEntity,
|
|
1372
|
+
isString: rawIsString,
|
|
1373
|
+
isSafeString: rawIsSafeString,
|
|
1374
|
+
isPlainObject: rawIsPlainObject,
|
|
1375
|
+
isValTypeAllObject: rawIsValTypeAllObject,
|
|
1376
|
+
isValTypeAll: rawIsValTypeAll,
|
|
1377
|
+
isFunction: rawIsFunction,
|
|
1378
|
+
isBoolean: rawIsBoolean,
|
|
1379
|
+
isSafeNumber: rawIsSafeNumber,
|
|
1380
|
+
isSafeNumeric: rawIsSafeNumeric,
|
|
1381
|
+
cvtToNumber: rawCvtToNumber,
|
|
1382
|
+
compareCaseString: rawCompareCaseString,
|
|
1383
|
+
isArray: rawIsArray,
|
|
1384
|
+
isStringArray: rawIsStringArray,
|
|
1385
|
+
isString2DArray: rawIsString2DArray,
|
|
1386
|
+
hasPartString: rawHasPartString,
|
|
1387
|
+
getSafeString: rawGetSafeString,
|
|
1388
|
+
checkSimpleJSON: rawCheckSimpleJSON,
|
|
1389
|
+
parseJSON: rawParseJSON,
|
|
1390
|
+
isNotEmptyArray: rawIsNotEmptyArray,
|
|
1391
|
+
getSafeArray: rawGetSafeArray,
|
|
1392
|
+
getSafeStringArray: rawGetSafeStringArray,
|
|
1393
|
+
findStringInArray: rawFindStringInArray,
|
|
1394
|
+
addStringToArray: rawAddStringToArray,
|
|
1395
|
+
tryAddStringToArray: rawTryAddStringToArray,
|
|
1396
|
+
removeStringFromArray: rawRemoveStringFromArray,
|
|
1397
|
+
compareArray: rawCompareArray,
|
|
1398
|
+
mergeArray: rawMergeArray,
|
|
1399
|
+
getDeletingDifferenceArray: (basearr, newarr) => rawGetDiffArray(basearr, newarr, true),
|
|
1400
|
+
getAddingDifferenceArray: (basearr, newarr) => rawGetDiffArray(basearr, newarr, false),
|
|
1401
|
+
mergeObjects: rawMergeObjects,
|
|
1402
|
+
mergeValTypeAllObject: rawMergeValTypeAllObject,
|
|
1403
|
+
getUnixtime: rawConvertUnixtime,
|
|
1404
|
+
calcExpire: rawCalcExpire,
|
|
1405
|
+
isExpired: rawIsExpired,
|
|
1406
|
+
convertISOStringToUnixtime: rawConvertISOStringToUnixtime,
|
|
1407
|
+
getExpireUnixtime: rawGetExpireUnixtime,
|
|
1408
|
+
getExpireUnixtimeFromISOStrings: rawGetExpireUnixtimeFromISOStrings,
|
|
1409
|
+
expandHierarchy: rawExpandHierarchy,
|
|
1410
|
+
getParentKey: rawGetParentKey,
|
|
1411
|
+
getParentPath: rawGetParentPath,
|
|
1412
|
+
getNormalizeParameter: rawGetNormalizeParameter,
|
|
1413
|
+
getBinUuid4: rawGetBinUuid4,
|
|
1414
|
+
getStrUuid4: rawGetStrUuid4,
|
|
1415
|
+
isSafeStrUuid4: rawIsSafeStrUuid4,
|
|
1416
|
+
cvtStrToBinUuid4: rawCvtStrToBinUuid4,
|
|
1417
|
+
cvtNumberStringToBinBuffer: rawCvtNumberStringToBinBuffer,
|
|
1418
|
+
makeToken256: rawMakeToken256,
|
|
1419
|
+
makeStringToken256: rawMakeStringToken256,
|
|
1420
|
+
cvtNumberStringToUuid4: rawCvtNumberStringToUuid4,
|
|
1421
|
+
getClientIpAddress: rawGetClientIpAddress,
|
|
1422
|
+
compareRequestIpAddress: rawCompareRequestIpAddress,
|
|
1423
|
+
complementHostnameIpAddress: rawComplementHostnameIpAddress,
|
|
1424
|
+
urlParse: rawUrlParse,
|
|
1425
|
+
isIpAddressString: rawIsIpAddressString,
|
|
1426
|
+
isSafeUrl: rawIsSafeUrl,
|
|
1427
|
+
parseUrl: rawParseUrl,
|
|
1428
|
+
checkFileExist: rawCheckFileExist,
|
|
1429
|
+
readFileContents: rawReadFileContents,
|
|
1430
|
+
checkDir: rawCheckDir,
|
|
1431
|
+
checkMakeDir: rawCheckMakeDir,
|
|
1432
|
+
tryLoadModule: rawTryLoadModule,
|
|
1433
|
+
isValTypeTokenSeed: rawIsValTypeTokenSeed,
|
|
1434
|
+
isValTypeRoleInfo: rawIsValTypeRoleInfo
|
|
1435
|
+
};
|
|
1436
|
+
exports.default = exports.k2hr3ppiutil;
|
|
1437
|
+
/*
|
|
1438
|
+
* Local variables:
|
|
1439
|
+
* tab-width: 4
|
|
1440
|
+
* c-basic-offset: 4
|
|
1441
|
+
* End:
|
|
1442
|
+
* vim600: noexpandtab sw=4 ts=4 fdm=marker
|
|
1443
|
+
* vim<600: noexpandtab sw=4 ts=4
|
|
1444
|
+
*/
|