diff --git a/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java b/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java
index 6915f57a8e5058694c35af4896934688cf4d7bf9..a60d92bfa9c05b1ec3b7f4124883bf39f41b840e 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java
@@ -48,6 +48,7 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff {
 	private static final String LEARNERS_BOOKMARKS_COURSE = "webdav.learners.bookmarks.courses";
 	private static final String LEARNERS_PARTICIPATING_COURSES = "webdav.learners.participating.courses";
 	private static final String PREPEND_COURSE_REFERENCE_TO_TITLE = "webdav.prepend.course.reference.to.title";
+	private static final String CURRICULUM_ELEMENTS_FOLDERS_ENABLED = "webdav.curriculumelements.folders.enabled";
 	
 	@Autowired
 	private List<WebDAVProvider> webdavProviders;
@@ -60,6 +61,8 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff {
 	private boolean digestAuthenticationEnabled;
 	@Value("${webdav.termsfolders.enabled:true}")
 	private boolean termsFoldersEnabled;
+	@Value("${webdav.curriculumelements.folders.enabled:false}")
+	private boolean curriculumElementFoldersEnabled;
 	@Value("${webdav.prepend.course.reference.to.title:false}")
 	private boolean prependCourseReferenceToTitle;
 
@@ -99,6 +102,11 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff {
 			termsFoldersEnabled = "true".equals(termsFoldersEnabledObj);
 		}
 		
+		String curriculumElementsFoldersEnabledObj = getStringPropertyValue(CURRICULUM_ELEMENTS_FOLDERS_ENABLED, true);
+		if(StringHelper.containsNonWhitespace(curriculumElementsFoldersEnabledObj)) {
+			curriculumElementFoldersEnabled = "true".equals(curriculumElementsFoldersEnabledObj);
+		}
+		
 		String learnersBookmarksCourseObj = getStringPropertyValue(LEARNERS_BOOKMARKS_COURSE, true);
 		if(StringHelper.containsNonWhitespace(learnersBookmarksCourseObj)) {
 			enableLearnersBookmarksCourse = "true".equals(learnersBookmarksCourseObj);
@@ -159,6 +167,16 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff {
 		setStringProperty(TERMS_FOLDERS_ENABLED, enabledStr, true);
 	}
 
+
+	public boolean isCurriculumElementFoldersEnabled() {
+		return curriculumElementFoldersEnabled;
+	}
+
+	public void setCurriculumElementFoldersEnabled(boolean enabled) {
+		this.curriculumElementFoldersEnabled = enabled;
+		setStringProperty(CURRICULUM_ELEMENTS_FOLDERS_ENABLED, Boolean.toString(enabled), true);
+	}
+
 	public boolean isEnableLearnersBookmarksCourse() {
 		return enableLearnersBookmarksCourse;
 	}
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java b/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java
index f531c4d0fc43cd26a39536be6142d8549254923b..55f9c1fd03bbd0a490068c2c293172c72e109d13 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java
@@ -37,8 +37,16 @@ import org.olat.core.gui.control.WindowControl;
  */
 public class WebDAVAdminController extends FormBasicController {
 	
-	private MultipleSelectionElement enableModuleEl, enableLinkEl, enableDigestEl, enableTermsFoldersEl,
-			learnersAsParticipantEl, learnersBookmarkEl, prependReferenceEl;
+	private static final String[] onKeys = new String[]{"xx"};
+	
+	private MultipleSelectionElement enableModuleEl;
+	private MultipleSelectionElement enableLinkEl;
+	private MultipleSelectionElement enableDigestEl;
+	private MultipleSelectionElement enableTermsFoldersEl;
+	private MultipleSelectionElement enableCurriculumElementFoldersEl;
+	private MultipleSelectionElement learnersAsParticipantEl;
+	private MultipleSelectionElement learnersBookmarkEl;
+	private MultipleSelectionElement prependReferenceEl;
 	
 	private final WebDAVModule webDAVModule;
 	
@@ -58,40 +66,45 @@ public class WebDAVAdminController extends FormBasicController {
 
 		boolean enabled = webDAVModule.isEnabled();
 		String[] values = new String[] { getTranslator().translate("webdav.on") };
-		enableModuleEl = uifactory.addCheckboxesHorizontal("webdavModule", "webdav.module", formLayout, new String[]{"xx"}, values);
+		enableModuleEl = uifactory.addCheckboxesHorizontal("webdavModule", "webdav.module", formLayout, onKeys, values);
 		enableModuleEl.select("xx", enabled);
 		enableModuleEl.addActionListener(FormEvent.ONCHANGE);
 		
-		enableLinkEl = uifactory.addCheckboxesHorizontal("webdavLink", "webdav.link", formLayout, new String[]{"xx"}, values);
+		enableLinkEl = uifactory.addCheckboxesHorizontal("webdavLink", "webdav.link", formLayout, onKeys, values);
 		enableLinkEl.select("xx", webDAVModule.isLinkEnabled());
 		enableLinkEl.addActionListener(FormEvent.ONCHANGE);
 		enableLinkEl.setEnabled(enabled);
 		
-		enableDigestEl = uifactory.addCheckboxesHorizontal("webdavDigest", "webdav.digest", formLayout, new String[]{"xx"}, values);
+		enableDigestEl = uifactory.addCheckboxesHorizontal("webdavDigest", "webdav.digest", formLayout, onKeys, values);
 		enableDigestEl.select("xx", webDAVModule.isDigestAuthenticationEnabled());
 		enableDigestEl.addActionListener(FormEvent.ONCHANGE);
 		enableDigestEl.setEnabled(enabled);
 		
 		uifactory.addSpacerElement("spacer1", formLayout, false);
 		
-		enableTermsFoldersEl = uifactory.addCheckboxesHorizontal("webdavTermsFolders", "webdav.termsfolders", formLayout, new String[]{"xx"}, values);
+		enableTermsFoldersEl = uifactory.addCheckboxesHorizontal("webdavTermsFolders", "webdav.termsfolders", formLayout, onKeys, values);
 		enableTermsFoldersEl.select("xx", webDAVModule.isTermsFoldersEnabled());
 		enableTermsFoldersEl.addActionListener(FormEvent.ONCHANGE);
 		enableTermsFoldersEl.setEnabled(enabled);
 		
-		prependReferenceEl = uifactory.addCheckboxesHorizontal("webdavPrepend", "webdav.prepend.reference", formLayout, new String[]{"xx"}, values);
+		enableCurriculumElementFoldersEl = uifactory.addCheckboxesHorizontal("webdavCurriculumsElementsFolders", "webdav.curriculumelementsfolders", formLayout, onKeys, values);
+		enableCurriculumElementFoldersEl.select("xx", webDAVModule.isCurriculumElementFoldersEnabled());
+		enableCurriculumElementFoldersEl.addActionListener(FormEvent.ONCHANGE);
+		enableCurriculumElementFoldersEl.setEnabled(enabled);
+		
+		prependReferenceEl = uifactory.addCheckboxesHorizontal("webdavPrepend", "webdav.prepend.reference", formLayout, onKeys, values);
 		prependReferenceEl.select("xx", webDAVModule.isPrependCourseReferenceToTitle());
 		prependReferenceEl.addActionListener(FormEvent.ONCHANGE);
 		prependReferenceEl.setEnabled(enabled);
 
 		uifactory.addSpacerElement("spacer2", formLayout, false);
 		
-		learnersAsParticipantEl = uifactory.addCheckboxesHorizontal("learnersParticipants", "webdav.for.learners.participants", formLayout, new String[]{"xx"}, values);
+		learnersAsParticipantEl = uifactory.addCheckboxesHorizontal("learnersParticipants", "webdav.for.learners.participants", formLayout, onKeys, values);
 		learnersAsParticipantEl.select("xx", webDAVModule.isEnableLearnersParticipatingCourses());
 		learnersAsParticipantEl.addActionListener(FormEvent.ONCHANGE);
 		learnersAsParticipantEl.setEnabled(enabled);
 		
-		learnersBookmarkEl = uifactory.addCheckboxesHorizontal("learnerBookmarks", "webdav.for.learners.bookmarks", formLayout, new String[]{"xx"}, values);
+		learnersBookmarkEl = uifactory.addCheckboxesHorizontal("learnerBookmarks", "webdav.for.learners.bookmarks", formLayout, onKeys, values);
 		learnersBookmarkEl.select("xx", webDAVModule.isEnableLearnersBookmarksCourse());
 		learnersBookmarkEl.addActionListener(FormEvent.ONCHANGE);
 		learnersBookmarkEl.setEnabled(enabled);
@@ -121,6 +134,9 @@ public class WebDAVAdminController extends FormBasicController {
 		} else if(source == enableTermsFoldersEl) {
 			boolean enabled = enableTermsFoldersEl.isAtLeastSelected(1);
 			webDAVModule.setTermsFoldersEnabled(enabled);
+		} else if(source == enableCurriculumElementFoldersEl) {
+			boolean enabled = enableCurriculumElementFoldersEl.isAtLeastSelected(1);
+			webDAVModule.setCurriculumElementFoldersEnabled(enabled);
 		} else if(source == learnersAsParticipantEl) {
 			boolean enabled = learnersAsParticipantEl.isAtLeastSelected(1);
 			webDAVModule.setEnableLearnersParticipatingCourses(enabled);
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
index 84b12d8bde0a7799d3230ef7a58728136650ba4d..b2dde1627107816c12da2f0c317baa5122804e2b 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
@@ -3,6 +3,7 @@ admin.menu.title=WebDAV
 admin.menu.title.alt=WebDAV Zugang
 admin.webdav.description=Mit Hilfe von WebDAV k\u00F6nnen Sie OpenOLAT Ordner auf Ihrem lokalen Desktop wie lokale Ordner anzeigen und verwenden. Konfigurieren Sie ob diese Funktion allen Benutzern Systemweit zur Verf\u00FCgung stehen soll. Bitte lesen sie die Kontexthilfe.
 core.webdav=WebDAV
+webdav.curriculumelementsfolders=Kurse nach Curriculumelementen gruppieren
 webdav.digest=Digest Authentication bei HTTP Zugang verwenden 
 webdav.for.learners.bookmarks=Zugriff f\u00FCr Studenten / Betreuer Favoriten
 webdav.for.learners.participants=Zugriff f\u00FCr Studenten / Betreuer Kurse
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
index 47a1aee8a2269e557c578a889fe77998433d88b1..b17b91bc6516c31697f202441bff6ad24e6a1610 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
@@ -3,6 +3,7 @@ admin.menu.title=WebDAV
 admin.menu.title.alt=WebDAV access
 admin.webdav.description=Using WebDAV you can mount and use OpenOLAT folders on your local desktop as if they were local folders. Enable this feature to make it accessable to all users of your platform. Please read the context help.
 core.webdav=WebDAV
+webdav.curriculumelementsfolders=Group courses by curriculum elements
 webdav.digest=Digest Authentication for HTTP access
 webdav.for.learners.bookmarks=Enable access for courses that users marked as favorite
 webdav.for.learners.participants=Enable access for courses where user is participant or coach
diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
index aa85cde2fb3eea63a26a9e9b5872be0f19f44f06..8f8beb9029ecad28319b9b8462d1332831919f90 100644
--- a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
+++ b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
@@ -36,6 +36,8 @@ import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.NamedContainerImpl;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VirtualContainer;
+import org.olat.modules.curriculum.CurriculumService;
+import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryStatusEnum;
 import org.olat.repository.RepositoryManager;
@@ -53,49 +55,52 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource {
 	
 	private final WebDAVModule webDAVModule;
 	private final RepositoryManager repositoryManager;
+	private final CurriculumService curriculumService;
 	
 	public CoursefolderWebDAVMergeSource(IdentityEnvironment identityEnv) {
 		super(identityEnv.getIdentity());
 		this.identityEnv = identityEnv;
 		webDAVModule = CoreSpringFactory.getImpl(WebDAVModule.class);
 		repositoryManager = CoreSpringFactory.getImpl(RepositoryManager.class);
+		curriculumService = CoreSpringFactory.getImpl(CurriculumService.class);
 	}
 	
 	@Override
 	protected List<VFSContainer> loadMergedContainers() {
 		List<VFSContainer> containers = new ArrayList<>();
 		
-		Map<String, VFSContainer> terms = null;
-		VirtualContainer noTermContainer = null;
+		Map<String, VFSContainer> terms = new HashMap<>();
+		VirtualContainer noTermContainer = new VirtualContainer("_other");
 		VirtualContainer finishedContainer = null;
 		
-		boolean useTerms = webDAVModule.isTermsFoldersEnabled();
-		if (useTerms) {
-			// prepare no-terms folder for all resources without semester term info or private date
-			terms = new HashMap<>();
-			noTermContainer = new VirtualContainer("_other");
-		} else {
+		boolean useSemestersTerms = webDAVModule.isTermsFoldersEnabled();
+		boolean useCurriculumElementsTerms = webDAVModule.isCurriculumElementFoldersEnabled();
+		boolean prependReference = webDAVModule.isPrependCourseReferenceToTitle();
+		
+		NamingAndGrouping namingAndGrouping = new NamingAndGrouping(useSemestersTerms, useCurriculumElementsTerms);
+		if(useCurriculumElementsTerms) {
+			namingAndGrouping.setCurriculumElementInfos(getCurriculumElementWebDAVInfosMap());
+		}
+		if(!useSemestersTerms && !useCurriculumElementsTerms) {
 			finishedContainer = new VirtualContainer("_finished");
 		}
-		boolean prependReference = webDAVModule.isPrependCourseReferenceToTitle();
 		
-		UniqueNames container = new UniqueNames();
-		List<RepositoryEntry> editorEntries = repositoryManager.queryByOwner(getIdentity(), "CourseModule");
-		appendCourses(editorEntries, true, containers, useTerms, terms, noTermContainer, finishedContainer, prependReference, container);
+		List<RepositoryEntry> editorEntries = repositoryManager.queryByOwner(getIdentity(), true, "CourseModule");
+		appendCourses(editorEntries, true, containers, terms, noTermContainer, finishedContainer, prependReference, namingAndGrouping);
 		
 		//add courses as participant and coaches
 		if(webDAVModule.isEnableLearnersParticipatingCourses()) {
 			List<RepositoryEntry> entries = repositoryManager.getLearningResourcesAsParticipantAndCoach(getIdentity(), "CourseModule");
-			appendCourses(entries, false, containers, useTerms, terms, noTermContainer, finishedContainer, prependReference, container);
+			appendCourses(entries, false, containers, terms, noTermContainer, finishedContainer, prependReference, namingAndGrouping);
 		}
 		
 		//add bookmarked courses
 		if(webDAVModule.isEnableLearnersBookmarksCourse()) {
 			List<RepositoryEntry> bookmarkedEntries = repositoryManager.getLearningResourcesAsBookmark(getIdentity(), identityEnv.getRoles(), "CourseModule", 0, -1);
-			appendCourses(bookmarkedEntries, false, containers, useTerms, terms, noTermContainer, finishedContainer, prependReference, container);
+			appendCourses(bookmarkedEntries, false, containers, terms, noTermContainer, finishedContainer, prependReference, namingAndGrouping);
 		}
 
-		if (useTerms) {
+		if (useSemestersTerms || useCurriculumElementsTerms) {
 			// add no-terms folder if any have been found
 			if (!noTermContainer.getItems().isEmpty()) {
 				addContainerToList(noTermContainer, containers);
@@ -107,52 +112,85 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource {
 		return containers;
 	}
 	
+	private Map<Long,List<CurriculumElementWebDAVInfos>> getCurriculumElementWebDAVInfosMap() {
+		List<CurriculumElementWebDAVInfos> infos = curriculumService.getCurriculumElementInfosForWebDAV(getIdentity());
+		Map<Long,List<CurriculumElementWebDAVInfos>> infoMap = new HashMap<>();
+		for(CurriculumElementWebDAVInfos info:infos) {
+			List<CurriculumElementWebDAVInfos> repoInfos = infoMap
+					.computeIfAbsent(info.getRepositoryEntryKey(), i -> new ArrayList<>());
+			if(!repoInfos.contains(info)) {
+				repoInfos.add(info);
+			}
+		}
+		return infoMap;
+	}
+	
 	private void appendCourses(List<RepositoryEntry> courseEntries, boolean editor, List<VFSContainer> containers,
-			boolean useTerms, Map<String, VFSContainer> terms, VirtualContainer noTermContainer, VirtualContainer finishedContainer,
-			boolean prependReference, UniqueNames container) {	
+			Map<String, VFSContainer> terms, VirtualContainer noTermContainer, VirtualContainer finishedContainer,
+			boolean prependReference, NamingAndGrouping namingAndGrouping) {	
 		
 		// Add all found repo entries to merge source
 		int count = 0;
 		for (RepositoryEntry re:courseEntries) {
-			if(container.isDuplicate(re)) {
+			if(namingAndGrouping.isDuplicate(re)) {
 				continue;
 			}
-			
-			String displayName = re.getDisplayname();
-			if(prependReference && StringHelper.containsNonWhitespace(re.getExternalRef())) {
-				displayName = re.getExternalRef() + " " + displayName;
-			}
-			String courseTitle = RequestUtil.normalizeFilename(displayName);
-			
+
 			if(finishedContainer != null && re.getEntryStatus() == RepositoryEntryStatusEnum.closed) {
-				String name = container.getFinishedUniqueName(courseTitle);
+				String courseTitle = getCourseTitle(re, prependReference);
+				String name = namingAndGrouping.getFinishedUniqueName(courseTitle);
 				NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
 				finishedContainer.getItems().add(cfContainer);
-			} else if (useTerms) {
+			} else if (namingAndGrouping.isUseSemesterTerms() || namingAndGrouping.isUseCurriculumElementsTerms()) {
 				RepositoryEntryLifecycle lc = re.getLifecycle();
-				if (lc != null && !lc.isPrivateCycle()) {
+				
+				boolean termed = false;
+				if (namingAndGrouping.isUseSemesterTerms() && lc != null && !lc.isPrivateCycle()) {
 					// when a semester term info is found, add it to corresponding term folder
 					String termSoftKey = lc.getSoftKey();
-					VFSContainer termContainer = terms.get(termSoftKey);
-					if (termContainer == null) {
-						// folder for this semester term does not yet exist, create one and add to map
-						String normalizedKey = RequestUtil.normalizeFilename(termSoftKey);
-						termContainer = new VirtualContainer(normalizedKey);
-						terms.put(termSoftKey, termContainer);
-						addContainerToList(termContainer, containers);
-					}
-					
-					String name = container.getTermUniqueName(termSoftKey, courseTitle);
+					VFSContainer termContainer = terms.computeIfAbsent(termSoftKey, term -> {
+						String normalizedKey = RequestUtil.normalizeFilename(term);
+						VirtualContainer container = new VirtualContainer(normalizedKey);
+						addContainerToList(container, containers);
+						return container;
+					});
+
+					String courseTitle = getCourseTitle(re, prependReference);
+					String name = namingAndGrouping.getTermUniqueName(termSoftKey, courseTitle);
 					NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
 					termContainer.getItems().add(cfContainer);
-				} else {
+					termed = true;
+				}
+				
+				if(namingAndGrouping.isUseCurriculumElementsTerms() && namingAndGrouping.hasCurriculumElements(re)) {
+					List<CurriculumElementWebDAVInfos> elements = namingAndGrouping.getCurriculumElementInfos().get(re.getKey());
+					for(CurriculumElementWebDAVInfos element:elements) {
+						String termSoftKey = getTermSoftKey(element);
+						VFSContainer termContainer = terms.computeIfAbsent(termSoftKey, term -> {
+							String normalizedKey = RequestUtil.normalizeFilename(term);
+							VirtualContainer container = new VirtualContainer(normalizedKey);
+							addContainerToList(container, containers);
+							return container;
+						});	
+
+						String courseTitle = getCourseTitle(re, false);
+						String name = namingAndGrouping.getTermUniqueName(termSoftKey, courseTitle);
+						NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
+						termContainer.getItems().add(cfContainer);
+						termed = true;
+					}
+				}
+				
+				if(!termed) {
 					// no semester term found, add to no-term folder
-					String name = container.getNoTermUniqueName(courseTitle);
+					String courseTitle = getCourseTitle(re, prependReference);
+					String name = namingAndGrouping.getNoTermUniqueName(courseTitle);
 					NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
 					noTermContainer.getItems().add(cfContainer);
 				}
 			} else {
-				String name = container.getContainersUniqueName(courseTitle);
+				String courseTitle = getCourseTitle(re, prependReference);
+				String name = namingAndGrouping.getContainersUniqueName(courseTitle);
 				NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
 				addContainerToList(cfContainer, containers);
 			}
@@ -162,7 +200,35 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource {
 		}
 	}
 	
-	private static class UniqueNames {
+	private String getCourseTitle(RepositoryEntry re, boolean prependReference) {
+		String displayName = re.getDisplayname();
+		if(prependReference && StringHelper.containsNonWhitespace(re.getExternalRef())) {
+			displayName = re.getExternalRef() + " " + displayName;
+		}
+		return RequestUtil.normalizeFilename(displayName);
+		
+	}
+	
+	private String getTermSoftKey(CurriculumElementWebDAVInfos element) {
+		StringBuilder sb = new StringBuilder();
+		if(StringHelper.containsNonWhitespace(element.getParentCurriculumElementDisplayName())) {
+			if(StringHelper.containsNonWhitespace(element.getParentCurriculumElementIdentifier())) {
+				sb.append(element.getParentCurriculumElementIdentifier()).append(" ");
+			}
+			sb.append(element.getParentCurriculumElementDisplayName());
+		} else if(StringHelper.containsNonWhitespace(element.getCurriculumElementDisplayName())) {
+			if(StringHelper.containsNonWhitespace(element.getCurriculumElementIdentifier())) {
+				sb.append(element.getCurriculumElementIdentifier()).append(" ");
+			}
+			sb.append(element.getCurriculumElementDisplayName());
+		}
+		return sb.toString();
+	}
+	
+	private static class NamingAndGrouping {
+		
+		private final boolean useSemesterTerms;
+		private final boolean useCurriculumElementsTerms;
 		
 		private final Set<RepositoryEntry> duplicates = new HashSet<>();
 		private final Set<String> containers = new HashSet<>();
@@ -170,6 +236,33 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource {
 		private final Set<String> finishedContainer = new HashSet<>();
 		private final Map<String,Set<String>> termContainers = new HashMap<>();
 		
+		private Map<Long,List<CurriculumElementWebDAVInfos>> curriculumElementInfos;
+		
+		public NamingAndGrouping(boolean useSemesterTerms, boolean useCurriculumElementsTerms) {
+			this.useSemesterTerms = useSemesterTerms;
+			this.useCurriculumElementsTerms = useCurriculumElementsTerms;
+		}
+		
+		public boolean isUseSemesterTerms() {
+			return useSemesterTerms;
+		}
+
+		public boolean isUseCurriculumElementsTerms() {
+			return useCurriculumElementsTerms;
+		}
+
+		public Map<Long, List<CurriculumElementWebDAVInfos>> getCurriculumElementInfos() {
+			return curriculumElementInfos;
+		}
+
+		public void setCurriculumElementInfos(Map<Long, List<CurriculumElementWebDAVInfos>> curriculumElementInfos) {
+			this.curriculumElementInfos = curriculumElementInfos;
+		}
+		
+		public boolean hasCurriculumElements(RepositoryEntry re) {
+			return curriculumElementInfos != null && curriculumElementInfos.containsKey(re.getKey());
+		}
+
 		public boolean isDuplicate(RepositoryEntry re) {
 			boolean duplicate = duplicates.contains(re);
 			if(!duplicate) {
diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumService.java b/src/main/java/org/olat/modules/curriculum/CurriculumService.java
index 1688ae639ce6d37e5186c8dd4d41a37e53750f87..bd61ee50391ec561c59a0ee44df80cca0223a547 100644
--- a/src/main/java/org/olat/modules/curriculum/CurriculumService.java
+++ b/src/main/java/org/olat/modules/curriculum/CurriculumService.java
@@ -31,6 +31,7 @@ import org.olat.core.id.Roles;
 import org.olat.modules.curriculum.model.CurriculumElementInfos;
 import org.olat.modules.curriculum.model.CurriculumElementMembershipChange;
 import org.olat.modules.curriculum.model.CurriculumElementRepositoryEntryViews;
+import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos;
 import org.olat.modules.curriculum.model.CurriculumInfos;
 import org.olat.modules.curriculum.model.CurriculumMember;
 import org.olat.modules.curriculum.model.CurriculumSearchParameters;
@@ -391,5 +392,8 @@ public interface CurriculumService {
 	
 	
 	public List<CurriculumElementRepositoryEntryViews> getCurriculumElements(Identity identity, Roles roles, CurriculumRef curriculum);
+	
+
+	public List<CurriculumElementWebDAVInfos> getCurriculumElementInfosForWebDAV(IdentityRef identity);
 
 }
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java
index 3201368282b8bf7d7802110d6cb850fbff3c4a13..a1722cecf3a47acca3c4ea12fe2070777f8fa160 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java
@@ -342,7 +342,6 @@ public class CurriculumElementDAO {
 				.getResultList();
 	}
 	
-	
 	public List<CurriculumElementMembership> getMembershipInfos(CurriculumRef curriculum, Collection<CurriculumElement> elements, Identity... identities) {
 		StringBuilder sb = new StringBuilder(256);
 		sb.append("select el.key, membership from curriculumelement el")
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java
index e342f4c791a0d1e194e8c5f1c3d7d6923486ebb5..1dbce1248aaffc730cb9bc10c2d2c716b00dc8f0 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java
@@ -28,6 +28,7 @@ import java.util.stream.Collectors;
 
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.QueryBuilder;
 import org.olat.core.id.Identity;
@@ -36,6 +37,7 @@ import org.olat.modules.curriculum.CurriculumElementRef;
 import org.olat.modules.curriculum.CurriculumElementStatus;
 import org.olat.modules.curriculum.CurriculumRef;
 import org.olat.modules.curriculum.CurriculumRoles;
+import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRef;
 import org.olat.repository.RepositoryEntryStatusEnum;
@@ -83,6 +85,39 @@ public class CurriculumRepositoryEntryRelationDAO {
 			.getResultList();
 	}
 	
+	public List<CurriculumElementWebDAVInfos> getCurriculumElementInfosForWebDAV(IdentityRef identity, List<String> roles) {
+		StringBuilder sb = new StringBuilder(256);
+		sb.append("select rel.entry.key, el.key, el.displayName, el.identifier,")
+		  .append(" parentEl.key, parentEl.displayName, parentEl.identifier")
+		  .append(" from curriculumelement as el")
+		  .append(" inner join el.group as bGroup")
+		  .append(" inner join bGroup.members as memberships")
+		  .append(" left join el.parent as parentEl")
+		  .append(" inner join repoentrytogroup as rel on (bGroup.key=rel.group.key)")
+		  .append(" where memberships.identity.key=:identityKey and memberships.role in (:roles)")
+		  .append(" group by rel.entry.key, el.key, el.displayName, el.identifier, parentEl.key, parentEl.displayName, parentEl.identifier");
+		
+		List<Object[]> rawObjects = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Object[].class)
+				.setParameter("identityKey", identity.getKey())
+				.setParameter("roles", roles)
+				.getResultList();
+		List<CurriculumElementWebDAVInfos> infos = new ArrayList<>(rawObjects.size());
+		for(Object[] rawObject:rawObjects) {
+			Long repositoryEntryKey = (Long)rawObject[0];
+			Long curriculumElementKey = (Long)rawObject[1];
+			String curriculumElementDisplayName = (String)rawObject[2];
+			String curriculumElementIdentifier = (String)rawObject[3];
+			Long parentCurriculumElementKey = (Long)rawObject[4];
+			String parentCurriculumElementDisplayName = (String)rawObject[5];
+			String parentCurriculumElementIdentifier = (String)rawObject[6];	
+			infos.add(new CurriculumElementWebDAVInfos(repositoryEntryKey,
+					curriculumElementKey, curriculumElementDisplayName, curriculumElementIdentifier,
+					parentCurriculumElementKey, parentCurriculumElementDisplayName, parentCurriculumElementIdentifier));
+		}
+		return infos;
+	}
+	
 	public List<CurriculumElement> getCurriculumElements(RepositoryEntryRef entry, Identity identity, Collection<CurriculumRoles> roles) {
 		StringBuilder sb = new StringBuilder(256);
 		sb.append("select el from curriculumelement as el")
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
index f1f698b1de36e7bb449eaade7a78693560325318..a6851af33b671dee5fc8b76039462628fc6760cb 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.olat.basesecurity.GroupMembershipInheritance;
+import org.olat.basesecurity.GroupRoles;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.basesecurity.OrganisationRoles;
 import org.olat.basesecurity.manager.GroupDAO;
@@ -56,6 +57,7 @@ import org.olat.modules.curriculum.model.CurriculumElementImpl;
 import org.olat.modules.curriculum.model.CurriculumElementInfos;
 import org.olat.modules.curriculum.model.CurriculumElementMembershipChange;
 import org.olat.modules.curriculum.model.CurriculumElementRepositoryEntryViews;
+import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos;
 import org.olat.modules.curriculum.model.CurriculumInfos;
 import org.olat.modules.curriculum.model.CurriculumMember;
 import org.olat.modules.curriculum.model.CurriculumSearchParameters;
@@ -460,6 +462,15 @@ public class CurriculumServiceImpl implements CurriculumService {
 		return curriculumElementToTaxonomyLevelDao.getCurriculumElements(level);
 	}
 
+	@Override
+	public List<CurriculumElementWebDAVInfos> getCurriculumElementInfosForWebDAV(IdentityRef identity) {
+		List<String> roles = new ArrayList<>();
+		roles.add(GroupRoles.owner.name());
+		roles.add(GroupRoles.coach.name());
+		roles.add(GroupRoles.participant.name());
+		return curriculumRepositoryEntryRelationDao.getCurriculumElementInfosForWebDAV(identity, roles);
+	}
+
 	@Override
 	public List<CurriculumElementRepositoryEntryViews> getCurriculumElements(Identity identity, Roles roles, CurriculumRef curriculum) {
 		if(curriculum == null) return Collections.emptyList();
diff --git a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementWebDAVInfos.java b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementWebDAVInfos.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2d133a2ba1f416d733f3dced344607b6a81bca9
--- /dev/null
+++ b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementWebDAVInfos.java
@@ -0,0 +1,100 @@
+/**
+ * <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.modules.curriculum.model;
+
+/**
+ * 
+ * Initial date: 21 août 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CurriculumElementWebDAVInfos {
+	
+	private final Long repositoryEntryKey;
+	
+	private final Long curriculumElementKey;
+	private final String curriculumElementDisplayName;
+	private final String curriculumElementIdentifier;
+	
+	private final Long parentCurriculumElementKey;
+	private final String parentCurriculumElementDisplayName;
+	private final String parentCurriculumElementIdentifier;
+	
+	public CurriculumElementWebDAVInfos(Long repositoryEntryKey,
+			Long curriculumElementKey, String curriculumElementDisplayName, String curriculumElementIdentifier,
+			Long parentCurriculumElementKey, String parentCurriculumElementDisplayName,String parentCurriculumElementIdentifier) {
+		this.repositoryEntryKey = repositoryEntryKey;
+		this.curriculumElementKey = curriculumElementKey;
+		this.curriculumElementDisplayName = curriculumElementDisplayName;
+		this.curriculumElementIdentifier = curriculumElementIdentifier;
+		this.parentCurriculumElementKey = parentCurriculumElementKey;
+		this.parentCurriculumElementDisplayName = parentCurriculumElementDisplayName;
+		this.parentCurriculumElementIdentifier = parentCurriculumElementIdentifier;
+	}
+
+	public Long getRepositoryEntryKey() {
+		return repositoryEntryKey;
+	}
+
+	public Long getCurriculumElementKey() {
+		return curriculumElementKey;
+	}
+
+	public String getCurriculumElementDisplayName() {
+		return curriculumElementDisplayName;
+	}
+
+	public String getCurriculumElementIdentifier() {
+		return curriculumElementIdentifier;
+	}
+
+	public Long getParentCurriculumElementKey() {
+		return parentCurriculumElementKey;
+	}
+
+	public String getParentCurriculumElementDisplayName() {
+		return parentCurriculumElementDisplayName;
+	}
+
+	public String getParentCurriculumElementIdentifier() {
+		return parentCurriculumElementIdentifier;
+	}
+	
+	@Override
+	public int hashCode() {
+		return (repositoryEntryKey == null ? 7645925 : repositoryEntryKey.hashCode())
+				+ (curriculumElementKey == null ? -4785 : curriculumElementKey.hashCode());
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof CurriculumElementWebDAVInfos) {
+			CurriculumElementWebDAVInfos infos = (CurriculumElementWebDAVInfos)obj;
+			return repositoryEntryKey != null && repositoryEntryKey.equals(infos.repositoryEntryKey)
+					&& curriculumElementKey != null && curriculumElementKey.equals(infos.curriculumElementKey);
+		}
+		return false;
+	}
+	
+	
+}
diff --git a/src/main/java/org/olat/repository/RepositoryManager.java b/src/main/java/org/olat/repository/RepositoryManager.java
index 1f45d67cae67f3d4e6952b5623acf758b54f2b7c..dc0cfaee3d9ab035cae95c5cbd9961a3162f904c 100644
--- a/src/main/java/org/olat/repository/RepositoryManager.java
+++ b/src/main/java/org/olat/repository/RepositoryManager.java
@@ -888,14 +888,14 @@ public class RepositoryManager {
 	 * @param limitType
 	 * @return Results
 	 */
-	public List<RepositoryEntry> queryByOwner(IdentityRef identity, String... limitTypes) {
+	public List<RepositoryEntry> queryByOwner(IdentityRef identity, boolean follow, String... limitTypes) {
 		if (identity == null) throw new AssertException("identity can not be null!");
 		QueryBuilder sb = new QueryBuilder(400);
 		sb.append("select v from repositoryentry v")
 		  .append(" inner join fetch v.olatResource as res")
 		  .append(" inner join fetch v.statistics as statistics")
 		  .append(" left join fetch v.lifecycle as lifecycle")
-		  .append(" inner join v.groups as relGroup on relGroup.defaultGroup=true")
+		  .append(" inner join v.groups as relGroup ").append(" on relGroup.defaultGroup=true", !follow)
 		  .append(" inner join relGroup.group as baseGroup")
 		  .append(" inner join baseGroup.members as membership on membership.role='").append(GroupRoles.owner.name()).append("'")
 		  .append(" where membership.identity.key=:identityKey and v.status ").in(RepositoryEntryStatusEnum.preparationToClosed());
diff --git a/src/main/java/org/olat/repository/controllers/RepositorySearchController.java b/src/main/java/org/olat/repository/controllers/RepositorySearchController.java
index 62b77cb68c4316732ae02c794cd5c08d3ee2dcb7..55d9e746fb9faf8b2ecbe710d3a4a83d1699dc66 100644
--- a/src/main/java/org/olat/repository/controllers/RepositorySearchController.java
+++ b/src/main/java/org/olat/repository/controllers/RepositorySearchController.java
@@ -339,7 +339,7 @@ public class RepositorySearchController extends BasicController implements Activ
 	
 	private void doSearchByOwnerLimitTypeInternal(Identity owner, String[] limitTypes, boolean updateFilters) {
 		searchType = SearchType.byOwner;
-		List<RepositoryEntry> entries = repositoryManager.queryByOwner(owner, limitTypes);
+		List<RepositoryEntry> entries = repositoryManager.queryByOwner(owner, true, limitTypes);
 		filterRepositoryEntries(entries);
 		if(updateFilters) {
 			updateFilters(entries, owner);
diff --git a/src/main/java/org/olat/repository/manager/RepositoryUserDataManager.java b/src/main/java/org/olat/repository/manager/RepositoryUserDataManager.java
index 439422587b678b422527f93fbf0b2d54de2fb98d..f41fd62e17a635d493221197f18938e9112e6f39 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryUserDataManager.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryUserDataManager.java
@@ -85,7 +85,7 @@ public class RepositoryUserDataManager implements UserDataDeletable, UserDataExp
 	public void deleteUserData(Identity identity, String newDeletedUserName) {
 		// Remove as owner
 		Identity adminIdentity = deletionModule.getAdminUserIdentity();
-		List<RepositoryEntry> ownedRepoEntries = repositoryManager.queryByOwner(identity);
+		List<RepositoryEntry> ownedRepoEntries = repositoryManager.queryByOwner(identity, false);
 		for (RepositoryEntry repositoryEntry: ownedRepoEntries) {
 			repositoryService.removeRole(identity, repositoryEntry, GroupRoles.owner.name());
 			if (adminIdentity != null && repositoryService.countMembers(repositoryEntry, GroupRoles.owner.name()) == 0) {
diff --git a/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java b/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java
index e228c0c6230e141a1e20036df100308df2931e52..97bbc2c98b9614e4488f72fd35e17f695d247508 100644
--- a/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java
+++ b/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java
@@ -256,7 +256,7 @@ public class RepositoryEntriesWebService {
 			Roles roles = getRoles(httpRequest);
 			
 			if(myEntries) {
-				List<RepositoryEntry> lstRepos = rm.queryByOwner(identity, restrictedType ? new String[] {type} : null);
+				List<RepositoryEntry> lstRepos = rm.queryByOwner(identity, true, restrictedType ? new String[] {type} : null);
 				boolean restrictedName = !name.equals("*");
 				boolean restrictedAuthor = !author.equals("*");
 				if(restrictedName || restrictedAuthor) {
diff --git a/src/test/java/org/olat/repository/RepositoryManagerTest.java b/src/test/java/org/olat/repository/RepositoryManagerTest.java
index c0ca1d2def53557e54f2921bca1c3215402eae47..7725cc2ea707acccf0cdcdcad9f832040444712c 100644
--- a/src/test/java/org/olat/repository/RepositoryManagerTest.java
+++ b/src/test/java/org/olat/repository/RepositoryManagerTest.java
@@ -234,12 +234,12 @@ public class RepositoryManagerTest extends OlatTestCase {
 		repositoryEntryRelationDao.addRole(participant, re, GroupRoles.participant.name());
 		dbInstance.commitAndCloseSession();
 		
-		List<RepositoryEntry> entries = repositoryManager.queryByOwner(owner);
+		List<RepositoryEntry> entries = repositoryManager.queryByOwner(owner, true);
 		Assert.assertNotNull(entries);
 		Assert.assertEquals(1, entries.size());
 		Assert.assertTrue(entries.contains(re));
 		
-		List<RepositoryEntry> partEntries = repositoryManager.queryByOwner(participant);
+		List<RepositoryEntry> partEntries = repositoryManager.queryByOwner(participant, true);
 		Assert.assertNotNull(partEntries);
 		Assert.assertEquals(0, partEntries.size());
 	}
@@ -253,7 +253,7 @@ public class RepositoryManagerTest extends OlatTestCase {
 		repositoryEntryRelationDao.addRole(id, re, GroupRoles.owner.name());
 		dbInstance.commitAndCloseSession();
 		
-		List<RepositoryEntry> entries = repositoryManager.queryByOwner(id);
+		List<RepositoryEntry> entries = repositoryManager.queryByOwner(id, true);
 		Assert.assertNotNull(entries);
 		Assert.assertEquals(1, entries.size());
 		Assert.assertTrue(entries.contains(re));