diff --git a/src/main/java/org/olat/admin/AdminModuleDispatcher.java b/src/main/java/org/olat/admin/AdminModuleDispatcher.java
index ced3c8502198b7220b2c100901eaf1afff4a96ca..9225b47a48859a4f434ba50fd1d84a6fa4f89ea8 100644
--- a/src/main/java/org/olat/admin/AdminModuleDispatcher.java
+++ b/src/main/java/org/olat/admin/AdminModuleDispatcher.java
@@ -47,29 +47,26 @@ import org.olat.core.util.session.UserSessionManager;
  */
 public class AdminModuleDispatcher implements Dispatcher {
 	
-	private final static  String PARAMETER_CMD          = "cmd"; 
-	private final static  String PARAMETER_MSG          = "msg";
-	private final static  String PARAMETER_MAX_MESSAGE  = "maxsessions";
-	private final static  String PARAMETER_NBR_SESSIONS = "nbrsessions";
-	private final static  String PARAMETER_SESSIONTIMEOUT ="sec";
+	private static final String PARAMETER_CMD          = "cmd"; 
+	private static final String PARAMETER_MSG          = "msg";
+	private static final String PARAMETER_MAX_MESSAGE  = "maxsessions";
+	private static final String PARAMETER_NBR_SESSIONS = "nbrsessions";
+	private static final String PARAMETER_SESSIONTIMEOUT ="sec";
 	
-	private final static  String CMD_SET_MAINTENANCE_MESSAGE    = "setmaintenancemessage";
-	private final static  String CMD_SET_INFO_MESSAGE    				= "setinfomessage"; 
-	private final static  String CMD_SET_LOGIN_BLOCKED          = "setloginblocked";
-	private final static  String CMD_SET_LOGIN_NOT_BLOCKED      = "setloginnotblocked";
-	private final static  String CMD_SET_MAX_SESSIONS           = "setmaxsessions";
-	private final static  String CMD_INVALIDATE_ALL_SESSIONS    = "invalidateallsessions";
-	private final static  String CMD_INVALIDATE_OLDEST_SESSIONS = "invalidateoldestsessions";
-	private final static  String CMD_SET_SESSIONTIMEOUT         = "sessiontimeout";
+	private static final String CMD_SET_MAINTENANCE_MESSAGE    = "setmaintenancemessage";
+	private static final String CMD_SET_INFO_MESSAGE    	   = "setinfomessage"; 
+	private static final String CMD_SET_LOGIN_BLOCKED          = "setloginblocked";
+	private static final String CMD_SET_LOGIN_NOT_BLOCKED      = "setloginnotblocked";
+	private static final String CMD_SET_MAX_SESSIONS           = "setmaxsessions";
+	private static final String CMD_INVALIDATE_ALL_SESSIONS    = "invalidateallsessions";
+	private static final String CMD_INVALIDATE_OLDEST_SESSIONS = "invalidateoldestsessions";
+	private static final String CMD_SET_SESSIONTIMEOUT         = "sessiontimeout";
 	
-	
-	/** 
-	 * @see org.olat.core.dispatcher.Dispatcher#execute(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String)
-	 */
+
 	@Override
 	public void execute(HttpServletRequest request, HttpServletResponse response) {
 		String cmd = request.getParameter(PARAMETER_CMD);
-		if (cmd.equalsIgnoreCase(CMD_SET_MAINTENANCE_MESSAGE) || cmd.equalsIgnoreCase(CMD_SET_INFO_MESSAGE)) {
+		if (CMD_SET_MAINTENANCE_MESSAGE.equalsIgnoreCase(cmd) || CMD_SET_INFO_MESSAGE.equalsIgnoreCase(cmd)) {
 			handleSetMaintenanceOrInfoMessage(request, response, cmd);
 		} else {
 			if (CoreSpringFactory.getImpl(AdminModule.class).checkSessionAdminToken(request)) {
@@ -182,7 +179,4 @@ public class AdminModuleDispatcher implements Dispatcher {
 			DispatcherModule.sendForbidden(request.getPathInfo(), response);
 		}
 	}
-
-	
-
 }
diff --git a/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml b/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml
index 41bb7c78a64696b7a1e4026c501c5376b173a683..f9150b090e074dc7c11618cfc386c81c67f99249 100644
--- a/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml
+++ b/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml
@@ -5,7 +5,7 @@
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd">
 
-	<bean id="taskExecutorManager" class="org.olat.core.commons.services.taskexecutor.manager.TaskExecutorManagerImpl">
+	<bean id="taskExecutorManager" class="org.olat.core.commons.services.taskexecutor.manager.TaskExecutorManagerImpl" destroy-method="shutdown">
 		<constructor-arg index="0" ref="mpTaskExecutorService" />
 		<constructor-arg index="1" ref="sequentialTaskExecutorService" />
 		<constructor-arg index="2" ref="lowPriorityTaskSpringExecutorService" />
diff --git a/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java b/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java
index 03b4c3221b25b850a57d9d00f4a5485abdf66ab4..8476ec56519f1c915fdb4e3d53c9d0f93407f689 100644
--- a/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java
+++ b/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java
@@ -112,8 +112,10 @@ public class TaskExecutorManagerImpl implements TaskExecutorManager {
 	}
 
 	public void shutdown() {
-		taskExecutor.shutdown();
-		sequentialTaskExecutor.shutdown();
+		timer.cancel();
+		taskExecutor.shutdownNow();
+		sequentialTaskExecutor.shutdownNow();
+		lowPriorityTaskExecutor.shutdownNow();
 	}
 	
 	@Override
diff --git a/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java b/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java
index 3a75af5f3e13367fa4db9f9cc1590ab565e7f4ce..c2955f99976710d0a1ced4d55cd50b768f1c218f 100644
--- a/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java
@@ -199,7 +199,9 @@ public class LinkRenderer extends DefaultComponentRenderer {
 				try(StringOutput href = new StringOutput()) {
 					LinkPopupSettings popup = link.getPopup();
 					ubu.buildURI(href, new String[] { VelocityContainer.COMMAND_ID }, new String[] { command }, null, AJAXFlags.MODE_NORMAL);
-					sb.append("href=\"javascript:;\" onclick=\"o_openPopUp('").append(href).append("','")
+					boolean hasUrl = StringHelper.containsNonWhitespace(link.getUrl());
+					String hrefUrl = hasUrl ? link.getUrl() : "javascript:;";
+					sb.append("href=\"").append(hrefUrl).append("\" onclick=\"o_openPopUp('").append(href).append("','")
 					  .append(popup.getTarget()).append("',").append(popup.getWidth())
 					  .append(",").append(popup.getHeight()).append("); return false;\" ");
 				} catch(IOException e) {
diff --git a/src/main/java/org/olat/core/servlets/StaticServlet.java b/src/main/java/org/olat/core/servlets/StaticServlet.java
index 43b77cdba4a6a288c24c05907ad3ecf8872c75a5..319696843b400967df81ce3b18e1b9a798d1576a 100644
--- a/src/main/java/org/olat/core/servlets/StaticServlet.java
+++ b/src/main/java/org/olat/core/servlets/StaticServlet.java
@@ -107,7 +107,7 @@ public class StaticServlet extends HttpServlet {
 			// version provided - remove it
 			int start = pathInfo.indexOf("/", 2);
 			int end = pathInfo.length();
-			if(start <= end) {
+			if(start >= 2 && start <= end) {
 				String staticRelPath = pathInfo.substring(start, end);
 				String normalizedRelPath = ServletUtil.normalizePath(staticRelPath);
 				if (normalizedRelPath == null) {
@@ -170,7 +170,7 @@ public class StaticServlet extends HttpServlet {
 					}
 				}
 				// log as error, file exists but wrongly mapped
-				log.warn("File exists but not mapped using version - use StaticMediaDispatch methods to create URL of static files! invalid URI::" + request.getRequestURI());			
+				log.warn("File exists but not mapped using version - use StaticMediaDispatch methods to create URL of static files! invalid URI::{}", request.getRequestURI());			
 			}
 		}
 		
diff --git a/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml b/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml
index b864cac3ad13e1dcce943712d9a7bfa6a3c6c666..8d6f85d75699e48b75e857b5021dcf97c5dafef6 100644
--- a/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml
+++ b/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml
@@ -13,11 +13,12 @@
 		<property name="className" value="org.olat.core.util.mail.ui.SendDocumentsByEMailController"/>
 	</bean>
 	
-		<bean id="mailAsyncExecutorService" class="org.springframework.core.task.support.ExecutorServiceAdapter">
+	<bean id="mailAsyncExecutorService" class="org.springframework.core.task.support.ExecutorServiceAdapter">
 		<constructor-arg index="0" ref="mailAsyncExecutor" />
 	</bean>
 	
 	<bean id="mailAsyncExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
+		<property name="waitForTasksToCompleteOnShutdown" value="true" />
 		<property name="corePoolSize" value="1" />
 		<property name="maxPoolSize" value="1" />
 		<property name="queueCapacity" value="2000" />
diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
index 884dc5b74b4499bc314b6c4dd6dea90da8db9fc1..390c8c5e2d77c1b43b05be503d4d21ebd273b92b 100644
--- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
@@ -26,7 +26,7 @@ chkbx.glossary.inverse.explain=Glossar Menu in Toolbar muss unter "Toolbar" konf
 chkbx.glossary.onoff=Glossar
 chkbx.search.onoff=Kurssuche
 chkbx.menu.onoff=Menu sichtbar f\u00FCr Teilnehmer und Betreuer
-chkbx.participantinfo.onoff=Teilnehmer Infos
+chkbx.participantinfo.onoff=Teilnehmerinfos
 chkbx.participantlist.onoff=Teilnehmerliste
 chkbx.toolbar.explain=Werkzeuge in Toolbar aktivieren:
 chkbx.toolbar.onoff=Toolbar sichtbar f\u00FCr Teilnehmer
diff --git a/src/main/java/org/olat/course/nodes/VideoCourseNode.java b/src/main/java/org/olat/course/nodes/VideoCourseNode.java
index c1c9e7edaa9eba37c906b9187e70d03682767476..873dc5d89e122ecb4d9a40ac171b5674984ca365 100644
--- a/src/main/java/org/olat/course/nodes/VideoCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/VideoCourseNode.java
@@ -32,6 +32,7 @@ import org.olat.core.gui.control.generic.tabbable.TabbableController;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Organisation;
 import org.olat.core.util.Util;
+import org.olat.core.util.ValidationStatus;
 import org.olat.core.util.nodes.INode;
 import org.olat.course.ICourse;
 import org.olat.course.condition.ConditionEditController;
@@ -46,6 +47,8 @@ import org.olat.course.run.navigation.NodeRunConstructionResult;
 import org.olat.course.run.userview.CourseNodeSecurityCallback;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.fileresource.types.VideoFileResource;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.video.ui.VideoDisplayOptions;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryImportExport;
 import org.olat.repository.handlers.RepositoryHandler;
@@ -72,7 +75,7 @@ public class VideoCourseNode extends AbstractAccessableCourseNode {
 
 	@Override
 	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) {
-		VideoEditController childTabCntrllr = new VideoEditController(this, ureq, wControl, course, euce);
+		VideoEditController childTabCntrllr = new VideoEditController(this, ureq, wControl);
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
 		return new NodeEditController(ureq, wControl, course, chosenNode, euce, childTabCntrllr);
 	}
@@ -93,13 +96,36 @@ public class VideoCourseNode extends AbstractAccessableCourseNode {
 	}
 
 	@Override
-	public NodeRunConstructionResult createNodeRunConstructionResult(
-			UserRequest ureq, WindowControl wControl,
-			UserCourseEnvironment userCourseEnv, CourseNodeSecurityCallback nodeSecCallback,
-			String nodecmd) {
+	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
+			UserCourseEnvironment userCourseEnv, CourseNodeSecurityCallback nodeSecCallback, String nodecmd) {
 		VideoRunController cprunC = new VideoRunController(getModuleConfiguration(), wControl, ureq, userCourseEnv, this);
 		return cprunC.createNodeRunConstructionResult(ureq);
 	}
+	
+	public VideoDisplayOptions getVideoDisplay(RepositoryEntry videoEntry, boolean readOnly) {
+		// configure the display controller according to config
+		ModuleConfiguration config = getModuleConfiguration();
+		boolean autoplay = config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY);
+		boolean comments = config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS);
+		boolean ratings = config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING);
+		String customtext = config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT);
+
+		VideoDisplayOptions displayOptions = VideoDisplayOptions.valueOf(autoplay, comments, ratings, true, false, false, null, false, readOnly);
+		switch(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT, "none")) {
+			case "customDescription":
+				displayOptions.setShowDescription(true);
+				displayOptions.setDescriptionText(customtext);
+				break;
+			case "resourceDescription":
+				displayOptions.setShowDescription(true);
+				displayOptions.setDescriptionText(videoEntry.getDescription());
+				break;
+			default:
+				displayOptions.setShowDescription(false);
+				break;
+		}
+		return displayOptions;
+	}
 
 	@Override
 	public StatusDescription isConfigValid(){
@@ -108,12 +134,11 @@ public class VideoCourseNode extends AbstractAccessableCourseNode {
 		StatusDescription sd = StatusDescription.NOERROR;
 		boolean isValid = VideoEditController.isModuleConfigValid(getModuleConfiguration());
 		if (!isValid) {
-			// FIXME: refine statusdescriptions
 			String shortKey = "no.video.chosen";
 			String longKey = "error.noreference.long";
 			String[] params = new String[] { this.getShortTitle() };
 			String translPackage = Util.getPackageName(VideoEditController.class);
-			sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translPackage);
+			sd = new StatusDescription(ValidationStatus.ERROR, shortKey, longKey, params, translPackage);
 			sd.setDescriptionForUnit(getIdent());
 			// set which pane is affected by error
 			sd.setActivateableViewIdentifier(VideoEditController.PANE_TAB_VIDEOCONFIG);
diff --git a/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java b/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java
index 33a2c61d48b4c10d8d50803080a86a6948b004db..23ffd497938b5d00de0868fd4aba5f025124231c 100644
--- a/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java
+++ b/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java
@@ -51,6 +51,7 @@ import org.olat.course.nodes.livestream.LiveStreamService;
 import org.olat.course.nodes.livestream.model.LiveStreamEventImpl;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRef;
+import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
 import org.springframework.stereotype.Service;
@@ -62,7 +63,7 @@ import org.springframework.stereotype.Service;
  *
  */
 @Service
-public class LiveStreamServiceImpl implements LiveStreamService {
+public class LiveStreamServiceImpl implements LiveStreamService, DisposableBean {
 	
 	private static final Logger log = Tracing.createLoggerFor(LiveStreamServiceImpl.class);
 	
@@ -84,6 +85,13 @@ public class LiveStreamServiceImpl implements LiveStreamService {
 		return scheduler;
 	}
 
+	@Override
+	public void destroy() throws Exception {
+		if(scheduler != null) {
+			scheduler.shutdownNow();
+		}
+	}
+
 	@Override
 	public List<? extends LiveStreamEvent> getRunningEvents(CourseCalendars calendars, int bufferBeforeMin,
 			int bufferAfterMin) {
diff --git a/src/main/java/org/olat/course/nodes/video/VideoEditController.java b/src/main/java/org/olat/course/nodes/video/VideoEditController.java
index 8306f361c1b5cd007d68052163c888a73c3cb502..f025b18285de636170bd1181da97904a83c62027 100644
--- a/src/main/java/org/olat/course/nodes/video/VideoEditController.java
+++ b/src/main/java/org/olat/course/nodes/video/VideoEditController.java
@@ -46,10 +46,8 @@ import org.olat.core.util.StringHelper;
 import org.olat.core.util.filter.FilterFactory;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSContainerMapper;
-import org.olat.course.ICourse;
 import org.olat.course.editor.NodeEditController;
 import org.olat.course.nodes.VideoCourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.fileresource.types.VideoFileResource;
 import org.olat.modules.ModuleConfiguration;
 import org.olat.modules.video.VideoManager;
@@ -71,11 +69,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 public class VideoEditController extends ActivateableTabbableDefaultController implements ControllerEventListener {
 
 	public static final String PANE_TAB_VIDEOCONFIG = "pane.tab.videoconfig";
-	private static final String PANE_TAB_ACCESSIBILITY = "pane.tab.accessibility";
-	private final static String[] paneKeys = { PANE_TAB_VIDEOCONFIG};
+	private static final String[] paneKeys = { PANE_TAB_VIDEOCONFIG};
 
 	public static final String NLS_ERROR_VIDEOREPOENTRYMISSING = "error.videorepoentrymissing";
-	private static final String NLS_CONDITION_ACCESSIBILITY_TITLE = "condition.accessibility.title";
 	private static final String NLS_COMMAND_CHOOSEVIDEO = "command.choosevideo";
 	private static final String NLS_COMMAND_CREATEVID = "command.createvideo";
 	private static final String NLS_COMMAND_CHANGEVID = "command.changevideo";
@@ -98,8 +94,8 @@ public class VideoEditController extends ActivateableTabbableDefaultController i
 	private TabbedPane myTabbedPane;
 	private VelocityContainer videoConfigurationVc;
 
-	private ModuleConfiguration config;
 	private final VideoCourseNode videoNode;
+	private final ModuleConfiguration config;
 	private RepositoryEntry repositoryEntry;
 
 	private CloseableModalController cmc;
@@ -107,10 +103,10 @@ public class VideoEditController extends ActivateableTabbableDefaultController i
 	private VideoOptionsForm videoOptionsCtrl;
 	private ReferencableEntriesSearchController searchController;
 
-	public VideoEditController(VideoCourseNode videoNode, UserRequest ureq, WindowControl wControl, ICourse course, UserCourseEnvironment euce) {
+	public VideoEditController(VideoCourseNode videoNode, UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
-		this.config = videoNode.getModuleConfiguration();
 		this.videoNode = videoNode;
+		this.config = videoNode.getModuleConfiguration();
 		
 		main = new Panel("videomain");
 
@@ -249,23 +245,7 @@ public class VideoEditController extends ActivateableTabbableDefaultController i
 		removeAsListenerAndDispose(cmc);
 		removeAsListenerAndDispose(previewCtrl);
 		
-		boolean autoplay = config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY);
-		boolean showRating = config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING);
-		boolean showComments = config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS);
-		
-		VideoDisplayOptions options = VideoDisplayOptions.valueOf(autoplay, showComments, showRating, true, true, false, false, "", true, true);
-		switch(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT, "none")) {
-			case "customDescription":
-				options.setCustomDescription(true);
-				options.setDescriptionText(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT));
-				break;
-			case "none":
-				options.setShowDescription(false);
-				break;
-			default:
-				break;
-		}
-
+		VideoDisplayOptions options = videoNode.getVideoDisplay(repositoryEntry, true);
 		previewCtrl = new VideoDisplayController(ureq, getWindowControl(), repositoryEntry, null, null, options);
 		listenTo(previewCtrl);
 		cmc = new CloseableModalController(getWindowControl(), translate("close"), previewCtrl.getInitialComponent(), true, translate(NLS_COMMAND_CHOOSEVIDEO));
diff --git a/src/main/java/org/olat/course/nodes/video/VideoRunController.java b/src/main/java/org/olat/course/nodes/video/VideoRunController.java
index 1418706518329832439c665d3dee11f7d41ba1df..966a991d7a6e9673879d6bafb3c4d6ffa97cc767 100644
--- a/src/main/java/org/olat/course/nodes/video/VideoRunController.java
+++ b/src/main/java/org/olat/course/nodes/video/VideoRunController.java
@@ -107,27 +107,9 @@ public class VideoRunController extends BasicController {
 			showError(VideoEditController.NLS_ERROR_VIDEOREPOENTRYMISSING);
 			return;
 		}
-		
-		// configure the display controller according to config
-		boolean autoplay = config.getBooleanSafe(VideoEditController.CONFIG_KEY_AUTOPLAY);
-		boolean comments = config.getBooleanSafe(VideoEditController.CONFIG_KEY_COMMENTS);
-		boolean ratings = config.getBooleanSafe(VideoEditController.CONFIG_KEY_RATING);
-		String customtext = config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_CUSTOMTEXT);
 
-		VideoDisplayOptions displayOptions = VideoDisplayOptions.valueOf(autoplay, comments, ratings, true, true, false, false, null, false, userCourseEnv.isCourseReadOnly());
-		switch(config.getStringValue(VideoEditController.CONFIG_KEY_DESCRIPTION_SELECT,"none")) {
-			case "customDescription":
-				displayOptions.setCustomDescription(true);
-				displayOptions.setDescriptionText(customtext);
-				break;
-			case "none":
-				displayOptions.setShowDescription(false);
-				break;
-			default:
-				break;
-		}
-		
 		RepositoryEntry courseEntry = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
+		VideoDisplayOptions displayOptions = videoNode.getVideoDisplay(videoEntry, userCourseEnv.isCourseReadOnly());
 		videoDispCtr = new VideoDisplayController(ureq, getWindowControl(), videoEntry, courseEntry, videoNode, displayOptions);
 		listenTo(videoDispCtr);
 		
diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java
index 3ad72bbf5a13ec8f253da66d76bc140447626274..924c0927824c021d4ad30cc6e556efac327c9f60 100644
--- a/src/main/java/org/olat/course/run/CourseRuntimeController.java
+++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java
@@ -870,6 +870,8 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im
 		if (calendarIsEnabled && userCourseEnv != null) {
 			calendarLink = LinkFactory.createToolLink("calendar",translate("command.calendar"), this, "o_icon_calendar");
 			calendarLink.setPopup(new LinkPopupSettings(950, 750, "cal"));
+			calendarLink.setUrl(BusinessControlFactory.getInstance()
+					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Calendar:0]"));
 			calendarLink.setVisible(cc.isCalendarEnabled());
 			toolbarPanel.addTool(calendarLink);
 		}
@@ -1294,6 +1296,10 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im
 				if (forumLink != null && forumLink.isVisible()) {
 					doForum(ureq);
 				}
+			} else if("Calendar".equalsIgnoreCase(type)) {
+				if (calendarLink != null && calendarLink.isVisible()) {
+					doCalendar(ureq);
+				}
 			} else if("Documents".equalsIgnoreCase(type)) {
 				if (documentsLink != null && documentsLink.isVisible()) {
 					activateSubEntries(ureq, doDocuments(ureq), entries);
@@ -1951,7 +1957,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im
 			currentToolCtr = emailCtrl;
 		} else {
 			delayedClose = Delayed.email;
-		};
+		}
 	}
 	
 	private BlogToolController doBlog(UserRequest ureq) {
@@ -2021,6 +2027,27 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im
 		return null;
 	}
 	
+	/**
+	 * Open the calendar as sub-controller.
+	 * 
+	 * @param ureq The user request
+	 * @return The calendar controller
+	 */
+	private CourseCalendarController doCalendar(UserRequest ureq) {
+		OLATResourceable ores = OresHelper.createOLATResourceableType("Calendar");
+		WindowControl swControl = addToHistory(ureq, ores, null);
+		CourseCalendarController calendarController = new CourseCalendarController(ureq, swControl, getUserCourseEnvironment());
+		pushController(ureq, translate("command.calendar"), calendarController);
+		setActiveTool(calendarLink);
+		currentToolCtr = calendarController;
+		return calendarController;
+	}
+	
+	/**
+	 * Open the course calendar as popup.
+	 * 
+	 * @param ureq The user request
+	 */
 	private void launchCalendar(UserRequest ureq) {
 		ControllerCreator ctrlCreator = (lureq, lwControl) -> {
 			ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
diff --git a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
index c92fc5cf7720e3517eaac46f941dfda2e0ca4220..edebc7ef4d3e1e97f94455f0cd916f9e5072bfbf 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java
@@ -103,7 +103,6 @@ public class VideoDisplayController extends BasicController {
 	private Integer userPreferredResolution;
 	
 	private RepositoryEntry videoEntry;
-	private String descriptionText;
 	private String mediaRepoBaseUrl;
 	private VideoMeta videoMetadata;
 	private VideoMarkers videoMarkers;
@@ -118,13 +117,9 @@ public class VideoDisplayController extends BasicController {
 	private VideoModule videoModule;
 	@Autowired
 	private VideoManager videoManager;
-
-	public VideoDisplayController(UserRequest ureq, WindowControl wControl, RepositoryEntry videoEntry, boolean autoWidth) {
-		this(ureq, wControl, videoEntry, null, null, VideoDisplayOptions.valueOf(false, false, false, true, true, false, autoWidth, null, false, false));
-	}
 	
 	public VideoDisplayController(UserRequest ureq, WindowControl wControl, RepositoryEntry videoEntry) {
-		this(ureq, wControl, videoEntry, null, null, VideoDisplayOptions.valueOf(false, false, false, true, true, false, false, null, false, false));
+		this(ureq, wControl, videoEntry, null, null, VideoDisplayOptions.valueOf(false, false, false, true, true, true, videoEntry.getDescription(), false, false));
 	}
 	
 	/**
@@ -141,7 +136,6 @@ public class VideoDisplayController extends BasicController {
 		super(ureq, wControl);
 		this.videoEntry = videoEntry;
 		this.displayOptions = displayOptions;
-		this.descriptionText = getDescription(courseNode, displayOptions);
 		
 		mainVC = createVelocityContainer("video_run");
 		putInitialPanel(mainVC);
@@ -224,12 +218,6 @@ public class VideoDisplayController extends BasicController {
 		PublisherData data = new PublisherData(VideoFileResource.TYPE_NAME, ores.getResourceableId() + "-" + subIdent, businessPath);
 		return new PublishingInformations(data, ctx);
 	}
-
-	private String getDescription(VideoCourseNode courseNode, VideoDisplayOptions options) {
-		if (options.isCustomDescription()) return options.getDescriptionText();
-		if (courseNode != null) return courseNode.getLearningObjectives();
-		return null;
-	}
 	
 	public VideoMeta getVideoMetadata() {
 		return videoMetadata;
@@ -425,9 +413,8 @@ public class VideoDisplayController extends BasicController {
 		mainVC.contextPut("masterUrl", masterUrl);
 		
 		mainVC.contextPut("title", videoEntry.getDisplayname());
-		if(displayOptions == null || displayOptions.isShowDescription()) {
-			String desc = (StringHelper.containsNonWhitespace(descriptionText) ? descriptionText : videoEntry.getDescription());
-			setText(desc, "description");
+		if(displayOptions.isShowDescription()) {
+			setText(displayOptions.getDescriptionText(), "description");
 		}
 		
 		String authors = videoEntry.getAuthors();
diff --git a/src/main/java/org/olat/modules/video/ui/VideoDisplayOptions.java b/src/main/java/org/olat/modules/video/ui/VideoDisplayOptions.java
index 466bf607e35458b65f83beb24a067fe1fc5ee8ad..de85d36046e7e20fd0b997ce12aa4b24952a2856 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoDisplayOptions.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoDisplayOptions.java
@@ -33,7 +33,6 @@ public class VideoDisplayOptions {
 	private boolean showRating;
 	private boolean showTitle;
 	private boolean showDescription;
-	private boolean customDescription;
 	private boolean autoWidth;
 	private boolean readOnly;
 	private String descriptionText;
@@ -46,11 +45,10 @@ public class VideoDisplayOptions {
 	private boolean authorMode;
 	
 	public static VideoDisplayOptions valueOf(boolean autoplay, boolean showComments, boolean showRating, boolean showTitle, boolean showDescription,
-			boolean customDescription, boolean autoWidth, String descriptionText, boolean authorMode, boolean readOnly) {
+			boolean autoWidth, String descriptionText, boolean authorMode, boolean readOnly) {
 		VideoDisplayOptions options = new VideoDisplayOptions();
 		options.setAutoplay(autoplay);
 		options.setAutoWidth(autoWidth);
-		options.setCustomDescription(customDescription);
 		options.setDescriptionText(descriptionText);
 		options.setReadOnly(readOnly);
 		options.setShowComments(showComments);
@@ -71,7 +69,6 @@ public class VideoDisplayOptions {
 		VideoDisplayOptions options = new VideoDisplayOptions();
 		options.setAutoplay(false);
 		options.setAutoWidth(false);
-		options.setCustomDescription(false);
 		options.setDescriptionText(null);
 		options.setReadOnly(false);
 		options.setShowComments(false);
@@ -167,14 +164,6 @@ public class VideoDisplayOptions {
 	public void setShowDescription(boolean showDescription) {
 		this.showDescription = showDescription;
 	}
-
-	public boolean isCustomDescription() {
-		return customDescription;
-	}
-	
-	public void setCustomDescription(boolean customDescription) {
-		this.customDescription = customDescription;
-	}
 	
 	public boolean isAutoWidth() {
 		return autoWidth;
diff --git a/src/main/java/org/olat/modules/video/ui/VideoListingController.java b/src/main/java/org/olat/modules/video/ui/VideoListingController.java
index a2f3acdcaa76220ca19c365c1a01e7fa5487b804..9425ff841324cb660b6dc5eae77654f79c2c062f 100644
--- a/src/main/java/org/olat/modules/video/ui/VideoListingController.java
+++ b/src/main/java/org/olat/modules/video/ui/VideoListingController.java
@@ -167,7 +167,7 @@ public class VideoListingController extends FormBasicController implements Activ
 		RepositoryEntrySecurity reSecurity = repositoryManager.isAllowed(ureq, videoEntry);
 		if (reSecurity.canLaunch()) {// no booking implemented for video
 			boolean readOnly = videoEntry.getEntryStatus().decommissioned();
-			VideoDisplayOptions options = VideoDisplayOptions.valueOf(true, true, true, true, true, false, true, null, false, readOnly);
+			VideoDisplayOptions options = VideoDisplayOptions.valueOf(true, true, true, true, true, false, videoEntry.getDescription(), false, readOnly);
 			VideoDisplayController videoDisplayCtr = new VideoDisplayController(ureq, getWindowControl(), videoEntry, null, null, options);
 			listenTo(videoDisplayCtr);
 			toolbarPanel.pushController(videoEntry.getDisplayname(), videoDisplayCtr);
diff --git a/src/main/java/org/olat/modules/webFeed/dispatching/FeedMediaDispatcher.java b/src/main/java/org/olat/modules/webFeed/dispatching/FeedMediaDispatcher.java
index 7e013b8f5547041db116261db0e2a06fccf55379..f45c717b478b869cd958c55d4636dde65df030b6 100644
--- a/src/main/java/org/olat/modules/webFeed/dispatching/FeedMediaDispatcher.java
+++ b/src/main/java/org/olat/modules/webFeed/dispatching/FeedMediaDispatcher.java
@@ -166,7 +166,7 @@ public class FeedMediaDispatcher implements Dispatcher, GenericEventListener {
 						try {
 							validatedUriCache.remove(key);
 						} catch (Exception e) {
-							log.info("Cannot remove this key: " + key);
+							log.info("Cannot remove this key: {}", key);
 						}
 					}
 				}
@@ -186,6 +186,11 @@ public class FeedMediaDispatcher implements Dispatcher, GenericEventListener {
 		} catch(NumberFormatException nfe) {
 			//
 		}
+		
+		if(requestedPath == null || requestedPath.length() == 0) {
+			DispatcherModule.sendBadRequest(request.getRequestURI(), response);
+			return;
+		}
 
 		Path path = null;
 		try {
diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
index 2c5b520af69dc622ca0679ec87e7c02bbf16abf6..b2c2e589c9cac93a3be8075008607987bd9624ae 100644
--- a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
@@ -513,7 +513,7 @@ public class CoursesWebService {
 		OLATResource originalOres = olatResourceManager.findResourceable(src.getOlatResource());
 		boolean isAlreadyLocked = handlerFactory.getRepositoryHandler(src).isLocked(originalOres);
 		LockResult lockResult = handlerFactory.getRepositoryHandler(src).acquireLock(originalOres, ureq.getIdentity());
-
+		
 		if(lockResult == null || (lockResult != null && lockResult.isSuccess()) && !isAlreadyLocked) {
 			//create new repo entry
 			String name;
@@ -601,6 +601,8 @@ public class CoursesWebService {
 			repositoryManager.copyImage(src, preparedEntry);
 			ICourse course = prepareCourse(preparedEntry, shortTitle, longTitle, courseConfigVO);
 			handlerFactory.getRepositoryHandler(src).releaseLock(lockResult);
+			
+			log.info(Tracing.M_AUDIT, "Create course {} from template {}", preparedEntry, src);
 			return course;
 		} else {
 			log.info("Course locked");
@@ -672,6 +674,7 @@ public class CoursesWebService {
 					? NodeAccessType.of(nodeAccessType)
 					: course.getCourseConfig().getNodeAccessType(); // default type
 			CourseFactory.initNodeAccessType(addedEntry, type);
+			log.info(Tracing.M_AUDIT, "Create course: {}", addedEntry);
 			return prepareCourse(addedEntry, shortTitle, longTitle, courseConfigVO);
 		} catch (Exception e) {
 			throw new WebApplicationException(e);
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java b/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java
index 1317b8e2eeb8b3f5c03b8d2322e144990f778c13..ea64d3eafcafa35fcc599ed414c1fc90c3501dba 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/UserAdminLifecycleConfigurationController.java
@@ -170,7 +170,7 @@ public class UserAdminLifecycleConfigurationController extends FormBasicControll
 	private TranslationBundle initForm(String labelI18nKey, String textI18nKey, FormItemContainer formLayout) {
 		String text = translate(textI18nKey);
 		StaticTextElement viewEl = uifactory.addStaticTextElement("view." + counter++, labelI18nKey, text, formLayout);
-		FormLink translationLink = uifactory.addFormLink("translate." + counter++, "translate", null, formLayout, Link.LINK);
+		FormLink translationLink = uifactory.addFormLink("translate." + counter++, "translation.edit", null, formLayout, Link.LINK);
 		TranslationBundle bundle = new TranslationBundle(textI18nKey, labelI18nKey, viewEl, translationLink);
 		translationLink.setUserObject(bundle);
 		return bundle;
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties
index e99014d6e61dc661ff7733e6bdd4ea479b926e54..0ba110225427eb127104ca8438a14168d7db7bbc 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties
@@ -29,10 +29,10 @@ mail.before.deletion.body.label=Text Benachrichtigung
 mail.before.deletion.subject=Konto wird gel\u00F6scht
 mail.before.deletion.subject.label=Betreff Benachrichtigung
 notification.noNews=Seit diesem Datum haben sich keine neue Benutzer angemeldet
-num.day.before.mail.deactivation=Anzhal Tage vor Mailbenachrichtigung
-num.day.before.mail.deletion=Anzhal Tage vor Mailbenachrichtigung
-num.inactive.day.deactivation=Anzhal Tage vor Deaktivierung
-num.inactive.day.deletion=Anzhal Tage vor L\u00F6schung
+num.day.before.mail.deactivation=Anzahl Tage vor Mailbenachrichtigung
+num.day.before.mail.deletion=Anzahl Tage vor Mailbenachrichtigung
+num.inactive.day.deactivation=Anzahl Tage vor Deaktivierung
+num.inactive.day.deletion=Anzahl Tage vor L\u00F6schung
 overview.inactive.user=Deaktivierte Benutzer
 overview.ready.to.delete.user=Bereits zu l\u00F6schen
 overview.ready.to.inactivate.user=Benutzer ohne Aktivit\u00E4t
@@ -48,3 +48,4 @@ table.name.firstName=Vorname
 table.name.lastName=Nachname
 translate=\u00DCbersetzen
 translate.title=\u00DCbersetzen "{0}"
+translation.edit=Bearbeiten
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties
index 7f56d05f424f5392d13d7a47f1fafb8117ee2b14..91e6d033147065696d7a176eaf037f59d4aa2118 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties
@@ -48,3 +48,4 @@ table.name.firstName=Name
 table.name.lastName=Last name
 translate=Translate
 translate.title=Translate "{0}"
+translation.edit=Edit
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties
index 012d00978b109b3cbf59d7b9ee67163b82453441..18c3706979345bcc8f89532943be0a3e3646a8a5 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties
@@ -48,3 +48,4 @@ table.name.firstName=Pr\u00E9nom
 table.name.lastName=Nom
 translate=Traduire
 translate.title=Traduire "{0}"
+translation.edit=Éditer
diff --git a/src/main/webapp-tomcat/WEB-INF/web.xml b/src/main/webapp-tomcat/WEB-INF/web.xml
index f04c3db9f495858d4ec3cf4ff0a8e9d9fa3c55e3..fdb67bd02e09fb42f345f3ed64c2765f37d891e3 100644
--- a/src/main/webapp-tomcat/WEB-INF/web.xml
+++ b/src/main/webapp-tomcat/WEB-INF/web.xml
@@ -264,4 +264,13 @@
     	<exception-type>java.lang.Throwable</exception-type>
     	<location>/errors/error.html</location>
     </error-page>
+    
+    <security-constraint>
+		<web-resource-collection>
+			<web-resource-name><strong>restricted methods</strong></web-resource-name>
+			<url-pattern>/*</url-pattern>
+			<http-method>TRACE</http-method>
+		</web-resource-collection>
+		<auth-constraint />
+    </security-constraint>
 </web-app>