Merge pull request #315 from sharelatex/bg-validate-filenames-client

validate filenames on the client
This commit is contained in:
Brian Gough 2018-02-08 09:16:05 +00:00 committed by GitHub
commit 9224e164fe
6 changed files with 69 additions and 10 deletions

View file

@ -119,6 +119,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
ng-blur="finishRenaming()",
select-name-when="entity.renaming",
on-enter="finishRenaming()"
valid-file
)
span.dropdown.entity-menu-toggle(
@ -207,6 +208,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
ng-blur="finishRenaming()",
select-name-when="entity.renaming",
on-enter="finishRenaming()"
valid-file
)
span.dropdown.entity-menu-toggle(
@ -316,10 +318,10 @@ script(type='text/ng-template', id='newDocModalTemplate')
ng-model="inputs.name",
on-enter="create()",
select-name-on="open",
ng-pattern="validFileRegex",
valid-file,
name="name"
)
.text-danger.row-spaced-small(ng-show="newDocForm.name.$error.pattern")
.text-danger.row-spaced-small(ng-show="newDocForm.name.$error.validFile")
| #{translate('files_cannot_include_invalid_characters')}
.modal-footer
button.btn.btn-default(
@ -347,10 +349,10 @@ script(type='text/ng-template', id='newFolderModalTemplate')
ng-model="inputs.name",
on-enter="create()",
select-name-on="open",
ng-pattern="validFileRegex",
valid-file,
name="name"
)
.text-danger.row-spaced-small(ng-show="newFolderForm.name.$error.pattern")
.text-danger.row-spaced-small(ng-show="newFolderForm.name.$error.validFile")
| #{translate('files_cannot_include_invalid_characters')}
.modal-footer
button.btn.btn-default(

View file

@ -20,6 +20,7 @@ define [
"ide/hotkeys/index"
"ide/wordcount/index"
"ide/directives/layout"
"ide/directives/validFile"
"ide/services/ide"
"__IDE_CLIENTSIDE_INCLUDES__"
"analytics/AbTestingManager"

View file

@ -0,0 +1,47 @@
# This file is shared between the frontend and server code of web, so that
# filename validation is the same in both implementations.
# Both copies must be kept in sync:
# app/coffee/Features/Project/SafePath.coffee
# public/coffee/ide/directives/SafePath.coffee
load = () ->
BADCHAR_RX = ///
[
\/ # no slashes
\* # no asterisk
\u0000-\u001F # no control characters (0-31)
\u007F # no delete
\u0080-\u009F # no unicode control characters (C1)
\uD800-\uDFFF # no unicode surrogate characters
]
///g
BADFILE_RX = ///
(^\.$) # reject . as a filename
| (^\.\.$) # reject .. as a filename
| (^\s+) # reject leading space
| (\s+$) # reject trailing space
///g
MAX_PATH = 1024 # Maximum path length, in characters. This is fairly arbitrary.
SafePath =
clean: (filename) ->
filename = filename.replace BADCHAR_RX, '_'
# for BADFILE_RX replace any matches with an equal number of underscores
filename = filename.replace BADFILE_RX, (match) ->
return new Array(match.length + 1).join("_")
return filename
isCleanFilename: (filename) ->
return SafePath.isAllowedLength(filename) &&
not filename.match(BADCHAR_RX) &&
not filename.match(BADFILE_RX)
isAllowedLength: (pathname) ->
return pathname.length > 0 && pathname.length <= MAX_PATH
if define?
define [], load
else
module.exports = load()

View file

@ -0,0 +1,12 @@
define [
"base"
"ide/directives/SafePath"
], (App, SafePath) ->
App.directive "validFile", () ->
return {
require: 'ngModel'
link: (scope, element, attrs, ngModelCtrl) ->
ngModelCtrl.$validators.validFile = (filename) ->
return SafePath.isCleanFilename filename
}

View file

@ -44,8 +44,6 @@ define [
App.controller "NewDocModalController", [
"$scope", "ide", "$modalInstance", "$timeout", "parent_folder",
($scope, ide, $modalInstance, $timeout, parent_folder) ->
$scope.validFileRegex = ide.validFileRegex
$scope.inputs =
name: "name.tex"
$scope.state =
@ -78,8 +76,6 @@ define [
App.controller "NewFolderModalController", [
"$scope", "ide", "$modalInstance", "$timeout", "parent_folder",
($scope, ide, $modalInstance, $timeout, parent_folder) ->
$scope.validFileRegex = ide.validFileRegex
$scope.inputs =
name: "name"
$scope.state =

View file

@ -32,8 +32,9 @@ define [
return if !$scope.entity.renaming
name = $scope.inputs.name
if !name.match(new RegExp(ide.validFileRegex))
# validator will set name to undefined for invalid filenames
if !name?
# Showing the modal blurs the rename box which calls us again
# so track this with the invalidModalShowing flag
return if invalidModalShowing