From da3a7385c34005f0106fb8ed83703aba76783a7e Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Tue, 25 Aug 2020 18:16:51 +0200
Subject: [PATCH] OO-4871: validate filename against + character in single page

---
 .../FileLinkChooserController.java            |  4 ++-
 .../linkchooser/LinkChooserController.java    |  5 ++--
 .../linkchooser/MediaChooserController.java   |  6 +---
 .../modules/bc/FileCopyController.java        |  2 +-
 .../modules/bc/FileUploadController.java      | 28 ++++++++++++++++++-
 .../richText/RichTextElementComponent.java    |  4 +--
 .../ui/DialogCourseNodeRunController.java     |  2 +-
 7 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java b/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java
index 7c44930216e..cc3f4330989 100644
--- a/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java
+++ b/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java
@@ -98,7 +98,8 @@ public class FileLinkChooserController extends BasicController {
 	 *          index.html
 	 */
 	public FileLinkChooserController(UserRequest ureq, WindowControl wControl,
-			VFSContainer rootDir, String uploadRelPath, String absolutePath, String[] suffixes, boolean uriValidation, String fileName) {
+			VFSContainer rootDir, String uploadRelPath, String absolutePath, String[] suffixes,
+			boolean uriValidation, boolean htmlLinkValidation, String fileName) {
 		super(ureq, wControl);
 		this.fileName = fileName;
 		this.suffixes = suffixes;
@@ -173,6 +174,7 @@ public class FileLinkChooserController extends BasicController {
 			
 			uploadCtr = new FileUploadController(wControl, fileUploadBase, ureq, uploadLimit, remainingSpace,
 					mimeTypes, uriValidation, true, false, true, true, false);
+			uploadCtr.setHtmlLinkValidation(htmlLinkValidation);
 			listenTo(uploadCtr);
 			// set specific upload path
 			uploadCtr.setUploadRelPath(uploadRelPath);
diff --git a/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java b/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java
index fa83aabebf4..2b40b962ffe 100644
--- a/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java
+++ b/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java
@@ -73,7 +73,7 @@ public class LinkChooserController extends BasicController {
 	 *          internalLinkTreeModel is null.
 	 */
 	public LinkChooserController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir,
-			String uploadRelPath, String absolutPath, String[] suffixes, boolean uriValidation, String fileName,
+			String uploadRelPath, String absolutPath, String[] suffixes, boolean uriValidation, boolean htmlExtraValidation, String fileName,
 			CustomLinkTreeModel customLinkTreeModel, CustomLinkTreeModel toolLinkTreeModel, boolean allowCustomMediaChooserFactory) {
 		super(ureq, wControl);
 		
@@ -82,7 +82,8 @@ public class LinkChooserController extends BasicController {
 		linkChooserTabbedPane = new TabbedPane("linkChooserTabbedPane", ureq.getLocale());
 		tabbedPaneViewVC.put("linkChooserTabbedPane", linkChooserTabbedPane);
 
-		fileLinkChooserController = new FileLinkChooserController(ureq, wControl, rootDir, uploadRelPath, absolutPath, suffixes, uriValidation, fileName);		
+		fileLinkChooserController = new FileLinkChooserController(ureq, wControl, rootDir, uploadRelPath, absolutPath, suffixes,
+				uriValidation, htmlExtraValidation, fileName);		
 		listenTo(fileLinkChooserController);
 		linkChooserTabbedPane.addTab(translate("linkchooser.tabbedpane.label.filechooser"), fileLinkChooserController.getInitialComponent());
 		
diff --git a/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java b/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java
index d3cbcb333b3..cfb9ced1076 100644
--- a/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java
+++ b/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java
@@ -64,13 +64,9 @@ public class MediaChooserController extends LinkChooserController {
 	 */
 	public MediaChooserController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir, String uploadRelPath, String[] suffixes, String fileName,
 			CustomLinkTreeModel customLinkTreeModel, boolean allowCustomMediaFactory) {
-		super(ureq, wControl, rootDir, uploadRelPath, null, suffixes, false, fileName, customLinkTreeModel, null, allowCustomMediaFactory);
+		super(ureq, wControl, rootDir, uploadRelPath, null, suffixes, true, false, fileName, customLinkTreeModel, null, allowCustomMediaFactory);
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {		
 		fireEvent(ureq, event);
diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java b/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java
index 449e576763a..c5a1dcb9c84 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java
@@ -91,7 +91,7 @@ public class FileCopyController extends LinkChooserController {
 	
 	public FileCopyController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir,
 			FolderComponent folderComponent) {
-		super(ureq, wControl, rootDir, null, null, null, false, "", null, null, true);
+		super(ureq, wControl, rootDir, null, null, null, false, false, "", null, null, true);
 		this.folderComponent = folderComponent;
 	}
 	
diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java
index cdab92c7cf5..b622e13a804 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java
@@ -35,6 +35,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 import java.util.regex.Pattern;
@@ -108,7 +109,14 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author Florian Gnägi
  */
 public class FileUploadController extends FormBasicController {
-	
+	/**
+	 * Extra validation for the htmlLinkValidation option
+	 */
+	private static final char[] HTML_EXTRA_FORBIDDEN_CHARS =  { '+' };
+	static {
+		Arrays.sort(HTML_EXTRA_FORBIDDEN_CHARS);
+	}
+
 	private static final String[] resizeKeys = new String[]{"resize"};
 	private int status = FolderCommandStatus.STATUS_SUCCESS;
 
@@ -129,6 +137,7 @@ public class FileUploadController extends FormBasicController {
 	private long remainingQuotKB;
 	private Set<String> mimeTypes;
 	private boolean uriValidation;
+	private boolean htmlLinkValidation;
 	//
 	// Form elements
 	private FileElement fileEl;
@@ -836,6 +845,14 @@ public class FileUploadController extends FormBasicController {
 		}
 	}
 
+	public boolean isHtmlLinkValidation() {
+		return htmlLinkValidation;
+	}
+
+	public void setHtmlLinkValidation(boolean htmlLinkValidation) {
+		this.htmlLinkValidation = htmlLinkValidation;
+	}
+
 	public String getNewFileName() {
 		return (this.newFile != null) ? this.newFile.getName() : null; 
 	}
@@ -954,6 +971,15 @@ public class FileUploadController extends FormBasicController {
 				itemEl.setErrorKey("cfile.name.notvalid.uri", null);
 				allOk &= false;
 			}
+		} else if(htmlLinkValidation) {
+			for(int i=0; i<filename.length(); i++) {
+				char character = filename.charAt(i);
+				if(Arrays.binarySearch(HTML_EXTRA_FORBIDDEN_CHARS, character) >= 0) {
+					itemEl.setErrorKey("cfile.name.notvalid", null);
+					allOk &= false;
+					break;
+				}
+			}
 		}
 		
 		return allOk;
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java
index 91b91a03101..d8232ed6551 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java
@@ -181,10 +181,10 @@ class RichTextElementComponent extends FormBaseComponentImpl {
 				CustomLinkTreeModel toolLinkTreeModel = config.getToolLinkTreeModel();
 				if (type.equals(CMD_FILEBROWSER)) {
 					// when in file mode we include the internal links to the selection
-					myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, uriValidation, fileName, linkBrowserCustomTreeModel, toolLinkTreeModel, allowCustomMediaFactory);			
+					myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, true, uriValidation, fileName, linkBrowserCustomTreeModel, toolLinkTreeModel, allowCustomMediaFactory);			
 				} else {
 					// in media or image mode, internal links make no sense here
-					myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, uriValidation, fileName, null, null, allowCustomMediaFactory);						
+					myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, true, uriValidation, fileName, null, null, allowCustomMediaFactory);						
 				}
 				return new LayoutMain3ColsController(lureq, lwControl, myLinkChooserController);
 			}
diff --git a/src/main/java/org/olat/course/nodes/dialog/ui/DialogCourseNodeRunController.java b/src/main/java/org/olat/course/nodes/dialog/ui/DialogCourseNodeRunController.java
index c8849c996b3..8599e9fe264 100644
--- a/src/main/java/org/olat/course/nodes/dialog/ui/DialogCourseNodeRunController.java
+++ b/src/main/java/org/olat/course/nodes/dialog/ui/DialogCourseNodeRunController.java
@@ -346,7 +346,7 @@ public class DialogCourseNodeRunController extends BasicController implements Ac
 	private class MyLinkChooserController extends LinkChooserController {
 		
 		public MyLinkChooserController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir, String uploadRelPath) {
-			super(ureq, wControl, rootDir, uploadRelPath, null, null, false, "", null, null, true);
+			super(ureq, wControl, rootDir, uploadRelPath, null, null, false, false, "", null, null, true);
 		}
 		
 		@Override
-- 
GitLab