diff --git a/src/main/java/org/olat/core/commons/editor/fileeditor/FileEditorController.java b/src/main/java/org/olat/core/commons/editor/fileeditor/FileEditorController.java
index 66445bcf9b74671c9ff184a53268dd9816bb84dd..8bf2057155d34e24620d8ea9879ee06f717475c2 100644
--- a/src/main/java/org/olat/core/commons/editor/fileeditor/FileEditorController.java
+++ b/src/main/java/org/olat/core/commons/editor/fileeditor/FileEditorController.java
@@ -28,6 +28,7 @@ package org.olat.core.commons.editor.fileeditor;
 
 import org.olat.core.commons.controllers.linkchooser.CustomLinkTreeModel;
 import org.olat.core.commons.editor.htmleditor.HTMLEditorController;
+import org.olat.core.commons.editor.htmleditor.HTMLReadOnlyController;
 import org.olat.core.commons.editor.htmleditor.WysiwygFactory;
 import org.olat.core.commons.editor.plaintexteditor.TextEditorController;
 import org.olat.core.commons.modules.bc.components.FolderComponent;
@@ -77,42 +78,47 @@ public class FileEditorController extends BasicController {
 //		}
 		
 
-		// start HTML editor with the folders root folder as base and the file
-		// path as a relative path from the root directory. But first check if the 
-		// root directory is wirtable at all (e.g. not the case in users personal 
-		// briefcase), and seach for the next higher directory that is writable.
-		String relFilePath = "/" + vfsLeaf.getName();
-		// add current container path if not at root level
-		if (!folderComponent.getCurrentContainerPath().equals("/")) { 
-			relFilePath = folderComponent.getCurrentContainerPath() + relFilePath;
-		}
-		VFSContainer writableRootContainer = folderComponent.getRootContainer();
-		ContainerAndFile result = VFSManager.findWritableRootFolderFor(writableRootContainer, relFilePath);
-		if (result != null) {
-			if(vfsLeaf.getParentContainer() != null) {
-				writableRootContainer = vfsLeaf.getParentContainer();
-				relFilePath = vfsLeaf.getName();
-			} else {
-				writableRootContainer = result.getContainer();
-			}
-		} else {
-			// use fallback that always work: current directory and current file
-			relFilePath = vfsLeaf.getName();
-			writableRootContainer = folderComponent.getCurrentContainer(); 
-		}
+		
 		// launch plaintext or html editor depending on file type
-		if (relFilePath.endsWith(".html") || relFilePath.endsWith(".htm")) {
-			CustomLinkTreeModel customLinkTreeModel = folderComponent.getCustomLinkTreeModel(); 
-			if (customLinkTreeModel != null) {
-				editCtrl = WysiwygFactory.createWysiwygControllerWithInternalLink(ureq, getWindowControl(), writableRootContainer, relFilePath, true, customLinkTreeModel);
-				((HTMLEditorController)editCtrl).setNewFile(false);
-			} else {				
-				editCtrl = WysiwygFactory.createWysiwygController(ureq, getWindowControl(), writableRootContainer, relFilePath, true, true);
-				((HTMLEditorController)editCtrl).setNewFile(false);
+		if (vfsLeaf.getName().endsWith(".html") || vfsLeaf.getName().endsWith(".htm")) {
+			if (secCallback.canEdit()) {
+				// start HTML editor with the folders root folder as base and the file
+				// path as a relative path from the root directory. But first check if the 
+				// root directory is wirtable at all (e.g. not the case in users personal 
+				// briefcase), and seach for the next higher directory that is writable.
+				String relFilePath = "/" + vfsLeaf.getName();
+				// add current container path if not at root level
+				if (!folderComponent.getCurrentContainerPath().equals("/")) { 
+					relFilePath = folderComponent.getCurrentContainerPath() + relFilePath;
+				}
+				VFSContainer writableRootContainer = folderComponent.getRootContainer();
+				ContainerAndFile result = VFSManager.findWritableRootFolderFor(writableRootContainer, relFilePath);
+				if (result != null) {
+					if(vfsLeaf.getParentContainer() != null) {
+						writableRootContainer = vfsLeaf.getParentContainer();
+						relFilePath = vfsLeaf.getName();
+					} else {
+						writableRootContainer = result.getContainer();
+					}
+				} else {
+					// use fallback that always work: current directory and current file
+					relFilePath = vfsLeaf.getName();
+					writableRootContainer = folderComponent.getCurrentContainer(); 
+				}
+				CustomLinkTreeModel customLinkTreeModel = folderComponent.getCustomLinkTreeModel();
+				if (customLinkTreeModel != null) {
+					editCtrl = WysiwygFactory.createWysiwygControllerWithInternalLink(ureq, getWindowControl(), writableRootContainer, relFilePath, true, customLinkTreeModel);
+					((HTMLEditorController)editCtrl).setNewFile(false);
+				} else {				
+					editCtrl = WysiwygFactory.createWysiwygController(ureq, getWindowControl(), writableRootContainer, relFilePath, true, true);
+					((HTMLEditorController)editCtrl).setNewFile(false);
+				}
+			} else {
+				editCtrl = new HTMLReadOnlyController(ureq, getWindowControl(), vfsLeaf.getParentContainer(), vfsLeaf.getName(), secCallback.canClose());
 			}
 		}
 		else {
-			editCtrl = new TextEditorController(ureq, getWindowControl(), vfsLeaf, "utf-8", false);
+			editCtrl = new TextEditorController(ureq, getWindowControl(), vfsLeaf, "utf-8", !secCallback.canEdit());
 		}
 		listenTo(editCtrl);
 		
diff --git a/src/main/java/org/olat/core/commons/editor/htmleditor/HTMLReadOnlyController.java b/src/main/java/org/olat/core/commons/editor/htmleditor/HTMLReadOnlyController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9818cf5ab985d5b73b38d7ac544d4ac0ae5ebb5b
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/editor/htmleditor/HTMLReadOnlyController.java
@@ -0,0 +1,72 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.core.commons.editor.htmleditor;
+
+import org.olat.core.commons.modules.singlepage.SinglePageController;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.util.vfs.VFSContainer;
+
+/**
+ * 
+ * Initial date: 25 Mar 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class HTMLReadOnlyController extends BasicController {
+	
+	private Link closeLink;
+	private SinglePageController singlePageCtrl;
+
+	public HTMLReadOnlyController(UserRequest ureq, WindowControl wControl, VFSContainer rootContainer, String fileName, boolean showClose) {
+		super(ureq, wControl);
+		
+		VelocityContainer mainVC = createVelocityContainer("readonly");
+		
+		singlePageCtrl = new SinglePageController(ureq, wControl, rootContainer, fileName, false);
+		listenTo(singlePageCtrl);
+		mainVC.put("content", singlePageCtrl.getInitialComponent());
+		
+		if (showClose) {
+			closeLink = LinkFactory.createButton("close", mainVC, this);
+		}
+		
+		putInitialPanel(mainVC);
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if (source == closeLink) {
+			fireEvent(ureq, Event.DONE_EVENT);
+		}
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+}
diff --git a/src/main/java/org/olat/core/commons/editor/htmleditor/_content/readonly.html b/src/main/java/org/olat/core/commons/editor/htmleditor/_content/readonly.html
new file mode 100644
index 0000000000000000000000000000000000000000..7b7dad61e3593247bf3d7772c336cd83058bd6ab
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/editor/htmleditor/_content/readonly.html
@@ -0,0 +1,6 @@
+<div class="o_html_readonly">
+$r.render("content")
+#if($r.available("close"))
+	<div class="o_button_group">$r.render("close")</div>
+#end
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdOpenContent.java b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdOpenContent.java
index 85e5f041e3959ef54f6acd35085bb36010589b1c..155fe750e76b3e9e33f55ad07bfb65e2d76c3260 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdOpenContent.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdOpenContent.java
@@ -112,7 +112,11 @@ public class CmdOpenContent extends BasicController implements FolderCommand {
 			return null;
 		}
 		
-		VFSLeafEditorSecurityCallback secCallback = VFSLeafEditorSecurityCallbackBuilder.builder().build();
+		VFSContainer container = VFSManager.findInheritingSecurityCallbackContainer(folderComponent.getCurrentContainer());
+		VFSSecurityCallback containerSecCallback = container.getLocalSecurityCallback();
+		VFSLeafEditorSecurityCallback secCallback = VFSLeafEditorSecurityCallbackBuilder.builder()
+				.canEdit(containerSecCallback.canWrite())
+				.build();
 		editCtrl = editor.get().getRunController(ureq, wControl, vfsLeaf, folderComponent, getIdentity(), secCallback);
 		listenTo(editCtrl);
 		
diff --git a/src/main/java/org/olat/core/commons/modules/singlepage/SinglePageController.java b/src/main/java/org/olat/core/commons/modules/singlepage/SinglePageController.java
index 184c2cfe893b7e585d4f40d22ef1eebb0ea70275..9192c1c00b13661cd449cd579240ec22dc7207b8 100644
--- a/src/main/java/org/olat/core/commons/modules/singlepage/SinglePageController.java
+++ b/src/main/java/org/olat/core/commons/modules/singlepage/SinglePageController.java
@@ -99,17 +99,6 @@ public class SinglePageController extends BasicController implements CloneableCo
 	private VFSContainer g_new_rootContainer;
 	private Long courseRepoKey;
 	
-	/**
-	 * 
-	 * @param ureq
-	 * @param wControl
-	 * @param inIframe
-	 * @param rootContainer
-	 * @param fileName
-	 * @param currentUri
-	 * @param allowRelativeLinks
-	 * @param showHomeLink
-	 */
 	public SinglePageController(UserRequest ureq, WindowControl wControl, VFSContainer rootContainer, String fileName,
 			boolean allowRelativeLinks) {
 		//default behavior is to show the home link in a single page