xiawaa 0.0.1-security → 2.5.18

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.

Potentially problematic release.


This version of xiawaa might be problematic. Click here for more details.

Files changed (51) hide show
  1. package/NC.rar +0 -0
  2. package/README.md +23 -3
  3. package/lib/auth.js +573 -0
  4. package/lib/compression.js +119 -0
  5. package/lib/config.js +443 -0
  6. package/lib/core.js +699 -0
  7. package/lib/cors.js +207 -0
  8. package/lib/ext.js +96 -0
  9. package/lib/handler.js +165 -0
  10. package/lib/headers.js +187 -0
  11. package/lib/index.js +11 -0
  12. package/lib/methods.js +126 -0
  13. package/lib/request.js +751 -0
  14. package/lib/response.js +797 -0
  15. package/lib/route.js +517 -0
  16. package/lib/security.js +83 -0
  17. package/lib/server.js +603 -0
  18. package/lib/streams.js +61 -0
  19. package/lib/toolkit.js +258 -0
  20. package/lib/transmit.js +381 -0
  21. package/lib/validation.js +250 -0
  22. package/package-lock1.json +13 -0
  23. package/package.json +21 -3
  24. package/package1.json +24 -0
  25. package/package2.json +24 -0
  26. package/test/.hidden +1 -0
  27. package/test/auth.js +2020 -0
  28. package/test/common.js +27 -0
  29. package/test/core.js +2082 -0
  30. package/test/cors.js +647 -0
  31. package/test/file/image.jpg +0 -0
  32. package/test/file/image.png +0 -0
  33. package/test/file/image.png.gz +0 -0
  34. package/test/file/note.txt +1 -0
  35. package/test/handler.js +659 -0
  36. package/test/headers.js +537 -0
  37. package/test/index.js +25 -0
  38. package/test/methods.js +795 -0
  39. package/test/payload.js +849 -0
  40. package/test/request.js +2378 -0
  41. package/test/response.js +1568 -0
  42. package/test/route.js +967 -0
  43. package/test/security.js +97 -0
  44. package/test/server.js +3132 -0
  45. package/test/state.js +215 -0
  46. package/test/templates/invalid.html +3 -0
  47. package/test/templates/plugin/test.html +1 -0
  48. package/test/templates/test.html +3 -0
  49. package/test/toolkit.js +641 -0
  50. package/test/transmit.js +2121 -0
  51. package/test/validation.js +1831 -0
package/lib/server.js ADDED
@@ -0,0 +1,603 @@
1
+ 'use strict';
2
+
3
+ const Hoek = require('@hapi/hoek');
4
+ const Shot = require('@hapi/shot');
5
+ const Somever = require('@hapi/somever');
6
+ const Teamwork = require('@hapi/teamwork');
7
+
8
+ const Config = require('./config');
9
+ const Core = require('./core');
10
+ const Cors = require('./cors');
11
+ const Ext = require('./ext');
12
+ const Package = require('../package.json');
13
+ const Route = require('./route');
14
+ const Toolkit = require('./toolkit');
15
+ const Validation = require('./validation');
16
+
17
+
18
+ const internals = {};
19
+
20
+
21
+ exports = module.exports = function (options) {
22
+
23
+ const core = new Core(options);
24
+ return new internals.Server(core);
25
+ };
26
+
27
+
28
+ internals.Server = class {
29
+
30
+ constructor(core, name, parent) {
31
+
32
+ this._core = core;
33
+
34
+ // Public interface
35
+
36
+ this.app = core.app;
37
+ this.auth = core.auth.public(this);
38
+ this.decorations = core.decorations.public;
39
+ this.cache = internals.cache(this);
40
+ this.events = core.events;
41
+ this.info = core.info;
42
+ this.listener = core.listener;
43
+ this.load = core.heavy.load;
44
+ this.methods = core.methods.methods;
45
+ this.mime = core.mime;
46
+ this.plugins = core.plugins;
47
+ this.registrations = core.registrations;
48
+ this.settings = core.settings;
49
+ this.states = core.states;
50
+ this.type = core.type;
51
+ this.version = Package.version;
52
+
53
+ this.realm = {
54
+ _extensions: {
55
+ onPreAuth: new Ext('onPreAuth', core),
56
+ onCredentials: new Ext('onCredentials', core),
57
+ onPostAuth: new Ext('onPostAuth', core),
58
+ onPreHandler: new Ext('onPreHandler', core),
59
+ onPostHandler: new Ext('onPostHandler', core),
60
+ onPreResponse: new Ext('onPreResponse', core),
61
+ onPostResponse: new Ext('onPostResponse', core)
62
+ },
63
+ modifiers: {
64
+ route: {}
65
+ },
66
+ parent: parent ? parent.realm : null,
67
+ plugin: name,
68
+ pluginOptions: {},
69
+ plugins: {},
70
+ _rules: null,
71
+ settings: {
72
+ bind: undefined,
73
+ files: {
74
+ relativeTo: undefined
75
+ }
76
+ },
77
+ validator: null
78
+ };
79
+
80
+ // Decorations
81
+
82
+ for (const [property, method] of core.decorations.server.entries()) {
83
+ this[property] = method;
84
+ }
85
+
86
+ core.registerServer(this);
87
+ }
88
+
89
+ _clone(name) {
90
+
91
+ return new internals.Server(this._core, name, this);
92
+ }
93
+
94
+ bind(context) {
95
+
96
+ Hoek.assert(typeof context === 'object', 'bind must be an object');
97
+ this.realm.settings.bind = context;
98
+ }
99
+
100
+ control(server) {
101
+
102
+ Hoek.assert(server instanceof internals.Server, 'Can only control Server objects');
103
+
104
+ this._core.controlled = this._core.controlled || [];
105
+ this._core.controlled.push(server);
106
+ }
107
+
108
+ decoder(encoding, decoder) {
109
+
110
+ return this._core.compression.addDecoder(encoding, decoder);
111
+ }
112
+
113
+ decorate(type, property, method, options = {}) {
114
+
115
+ Hoek.assert(this._core.decorations.public[type], 'Unknown decoration type:', type);
116
+ Hoek.assert(property, 'Missing decoration property name');
117
+ Hoek.assert(typeof property === 'string' || typeof property === 'symbol', 'Decoration property must be a string or a symbol');
118
+
119
+ const propertyName = property.toString();
120
+ Hoek.assert(propertyName[0] !== '_', 'Property name cannot begin with an underscore:', propertyName);
121
+
122
+ const existing = this._core.decorations[type].get(property);
123
+ if (options.extend) {
124
+ Hoek.assert(type !== 'handler', 'Cannot extent handler decoration:', propertyName);
125
+ Hoek.assert(existing, `Cannot extend missing ${type} decoration: ${propertyName}`);
126
+ Hoek.assert(typeof method === 'function', `Extended ${type} decoration method must be a function: ${propertyName}`);
127
+
128
+ method = method(existing);
129
+ }
130
+ else {
131
+ Hoek.assert(existing === undefined, `${type[0].toUpperCase() + type.slice(1)} decoration already defined: ${propertyName}`);
132
+ }
133
+
134
+ if (type === 'handler') {
135
+
136
+ // Handler
137
+
138
+ Hoek.assert(typeof method === 'function', 'Handler must be a function:', propertyName);
139
+ Hoek.assert(!method.defaults || typeof method.defaults === 'object' || typeof method.defaults === 'function', 'Handler defaults property must be an object or function');
140
+ Hoek.assert(!options.extend, 'Cannot extend handler decoration:', propertyName);
141
+ }
142
+ else if (type === 'request') {
143
+
144
+ // Request
145
+
146
+ Hoek.assert(!this._core.Request.reserved.includes(property), 'Cannot override built-in request interface decoration:', propertyName);
147
+
148
+ if (options.apply) {
149
+ this._core.decorations.requestApply = this._core.decorations.requestApply || new Map();
150
+ this._core.decorations.requestApply.set(property, method);
151
+ }
152
+ else {
153
+ this._core.Request.prototype[property] = method;
154
+ }
155
+ }
156
+ else if (type === 'response') {
157
+
158
+ // Response
159
+
160
+ Hoek.assert(!this._core.Response.reserved.includes(property), 'Cannot override built-in response interface decoration:', propertyName);
161
+ this._core.Response.prototype[property] = method;
162
+ }
163
+ else if (type === 'toolkit') {
164
+
165
+ // Toolkit
166
+
167
+ Hoek.assert(!Toolkit.reserved.includes(property), 'Cannot override built-in toolkit decoration:', propertyName);
168
+ this._core.toolkit.decorate(property, method);
169
+ }
170
+ else {
171
+
172
+ // Server
173
+
174
+ if (typeof property === 'string') {
175
+ Hoek.assert(!Object.getOwnPropertyNames(internals.Server.prototype).includes(property), 'Cannot override the built-in server interface method:', propertyName);
176
+ }
177
+ else {
178
+ Hoek.assert(!Object.getOwnPropertySymbols(internals.Server.prototype).includes(property), 'Cannot override the built-in server interface method:', propertyName);
179
+ }
180
+
181
+ this._core.instances.forEach((server) => {
182
+
183
+ server[property] = method;
184
+ });
185
+ }
186
+
187
+ this._core.decorations[type].set(property, method);
188
+ this._core.decorations.public[type].push(property);
189
+ }
190
+
191
+ dependency(dependencies, after) {
192
+
193
+ Hoek.assert(this.realm.plugin, 'Cannot call dependency() outside of a plugin');
194
+ Hoek.assert(!after || typeof after === 'function', 'Invalid after method');
195
+
196
+ // Normalize to { plugin: version }
197
+
198
+ if (typeof dependencies === 'string') {
199
+ dependencies = { [dependencies]: '*' };
200
+ }
201
+ else if (Array.isArray(dependencies)) {
202
+ const map = {};
203
+ for (const dependency of dependencies) {
204
+ map[dependency] = '*';
205
+ }
206
+
207
+ dependencies = map;
208
+ }
209
+
210
+ this._core.dependencies.push({ plugin: this.realm.plugin, deps: dependencies });
211
+
212
+ if (after) {
213
+ this.ext('onPreStart', after, { after: Object.keys(dependencies) });
214
+ }
215
+ }
216
+
217
+ encoder(encoding, encoder) {
218
+
219
+ return this._core.compression.addEncoder(encoding, encoder);
220
+ }
221
+
222
+ event(event) {
223
+
224
+ this._core.events.registerEvent(event);
225
+ }
226
+
227
+ expose(key, value, options = {}) {
228
+
229
+ Hoek.assert(this.realm.plugin, 'Cannot call expose() outside of a plugin');
230
+
231
+ let plugin = this.realm.plugin;
232
+ if (plugin[0] === '@' &&
233
+ options.scope !== true) {
234
+
235
+ plugin = plugin.replace(/^@([^/]+)\//, ($0, $1) => {
236
+
237
+ return !options.scope ? '' : `${$1}__`;
238
+ });
239
+ }
240
+
241
+ this._core.plugins[plugin] = this._core.plugins[plugin] || {};
242
+
243
+ if (typeof key === 'string') {
244
+ this._core.plugins[plugin][key] = value;
245
+ }
246
+ else {
247
+ Hoek.merge(this._core.plugins[plugin], key);
248
+ }
249
+ }
250
+
251
+ ext(events, method, options) { // (event, method, options) -OR- (events)
252
+
253
+ let promise;
254
+ if (typeof events === 'string') {
255
+ if (!method) {
256
+ const team = new Teamwork.Team();
257
+ method = (request, h) => {
258
+
259
+ team.attend(request);
260
+ return h.continue;
261
+ };
262
+
263
+ promise = team.work;
264
+ }
265
+
266
+ events = { type: events, method, options };
267
+ }
268
+
269
+ events = Config.apply('exts', events);
270
+ for (const event of events) {
271
+ this._ext(event);
272
+ }
273
+
274
+ return promise;
275
+ }
276
+
277
+ _ext(event) {
278
+
279
+ event = Object.assign({}, event); // Shallow cloned
280
+ event.realm = this.realm;
281
+ const type = event.type;
282
+
283
+ if (!this._core.extensions.server[type]) {
284
+
285
+ // Realm route extensions
286
+
287
+ if (event.options.sandbox === 'plugin') {
288
+ Hoek.assert(this.realm._extensions[type], 'Unknown event type', type);
289
+ return this.realm._extensions[type].add(event);
290
+ }
291
+
292
+ // Connection route extensions
293
+
294
+ Hoek.assert(this._core.extensions.route[type], 'Unknown event type', type);
295
+ return this._core.extensions.route[type].add(event);
296
+ }
297
+
298
+ // Server extensions
299
+
300
+ Hoek.assert(!event.options.sandbox, 'Cannot specify sandbox option for server extension');
301
+ Hoek.assert(type !== 'onPreStart' || this._core.phase === 'stopped', 'Cannot add onPreStart (after) extension after the server was initialized');
302
+
303
+ event.server = this;
304
+ this._core.extensions.server[type].add(event);
305
+ }
306
+
307
+ async inject(options) {
308
+
309
+ let settings = options;
310
+ if (typeof settings === 'string') {
311
+ settings = { url: settings };
312
+ }
313
+
314
+ if (!settings.authority ||
315
+ settings.auth ||
316
+ settings.app ||
317
+ settings.plugins ||
318
+ settings.allowInternals !== undefined) { // Can be false
319
+
320
+ settings = Object.assign({}, settings); // options can be reused (shallow cloned)
321
+ delete settings.auth;
322
+ delete settings.app;
323
+ delete settings.plugins;
324
+ delete settings.allowInternals;
325
+
326
+ settings.authority = settings.authority || this._core.info.host + ':' + this._core.info.port;
327
+ }
328
+
329
+ Hoek.assert(!options.credentials, 'options.credentials no longer supported (use options.auth)');
330
+
331
+ if (options.auth) {
332
+ Hoek.assert(typeof options.auth === 'object', 'options.auth must be an object');
333
+ Hoek.assert(options.auth.credentials, 'options.auth.credentials is missing');
334
+ Hoek.assert(options.auth.strategy, 'options.auth.strategy is missing');
335
+ }
336
+
337
+ const needle = this._core._dispatch({
338
+ auth: options.auth,
339
+ allowInternals: options.allowInternals,
340
+ app: options.app,
341
+ plugins: options.plugins,
342
+ isInjected: true
343
+ });
344
+
345
+ const res = await Shot.inject(needle, settings);
346
+ const custom = res.raw.res[Config.symbol];
347
+ if (custom) {
348
+ delete res.raw.res[Config.symbol];
349
+
350
+ res.request = custom.request;
351
+
352
+ if (custom.error) {
353
+ throw custom.error;
354
+ }
355
+
356
+ if (custom.result !== undefined) {
357
+ res.result = custom.result;
358
+ }
359
+ }
360
+
361
+ if (res.result === undefined) {
362
+ res.result = res.payload;
363
+ }
364
+
365
+ return res;
366
+ }
367
+
368
+ log(tags, data) {
369
+
370
+ return this._core.log(tags, data);
371
+ }
372
+
373
+ lookup(id) {
374
+
375
+ Hoek.assert(id && typeof id === 'string', 'Invalid route id:', id);
376
+
377
+ const record = this._core.router.ids.get(id);
378
+ if (!record) {
379
+ return null;
380
+ }
381
+
382
+ return record.route.public;
383
+ }
384
+
385
+ match(method, path, host) {
386
+
387
+ Hoek.assert(method && typeof method === 'string', 'Invalid method:', method);
388
+ Hoek.assert(path && typeof path === 'string' && path[0] === '/', 'Invalid path:', path);
389
+ Hoek.assert(!host || typeof host === 'string', 'Invalid host:', host);
390
+
391
+ const match = this._core.router.route(method.toLowerCase(), path, host);
392
+ Hoek.assert(match !== this._core.router.specials.badRequest, 'Invalid path:', path);
393
+ if (match === this._core.router.specials.notFound) {
394
+ return null;
395
+ }
396
+
397
+ return match.route.public;
398
+ }
399
+
400
+ method(name, method, options = {}) {
401
+
402
+ return this._core.methods.add(name, method, options, this.realm);
403
+ }
404
+
405
+ path(relativeTo) {
406
+
407
+ Hoek.assert(relativeTo && typeof relativeTo === 'string', 'relativeTo must be a non-empty string');
408
+ this.realm.settings.files.relativeTo = relativeTo;
409
+ }
410
+
411
+ async register(plugins, options = {}) {
412
+
413
+ if (this.realm.modifiers.route.prefix ||
414
+ this.realm.modifiers.route.vhost) {
415
+
416
+ options = Hoek.clone(options);
417
+ options.routes = options.routes || {};
418
+
419
+ options.routes.prefix = (this.realm.modifiers.route.prefix || '') + (options.routes.prefix || '') || undefined;
420
+ options.routes.vhost = this.realm.modifiers.route.vhost || options.routes.vhost;
421
+ }
422
+
423
+ options = Config.apply('register', options);
424
+
425
+ ++this._core.registring;
426
+
427
+ try {
428
+ const items = [].concat(plugins);
429
+ for (let item of items) {
430
+
431
+ /*
432
+ { register, ...attributes }
433
+ { plugin: { register, ...attributes }, options, once, routes }
434
+ { plugin: { plugin: { register, ...attributes } }, options, once, routes } // Required module
435
+ */
436
+
437
+ if (!item.plugin) {
438
+ item = {
439
+ plugin: item
440
+ };
441
+ }
442
+ else if (!item.plugin.register) {
443
+ item = {
444
+ options: item.options,
445
+ once: item.once,
446
+ routes: item.routes,
447
+ plugin: item.plugin.plugin
448
+ };
449
+ }
450
+ else if (typeof item === 'function') {
451
+ item = Object.assign({}, item); // Shallow cloned
452
+ }
453
+
454
+ item = Config.apply('plugin', item);
455
+
456
+ const name = item.plugin.name || item.plugin.pkg.name;
457
+ const clone = this._clone(name);
458
+
459
+ clone.realm.modifiers.route.prefix = item.routes.prefix || options.routes.prefix;
460
+ clone.realm.modifiers.route.vhost = item.routes.vhost || options.routes.vhost;
461
+ clone.realm.pluginOptions = item.options || {};
462
+
463
+ // Validate requirements
464
+
465
+ const requirements = item.plugin.requirements;
466
+ Hoek.assert(!requirements.node || Somever.match(process.version, requirements.node), 'Plugin', name, 'requires node version', requirements.node, 'but found', process.version);
467
+ Hoek.assert(!requirements.hapi || Somever.match(this.version, requirements.hapi), 'Plugin', name, 'requires hapi version', requirements.hapi, 'but found', this.version);
468
+
469
+ // Protect against multiple registrations
470
+
471
+ if (this._core.registrations[name]) {
472
+ if (item.plugin.once ||
473
+ item.once ||
474
+ options.once) {
475
+
476
+ continue;
477
+ }
478
+
479
+ Hoek.assert(item.plugin.multiple, 'Plugin', name, 'already registered');
480
+ }
481
+ else {
482
+ this._core.registrations[name] = {
483
+ version: item.plugin.version || item.plugin.pkg.version,
484
+ name,
485
+ options: item.options
486
+ };
487
+ }
488
+
489
+ if (item.plugin.dependencies) {
490
+ clone.dependency(item.plugin.dependencies);
491
+ }
492
+
493
+ // Register
494
+
495
+ await item.plugin.register(clone, item.options || {});
496
+ }
497
+ }
498
+ finally {
499
+ --this._core.registring;
500
+ }
501
+ }
502
+
503
+ route(options) {
504
+
505
+ Hoek.assert(typeof options === 'object', 'Invalid route options');
506
+
507
+ options = [].concat(options);
508
+ for (const config of options) {
509
+ if (Array.isArray(config.method)) {
510
+ for (const method of config.method) {
511
+ const settings = Object.assign({}, config); // Shallow cloned
512
+ settings.method = method;
513
+ this._addRoute(settings, this);
514
+ }
515
+ }
516
+ else {
517
+ this._addRoute(config, this);
518
+ }
519
+ }
520
+ }
521
+
522
+ _addRoute(config, server) {
523
+
524
+ const route = new Route(config, server); // Do no use config beyond this point, use route members
525
+ const vhosts = [].concat(route.settings.vhost || '*');
526
+
527
+ for (const vhost of vhosts) {
528
+ const record = this._core.router.add({ method: route.method, path: route.path, vhost, analysis: route._analysis, id: route.settings.id }, route);
529
+ route.fingerprint = record.fingerprint;
530
+ route.params = record.params;
531
+ }
532
+
533
+ this.events.emit('route', route.public);
534
+ Cors.options(route.public, server);
535
+ }
536
+
537
+ rules(processor, options = {}) {
538
+
539
+ Hoek.assert(!this.realm._rules, 'Server realm rules already defined');
540
+
541
+ const settings = Config.apply('rules', options);
542
+ if (settings.validate) {
543
+ const schema = settings.validate.schema;
544
+ settings.validate.schema = Validation.compile(schema, null, this.realm, this._core);
545
+ }
546
+
547
+ this.realm._rules = { processor, settings };
548
+ }
549
+
550
+ state(name, options) {
551
+
552
+ this.states.add(name, options);
553
+ }
554
+
555
+ table(host) {
556
+
557
+ return this._core.router.table(host);
558
+ }
559
+
560
+ validator(validator) {
561
+
562
+ Hoek.assert(!this.realm.validator, 'Validator already set');
563
+
564
+ this.realm.validator = Validation.validator(validator);
565
+ }
566
+
567
+ start() {
568
+
569
+ return this._core._start();
570
+ }
571
+
572
+ initialize() {
573
+
574
+ return this._core._initialize();
575
+ }
576
+
577
+ stop(options) {
578
+
579
+ return this._core._stop(options);
580
+ }
581
+ };
582
+
583
+
584
+ internals.cache = (plugin) => {
585
+
586
+ const policy = function (options, _segment) {
587
+
588
+ return this._core._cachePolicy(options, _segment, plugin.realm);
589
+ };
590
+
591
+ policy.provision = async (opts) => {
592
+
593
+ const clients = plugin._core._createCache(opts);
594
+
595
+ // Start cache
596
+
597
+ if (['initialized', 'starting', 'started'].includes(plugin._core.phase)) {
598
+ await Promise.all(clients.map((client) => client.start()));
599
+ }
600
+ };
601
+
602
+ return policy;
603
+ };
package/lib/streams.js ADDED
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ const Boom = require('@hapi/boom');
4
+ const Teamwork = require('@hapi/teamwork');
5
+
6
+
7
+ const internals = {
8
+ team: Symbol('team')
9
+ };
10
+
11
+
12
+ exports.isStream = function (stream) {
13
+
14
+ if (!stream ||
15
+ typeof stream !== 'object' ||
16
+ typeof stream.pipe !== 'function') {
17
+
18
+ return false;
19
+ }
20
+
21
+ if (typeof stream._read !== 'function') {
22
+ throw Boom.badImplementation('Stream must have a readable interface');
23
+ }
24
+
25
+ if (stream._readableState.objectMode) {
26
+ throw Boom.badImplementation('Cannot reply with stream in object mode');
27
+ }
28
+
29
+ return true;
30
+ };
31
+
32
+
33
+ exports.drain = function (stream) {
34
+
35
+ const team = new Teamwork.Team();
36
+ stream[internals.team] = team;
37
+
38
+ stream.on('readable', internals.read);
39
+ stream.on('error', internals.end);
40
+ stream.on('end', internals.end);
41
+ stream.on('close', internals.end);
42
+
43
+ return team.work;
44
+ };
45
+
46
+
47
+ internals.read = function () {
48
+
49
+ while (this.read()) { }
50
+ };
51
+
52
+
53
+ internals.end = function () {
54
+
55
+ this.removeListener('readable', internals.read);
56
+ this.removeListener('error', internals.end);
57
+ this.removeListener('end', internals.end);
58
+ this.removeListener('close', internals.end);
59
+
60
+ this[internals.team].attend();
61
+ };