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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

BuiltInFilters.js

Zuletzt modifiziert: 09.10.2024, 12:57 - Dateigröße: 11.47 KiB


 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  }