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 a80d382a4df557e4f191200184ab87ff75984edb..8d2065831532f7724343432cc50f9a57f7a37f43 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 @@ -70,7 +70,9 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff { private boolean prependCourseReferenceToTitle; @Value("${webdav.basic.authentication.black.list}") private String basicAuthenticationBlackList; - + @Value("${webdav.user.agent.black.list}") + private String userAgentBlackList; + @Value("${webdav.learners.bookmarks.enabled:true}") private boolean enableLearnersBookmarksCourse; /** @@ -233,6 +235,21 @@ public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff { this.basicAuthenticationBlackList = basicAuthenticationBlackList; } + public String[] getUserAgentBlackListArray() { + if(StringHelper.containsNonWhitespace(userAgentBlackList)) { + return userAgentBlackList.split("[,]"); + } + return new String[0]; + } + + public String getUserAgentBlackList() { + return userAgentBlackList; + } + + public void setUserAgentBlackList(String userAgentBlackList) { + this.userAgentBlackList = userAgentBlackList; + } + /** * Return an unmodifiable map * @return diff --git a/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java b/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java index 03a7820cee2e0e5da9c93a8256d30063851ad4ba..cad3154c7b23d35d171de702e3dd845db8604216 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java +++ b/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java @@ -54,9 +54,11 @@ import org.olat.core.commons.services.webdav.WebDAVDispatcher; import org.olat.core.commons.services.webdav.WebDAVManager; import org.olat.core.commons.services.webdav.WebDAVModule; import org.olat.core.dispatcher.Dispatcher; +import org.olat.core.gui.media.ServletUtil; import org.olat.core.helpers.Settings; import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; import org.olat.core.util.vfs.QuotaExceededException; import org.olat.core.util.vfs.VFSItem; @@ -273,7 +275,7 @@ public class WebDAVDispatcherImpl throws ServletException, IOException { if (webDAVManager == null) { resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR); - } else if(webDAVModule == null || !webDAVModule.isEnabled()) { + } else if(webDAVModule == null || !webDAVModule.isEnabled() || isUserAgentExcluded(req)) { resp.setStatus(WebdavStatus.SC_FORBIDDEN); } else if (webDAVManager.handleAuthentication(req, resp)) { webdavService(req, resp); @@ -281,6 +283,21 @@ public class WebDAVDispatcherImpl //the method handleAuthentication will send the challenges for authentication } } + + private boolean isUserAgentExcluded(HttpServletRequest req) { + String userAgent = ServletUtil.getUserAgent(req); + if(!StringHelper.containsNonWhitespace(userAgent)) { + userAgent = ""; + } + String[] blackList = webDAVModule.getUserAgentBlackListArray(); + for(String blackListedAgent:blackList) { + if((blackListedAgent.length() < 2 && userAgent.equalsIgnoreCase(blackListedAgent)) + || (blackListedAgent.length() >= 2 && userAgent.contains(blackListedAgent))) { + return true; + } + } + return false; + } /** * Handles the special WebDAV methods. 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 457f814f10773b80f20a3804872de8a77ee6c00b..37ad1d594cec3b2cdfd34262ce0af392ac4611c9 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 @@ -19,16 +19,20 @@ */ package org.olat.core.commons.services.webdav.ui; -import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.webdav.WebDAVModule; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.SpacerElement; +import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.springframework.beans.factory.annotation.Autowired; /** * @@ -39,6 +43,8 @@ public class WebDAVAdminController extends FormBasicController { private static final String[] onKeys = new String[]{"xx"}; + private TextElement excludeUserAgentsClientsEl; + private MultipleSelectionElement excludeClientsEl; private MultipleSelectionElement enableModuleEl; private MultipleSelectionElement enableLinkEl; private MultipleSelectionElement enableDigestEl; @@ -48,13 +54,17 @@ public class WebDAVAdminController extends FormBasicController { private MultipleSelectionElement learnersAsParticipantEl; private MultipleSelectionElement learnersBookmarkEl; private MultipleSelectionElement prependReferenceEl; + private SpacerElement spacer1; + private SpacerElement spacer2; - private final WebDAVModule webDAVModule; + + @Autowired + private WebDAVModule webDAVModule; public WebDAVAdminController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl); - webDAVModule = CoreSpringFactory.getImpl(WebDAVModule.class); initForm(ureq); + updateEnabledDisabled(); } @Override @@ -64,56 +74,51 @@ public class WebDAVAdminController extends FormBasicController { setFormDescription("admin.webdav.description"); setFormContextHelp("WebDAV"); - boolean enabled = webDAVModule.isEnabled(); String[] values = new String[] { getTranslator().translate("webdav.on") }; enableModuleEl = uifactory.addCheckboxesHorizontal("webdavModule", "webdav.module", formLayout, onKeys, values); - enableModuleEl.select("xx", enabled); enableModuleEl.addActionListener(FormEvent.ONCHANGE); + enableModuleEl.select("xx", enabled); 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, onKeys, values); enableDigestEl.select("xx", webDAVModule.isDigestAuthenticationEnabled()); - enableDigestEl.addActionListener(FormEvent.ONCHANGE); - enableDigestEl.setEnabled(enabled); + + String excludedUserAgents = webDAVModule.getUserAgentBlackList(); + excludeClientsEl = uifactory.addCheckboxesHorizontal("webdavExclusion", "webdav.client.exclusion", formLayout, onKeys, values); + excludeClientsEl.select("xx", StringHelper.containsNonWhitespace(excludedUserAgents)); + excludeClientsEl.addActionListener(FormEvent.ONCHANGE); + + excludeUserAgentsClientsEl = uifactory.addTextElement("webdav.user.agent.exclusion", 4096, excludedUserAgents, formLayout); + excludeUserAgentsClientsEl.setVisible(excludeClientsEl.isAtLeastSelected(1)); - uifactory.addSpacerElement("spacer1", formLayout, false); + spacer1 = uifactory.addSpacerElement("spacer1", formLayout, false); enableTermsFoldersEl = uifactory.addCheckboxesHorizontal("webdavTermsFolders", "webdav.termsfolders", formLayout, onKeys, values); enableTermsFoldersEl.select("xx", webDAVModule.isTermsFoldersEnabled()); - enableTermsFoldersEl.addActionListener(FormEvent.ONCHANGE); - enableTermsFoldersEl.setEnabled(enabled); enableCurriculumElementFoldersEl = uifactory.addCheckboxesHorizontal("webdavCurriculumsElementsFolders", "webdav.curriculumelementsfolders", formLayout, onKeys, values); enableCurriculumElementFoldersEl.select("xx", webDAVModule.isCurriculumElementFoldersEnabled()); - enableCurriculumElementFoldersEl.addActionListener(FormEvent.ONCHANGE); - enableCurriculumElementFoldersEl.setEnabled(enabled); enableManagedFoldersEl = uifactory.addCheckboxesHorizontal("webdavManagedFolders", "webdav.managedfolders", formLayout, onKeys, values); enableManagedFoldersEl.select("xx", webDAVModule.isManagedFoldersEnabled()); - enableManagedFoldersEl.addActionListener(FormEvent.ONCHANGE); - enableManagedFoldersEl.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); + + spacer2 = uifactory.addSpacerElement("spacer2", formLayout, false); 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, onKeys, values); learnersBookmarkEl.select("xx", webDAVModule.isEnableLearnersBookmarksCourse()); - learnersBookmarkEl.addActionListener(FormEvent.ONCHANGE); - learnersBookmarkEl.setEnabled(enabled); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("save", buttonsCont); } @Override @@ -126,41 +131,44 @@ public class WebDAVAdminController extends FormBasicController { if(source == enableModuleEl) { boolean enabled = enableModuleEl.isAtLeastSelected(1); webDAVModule.setEnabled(enabled); - enableLinkEl.setEnabled(enabled); - enableDigestEl.setEnabled(enabled); - enableTermsFoldersEl.setEnabled(enabled); - learnersAsParticipantEl.setEnabled(enabled); - learnersBookmarkEl.setEnabled(enabled); - } else if(source == enableLinkEl) { - boolean enabled = enableLinkEl.isAtLeastSelected(1); - webDAVModule.setLinkEnabled(enabled); - } else if(source == enableDigestEl) { - boolean enabled = enableDigestEl.isAtLeastSelected(1); - webDAVModule.setDigestAuthenticationEnabled(enabled); - } 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); - } else if(source == learnersBookmarkEl) { - boolean enabled = learnersBookmarkEl.isAtLeastSelected(1); - webDAVModule.setEnableLearnersBookmarksCourse(enabled); - } else if(source == prependReferenceEl) { - boolean enabled = prependReferenceEl.isAtLeastSelected(1); - webDAVModule.setPrependCourseReferenceToTitle(enabled); - } else if(source == enableManagedFoldersEl) { - boolean enabled = enableManagedFoldersEl.isAtLeastSelected(1); - webDAVModule.setManagedFoldersEnabled(enabled); + updateEnabledDisabled(); + } else if(source == excludeClientsEl) { + excludeUserAgentsClientsEl.setVisible(excludeClientsEl.isAtLeastSelected(1)); } super.formInnerEvent(ureq, source, event); } + + private void updateEnabledDisabled() { + boolean enabled = enableModuleEl.isAtLeastSelected(1); + + enableLinkEl.setVisible(enabled); + enableDigestEl.setVisible(enabled); + enableTermsFoldersEl.setVisible(enabled); + learnersAsParticipantEl.setVisible(enabled); + learnersBookmarkEl.setVisible(enabled); + enableCurriculumElementFoldersEl.setVisible(enabled); + enableManagedFoldersEl.setVisible(enabled); + prependReferenceEl.setVisible(enabled); + excludeClientsEl.setVisible(enabled); + excludeUserAgentsClientsEl.setVisible(enabled && excludeClientsEl.isAtLeastSelected(1)); + spacer1.setVisible(enabled); + spacer2.setVisible(enabled); + } @Override protected void formOK(UserRequest ureq) { - // + webDAVModule.setLinkEnabled(enableLinkEl.isAtLeastSelected(1)); + webDAVModule.setDigestAuthenticationEnabled(enableDigestEl.isAtLeastSelected(1)); + webDAVModule.setTermsFoldersEnabled(enableTermsFoldersEl.isAtLeastSelected(1)); + webDAVModule.setCurriculumElementFoldersEnabled(enableCurriculumElementFoldersEl.isAtLeastSelected(1)); + webDAVModule.setEnableLearnersParticipatingCourses(learnersAsParticipantEl.isAtLeastSelected(1)); + webDAVModule.setEnableLearnersBookmarksCourse(learnersBookmarkEl.isAtLeastSelected(1)); + webDAVModule.setPrependCourseReferenceToTitle(prependReferenceEl.isAtLeastSelected(1)); + webDAVModule.setManagedFoldersEnabled(enableManagedFoldersEl.isAtLeastSelected(1)); + if(excludeClientsEl.isAtLeastSelected(1)) { + webDAVModule.setUserAgentBlackList(excludeUserAgentsClientsEl.getValue()); + } else { + webDAVModule.setUserAgentBlackList(null); + } } } 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 e081425ac73199d655d8f42795193eea0db1895b..97cd86527ad9d4c263a812229ad028d1b7a1503e 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.client.exclusion=WebDAV Client Verbot webdav.curriculumelementsfolders=Kurse nach Curriculumelementen gruppieren webdav.digest=Digest Authentication bei HTTP Zugang verwenden webdav.for.learners.bookmarks=Zugriff f\u00FCr Studenten / Betreuer Favoriten @@ -13,3 +14,4 @@ webdav.module=WebDAV Zugang webdav.on=ein webdav.prepend.reference=Kennzeichen dem Titel voranstellen webdav.termsfolders=Kurse nach Semesterdaten gruppieren +webdav.user.agent.exclusion=Liste von User-Agent (Komma als Trenzeichen) 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 a4a726fe0211c2ab0ffc5930452415130b39a804..28fe7f470a79cd039b51795fc3d4f1139b2d47f1 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.client.exclusion=WebDAV Client exclusion 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 @@ -13,3 +14,4 @@ webdav.module=WebDAV access webdav.on=enabled webdav.prepend.reference=Prepend external course reference to title webdav.termsfolders=Group courses by semester terms +webdav.user.agent.exclusion=List of User-Agents (comma as separator) diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 7b34f89ff55854797be1e3db7bc5dd7240191ff1..7a27ea4023469cbf61093025dd48808c2879a228 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -563,6 +563,8 @@ auth.digest.enabled=true webdav.termsfolders.enabled=true # User agents for which the basic authentication should never be proposed webdav.basic.authentication.black.list=Microsoft Office Excel,Microsoft Excel,Microsoft-WebDAV-MiniRedir +# User agents which don't play nice +webdav.user.agent.black.list=- ######################################################################## # Image and PDF scale/thumbnail options