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/cors.js ADDED
@@ -0,0 +1,207 @@
1
+ 'use strict';
2
+
3
+ const Boom = require('@hapi/boom');
4
+ const Hoek = require('@hapi/hoek');
5
+
6
+ let Route = null; // Delayed load due to circular dependency
7
+
8
+
9
+ const internals = {};
10
+
11
+
12
+ exports.route = function (options) {
13
+
14
+ if (!options) {
15
+ return false;
16
+ }
17
+
18
+ const settings = Hoek.clone(options);
19
+ settings._headers = settings.headers.concat(settings.additionalHeaders);
20
+ settings._headersString = settings._headers.join(',');
21
+ for (let i = 0; i < settings._headers.length; ++i) {
22
+ settings._headers[i] = settings._headers[i].toLowerCase();
23
+ }
24
+
25
+ if (settings._headers.indexOf('origin') === -1) {
26
+ settings._headers.push('origin');
27
+ }
28
+
29
+ settings._exposedHeaders = settings.exposedHeaders.concat(settings.additionalExposedHeaders).join(',');
30
+
31
+ if (settings.origin === 'ignore') {
32
+ settings._origin = false;
33
+ }
34
+ else if (settings.origin.indexOf('*') !== -1) {
35
+ Hoek.assert(settings.origin.length === 1, 'Cannot specify cors.origin * together with other values');
36
+ settings._origin = true;
37
+ }
38
+ else {
39
+ settings._origin = {
40
+ qualified: [],
41
+ wildcards: []
42
+ };
43
+
44
+ for (const origin of settings.origin) {
45
+ if (origin.indexOf('*') !== -1) {
46
+ settings._origin.wildcards.push(new RegExp('^' + Hoek.escapeRegex(origin).replace(/\\\*/g, '.*').replace(/\\\?/g, '.') + '$'));
47
+ }
48
+ else {
49
+ settings._origin.qualified.push(origin);
50
+ }
51
+ }
52
+ }
53
+
54
+ return settings;
55
+ };
56
+
57
+
58
+ exports.options = function (route, server) {
59
+
60
+ if (route.method === 'options' ||
61
+ !route.settings.cors) {
62
+
63
+ return;
64
+ }
65
+
66
+ exports.handler(server);
67
+ };
68
+
69
+
70
+ exports.handler = function (server) {
71
+
72
+ Route = Route || require('./route');
73
+
74
+ if (server._core.router.specials.options) {
75
+ return;
76
+ }
77
+
78
+ const definition = {
79
+ method: '_special',
80
+ path: '/{p*}',
81
+ handler: internals.handler,
82
+ options: {
83
+ cors: false
84
+ }
85
+ };
86
+
87
+ const route = new Route(definition, server, { special: true });
88
+ server._core.router.special('options', route);
89
+ };
90
+
91
+
92
+ internals.handler = function (request, h) {
93
+
94
+ // Validate CORS preflight request
95
+
96
+ const method = request.headers['access-control-request-method'];
97
+ if (!method) {
98
+ throw Boom.notFound('CORS error: Missing Access-Control-Request-Method header');
99
+ }
100
+
101
+ // Lookup route
102
+
103
+ const route = request.server.match(method, request.path, request.info.hostname);
104
+ if (!route) {
105
+ throw Boom.notFound();
106
+ }
107
+
108
+ const settings = route.settings.cors;
109
+ if (!settings) {
110
+ return { message: 'CORS is disabled for this route' };
111
+ }
112
+
113
+ // Validate Origin header
114
+
115
+ const origin = request.headers.origin;
116
+
117
+ if (!origin &&
118
+ settings._origin !== false) {
119
+
120
+ throw Boom.notFound('CORS error: Missing Origin header');
121
+ }
122
+
123
+ if (!exports.matchOrigin(origin, settings)) {
124
+ return { message: 'CORS error: Origin not allowed' };
125
+ }
126
+
127
+ // Validate allowed headers
128
+
129
+ let headers = request.headers['access-control-request-headers'];
130
+ if (headers) {
131
+ headers = headers.toLowerCase().split(/\s*,\s*/);
132
+ if (Hoek.intersect(headers, settings._headers).length !== headers.length) {
133
+ return { message: 'CORS error: Some headers are not allowed' };
134
+ }
135
+ }
136
+
137
+ // Reply with the route CORS headers
138
+
139
+ const response = h.response();
140
+ response._header('access-control-allow-origin', settings._origin ? origin : '*');
141
+ response._header('access-control-allow-methods', method);
142
+ response._header('access-control-allow-headers', settings._headersString);
143
+ response._header('access-control-max-age', settings.maxAge);
144
+
145
+ if (settings.credentials) {
146
+ response._header('access-control-allow-credentials', 'true');
147
+ }
148
+
149
+ if (settings._exposedHeaders) {
150
+ response._header('access-control-expose-headers', settings._exposedHeaders);
151
+ }
152
+
153
+ return response;
154
+ };
155
+
156
+
157
+ exports.headers = function (response) {
158
+
159
+ const request = response.request;
160
+ const settings = request.route.settings.cors;
161
+
162
+ if (settings._origin !== false) {
163
+ response.vary('origin');
164
+ }
165
+
166
+ if ((request.info.cors && !request.info.cors.isOriginMatch) || // After route lookup
167
+ !exports.matchOrigin(request.headers.origin, request.route.settings.cors)) { // Response from onRequest
168
+
169
+ return;
170
+ }
171
+
172
+ response._header('access-control-allow-origin', settings._origin ? request.headers.origin : '*');
173
+
174
+ if (settings.credentials) {
175
+ response._header('access-control-allow-credentials', 'true');
176
+ }
177
+
178
+ if (settings._exposedHeaders) {
179
+ response._header('access-control-expose-headers', settings._exposedHeaders, { append: true });
180
+ }
181
+ };
182
+
183
+
184
+ exports.matchOrigin = function (origin, settings) {
185
+
186
+ if (settings._origin === true ||
187
+ settings._origin === false) {
188
+
189
+ return true;
190
+ }
191
+
192
+ if (!origin) {
193
+ return false;
194
+ }
195
+
196
+ if (settings._origin.qualified.indexOf(origin) !== -1) {
197
+ return true;
198
+ }
199
+
200
+ for (const wildcard of settings._origin.wildcards) {
201
+ if (origin.match(wildcard)) {
202
+ return true;
203
+ }
204
+ }
205
+
206
+ return false;
207
+ };
package/lib/ext.js ADDED
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const Hoek = require('@hapi/hoek');
4
+ const Topo = require('@hapi/topo');
5
+
6
+
7
+ const internals = {};
8
+
9
+
10
+ exports = module.exports = internals.Ext = class {
11
+
12
+ type = null;
13
+ nodes = null;
14
+
15
+ #core = null;
16
+ #routes = [];
17
+ #topo = new Topo.Sorter();
18
+
19
+ constructor(type, core) {
20
+
21
+ this.#core = core;
22
+ this.type = type;
23
+ }
24
+
25
+ add(event) {
26
+
27
+ const methods = [].concat(event.method);
28
+ for (const method of methods) {
29
+ const settings = {
30
+ before: event.options.before,
31
+ after: event.options.after,
32
+ group: event.realm.plugin,
33
+ sort: this.#core.extensionsSeq++
34
+ };
35
+
36
+ const node = {
37
+ func: method, // Request: function (request, h), Server: function (server)
38
+ bind: event.options.bind,
39
+ server: event.server, // Server event
40
+ realm: event.realm,
41
+ timeout: event.options.timeout
42
+ };
43
+
44
+ this.#topo.add(node, settings);
45
+ }
46
+
47
+ this.nodes = this.#topo.nodes;
48
+
49
+ // Notify routes
50
+
51
+ for (const route of this.#routes) {
52
+ route.rebuild(event);
53
+ }
54
+ }
55
+
56
+ merge(others) {
57
+
58
+ const merge = [];
59
+ for (const other of others) {
60
+ merge.push(other.#topo);
61
+ }
62
+
63
+ this.#topo.merge(merge);
64
+ this.nodes = this.#topo.nodes.length ? this.#topo.nodes : null;
65
+ }
66
+
67
+ subscribe(route) {
68
+
69
+ this.#routes.push(route);
70
+ }
71
+
72
+ static combine(route, type) {
73
+
74
+ const ext = new internals.Ext(type, route._core);
75
+
76
+ const events = route.settings.ext[type];
77
+ if (events) {
78
+ for (let event of events) {
79
+ event = Object.assign({}, event); // Shallow cloned
80
+ Hoek.assert(!event.options.sandbox, 'Cannot specify sandbox option for route extension');
81
+ event.realm = route.realm;
82
+ ext.add(event);
83
+ }
84
+ }
85
+
86
+ const server = route._core.extensions.route[type];
87
+ const realm = route.realm._extensions[type];
88
+
89
+ ext.merge([server, realm]);
90
+
91
+ server.subscribe(route);
92
+ realm.subscribe(route);
93
+
94
+ return ext;
95
+ }
96
+ };
package/lib/handler.js ADDED
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ const Hoek = require('@hapi/hoek');
4
+
5
+
6
+ const internals = {};
7
+
8
+
9
+ exports.execute = async function (request) {
10
+
11
+ // Prerequisites
12
+
13
+ if (request._route._prerequisites) {
14
+ for (const set of request._route._prerequisites) { // Serial execution of each set
15
+ const pres = [];
16
+ for (const item of set) {
17
+ pres.push(internals.handler(request, item.method, item));
18
+ }
19
+
20
+ const responses = await Promise.all(pres); // Parallel execution within sets
21
+ for (const response of responses) {
22
+ if (response !== undefined) {
23
+ return response;
24
+ }
25
+ }
26
+ }
27
+ }
28
+
29
+ // Handler
30
+
31
+ const result = await internals.handler(request, request.route.settings.handler);
32
+ if (result._takeover ||
33
+ typeof result === 'symbol') {
34
+
35
+ return result;
36
+ }
37
+
38
+ request._setResponse(result);
39
+ };
40
+
41
+
42
+ internals.handler = async function (request, method, pre) {
43
+
44
+ const bind = request.route.settings.bind;
45
+ const realm = request.route.realm;
46
+ let response = await request._core.toolkit.execute(method, request, { bind, realm, continue: 'null' });
47
+
48
+ // Handler
49
+
50
+ if (!pre) {
51
+ if (response.isBoom) {
52
+ request._log(['handler', 'error'], response);
53
+ throw response;
54
+ }
55
+
56
+ return response;
57
+ }
58
+
59
+ // Pre
60
+
61
+ if (response.isBoom) {
62
+ response.assign = pre.assign;
63
+ response = await request._core.toolkit.failAction(request, pre.failAction, response, { tags: ['pre', 'error'], retain: true });
64
+ }
65
+
66
+ if (typeof response === 'symbol') {
67
+ return response;
68
+ }
69
+
70
+ if (pre.assign) {
71
+ request.pre[pre.assign] = (response.isBoom ? response : response.source);
72
+ request.preResponses[pre.assign] = response;
73
+ }
74
+
75
+ if (response._takeover) {
76
+ return response;
77
+ }
78
+ };
79
+
80
+
81
+ exports.defaults = function (method, handler, core) {
82
+
83
+ let defaults = null;
84
+
85
+ if (typeof handler === 'object') {
86
+ const type = Object.keys(handler)[0];
87
+ const serverHandler = core.decorations.handler.get(type);
88
+
89
+ Hoek.assert(serverHandler, 'Unknown handler:', type);
90
+
91
+ if (serverHandler.defaults) {
92
+ defaults = (typeof serverHandler.defaults === 'function' ? serverHandler.defaults(method) : serverHandler.defaults);
93
+ }
94
+ }
95
+
96
+ return defaults || {};
97
+ };
98
+
99
+
100
+ exports.configure = function (handler, route) {
101
+
102
+ if (typeof handler === 'object') {
103
+ const type = Object.keys(handler)[0];
104
+ const serverHandler = route._core.decorations.handler.get(type);
105
+
106
+ Hoek.assert(serverHandler, 'Unknown handler:', type);
107
+
108
+ return serverHandler(route.public, handler[type]);
109
+ }
110
+
111
+ return handler;
112
+ };
113
+
114
+
115
+ exports.prerequisitesConfig = function (config) {
116
+
117
+ if (!config) {
118
+ return null;
119
+ }
120
+
121
+ /*
122
+ [
123
+ [
124
+ function (request, h) { },
125
+ {
126
+ method: function (request, h) { }
127
+ assign: key1
128
+ },
129
+ {
130
+ method: function (request, h) { },
131
+ assign: key2
132
+ }
133
+ ],
134
+ {
135
+ method: function (request, h) { },
136
+ assign: key3
137
+ }
138
+ ]
139
+ */
140
+
141
+ const prerequisites = [];
142
+
143
+ for (let pres of config) {
144
+ pres = [].concat(pres);
145
+
146
+ const set = [];
147
+ for (let pre of pres) {
148
+ if (typeof pre !== 'object') {
149
+ pre = { method: pre };
150
+ }
151
+
152
+ const item = {
153
+ method: pre.method,
154
+ assign: pre.assign,
155
+ failAction: pre.failAction || 'error'
156
+ };
157
+
158
+ set.push(item);
159
+ }
160
+
161
+ prerequisites.push(set);
162
+ }
163
+
164
+ return prerequisites.length ? prerequisites : null;
165
+ };
package/lib/headers.js ADDED
@@ -0,0 +1,187 @@
1
+ 'use strict';
2
+
3
+
4
+ const Stream = require('stream');
5
+
6
+ const Boom = require('@hapi/boom');
7
+
8
+
9
+ const internals = {};
10
+
11
+
12
+ exports.cache = function (response) {
13
+
14
+ const request = response.request;
15
+ if (response.headers['cache-control']) {
16
+ return;
17
+ }
18
+
19
+ const settings = request.route.settings.cache;
20
+ const policy = settings && request._route._cache && (settings._statuses.has(response.statusCode) || (response.statusCode === 304 && settings._statuses.has(200)));
21
+
22
+ if (policy ||
23
+ response.settings.ttl) {
24
+
25
+ const ttl = response.settings.ttl !== null ? response.settings.ttl : request._route._cache.ttl();
26
+ const privacy = request.auth.isAuthenticated || response.headers['set-cookie'] ? 'private' : settings.privacy || 'default';
27
+ response._header('cache-control', 'max-age=' + Math.floor(ttl / 1000) + ', must-revalidate' + (privacy !== 'default' ? ', ' + privacy : ''));
28
+ }
29
+ else if (settings) {
30
+ response._header('cache-control', settings.otherwise);
31
+ }
32
+ };
33
+
34
+
35
+ exports.content = async function (response) {
36
+
37
+ const request = response.request;
38
+ if (response._isPayloadSupported() ||
39
+ request.method === 'head') {
40
+
41
+ await response._marshal();
42
+
43
+ if (request.jsonp &&
44
+ response._payload.jsonp) {
45
+
46
+ response._header('content-type', 'text/javascript' + (response.settings.charset ? '; charset=' + response.settings.charset : ''));
47
+ response._header('x-content-type-options', 'nosniff');
48
+ response._payload.jsonp(request.jsonp);
49
+ }
50
+
51
+ if (response._payload.size &&
52
+ typeof response._payload.size === 'function') {
53
+
54
+ response._header('content-length', response._payload.size(), { override: false });
55
+ }
56
+
57
+ if (!response._isPayloadSupported()) {
58
+ response._close(); // Close unused file streams
59
+ response._payload = new internals.Empty(); // Set empty stream
60
+ }
61
+
62
+ exports.type(response);
63
+ }
64
+ else {
65
+
66
+ // Set empty stream
67
+
68
+ response._close(); // Close unused file streams
69
+ response._payload = new internals.Empty();
70
+ delete response.headers['content-length'];
71
+ }
72
+ };
73
+
74
+
75
+ exports.state = async function (response) {
76
+
77
+ const request = response.request;
78
+ const states = [];
79
+
80
+ for (const stateName in request._states) {
81
+ states.push(request._states[stateName]);
82
+ }
83
+
84
+ try {
85
+ for (const name in request._core.states.cookies) {
86
+ const autoValue = request._core.states.cookies[name].autoValue;
87
+ if (!autoValue || name in request._states || name in request.state) {
88
+ continue;
89
+ }
90
+
91
+ if (typeof autoValue !== 'function') {
92
+ states.push({ name, value: autoValue });
93
+ continue;
94
+ }
95
+
96
+ const value = await autoValue(request);
97
+ states.push({ name, value });
98
+ }
99
+
100
+ if (!states.length) {
101
+ return;
102
+ }
103
+
104
+ let header = await request._core.states.format(states, request);
105
+ const existing = response.headers['set-cookie'];
106
+ if (existing) {
107
+ header = (Array.isArray(existing) ? existing : [existing]).concat(header);
108
+ }
109
+
110
+ response._header('set-cookie', header);
111
+ }
112
+ catch (err) {
113
+ const error = Boom.boomify(err);
114
+ request._log(['state', 'response', 'error'], error);
115
+ request._states = {}; // Clear broken state
116
+ throw error;
117
+ }
118
+ };
119
+
120
+
121
+ exports.type = function (response) {
122
+
123
+ const type = response.contentType;
124
+ if (type !== null && type !== response.headers['content-type']) {
125
+ response.type(type);
126
+ }
127
+ };
128
+
129
+
130
+ exports.entity = function (response) {
131
+
132
+ const request = response.request;
133
+
134
+ if (!request._entity) {
135
+ return;
136
+ }
137
+
138
+ if (request._entity.etag &&
139
+ !response.headers.etag) {
140
+
141
+ response.etag(request._entity.etag, { vary: request._entity.vary });
142
+ }
143
+
144
+ if (request._entity.modified &&
145
+ !response.headers['last-modified']) {
146
+
147
+ response.header('last-modified', request._entity.modified);
148
+ }
149
+ };
150
+
151
+
152
+ exports.unmodified = function (response) {
153
+
154
+ const request = response.request;
155
+ if (response.statusCode === 304) {
156
+ return;
157
+ }
158
+
159
+ const entity = {
160
+ etag: response.headers.etag,
161
+ vary: response.settings.varyEtag,
162
+ modified: response.headers['last-modified']
163
+ };
164
+
165
+ const etag = request._core.Response.unmodified(request, entity);
166
+ if (etag) {
167
+ response.code(304);
168
+
169
+ if (etag !== true) { // Override etag with incoming weak match
170
+ response.headers.etag = etag;
171
+ }
172
+ }
173
+ };
174
+
175
+
176
+ internals.Empty = class extends Stream.Readable {
177
+
178
+ _read(/* size */) {
179
+
180
+ this.push(null);
181
+ }
182
+
183
+ writeToStream(stream) {
184
+
185
+ stream.end();
186
+ }
187
+ };
package/lib/index.js ADDED
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const Server = require('./server');
4
+
5
+
6
+ const internals = {};
7
+
8
+
9
+ exports.Server = Server;
10
+
11
+ exports.server = Server;