validation.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Puter.
  5. *
  6. * Puter is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. /* ~~~ Filesystem validation ~~~
  20. This module contains functions that validate filesystem operations.
  21. */
  22. /* eslint-disable no-control-regex */
  23. const config = require("../config");
  24. const path_excludes = () => /[\x00-\x1F]/g;
  25. const node_excludes = () => /[/\x00-\x1F]/g;
  26. // this characters are not allowed in path names because
  27. // they might be used to trick the user into thinking
  28. // a filename is different from what it actually is.
  29. const safety_excludes = [
  30. /[\u202A-\u202E]/, // RTL and LTR override
  31. /[\u200E-\u200F]/, // RTL and LTR mark
  32. /[\u2066-\u2069]/, // RTL and LTR isolate
  33. /[\u2028-\u2029]/, // line and paragraph separator
  34. /[\uFF01-\uFF5E]/, // fullwidth ASCII
  35. /[\u2060]/, // word joiner
  36. /[\uFEFF]/, // zero width no-break space
  37. /[\uFFFE-\uFFFF]/, // non-characters
  38. ];
  39. const is_valid_node_name = function is_valid_node_name (name) {
  40. if ( typeof name !== 'string' ) return false;
  41. if ( node_excludes().test(name) ) return false;
  42. for ( const exclude of safety_excludes ) {
  43. if ( exclude.test(name) ) return false;
  44. }
  45. if ( name.length > config.max_fsentry_name_length ) return false;
  46. // Names are allowed to contain dots, but cannot
  47. // contain only dots. (this covers '.' and '..')
  48. const name_without_dots = name.replace(/\./g, '');
  49. if ( name_without_dots.length < 1 ) return false;
  50. return true;
  51. }
  52. const is_valid_path = function is_valid_path (path, {
  53. no_relative_components,
  54. allow_path_fragment,
  55. } = {}) {
  56. if ( typeof path !== 'string' ) return false;
  57. if ( path.length < 1 ) false;
  58. if ( path_excludes().test(path) ) return false;
  59. for ( const exclude of safety_excludes ) {
  60. if ( exclude.test(path) ) return false;
  61. }
  62. if ( ! allow_path_fragment ) if ( path[0] !== '/' && path[0] !== '.' ) {
  63. return false;
  64. }
  65. if ( no_relative_components ) {
  66. const components = path.split('/');
  67. for ( const component of components ) {
  68. if ( component === '' ) continue;
  69. const name_without_dots = component.replace(/\./g, '');
  70. if ( name_without_dots.length < 1 ) return false;
  71. }
  72. }
  73. return true;
  74. }
  75. module.exports = {
  76. is_valid_node_name,
  77. is_valid_path,
  78. };