SafePath.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-undef,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * DS207: Consider shorter variations of null checks
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. // This file is shared between the frontend and server code of web, so that
  15. // filename validation is the same in both implementations.
  16. // Both copies must be kept in sync:
  17. // app/coffee/Features/Project/SafePath.coffee
  18. // public/coffee/ide/directives/SafePath.coffee
  19. const load = function() {
  20. let SafePath
  21. const BADCHAR_RX = new RegExp(
  22. `\
  23. [\
  24. \\/\
  25. \\\\\
  26. \\*\
  27. \\u0000-\\u001F\
  28. \\u007F\
  29. \\u0080-\\u009F\
  30. \\uD800-\\uDFFF\
  31. ]\
  32. `,
  33. 'g'
  34. )
  35. const BADFILE_RX = new RegExp(
  36. `\
  37. (^\\.$)\
  38. |(^\\.\\.$)\
  39. |(^\\s+)\
  40. |(\\s+$)\
  41. `,
  42. 'g'
  43. )
  44. // Put a block on filenames which match javascript property names, as they
  45. // can cause exceptions where the code puts filenames into a hash. This is a
  46. // temporary workaround until the code in other places is made safe against
  47. // property names.
  48. //
  49. // The list of property names is taken from
  50. // ['prototype'].concat(Object.getOwnPropertyNames(Object.prototype))
  51. const BLOCKEDFILE_RX = new RegExp(`\
  52. ^(\
  53. prototype\
  54. |constructor\
  55. |toString\
  56. |toLocaleString\
  57. |valueOf\
  58. |hasOwnProperty\
  59. |isPrototypeOf\
  60. |propertyIsEnumerable\
  61. |__defineGetter__\
  62. |__lookupGetter__\
  63. |__defineSetter__\
  64. |__lookupSetter__\
  65. |__proto__\
  66. )$\
  67. `)
  68. const MAX_PATH = 1024 // Maximum path length, in characters. This is fairly arbitrary.
  69. return (SafePath = {
  70. clean(filename) {
  71. filename = filename.replace(BADCHAR_RX, '_')
  72. // for BADFILE_RX replace any matches with an equal number of underscores
  73. filename = filename.replace(BADFILE_RX, match =>
  74. new Array(match.length + 1).join('_')
  75. )
  76. // replace blocked filenames 'prototype' with '@prototype'
  77. filename = filename.replace(BLOCKEDFILE_RX, '@$1')
  78. return filename
  79. },
  80. isCleanFilename(filename) {
  81. return (
  82. SafePath.isAllowedLength(filename) &&
  83. !filename.match(BADCHAR_RX) &&
  84. !filename.match(BADFILE_RX)
  85. )
  86. },
  87. isAllowedLength(pathname) {
  88. return pathname.length > 0 && pathname.length <= MAX_PATH
  89. }
  90. })
  91. }
  92. if (typeof define !== 'undefined' && define !== null) {
  93. define([], load)
  94. } else {
  95. module.exports = load()
  96. }