diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java
index ac2470e383338f7fd21b3be8a14db1ea20aa34ca..9e133ced78ea64ce3422cfaeb6a9aea496c5a4c8 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java
@@ -89,6 +89,8 @@ public interface MetaInfo {
 	 * @return The identity of the initial author.
 	 */
 	public Identity getAuthorIdentity();
+	
+	public boolean hasAuthorIdentity();
 
 	/**
 	 * Corresponds to DublinCore:description
@@ -209,6 +211,9 @@ public interface MetaInfo {
 	 */
 	public VFSLeaf getThumbnail(int maxWidth, int maxHeight, boolean fill);
 	
+	/**
+	 * Thumbnails are cleared and the metadata file is written on the disk
+	 */
 	public void clearThumbnails();
 
 	/**
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java
index 49f3c920067fffe950bea29d0e105a907941ac6a..bb5511345336d0f0354aebc739d8d2c3659021cb 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java
@@ -561,13 +561,18 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getAuthorIdentity()
 	 */
 	public Identity getAuthorIdentity() {
-		if (this.authorIdentKey == null) {
+		if (authorIdentKey == null) {
 			return null;
 		} else {
-			return BaseSecurityManager.getInstance().loadIdentityByKey(this.authorIdentKey);
+			return BaseSecurityManager.getInstance().loadIdentityByKey(authorIdentKey);
 		}
 	}
 
+	@Override
+	public boolean hasAuthorIdentity() {
+		return (authorIdentKey != null);
+	}
+
 	/**
 	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getHTMLFormattedAuthor()
 	 */
@@ -808,6 +813,9 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return new LocalFileImpl(thumbnailInfo.getThumbnailFile());
 	}
 	
+	/**
+	 * Thumbnails are cleared and the XML file is written on the disk
+	 */
 	@Override
 	public void clearThumbnails() {
 		cannotGenerateThumbnail = false;
diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java b/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java
index 2c4cd1294a67adff37b781df2222d80198d72064..0e47b713deacd3f03903cb0aa742fc66afc4aa55 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java
@@ -208,7 +208,6 @@ public class VFSResourceRoot implements WebResourceRoot  {
 		}
 		
 		try {
-	        //FileUtils.copy(is, childLeaf.getOutputStream(false));
 	        copyVFS(childLeaf, is);
 		} catch (QuotaExceededException e) {
 			throw e;
@@ -228,10 +227,10 @@ public class VFSResourceRoot implements WebResourceRoot  {
 		
 		if(childLeaf instanceof MetaTagged && identity != null) {
 			MetaInfo infos = ((MetaTagged)childLeaf).getMetaInfo();
-			if(infos != null && infos.getAuthorIdentity() == null) {
+			if(infos != null && !infos.hasAuthorIdentity()) {
 				infos.setAuthor(identity);
 				infos.clearThumbnails();
-				infos.write();
+				//infos.write(); the clearThumbnails call write()
 			}
 		}
 		
diff --git a/src/main/java/org/olat/core/servlets/OpenOLATServlet.java b/src/main/java/org/olat/core/servlets/OpenOLATServlet.java
index 9650d407ace1453724d13dd490b1fccaa0c84e5e..ff85f70c1e7233bd55c3171844aead6ad76500f3 100644
--- a/src/main/java/org/olat/core/servlets/OpenOLATServlet.java
+++ b/src/main/java/org/olat/core/servlets/OpenOLATServlet.java
@@ -226,7 +226,14 @@ public class OpenOLATServlet extends HttpServlet {
 	@Override
 	protected void doHead(HttpServletRequest req, HttpServletResponse resp)
 	throws ServletException, IOException {
-		webDAVDispatcher.execute(req, resp);
+		String subContext = DispatcherModule.getFirstPath(req);
+		if("/".equals(subContext)) {
+			webDAVDispatcher.execute(req, resp);
+		} else if("/webdav".equals(subContext) || "/webdav/".equals(subContext)) {
+			webDAVDispatcher.execute(req, resp);
+		} else {
+			executeUserRequest(req, resp);
+		}
 	}
 
 	/**
diff --git a/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java b/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java
index 4f5ad61539f993bfd9a79b45899d569b957edcd4..1c255d0096bcb0ef2b735dee5555944306125b85 100644
--- a/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java
+++ b/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java
@@ -1618,6 +1618,13 @@ public class MailManagerImpl extends BasicManager implements MailManager {
 					}
 				}
 				Transport.send(msg);
+			} else if(Settings.isDebuging() && result.getReturnCode() == MailerResult.OK) {
+				try {
+					logInfo("E-mail send: " + msg.getSubject());
+					logInfo("Content    : " + msg.getContent());
+				} catch (IOException e) {
+					logError("", e);
+				}
 			} else {
 				result.setReturnCode(MailerResult.MAILHOST_UNDEFINED);
 			}
diff --git a/src/main/java/org/olat/core/util/vfs/lock/LockInfo.java b/src/main/java/org/olat/core/util/vfs/lock/LockInfo.java
index f7a068b5db7141b9fd5a9d9dba2241f24b0a3723..07bff06e5745bffbd42fdc72b923a274c5fb4559 100644
--- a/src/main/java/org/olat/core/util/vfs/lock/LockInfo.java
+++ b/src/main/java/org/olat/core/util/vfs/lock/LockInfo.java
@@ -162,7 +162,7 @@ public class LockInfo {
      * Return true if the lock has expired.
      */
     public boolean hasExpired() {
-        return (System.currentTimeMillis() > expiresAt);
+        return (System.currentTimeMillis() > getExpiresAt());
     }
 
     /**
diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
index cf795906feb14b69d25decc0eb3d6d8bc4081a6d..1976b0cfedd02b0a51282bfd1af9b1bad5567c92 100644
--- a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
+++ b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
@@ -29,7 +29,6 @@ import org.olat.core.util.vfs.NamedContainerImpl;
 import org.olat.core.util.vfs.VFSConstants;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
-import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.VFSStatus;
 import org.olat.core.util.vfs.filters.VFSItemFilter;
 import org.olat.repository.RepositoryEntry;
@@ -47,7 +46,6 @@ class CoursefolderWebDAVMergeSource extends MergeSource {
 	private final Identity identity;
 	private long loadTime;
 	
-	
 	public CoursefolderWebDAVMergeSource(Identity identity) {
 		super(null, null);
 		this.identity = identity;
@@ -85,49 +83,34 @@ class CoursefolderWebDAVMergeSource extends MergeSource {
 
 	@Override
 	public List<VFSItem> getItems() {
-		if(!init) {
-			init();
-		}
+		checkInitialization();
 		return super.getItems();
 	}
 
 	@Override
 	public List<VFSItem> getItems(VFSItemFilter filter) {
-		if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
-			init();
-		}
+		checkInitialization();
 		return super.getItems(filter);
 	}
 
 	@Override
 	public VFSItem resolve(String path) {
-		if(init) {
-			return super.resolve(path);
-		}
-		
-		path = VFSManager.sanitizePath(path);
-		if (path.equals("/")) {
-			return this;
-		}
-		
-		String childName = VFSManager.extractChild(path);
-		RepositoryManager rm = RepositoryManager.getInstance();
-		List<RepositoryEntry> entries = rm.queryByEditor(identity, CourseModule.getCourseTypeName());
-		for(RepositoryEntry entry:entries) {
-			String courseTitle = RequestUtil.normalizeFilename(entry.getDisplayname());
-			if(childName.equals(courseTitle)) {
-				NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(childName, entry.getOlatResource());
-				String nextPath = path.substring(childName.length() + 1);
-				return cfContainer.resolve(nextPath);
+		checkInitialization();
+		return super.resolve(path);
+	}
+	
+	private void checkInitialization() {
+		if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
+			synchronized(this) {
+				if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
+					init();
+				}
 			}
 		}
-
-		return super.resolve(path);
 	}
 	
 	@Override
 	protected void init() {
-		super.init();
 		RepositoryManager rm = RepositoryManager.getInstance();
 		List<RepositoryEntry> courseEntries = rm.queryByEditor(identity, CourseModule.getCourseTypeName());
 		List<VFSContainer> containers = new ArrayList<>();
diff --git a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties
index 3de2225dca9ab299a6028c6b59de4fb87e452979..22ad7bfe787ae39ee87e792a08d2e6996cda00d4 100644
--- a/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/course/nodes/cl/ui/_i18n/LocalStrings_fr.properties
@@ -1,4 +1,4 @@
-#Tue Apr 15 23:08:27 CEST 2014
+#Wed Apr 23 22:54:35 CEST 2014
 add.checkbox=Ajouter une case \u00E0 cocher
 assessment=Evaluation
 assessment.checkbox.description=Modifier en fonction de la case \u00E0 cocher\: modifier la case \u00E0 cocher s\u00E9lectionner gr\u00E2ce au filtre de tous les participants.
@@ -17,7 +17,48 @@ chelp.assessment.checkbox.2=La pr\u00E9s\u00E9lection des groupes permet de filt
 chelp.checkbox.1=Ici, vous pouvez cr\u00E9er et \u00E9diter les cases \u00E0 cocher de la liste de contr\u00F4le que vous avez pr\u00E9alablement configur\u00E9e. Dans le tableau, vous trouverez les cases \u00E0 cocher existant d\u00E9j\u00E0 dans cette liste de contr\u00F4le. Cliquez "Ajouter une case \u00E0 cocher" pour cr\u00E9er \u00E0 une nouvelle case \u00E0 cocher. Cela ouvre un nouvel formulaire.
 chelp.checkbox.2=<strong>$\:checkbox.title</strong>\: saisissez un titre court mais descriptif pour la nouvelle case \u00E0 cocher.
 chelp.checkbox.3=<strong>$\:release</strong>\: d\u00E9fini qui peut effectivement s\u00E9lectionn\u00E9 la case. Pour "Participant et entra\u00EEneur", tous deux peuvent cocher la case. Si "Entra\u00EEneur" est choisi, les participants verront la case, mais ne seront pas en mesure de la s\u00E9lectionner.
+chelp.checkbox.4=<strong>$\:label</strong>\: vous pouvez choisir parmi 5 types diff\u00E9rent de cases \u00E0 cocher\: "Termin\u00E9", "Trait\u00E9", "Pr\u00E9sent\u00E9", "V\u00E9rifi\u00E9" et "Pr\u00E9sent". Choisissez la plus appropri\u00E9e \u00E0 vos besoins.
+chelp.checkbox.5=<strong>$\:points</strong>\: d\u00E9terminer si et combien des points seront attribu\u00E9s pour les cases \u00E0 cocher s\u00E9lectionn\u00E9es.
+chelp.checkbox.6=La <strong>description</strong> est pr\u00E9sent\u00E9 dans la liste \u00E0 droite de la case \u00E0 cocher avec le titre, le score (si configur\u00E9) et le fichier \u00E0 t\u00E9l\u00E9charger le cas \u00E9ch\u00E9ant.
+chelp.checkbox.7=Si n\u00E9cessaire, vous pouvez ajouter un <strong>fichier</strong> que les participants pourront t\u00E9l\u00E9charger.
+chelp.checkbox.template.1=La fonction "Plusieurs listes de contr\u00F4le" vous permet de cr\u00E9er un plusieurs listes de contr\u00F4le de m\u00EAme nature avec un assistant. Ceux-ci sont ajout\u00E9s \u00E0 votre cours comme sous-\u00E9l\u00E9ments d'un \u00E9l\u00E9ment structure. Vous pouvez ensuite glisser-d\u00E9poser l'\u00E9l\u00E9ment de structure et les listes de contr\u00F4le selon vos d\u00E9sirs dans le cours.
+chelp.checkbox.template.2=La premi\u00E8re \u00E9tape de l'assistant vous permet de cr\u00E9er un mod\u00E8le sur lequel toutes les listes de contr\u00F4le seront bas\u00E9es. Toutes les listes, cases \u00E0 cocher et param\u00E8tres de configuration peuvent \u00EAtre \u00E9dit\u00E9s s\u00E9par\u00E9ment dans l'\u00E9diteur de cours apr\u00E8s leur cr\u00E9ation.
+chelp.checkbox.template.3=Pour plus d'informations sur la cr\u00E9ation et l'\u00E9dition des cases \u00E0 cocher, veuillez s'il vous pla\u00EEt lire l'aide contextuelle sous
 chelp.cl-assessment-checkbox.title=Liste de contr\u00F4le\: \u00E9valuation par case \u00E0 cocher
+chelp.cl-checkbox-template.title=Fonction plusieurs listes de contr\u00F4le\: cr\u00E9er un mod\u00E8le
+chelp.cl-checkbox.title=Listes de contr\u00F4le\: \u00E9diter les cases \u00E0 cocher
+chelp.cl-coach-assessment.title=Listes de contr\u00F4le\: \u00E9valuation et g\u00E9rer les listes de contr\u00F4le
+chelp.cl-config.title=Listes de contr\u00F4le\: configuration
+chelp.cl-metadatas.title=Fonction plusieurs listes de contr\u00F4le\: titre et d\u00E9lai
+chelp.cl-st-config.title=Fonction plusieurs listes de contr\u00F4le\: information pour l'\u00E9l\u00E9ment structure
+chelp.cl-template-configuration.title=Fonction plusieurs listes de contr\u00F4le\: configuration
+chelp.coach.1=G\u00E9rer les listes de tous les participants au cours que vous suivez comme coach et imprimez les aper\u00E7us. La configuration des liste de contr\u00F4le et des cases \u00E0 cocher individuelles sont effectu\u00E9es dans l'\u00E9diteur de cours. Le tableau montre les cases coch\u00E9es pour tous les participants.
+chelp.coach.2=Il existe trois modes d'\u00E9dition diff\u00E9rents \u00E0 votre disposition. Vous pouvez modifier les cases d'un participant par l'interm\u00E9diaire du lien "<strong>$\:table.header.edit.checkbox</strong>" \u00E0 la droite du tableau, modifier une case \u00E0 cocher pr\u00E9cise pour tous les participants en utilisant le menu "Edition par case \u00E0 cocher", ou modifier toutes les cases \u00E0 travers tous les participants directement dans le tableau r\u00E9el en utilisant le bouton "<strong>$org.olat.core\:edit</strong>" au bas de la table.
+chelp.coach.3=En utilisant le lien "<strong>$\:table.header.edit.checkbox</strong>", une liste de contr\u00F4le sp\u00E9cifique \u00E0 l'utilisateur s'ouvre, vous permettant de s\u00E9lectionner ou d\u00E9s\u00E9lectionner les cases \u00E0 cocher. S\u00E9lectionnez l'onglet "<strong>$\:assessment</strong>" pour acc\u00E9der directement au formulaire d'\u00E9valuation. Vous pouvez \u00E9galement acc\u00E9der \u00E0 ce formulaire d'\u00E9valuation par l'interm\u00E9diaire de l'outil d'\u00E9valuation.
+chelp.coach.4=Le bouton "<strong>$\:box.assessment</strong>" ouvre une liste de tous les participants filtr\u00E9s par case \u00E0 cocher. S'il vous pla\u00EEt, veuillez lire l'aide contextuelle correspondante pour plus d'informations. Vous pouvez modifier toutes les cases de tous les participants dans la table en utilisant le bouton "Editer".
+chelp.coach.5=Vous pouvez aussi t\u00E9l\u00E9charger la version PDF pour une utilisation hors ligne. Le bouton "<strong>$\:pdf.export</strong>" ouvre un fichier PDF avec les listes de contr\u00F4le actuelles de tous vos participants supervis\u00E9s. Le fichier PDF contient une colonne pour des signatures.
+chelp.coach.6=Cliquer sur "<strong>$\:pdf.export.checked</strong>" cr\u00E9e un fichier PDF contenant une table par case \u00E0 coche avec tous les participants qui ont d\u00E9j\u00E0 coch\u00E9 ladite case.
+chelp.coach.7="<strong>$\:pdf.export.checked</strong>" cr\u00E9\u00E9 un fichier PDF avec chaque case \u00E0 cocher contient avec la liste des participants qui ont d\u00E9j\u00E0 coch\u00E9 la case correspondante.
+chelp.config.1=L'\u00E9l\u00E9ment de cours vous permet d'int\u00E9grer des listes de contr\u00F4le dans la structure du cours. La liste de contr\u00F4le comme outil d'information aide les utilisateurs par exemple\: dans l'ex\u00E9cution de t\u00E2ches restreintes, en gardant une liste de pr\u00E9sence ou en maintenant une liste de choses \u00E0 faire.
+chelp.config.10=<strong>$\:config.cutvalue</strong>\: s'il vous pla\u00EEt entrez le nombre minimum de points n\u00E9cessaires pour obtenir "r\u00E9ussi". En-dessous de cette valeur les participants auront "non r\u00E9ussi". Vous ne pouvez pas le faire si vous avez s\u00E9lectionn\u00E9 "manuellement par le tuteur" ou "automatique (en utilisant le nombre de cases)" dans "Acc\u00E8s".
+chelp.config.11=<strong>$\:sum.cutvalue</strong>\: entrez le nombre minimum de cases coch\u00E9es n\u00E9cessaires pour obtenir "r\u00E9ussi". Vous ne pouvez pas le faire si vous avez s\u00E9lectionn\u00E9 "manuellement par le tuteur" ou "automatique (en utilisant la valeur de cases)" dans "Acc\u00E8s".
+chelp.config.12=<strong>$\:config.comment</strong>\: en cochant cette case, vous avez la possibilit\u00E9 d'ajouter un commentaire individuel sur votre \u00E9valuation.
+chelp.config.13=<strong>$\:config.tip.user</strong>\: entrez un texte qui sera affich\u00E9 \u00E0 tous les participants chaque fois qu'ils cliqueront sur l'\u00E9l\u00E9ment de cours.
+chelp.config.14=<strong>$\:config.tip.coach</strong>\: entrez un texte qui sera affich\u00E9 aux coaches du cours lors de l'\u00E9valuation des participants.
+chelp.config.2=Pour chaque \u00E9l\u00E9ment de cours, cr\u00E9er une liste avec autant de cases \u00E0 cocher que n\u00E9cessaire.
+chelp.config.3=Dans cet onglet, vous pouvez d\u00E9terminer si la liste de contr\u00F4le sera soumise \u00E0 un d\u00E9lai et si et comment les participants seront \u00E9valu\u00E9s. Ces param\u00E8tres ont un impact sur l'\u00E9valuation qui est \u00E0 votre disposition dans l'outil d'\u00E9valuation. Attention\: une fois que l'\u00E9valuation a eu lieu, nous vous conseillons de ne plus modifier la configuration.
+chelp.config.4=<strong>$\:config.due.date</strong>\: choisissez ici si la liste doit \u00EAtre compl\u00E9t\u00E9e avant une certaine date. Vous pouvez verrouiller la liste des participants apr\u00E8s l'expiration du d\u00E9lai.
+chelp.config.5=<strong>$\:config.points</strong>\: si vous attribuez des points aux cases \u00E0 cocher dans l'onglet "cases \u00E0 cocher", vous pouvez les attribuer manuellement ou automatiquement. Si vous ne cochez pas cette case, aucun score ne sera attribu\u00E9.
+chelp.config.6=<strong>$\:config.points.min</strong>\: entrez le score minimum qu'un participant au cours peut atteindre. Vous ne pouvez pas faire cela si vous n'avez pas coch\u00E9 la case "Distribuer points".
+chelp.config.7=<strong>$\:config.points.max</strong>\: entrez le score maximum qu'un participant au cours peut atteindre. Vous ne pouvez pas faire cela si vous n'avez pas coch\u00E9 la case "Distribuer points".
+chelp.config.8=<strong>$\:config.passed</strong>\: si vous s\u00E9lectionnez cette option, le status "r\u00E9ussi" ou "non r\u00E9ussi" sera montr\u00E9. Si vous ne la s\u00E9lectionnez pas, rien ne sera montr\u00E9.
+chelp.config.9=<strong>$\:config.output</strong>\: par le biais de "Automatiquement par valuer limite", "Automatiquement par nombre de cases coch\u00E9es" ou "Manuellement par le coach", vous avez la possibilit\u00E9 de d\u00E9cider si "r\u00E9ussi" ou "non r\u00E9ussi" sera allou\u00E9 automatiquement en fonction de la valeur limite ou si le coach devra l'affecter manuellement. Vous ne pouvez pas faire cela si vous n'avez pas coch\u00E9 la case "Afficher r\u00E9ussi/pas r\u00E9ussi".
+chelp.metadatas.1=La troisi\u00E8me \u00E9tape de l'assistant vous permet de personnaliser les titres des listes de contr\u00F4le en fonction de vos d\u00E9sirs. D\u00E9finissez le d\u00E9lai pour chaque liste si vous avez activ\u00E9 la date limite \u00E0 l'\u00E9tape pr\u00E9c\u00E9dente. Il suffit de laisser le champ r\u00E9serv\u00E9 \u00E0 la date vide si vous ne voulez pas configurer de d\u00E9lai.
+chelp.stconfig.1=D\u00E9finissez le titre et la description de l'\u00E9l\u00E9ment structure m\u00E8re pendant la quatri\u00E8me et derni\u00E8re \u00E9tape. Tant le titre abr\u00E9g\u00E9 que le titre seront affich\u00E9s dans le cours, comme \u00E0 l'accoutum\u00E9.
+chelp.stconfig.2=D\u00E9terminez si les donn\u00E9es d'\u00E9valuation des sous-\u00E9l\u00E9ments de type liste de contr\u00F4le seront affich\u00E9 dans l'\u00E9l\u00E9ment de cours structure, et comment l'\u00E9valuation devra \u00EAtre men\u00E9e. Pour plus d'informations sur l'\u00E9l\u00E9ment de cours structure et sur l'\u00E9valuation des autres \u00E9l\u00E9ments de cours, veuillez vous r\u00E9f\u00E9rer \u00E0 l'aide contextuelle sous
+chelp.template.config.1=La deuxi\u00E8me \u00E9tape vous permet de d\u00E9terminer le nombre de listes de contr\u00F4le qui devra \u00EAtre cr\u00E9\u00E9 sur la base du mod\u00E8le pr\u00E9d\u00E9fini dans la premi\u00E8re \u00E9tape. Indiquez un titre, que reprendra alors les titres individuels de la liste de contr\u00F4le avec un num\u00E9ro s\u00E9quentiel en sus. Vous pouvez adapter les titres \u00E0 l'\u00E9tape suivante.
+chelp.template.config.2=Pour plus d'informations sur la configuration de la liste de contr\u00F4le, veuillez vous r\u00E9f\u00E9rez \u00E0 l'aide contextuelle sous
+chelp.template.config.3=. Si vous configur\u00E9 les listes de contr\u00F4le avec une date limite, vous pouvez d\u00E9finir le d\u00E9lai de la troisi\u00E8me \u00E9tape.
 coach.desc=Dans la liste ci-dessous vous trouverez tous les participants du cours que vous supervisez. S\u00E9lectionnez "$\:table.header.edit.checkbox" pour changer les cases \u00E0 cocher ou le score d'un participant.
 coach.due.date.desc=S'il vous pla\u00EEt noter que cette liste de contr\u00F4le fixe un d\u00E9lai. En tant que coach, vous ne devez effectuer des changements qu'apr\u00E8s la date limite d'expiration.
 comment.nocomment=$org.olat.course.nodes.ms\:comment.nocomment
diff --git a/src/main/java/org/olat/course/nodes/ta/DropboxController.java b/src/main/java/org/olat/course/nodes/ta/DropboxController.java
index dcfa27fe956f2a1d873ae13140beffd72d2c5369..b93b8d68d132414fa597942a5b4c7e9ee2fede72 100644
--- a/src/main/java/org/olat/course/nodes/ta/DropboxController.java
+++ b/src/main/java/org/olat/course/nodes/ta/DropboxController.java
@@ -145,12 +145,13 @@ public class DropboxController extends BasicController {
 		myContent.contextPut("previewMode", previewMode ? Boolean.TRUE : Boolean.FALSE);
 
 		// notification
+		CourseEnvironment courseEnv = userCourseEnv.getCourseEnvironment();
+		subsContext = DropboxFileUploadNotificationHandler.getSubscriptionContext(courseEnv, node);
 		if ( hasNotification && !previewMode) {
 			// offer subscription, but not to guests
-			subsContext = DropboxFileUploadNotificationHandler.getSubscriptionContext(userCourseEnv, node);
 			if (subsContext != null) {
-				contextualSubscriptionCtr = AbstractTaskNotificationHandler.createContextualSubscriptionController(ureq, wControl, getDropboxPathRelToFolderRoot(
-						userCourseEnv.getCourseEnvironment(), node), subsContext, DropboxController.class);
+				String path = getDropboxPathRelToFolderRoot(courseEnv, node);
+				contextualSubscriptionCtr = AbstractTaskNotificationHandler.createContextualSubscriptionController(ureq, wControl, path, subsContext, DropboxController.class);
 				myContent.put("subscription", contextualSubscriptionCtr.getInitialComponent());
 				myContent.contextPut("hasNotification", Boolean.TRUE);
 			}
@@ -243,7 +244,7 @@ public class DropboxController extends BasicController {
 				
 				VFSLeaf fOut;
 				if (fDropbox.resolve(fIn.getName()) != null) {
-					//FIXME ms: check if dropbox quota is exceeded -> with customers abkl�ren
+					//FIXME ms: check if dropbox quota is exceeded -> clarify with customers 
 					fOut = fDropbox.createChildLeaf(getNewUniqueName(fIn.getName()));
 				} else {
 					fOut = fDropbox.createChildLeaf(fIn.getName());
@@ -308,7 +309,6 @@ public class DropboxController extends BasicController {
 						} 
 					}
 
-					subsContext = DropboxFileUploadNotificationHandler.getSubscriptionContext(userCourseEnv, node);
 					// inform subscription manager about new element
 					if (subsContext != null) {
 						NotificationsManager.getInstance().markPublisherNews(subsContext, ureq.getIdentity(), true);
diff --git a/src/main/java/org/olat/course/nodes/ta/DropboxFileUploadNotificationHandler.java b/src/main/java/org/olat/course/nodes/ta/DropboxFileUploadNotificationHandler.java
index 8e86e8eaf4153653f6ee21f5a7fffc086fce8b43..75ee0375618e05a3021108711ef4eeebf2736fa6 100644
--- a/src/main/java/org/olat/course/nodes/ta/DropboxFileUploadNotificationHandler.java
+++ b/src/main/java/org/olat/course/nodes/ta/DropboxFileUploadNotificationHandler.java
@@ -31,7 +31,7 @@ import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.course.CourseModule;
 import org.olat.course.nodes.CourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.course.run.environment.CourseEnvironment;
 
 /**
  * Description:<br>
@@ -51,8 +51,8 @@ public class DropboxFileUploadNotificationHandler extends AbstractTaskNotificati
 		//empty block
 	}
 	
-	protected static SubscriptionContext getSubscriptionContext(UserCourseEnvironment userCourseEnv, CourseNode node) {
-	  return CourseModule.createSubscriptionContext(userCourseEnv.getCourseEnvironment(), node, node.getIdent());
+	protected static SubscriptionContext getSubscriptionContext(CourseEnvironment courseEnv, CourseNode node) {
+	  return CourseModule.createSubscriptionContext(courseEnv, node, node.getIdent());
 	}
 
 	protected String getCssClassIcon() {
diff --git a/src/main/java/org/olat/course/nodes/ta/SolutionController.java b/src/main/java/org/olat/course/nodes/ta/SolutionController.java
index 99fc83fd2bf9ad35bea4ee200e123bc4d46715a0..3e935e3d755a84b96239349bb16c37757779e731 100644
--- a/src/main/java/org/olat/course/nodes/ta/SolutionController.java
+++ b/src/main/java/org/olat/course/nodes/ta/SolutionController.java
@@ -42,7 +42,6 @@ import org.olat.core.util.vfs.callbacks.ReadOnlyCallback;
 import org.olat.course.nodes.CourseNode;
 import org.olat.course.nodes.TACourseNode;
 import org.olat.course.run.environment.CourseEnvironment;
-import org.olat.course.run.userview.UserCourseEnvironment;
 
 /**
  *  
@@ -64,28 +63,27 @@ public class SolutionController extends BasicController {
 	 * @param wControl
 	 * @param config
 	 * @param node
-	 * @param userCourseEnv
+	 * @param courseEnv
 	 * @param previewMode
 	 */
-	public SolutionController(UserRequest ureq, WindowControl wControl, CourseNode node, UserCourseEnvironment userCourseEnv, boolean previewMode) {
+	public SolutionController(UserRequest ureq, WindowControl wControl, CourseNode node, CourseEnvironment courseEnv, boolean previewMode) {
 		super(ureq, wControl);
 		
 		myContent = createVelocityContainer("solutionRun");
 		
 		// returnbox display
-		OlatRootFolderImpl rootFolder = new OlatRootFolderImpl(
-			SolutionController.getSolutionPathRelToFolderRoot(userCourseEnv.getCourseEnvironment(), node), null);
+		String solutionPath = SolutionController.getSolutionPathRelToFolderRoot(courseEnv, node);
+		OlatRootFolderImpl rootFolder = new OlatRootFolderImpl(solutionPath, null);
 		OlatNamedContainerImpl namedContainer = new OlatNamedContainerImpl("solutions", rootFolder); 
 		namedContainer.setLocalSecurityCallback(new ReadOnlyCallback());
 		solutionFolderRunController = new FolderRunController(namedContainer, false, ureq, wControl);
 		solutionFolderRunController.addControllerListener(this);
 		myContent.put("solutionbox", solutionFolderRunController.getInitialComponent());
-		if ( !previewMode) {
+		if (!previewMode) {
 			// offer subscription, but not to guests
-			subsContext = SolutionFileUploadNotificationHandler.getSubscriptionContext(userCourseEnv, node);
+			subsContext = SolutionFileUploadNotificationHandler.getSubscriptionContext(courseEnv, node);
 			if (subsContext != null) {
-				contextualSubscriptionCtr = AbstractTaskNotificationHandler.createContextualSubscriptionController(ureq, wControl, getSolutionPathRelToFolderRoot(
-						userCourseEnv.getCourseEnvironment(), node), subsContext, SolutionController.class);
+				contextualSubscriptionCtr = AbstractTaskNotificationHandler.createContextualSubscriptionController(ureq, wControl, solutionPath, subsContext, SolutionController.class);
 				myContent.put("subscription", contextualSubscriptionCtr.getInitialComponent());
 				myContent.contextPut("hasNotification", Boolean.TRUE);
 			}
diff --git a/src/main/java/org/olat/course/nodes/ta/SolutionFileUploadNotificationHandler.java b/src/main/java/org/olat/course/nodes/ta/SolutionFileUploadNotificationHandler.java
index e4036196b8ab617fba998951ac8ab3ee81906135..9c3a969b93757185faea05d1a60a6480eed27b12 100644
--- a/src/main/java/org/olat/course/nodes/ta/SolutionFileUploadNotificationHandler.java
+++ b/src/main/java/org/olat/course/nodes/ta/SolutionFileUploadNotificationHandler.java
@@ -32,7 +32,7 @@ import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.course.CourseModule;
 import org.olat.course.nodes.CourseNode;
-import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.course.run.environment.CourseEnvironment;
 
 /**
  * Description:<br>
@@ -51,8 +51,8 @@ public class SolutionFileUploadNotificationHandler extends AbstractTaskNotificat
 		//empty block
 	}
 
-	protected static SubscriptionContext getSubscriptionContext(UserCourseEnvironment userCourseEnv, CourseNode node) {
-	  return CourseModule.createSubscriptionContext(userCourseEnv.getCourseEnvironment(), node, "Solutionbox");
+	protected static SubscriptionContext getSubscriptionContext(CourseEnvironment courseEnv, CourseNode node) {
+	  return CourseModule.createSubscriptionContext(courseEnv, node, "Solutionbox");
 	}
 
 	protected String getCssClassIcon() {
diff --git a/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java b/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java
index 890016621d6fe2481bdc42a0f4a9171af8077744..3ca8a6d8aacabac91d7e4ba648f9d68aa342f558 100644
--- a/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java
+++ b/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java
@@ -255,7 +255,7 @@ public class TACourseNodeEditController extends ActivateableTabbableDefaultContr
 		editScoring.contextPut("isOverwriting", new Boolean(false));
 		
 		// Solution-Tab		
-		solutionVC = this.createVelocityContainer("editSolutionFolder");
+		solutionVC = createVelocityContainer("editSolutionFolder");
 		vfButton = LinkFactory.createButton("link.solutionFolder", solutionVC, this);
 				
 	}
@@ -290,10 +290,9 @@ public class TACourseNodeEditController extends ActivateableTabbableDefaultContr
 			} else {				
 				// already assigned task => open dialog with warn
 				String[] args = new String[] { new Integer(assignedProps.size()).toString() };				
-				dialogBoxController = this.activateOkCancelDialog(ureq, "", getTranslator().translate("taskfolder.overwriting.confirm", args), dialogBoxController);
+				dialogBoxController = activateOkCancelDialog(ureq, "", getTranslator().translate("taskfolder.overwriting.confirm", args), dialogBoxController);
 			}
-		} else if (source == vfButton) {			
-			if (log.isDebug()) log.debug("Event for sampleVC");
+		} else if (source == vfButton) {
 			// switch to new dialog
 			OlatNamedContainerImpl namedContainer = TACourseNode.getNodeFolderContainer(node, course.getCourseEnvironment());
 			Quota quota = QuotaManager.getInstance().getCustomQuota(namedContainer.getRelPath());
@@ -301,14 +300,12 @@ public class TACourseNodeEditController extends ActivateableTabbableDefaultContr
 				Quota defQuota = QuotaManager.getInstance().getDefaultQuota(QuotaConstants.IDENTIFIER_DEFAULT_NODES);
 				quota = QuotaManager.getInstance().createQuota(namedContainer.getRelPath(), defQuota.getQuotaKB(), defQuota.getUlLimitKB());
 			}
-			VFSSecurityCallback secCallback = new FullAccessWithQuotaCallback(quota);
+			SubscriptionContext subContext = SolutionFileUploadNotificationHandler.getSubscriptionContext(course.getCourseEnvironment(), node);
+			VFSSecurityCallback secCallback = new FullAccessWithQuotaCallback(quota, subContext);
 			namedContainer.setLocalSecurityCallback(secCallback);
-			CloseableModalController cmc = new CloseableModalController(getWindowControl(), translate("close"),
-				new FolderRunController(namedContainer, false, ureq, getWindowControl()).getInitialComponent());
+			FolderRunController folderCtrl = new FolderRunController(namedContainer, false, ureq, getWindowControl());
+			CloseableModalController cmc = new CloseableModalController(getWindowControl(), translate("close"), folderCtrl.getInitialComponent());
 			cmc.activate();
-			
-			if (log.isDebug()) log.debug("Switch to sample folder dialog : DONE");
-			return;
 		} else if (source == editScoringConfigButton){
 			scoringController.setDisplayOnly(false);
 			editScoring.contextPut("isOverwriting", new Boolean(true));
diff --git a/src/main/java/org/olat/course/nodes/ta/TACourseNodeRunController.java b/src/main/java/org/olat/course/nodes/ta/TACourseNodeRunController.java
index 7b3d8a8f8efbecd332b6e273385cda0632241ccf..77473921b79b23c226b60d57cd231fe983e3fa86 100644
--- a/src/main/java/org/olat/course/nodes/ta/TACourseNodeRunController.java
+++ b/src/main/java/org/olat/course/nodes/ta/TACourseNodeRunController.java
@@ -103,7 +103,7 @@ public class TACourseNodeRunController extends BasicController {
 		}
 
 		if (hasSolution) {
-			solutionController = new SolutionController(ureq, wControl, ne.getCourseNode(), userCourseEnv, previewMode);
+			solutionController = new SolutionController(ureq, wControl, ne.getCourseNode(), userCourseEnv.getCourseEnvironment(), previewMode);
 			content.put("solutionController", solutionController.getInitialComponent());
 			content.contextPut("hasSolution", Boolean.TRUE);
 		}
diff --git a/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java b/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java
index be74a9a0d2cd1fa18d82ca30c046195db6d6576e..7cc3ea59da0d71df77ea49fcdab2c84412a69c55 100644
--- a/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java
+++ b/src/main/java/org/olat/group/GroupfoldersWebDAVMergeSource.java
@@ -39,7 +39,6 @@ import org.olat.core.util.vfs.QuotaManager;
 import org.olat.core.util.vfs.VFSConstants;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
-import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.VFSStatus;
 import org.olat.core.util.vfs.callbacks.FullAccessWithQuotaCallback;
 import org.olat.core.util.vfs.callbacks.ReadOnlyCallback;
@@ -91,60 +90,34 @@ class GroupfoldersWebDAVMergeSource extends MergeSource {
 
 	@Override
 	public List<VFSItem> getItems() {
-		if(!init) {
-			init();
-		}
+		checkInitialization();
 		return super.getItems();
 	}
 
 	@Override
 	public List<VFSItem> getItems(VFSItemFilter filter) {
-		if(!init  || (System.currentTimeMillis() - loadTime) > 60000) {
-			init();
-		}
+		checkInitialization();
 		return super.getItems(filter);
 	}
 
 	@Override
 	public VFSItem resolve(String path) {
-		if(init) {
-			return super.resolve(path);
-		}
-		
-		path = VFSManager.sanitizePath(path);
-		if (path.equals("/")) {
-			return this;
-		}
-		
-		String childName = VFSManager.extractChild(path);
-
-		SearchBusinessGroupParams params = new SearchBusinessGroupParams(identity, true, true);
-		params.addTools(CollaborationTools.TOOL_FOLDER);
-		BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
-		List<BusinessGroup> groups = bgs.findBusinessGroups(params, null, 0, -1);
-		Set<String> addedGroupNames = new HashSet<String>();
-		for(BusinessGroup group:groups) {
-			String name = nameIdentifier(group, addedGroupNames);
-			if(name == null) {
-				continue;
+		checkInitialization();
+		return super.resolve(path);
+	}
+	
+	private void checkInitialization() {
+		if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
+			synchronized(this) {
+				if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
+					init();
+				}
 			}
-			
-			name = RequestUtil.normalizeFilename(name);
-			if(childName.equals(name)) {
-				String nextPath = path.substring(childName.length() + 1);
-				VFSContainer grpContainer = getGroupContainer(name, group, false);
-				VFSItem item = grpContainer.resolve(nextPath);
-				return item;
-			}	
 		}
-
-		return super.resolve(path);
 	}
 	
 	@Override
 	protected void init() {
-		super.init();
-
 		// collect buddy groups
 		BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
 
diff --git a/src/main/java/org/olat/ims/qti/statistics/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti/statistics/ui/_i18n/LocalStrings_en.properties
index e2de125304d3ff3fcd5de08eed4d0ca1e107ce97..b322d8f0144d9ff8eaaa852d93e813bc83563e8f 100644
--- a/src/main/java/org/olat/ims/qti/statistics/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti/statistics/ui/_i18n/LocalStrings_en.properties
@@ -42,6 +42,8 @@ chart.thisquestionwrongansweredpercent={0}% of the participants did not answer t
 chart.title.completiontime=Completion time
 chart.title.ovpassedfailed=Passed / Failed
 download.raw.data=Download raw data
+essay.warning.test=This test contains question of type essay. Please navigate to the respective question for further analysis.
+essay.warning.survey=This questionnaire contains question of type essay. Please navigate to the respective question for further analysis.
 fig.averagedur=Average completion time
 fig.averagescore=Average score
 fig.avg=Arithmetic average
diff --git a/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java b/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java
index ca1608e8cdac284524f7c84764359ad4433b2f4e..b5123f8009d39b74e443ea10b9b1d39e63894b53 100644
--- a/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java
+++ b/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVMergeSource.java
@@ -27,7 +27,6 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import org.olat.core.commons.services.webdav.servlets.RequestUtil;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
 import org.olat.core.logging.OLog;
@@ -35,7 +34,6 @@ import org.olat.core.logging.Tracing;
 import org.olat.core.util.vfs.MergeSource;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
-import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.filters.VFSItemFilter;
 import org.olat.fileresource.types.SharedFolderFileResource;
 import org.olat.repository.RepositoryEntry;
@@ -64,94 +62,34 @@ public class SharedFolderWebDAVMergeSource extends MergeSource {
 
 	@Override
 	public List<VFSItem> getItems() {
-		if(!init) {
-			init();
-		}
+		checkInitialization();
 		return super.getItems();
 	}
 
 	@Override
 	public List<VFSItem> getItems(VFSItemFilter filter) {
-		if(!init  || (System.currentTimeMillis() - loadTime) > 60000) {
-			init();
-		}
+		checkInitialization();
 		return super.getItems(filter);
 	}
 
 	@Override
 	public VFSItem resolve(String path) {
-		if(init) {
-			return super.resolve(path);
-		}
-
-		path = VFSManager.sanitizePath(path);
-		if (path.equals("/")) {
-			return this;
-		}
-		
-		String childName = VFSManager.extractChild(path);
-		RepositoryManager repoManager = RepositoryManager.getInstance();
-		
-		//lookup in my shared folders
-		List<RepositoryEntry> ownerEntries = repoManager.queryByOwner(identity, SharedFolderFileResource.TYPE_NAME);
-		for (RepositoryEntry re : ownerEntries) {
-			String name = RequestUtil.normalizeFilename(re.getDisplayname());
-			if(childName.equals(name)) {
-				VFSContainer shared = getSharedContainer(re, false);
-				String nextPath = path.substring(childName.length() + 1);
-				return shared.resolve(nextPath);
-			}	
-		}
-		
-		if (publiclyReadableFolders != null && publiclyReadableFolders.size() > 0) {
-			String firstItem = publiclyReadableFolders.get(0);
-			// If the first value in the list is '*', list all resource folders.
-			if (firstItem != null && firstItem.equals("*")) {
-				// fake role that represents normally logged in user
-				Roles registeredUserRole = new Roles(false, false, false, false, false, false, false);
-				List<String> types = Collections.singletonList(SharedFolderFileResource.TYPE_NAME);
-				List<RepositoryEntry> allEntries = repoManager.queryByTypeLimitAccess(identity, types, registeredUserRole);
-				for (RepositoryEntry re : allEntries) {
-					String name = RequestUtil.normalizeFilename(re.getDisplayname());
-					if(childName.equals(name)) {
-						VFSContainer shared = getSharedContainer(re, true);
-						String nextPath = path.substring(childName.length() + 1);
-						return shared.resolve(nextPath);
-					}	
-				}
-			} else {
-				// only list the specified folders
-				List<Long> publiclyReadableFoldersKeys = getSharedKeys();	
-				List<RepositoryEntry> entries = repoManager.lookupRepositoryEntries(publiclyReadableFoldersKeys);
-				for (RepositoryEntry re:entries) {
-					String name = RequestUtil.normalizeFilename(re.getDisplayname());
-					if (childName.equals(name) && 
-							(re.getAccess() >= RepositoryEntry.ACC_USERS || (re.getAccess() == RepositoryEntry.ACC_OWNERS && re.isMembersOnly()))) {
-						
-						VFSContainer shared = getSharedContainer(re, true);
-						String nextPath = path.substring(childName.length() + 1);
-						return shared.resolve(nextPath);
-					}
-				}
-			}
-		}
-		
+		checkInitialization();
 		return super.resolve(path);
 	}
 	
-	private VFSContainer getSharedContainer(RepositoryEntry re, boolean readOnly) {
-		SharedFolderManager sfm = SharedFolderManager.getInstance();
-		VFSContainer shared = sfm.getNamedSharedFolder(re, true);
-		if(readOnly) {
-			shared.setLocalSecurityCallback(readOnlyCallback);
+	private void checkInitialization() {
+		if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
+			synchronized(this) {
+				if(!init || (System.currentTimeMillis() - loadTime) > 60000) {
+					init();
+				}
+			}
 		}
-		return shared;
 	}
 	
 	@Override
 	protected void init() {
-		super.init();
-
 		SharedFolderManager sfm = SharedFolderManager.getInstance();
 		RepositoryManager repoManager = RepositoryManager.getInstance();
 		List<VFSContainer> containers = new ArrayList<>();
diff --git a/src/main/java/org/olat/registration/RegistrationController.java b/src/main/java/org/olat/registration/RegistrationController.java
index ccef747ae97b611cedd4e324296a9f881a7c7a54..11643199c2c7054853e08dd624e69748b68823bf 100644
--- a/src/main/java/org/olat/registration/RegistrationController.java
+++ b/src/main/java/org/olat/registration/RegistrationController.java
@@ -389,7 +389,12 @@ public class RegistrationController extends BasicController implements Activatea
 		finishVC.contextPut("locale", getLocale());
 		finishVC.contextPut("username", registrationForm.getLogin());
 		finishVC.contextPut("text", getTranslator().translate("step5.reg.text", new String[] {registrationForm.getLogin() }));
-		finishVC.contextPut("loginhref", WebappHelper.getServletContextPath());
+		String loginhref = WebappHelper.getServletContextPath();
+		if(StringHelper.containsNonWhitespace(loginhref)) {
+			finishVC.contextPut("loginhref", loginhref);
+		} else {
+			finishVC.contextPut("loginhref", "/");
+		}
 		
 		regarea.setContent(finishVC);
 	}
diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java
index 46e15caaf7ca5807ed6b67cc5a300e97793eae73..01c0bd881b916524274dd8ae5bb1ce3e4de5d24f 100644
--- a/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java
+++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java
@@ -124,6 +124,33 @@ public class WebDAVCommandsTest extends WebDAVTestCase {
 		IOUtils.closeQuietly(conn);
 	}
 	
+	@Test
+	public void testHead()
+	throws IOException, URISyntaxException {
+		//create a user
+		Identity user = JunitTestHelper.createAndPersistIdentityAsUser("webdav-2-" + UUID.randomUUID().toString());
+
+		WebDAVConnection conn = new WebDAVConnection();
+		conn.setCredentials(user.getName(), "A6B7C8");
+		
+		//create a file
+		String publicPath = FolderConfig.getUserHomes() + "/" + user.getName() + "/public";
+		VFSContainer vfsPublic = new OlatRootFolderImpl(publicPath, null);
+		createFile(vfsPublic, "test_head.txt");
+		
+		//head file
+		URI publicUri = conn.getBaseURI().path("webdav").path("home").path("public").path("test_head.txt").build();
+		HttpResponse response = conn.head(publicUri);
+		Header lengthHeader = response.getFirstHeader("Content-Length");
+		Assert.assertNotNull(lengthHeader);
+		Assert.assertEquals("0", lengthHeader.getValue());
+		Header typeHeader = response.getFirstHeader("Content-Type");
+		Assert.assertNotNull(typeHeader);
+		Assert.assertEquals("text/plain", typeHeader.getValue());
+		EntityUtils.consume(response.getEntity());
+		IOUtils.closeQuietly(conn);
+	}
+	
 	@Test
 	public void testPropFind()
 	throws IOException, URISyntaxException {
diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java
index 4eda895288706d50383f2944fbd91db18ee43d2f..414e44d6979f57d39dd60929cc674d116019f38c 100644
--- a/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java
+++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java
@@ -38,6 +38,7 @@ import org.apache.http.client.CookieStore;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
 import org.apache.http.client.methods.HttpOptions;
 import org.apache.http.client.methods.HttpPut;
 import org.apache.http.client.methods.HttpUriRequest;
@@ -93,6 +94,13 @@ public class WebDAVConnection implements Closeable {
 		return response;
 	}
 	
+	public HttpResponse head(URI uri) throws IOException, URISyntaxException {
+		HttpHead propfind = new HttpHead(uri);
+		HttpResponse response = execute(propfind);
+		Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+		return response;
+	}
+	
 	public String propfind(URI uri, int depth) throws IOException, URISyntaxException {
 		HttpPropFind propfind = new HttpPropFind(uri);
 		propfind.addHeader("Depth", Integer.toString(depth));