Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
BuiltInFilters.js
001 /**
002 * @param {!string} str
003 * @return {!string}
004 */
005 function rawurlencode(str)
006 {
007 return encodeURIComponent(str).replace(
008 /[!'()*]/g,
009 /**
010 * @param {!string} c
011 */
012 function(c)
013 {
014 return '%' + c.charCodeAt(0).toString(16).toUpperCase();
015 }
016 );
017 }
018
019 /**
020 * IMPORTANT NOTE: those filters are only meant to catch bad input and honest mistakes. They don't
021 * match their PHP equivalent exactly and may let unwanted values through. Their
022 * result should always be checked by PHP filters
023 *
024 * @const
025 */
026 var BuiltInFilters =
027 {
028 /**
029 * @param {*} attrValue
030 * @return {*}
031 */
032 filterAlnum: function(attrValue)
033 {
034 return /^[0-9A-Za-z]+$/.test(attrValue) ? attrValue : false;
035 },
036
037 /**
038 * @param {*} attrValue
039 * @return {*}
040 */
041 filterColor: function(attrValue)
042 {
043 return /^(?:#[0-9a-f]{3,6}|rgb\(\d{1,3}, *\d{1,3}, *\d{1,3}\)|[a-z]+)$/i.test(attrValue) ? attrValue : false;
044 },
045
046 /**
047 * @param {*} attrValue
048 * @return {*}
049 */
050 filterEmail: function(attrValue)
051 {
052 return /^[-\w.+]+@[-\w.]+$/.test(attrValue) ? attrValue : false;
053 },
054
055 /**
056 * @param {*} attrValue
057 * @return {!boolean}
058 */
059 filterFalse: function(attrValue)
060 {
061 return false;
062 },
063
064 /**
065 * @param {*} attrValue
066 * @return {*}
067 */
068 filterFloat: function(attrValue)
069 {
070 return /^(?:0|-?[1-9]\d*)(?:\.\d+)?(?:e[1-9]\d*)?$/i.test(attrValue) ? attrValue : false;
071 },
072
073 /**
074 * @param {*} attrValue Original value
075 * @param {!Object} map Hash map
076 * @param {!boolean} strict Whether this map is strict (values with no match are invalid)
077 * @return {*} Filtered value, or FALSE if invalid
078 */
079 filterHashmap: function(attrValue, map, strict)
080 {
081 if (attrValue in map)
082 {
083 return map[attrValue];
084 }
085
086 return (strict) ? false : attrValue;
087 },
088
089 /**
090 * @param {*} attrValue
091 * @return {*}
092 */
093 filterIdentifier: function(attrValue)
094 {
095 return /^[-\w]+$/.test(attrValue) ? attrValue : false;
096 },
097
098 /**
099 * @param {*} attrValue
100 * @return {*}
101 */
102 filterInt: function(attrValue)
103 {
104 return /^(?:0|-?[1-9]\d*)$/.test(attrValue) ? attrValue : false;
105 },
106
107 /**
108 * @param {*} attrValue
109 * @return {*}
110 */
111 filterIp: function(attrValue)
112 {
113 if (/^[\d.]+$/.test(attrValue))
114 {
115 return BuiltInFilters.filterIpv4(attrValue);
116 }
117
118 if (/^[\da-f:]+$/i.test(attrValue))
119 {
120 return BuiltInFilters.filterIpv6(attrValue);
121 }
122
123 return false;
124 },
125
126 /**
127 * @param {*} attrValue
128 * @return {*}
129 */
130 filterIpport: function(attrValue)
131 {
132 var m, ip;
133
134 if (m = /^\[([\da-f:]+)(\]:[1-9]\d*)$/i.exec(attrValue))
135 {
136 ip = BuiltInFilters.filterIpv6(m[1]);
137
138 if (ip === false)
139 {
140 return false;
141 }
142
143 return '[' + ip + m[2];
144 }
145
146 if (m = /^([\d.]+)(:[1-9]\d*)$/.exec(attrValue))
147 {
148 ip = BuiltInFilters.filterIpv4(m[1]);
149
150 if (ip === false)
151 {
152 return false;
153 }
154
155 return ip + m[2];
156 }
157
158 return false;
159 },
160
161 /**
162 * @param {*} attrValue
163 * @return {*}
164 */
165 filterIpv4: function(attrValue)
166 {
167 if (!/^\d+\.\d+\.\d+\.\d+$/.test(attrValue))
168 {
169 return false;
170 }
171
172 var i = 4, p = attrValue.split('.');
173 while (--i >= 0)
174 {
175 // NOTE: ext/filter doesn't support octal notation
176 if (p[i].charAt(0) === '0' || p[i] > 255)
177 {
178 return false;
179 }
180 }
181
182 return attrValue;
183 },
184
185 /**
186 * @param {*} attrValue
187 * @return {*}
188 */
189 filterIpv6: function(attrValue)
190 {
191 return /^(\d*:){2,7}\d+(?:\.\d+\.\d+\.\d+)?$/.test(attrValue) ? attrValue : false;
192 },
193
194 /**
195 * @param {*} attrValue
196 * @param {!Array.<!Array>} map
197 * @return {*}
198 */
199 filterMap: function(attrValue, map)
200 {
201 var i = -1, cnt = map.length;
202 while (++i < cnt)
203 {
204 if (map[i][0].test(attrValue))
205 {
206 return map[i][1];
207 }
208 }
209
210 return attrValue;
211 },
212
213 /**
214 * @param {*} attrValue
215 * @return {*}
216 */
217 filterNumber: function(attrValue)
218 {
219 return /^\d+$/.test(attrValue) ? attrValue : false;
220 },
221
222 /**
223 * @param {*} attrValue
224 * @param {!number} min
225 * @param {!number} max
226 * @param {Logger} logger
227 * @return {!number|boolean}
228 */
229 filterRange: function(attrValue, min, max, logger)
230 {
231 if (!/^(?:0|-?[1-9]\d*)$/.test(attrValue))
232 {
233 return false;
234 }
235
236 attrValue = parseInt(attrValue, 10);
237
238 if (attrValue < min)
239 {
240 if (logger)
241 {
242 logger.warn(
243 'Value outside of range, adjusted up to min value',
244 {
245 'attrValue' : attrValue,
246 'min' : min,
247 'max' : max
248 }
249 );
250 }
251
252 return min;
253 }
254
255 if (attrValue > max)
256 {
257 if (logger)
258 {
259 logger.warn(
260 'Value outside of range, adjusted down to max value',
261 {
262 'attrValue' : attrValue,
263 'min' : min,
264 'max' : max
265 }
266 );
267 }
268
269 return max;
270 }
271
272 return attrValue;
273 },
274
275 /**
276 * @param {*} attrValue
277 * @param {!RegExp} regexp
278 * @return {*}
279 */
280 filterRegexp: function(attrValue, regexp)
281 {
282 return regexp.test(attrValue) ? attrValue : false;
283 },
284
285 /**
286 * @param {*} attrValue
287 * @return {*}
288 */
289 filterSimpletext: function(attrValue)
290 {
291 return /^[-\w+., ]+$/.test(attrValue) ? attrValue : false;
292 },
293
294 /**
295 * @param {*} attrValue
296 * @return {*}
297 */
298 filterUint: function(attrValue)
299 {
300 return /^(?:0|[1-9]\d*)$/.test(attrValue) ? attrValue : false;
301 },
302
303 /**
304 * @param {*} attrValue
305 * @param {!Object} urlConfig
306 * @param {Logger} logger
307 * @return {*}
308 */
309 filterUrl: function(attrValue, urlConfig, logger)
310 {
311 /**
312 * Trim the URL to conform with HTML5 then parse it
313 * @link http://dev.w3.org/html5/spec/links.html#attr-hyperlink-href
314 */
315 var p = BuiltInFilters.parseUrl(attrValue.replace(/^\s+/, '').replace(/\s+$/, ''));
316
317 var error = BuiltInFilters.validateUrl(urlConfig, p);
318 if (error)
319 {
320 if (logger)
321 {
322 p['attrValue'] = attrValue;
323 logger.err(error, p);
324 }
325
326 return false;
327 }
328
329 return BuiltInFilters.rebuildUrl(urlConfig, p);
330 },
331
332 /**
333 * Parse a URL and return its components
334 *
335 * Similar to PHP's own parse_url() except that all parts are always returned
336 *
337 * @param {!string} url Original URL
338 * @return {!Object}
339 */
340 parseUrl: function(url)
341 {
342 var regexp = /^(?:([a-z][-+.\w]*):)?(?:\/\/(?:([^:\/?#]*)(?::([^\/?#]*)?)?@)?(?:(\[[a-f\d:]+\]|[^:\/?#]+)(?::(\d*))?)?(?![^\/?#]))?([^?#]*)(\?[^#]*)?(#.*)?$/i;
343
344 // NOTE: this regexp always matches because of the last three captures
345 var m = regexp['exec'](url),
346 parts = {},
347 tokens = ['scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'];
348 tokens.forEach(
349 function(name, i)
350 {
351 parts[name] = (m[i + 1] > '') ? m[i + 1] : '';
352 }
353 );
354
355 /**
356 * @link http://tools.ietf.org/html/rfc3986#section-3.1
357 *
358 * 'An implementation should accept uppercase letters as equivalent to lowercase in
359 * scheme names (e.g., allow "HTTP" as well as "http") for the sake of robustness but
360 * should only produce lowercase scheme names for consistency.'
361 */
362 parts['scheme'] = parts['scheme'].toLowerCase();
363
364 /**
365 * Normalize the domain label separators and remove trailing dots
366 * @link http://url.spec.whatwg.org/#domain-label-separators
367 */
368 parts['host'] = parts['host'].replace(/[\u3002\uff0e\uff61]/g, '.').replace(/\.+$/g, '');
369
370 // Test whether host has non-ASCII characters and punycode it if possible
371 if (/[^\x00-\x7F]/.test(parts['host']) && typeof punycode !== 'undefined')
372 {
373 parts['host'] = punycode.toASCII(parts['host']);
374 }
375
376 return parts;
377 },
378
379 /**
380 * Rebuild a parsed URL
381 *
382 * @param {!Object} urlConfig
383 * @param {!Object} p
384 * @return {!string}
385 */
386 rebuildUrl: function(urlConfig, p)
387 {
388 var url = '';
389 if (p['scheme'] !== '')
390 {
391 url += p['scheme'] + ':';
392 }
393 if (p['host'] === '')
394 {
395 // Allow the file: scheme to not have a host and ensure it starts with slashes
396 if (p['scheme'] === 'file')
397 {
398 url += '//';
399 }
400 }
401 else
402 {
403 url += '//';
404
405 // Add the credentials if applicable
406 if (p['user'] !== '')
407 {
408 // Reencode the credentials in case there are invalid chars in them, or suspicious
409 // characters such as : or @ that could confuse a browser into connecting to the
410 // wrong host (or at least, to a host that is different than the one we thought)
411 url += rawurlencode(decodeURIComponent(p['user']));
412
413 if (p['pass'] !== '')
414 {
415 url += ':' + rawurlencode(decodeURIComponent(p['pass']));
416 }
417
418 url += '@';
419 }
420
421 url += p['host'];
422
423 // Append the port number (note that as per the regexp it can only contain digits)
424 if (p['port'] !== '')
425 {
426 url += ':' + p['port'];
427 }
428 }
429
430 // Build the path, including the query and fragment parts
431 var path = p['path'] + p['query'] + p['fragment'];
432
433 /**
434 * "For consistency, URI producers and normalizers should use uppercase hexadecimal digits
435 * for all percent- encodings."
436 *
437 * @link http://tools.ietf.org/html/rfc3986#section-2.1
438 */
439 path = path.replace(
440 /%.?[a-f]/,
441 function (m)
442 {
443 return m[0].toUpperCase();
444 },
445 path
446 );
447
448 // Append the sanitized path to the URL
449 url += BuiltInFilters.sanitizeUrl(path);
450
451 // Replace the first colon if there's no scheme and it could potentially be interpreted as
452 // the scheme separator
453 if (!p['scheme'])
454 {
455 url = url.replace(/^([^\/]*):/, '$1%3A', url);
456 }
457
458 return url;
459 },
460
461 /**
462 * Sanitize a URL for safe use regardless of context
463 *
464 * This method URL-encodes some sensitive characters in case someone would want to use the URL in
465 * some JavaScript thingy, or in CSS. We also encode characters that are not allowed in the path
466 * of a URL as defined in RFC 3986 appendix A, including percent signs that are not immediately
467 * followed by two hex digits.
468 *
469 * " and ' to prevent breaking out of quotes (JavaScript or otherwise)
470 * ( and ) to prevent the use of functions in JavaScript (eval()) or CSS (expression())
471 * < and > to prevent breaking out of <script>
472 * \r and \n because they're illegal in JavaScript
473 * [ and ] because the W3 validator rejects them and they "should" be escaped as per RFC 3986
474 * Non-ASCII characters as per RFC 3986
475 * Control codes and spaces, as per RFC 3986
476 *
477 * @link http://sla.ckers.org/forum/read.php?2,51478
478 * @link http://timelessrepo.com/json-isnt-a-javascript-subset
479 * @link http://www.ietf.org/rfc/rfc3986.txt
480 * @link http://stackoverflow.com/a/1547922
481 * @link http://tools.ietf.org/html/rfc3986#appendix-A
482 *
483 * @param {!string} url Original URL
484 * @return {!string} Sanitized URL
485 */
486 sanitizeUrl: function(url)
487 {
488 return url.replace(/[^\u0020-\u007E]+/g, encodeURIComponent).replace(/%(?![0-9A-Fa-f]{2})|[^!#-&*-;=?-Z_a-z~]/g, escape);
489 },
490
491 /**
492 * Validate a parsed URL
493 *
494 * @param {!Object} urlConfig
495 * @param {!Object} p
496 * @return {string|undefined}
497 */
498 validateUrl: function(urlConfig, p)
499 {
500 if (p['scheme'] !== '' && !urlConfig.allowedSchemes.test(p['scheme']))
501 {
502 return 'URL scheme is not allowed';
503 }
504
505 if (p['host'] === '')
506 {
507 // Reject malformed URLs such as http:///example.org but allow schemeless paths
508 if (p['scheme'] !== 'file' && p['scheme'] !== '')
509 {
510 return 'Missing host';
511 }
512 }
513 else
514 {
515 /**
516 * Test whether the host is valid
517 * @link http://tools.ietf.org/html/rfc1035#section-2.3.1
518 * @link http://tools.ietf.org/html/rfc1123#section-2
519 */
520 var regexp = /^(?!-)[-a-z0-9]{0,62}[a-z0-9](?:\.(?!-)[-a-z0-9]{0,62}[a-z0-9])*$/i;
521 if (!regexp.test(p['host']))
522 {
523 // If the host invalid, retest as an IPv4 and IPv6 address (IPv6 in brackets)
524 if (!BuiltInFilters.filterIpv4(p['host'])
525 && !BuiltInFilters.filterIpv6(p['host'].replace(/^\[(.*)\]$/, '$1', p['host'])))
526 {
527 return 'URL host is invalid';
528 }
529 }
530
531 if ((urlConfig.disallowedHosts && urlConfig.disallowedHosts.test(p['host']))
532 || (urlConfig.restrictedHosts && !urlConfig.restrictedHosts.test(p['host'])))
533 {
534 return 'URL host is not allowed';
535 }
536 }
537 }
538 }