From a40b406dc84659cd96f1688a061b296d540e64df Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Mon, 6 Jan 2014 14:53:55 +0100
Subject: [PATCH] OO-922: add a check box to force downloads of files in the
 folder component

---
 .../security/SecurityAdminController.java     | 19 ++++++++----
 .../security/_i18n/LocalStrings_de.properties |  1 +
 .../core/commons/modules/bc/FolderModule.java | 31 +++++++++++++++----
 .../bc/_spring/folderModuleCorecontext.xml    |  1 +
 .../modules/bc/commands/CmdServeResource.java | 21 +++++++++++--
 .../olat/core/util/vfs/VFSMediaResource.java  |  2 +-
 .../resources/serviceconfig/olat.properties   |  3 ++
 7 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/src/main/java/org/olat/admin/security/SecurityAdminController.java b/src/main/java/org/olat/admin/security/SecurityAdminController.java
index 139c36d0bd1..eac71533ac6 100644
--- a/src/main/java/org/olat/admin/security/SecurityAdminController.java
+++ b/src/main/java/org/olat/admin/security/SecurityAdminController.java
@@ -21,6 +21,7 @@ package org.olat.admin.security;
 
 import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.modules.bc.FolderModule;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -38,12 +39,15 @@ import org.olat.core.gui.control.WindowControl;
  */
 public class SecurityAdminController extends FormBasicController {
 	
-	private MultipleSelectionElement wikiEl, topFrameEl;
+	private MultipleSelectionElement wikiEl, topFrameEl, forceDownloadEl;
+
+	private final FolderModule folderModule;
 	private final BaseSecurityModule securityModule;
 	
 	public SecurityAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 		securityModule = CoreSpringFactory.getImpl(BaseSecurityModule.class);
+		folderModule = CoreSpringFactory.getImpl(FolderModule.class);
 		initForm(ureq);
 	}
 
@@ -63,6 +67,10 @@ public class SecurityAdminController extends FormBasicController {
 		wikiEl = uifactory.addCheckboxesHorizontal("sec.wiki", "sec.wiki", formLayout, frameKeys, frameValues, null);
 		wikiEl.select("on", securityModule.isWikiEnabled());
 		wikiEl.addActionListener(this, FormEvent.ONCHANGE);
+
+		forceDownloadEl = uifactory.addCheckboxesHorizontal("sec.download", "sec.force.download", formLayout, frameKeys, frameValues, null);
+		forceDownloadEl.select("on", folderModule.isForceDownload());
+		forceDownloadEl.addActionListener(this, FormEvent.ONCHANGE);
 	}
 	
 	@Override
@@ -78,6 +86,9 @@ public class SecurityAdminController extends FormBasicController {
 		} else if(wikiEl == source) {
 			boolean enabled = wikiEl.isAtLeastSelected(1);
 			securityModule.setWikiEnabled(enabled);
+		} else if(forceDownloadEl == source) {
+			boolean enabled = forceDownloadEl.isAtLeastSelected(1);
+			folderModule.setForceDownload(enabled);
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
@@ -86,8 +97,4 @@ public class SecurityAdminController extends FormBasicController {
 	protected void formOK(UserRequest ureq) {
 		//
 	}
-
-
-	
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties
index 7f234fe55cf..62315493b4d 100644
--- a/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/admin/security/_i18n/LocalStrings_de.properties
@@ -6,6 +6,7 @@ chelp.ced-sec.title=Sicherheitsaspekten von OpenOLAT
 help.hover.sec=Hilfe zur Sicherheits in OpenOLAT konfigurieren
 sec.title=Sicherheitsaspekten von OpenOLAT
 sec.description=Sie k\u00F6nnen hier ein paar Sicherheitsentscheidung nehmen
+sec.force.download=Datei herunterladen
 sec.topframe=Enforce top frame
 sec.wiki=Wiki
 
diff --git a/src/main/java/org/olat/core/commons/modules/bc/FolderModule.java b/src/main/java/org/olat/core/commons/modules/bc/FolderModule.java
index 9ef16f148fe..c92065da375 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/FolderModule.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/FolderModule.java
@@ -33,6 +33,7 @@ import org.olat.core.configuration.PersistedProperties;
 import org.olat.core.helpers.Settings;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.version.FolderVersioningConfigurator;
 
 /**
@@ -42,15 +43,18 @@ import org.olat.core.util.vfs.version.FolderVersioningConfigurator;
  */
 public class FolderModule extends AbstractOLATModule {	
 	
-	OLog log = Tracing.createLoggerFor(FolderModule.class);
+	private static final OLog log = Tracing.createLoggerFor(FolderModule.class);
 	private static final String CONFIG_ROOT = "Root";
 	private static final String CONFIG_LIMITULMB = "LimitULMB";
 	private static final String CONFIG_EDITFILESIZELIMIT = "EditFileSizeLimit";
 	private static final String CONFIG_QUOTAMB = "QuotaMB";
 	private static final String CONFIG_SENDDOCLINKONLY = "SendDocLinkOnly";
 	private static final String CONFIG_SENDDOCTOEXTERN = "SendDocToExtern";
+	private static final String CONFIG_FORCE_DOWNLOAD = "forceDownload";
 	private FolderVersioningConfigurator versioning;
 	
+	private String forceDownload;
+	
 	/**
 	 * [used by spring]
 	 */
@@ -99,18 +103,26 @@ public class FolderModule extends AbstractOLATModule {
 		// create tmp directory
 		File fTmp = new File(FolderConfig.getCanonicalTmpDir());
 		fTmp.mkdirs();
-		
+
+		forceDownload = getStringConfigParameter(CONFIG_FORCE_DOWNLOAD, "true", true);
 	}
 
 	@Override
 	protected void initFromChangedProperties() {
-		// TODO Auto-generated method stub
-		
+		updateProperties();
 	}
 
 	@Override
 	public void init() {
 		FolderConfig.setVersioningConfigurator(versioning);
+		updateProperties();
+	}
+	
+	private void updateProperties() {
+		String enabled = getStringPropertyValue(CONFIG_FORCE_DOWNLOAD, true);
+		if(StringHelper.containsNonWhitespace(enabled)) {
+			forceDownload = enabled;
+		}
 	}
 
 	/**
@@ -125,6 +137,13 @@ public class FolderModule extends AbstractOLATModule {
 	public void setPersistedProperties(PersistedProperties persistedProperties) {
 		this.moduleConfigProperties = persistedProperties;
 	}
-	
 
-}
+	public boolean isForceDownload() {
+		return "true".equals(forceDownload);
+	}
+
+	public void setForceDownload(boolean enable) {
+		String enabled = enable ? "true" : "false";
+		setStringProperty(CONFIG_FORCE_DOWNLOAD, enabled, true);
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/modules/bc/_spring/folderModuleCorecontext.xml b/src/main/java/org/olat/core/commons/modules/bc/_spring/folderModuleCorecontext.xml
index d2c928d7cfd..65f2f9d44aa 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/_spring/folderModuleCorecontext.xml
+++ b/src/main/java/org/olat/core/commons/modules/bc/_spring/folderModuleCorecontext.xml
@@ -33,6 +33,7 @@
 				SendDocLinkOnly=${folder.sendDocumentLinkOnly}
 				<!--   max edit filesize for online-editing in Bytes -->
 				EditFileSizeLimit=${folder.editFileSizeLimitBytes}
+				forceDownload=${folder.force.download}
              </value>
       </property>
 </bean>
diff --git a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdServeResource.java b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdServeResource.java
index ef4cedad879..718539a93d5 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdServeResource.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdServeResource.java
@@ -30,7 +30,9 @@ import java.io.InputStream;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.modules.bc.FolderLoggingAction;
+import org.olat.core.commons.modules.bc.FolderModule;
 import org.olat.core.commons.modules.bc.components.FolderComponent;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
@@ -78,6 +80,8 @@ public class CmdServeResource implements FolderCommand {
 		} else if(!(vfsitem instanceof VFSLeaf)) {
 			mr = new NotFoundMediaResource(path);
 		} else {
+			boolean forceDownload = CoreSpringFactory.getImpl(FolderModule.class).isForceDownload();
+			
 			VFSLeaf vfsfile = (VFSLeaf)vfsitem;
 			if (path.toLowerCase().endsWith(".html") || path.toLowerCase().endsWith(".htm")) {
 				// setCurrentURI(path);
@@ -106,7 +110,7 @@ public class CmdServeResource implements FolderCommand {
 				g_encoding = enc;
 				if (useLoaded) {
 					StringMediaResource smr = new StringMediaResource();
-					String mimetype = "text/html;charset=" + enc;
+					String mimetype = forceDownload ? VFSMediaResource.MIME_TYPE_FORCE_DOWNLOAD : "text/html;charset=" + enc;
 					smr.setContentType(mimetype);
 					smr.setEncoding(enc);
 					smr.setData(page);
@@ -117,6 +121,9 @@ public class CmdServeResource implements FolderCommand {
 					// again)
 					VFSMediaResource vmr = new VFSMediaResource(vfsfile);
 					vmr.setEncoding(enc);
+					if(forceDownload) {
+						vmr.setDownloadable(true);
+					}
 					mr = vmr;
 				}
 			} else if (path.endsWith(".js")) { // a javascript library
@@ -127,12 +134,20 @@ public class CmdServeResource implements FolderCommand {
 				// together with the mime-type, which is wrong.
 				// so we assume the .js file has the same encoding as the html file
 				// that loads the .js file
-				if (g_encoding != null) vmr.setEncoding(g_encoding);
+				if (g_encoding != null) {
+					vmr.setEncoding(g_encoding);
+				}
+				if(forceDownload) {
+					vmr.setDownloadable(true);
+				}
 				mr = vmr;
 			} else if (path.endsWith(".txt")) {
 				//text files created in OpenOLAT are utf-8, prefer this encoding
 				VFSMediaResource vmr = new VFSMediaResource(vfsfile);
 				vmr.setEncoding("utf-8");
+				if(forceDownload) {
+					vmr.setDownloadable(true);
+				}
 				mr = vmr;
 			} else {
 				// binary data: not .html, not .htm, not .js -> treated as is
@@ -140,6 +155,8 @@ public class CmdServeResource implements FolderCommand {
 				// This is to prevent the login prompt in Excel, Word and PowerPoint
 				if (path.endsWith(".xlsx") || path.endsWith(".pptx") || path.endsWith(".docx")) {
 					vmr.setDownloadable(true);
+				} else if(forceDownload) {
+					vmr.setDownloadable(true);
 				}
 				mr = vmr;
 			}
diff --git a/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java b/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java
index b98be6062ee..1bd5932b0ee 100644
--- a/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java
+++ b/src/main/java/org/olat/core/util/vfs/VFSMediaResource.java
@@ -41,7 +41,7 @@ public class VFSMediaResource implements MediaResource {
 
 	private static final String MIME_TYPE_OCTET_STREAM = "application/octet-stream";
 	//use this pseudo mime-type to force download on ie 6
-	private static final String MIME_TYPE_FORCE_DOWNLOAD = "application/force-download";
+	public static final String MIME_TYPE_FORCE_DOWNLOAD = "application/force-download";
 	private VFSLeaf vfsLeaf;
 	private String encoding;
 	boolean unknownMimeType = false;
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index 4121fb722c6..36d2c8c05d9 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -43,6 +43,9 @@ folder.sendDocumentToExtern=true
 folder.sendDocumentLinkOnly=true
 # file size limit for HTML and text editor is 1MB
 folder.editFileSizeLimitBytes=1048576
+#force download of the files
+folder.force.download=true
+folder.force.download.values=true,false
 
 ########################################################################
 # Application settings
-- 
GitLab