]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/request/node_modules/hawk/lib/utils.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / node_modules / request / node_modules / hawk / lib / utils.js
1 // Load modules
2
3 var Sntp = require('sntp');
4 var Boom = require('boom');
5
6
7 // Declare internals
8
9 var internals = {};
10
11
12 exports.version = function () {
13
14     return require('../package.json').version;
15 };
16
17
18 exports.limits = {
19     maxMatchLength: 4096            // Limit the length of uris and headers to avoid a DoS attack on string matching
20 };
21
22
23 // Extract host and port from request
24
25 //                                            $1                            $2
26 internals.hostHeaderRegex = /^(?:(?:\r\n)?\s)*((?:[^:]+)|(?:\[[^\]]+\]))(?::(\d+))?(?:(?:\r\n)?\s)*$/;              // (IPv4, hostname)|(IPv6)
27
28
29 exports.parseHost = function (req, hostHeaderName) {
30
31     hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
32     var hostHeader = req.headers[hostHeaderName];
33     if (!hostHeader) {
34         return null;
35     }
36
37     if (hostHeader.length > exports.limits.maxMatchLength) {
38         return null;
39     }
40
41     var hostParts = hostHeader.match(internals.hostHeaderRegex);
42     if (!hostParts) {
43         return null;
44     }
45
46     return {
47         name: hostParts[1],
48         port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
49     };
50 };
51
52
53 // Parse Content-Type header content
54
55 exports.parseContentType = function (header) {
56
57     if (!header) {
58         return '';
59     }
60
61     return header.split(';')[0].trim().toLowerCase();
62 };
63
64
65 // Convert node's  to request configuration object
66
67 exports.parseRequest = function (req, options) {
68
69     if (!req.headers) {
70         return req;
71     }
72
73     // Obtain host and port information
74
75     var host;
76     if (!options.host ||
77         !options.port) {
78
79         host = exports.parseHost(req, options.hostHeaderName);
80         if (!host) {
81             return new Error('Invalid Host header');
82         }
83     }
84
85     var request = {
86         method: req.method,
87         url: req.url,
88         host: options.host || host.name,
89         port: options.port || host.port,
90         authorization: req.headers.authorization,
91         contentType: req.headers['content-type'] || ''
92     };
93
94     return request;
95 };
96
97
98 exports.now = function (localtimeOffsetMsec) {
99
100     return Sntp.now() + (localtimeOffsetMsec || 0);
101 };
102
103
104 exports.nowSecs = function (localtimeOffsetMsec) {
105
106     return Math.floor(exports.now(localtimeOffsetMsec) / 1000);
107 };
108
109
110 internals.authHeaderRegex = /^(\w+)(?:\s+(.*))?$/;                                      // Header: scheme[ something]
111 internals.attributeRegex = /^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/;   // !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
112
113
114 // Parse Hawk HTTP Authorization header
115
116 exports.parseAuthorizationHeader = function (header, keys) {
117
118     keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
119
120     if (!header) {
121         return Boom.unauthorized(null, 'Hawk');
122     }
123
124     if (header.length > exports.limits.maxMatchLength) {
125         return Boom.badRequest('Header length too long');
126     }
127
128     var headerParts = header.match(internals.authHeaderRegex);
129     if (!headerParts) {
130         return Boom.badRequest('Invalid header syntax');
131     }
132
133     var scheme = headerParts[1];
134     if (scheme.toLowerCase() !== 'hawk') {
135         return Boom.unauthorized(null, 'Hawk');
136     }
137
138     var attributesString = headerParts[2];
139     if (!attributesString) {
140         return Boom.badRequest('Invalid header syntax');
141     }
142
143     var attributes = {};
144     var errorMessage = '';
145     var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
146
147         // Check valid attribute names
148
149         if (keys.indexOf($1) === -1) {
150             errorMessage = 'Unknown attribute: ' + $1;
151             return;
152         }
153
154         // Allowed attribute value characters
155
156         if ($2.match(internals.attributeRegex) === null) {
157             errorMessage = 'Bad attribute value: ' + $1;
158             return;
159         }
160
161         // Check for duplicates
162
163         if (attributes.hasOwnProperty($1)) {
164             errorMessage = 'Duplicate attribute: ' + $1;
165             return;
166         }
167
168         attributes[$1] = $2;
169         return '';
170     });
171
172     if (verify !== '') {
173         return Boom.badRequest(errorMessage || 'Bad header format');
174     }
175
176     return attributes;
177 };
178
179
180 exports.unauthorized = function (message, attributes) {
181
182     return Boom.unauthorized(message, 'Hawk', attributes);
183 };