You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2023/12/21 05:06:05 UTC

(openmeetings) 29/29: [OPENMEETINGS-2756] the build seems to be fixed

This is an automated email from the ASF dual-hosted git repository.

solomax pushed a commit to branch jakarta-spring-6
in repository https://gitbox.apache.org/repos/asf/openmeetings.git

commit b7d01a1ed9233718932c53753a5114f4977769bd
Author: Maxim Solodovnik <so...@apache.org>
AuthorDate: Thu Dec 21 12:05:23 2023 +0700

    [OPENMEETINGS-2756] the build seems to be fixed
---
 .../src/main/java/module-info.java                 |    3 +-
 openmeetings-service/pom.xml                       |    8 +-
 .../src/main/java/module-info.java                 |    9 +-
 .../jackrabbit/webdav/AbstractLocatorFactory.java  |  403 +++++
 .../webdav/ContentCodingAwareRequest.java          |   39 +
 .../apache/jackrabbit/webdav/DavCompliance.java    |   72 +
 .../org/apache/jackrabbit/webdav/DavConstants.java |  154 ++
 .../org/apache/jackrabbit/webdav/DavException.java |  175 +++
 .../jackrabbit/webdav/DavLocatorFactory.java       |   72 +
 .../org/apache/jackrabbit/webdav/DavMethods.java   |  410 ++++++
 .../org/apache/jackrabbit/webdav/DavResource.java  |  334 +++++
 .../jackrabbit/webdav/DavResourceFactory.java      |   46 +
 .../jackrabbit/webdav/DavResourceIterator.java     |   39 +
 .../jackrabbit/webdav/DavResourceIteratorImpl.java |   85 ++
 .../jackrabbit/webdav/DavResourceLocator.java      |  115 ++
 .../jackrabbit/webdav/DavServletRequest.java       |  199 +++
 .../jackrabbit/webdav/DavServletResponse.java      |  149 ++
 .../org/apache/jackrabbit/webdav/DavSession.java   |   62 +
 .../jackrabbit/webdav/DavSessionProvider.java      |   48 +
 .../org/apache/jackrabbit/webdav/MultiStatus.java  |  193 +++
 .../jackrabbit/webdav/MultiStatusResponse.java     |  486 ++++++
 .../java/org/apache/jackrabbit/webdav/Status.java  |  125 ++
 .../apache/jackrabbit/webdav/WebdavRequest.java    |   36 +
 .../jackrabbit/webdav/WebdavRequestContext.java    |   30 +
 .../jackrabbit/webdav/WebdavRequestImpl.java       | 1324 +++++++++++++++++
 .../apache/jackrabbit/webdav/WebdavResponse.java   |   42 +
 .../jackrabbit/webdav/WebdavResponseImpl.java      |  392 +++++
 .../jackrabbit/webdav/bind/BindConstants.java      |   52 +
 .../apache/jackrabbit/webdav/bind/BindInfo.java    |  108 ++
 .../jackrabbit/webdav/bind/BindServletRequest.java |   65 +
 .../jackrabbit/webdav/bind/BindableResource.java   |   50 +
 .../jackrabbit/webdav/bind/ParentElement.java      |  111 ++
 .../apache/jackrabbit/webdav/bind/ParentSet.java   |   45 +
 .../apache/jackrabbit/webdav/bind/RebindInfo.java  |  108 ++
 .../apache/jackrabbit/webdav/bind/UnbindInfo.java  |   90 ++
 .../jackrabbit/webdav/bind/package-info.java       |   18 +
 .../webdav/client/methods/BaseDavRequest.java      |  219 +++
 .../jackrabbit/webdav/client/methods/HttpBind.java |   54 +
 .../webdav/client/methods/HttpCheckin.java         |   51 +
 .../webdav/client/methods/HttpCheckout.java        |   51 +
 .../jackrabbit/webdav/client/methods/HttpCopy.java |   59 +
 .../webdav/client/methods/HttpDelete.java          |   43 +
 .../webdav/client/methods/HttpLabel.java           |   57 +
 .../jackrabbit/webdav/client/methods/HttpLock.java |  107 ++
 .../webdav/client/methods/HttpMerge.java           |   55 +
 .../webdav/client/methods/HttpMkcol.java           |   51 +
 .../webdav/client/methods/HttpMkworkspace.java     |   51 +
 .../jackrabbit/webdav/client/methods/HttpMove.java |   56 +
 .../webdav/client/methods/HttpOptions.java         |   79 +
 .../webdav/client/methods/HttpOrderpatch.java      |   53 +
 .../jackrabbit/webdav/client/methods/HttpPoll.java |   58 +
 .../webdav/client/methods/HttpPropfind.java        |   77 +
 .../webdav/client/methods/HttpProppatch.java       |  104 ++
 .../webdav/client/methods/HttpRebind.java          |   54 +
 .../webdav/client/methods/HttpReport.java          |   66 +
 .../webdav/client/methods/HttpSearch.java          |   54 +
 .../webdav/client/methods/HttpSubscribe.java       |   88 ++
 .../webdav/client/methods/HttpUnbind.java          |   54 +
 .../webdav/client/methods/HttpUnlock.java          |   55 +
 .../webdav/client/methods/HttpUnsubscribe.java     |   53 +
 .../webdav/client/methods/HttpUpdate.java          |   54 +
 .../webdav/client/methods/HttpVersionControl.java  |   51 +
 .../webdav/client/methods/XmlEntity.java           |   68 +
 .../webdav/client/methods/package-info.java        |   31 +
 .../jackrabbit/webdav/header/CodedUrlHeader.java   |  113 ++
 .../jackrabbit/webdav/header/DepthHeader.java      |  128 ++
 .../jackrabbit/webdav/header/FieldValueParser.java |   55 +
 .../apache/jackrabbit/webdav/header/Header.java    |   27 +
 .../apache/jackrabbit/webdav/header/IfHeader.java  |  905 ++++++++++++
 .../jackrabbit/webdav/header/LabelHeader.java      |   61 +
 .../jackrabbit/webdav/header/OverwriteHeader.java  |   75 +
 .../webdav/header/PollTimeoutHeader.java           |   52 +
 .../jackrabbit/webdav/header/TimeoutHeader.java    |  104 ++
 .../jackrabbit/webdav/header/package-info.java     |   18 +
 .../apache/jackrabbit/webdav/io/InputContext.java  |   78 +
 .../jackrabbit/webdav/io/InputContextImpl.java     |   98 ++
 .../apache/jackrabbit/webdav/io/OutputContext.java |   82 ++
 .../jackrabbit/webdav/io/OutputContextImpl.java    |   88 ++
 .../apache/jackrabbit/webdav/io/package-info.java  |   18 +
 .../jackrabbit/webdav/lock/AbstractActiveLock.java |   86 ++
 .../jackrabbit/webdav/lock/AbstractLockEntry.java  |   47 +
 .../apache/jackrabbit/webdav/lock/ActiveLock.java  |  124 ++
 .../jackrabbit/webdav/lock/DefaultActiveLock.java  |  147 ++
 .../jackrabbit/webdav/lock/LockDiscovery.java      |  233 +++
 .../apache/jackrabbit/webdav/lock/LockEntry.java   |   39 +
 .../apache/jackrabbit/webdav/lock/LockInfo.java    |  237 +++
 .../apache/jackrabbit/webdav/lock/LockManager.java |   87 ++
 .../org/apache/jackrabbit/webdav/lock/Scope.java   |  122 ++
 .../jackrabbit/webdav/lock/SimpleLockManager.java  |  233 +++
 .../jackrabbit/webdav/lock/SupportedLock.java      |  166 +++
 .../org/apache/jackrabbit/webdav/lock/Type.java    |  129 ++
 .../jackrabbit/webdav/lock/package-info.java       |   18 +
 .../webdav/observation/DefaultEventType.java       |  148 ++
 .../jackrabbit/webdav/observation/EventBundle.java |   29 +
 .../webdav/observation/EventDiscovery.java         |  121 ++
 .../jackrabbit/webdav/observation/EventType.java   |   30 +
 .../jackrabbit/webdav/observation/Filter.java      |   74 +
 .../webdav/observation/ObservationConstants.java   |  101 ++
 .../observation/ObservationDavServletRequest.java  |   54 +
 .../observation/ObservationDavServletResponse.java |   45 +
 .../webdav/observation/ObservationResource.java    |   72 +
 .../webdav/observation/Subscription.java           |   49 +
 .../webdav/observation/SubscriptionDiscovery.java  |  139 ++
 .../webdav/observation/SubscriptionInfo.java       |  242 +++
 .../webdav/observation/SubscriptionManager.java    |   69 +
 .../webdav/observation/package-info.java           |   18 +
 .../jackrabbit/webdav/ordering/OrderPatch.java     |  212 +++
 .../webdav/ordering/OrderingConstants.java         |  106 ++
 .../webdav/ordering/OrderingDavServletRequest.java |   55 +
 .../webdav/ordering/OrderingResource.java          |   47 +
 .../jackrabbit/webdav/ordering/OrderingType.java   |   52 +
 .../jackrabbit/webdav/ordering/Position.java       |  164 +++
 .../jackrabbit/webdav/ordering/package-info.java   |   18 +
 .../org/apache/jackrabbit/webdav/package-info.java |   18 +
 .../webdav/property/AbstractDavProperty.java       |  163 ++
 .../jackrabbit/webdav/property/DavProperty.java    |   71 +
 .../webdav/property/DavPropertyIterator.java       |   34 +
 .../webdav/property/DavPropertyName.java           |  206 +++
 .../webdav/property/DavPropertyNameIterator.java   |   28 +
 .../webdav/property/DavPropertyNameSet.java        |  203 +++
 .../jackrabbit/webdav/property/DavPropertySet.java |  300 ++++
 .../webdav/property/DefaultDavProperty.java        |  144 ++
 .../jackrabbit/webdav/property/HrefProperty.java   |  159 ++
 .../jackrabbit/webdav/property/PropContainer.java  |  120 ++
 .../jackrabbit/webdav/property/PropEntry.java      |   25 +
 .../jackrabbit/webdav/property/PropfindInfo.java   |   84 ++
 .../jackrabbit/webdav/property/ProppatchInfo.java  |  128 ++
 .../jackrabbit/webdav/property/ResourceType.java   |  205 +++
 .../jackrabbit/webdav/property/package-info.java   |   18 +
 .../jackrabbit/webdav/search/QueryGrammerSet.java  |  144 ++
 .../jackrabbit/webdav/search/SearchConstants.java  |   91 ++
 .../jackrabbit/webdav/search/SearchInfo.java       |  271 ++++
 .../jackrabbit/webdav/search/SearchResource.java   |   55 +
 .../jackrabbit/webdav/search/package-info.java     |   18 +
 .../jackrabbit/webdav/security/AclProperty.java    |  262 ++++
 .../jackrabbit/webdav/security/AclResource.java    |   70 +
 .../webdav/security/AclRestrictionsProperty.java   |  107 ++
 .../security/CurrentUserPrivilegeSetProperty.java  |   90 ++
 .../jackrabbit/webdav/security/Principal.java      |  189 +++
 .../jackrabbit/webdav/security/Privilege.java      |  204 +++
 .../webdav/security/SecurityConstants.java         |  110 ++
 .../webdav/security/SupportedPrivilege.java        |  139 ++
 .../security/SupportedPrivilegeSetProperty.java    |   95 ++
 .../jackrabbit/webdav/security/package-info.java   |   18 +
 .../security/report/AbstractSecurityReport.java    |   82 ++
 .../webdav/security/report/AclPrincipalReport.java |   96 ++
 .../security/report/PrincipalMatchReport.java      |  115 ++
 .../security/report/PrincipalSearchReport.java     |  184 +++
 .../security/report/SearchablePropertyReport.java  |  204 +++
 .../webdav/security/report/package-info.java       |   18 +
 .../webdav/server/AbstractWebdavServlet.java       | 1557 ++++++++++++++++++++
 .../webdav/server/WebdavRequestContextHolder.java  |   46 +
 .../webdav/server/WebdavRequestContextImpl.java    |   35 +
 .../jackrabbit/webdav/server/package-info.java     |   18 +
 .../webdav/transaction/TransactionConstants.java   |  125 ++
 .../transaction/TransactionDavServletRequest.java  |   51 +
 .../webdav/transaction/TransactionInfo.java        |  105 ++
 .../webdav/transaction/TransactionResource.java    |   59 +
 .../webdav/transaction/TxActiveLock.java           |   93 ++
 .../jackrabbit/webdav/transaction/TxLockEntry.java |   72 +
 .../webdav/transaction/TxLockManager.java          |   65 +
 .../webdav/transaction/package-info.java           |   18 +
 .../apache/jackrabbit/webdav/util/CSRFUtil.java    |  168 +++
 .../apache/jackrabbit/webdav/util/EncodeUtil.java  |  220 +++
 .../jackrabbit/webdav/util/HttpDateFormat.java     |   64 +
 .../webdav/util/HttpDateTimeFormatter.java         |  152 ++
 .../webdav/util/LinkHeaderFieldParser.java         |  197 +++
 .../jackrabbit/webdav/util/package-info.java       |   18 +
 .../webdav/version/ActivityResource.java           |   98 ++
 .../webdav/version/BaselineResource.java           |   81 +
 .../jackrabbit/webdav/version/DeltaVConstants.java |  374 +++++
 .../jackrabbit/webdav/version/DeltaVResource.java  |  111 ++
 .../webdav/version/DeltaVServletRequest.java       |   84 ++
 .../jackrabbit/webdav/version/LabelInfo.java       |  188 +++
 .../webdav/version/LabelSetProperty.java           |   63 +
 .../jackrabbit/webdav/version/MergeInfo.java       |  182 +++
 .../jackrabbit/webdav/version/OptionsInfo.java     |  126 ++
 .../jackrabbit/webdav/version/OptionsResponse.java |  144 ++
 .../webdav/version/SupportedMethodSetProperty.java |   63 +
 .../jackrabbit/webdav/version/UpdateInfo.java      |  243 +++
 .../webdav/version/VersionControlledResource.java  |  363 +++++
 .../webdav/version/VersionHistoryResource.java     |   73 +
 .../jackrabbit/webdav/version/VersionResource.java |  213 +++
 .../webdav/version/VersionableResource.java        |   64 +
 .../webdav/version/WorkspaceResource.java          |   94 ++
 .../jackrabbit/webdav/version/package-info.java    |   18 +
 .../webdav/version/report/AbstractReport.java      |   59 +
 .../version/report/CompareBaselineReport.java      |  188 +++
 .../version/report/ExpandPropertyReport.java       |  266 ++++
 .../report/LatestActivityVersionReport.java        |  151 ++
 .../version/report/LocateByHistoryReport.java      |  175 +++
 .../jackrabbit/webdav/version/report/Report.java   |   62 +
 .../webdav/version/report/ReportInfo.java          |  263 ++++
 .../webdav/version/report/ReportType.java          |  190 +++
 .../version/report/SupportedReportSetProperty.java |  119 ++
 .../webdav/version/report/VersionTreeReport.java   |  187 +++
 .../webdav/version/report/package-info.java        |   18 +
 .../webdav/xml/DavDocumentBuilderFactory.java      |   87 ++
 .../org/apache/jackrabbit/webdav/xml/DomUtil.java  |  839 +++++++++++
 .../jackrabbit/webdav/xml/ElementIterator.java     |  170 +++
 .../apache/jackrabbit/webdav/xml/Namespace.java    |   97 ++
 .../apache/jackrabbit/webdav/xml/ResultHelper.java |  458 ++++++
 .../jackrabbit/webdav/xml/XmlSerializable.java     |   38 +
 .../apache/jackrabbit/webdav/xml/package-info.java |   18 +
 .../apache/jackrabbit/webdav/statuscode.properties |   62 +
 openmeetings-util/src/main/java/module-info.java   |    4 +-
 openmeetings-web/src/main/java/module-info.java    |    9 +-
 .../org/apache/openmeetings/ldap/TestLdap.java     |    2 -
 pom.xml                                            |   20 +-
 209 files changed, 26536 insertions(+), 24 deletions(-)

diff --git a/openmeetings-install/src/main/java/module-info.java b/openmeetings-install/src/main/java/module-info.java
index e7aa2a2c2..2ee926d43 100644
--- a/openmeetings-install/src/main/java/module-info.java
+++ b/openmeetings-install/src/main/java/module-info.java
@@ -24,8 +24,10 @@ module org.apache.openmeetings.install {
 
 	requires com.github.openjson;
 
+	requires org.apache.commons.cli;
 	requires org.apache.commons.io;
 	requires org.apache.commons.lang3;
+	requires org.apache.commons.text;
 
 	requires org.apache.openjpa;
 
@@ -45,7 +47,6 @@ module org.apache.openmeetings.install {
 	requires spring.web;
 
 	requires java.desktop;
-	requires commons.cli;
 	requires quartz;
 	requires xstream;
 
diff --git a/openmeetings-service/pom.xml b/openmeetings-service/pom.xml
index d3524fab7..4384c2e72 100644
--- a/openmeetings-service/pom.xml
+++ b/openmeetings-service/pom.xml
@@ -53,9 +53,9 @@
 			<groupId>com.github.caldav4j</groupId>
 			<artifactId>caldav4j</artifactId>
 		</dependency>
-		<dependency>
+		<!--dependency> FIXME TODO have to be placed back as soon as `jackrabbit.webdav` will be jackarta compatible
 			<groupId>org.apache.jackrabbit</groupId>
-			<artifactId>jackrabbit-webdav-jakarta</artifactId>
-		</dependency>
-</dependencies>
+			<artifactId>jackrabbit-webdav</artifactId>
+		</dependency-->
+	</dependencies>
 </project>
diff --git a/openmeetings-service/src/main/java/module-info.java b/openmeetings-service/src/main/java/module-info.java
index 16b3d8aba..e2e2ededb 100644
--- a/openmeetings-service/src/main/java/module-info.java
+++ b/openmeetings-service/src/main/java/module-info.java
@@ -26,7 +26,14 @@ module org.apache.openmeetings.service {
 	exports org.apache.openmeetings.service.room;
 	exports org.apache.openmeetings.service.scheduler;
 
+	//FIXME TODO temporary
+	exports org.apache.jackrabbit.webdav;
+	exports org.apache.jackrabbit.webdav.xml;
+	exports org.apache.jackrabbit.webdav.property;
+	exports org.apache.jackrabbit.webdav.client.methods;
+
 	requires org.apache.commons.lang3;
+	requires org.apache.commons.text;
 
 	requires transitive org.apache.openmeetings.db;
 	requires org.apache.openmeetings.core;
@@ -45,7 +52,7 @@ module org.apache.openmeetings.service {
 
 	requires org.apache.httpcomponents.httpcore;
 	requires org.apache.httpcomponents.httpclient;
-	requires jackrabbit.webdav.jakarta;
+	//requires jackrabbit.webdav; FIXME TODO have to be placed back as soon as `jackrabbit.webdav` will be jackarta compatible
 	requires caldav4j;
 	requires java.xml;
 	requires org.mnode.ical4j.core;
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java
new file mode 100644
index 000000000..36b0a68e1
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.util.EncodeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code AbstractLocatorFactory} is an implementation of the DavLocatorFactory
+ * interface that defines how a given URI is split to workspace path and
+ * resource path and how it's implementation of {@code DavResourceLocator}
+ * builds the href. In contrast, the conversion from repository path to
+ * resource path and vice versa is left to subclasses.
+ */
+public abstract class AbstractLocatorFactory implements DavLocatorFactory {
+
+    private static Logger log = LoggerFactory.getLogger(AbstractLocatorFactory.class);
+
+    private final String pathPrefix;
+
+    /**
+     * Create a new factory
+     *
+     * @param pathPrefix Prefix, that needs to be removed in order to retrieve
+     * the path of the repository item from a given {@code DavResourceLocator}.
+     */
+    public AbstractLocatorFactory(String pathPrefix) {
+        this.pathPrefix = pathPrefix;
+    }
+
+    //--------------------------------------------------< DavLocatorFactory >---
+    /**
+     * Create a new {@code DavResourceLocator}. Any leading prefix and
+     * path-prefix (as defined with the constructor) are removed from the
+     * given request handle. The same applies for trailing '/'. The remaining
+     * String is called the 'resource handle' and it's first segment is treated
+     * as workspace name. If resource handle (and therefore workspace name)
+     * are missing, both values are set to {@code null}.
+     * <p>
+     * Examples:
+     *
+     * <pre>
+     * http://www.foo.bar/ (path prefix missing)
+     * -&gt; workspace path = null
+     * -&gt; resource path  = null
+     * -&gt; href           = http://www.foo.bar/pathPrefix/
+     *
+     * http://www.foo.bar/pathPrefix/
+     * -&gt; workspace path = null
+     * -&gt; resource path  = null
+     * -&gt; href           = http://www.foo.bar/pathPrefix/
+     *
+     * http://www.foo.bar/pathPrefix/wspName
+     * -&gt; workspace path = /wspName
+     * -&gt; resource path  = /wspName
+     * -&gt; href           = http://www.foo.bar/pathPrefix/wspName
+     *
+     * http://www.foo.bar/pathPrefix/wspName/anypath
+     * -&gt; workspace path = /wspName
+     * -&gt; resource path  = /wspName/anypath
+     * -&gt; href           = http://www.foo.bar/pathPrefix/wspName/anypath
+     * </pre>
+     *
+     * NOTE: If the given href is an absolute URI it must start with the
+     * specified prefix.
+     *
+     * @param prefix
+     * @param href
+     * @return a new {@code DavResourceLocator}
+     * @throws IllegalArgumentException if the given href is {@code null}
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String href) {
+        if (href == null) {
+            throw new IllegalArgumentException("Request handle must not be null.");
+        }
+
+        // build prefix string and remove all prefixes from the given href.
+        StringBuffer b = new StringBuffer("");
+        if (prefix != null && prefix.length() > 0) {
+            b.append(prefix);
+            if (href.startsWith(prefix)) {
+                href = href.substring(prefix.length());
+            }
+        }
+        if (pathPrefix != null && pathPrefix.length() > 0) {
+            if (!b.toString().endsWith(pathPrefix)) {
+                b.append(pathPrefix);
+            }
+            if (href.startsWith(pathPrefix)) {
+                href = href.substring(pathPrefix.length());
+            }
+        }
+
+        // remove trailing "/" that is present with collections
+        if (href.endsWith("/")) {
+            href = href.substring(0, href.length() - 1);
+        }
+
+        String resourcePath;
+        String workspacePath;
+
+        // an empty requestHandle (after removal of the "/") signifies a request
+        // to the root that does not represent a repository item.
+        if ("".equals(href)) {
+            resourcePath = null;
+            workspacePath = null;
+        } else {
+            resourcePath = EncodeUtil.unescape(href);
+            // retrieve wspPath: look for the first slash ignoring the leading one
+            int pos = href.indexOf('/', 1);
+            if (pos == -1) {
+                // request to a 'workspace' resource
+                workspacePath = resourcePath;
+            } else {
+                // separate the workspace path from the resource path.
+                workspacePath = EncodeUtil.unescape(href.substring(0, pos));
+            }
+        }
+
+        log.trace("createResourceLocator: prefix='" + prefix + "' href='" + href + "' -> prefix='" + b.toString()
+                + "' workspacePath='" + workspacePath + "' resourcePath='" + resourcePath + "'");
+        return new DavResourceLocatorImpl(b.toString(), workspacePath, resourcePath, this);
+    }
+
+    /**
+     * Like {@link #createResourceLocator(String, String)}, but by setting
+     * {@code forDestination} to {@code true} any special processing of URI
+     * suffixes can be disabled.
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) {
+        return createResourceLocator(prefix, href);
+    }
+
+   /**
+     * Create a new {@code DavResourceLocator} from the specified prefix,
+     * workspace path and resource path, without modifying the specified Strings.
+     * Note, that it is expected that the resource path starts with the
+     * given workspace path unless both values are {@code null}.
+     *
+     * @param prefix
+     * @param workspacePath path or the workspace containing this resource or
+     * {@code null}.
+     * @param resourcePath Path of the resource or {@code null}. Any non
+     * null value must start with the specified workspace path.
+     * @return a new {@code DavResourceLocator}
+     * @see DavLocatorFactory#createResourceLocator(String, String, String)
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) {
+        return createResourceLocator(prefix, workspacePath, resourcePath, true);
+    }
+
+    /**
+     * Create a new {@code DavResourceLocator} from the specified prefix,
+     * workspace path and resource path. If {@code isResourcePath} is set
+     * to {@code false}, the given 'resourcePath' is converted by calling
+     * {@link #getResourcePath(String, String)}. Otherwise the same restriction
+     * applies as for {@link #createResourceLocator(String, String, String)}.
+     *
+     * @param prefix
+     * @param workspacePath
+     * @param path
+     * @param isResourcePath
+     * @return
+     * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean)
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) {
+        String resourcePath = (isResourcePath) ? path : getResourcePath(path, workspacePath);
+        return new DavResourceLocatorImpl(prefix, workspacePath, resourcePath, this);
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Subclasses must defined how the repository path is built from the given
+     * resource and workspace path.
+     *
+     * @param resourcePath
+     * @param wspPath
+     * @return
+     */
+    protected abstract String getRepositoryPath(String resourcePath, String wspPath);
+
+    /**
+     * Subclasses must defined how the resource path is built from the given
+     * repository and workspace path.
+     *
+     * @param repositoryPath
+     * @param wspPath
+     * @return
+     */
+    protected abstract String getResourcePath(String repositoryPath, String wspPath);
+
+    //--------------------------------------------------------< DavResource >---
+    /**
+     * Private inner class {@code DavResourceLocatorImpl} implementing
+     * the {@code DavResourceLocator} interface.
+     */
+    private class DavResourceLocatorImpl implements DavResourceLocator {
+
+        private final String prefix;
+        private final String workspacePath;
+        private final String resourcePath;
+        private final AbstractLocatorFactory factory;
+
+        private final String href;
+
+        /**
+         * Create a new {@code DavResourceLocatorImpl}.
+         *
+         * @param prefix
+         * @param workspacePath
+         * @param resourcePath
+         */
+        private DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, AbstractLocatorFactory factory) {
+
+            this.prefix = prefix;
+            this.workspacePath = workspacePath;
+            this.resourcePath = resourcePath;
+            this.factory = factory;
+
+            StringBuffer buf = new StringBuffer(prefix);
+            // NOTE: no need to append the workspace path, since it must
+            // be part of the resource path.
+            if (resourcePath != null && resourcePath.length() > 0) {
+                // check if condition is really met
+                if (!resourcePath.startsWith(workspacePath)) {
+                    throw new IllegalArgumentException("Resource path '" + resourcePath + "' does not start with workspace path '" + workspacePath + "'.");
+                }
+                buf.append(EncodeUtil.escapePath(resourcePath));
+            }
+            int length = buf.length();
+            if (length == 0 || (length > 0 && buf.charAt(length - 1) != '/')) {
+                buf.append("/");
+            }
+            this.href = buf.toString();
+        }
+
+        /**
+         * Return the prefix used to build the href String. This includes the initial
+         * hrefPrefix as well a the path prefix.
+         *
+         * @return prefix String used to build the href.
+         */
+        public String getPrefix() {
+            return prefix;
+        }
+
+        /**
+         * Returns the resource path which always starts with the workspace
+         * path, if a workspace resource exists. For the top most resource
+         * (request handle '/'), {@code null} is returned.
+         *
+         * @return resource path or {@code null}
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath()
+         */
+        public String getResourcePath() {
+            return resourcePath;
+        }
+
+        /**
+         * Return the workspace path or {@code null} if this locator object
+         * represents the '/' request handle.
+         *
+         * @return workspace path or {@code null}
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath()
+         */
+        public String getWorkspacePath() {
+            return workspacePath;
+        }
+
+        /**
+         * Return the workspace name or {@code null} if this locator object
+         * represents the '/' request handle, which does not contain a workspace
+         * path.
+         *
+         * @return workspace name or {@code null}
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName()
+         */
+        public String getWorkspaceName() {
+            if (workspacePath != null && workspacePath.length() > 0) {
+                return workspacePath.substring(1);
+            }
+            return null;
+        }
+
+        /**
+         * Returns true if the specified locator object refers to a resource within
+         * the same workspace.
+         *
+         * @param locator
+         * @return true if the workspace name obtained from the given locator
+         * refers to the same workspace as the workspace name of this locator.
+         * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator)
+         */
+        public boolean isSameWorkspace(DavResourceLocator locator) {
+            return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName());
+        }
+
+        /**
+         * Returns true if the specified string equals to this workspace name or
+         * if both names are null.
+         *
+         * @param workspaceName
+         * @return true if the workspace name is equal to this workspace name.
+         * @see DavResourceLocator#isSameWorkspace(String)
+         */
+        public boolean isSameWorkspace(String workspaceName) {
+            String thisWspName = getWorkspaceName();
+            return (thisWspName == null) ? workspaceName == null : thisWspName.equals(workspaceName);
+        }
+
+        /**
+         * Returns an 'href' consisting of prefix and resource path (which starts
+         * with the workspace path). It assures a trailing '/' in case the href
+         * is used for collection. Note, that the resource path is
+         * {@link org.apache.jackrabbit.webdav.util.EncodeUtil#escapePath(String) escaped}.
+         *
+         * @param isCollection
+         * @return href String representing the text of the href element
+         * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF
+         * @see DavResourceLocator#getHref(boolean)
+         */
+        public String getHref(boolean isCollection) {
+            return (isCollection) ? href : href.substring(0, href.length() - 1);
+        }
+
+        /**
+         * Returns true if the 'workspacePath' field is {@code null}.
+         *
+         * @return true if the 'workspacePath' field is {@code null}.
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation()
+         */
+        public boolean isRootLocation() {
+            return getWorkspacePath() == null;
+        }
+
+        /**
+         * Return the factory that created this locator.
+         *
+         * @return factory
+         * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory()
+         */
+        public DavLocatorFactory getFactory() {
+            return factory;
+        }
+
+        /**
+         * Uses {@link AbstractLocatorFactory#getRepositoryPath(String, String)}
+         * to build the repository path.
+         *
+         * @see DavResourceLocator#getRepositoryPath()
+         */
+        public String getRepositoryPath() {
+            return factory.getRepositoryPath(getResourcePath(), getWorkspacePath());
+        }
+
+        /**
+         * Computes the hash code from the href, that is built from the prefix,
+         * the workspace name and the resource path all of them representing
+         * final instance fields.
+         *
+         * @return the hash code
+         */
+        @Override
+        public int hashCode() {
+            return href.hashCode();
+        }
+
+        /**
+         * Returns true, if the given object is a {@code DavResourceLocatorImpl}
+         * with the same hash code.
+         *
+         * @param obj the object to compare to
+         * @return {@code true} if the 2 objects are equal;
+         *         {@code false} otherwise
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
+            }
+            if (obj instanceof DavResourceLocatorImpl) {
+                DavResourceLocatorImpl other = (DavResourceLocatorImpl) obj;
+                return hashCode() == other.hashCode();
+            }
+            return false;
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java
new file mode 100644
index 000000000..27a24b7f9
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+public interface ContentCodingAwareRequest {
+
+    /**
+     * Element name for signaling "must be supported content coding"
+     */
+    public final QName PRECONDITION_SUPPORTED = new QName("http://www.day.com/jcr/webdav/1.0", "supported-content-coding", "dcr");
+
+    /**
+     * @return value suitable for Accept response field
+     */
+    public String getAcceptableCodings();
+
+    /**
+     * @return content codings used in request
+     */
+    public List<String> getRequestContentCodings();
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java
new file mode 100644
index 000000000..de09b5b60
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * <code>DavCompliance</code> defines constants for the various compliance
+ * classes defined RFC 2518, RFC 4918 and it's extensions.
+ */
+public final class DavCompliance {
+
+    /**
+     * Avoid instantiation
+     */
+    private DavCompliance() {}
+
+    // RFC 2518
+    public static final String _1_ = "1";
+    public static final String _2_ = "2";
+
+    // RFC 4918
+    public static final String _3_ = "3";
+
+    // RFC 3253
+    public static final String ACTIVITY = "activity";
+    public static final String BASELINE = "baseline";
+    public static final String CHECKOUT_IN_PLACE = "checkout-in-place";
+    public static final String LABEL = "label";
+    public static final String MERGE = "merge";
+    public static final String UPDATE = "update";
+    public static final String VERSION_CONTROL = "version-control";
+    public static final String VERSION_CONTROLLED_COLLECTION = "version-controlled-collection";
+    public static final String VERSION_HISTORY = "version-history";
+    public static final String WORKING_RESOURCE = "working-resource";
+    public static final String WORKSPACE = "workspace";
+
+    // RFC 3648
+    public static final String ORDERED_COLLECTIONS = "ordered-collections";
+
+    // RFC 3744
+    public static final String ACCESS_CONTROL = "access-control";
+
+    // RFC 5842
+    public static final String BIND = "bind";
+    
+    // no RFC
+    public static final String OBSERVATION = "observation";
+
+    public static String concatComplianceClasses(String[] complianceClasses) {
+        StringBuffer b = new StringBuffer();
+        for (int i = 0; i < complianceClasses.length; i++) {
+            if (i > 0) {
+                b.append(",");
+            }
+            b.append(complianceClasses[i]);
+        }
+        return b.toString();
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java
new file mode 100644
index 000000000..a50b1cd2a
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.util.HttpDateFormat;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+
+import java.text.DateFormat;
+
+/**
+ * <code>DavConstants</code> provide constants for request and response
+ * headers, XML elements and property names defined by
+ * <a href="http://www.webdav.org/specs/rfc2518.html">RFC 2518</a>. In addition,
+ * common date formats (creation date and modification time) are included.
+ */
+public interface DavConstants {
+
+    /**
+     * Default Namespace constant
+     */
+    public static final Namespace NAMESPACE = Namespace.getNamespace("D", "DAV:");
+
+    //--------------------------------< Headers (Names and Value Constants) >---
+    public static final String HEADER_DAV = "DAV";
+    public static final String HEADER_DESTINATION = "Destination";
+    public static final String HEADER_IF = "If";
+    public static final String HEADER_AUTHORIZATION = "Authorization";
+    public static final String HEADER_CONTENT_TYPE = "Content-Type";
+    public static final String HEADER_CONTENT_LENGTH = "Content-Length";
+    public static final String HEADER_CONTENT_LANGUAGE = "Content-Language";
+    public static final String HEADER_ETAG = "ETag";
+    public static final String HEADER_LAST_MODIFIED = "Last-Modified";
+
+    //--------------------------------------------------< Lock-Token Header >---
+    public static final String HEADER_LOCK_TOKEN = "Lock-Token";
+    public static final String OPAQUE_LOCK_TOKEN_PREFIX = "opaquelocktoken:";
+
+    //-----------------------------------------------------< Timeout Header >---
+    public static final String HEADER_TIMEOUT = "Timeout";
+    public static final String TIMEOUT_INFINITE = "Infinite";
+    // RFC 2518: timeout value for TimeType "Second" MUST NOT be greater than 2^32-1
+    public static final long INFINITE_TIMEOUT = Integer.MAX_VALUE;
+    public static final long UNDEFINED_TIMEOUT = Integer.MIN_VALUE;
+
+    //---------------------------------------------------< Overwrite Header >---
+    public static final String HEADER_OVERWRITE = "Overwrite";
+
+    //-------------------------------------------------------< Depth Header >---
+    public static final String HEADER_DEPTH = "Depth";
+    public static final String DEPTH_INFINITY_S = "infinity";
+    public static final int DEPTH_INFINITY = Integer.MAX_VALUE;
+    public static final int DEPTH_0 = 0;
+    public static final int DEPTH_1 = 1;
+
+    //---< XML Element, Attribute Names >---------------------------------------
+    public static final String XML_ALLPROP = "allprop";
+    public static final String XML_COLLECTION = "collection";
+    public static final String XML_DST = "dst";
+    public static final String XML_HREF = "href";
+    public static final String XML_INCLUDE = "include";
+    public static final String XML_KEEPALIVE = "keepalive";
+    public static final String XML_LINK = "link";
+    public static final String XML_MULTISTATUS = "multistatus";
+    public static final String XML_OMIT = "omit";
+    public static final String XML_PROP = "prop";
+    public static final String XML_PROPERTYBEHAVIOR = "propertybehavior";
+    public static final String XML_PROPERTYUPDATE = "propertyupdate";
+    public static final String XML_PROPFIND = "propfind";
+    public static final String XML_PROPNAME = "propname";
+    public static final String XML_PROPSTAT = "propstat";
+    public static final String XML_REMOVE = "remove";
+    public static final String XML_RESPONSE = "response";
+    public static final String XML_RESPONSEDESCRIPTION = "responsedescription";
+    public static final String XML_SET = "set";
+    public static final String XML_SOURCE = "source";
+    public static final String XML_STATUS = "status";
+
+    //------------------------------------------------------------< locking >---
+    public static final String XML_ACTIVELOCK = "activelock";
+    public static final String XML_DEPTH = "depth";
+    public static final String XML_LOCKTOKEN = "locktoken";
+    public static final String XML_TIMEOUT = "timeout";
+    public static final String XML_LOCKSCOPE = "lockscope";
+    public static final String XML_EXCLUSIVE = "exclusive";
+    public static final String XML_SHARED = "shared";
+    public static final String XML_LOCKENTRY = "lockentry";
+    public static final String XML_LOCKINFO = "lockinfo";
+    public static final String XML_LOCKTYPE = "locktype";
+    public static final String XML_WRITE = "write";
+    public static final String XML_OWNER = "owner";
+    /**
+     * The <code>lockroot</code> XML element
+     * @see <a href="http://www.webdav.org/specs/rfc4918.html#ELEMENT_lockroot">RFC 4918</a>
+     */
+    public static final String XML_LOCKROOT = "lockroot";
+
+    //-----------------------------------------------------< Property Names >---
+    /*
+     * Webdav property names as defined by RFC 2518<br>
+     * Note: Microsoft webdav clients as well as Webdrive request additional
+     * property (e.g. href, name, owner, isRootLocation, isCollection)  within the
+     * default namespace, which are are ignored by this implementation, except
+     * for the 'isCollection' property, needed for XP built-in clients.
+     */
+    public static final String PROPERTY_CREATIONDATE = "creationdate";
+    public static final String PROPERTY_DISPLAYNAME = "displayname";
+    public static final String PROPERTY_GETCONTENTLANGUAGE = "getcontentlanguage";
+    public static final String PROPERTY_GETCONTENTLENGTH = "getcontentlength";
+    public static final String PROPERTY_GETCONTENTTYPE = "getcontenttype";
+    public static final String PROPERTY_GETETAG = "getetag";
+    public static final String PROPERTY_GETLASTMODIFIED = "getlastmodified";
+    public static final String PROPERTY_LOCKDISCOVERY = "lockdiscovery";
+    public static final String PROPERTY_RESOURCETYPE = "resourcetype";
+    public static final String PROPERTY_SOURCE = "source";
+    public static final String PROPERTY_SUPPORTEDLOCK = "supportedlock";
+
+    //-------------------------------------------------< PropFind Constants >---
+    public static final int PROPFIND_BY_PROPERTY = 0;
+    public static final int PROPFIND_ALL_PROP = 1;
+    public static final int PROPFIND_PROPERTY_NAMES = 2;
+    public static final int PROPFIND_ALL_PROP_INCLUDE = 3; // RFC 4918, Section 9.1
+
+    //----------------------------------------------< Date Format Constants >---
+    /**
+     * Marker for undefined modification or creation time.
+     */
+    public static long UNDEFINED_TIME = -1;
+
+    /**
+     * modificationDate date format per RFC 1123.<br>
+     * NOTE: Access to <code>DateFormat</code> isn't thread save.
+     */
+    public static DateFormat modificationDateFormat = HttpDateFormat.modificationDateFormat();
+
+    /**
+     * Simple date format for the creation date ISO representation (partial).<br>
+     * NOTE: Access to <code>DateFormat</code> isn't thread save.
+     */
+    public static DateFormat creationDateFormat = HttpDateFormat.creationDateFormat();
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavException.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavException.java
new file mode 100644
index 000000000..1c7c611db
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavException.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * <code>DavException</code> extends the {@link Exception} class in order
+ * to simplify handling of exceptional situations occurring during processing
+ * of WebDAV requests and provides possibility to retrieve an Xml representation
+ * of the error.
+ */
+public class DavException extends Exception implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(DavException.class);
+    private static Properties statusPhrases = new Properties();
+    static {
+        try {
+            statusPhrases.load(DavException.class.getResourceAsStream("statuscode.properties"));
+        } catch (IOException e) {
+            log.error("Failed to load status properties: " + e.getMessage());
+        }
+    }
+
+    public static final String XML_ERROR = "error";
+
+    private int errorCode = DavServletResponse.SC_INTERNAL_SERVER_ERROR;
+    private Element errorCondition;
+
+    /**
+     * Create a new <code>DavException</code>.
+     *
+     * @param errorCode integer specifying any of the status codes defined by
+     * {@link DavServletResponse}.
+     * @param message Human readable error message.
+     * @see DavException#DavException(int, String, Throwable, Element)
+     */
+    public DavException(int errorCode, String message) {
+        this(errorCode, message, null, null);
+    }
+
+    /**
+     * Create a new <code>DavException</code>.
+     *
+     * @param errorCode integer specifying any of the status codes defined by
+     * {@link DavServletResponse}.
+     * @param cause Cause of this DavException
+     * @see DavException#DavException(int, String, Throwable, Element)
+     */
+    public DavException(int errorCode, Throwable cause) {
+        this(errorCode, null, cause, null);
+    }
+
+    /**
+     * Create a new <code>DavException</code>.
+     *
+     * @param errorCode integer specifying any of the status codes defined by
+     * {@link DavServletResponse}.
+     * @see DavException#DavException(int, String, Throwable, Element)
+     */
+    public DavException(int errorCode) {
+        this(errorCode, statusPhrases.getProperty(String.valueOf(errorCode)), null, null);
+    }
+
+    /**
+     * Create a new <code>DavException</code>.
+     *
+     * @param errorCode integer specifying any of the status codes defined by
+     * {@link DavServletResponse}.
+     * @param message Human readable error message.
+     * @param cause Cause of this <code>DavException</code>.
+     * @param errorCondition Xml element providing detailed information about
+     * the error. If the condition is not <code>null</code>, {@link #toXml(Document)}
+     */
+    public DavException(int errorCode, String message, Throwable cause, Element errorCondition) {
+        super(message, cause);
+        this.errorCode = errorCode;
+        this.errorCondition = errorCondition;
+        log.debug("DavException: (" + errorCode + ") " + message);
+    }
+
+    /**
+     * Return the error code attached to this <code>DavException</code>.
+     *
+     * @return errorCode
+     */
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    /**
+     * Return the status phrase corresponding to the error code attached to
+     * this <code>DavException</code>.
+     *
+     * @return status phrase corresponding to the error code.
+     * @see #getErrorCode()
+     */
+    public String getStatusPhrase() {
+        return getStatusPhrase(errorCode);
+    }
+
+    /**
+     * Returns the status phrase for the given error code.
+     *
+     * @param errorCode
+     * @return status phrase corresponding to the given error code.
+     */
+    public static String getStatusPhrase(int errorCode) {
+        return statusPhrases.getProperty(errorCode + "");
+    }
+
+    /**
+     * @return true if a error condition has been specified, false otherwise.
+     */
+    public boolean hasErrorCondition() {
+        return errorCondition != null;
+    }
+
+    /**
+     * Return the error condition attached to this <code>DavException</code>.
+     *
+     * @return errorCondition
+     */
+    public Element getErrorCondition() {
+        return errorCondition;
+    }
+
+    /**
+     * Returns a DAV:error element containing the error condition or
+     * <code>null</code> if no specific condition is available. See
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     * Section 1.6 "Method Preconditions and Postconditions" for additional
+     * information.
+     *
+     * @param document
+     * @return A DAV:error element indicating the error cause or <code>null</code>.
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     */
+    public Element toXml(Document document) {
+        if (hasErrorCondition()) {
+            Element error;
+            if (DomUtil.matches(errorCondition, XML_ERROR, DavConstants.NAMESPACE)) {
+                error = (Element) document.importNode(errorCondition, true);
+            } else {
+                error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE);
+                error.appendChild(document.importNode(errorCondition, true));
+            }
+            return error;
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java
new file mode 100644
index 000000000..db4ca0a9b
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * <code>DavLocatorFactory</code>...
+ */
+public interface DavLocatorFactory {
+
+    /**
+     * Create a new <code>DavResourceLocator</code>.
+     *
+     * @param prefix String consisting of  [scheme:][//authority][path] where
+     * path defines the (imaginary) path to the {@link DavResourceLocator#isRootLocation root location}.
+     * @param href of the resource to be created. The given string may start with
+     * the 'prefix'. Please note, that in contrast to
+     * {@link DavLocatorFactory#createResourceLocator(String, String, String)} the
+     * href is expected to be URL encoded.
+     * @return a new resource locator.
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String href);
+
+    /**
+     * Create a new <code>DavResourceLocator</code>. This methods corresponds to
+     * {@link DavLocatorFactory#createResourceLocator(String, String, String, boolean)}
+     * with the flag set to true.
+     *
+     * @param prefix String consisting of  [scheme:][//authority][path] where
+     * path defines the path to the {@link DavResourceLocator#isRootLocation root location}.
+     * @param workspacePath the first segment of the URIs path indicating the
+     * workspace. The implementation may allow a empty String if workspaces
+     * are not supported.
+     * @param resourcePath the URL decoded resource path.
+     * @return a new resource locator.
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath);
+
+    /**
+     *
+     * @param prefix String consisting of  [scheme:][//authority][path] where
+     * path defines the path to the {@link DavResourceLocator#isRootLocation root location}.
+     * @param workspacePath the first segment of the URIs path indicating the
+     * workspace. The implementation may allow a empty String if workspaces
+     * are not supported.
+     * @param path the URL decoded path.
+     * @param isResourcePath If true this method returns the same as
+     * {@link DavLocatorFactory#createResourceLocator(String, String, String)},
+     * otherwise the given path is treated as internal repository path.
+     * The implementation may choose to implement a conversion of the repository
+     * path to a valid resource path, e.g. (un)escaping of certain characters, due
+     * to incompatibility with the URI definition (or vice versa). Note that
+     * {@link DavResourceLocator#getRepositoryPath()} should in this case implement
+     * the reverse operation.
+     * @return a new resource locator.
+     * @see DavResourceLocator#getRepositoryPath()
+     */
+    public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath);
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java
new file mode 100644
index 000000000..003d7976d
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * <code>DavMethods</code> defines constants for the WebDAV METHODS.
+ */
+public final class DavMethods {
+
+    /**
+     * Avoid instantiation
+     */
+    private DavMethods() {}
+
+    /**
+     * A map of WebDAV METHODS
+     */
+    private static Map<String, Integer> methodMap = new HashMap<String, Integer>();
+
+    /**
+     * An array of method codes that are affected by a Label header
+     * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#HEADER_LABEL
+     */
+    private static int[] labelMethods;
+
+    /**
+     * An array of method codes defined by RFC 3253 (deltaV)
+     */
+    private static int[] deltaVMethods;
+
+    /**
+     * The webdav OPTIONS method and public constant
+     */
+    public static final int DAV_OPTIONS = 1;
+    public static final String METHOD_OPTIONS = "OPTIONS";
+
+    /**
+     * The webdav GET method and public constant
+     */
+    public static final int DAV_GET = DAV_OPTIONS + 1;
+    public static final String METHOD_GET = "GET";
+
+    /**
+     * The webdav HEAD method and public constant
+     */
+    public static final int DAV_HEAD = DAV_GET + 1;
+    public static final String METHOD_HEAD = "HEAD";
+
+
+    /**
+     * The webdav POST method and public constant
+     */
+    public static final int DAV_POST = DAV_HEAD + 1;
+    public static final String METHOD_POST = "POST";
+
+
+    /** The webdav DELETE method and public constant */
+    public static final int DAV_DELETE = DAV_POST + 1;
+    public static final String METHOD_DELETE = "DELETE";
+
+
+    /** The webdav PUT method and public constant */
+    public static final int DAV_PUT = DAV_DELETE + 1;
+    public static final String METHOD_PUT = "PUT";
+
+
+    /**
+     * The webdav PROPFIND method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>.
+     */
+    public static final int DAV_PROPFIND = DAV_PUT + 1;
+    public static final String METHOD_PROPFIND = "PROPFIND";
+
+
+    /**
+     * The webdav PROPPATCH method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
+     */
+    public static final int DAV_PROPPATCH = DAV_PROPFIND + 1;
+    public static final String METHOD_PROPPATCH = "PROPPATCH";
+
+
+    /**
+     * The webdav MKCOL (make collection) method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
+     */
+    public static final int DAV_MKCOL = DAV_PROPPATCH + 1;
+    public static final String METHOD_MKCOL = "MKCOL";
+
+
+    /**
+     * The webdav COPY method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
+     */
+    public static final int DAV_COPY = DAV_MKCOL + 1;
+    public static final String METHOD_COPY = "COPY";
+
+
+    /**
+     * The webdav MOVE method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
+     */
+    public static final int DAV_MOVE = DAV_COPY + 1;
+    public static final String METHOD_MOVE = "MOVE";
+
+
+    /**
+     * The webdav LOCK method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
+     */
+    public static final int DAV_LOCK = DAV_MOVE + 1;
+    public static final String METHOD_LOCK = "LOCK";
+
+
+    /**
+     * The webdav UNLOCK method and public constant as defined by
+     * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
+     */
+    public static final int DAV_UNLOCK = DAV_LOCK + 1;
+    public static final String METHOD_UNLOCK = "UNLOCK";
+
+
+    /**
+     * The webdav ORDERPATCH method and public constant
+     * defined by <a href="http://www.ietf.org/rfc/rfc3648.txt">RFC 3648</a>.
+     */
+    public static final int DAV_ORDERPATCH = DAV_UNLOCK + 1;
+    public static final String METHOD_ORDERPATCH = "ORDERPATCH";
+
+
+    /**
+     * The webdav SUBSCRIBE method and public constant.<br>
+     * NOTE: This method is not defined by any of the Webdav RFCs
+     */
+    public static final int DAV_SUBSCRIBE = DAV_ORDERPATCH + 1;
+    public static final String METHOD_SUBSCRIBE = "SUBSCRIBE";
+
+
+    /**
+     * The webdav UNSUBSCRIBE method and public constant<br>
+     * NOTE: This method is not defined by any of the Webdav RFCs
+     */
+    public static final int DAV_UNSUBSCRIBE = DAV_SUBSCRIBE + 1;
+    public static final String METHOD_UNSUBSCRIBE = "UNSUBSCRIBE";
+
+
+    /**
+     * The webdav POLL method and public constant<br>
+     * NOTE: This method is not defined by any of the Webdav RFCs
+     */
+    public static final int DAV_POLL = DAV_UNSUBSCRIBE + 1;
+    public static final String METHOD_POLL = "POLL";
+
+
+    /**
+     * The webdav SEARCH method and public constant as defined by the
+     * Webdav Search internet draft.
+     */
+    public static final int DAV_SEARCH = DAV_POLL + 1;
+    public static final String METHOD_SEARCH = "SEARCH";
+
+
+    /**
+     * The webdav REPORT method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_REPORT = DAV_SEARCH + 1;
+    public static final String METHOD_REPORT = "REPORT";
+
+
+    /**
+     * The webdav VERSION-CONTROL method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_VERSION_CONTROL = DAV_REPORT + 1;
+    public static final String METHOD_VERSION_CONTROL = "VERSION-CONTROL";
+
+    /**
+     * The webdav CHECKIN method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_CHECKIN = DAV_VERSION_CONTROL + 1;
+    public static final String METHOD_CHECKIN = "CHECKIN";
+
+    /**
+     * The webdav CHECKOUT method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_CHECKOUT = DAV_CHECKIN + 1;
+    public static final String METHOD_CHECKOUT = "CHECKOUT";
+
+    /**
+     * The webdav UNCHECKOUT method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_UNCHECKOUT = DAV_CHECKOUT + 1;
+    public static final String METHOD_UNCHECKOUT = "UNCHECKOUT";
+
+    /**
+     * The webdav LABEL method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_LABEL = DAV_UNCHECKOUT + 1;
+    public static final String METHOD_LABEL = "LABEL";
+
+    /**
+     * The webdav MERGE method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_MERGE = DAV_LABEL + 1;
+    public static final String METHOD_MERGE = "MERGE";
+
+    /**
+     * The webdav UPDATE method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_UPDATE = DAV_MERGE + 1;
+    public static final String METHOD_UPDATE = "UPDATE";
+
+    /**
+     * The webdav MKWORKSPACE method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_MKWORKSPACE = DAV_UPDATE + 1;
+    public static final String METHOD_MKWORKSPACE = "MKWORKSPACE";
+
+    /**
+     * The webdav BASELINE-CONTROL method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_BASELINE_CONTROL = DAV_MKWORKSPACE + 1;
+    public static final String METHOD_BASELINE_CONTROL = "BASELINE-CONTROL";
+
+    /**
+     * The webdav MKACTIVITY method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a>
+     */
+    public static final int DAV_MKACTIVITY = DAV_BASELINE_CONTROL + 1;
+    public static final String METHOD_MKACTIVITY = "MKACTIVITY";
+
+    /**
+     * The webdav ACL method and public constant defined by
+     * <a href="http://www.ietf.org/rfc/rfc3744.txt">RFC 3744</a>
+     */
+    public static final int DAV_ACL = DAV_MKACTIVITY + 1;
+    public static final String METHOD_ACL = "ACL";
+
+    /**
+     * The webdav REBIND method and public constant defined by
+     * the BIND specification
+     */
+    public static final int DAV_REBIND = DAV_ACL + 1;
+    public static final String METHOD_REBIND = "REBIND";
+
+    /**
+     * The webdav UNBIND method and public constant defined by
+     * the BIND specification
+     */
+    public static final int DAV_UNBIND = DAV_REBIND + 1;
+    public static final String METHOD_UNBIND = "UNBIND";
+
+    /**
+     * The webdav BIND method and public constant defined by
+     * the BIND specification
+     */
+    public static final int DAV_BIND = DAV_UNBIND + 1;
+    public static final String METHOD_BIND = "BIND";
+
+    /**
+     * Returns webdav method type code, error result &lt;= 0
+     * Valid type codes &gt; 0
+     */
+    public static int getMethodCode(String method) {
+        Integer code = methodMap.get(method.toUpperCase(Locale.ROOT));
+        if (code != null) {
+            return code;
+        }
+        return 0;
+    }
+
+    /**
+     * Static initializer for methodTable map
+     */
+    private static void addMethodCode(String method, int code) {
+        methodMap.put(method, code);
+    }
+
+    /**
+     *  Webdav Method table
+     */
+    static {
+        addMethodCode(METHOD_OPTIONS, DAV_OPTIONS);
+        addMethodCode(METHOD_GET, DAV_GET);
+        addMethodCode(METHOD_HEAD, DAV_HEAD);
+        addMethodCode(METHOD_POST, DAV_POST);
+        addMethodCode(METHOD_PUT, DAV_PUT);
+        addMethodCode(METHOD_DELETE, DAV_DELETE);
+        addMethodCode(METHOD_PROPFIND, DAV_PROPFIND);
+        addMethodCode(METHOD_PROPPATCH, DAV_PROPPATCH);
+        addMethodCode(METHOD_MKCOL, DAV_MKCOL);
+        addMethodCode(METHOD_COPY, DAV_COPY);
+        addMethodCode(METHOD_MOVE, DAV_MOVE);
+        addMethodCode(METHOD_LOCK, DAV_LOCK);
+        addMethodCode(METHOD_UNLOCK, DAV_UNLOCK);
+        addMethodCode(METHOD_ORDERPATCH, DAV_ORDERPATCH);
+        addMethodCode(METHOD_SUBSCRIBE, DAV_SUBSCRIBE);
+        addMethodCode(METHOD_UNSUBSCRIBE, DAV_UNSUBSCRIBE);
+        addMethodCode(METHOD_POLL, DAV_POLL);
+        addMethodCode(METHOD_SEARCH, DAV_SEARCH);
+        addMethodCode(METHOD_REPORT, DAV_REPORT);
+        addMethodCode(METHOD_VERSION_CONTROL, DAV_VERSION_CONTROL);
+        addMethodCode(METHOD_CHECKIN, DAV_CHECKIN);
+        addMethodCode(METHOD_CHECKOUT, DAV_CHECKOUT);
+        addMethodCode(METHOD_UNCHECKOUT, DAV_UNCHECKOUT);
+        addMethodCode(METHOD_LABEL, DAV_LABEL);
+        addMethodCode(METHOD_MERGE, DAV_MERGE);
+        addMethodCode(METHOD_UPDATE, DAV_UPDATE);
+        addMethodCode(METHOD_MKWORKSPACE, DAV_MKWORKSPACE);
+        addMethodCode(METHOD_BASELINE_CONTROL, DAV_BASELINE_CONTROL);
+        addMethodCode(METHOD_MKACTIVITY, DAV_MKACTIVITY);
+        addMethodCode(METHOD_ACL, DAV_ACL);
+        addMethodCode(METHOD_REBIND, DAV_REBIND);
+        addMethodCode(METHOD_UNBIND, DAV_UNBIND);
+        addMethodCode(METHOD_BIND, DAV_BIND);
+
+        labelMethods = new int[] { DAV_GET, DAV_HEAD, DAV_OPTIONS, DAV_PROPFIND,
+                                   DAV_LABEL, DAV_COPY };
+
+        deltaVMethods = new int[] { DAV_REPORT, DAV_VERSION_CONTROL, DAV_CHECKIN,
+                                    DAV_CHECKOUT, DAV_UNCHECKOUT, DAV_LABEL,
+                                    DAV_MERGE, DAV_UPDATE, DAV_MKWORKSPACE,
+                                    DAV_BASELINE_CONTROL, DAV_MKACTIVITY };
+    }
+
+    /**
+     * Returns <code>true</code> if the request is to create a resource.
+     * True for <code>PUT</code>, <code>POST</code>, <code>MKCOL</code>
+     * and <code>MKWORKSPACE</code> requests.
+     *
+     * @return true if request method is to create (or replace) a resource
+     */
+    public static boolean isCreateRequest(DavServletRequest request) {
+        int methodCode = getMethodCode(request.getMethod());
+        return ( methodCode == DAV_PUT ||
+                 methodCode == DAV_POST ||
+                 methodCode == DAV_MKCOL ||
+                 methodCode == DAV_MKWORKSPACE);
+    }
+
+    /**
+     * Returns <code>true</code> if the request is to create a collection resource.
+     * True for <code>MKCOL</code> and <code>MKWORKSPACE</code> requests.
+     *
+     * @return true if request method is to create a new collection resource
+     */
+    public static boolean isCreateCollectionRequest(DavServletRequest request) {
+        int methodCode = getMethodCode(request.getMethod());
+        return (methodCode == DAV_MKCOL || methodCode == DAV_MKWORKSPACE);
+    }
+
+    /**
+     * Returns true, if the specified method is affected by a Label header
+     *
+     * @param request
+     * @return
+     */
+    public static boolean isMethodAffectedByLabel(DavServletRequest request) {
+        int code = getMethodCode(request.getMethod());
+        for (int labelMethod : labelMethods) {
+            if (code == labelMethod) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true, if the specified method is defined by RFC 3253
+     *
+     * @param request
+     * @return true, if the specified method is defined by RFC 3253
+     */
+    public static boolean isDeltaVMethod(DavServletRequest request) {
+        int code = getMethodCode(request.getMethod());
+        for (int deltaVMethod : deltaVMethods) {
+            if (code == deltaVMethod) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResource.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResource.java
new file mode 100644
index 000000000..6e70a4206
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResource.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.lock.LockManager;
+import org.apache.jackrabbit.webdav.lock.Scope;
+import org.apache.jackrabbit.webdav.lock.Type;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * <code>DavResource</code> provides standard WebDAV functionality as specified
+ * by <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>.
+ */
+public interface DavResource {
+
+    /**
+     * String constant representing the WebDAV 1 and 2 method set.
+     */
+    public static final String METHODS = "OPTIONS, GET, HEAD, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK";
+
+    /**
+     * Returns a comma separated list of all compliance classes the given
+     * resource is fulfilling.
+     *
+     * @return compliance classes
+     */
+    public String getComplianceClass();
+
+    /**
+     * Returns a comma separated list of all METHODS supported by the given
+     * resource.
+     *
+     * @return METHODS supported by this resource.
+     */
+    public String getSupportedMethods();
+
+    /**
+     * Returns true if this webdav resource represents an existing repository item.
+     *
+     * @return true, if the resource represents an existing repository item.
+     */
+    public boolean exists();
+
+    /**
+     * Returns true if this webdav resource has the resourcetype 'collection'.
+     *
+     * @return true if the resource represents a collection resource.
+     */
+    public boolean isCollection();
+
+    /**
+     * Returns the display name of this resource.
+     *
+     * @return display name.
+     */
+    public String getDisplayName();
+
+    /**
+     * Returns the {@link DavResourceLocator locator} object for this webdav resource,
+     * which encapsulates the information for building the complete 'href'.
+     *
+     * @return the locator for this resource.
+     * @see #getResourcePath()
+     * @see #getHref()
+     */
+    public DavResourceLocator getLocator();
+
+    /**
+     * Returns the path of the hierarchy element defined by this <code>DavResource</code>.
+     * This method is a shortcut for <code>DavResource.getLocator().getResourcePath()</code>.
+     *
+     * @return path of the element defined by this <code>DavResource</code>.
+     */
+    public String getResourcePath();
+
+    /**
+     * Returns the absolute href of this resource as returned in the
+     * multistatus response body.
+     *
+     * @return href
+     */
+    public String getHref();
+
+    /**
+     * Return the time of the last modification or -1 if the modification time
+     * could not be retrieved.
+     *
+     * @return time of last modification or -1.
+     */
+    public long getModificationTime();
+
+    /**
+     * Spools the resource properties and ev. content to the specified context
+     * (e.g. to respond to a 'GET' or 'HEAD' request). The context could e.g.
+     * wrap the servlet response.
+     *
+     * @param outputContext The output context.
+     * @throws IOException If an error occurs.
+     */
+    public void spool(OutputContext outputContext) throws IOException;
+
+    /**
+     * Returns an array of all {@link DavPropertyName property names} available
+     * on this resource.
+     *
+     * @return an array of property names.
+     */
+    public DavPropertyName[] getPropertyNames();
+
+    /**
+     * Return the webdav property with the specified name.
+     *
+     * @param name name of the webdav property
+     * @return the {@link DavProperty} with the given name or <code>null</code>
+     * if the property does not exist.
+     */
+    public DavProperty<?> getProperty(DavPropertyName name);
+
+    /**
+     * Returns all webdav properties present on this resource that will be
+     * return upon a {@link DavConstants#PROPFIND_ALL_PROP} request. The
+     * implementation may in addition expose other (protected or calculated)
+     * properties which should be marked accordingly (see also
+     * {@link org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop()}.
+     *
+     * @return a {@link DavPropertySet} containing at least all properties
+     * of this resource that are exposed in 'allprop' PROPFIND request.
+     */
+    public DavPropertySet getProperties();
+
+    /**
+     * Add/Set the specified property on this resource.
+     *
+     * @param property
+     * @throws DavException if an error occurs
+     */
+    public void setProperty(DavProperty<?> property) throws DavException;
+
+    /**
+     * Remove the specified property from this resource.
+     *
+     * @param propertyName
+     * @throws DavException if an error occurs
+     */
+    public void removeProperty(DavPropertyName propertyName) throws DavException;
+
+    /**
+     * Set/add and remove the specified properties from this resource.
+     *
+     * @param changeList list containing {@link DavPropertyName} objects (for
+     * properties to be removed) and {@link DavProperty} objects (for
+     * properties to be added/set).
+     * @return multistatus response listing the status resulting from
+     * setting and/or removing the specified properties, in order to allow a
+     * detailed multistatus response.
+     * @throws DavException if an error occurred. This may be the case if the
+     * general state of the resource prevents any properties to be set or removed
+     * (e.g. due to a lock).
+     */
+    public MultiStatusResponse alterProperties(List<? extends PropEntry> changeList) throws DavException;
+
+    /**
+     * Retrieve the resource this resource is internal member of.
+     *
+     * @return resource this resource is an internal member of. In case this resource
+     * is the root <code>null</code> is returned.
+     */
+    public DavResource getCollection();
+
+    /**
+     * Add the given resource as an internal member to this resource.
+     *
+     * @param resource {@link DavResource} to be added as internal member.
+     * @param inputContext Context providing the properties and content for the
+     * internal member to be created or replaced.
+     * @throws DavException
+     */
+    public void addMember(DavResource resource, InputContext inputContext) throws DavException;
+
+    /**
+     * Returns an iterator over all internal members.
+     *
+     * @return a {@link DavResourceIterator} over all internal members.
+     */
+    public DavResourceIterator getMembers();
+
+    /**
+     * Removes the specified member from this resource.
+     *
+     * @throws DavException
+     */
+    public void removeMember(DavResource member) throws DavException;
+
+    /**
+     * Move this DavResource to the given destination resource
+     *
+     * @param destination
+     * @throws DavException
+     */
+    public void move(DavResource destination) throws DavException;
+
+    /**
+     * Copy this DavResource to the given destination resource
+     *
+     * @param destination
+     * @param shallow
+     * @throws DavException
+     */
+    public void copy(DavResource destination, boolean shallow) throws DavException;
+
+    /**
+     * Returns true, if the this resource allows locking. NOTE, that this method
+     * does not define, whether a lock/unlock can be successfully executed.
+     *
+     * @return true, if this resource supports any locking.
+     * @param type
+     * @param scope
+     */
+    public boolean isLockable(Type type, Scope scope);
+
+    /**
+     * Returns true if a lock applies to this resource. This may be either a
+     * lock on this resource itself or a deep lock inherited from a collection
+     * above this resource.<br>
+     * Note, that true is returned whenever a lock applies to that resource even
+     * if the lock is expired or not effective due to the fact that the request
+     * provides the proper lock token.
+     *
+     * @return true if a lock applies to this resource.
+     * @param type
+     */
+    public boolean hasLock(Type type, Scope scope);
+
+    /**
+     * Return the lock present on this webdav resource or <code>null</code>
+     * if the resource is either not locked or not lockable at all. Note, that
+     * a resource may have a lock that is inherited by a deep lock enforced on
+     * one of its 'parent' resources.
+     *
+     * @return lock information of this resource or <code>null</code> if this
+     * resource has no lock applying it. If an error occurs while retrieving the
+     * lock information <code>null</code> is returned as well.
+     * @param type
+     */
+    public ActiveLock getLock(Type type, Scope scope) ;
+
+    /**
+     * Returns an array of all locks applied to the given resource.
+     *
+     * @return array of locks. The array is empty if there are no locks applied
+     * to this resource.
+     */
+    public ActiveLock[] getLocks();
+
+    /**
+     * Lock this webdav resource with the information retrieve from the request
+     * and return the resulting lockdiscovery object.
+     *
+     * @param reqLockInfo lock info as retrieved from the request.
+     * @return lockdiscovery object to be returned in the response. If the lock
+     * could not be obtained a <code>DavException</code> is thrown.
+     * @throws DavException if the lock could not be obtained.
+     */
+    public ActiveLock lock(LockInfo reqLockInfo) throws DavException;
+
+    /**
+     * Refresh an existing lock by resetting the timeout.
+     *
+     * @param reqLockInfo lock info as retrieved from the request.
+     * @param lockToken identifying the lock to be refreshed.
+     * @return lockdiscovery object to be returned in the response body. If the lock
+     * could not be refreshed a <code>DavException</code> is thrown.
+     * @throws DavException if the lock could not be refreshed.
+     */
+    public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) throws DavException;
+
+    /**
+     * Remove the lock identified by the included lock token from this resource.
+     * This method will return false if the unlocking did not succeed.
+     *
+     * @param lockToken identifying the lock to be removed.
+     * @throws DavException if the lock could not be removed.
+     */
+    public void unlock(String lockToken) throws DavException;
+
+    /**
+     * Add an external {@link LockManager} to this resource. This method may
+     * throw {@link UnsupportedOperationException} if the resource does handle
+     * locking itself.
+     *
+     * @param lockmgr
+     * @see LockManager
+     */
+    public void addLockManager(LockManager lockmgr);
+
+    /**
+     * Return the <code>DavResourceFactory</code> that created this resource.
+     *
+     * @return the factory that created this resource.
+     */
+    public DavResourceFactory getFactory();
+
+    /**
+     * Retrieve the <code>DavSession</code> associated with this resource.
+     *
+     * @return session object associated with this resource.
+     */
+    public DavSession getSession();
+}
+
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java
new file mode 100644
index 000000000..b015fe330
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * <code>DavResourceFactory</code> interface defines a single method for creating
+ * {@link DavResource} objects.
+ */
+public interface DavResourceFactory {
+
+    /**
+     * Create a {@link DavResource} object from the given locator, request and response
+     * objects.
+     *
+     * @param locator locator of the resource
+     * @param request
+     * @param response
+     * @return a new <code>DavResource</code> object.
+     * @throws DavException
+     */
+    public DavResource createResource(DavResourceLocator locator, DavServletRequest request, DavServletResponse response) throws DavException;
+
+    /**
+     * Create a new {@link DavResource} object from the given locator and session.
+     *
+     * @param locator
+     * @param session
+     * @return a new <code>DavResource</code> object.
+     * @throws DavException
+     */
+    public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException;
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java
new file mode 100644
index 000000000..e625b28ad
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import java.util.Iterator;
+
+/**
+ * DavResourceIterator extends the <code>Iterator</code> interface. Additional
+ * METHODS allow to retrieve the next {@link DavResource} from the iterator
+ * and the iterators size.
+ */
+public interface DavResourceIterator extends Iterator<DavResource> {
+
+    /**
+     * Returns the next {@link DavResource} in the iterator
+     * @return the next {@link DavResource}
+     */
+    public DavResource nextResource();
+
+    /**
+     * Return the number of {@link DavResource}s in the iterator.
+     * @return number of elements in the iterator.
+     */
+    public int size();
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java
new file mode 100644
index 000000000..3f43b7a9a
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * <code>DavResourceIteratorImpl</code> implementation of the {@link DavResourceIterator}
+ * interface.<br>
+ * NOTE: {@link #remove()} is not implemented.
+ */
+public class DavResourceIteratorImpl implements DavResourceIterator {
+
+    private static Logger log = LoggerFactory.getLogger(DavResourceIteratorImpl.class);
+
+    public static final DavResourceIterator EMPTY = new DavResourceIteratorImpl(Collections.<DavResource>emptyList());
+
+    private Iterator<DavResource> it;
+    private int size;
+
+    /**
+     * Create a new DavResourceIterator from the specified list.
+     * @param list
+     */
+    public DavResourceIteratorImpl(List<DavResource> list) {
+        it = list.iterator();
+        size = list.size();
+    }
+
+    /**
+     * @see DavResourceIterator#hasNext()
+     */
+    public boolean hasNext() {
+        return it.hasNext();
+    }
+
+    /**
+     * @see DavResourceIterator#next()
+     */
+    public DavResource next() {
+        return it.next();
+    }
+
+    /**
+     * @see DavResourceIterator#nextResource()
+     */
+    public DavResource nextResource() {
+        return next();
+    }
+
+    /**
+     * Returns the size of the initial list.
+     *
+     * @see DavResourceIterator#size()
+     */
+    public int size() {
+        return size;
+    }
+
+    /**
+     * @see DavResourceIterator#remove()
+     */
+    public void remove() {
+        throw new UnsupportedOperationException("Remove not allowed with DavResourceIteratorImpl");
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java
new file mode 100644
index 000000000..2a9b82270
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * <code>DavResourceLocator</code>...
+ */
+public interface DavResourceLocator {
+
+    /**
+     * Return the prefix used to build the complete href of the resource as
+     * required for the {@link DavConstants#XML_HREF href Xml} element.
+     * This includes scheme and host information as well as constant prefixes.
+     * However, this must not include workspace prefix.
+     *
+     * @return prefix needed in order to build the href from a resource path.
+     * @see #getResourcePath()
+     */
+    public String getPrefix();
+
+    /**
+     * Return the resource path.
+     *
+     * @return resource path
+     */
+    public String getResourcePath();
+
+    /**
+     * Return the path of the workspace the resource identified by this
+     * locator is member of.
+     *
+     * @return path of the workspace
+     */
+    public String getWorkspacePath();
+
+    /**
+     * Return the name of the workspace the resource identified by this
+     * locator is member of.
+     *
+     * @return workspace name
+     */
+    public String getWorkspaceName();
+
+    /**
+     * Returns true if the specified locator refers to a resource within the
+     * same workspace.
+     *
+     * @param locator
+     * @return true if both paths are in the same workspace.
+     */
+    public boolean isSameWorkspace(DavResourceLocator locator);
+
+    /**
+     * Returns true if the specified workspace name equals to the workspace
+     * name defined with this locator.
+     *
+     * @param workspaceName
+     * @return true if workspace names are equal.
+     */
+    public boolean isSameWorkspace(String workspaceName);
+
+    /**
+     * Return the 'href' representation of this locator object. The implementation
+     * should perform an URL encoding of the resource path.
+     *
+     * @param isCollection
+     * @return 'href' representation of this path
+     * @see DavConstants#XML_HREF
+     * @see DavResource#getHref()
+     */
+    public String getHref(boolean isCollection);
+
+    /**
+     * Returns true if this <code>DavResourceLocator</code> represents the root
+     * locator that would be requested with 'hrefPrefix'+'pathPrefix' with or
+     * without a trailing '/'.
+     *
+     * @return true if this locator object belongs to the root resource.
+     */
+    public boolean isRootLocation();
+
+    /**
+     * Return the locator factory that created this locator.
+     *
+     * @return the locator factory
+     */
+    public DavLocatorFactory getFactory();
+
+    /**
+     * An implementation may choose to circumvent the incompatibility of a
+     * repository path with the URI path by applying an appropriate conversion.
+     * This utility method allows to retrieve this transformed repository path.
+     * By default this method should return the same as {@link #getResourcePath()}
+     *
+     * @return a repository compatible form if the resource path.
+     * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean)
+     * that allows to build a valid <code>DavResourceLocator</code> from a given
+     * repository path.
+     */
+    public String getRepositoryPath();
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java
new file mode 100644
index 000000000..e26f0cdcb
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+import org.w3c.dom.Document;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * <code>DavServletRequest</code> extends the HttpServletRequest by Webdav
+ * specific METHODS.
+ */
+public interface DavServletRequest extends HttpServletRequest {
+
+    /**
+     * Sets the <code>DavSession</code> to this request.
+     *
+     * @param session
+     */
+    public void setDavSession(DavSession session);
+
+    /**
+     * Returns the {@link DavSession} created for this request.
+     *
+     * @return session for this resource
+     */
+    public DavSession getDavSession();
+
+    /**
+     * Return the locator of the requested {@link DavResource resource}.
+     *
+     * @return locator of the requested {@link DavResource resource}.
+     */
+    public DavResourceLocator getRequestLocator();
+
+    /**
+     * Parse the {@link DavConstants#HEADER_DESTINATION Destination header}
+     * and return the locator of the corresponding {@link DavResource resource}.
+     *
+     * @return locator of the resource specified with the Destination header.
+     * @see DavConstants#HEADER_DESTINATION
+     */
+    public DavResourceLocator getDestinationLocator() throws DavException;
+
+    /**
+     * Returns true if the {@link DavConstants#HEADER_OVERWRITE Overwrite header}
+     * is set to 'T' thus instructing the server to overwrite the state of a
+     * non-null destination resource during a COPY or MOVE. A Overwrite header
+     * value of 'F' will return false.
+     *
+     * @return true if the Overwrite header is set to 'T', false if it is set
+     * to 'F'.
+     * @see DavConstants#HEADER_OVERWRITE
+     */
+    public boolean isOverwrite();
+
+    /**
+     * Return the integer representation of the given {@link DavConstants#HEADER_DEPTH
+     * Depth header}. 'Infinity' is represented by {@link DavConstants#DEPTH_INFINITY}.
+     *
+     * @return integer representation of the {@link DavConstants#HEADER_DEPTH
+     * Depth header}.
+     * @see DavConstants#HEADER_DEPTH
+     */
+    public int getDepth();
+
+    /**
+     * Returns the integer representation of the {@link DavConstants#HEADER_DEPTH
+     * Depth header} or the given defaultValue, if the Depth header is missing.
+     *
+     * @param defaultValue to be returned if no Depth header is present.
+     * @return integer representation of the {@link DavConstants#HEADER_DEPTH
+     * Depth header} or the given defaultValue.
+     * @see DavConstants#HEADER_DEPTH
+     */
+    public int getDepth(int defaultValue);
+
+    /**
+     * Returns the token present in the {@link DavConstants#HEADER_LOCK_TOKEN
+     * Lock-Token Header} or <code>null</code> if no such header is available.<br>
+     * Note: The 'Lock-Token' header is sent with UNLOCK requests and with
+     * lock responses only. For any other request that may be affected by a lock
+     * the 'If' header field is responsible.
+     *
+     * @return the token present in the Lock-Token header.
+     * @see DavConstants#HEADER_LOCK_TOKEN
+     */
+    public String getLockToken();
+
+    /**
+     * Return the timeout requested in the {@link DavConstants#HEADER_TIMEOUT
+     * Timeout header} as <code>long</code>. The representation of the
+     * 'Infinite' timeout is left to the implementation.
+     *
+     * @return long value representation of the Timeout header.
+     * @see DavConstants#HEADER_TIMEOUT
+     * @see DavConstants#TIMEOUT_INFINITE
+     */
+    public long getTimeout();
+
+    /**
+     * Parse the Xml request body and return a {@link org.w3c.dom.Document}.
+     *
+     * @return Document representing the Xml request body or <code>null</code>
+     * if no request body is present.
+     * @throws DavException If the request body cannot be parsed into an Xml
+     * Document.
+     */
+    public Document getRequestDocument() throws DavException;
+
+    /**
+     * Return the type of PROPFIND request as indicated by the PROPFIND request
+     * body.
+     *
+     * @return type of PROPFIND request
+     * @see DavConstants#PROPFIND_ALL_PROP
+     * @see DavConstants#PROPFIND_BY_PROPERTY
+     * @see DavConstants#PROPFIND_PROPERTY_NAMES
+     * @see DavConstants#PROPFIND_ALL_PROP_INCLUDE
+     * @throws DavException If the propfind type could not be determined due to
+     * an invalid request body.
+     */
+    public int getPropFindType() throws DavException;
+
+    /**
+     * Return the set of properties the client requested with a PROPFIND request
+     * or an empty set if the type of PROPFIND request was {@link DavConstants#PROPFIND_ALL_PROP}
+     * or {@link DavConstants#PROPFIND_PROPERTY_NAMES}.
+     *
+     * @return set of properties the client requested with a PROPFIND request
+     * @throws DavException In case of invalid request body
+     */
+    public DavPropertyNameSet getPropFindProperties() throws DavException;
+
+    /**
+     * Return a {@link List} of property change operations. Each entry
+     * is either of type {@link DavPropertyName}, indicating a &lt;remove&gt;
+     * operation, or of type {@link DavProperty}, indicating a &lt;set&gt;
+     * operation. Note that ordering is significant here.
+     *
+     * @return {@link List} of property change operations
+     * @throws DavException In case of invalid request body
+     */
+    public List<? extends PropEntry> getPropPatchChangeList() throws DavException;
+
+    /**
+     * Return the parsed 'lockinfo' request body, the {@link DavConstants#HEADER_TIMEOUT
+     * Timeout header} and the {@link DavConstants#HEADER_DEPTH Depth header}
+     * of a LOCK request as <code>LockInfo</code> object.
+     *
+     * @return <code>LockInfo</code> object encapsulating the information
+     * present in the LOCK request.
+     * @see DavConstants#HEADER_TIMEOUT
+     * @see DavConstants#HEADER_DEPTH
+     * @see DavConstants#XML_LOCKINFO
+     * @throws DavException
+     */
+    public LockInfo getLockInfo() throws DavException;
+
+    /**
+     * Returns true, if the {@link DavConstants#HEADER_IF If header} present
+     * with the request matches the given resource.
+     *
+     * @param resource
+     * @return true, if the test is successful, false otherwise.
+     */
+    public boolean matchesIfHeader(DavResource resource);
+
+    /**
+     * Returns true, if the {@link DavConstants#HEADER_IF If header} present
+     * with the request matches to the given href, token and eTag.
+     *
+     * @param href
+     * @param token
+     * @param eTag
+     * @return true, if the test is successful, false otherwise.
+     */
+    public boolean matchesIfHeader(String href, String token, String eTag);
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java
new file mode 100644
index 000000000..452b974e6
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * <code>WebdavResponse</code> extends the HttpServletResponse by
+ * Webdav specific status codes and METHODS.
+ */
+public interface DavServletResponse extends HttpServletResponse {
+
+    /**
+     * The 102 (Processing) status code is an interim response used to
+     * inform the client that the server has accepted the complete request,
+     * but has not yet completed it.
+     */
+    int SC_PROCESSING = 102;
+
+    /**
+     * Status code (207) indicating that the response requires
+     * providing status for multiple independent operations.
+     */
+    int SC_MULTI_STATUS = 207;
+
+    /**
+     * The 422 (Unprocessable Entity) status code means the server understands
+     * the content type of the request entity (hence a 415(Unsupported Media Type)
+     * status code is inappropriate), and the syntax of the request entity is
+     * correct (thus a 400 (Bad Request) status code is inappropriate) but was
+     * unable to process the contained instructions. For example, this error
+     * condition may occur if an XML request body contains well-formed (i.e.,
+     * syntactically correct), but semantically erroneous XML instructions.
+     */
+    int SC_UNPROCESSABLE_ENTITY = 422;
+
+    /**
+     * Status code (423) indicating the destination resource of a
+     * method is locked, and either the request did not contain a
+     * valid Lock-Info header, or the Lock-Info header identifies
+     * a lock held by another principal.
+     */
+    int SC_LOCKED = 423;
+
+    /**
+     * Status code (424) indicating that the method could not be
+     * performed on the resource, because the requested action depended
+     * on another action which failed.
+     */
+    int SC_FAILED_DEPENDENCY = 424;
+
+    /**
+     * Status code (507) indicating that the resource does not have
+     * sufficient space to record the state of the resource after the
+     * execution of this method.
+     */
+    int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 507;
+
+    /**
+     * Send a response body given more detailed information about the error
+     * occurred.
+     *
+     * @param error
+     * @throws IOException
+     */
+    public void sendError(DavException error) throws IOException;
+
+    /**
+     * Send the multistatus response to the client. A multistatus response
+     * is returned in response to a successful PROPFIND and PROPPATCH request.
+     * In addition multistatus response is required response in case a COPY,
+     * MOVE, DELETE, LOCK or PROPPATCH request fails.
+     *
+     * @param multistatus
+     * @throws IOException
+     * @see #SC_MULTI_STATUS
+     */
+    public void sendMultiStatus(MultiStatus multistatus) throws IOException;
+
+    /**
+     * Send the multistatus response to the client. A multistatus response
+     * is returned in response to a successful PROPFIND and PROPPATCH request.
+     * In addition multistatus response is required response in case a COPY,
+     * MOVE, DELETE, LOCK or PROPPATCH request fails.
+     *
+     * @param multistatus
+     * @param acceptableContentCodings content codings accepted by the client
+     * @throws IOException
+     * @see #SC_MULTI_STATUS
+     */
+    default void sendMultiStatus(MultiStatus multistatus, List<String> acceptableContentCodings) throws IOException {
+        sendMultiStatus(multistatus);
+    }
+
+    /**
+     * Send the lock response for a successful LOCK request, that was intended
+     * to refresh an existing lock. The locks array must contain at least
+     * a single element; the <code>ActiveLock</code> objects are then
+     * included in the lockdiscovery property of the response body as required
+     * by RFC 2518.
+     *
+     * @param locks
+     * @throws IOException
+     * @see DavConstants#PROPERTY_LOCKDISCOVERY
+     */
+    public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException;
+
+    /**
+     * Generic method to return an Xml response body.
+     *
+     * @param serializable object that can be converted to the root Xml element
+     * of the document to be sent as response body.
+     * @param status Status code to be used with {@link #setStatus(int)}.
+     * @throws IOException
+     */
+    public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException;
+
+    /**
+     * Generic method to return an Xml response body.
+     *
+     * @param serializable object that can be converted to the root Xml element
+     * of the document to be sent as response body.
+     * @param status Status code to be used with {@link #setStatus(int)}.
+     * @param acceptableContentCodings content codings accepted by the client
+     * @throws IOException
+     */
+    default void sendXmlResponse(XmlSerializable serializable, int status, List<String> acceptableContentCodings) throws IOException {
+        sendXmlResponse(serializable, status);
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavSession.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavSession.java
new file mode 100644
index 000000000..90cc43e0a
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavSession.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * <code>DavSession</code> allows to pass session information between request,
+ * response and resource(s).
+ */
+public interface DavSession {
+
+    /**
+     * Adds a reference to this <code>DavSession</code> indicating that this
+     * session must not be discarded after completion of the current request.
+     *
+     * @param reference to be added.
+     */
+    public void addReference(Object reference);
+
+    /**
+     * Releasing a reference to this <code>DavSession</code>. If no more
+     * references are present, this session may be discarded.
+     *
+     * @param reference to be removed.
+     */
+    public void removeReference(Object reference);
+
+    /**
+     * Adds a lock token to this <code>DavSession</code>.
+     *
+     * @param token
+     */
+    public void addLockToken(String token);
+
+    /**
+     * Returns the lock tokens of this <code>DavSession</code>.
+     *
+     * @return
+     */
+    public String[] getLockTokens();
+
+    /**
+     * Removes a lock token from this <code>DavSession</code>.
+     *
+     * @param token
+     */
+    public void removeLockToken(String token);
+
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java
new file mode 100644
index 000000000..ff1f7062d
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * <code>DavSessionProvider</code> is an interface for components that
+ * can initiate and complete {@link DavSession}s. A provider is
+ * responsible for supplying references from a {@link WebdavRequest}
+ * to a {@link DavSession} when acquired and removing the references
+ * when released.
+
+ */
+public interface DavSessionProvider {
+
+    /**
+     * Acquires a DavSession. Upon success, the WebdavRequest will
+     * reference that session.
+     *
+     * A session will not be available if an exception is thrown.
+     *
+     * @param request
+     * @return <code>true</code> if the session was attached to the request;
+     *         <code>false</code> otherwise.
+     * @throws DavException if a problem occurred while obtaining the session
+     */
+    public boolean attachSession(WebdavRequest request) throws DavException;
+
+    /**
+     * Releases the reference from the request to the session.
+     *
+     * @param request
+     */
+    public void releaseSession(WebdavRequest request);
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java
new file mode 100644
index 000000000..79536b628
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * MultiStatus representing the content of a multistatus response body and
+ * allows to retrieve the Xml representation.
+ */
+public class MultiStatus implements DavConstants, XmlSerializable {
+
+    /**
+     * Map collecting the responses for this multistatus, where every href must
+     * only occur one single time.
+     */
+    private Map<String, MultiStatusResponse> responses = new LinkedHashMap<String, MultiStatusResponse>();
+
+    /**
+     * A general response description at the multistatus top level is used to
+     * provide a general message describing the overarching nature of the response.
+     * If this value is available an application may use it instead of
+     * presenting the individual response descriptions contained within the
+     * responses.
+     */
+    private String responseDescription;
+
+    /**
+     * Add response(s) to this multistatus, in order to build a multistatus for
+     * responding to a PROPFIND request.
+     *
+     * @param resource The resource to add property from
+     * @param propNameSet The requested property names of the PROPFIND request
+     * @param propFindType
+     * @param depth
+     */
+    public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet,
+                                      int propFindType, int depth) {
+        addResponse(new MultiStatusResponse(resource, propNameSet, propFindType));
+        if (depth > 0 && resource.isCollection()) {
+            DavResourceIterator iter = resource.getMembers();
+            while (iter.hasNext()) {
+                addResourceProperties(iter.nextResource(), propNameSet, propFindType, depth-1);
+            }
+        }
+    }
+
+    /**
+     * Add response(s) to this multistatus, in order to build a multistatus e.g.
+     * in order to respond to a PROPFIND request. Please note, that in terms
+     * of PROPFIND, this method would correspond to a
+     * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type.
+     *
+     * @param resource The resource to add property from
+     * @param propNameSet The requested property names of the PROPFIND request
+     * @param depth
+     * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for
+     * the corresponding method that allows to specify the type.
+     */
+    public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet,
+                                      int depth) {
+        addResourceProperties(resource, propNameSet, PROPFIND_BY_PROPERTY, depth);
+    }
+
+    /**
+     * Add response(s) to this multistatus, in order to build a multistatus
+     * as returned for COPY, MOVE, LOCK or DELETE requests resulting in an error
+     * with a resource other than the resource identified in the Request-URI.
+     *
+     * @param resource
+     * @param status
+     * @param depth
+     */
+    public void addResourceStatus(DavResource resource, int status, int depth) {
+        addResponse(new MultiStatusResponse(resource.getHref(), status));
+        if (depth > 0 && resource.isCollection()) {
+            DavResourceIterator iter = resource.getMembers();
+            while (iter.hasNext()) {
+                addResourceStatus(iter.nextResource(), status, depth-1);
+            }
+        }
+    }
+
+    /**
+     * Add a <code>MultiStatusResponse</code> element to this <code>MultiStatus</code>
+     * <p>
+     * This method is synchronized to avoid the problem described in
+     * <a href="https://issues.apache.org/jira/browse/JCR-2755">JCR-2755</a>.
+     *
+     * @param response
+     */
+    public synchronized void addResponse(MultiStatusResponse response) {
+        responses.put(response.getHref(), response);
+    }
+
+    /**
+     * Returns the multistatus responses present as array.
+     * <p>
+     * This method is synchronized to avoid the problem described in
+     * <a href="https://issues.apache.org/jira/browse/JCR-2755">JCR-2755</a>.
+     *
+     * @return array of all {@link MultiStatusResponse responses} present in this
+     * multistatus.
+     */
+    public synchronized MultiStatusResponse[] getResponses() {
+        return responses.values().toArray(new MultiStatusResponse[responses.size()]);
+    }
+
+    /**
+     * Set the response description.
+     *
+     * @param responseDescription
+     */
+    public void setResponseDescription(String responseDescription) {
+        this.responseDescription = responseDescription;
+    }
+
+    /**
+     * Returns the response description.
+     *
+     * @return responseDescription
+     */
+    public String getResponseDescription() {
+        return responseDescription;
+    }
+
+    /**
+     * Return the Xml representation of this <code>MultiStatus</code>.
+     *
+     * @return Xml document
+     * @param document
+     */
+    public Element toXml(Document document) {
+        Element multistatus = DomUtil.createElement(document, XML_MULTISTATUS, NAMESPACE);
+        for (MultiStatusResponse resp : getResponses()) {
+            multistatus.appendChild(resp.toXml(document));
+        }
+        if (responseDescription != null) {
+            Element respDesc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE, responseDescription);
+            multistatus.appendChild(respDesc);
+        }
+        return multistatus;
+    }
+
+    /**
+     * Build a <code>MultiStatus</code> from the specified xml element.
+     *
+     * @param multistatusElement
+     * @return new <code>MultiStatus</code> instance.
+     * @throws IllegalArgumentException if the given document is <code>null</code>
+     * or does not provide the required element.
+     */
+    public static MultiStatus createFromXml(Element multistatusElement) {
+        if (!DomUtil.matches(multistatusElement, XML_MULTISTATUS, NAMESPACE)) {
+            throw new IllegalArgumentException("DAV:multistatus element expected.");
+        }
+
+        MultiStatus multistatus = new MultiStatus();
+
+        ElementIterator it = DomUtil.getChildren(multistatusElement, XML_RESPONSE, NAMESPACE);
+        while (it.hasNext()) {
+            Element respElem = it.nextElement();
+            MultiStatusResponse response = MultiStatusResponse.createFromXml(respElem);
+            multistatus.addResponse(response);
+        }
+
+        // optional response description on the multistatus element
+        multistatus.setResponseDescription(DomUtil.getChildText(multistatusElement, XML_RESPONSEDESCRIPTION, NAMESPACE));
+        return multistatus;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java
new file mode 100644
index 000000000..a0a5d0d7c
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java
@@ -0,0 +1,486 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
+import org.apache.jackrabbit.webdav.property.PropContainer;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <code>MultiStatusResponse</code> represents the DAV:multistatus element defined
+ * by RFC 2518:
+ * <pre>
+ * &lt;!ELEMENT response (href, ((href*, status)|(propstat+)), responsedescription?) &gt;
+ * &lt;!ELEMENT status (#PCDATA) &gt;
+ * &lt;!ELEMENT propstat (prop, status, responsedescription?) &gt;
+ * &lt;!ELEMENT responsedescription (#PCDATA) &gt;
+ * &lt;!ELEMENT prop ANY &gt;
+ * </pre>
+ */
+public class MultiStatusResponse implements XmlSerializable, DavConstants {
+
+    private static final int TYPE_PROPSTAT = 0;
+    private static final int TYPE_HREFSTATUS = 1;
+
+    /**
+     * The type of MultiStatusResponse
+     */
+    private final int type;
+
+    /**
+     * The content the 'href' element for this response
+     */
+    private final String href;
+
+    /**
+     * An optional response description.
+     */
+    private final String responseDescription;
+
+    /**
+     * Type of MultiStatus response: Href + Status
+     */
+    private Status status;
+
+    /**
+     * Type of MultiStatus response: PropStat Hashmap containing all status
+     */
+    private HashMap<Integer, PropContainer> statusMap = new HashMap<Integer, PropContainer>();
+
+    private MultiStatusResponse(String href, String responseDescription, int type) {
+        if (!isValidHref(href)) {
+            throw new IllegalArgumentException("Invalid href ('" + href + "')");
+        }
+        this.href = href;
+        this.responseDescription = responseDescription;
+        this.type = type;
+    }
+
+    /**
+     * Constructs an WebDAV multistatus response
+     *
+     * @param href
+     * @param status
+     * @param responseDescription
+     */
+    public MultiStatusResponse(String href, Status status, String responseDescription) {
+        this(href, responseDescription, TYPE_HREFSTATUS);
+        if (status == null) {
+            throw new IllegalArgumentException("Status must not be null in case of a multistatus reponse that consists of href + status only.");
+        }
+        this.status = status;
+    }
+
+    /**
+     * Constructs an WebDAV multistatus response for a given resource. This
+     * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in
+     * case of error with a resource other than the resource identified in the
+     * Request-URI.<br>
+     * The response description is set to <code>null</code>.
+     *
+     * @param href
+     * @param statusCode
+     */
+    public MultiStatusResponse(String href, int statusCode) {
+        this(href, statusCode, null);
+    }
+
+    /**
+     * Constructs an WebDAV multistatus response for a given resource. This
+     * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in
+     * case of error with a resource other than the resource identified in the
+     * Request-URI.
+     *
+     * @param href
+     * @param statusCode
+     * @param responseDescription
+     */
+    public MultiStatusResponse(String href, int statusCode, String responseDescription) {
+        this(href, new Status(statusCode), responseDescription);
+    }
+
+    /**
+     * Constructs an empty WebDAV multistatus response of type 'PropStat'
+     */
+    public MultiStatusResponse(String href, String responseDescription) {
+        this(href, responseDescription, TYPE_PROPSTAT);
+    }
+
+    /**
+     * Constructs a WebDAV multistatus response and retrieves the resource
+     * properties according to the given <code>DavPropertyNameSet</code>.
+     *
+     * @param resource
+     * @param propNameSet
+     */
+    public MultiStatusResponse(DavResource resource, DavPropertyNameSet propNameSet) {
+        this(resource, propNameSet, PROPFIND_BY_PROPERTY);
+    }
+
+    /**
+     * Constructs a WebDAV multistatus response and retrieves the resource
+     * properties according to the given <code>DavPropertyNameSet</code>. It
+     * adds all known property to the '200' set, while unknown properties are
+     * added to the '404' set.
+     * <p>
+     * Note, that the set of property names is ignored in case of a {@link
+     * #PROPFIND_ALL_PROP} and {@link #PROPFIND_PROPERTY_NAMES} propFindType.
+     *
+     * @param resource The resource to retrieve the property from
+     * @param propNameSet The property name set as obtained from the request
+     * body.
+     * @param propFindType any of the following values: {@link
+     * #PROPFIND_ALL_PROP}, {@link #PROPFIND_BY_PROPERTY}, {@link
+     * #PROPFIND_PROPERTY_NAMES}, {@link #PROPFIND_ALL_PROP_INCLUDE}
+     */
+    public MultiStatusResponse(
+            DavResource resource, DavPropertyNameSet propNameSet,
+            int propFindType) {
+        this(resource.getHref(), null, TYPE_PROPSTAT);
+
+        if (propFindType == PROPFIND_PROPERTY_NAMES) {
+            // only property names requested
+            PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true);
+            for (DavPropertyName propName : resource.getPropertyNames()) {
+                status200.addContent(propName);
+            }
+        } else {
+            // all or a specified set of property and their values requested.
+            PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false);
+
+            // Collection of missing property names for 404 responses
+            Set<DavPropertyName> missing = new HashSet<DavPropertyName>(propNameSet.getContent());
+
+            // Add requested properties or all non-protected properties,
+            // or non-protected properties plus requested properties (allprop/include) 
+            if (propFindType == PROPFIND_BY_PROPERTY) {
+                // add explicitly requested properties (proptected or non-protected)
+                for (DavPropertyName propName : propNameSet) {
+                    DavProperty<?> prop = resource.getProperty(propName);
+                    if (prop != null) {
+                        status200.addContent(prop);
+                        missing.remove(propName);
+                    }
+                }
+            } else {
+                // add all non-protected properties
+                for (DavProperty<?> property : resource.getProperties()) {
+                    boolean allDeadPlusRfc4918LiveProperties =
+                        propFindType == PROPFIND_ALL_PROP
+                        || propFindType == PROPFIND_ALL_PROP_INCLUDE;
+                    boolean wasRequested = missing.remove(property.getName());
+
+                    if ((allDeadPlusRfc4918LiveProperties
+                            && !property.isInvisibleInAllprop())
+                            || wasRequested) {
+                        status200.addContent(property);
+                    }
+                }
+
+                // try if missing properties specified in the include section
+                // can be obtained using resource.getProperty
+                if (propFindType == PROPFIND_ALL_PROP_INCLUDE && !missing.isEmpty()) {
+                    for (DavPropertyName propName : new HashSet<DavPropertyName>(missing)) {
+                        DavProperty<?> prop = resource.getProperty(propName);
+                        if (prop != null) {
+                            status200.addContent(prop);
+                            missing.remove(propName);
+                        }
+                    }
+                }
+            }
+
+            if (!missing.isEmpty() && propFindType != PROPFIND_ALL_PROP) {
+                PropContainer status404 = getPropContainer(DavServletResponse.SC_NOT_FOUND, true);
+                for (DavPropertyName propName : missing) {
+                    status404.addContent(propName);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the href
+     *
+     * @return href
+     * @see MultiStatusResponse#getHref()
+     */
+    public String getHref() {
+        return href;
+    }
+
+    /**
+     * @return responseDescription
+     * @see MultiStatusResponse#getResponseDescription()
+     */
+    public String getResponseDescription() {
+        return responseDescription;
+    }
+
+    /**
+     * Return an array listing all 'status' available is this response object.
+     * Note, that a the array contains a single element if this
+     * <code>MultiStatusResponse</code> defines an response consisting of
+     * href and status elements.
+     *
+     * @return
+     */
+    public Status[] getStatus() {
+        Status[] sts;
+        if (type == TYPE_PROPSTAT) {
+            sts = new Status[statusMap.size()];
+            Iterator<Integer> iter = statusMap.keySet().iterator();
+            for (int i = 0; iter.hasNext(); i++) {
+                Integer statusKey = iter.next();
+                sts[i] = new Status(statusKey);
+            }
+        } else {
+            sts = new Status[] {status};
+        }
+        return sts;
+    }
+
+    /**
+     * @return {@code true} if the response is of type "propstat" (containing information about individual properties)
+     */
+    public boolean isPropStat() {
+        return this.type == TYPE_PROPSTAT;
+    }
+
+    /**
+     * @param document
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element response = DomUtil.createElement(document, XML_RESPONSE, NAMESPACE);
+        // add '<href>'
+        response.appendChild(DomUtil.hrefToXml(getHref(), document));
+        if (type == TYPE_PROPSTAT) {
+            // add '<propstat>' elements
+            for (Integer statusKey : statusMap.keySet()) {
+                Status st = new Status(statusKey);
+                PropContainer propCont = statusMap.get(statusKey);
+                if (!propCont.isEmpty()) {
+                    Element propstat = DomUtil.createElement(document, XML_PROPSTAT, NAMESPACE);
+                    propstat.appendChild(propCont.toXml(document));
+                    propstat.appendChild(st.toXml(document));
+                    response.appendChild(propstat);
+                }
+            }
+        } else {
+            // add a single '<status>' element
+            // NOTE: a href+status response cannot be created with 'null' status
+            response.appendChild(status.toXml(document));
+        }
+        // add the optional '<responsedescription>' element
+        String description = getResponseDescription();
+        if (description != null) {
+            Element desc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE);
+            DomUtil.setText(desc, description);
+            response.appendChild(desc);
+        }
+        return response;
+    }
+    //----------------------------------------------< type specific methods >---
+    /**
+     * Adds a property to this response '200' propstat set.
+     *
+     * @param property the property to add
+     */
+    public void add(DavProperty<?> property) {
+        checkType(TYPE_PROPSTAT);
+        PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false);
+        status200.addContent(property);
+    }
+
+    /**
+     * Adds a property name to this response '200' propstat set.
+     *
+     * @param propertyName the property name to add
+     */
+    public void add(DavPropertyName propertyName) {
+        checkType(TYPE_PROPSTAT);
+        PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true);
+        status200.addContent(propertyName);
+    }
+
+    /**
+     * Adds a property to this response
+     *
+     * @param property the property to add
+     * @param status the status of the response set to select
+     */
+    public void add(DavProperty<?> property, int status) {
+        checkType(TYPE_PROPSTAT);
+        PropContainer propCont = getPropContainer(status, false);
+        propCont.addContent(property);
+    }
+
+    /**
+     * Adds a property name to this response
+     *
+     * @param propertyName the property name to add
+     * @param status the status of the response set to select
+     */
+    public void add(DavPropertyName propertyName, int status) {
+        checkType(TYPE_PROPSTAT);
+        PropContainer propCont = getPropContainer(status, true);
+        propCont.addContent(propertyName);
+    }
+
+    /**
+     * @param status
+     * @return
+     */
+    private PropContainer getPropContainer(int status, boolean forNames) {
+        PropContainer propContainer = statusMap.get(status);
+        if (propContainer == null) {
+            if (forNames) {
+                propContainer = new DavPropertyNameSet();
+            } else {
+                propContainer = new DavPropertySet();
+            }
+            statusMap.put(status, propContainer);
+        }
+        return propContainer;
+    }
+
+    private void checkType(int type) {
+        if (this.type != type) {
+            throw new IllegalStateException("The given MultiStatusResponse is not of the required type.");
+        }
+    }
+
+    /**
+     * Get properties present in this response for the given status code. In
+     * case this MultiStatusResponse does not represent a 'propstat' response,
+     * always an empty {@link DavPropertySet} will be returned.
+     *
+     * @param status
+     * @return property set
+     */
+    public DavPropertySet getProperties(int status) {
+        if (statusMap.containsKey(status)) {
+            PropContainer mapEntry = statusMap.get(status);
+            if (mapEntry != null && mapEntry instanceof DavPropertySet) {
+                return (DavPropertySet) mapEntry;
+            }
+        }
+        return new DavPropertySet();
+    }
+
+    /**
+     * Get property names present in this response for the given status code. In
+     * case this MultiStatusResponse does not represent a 'propstat' response,
+     * always an empty {@link DavPropertyNameSet} will be returned.
+     *
+     * @param status
+     * @return property names
+     */
+    public DavPropertyNameSet getPropertyNames(int status) {
+        if (statusMap.containsKey(status)) {
+            PropContainer mapEntry = statusMap.get(status);
+            if (mapEntry != null) {
+                if (mapEntry instanceof DavPropertySet) {
+                    DavPropertyNameSet set = new DavPropertyNameSet();
+                    for (DavPropertyName name : ((DavPropertySet) mapEntry).getPropertyNames()) {
+                        set.add(name);
+                    }
+                    return set;
+                } else {
+                    // is already a DavPropertyNameSet
+                    return (DavPropertyNameSet) mapEntry;
+                }
+            }
+        }
+        return new DavPropertyNameSet();
+    }
+
+    /**
+     * Build a new response object from the given xml element.
+     *
+     * @param responseElement
+     * @return new <code>MultiStatusResponse</code> instance
+     * @throws IllegalArgumentException if the specified element is
+     * <code>null</code> or not a DAV:response element or if the mandatory
+     * DAV:href child is missing.
+     */
+    public static MultiStatusResponse createFromXml(Element responseElement) {
+        if (!DomUtil.matches(responseElement, XML_RESPONSE, NAMESPACE)) {
+            throw new IllegalArgumentException("DAV:response element required.");
+        }
+        String href = DomUtil.getChildTextTrim(responseElement, XML_HREF, NAMESPACE);
+        if (href == null) {
+            throw new IllegalArgumentException("DAV:response element must contain a DAV:href element expected.");
+        }
+        String statusLine = DomUtil.getChildText(responseElement, XML_STATUS, NAMESPACE);
+        String responseDescription = DomUtil.getChildText(responseElement, XML_RESPONSEDESCRIPTION, NAMESPACE);
+
+        MultiStatusResponse response;
+        if (statusLine != null) {
+            Status status = Status.parse(statusLine);
+            response = new MultiStatusResponse(href, status, responseDescription);
+        } else {
+            response = new MultiStatusResponse(href, responseDescription, TYPE_PROPSTAT);
+            // read propstat elements
+            ElementIterator it = DomUtil.getChildren(responseElement, XML_PROPSTAT, NAMESPACE);
+            while (it.hasNext()) {
+                Element propstat = it.nextElement();
+                String propstatus = DomUtil.getChildText(propstat, XML_STATUS, NAMESPACE);
+                Element prop = DomUtil.getChildElement(propstat, XML_PROP, NAMESPACE);
+                if (propstatus != null && prop != null) {
+                    int statusCode = Status.parse(propstatus).getStatusCode();
+                    ElementIterator propIt = DomUtil.getChildren(prop);
+                    while (propIt.hasNext()) {
+                        Element el = propIt.nextElement();
+                        /*
+                        always build dav property from the given element, since
+                        distinction between prop-names and properties not having
+                        a value is not possible.
+                        retrieval of the set of 'property names' is possible from
+                        the given prop-set by calling DavPropertySet#getPropertyNameSet()
+                        */
+                        DavProperty<?> property = DefaultDavProperty.createFromXml(el);
+                        response.add(property, statusCode);
+                    }
+                }
+            }
+        }
+        return response;
+    }
+
+    /**
+     * @param href
+     * @return false if the given href is <code>null</code> or empty string.
+     */
+    private static boolean isValidHref(String href) {
+        return href != null && !"".equals(href);
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/Status.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/Status.java
new file mode 100644
index 000000000..4357416cc
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/Status.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import java.util.Locale;
+
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * <code>Status</code> encapsulating the 'status' present in multistatus
+ * responses.
+ */
+public class Status implements DavConstants, XmlSerializable{
+
+    private static Logger log = LoggerFactory.getLogger(Status.class);
+
+    private final String version;
+    private final int code;
+    private final String phrase;
+
+    public Status(int code) {
+        version = "HTTP/1.1";
+        this.code = code;
+        phrase = DavException.getStatusPhrase(code);
+    }
+
+    public Status(String version, int code, String phrase) {
+        this.version = version;
+        this.code = code;
+        this.phrase = phrase;
+    }
+
+    public int getStatusCode() {
+        return code;
+    }
+
+    /**
+     * @see XmlSerializable#toXml(Document)
+     */
+    public Element toXml(Document document) {
+        String statusLine = version + " " + code + " " + phrase;
+        Element e = DomUtil.createElement(document, XML_STATUS, NAMESPACE);
+        DomUtil.setText(e, statusLine);
+        return e;
+    }
+
+    /**
+     * Parse the given status line and return a new <code>Status</code> object.
+     *
+     * @param statusLine
+     * @return a new <code>Status</code>
+     */
+    public static Status parse(String statusLine) {
+        if (statusLine == null) {
+            throw new IllegalArgumentException("Unable to parse status line from null xml element.");
+        }
+        Status status;
+
+        // code copied from org.apache.commons.httpclient.StatusLine
+        int length = statusLine.length();
+        int at = 0;
+        int start = 0;
+        try {
+            while (Character.isWhitespace(statusLine.charAt(at))) {
+                ++at;
+                ++start;
+            }
+            if (!"HTTP".equals(statusLine.substring(at, at += 4))) {
+                log.warn("Status-Line '" + statusLine + "' does not start with HTTP");
+            }
+            //handle the HTTP-Version
+            at = statusLine.indexOf(' ', at);
+            if (at <= 0) {
+                log.warn("Unable to parse HTTP-Version from the status line: '" + statusLine + "'");
+            }
+            String version = (statusLine.substring(start, at)).toUpperCase(Locale.ROOT);
+            //advance through spaces
+            while (statusLine.charAt(at) == ' ') {
+                at++;
+            }
+            //handle the Status-Code
+            int code;
+            int to = statusLine.indexOf(' ', at);
+            if (to < 0) {
+                to = length;
+            }
+            try {
+                code = Integer.parseInt(statusLine.substring(at, to));
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Unable to parse status code from status line: '" + statusLine + "'");
+            }
+            //handle the Reason-Phrase
+            String phrase = "";
+            at = to + 1;
+            if (at < length) {
+                phrase = statusLine.substring(at).trim();
+            }
+
+            status = new Status(version, code, phrase);
+
+        } catch (StringIndexOutOfBoundsException e) {
+            throw new IllegalArgumentException("Status-Line '" + statusLine + "' is not valid");
+        }
+        return status;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java
new file mode 100644
index 000000000..09aa79f88
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest;
+import org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest;
+import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest;
+import org.apache.jackrabbit.webdav.version.DeltaVServletRequest;
+import org.apache.jackrabbit.webdav.bind.BindServletRequest;
+
+/**
+ * The empty <code>WebdavRequest</code> interface collects the functionality
+ * defined by {@link org.apache.jackrabbit.webdav.DavServletRequest} encapsulating
+ * the core Webdav specification (RFC 2518) as well as the various extensions
+ * used for observation and transaction support, ordering of collections, search
+ * and versioning.
+ */
+public interface WebdavRequest extends DavServletRequest,
+        ObservationDavServletRequest, OrderingDavServletRequest,
+        TransactionDavServletRequest, DeltaVServletRequest,
+        BindServletRequest {
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java
new file mode 100644
index 000000000..c1de4183c
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+/**
+ * Interface providing the minimum WebDAV request information associated with the current thread of execution.
+ */
+public interface WebdavRequestContext {
+
+    /**
+     * Return the current {@link WebdavRequest} instance associated with the current thread of execution.
+     * @return the current {@link WebdavRequest} instance associated with the current thread of execution
+     */
+    public WebdavRequest getRequest();
+
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
new file mode 100644
index 000000000..493531394
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
@@ -0,0 +1,1324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletConnection;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import jakarta.servlet.http.HttpUpgradeHandler;
+import jakarta.servlet.http.Part;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.jackrabbit.webdav.bind.BindInfo;
+import org.apache.jackrabbit.webdav.bind.RebindInfo;
+import org.apache.jackrabbit.webdav.bind.UnbindInfo;
+import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
+import org.apache.jackrabbit.webdav.header.DepthHeader;
+import org.apache.jackrabbit.webdav.header.IfHeader;
+import org.apache.jackrabbit.webdav.header.LabelHeader;
+import org.apache.jackrabbit.webdav.header.OverwriteHeader;
+import org.apache.jackrabbit.webdav.header.PollTimeoutHeader;
+import org.apache.jackrabbit.webdav.header.TimeoutHeader;
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.lock.Scope;
+import org.apache.jackrabbit.webdav.lock.Type;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
+import org.apache.jackrabbit.webdav.ordering.OrderPatch;
+import org.apache.jackrabbit.webdav.ordering.OrderingConstants;
+import org.apache.jackrabbit.webdav.ordering.Position;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet;
+import org.apache.jackrabbit.webdav.transaction.TransactionConstants;
+import org.apache.jackrabbit.webdav.transaction.TransactionInfo;
+import org.apache.jackrabbit.webdav.version.LabelInfo;
+import org.apache.jackrabbit.webdav.version.MergeInfo;
+import org.apache.jackrabbit.webdav.version.OptionsInfo;
+import org.apache.jackrabbit.webdav.version.UpdateInfo;
+import org.apache.jackrabbit.webdav.version.report.ReportInfo;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+/**
+ * <code>WebdavRequestImpl</code>...
+ */
+public class WebdavRequestImpl implements WebdavRequest, DavConstants, ContentCodingAwareRequest {
+
+    private static Logger log = LoggerFactory.getLogger(WebdavRequestImpl.class);
+
+    private final HttpServletRequest httpRequest;
+    private final DavLocatorFactory factory;
+    private final IfHeader ifHeader;
+    private final String hrefPrefix;
+
+    private DavSession session;
+
+    private int propfindType = PROPFIND_ALL_PROP;
+    private DavPropertyNameSet propfindProps;
+    private DavPropertySet proppatchSet;
+    private List<PropEntry> proppatchList;
+
+    /**
+     * Creates a new <code>DavServletRequest</code> with the given parameters.
+     */
+    public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory) {
+        this(httpRequest, factory, true);
+    }
+
+    /**
+     * Creates a new <code>DavServletRequest</code> with the given parameters.
+     *
+     * @param httpRequest
+     * @param factory
+     * @param createAbsoluteURI defines if we must create a absolute URI. if false a absolute path will be created
+     */
+    public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory, boolean createAbsoluteURI) {
+        this.httpRequest = httpRequest;
+        this.factory = factory;
+        this.ifHeader = new IfHeader(httpRequest);
+
+        String host = getHeader("Host");
+        String scheme = getScheme();
+        String uriPrefix = scheme + "://" + host + getContextPath();
+        this.hrefPrefix = createAbsoluteURI ? uriPrefix : getContextPath();
+    }
+
+    /**
+     * Sets the session field and adds all lock tokens present with either the
+     * Lock-Token header or the If header to the given session object.
+     *
+     * @param session
+     * @see DavServletRequest#setDavSession(DavSession)
+     */
+    public void setDavSession(DavSession session) {
+        this.session = session;
+        // set lock-tokens from header to the current session
+        if (session != null) {
+            String lt = getLockToken();
+            if (lt != null) {
+                session.addLockToken(lt);
+            }
+            // add all token present in the the If header to the session as well.
+            Iterator<String> it = ifHeader.getAllTokens();
+            while (it.hasNext()) {
+                String ifHeaderToken = it.next();
+                session.addLockToken(ifHeaderToken);
+            }
+        }
+    }
+
+    /**
+     * @see DavServletRequest#getDavSession()
+     */
+    public DavSession getDavSession() {
+        return session;
+    }
+
+    /**
+     * Return a <code>DavResourceLocator</code> representing the request handle.
+     *
+     * @return locator of the requested resource
+     * @see DavServletRequest#getRequestLocator()
+     */
+    public DavResourceLocator getRequestLocator() {
+        String path = getRequestURI();
+        String ctx = getContextPath();
+        if (path.startsWith(ctx)) {
+            path = path.substring(ctx.length());
+        }
+        return factory.createResourceLocator(hrefPrefix, path);
+    }
+
+    /**
+     * Parse the destination header field and return the path of the destination
+     * resource.
+     *
+     * @return path of the destination resource.
+     * @throws DavException
+     * @see #HEADER_DESTINATION
+     * @see DavServletRequest#getDestinationLocator
+     */
+    public DavResourceLocator getDestinationLocator() throws DavException {
+        return getHrefLocator(httpRequest.getHeader(HEADER_DESTINATION), true);
+    }
+
+    private DavResourceLocator getHrefLocator(String href, boolean forDestination) throws DavException {
+        String ref = href;
+        if (ref != null) {
+            //href should be a Simple-ref production as defined in RFC4918, so it is either an absolute URI
+            //or an absolute path
+            try {
+                URI uri = new URI(ref).normalize(); // normalize path (see JCR-3174)
+                String auth = uri.getAuthority();
+                ref = uri.getRawPath();
+                if (auth == null) {
+                    //verify that href is an absolute path
+                    if (ref.startsWith("//") || !ref.startsWith("/")) {
+                        log.warn("expected absolute path but found " + ref);
+                        throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                    }
+                } else if (!auth.equals(httpRequest.getHeader("Host"))) {
+                    //this looks like an unsupported cross-server operation, but of course a reverse-proxy
+                    //might have rewritten the Host header. Since we can't find out, we have to reject anyway.
+                    //Better use absolute paths in DAV:href elements!
+                    throw new DavException(DavServletResponse.SC_FORBIDDEN);
+                }
+            } catch (URISyntaxException e) {
+                log.warn("malformed uri: " + href, e);
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+            // cut off the context path
+            String contextPath = httpRequest.getContextPath();
+            if (ref.startsWith(contextPath)) {
+                ref = ref.substring(contextPath.length());
+            } else {
+                //absolute path has to start with context path
+                throw new DavException(DavServletResponse.SC_FORBIDDEN);
+            }
+        }
+        if (factory instanceof AbstractLocatorFactory) {
+            return ((AbstractLocatorFactory)factory).createResourceLocator(hrefPrefix, ref, forDestination);
+        }
+        else {
+            return factory.createResourceLocator(hrefPrefix, ref);
+        }
+    }
+
+    /**
+     * Parse a href and return the path of the resource.
+     *
+     * @return path of the resource identified by the href.
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getHrefLocator
+     */
+    public DavResourceLocator getHrefLocator(String href) throws DavException {
+        return getHrefLocator(href, false);
+    }
+
+    /**
+     * Returns the path of the member resource of the request resource which is identified by the segment parameter.
+     *
+     * @return path of internal member resource.
+     */
+    public DavResourceLocator getMemberLocator(String segment) {
+        String path = (this.getRequestLocator().getHref(true) + segment).substring(hrefPrefix.length());
+        return factory.createResourceLocator(hrefPrefix, path);
+    }
+
+    /**
+     * Return true if the overwrite header does not inhibit overwriting.
+     *
+     * @return true if the overwrite header requests 'overwriting'
+     * @see #HEADER_OVERWRITE
+     * @see DavServletRequest#isOverwrite()
+     */
+    public boolean isOverwrite() {
+        return new OverwriteHeader(httpRequest).isOverwrite();
+    }
+
+    /**
+     * @see DavServletRequest#getDepth(int)
+     */
+    public int getDepth(int defaultValue) {
+        return DepthHeader.parse(httpRequest, defaultValue).getDepth();
+    }
+
+    /**
+     * @see DavServletRequest#getDepth()
+     */
+    public int getDepth() {
+        return getDepth(DEPTH_INFINITY);
+    }
+
+    /**
+     * Parse the Timeout header and return a long representing the value.
+     * {@link #UNDEFINED_TIMEOUT} is used as default value if no header
+     * is available or if the parsing fails.
+     *
+     * @return milliseconds indicating length of the timeout.
+     * @see DavServletRequest#getTimeout()
+     * @see TimeoutHeader#parse(jakarta.servlet.http.HttpServletRequest, long)
+     */
+    public long getTimeout() {
+        return TimeoutHeader.parse(httpRequest, UNDEFINED_TIMEOUT).getTimeout();
+    }
+
+    /**
+     * Retrieve the lock token from the 'Lock-Token' header.
+     *
+     * @return String representing the lock token sent in the Lock-Token header.
+     * @throws IllegalArgumentException If the value has not the correct format.
+     * @see #HEADER_LOCK_TOKEN
+     * @see DavServletRequest#getLockToken()
+     */
+    public String getLockToken() {
+        return CodedUrlHeader.parse(httpRequest, HEADER_LOCK_TOKEN).getCodedUrl();
+    }
+
+    /**
+     * @see DavServletRequest#getRequestDocument()
+     */
+    public Document getRequestDocument() throws DavException {
+        Document requestDocument = null;
+        /*
+        Don't attempt to parse the body if the content length header is 0.
+        NOTE: a value of -1 indicates that the length is unknown, thus we have
+        to parse the body. Note that http1.1 request using chunked transfer
+        coding will therefore not be detected here.
+        */
+        if (httpRequest.getContentLength() == 0) {
+            return requestDocument;
+        }
+        // try to parse the request body
+        try {
+            InputStream in = getDecodedInputStream();
+            if (in != null) {
+                // use a buffered input stream to find out whether there actually
+                // is a request body
+                InputStream bin = new BufferedInputStream(in);
+                bin.mark(1);
+                boolean isEmpty = -1 == bin.read();
+                bin.reset();
+                if (!isEmpty) {
+                    requestDocument = DomUtil.parseDocument(bin);
+                }
+            }
+        } catch (IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to build an XML Document from the request body: " + e.getMessage());
+            }
+            Throwable cause = e.getCause();
+            throw (cause instanceof DavException) ? (DavException) cause : new DavException(DavServletResponse.SC_BAD_REQUEST);
+        } catch (ParserConfigurationException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to build an XML Document from the request body: " + e.getMessage());
+            }
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR);
+        } catch (SAXException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to build an XML Document from the request body: " + e.getMessage());
+            }
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return requestDocument;
+    }
+
+    /**
+     * Returns the type of PROPFIND as indicated by the request body.
+     *
+     * @return type of the PROPFIND request. Default value is {@link #PROPFIND_ALL_PROP allprops}
+     * @see DavServletRequest#getPropFindType()
+     */
+    public int getPropFindType() throws DavException {
+        if (propfindProps == null) {
+            parsePropFindRequest();
+        }
+        return propfindType;
+    }
+
+    /**
+     * Returns the set of properties requested by the PROPFIND body or an
+     * empty set if the {@link #getPropFindType type} is either 'allprop' or
+     * 'propname'.
+     *
+     * @return set of properties requested by the PROPFIND body or an empty set.
+     * @see DavServletRequest#getPropFindProperties()
+     */
+    public DavPropertyNameSet getPropFindProperties() throws DavException {
+        if (propfindProps == null) {
+            parsePropFindRequest();
+        }
+        return propfindProps;
+    }
+
+    private InputStream getDecodedInputStream() throws IOException {
+        List<String> contentCodings = getRequestContentCodings();
+        int len = contentCodings.size();
+
+        log.trace("content codings: " + contentCodings);
+        InputStream result = httpRequest.getInputStream();
+
+        for (int i = 1; i <= len; i++) {
+            String s = contentCodings.get(len - i);
+            log.trace("decoding: " + s);
+            if ("gzip".equals(s)) {
+                result = new GZIPInputStream(result);
+            } else if ("deflate".equals(s)) {
+                result = new InflaterInputStream(result);
+            } else {
+                String message = "Unsupported content coding: " + s;
+                try {
+                    Element condition = DomUtil.createElement(DomUtil.createDocument(), PRECONDITION_SUPPORTED);
+                    throw new IOException(
+                            new DavException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, null, condition));
+                } catch (ParserConfigurationException ex) {
+                    throw new IOException(message);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private List<String> requestContentCodings = null;
+
+    @Override
+    public List<String> getRequestContentCodings() {
+        if (requestContentCodings == null) {
+            requestContentCodings = AbstractWebdavServlet.getContentCodings(httpRequest);
+        }
+
+        return requestContentCodings;
+    }
+
+    @Override
+    public String getAcceptableCodings() {
+        return "deflate, gzip";
+    }
+
+    /**
+     * Parse the propfind request body in order to determine the type of the propfind
+     * and the set of requested property.
+     * NOTE: An empty 'propfind' request body will be treated as request for all
+     * property according to the specification.
+     */
+    private void parsePropFindRequest() throws DavException {
+        propfindProps = new DavPropertyNameSet();
+        Document requestDocument = getRequestDocument();
+        // propfind httpRequest with empty body >> retrieve all property
+        if (requestDocument == null) {
+            return;
+        }
+
+        // propfind httpRequest with invalid body
+        Element root = requestDocument.getDocumentElement();
+        if (!XML_PROPFIND.equals(root.getLocalName())) {
+            log.info("PropFind-Request has no <propfind> tag.");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropFind-Request has no <propfind> tag.");
+        }
+
+        DavPropertyNameSet include = null;
+
+        ElementIterator it = DomUtil.getChildren(root);
+        int propfindTypeFound = 0;
+
+        while (it.hasNext()) {
+            Element child = it.nextElement();
+            String nodeName = child.getLocalName();
+            if (NAMESPACE.getURI().equals(child.getNamespaceURI())) {
+                if (XML_PROP.equals(nodeName)) {
+                    propfindType = PROPFIND_BY_PROPERTY;
+                    propfindProps = new DavPropertyNameSet(child);
+                    propfindTypeFound += 1;
+                }
+                else if (XML_PROPNAME.equals(nodeName)) {
+                    propfindType = PROPFIND_PROPERTY_NAMES;
+                    propfindTypeFound += 1;
+                }
+                else if (XML_ALLPROP.equals(nodeName)) {
+                    propfindType = PROPFIND_ALL_PROP;
+                    propfindTypeFound += 1;
+                }
+                else if (XML_INCLUDE.equals(nodeName)) {
+                    include = new DavPropertyNameSet();
+                    ElementIterator pit = DomUtil.getChildren(child);
+                    while (pit.hasNext()) {
+                        include.add(DavPropertyName.createFromXml(pit.nextElement()));
+                    }
+                }
+            }
+        }
+
+        if (propfindTypeFound > 1) {
+            log.info("Multiple top-level propfind instructions");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Multiple top-level propfind instructions");
+        }
+
+        if (include != null) {
+            if (propfindType == PROPFIND_ALL_PROP) {
+                // special case: allprop with include extension
+                propfindType = PROPFIND_ALL_PROP_INCLUDE;
+                propfindProps = include;
+            }
+            else {
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST, "<include> goes only with <allprop>");
+
+            }
+        }
+    }
+
+     /**
+      * Return a {@link List} of property change operations. Each entry
+      * is either of type {@link DavPropertyName}, indicating a &lt;remove&gt;
+      * operation, or of type {@link DavProperty}, indicating a &lt;set&gt;
+      * operation. Note that ordering is significant here.
+      *
+      * @return the list of change operations entries in the PROPPATCH request body
+      * @see DavServletRequest#getPropPatchChangeList()
+      */
+     public List<? extends PropEntry> getPropPatchChangeList() throws DavException {
+         if (proppatchList == null) {
+             parsePropPatchRequest();
+         }
+         return proppatchList;
+     }
+
+    /**
+     * Parse the PROPPATCH request body.
+     */
+    private void parsePropPatchRequest() throws DavException {
+
+        proppatchSet = new DavPropertySet();
+        proppatchList = new ArrayList<PropEntry>();
+
+        Document requestDocument = getRequestDocument();
+
+        if (requestDocument == null) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid request body.");
+        }
+
+        Element root = requestDocument.getDocumentElement();
+        if (!DomUtil.matches(root, XML_PROPERTYUPDATE, NAMESPACE)) {
+            log.warn("PropPatch-Request has no <DAV:propertyupdate> tag.");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropPatch-Request has no <propertyupdate> tag.");
+        }
+
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element el = it.nextElement();
+            if (DomUtil.matches(el, XML_SET, NAMESPACE)) {
+                Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE);
+                if (propEl != null) {
+                    ElementIterator properties = DomUtil.getChildren(propEl);
+                    while (properties.hasNext()) {
+                        DavProperty<?> davProp = DefaultDavProperty.createFromXml(properties.nextElement());
+                        proppatchSet.add(davProp);
+                        proppatchList.add(davProp);
+                    }
+                }
+            } else if (DomUtil.matches(el, XML_REMOVE, NAMESPACE)) {
+                Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE);
+                if (propEl != null) {
+                    ElementIterator properties = DomUtil.getChildren(propEl);
+                    while (properties.hasNext()) {
+                        DavProperty<?> davProp = DefaultDavProperty.createFromXml(properties.nextElement());
+                        proppatchSet.add(davProp);
+                        proppatchList.add(davProp.getName());
+                    }
+                }
+            } else {
+                log.debug("Unknown element in DAV:propertyupdate: " + el.getNodeName());
+                // unknown child elements are ignored
+            }
+        }
+    }
+
+    /**
+     * {@link LockInfo} object encapsulating the information passed with a LOCK
+     * request if the LOCK request body was valid. If the request body is
+     * missing a 'refresh lock' request is assumed. The {@link LockInfo}
+     * then only provides timeout and isDeep property and returns true on
+     * {@link org.apache.jackrabbit.webdav.lock.LockInfo#isRefreshLock()}
+     *
+     * @return lock info object or <code>null</code> if an error occurred while
+     *         parsing the request body.
+     * @throws DavException throws a 400 (Bad Request) DavException if a request
+     * body is present but does not start with a DAV:lockinfo element. Note however,
+     * that a non-existing request body is a valid request used to refresh
+     * an existing lock.
+     * @see DavServletRequest#getLockInfo()
+     */
+    public LockInfo getLockInfo() throws DavException {
+        LockInfo lockInfo;
+        boolean isDeep = (getDepth(DEPTH_INFINITY) == DEPTH_INFINITY);
+        Document requestDocument = getRequestDocument();
+        // check if XML request body is present. It SHOULD have one for
+        // 'create Lock' request and missing for a 'refresh Lock' request
+        if (requestDocument != null) {
+            Element root = requestDocument.getDocumentElement();
+            if (root.getLocalName().equals(XML_LOCKINFO)) {
+                lockInfo = new LockInfo(root, getTimeout(), isDeep);
+            } else {
+                log.debug("Lock request body must start with a DAV:lockinfo element.");
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        } else {
+            lockInfo = new LockInfo(null, getTimeout(), isDeep);
+        }
+        return lockInfo;
+    }
+
+    /**
+     * Test if the if header matches the given resource. The comparison is
+     * made with the {@link DavResource#getHref()
+     * resource href} and the token returned from an exclusive write lock present on
+     * the resource.<br>
+     * NOTE: If either the If header or the resource is <code>null</code> or if
+     * the resource has not applied an exclusive write lock the preconditions are met.
+     * If in contrast the lock applied to the given resource returns a
+     * <code>null</code> lock token (e.g. for security reasons) or a lock token
+     * that does not match, the method will return false.
+     *
+     * @param resource Webdav resources being operated on
+     * @return true if the test is successful and the preconditions for the
+     *         request processing are fulfilled.
+     * @see DavServletRequest#matchesIfHeader(DavResource)
+     * @see IfHeader#matches(String, String, String)
+     * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope)
+     * @see org.apache.jackrabbit.webdav.lock.ActiveLock#getToken()
+     */
+    public boolean matchesIfHeader(DavResource resource) {
+        // no ifheader
+        // >> preconditions ok so far
+        if (!ifHeader.hasValue() || resource == null) {
+            return true;
+        }
+
+        ActiveLock[] locks = resource.getLocks();
+        if (!resource.exists() || locks.length == 0) {
+            return matchesIfHeader(resource.getHref(), null, getStrongETag(resource));
+        }
+        for (ActiveLock lock : locks) {
+            if (matchesIfHeader(resource.getHref(), lock.getToken(), getStrongETag(resource))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see DavServletRequest#matchesIfHeader(String, String, String)
+     * @see IfHeader#matches(String, String, String)
+     */
+    public boolean matchesIfHeader(String href, String token, String eTag) {
+        return ifHeader.matches(href, token, isStrongETag(eTag) ?  eTag : "");
+    }
+
+    /**
+     * Returns the strong etag present on the given resource or empty string
+     * if either the resource does not provide any etag or if the etag is weak.
+     *
+     * @param resource
+     * @return strong etag or empty string.
+     */
+    private String getStrongETag(DavResource resource) {
+        if (resource.exists()) {
+            DavProperty<?> prop = resource.getProperty(DavPropertyName.GETETAG);
+            if (prop != null && prop.getValue() != null) {
+                String etag = prop.getValue().toString();
+                if (isStrongETag(etag)) {
+                    return etag;
+                }
+            }
+        }
+        // no strong etag available
+        return "";
+    }
+
+    /**
+     * Returns true if the given string represents a strong etag.
+     *
+     * @param eTag
+     * @return true, if its a strong etag
+     */
+    private static boolean isStrongETag(String eTag) {
+        return eTag != null && eTag.length() > 0 && !eTag.startsWith("W\\");
+    }
+
+    //-----------------------------< TransactionDavServletRequest Interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionId()
+     */
+    public String getTransactionId() {
+        return CodedUrlHeader.parse(httpRequest, TransactionConstants.HEADER_TRANSACTIONID).getCodedUrl();
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionInfo()
+     */
+    public TransactionInfo getTransactionInfo() throws DavException {
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            return new TransactionInfo(requestDocument.getDocumentElement());
+        }
+        return null;
+    }
+
+    //-----------------------------< ObservationDavServletRequest Interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionId()
+     */
+    public String getSubscriptionId() {
+        return CodedUrlHeader.parse(httpRequest, ObservationConstants.HEADER_SUBSCRIPTIONID).getCodedUrl();
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getPollTimeout()
+     */
+    public long getPollTimeout() {
+        return PollTimeoutHeader.parseHeader(httpRequest, 0).getTimeout();
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionInfo()
+     */
+    public SubscriptionInfo getSubscriptionInfo() throws DavException {
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            Element root = requestDocument.getDocumentElement();
+            if (ObservationConstants.XML_SUBSCRIPTIONINFO.equals(root.getLocalName())) {
+                int depth = getDepth(DEPTH_0);
+                return new SubscriptionInfo(root, getTimeout(), depth == DEPTH_INFINITY);
+            }
+        }
+        return null;
+    }
+
+    //--------------------------------< OrderingDavServletRequest Interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderingType()
+     */
+    public String getOrderingType() {
+        return getHeader(OrderingConstants.HEADER_ORDERING_TYPE);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getPosition()
+     */
+    public Position getPosition() {
+        String h = getHeader(OrderingConstants.HEADER_POSITION);
+        Position pos = null;
+        if (h != null) {
+            String[] typeNSegment = h.split("\\s");
+            if (typeNSegment.length == 2) {
+                try {
+                    pos = new Position(typeNSegment[0], typeNSegment[1]);
+                } catch (IllegalArgumentException e) {
+                    log.error("Cannot parse Position header: " + e.getMessage());
+                }
+            }
+        }
+        return pos;
+    }
+
+    /**
+     * @return <code>OrderPatch</code> object representing the orderpatch request
+     *         body or <code>null</code> if the
+     * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderPatch()
+     */
+    public OrderPatch getOrderPatch() throws DavException {
+        OrderPatch op = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            Element root = requestDocument.getDocumentElement();
+            op = OrderPatch.createFromXml(root);
+        } else {
+            log.error("Error while building xml document from ORDERPATH request body.");
+        }
+        return op;
+    }
+
+    //-------------------------------------< DeltaVServletRequest interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel()
+     */
+    public String getLabel() {
+        LabelHeader label = LabelHeader.parse(this);
+        if (label != null) {
+            return label.getLabel();
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabelInfo()
+     */
+    public LabelInfo getLabelInfo() throws DavException {
+        LabelInfo lInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            Element root = requestDocument.getDocumentElement();
+            int depth = getDepth(DEPTH_0);
+            lInfo = new LabelInfo(root, depth);
+        }
+        return lInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getMergeInfo()
+     */
+    public MergeInfo getMergeInfo()  throws DavException {
+        MergeInfo mInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            mInfo = new MergeInfo(requestDocument.getDocumentElement());
+        }
+        return mInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getUpdateInfo()
+     */
+    public UpdateInfo getUpdateInfo() throws DavException  {
+        UpdateInfo uInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            uInfo = new UpdateInfo(requestDocument.getDocumentElement());
+        }
+        return uInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getReportInfo()
+     */
+    public ReportInfo getReportInfo() throws DavException  {
+        ReportInfo rInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            rInfo = new ReportInfo(requestDocument.getDocumentElement(), getDepth(DEPTH_0));
+        }
+        return rInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getOptionsInfo()
+     */
+    public OptionsInfo getOptionsInfo() throws DavException {
+        OptionsInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = OptionsInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getRebindInfo()
+     */
+    public RebindInfo getRebindInfo() throws DavException {
+        RebindInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = RebindInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getUnbindInfo()
+     */
+    public UnbindInfo getUnbindInfo() throws DavException {
+        UnbindInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = UnbindInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getBindInfo()
+     */
+    public BindInfo getBindInfo() throws DavException {
+        BindInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = BindInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
+    //---------------------------------------< HttpServletRequest interface >---
+
+    @Override
+    public String getAuthType() {
+        return httpRequest.getAuthType();
+    }
+
+    @Override
+    public Cookie[] getCookies() {
+        return httpRequest.getCookies();
+    }
+
+    @Override
+    public long getDateHeader(String s) {
+        return httpRequest.getDateHeader(s);
+    }
+
+    @Override
+    public String getHeader(String s) {
+        return httpRequest.getHeader(s);
+    }
+
+    @Override
+    public Enumeration<String> getHeaders(String s) {
+        return httpRequest.getHeaders(s);
+    }
+
+    @Override
+    public Enumeration<String> getHeaderNames() {
+        return httpRequest.getHeaderNames();
+    }
+
+    @Override
+    public int getIntHeader(String s) {
+        return httpRequest.getIntHeader(s);
+    }
+
+    @Override
+    public String getMethod() {
+        return httpRequest.getMethod();
+    }
+
+    @Override
+    public String getPathInfo() {
+        return httpRequest.getPathInfo();
+    }
+
+    @Override
+    public String getPathTranslated() {
+        return httpRequest.getPathTranslated();
+    }
+
+    @Override
+    public String getContextPath() {
+        return httpRequest.getContextPath();
+    }
+
+    @Override
+    public String getQueryString() {
+        return httpRequest.getQueryString();
+    }
+
+    @Override
+    public String getRemoteUser() {
+        return httpRequest.getRemoteUser();
+    }
+
+    @Override
+    public boolean isUserInRole(String s) {
+        return httpRequest.isUserInRole(s);
+    }
+
+    @Override
+    public Principal getUserPrincipal() {
+        return httpRequest.getUserPrincipal();
+    }
+
+    @Override
+    public String getRequestedSessionId() {
+        return httpRequest.getRequestedSessionId();
+    }
+
+    @Override
+    public String getRequestURI() {
+        return httpRequest.getRequestURI();
+    }
+
+    @Override
+    public StringBuffer getRequestURL() {
+        return httpRequest.getRequestURL();
+    }
+
+    @Override
+    public String getServletPath() {
+        return httpRequest.getServletPath();
+    }
+
+    @Override
+    public HttpSession getSession(boolean b) {
+        return httpRequest.getSession(b);
+    }
+
+    @Override
+    public HttpSession getSession() {
+        return httpRequest.getSession();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdValid() {
+        return httpRequest.isRequestedSessionIdValid();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromCookie() {
+        return httpRequest.isRequestedSessionIdFromCookie();
+    }
+
+    @Override
+    public boolean isRequestedSessionIdFromURL() {
+        return httpRequest.isRequestedSessionIdFromURL();
+    }
+
+    @Override
+    public Object getAttribute(String s) {
+        return httpRequest.getAttribute(s);
+    }
+
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return httpRequest.getAttributeNames();
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return httpRequest.getCharacterEncoding();
+    }
+
+    @Override
+    public void setCharacterEncoding(String s) throws UnsupportedEncodingException {
+        httpRequest.setCharacterEncoding(s);
+    }
+
+    @Override
+    public int getContentLength() {
+        return httpRequest.getContentLength();
+    }
+
+    @Override
+    public String getContentType() {
+        return httpRequest.getContentType();
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        return new MyServletInputStream(getDecodedInputStream());
+    }
+
+    @Override
+    public String getParameter(String s) {
+        return httpRequest.getParameter(s);
+    }
+
+    @Override
+    public Enumeration<String> getParameterNames() {
+        return httpRequest.getParameterNames();
+    }
+
+    @Override
+    public String[] getParameterValues(String s) {
+        return httpRequest.getParameterValues(s);
+    }
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        return httpRequest.getParameterMap();
+    }
+
+    @Override
+    public String getProtocol() {
+        return httpRequest.getProtocol();
+    }
+
+    @Override
+    public String getScheme() {
+        return httpRequest.getScheme();
+    }
+
+    @Override
+    public String getServerName() {
+        return httpRequest.getServerName();
+    }
+
+    @Override
+    public int getServerPort() {
+        return httpRequest.getServerPort();
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return httpRequest.getReader();
+    }
+
+    @Override
+    public String getRemoteAddr() {
+        return httpRequest.getRemoteAddr();
+    }
+
+    @Override
+    public String getRemoteHost() {
+        return httpRequest.getRemoteHost();
+    }
+
+    @Override
+    public void setAttribute(String s, Object o) {
+        httpRequest.setAttribute(s, o);
+    }
+
+    @Override
+    public void removeAttribute(String s) {
+        httpRequest.removeAttribute(s);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return httpRequest.getLocale();
+    }
+
+    @Override
+    public Enumeration<Locale> getLocales() {
+        return httpRequest.getLocales();
+    }
+
+    @Override
+    public boolean isSecure() {
+        return httpRequest.isSecure();
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(String s) {
+        return httpRequest.getRequestDispatcher(s);
+    }
+
+    @Override
+    public int getRemotePort() {
+        return httpRequest.getRemotePort();
+    }
+
+    @Override
+    public String getLocalName() {
+        return httpRequest.getLocalName();
+    }
+
+    @Override
+    public String getLocalAddr() {
+        return httpRequest.getLocalAddr();
+    }
+
+    @Override
+    public int getLocalPort() {
+        return httpRequest.getLocalPort();
+    }
+
+    @Override
+    public String changeSessionId() {
+        return httpRequest.changeSessionId();
+    }
+
+    @Override
+    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+        return httpRequest.authenticate(response);
+    }
+
+    @Override
+    public void login(String username, String password) throws ServletException {
+        httpRequest.login(username, password);
+    }
+
+    @Override
+    public void logout() throws ServletException {
+        httpRequest.logout();
+    }
+
+    @Override
+    public Collection<Part> getParts() throws IOException, ServletException {
+        return httpRequest.getParts();
+    }
+
+    @Override
+    public Part getPart(String name) throws IOException, ServletException {
+        return httpRequest.getPart(name);
+    }
+
+    @Override
+    public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
+        return httpRequest.upgrade(handlerClass);
+    }
+
+    @Override
+    public long getContentLengthLong() {
+        return httpRequest.getContentLengthLong();
+    }
+
+    @Override
+    public ServletContext getServletContext() {
+        return httpRequest.getServletContext();
+    }
+
+    @Override
+    public AsyncContext startAsync() throws IllegalStateException {
+        return httpRequest.startAsync();
+    }
+
+    @Override
+    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {
+        return httpRequest.startAsync(servletRequest, servletResponse);
+    }
+
+    @Override
+    public boolean isAsyncStarted() {
+        return httpRequest.isAsyncStarted();
+    }
+
+    @Override
+    public boolean isAsyncSupported() {
+        return httpRequest.isAsyncSupported();
+    }
+
+    @Override
+    public AsyncContext getAsyncContext() {
+        return httpRequest.getAsyncContext();
+    }
+
+    @Override
+    public DispatcherType getDispatcherType() {
+        return httpRequest.getDispatcherType();
+    }
+
+	@Override
+    public ServletConnection getServletConnection() {
+		return httpRequest.getServletConnection();
+	}
+
+	@Override
+    public String getProtocolRequestId() {
+		return httpRequest.getProtocolRequestId();
+	}
+
+	@Override
+    public String getRequestId() {
+		return httpRequest.getRequestId();
+	}
+
+	private static class MyServletInputStream extends ServletInputStream {
+
+        private final InputStream delegate;
+
+        public MyServletInputStream(InputStream delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public int available() throws IOException {
+            return delegate.available();
+        }
+
+        @Override
+        public void close() throws IOException {
+            delegate.close();
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return delegate.equals(other);
+        }
+
+        @Override
+        public int hashCode() {
+            return delegate.hashCode();
+        }
+
+        @Override
+        public void mark(int readlimit) {
+            delegate.mark(readlimit);
+        }
+
+        @Override
+        public boolean markSupported() {
+            return delegate.markSupported();
+        }
+
+        @Override
+        public int read() throws IOException {
+            return delegate.read();
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            return delegate.read(b, off, len);
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            return delegate.read(b);
+        }
+
+        @Override
+        public int readLine(byte[] b, int off, int len) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void reset() throws IOException {
+            delegate.reset();
+        }
+
+        @Override
+        public long skip(long n) throws IOException {
+            return delegate.skip(n);
+        }
+
+        @Override
+        public String toString() {
+            return delegate.toString();
+        }
+
+        @Override
+        public boolean isFinished() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isReady() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void setReadListener(ReadListener readListener) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java
new file mode 100644
index 000000000..2fa1811b6
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse;
+
+/**
+ * The empty <code>WebdavResponse</code> interface collects the functionality
+ * defined by {@link org.apache.jackrabbit.webdav.DavServletResponse}
+ * encapsulating for the core WebDAV specification (RFC 2518) as well as the
+ * various extensions used for observation and transaction support, ordering of
+ * collections, search and versioning.
+ */
+public interface WebdavResponse extends DavServletResponse, ObservationDavServletResponse {
+
+    // can be removed when we move to Servlet API 4.0
+    public default void setTrailerFields(Supplier<Map<String, String>> supplier) {
+        // nop
+    }
+
+    // can be removed when we move to Servlet API 4.0
+    public default Supplier<Map<String, String>> getTrailerFields() {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java
new file mode 100644
index 000000000..660d951ad
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java
@@ -0,0 +1,392 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
+import org.apache.jackrabbit.webdav.header.Header;
+import org.apache.jackrabbit.webdav.lock.ActiveLock;
+import org.apache.jackrabbit.webdav.lock.LockDiscovery;
+import org.apache.jackrabbit.webdav.observation.EventDiscovery;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.apache.jackrabbit.webdav.observation.Subscription;
+import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * WebdavResponseImpl implements the <code>WebdavResponse</code> interface.
+ */
+public class WebdavResponseImpl implements WebdavResponse {
+
+    private static Logger log = LoggerFactory.getLogger(WebdavResponseImpl.class);
+
+    private HttpServletResponse httpResponse;
+
+    /**
+     * Create a new <code>WebdavResponse</code>
+     *
+     * @param httpResponse
+     */
+    public WebdavResponseImpl(HttpServletResponse httpResponse) {
+        this(httpResponse, false);
+    }
+
+    /**
+     * Create a new <code>WebdavResponse</code>
+     *
+     * @param httpResponse
+     * @param noCache
+     */
+    public WebdavResponseImpl(HttpServletResponse httpResponse, boolean noCache) {
+        this.httpResponse = httpResponse;
+        if (noCache) {
+            /* set cache control headers */
+            addHeader("Pragma", "No-cache");  // http1.0
+            addHeader("Cache-Control", "no-cache"); // http1.1
+        }
+    }
+
+    /**
+     * If the specifid exception provides an error condition an Xml response body
+     * is sent providing more detailed information about the error. Otherwise only
+     * the error code and status phrase is sent back.
+     *
+     * @param exception
+     * @throws IOException
+     * @see DavServletResponse#sendError(org.apache.jackrabbit.webdav.DavException)
+     * @see #sendError(int, String)
+     * @see #sendXmlResponse(XmlSerializable, int)
+     */
+    public void sendError(DavException exception) throws IOException {
+        if (!exception.hasErrorCondition()) {
+            httpResponse.sendError(exception.getErrorCode(), exception.getStatusPhrase());
+        } else {
+            sendXmlResponse(exception, exception.getErrorCode());
+        }
+    }
+
+    @Override
+    public void sendMultiStatus(MultiStatus multistatus) throws IOException {
+        sendXmlResponse(multistatus, SC_MULTI_STATUS);
+    }
+
+    @Override
+    public void sendMultiStatus(MultiStatus multistatus, List<String> acceptableContentCodings) throws IOException {
+        sendXmlResponse(multistatus, SC_MULTI_STATUS, acceptableContentCodings);
+    }
+
+    /**
+     * Send response body for a lock request that was intended to refresh one
+     * or several locks.
+     *
+     * @param locks
+     * @throws java.io.IOException
+     * @see DavServletResponse#sendRefreshLockResponse(org.apache.jackrabbit.webdav.lock.ActiveLock[])
+     */
+    public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException {
+        DavPropertySet propSet = new DavPropertySet();
+        propSet.add(new LockDiscovery(locks));
+        sendXmlResponse(propSet, SC_OK);
+    }
+
+    @Override
+    public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException {
+        sendXmlResponse(serializable, status, Collections.emptyList());
+    }
+
+    @Override
+    public void sendXmlResponse(XmlSerializable serializable, int status, List<String> acceptableContentCodings) throws IOException {
+        httpResponse.setStatus(status);
+
+        if (serializable != null) {
+            try {
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                Document doc = DomUtil.createDocument();
+                doc.appendChild(serializable.toXml(doc));
+                DomUtil.transformDocument(doc, out);
+                out.close();
+
+                httpResponse.setContentType("text/xml; charset=UTF-8");
+
+                // use GZIP iff accepted by client and content size >= 256 octets
+                if (out.size() < 256 || !acceptableContentCodings.contains("gzip")) {
+                    httpResponse.setContentLength(out.size());
+                    out.writeTo(httpResponse.getOutputStream());
+                } else {
+                    httpResponse.setHeader("Content-Encoding", "gzip");
+                    try (OutputStream os = new GZIPOutputStream(httpResponse.getOutputStream())) {
+                        out.writeTo(os);
+                    }
+                }
+            } catch (ParserConfigurationException e) {
+                log.error(e.getMessage());
+                throw new IOException(e.getMessage());
+            } catch (TransformerException e) {
+                log.error(e.getMessage());
+                throw new IOException(e.getMessage());
+            } catch (SAXException e) {
+                log.error(e.getMessage());
+                throw new IOException(e.getMessage());
+            }
+        }
+    }
+
+    //----------------------------< ObservationDavServletResponse Interface >---
+    /**
+     *
+     * @param subscription
+     * @throws IOException
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendSubscriptionResponse(org.apache.jackrabbit.webdav.observation.Subscription)
+     */
+    public void sendSubscriptionResponse(Subscription subscription) throws IOException {
+        String id = subscription.getSubscriptionId();
+        if (id != null) {
+            Header h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, id);
+            httpResponse.setHeader(h.getHeaderName(), h.getHeaderValue());
+        }
+        DavPropertySet propSet = new DavPropertySet();
+        propSet.add(new SubscriptionDiscovery(subscription));
+        sendXmlResponse(propSet, SC_OK);
+    }
+
+    /**
+     *
+     * @param eventDiscovery
+     * @throws IOException
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendPollResponse(org.apache.jackrabbit.webdav.observation.EventDiscovery)
+     */
+    public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException {
+        sendXmlResponse(eventDiscovery, SC_OK);
+    }
+
+    //--------------------------------------< HttpServletResponse interface >---
+
+    @Override
+    public void addCookie(Cookie cookie) {
+        httpResponse.addCookie(cookie);
+    }
+
+    @Override
+    public boolean containsHeader(String s) {
+        return httpResponse.containsHeader(s);
+    }
+
+    @Override
+    public String encodeURL(String s) {
+        return httpResponse.encodeRedirectURL(s);
+    }
+
+    @Override
+    public String encodeRedirectURL(String s) {
+        return httpResponse.encodeRedirectURL(s);
+    }
+
+    @Override
+    public void sendError(int i, String s) throws IOException {
+        httpResponse.sendError(i, s);
+    }
+
+    @Override
+    public void sendError(int i) throws IOException {
+        httpResponse.sendError(i);
+    }
+
+    @Override
+    public void sendRedirect(String s) throws IOException {
+        httpResponse.sendRedirect(s);
+    }
+
+    @Override
+    public void setDateHeader(String s, long l) {
+        httpResponse.setDateHeader(s, l);
+    }
+
+    @Override
+    public void addDateHeader(String s, long l) {
+        httpResponse.addDateHeader(s, l);
+    }
+
+    @Override
+    public void setHeader(String s, String s1) {
+        httpResponse.setHeader(s, s1);
+    }
+
+    @Override
+    public void addHeader(String s, String s1) {
+        httpResponse.addHeader(s, s1);
+    }
+
+    @Override
+    public void setIntHeader(String s, int i) {
+        httpResponse.setIntHeader(s, i);
+    }
+
+    @Override
+    public void addIntHeader(String s, int i) {
+        httpResponse.addIntHeader(s, i);
+    }
+
+    @Override
+    public void setStatus(int i) {
+        httpResponse.setStatus(i);
+    }
+
+    @Override
+    public String getCharacterEncoding() {
+        return httpResponse.getCharacterEncoding();
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+        return httpResponse.getOutputStream();
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        return httpResponse.getWriter();
+    }
+
+    @Override
+    public void setContentLength(int i) {
+        httpResponse.setContentLength(i);
+    }
+
+    @Override
+    public void setContentType(String s) {
+        httpResponse.setContentType(s);
+    }
+
+    @Override
+    public void setBufferSize(int i) {
+        httpResponse.setBufferSize(i);
+    }
+
+    @Override
+    public int getBufferSize() {
+        return httpResponse.getBufferSize();
+    }
+
+    @Override
+    public void flushBuffer() throws IOException {
+        httpResponse.flushBuffer();
+    }
+
+    @Override
+    public void resetBuffer() {
+        httpResponse.resetBuffer();
+    }
+
+    @Override
+    public boolean isCommitted() {
+        return httpResponse.isCommitted();
+    }
+
+    @Override
+    public void reset() {
+        httpResponse.reset();
+    }
+
+    @Override
+    public void setLocale(Locale locale) {
+        httpResponse.setLocale(locale);
+    }
+
+    @Override
+    public Locale getLocale() {
+        return httpResponse.getLocale();
+    }
+
+    @Override
+    public String getContentType() {
+        return httpResponse.getContentType();
+    }
+
+    @Override
+    public void setCharacterEncoding(String charset) {
+        httpResponse.setCharacterEncoding(charset);
+    }
+
+    @Override
+    public int getStatus() {
+        return httpResponse.getStatus();
+    }
+
+    @Override
+    public String getHeader(String name) {
+        return httpResponse.getHeader(name);
+    }
+
+    @Override
+    public Collection<String> getHeaders(String name) {
+        return httpResponse.getHeaders(name);
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        return httpResponse.getHeaderNames();
+    }
+
+    @Override
+    public void setContentLengthLong(long len) {
+        httpResponse.setContentLengthLong(len);
+    }
+
+    // Servlet 4.0 API support for trailers, for now using reflection
+
+    public void setTrailerFields(Supplier<Map<String, String>> supplier) {
+        try {
+            java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("setTrailerFields", Supplier.class);
+            stf.invoke(httpResponse, supplier);
+        } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException
+                | SecurityException ex) {
+            throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Supplier<Map<String, String>> getTrailerFields() {
+        try {
+            java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("getTrailerFields");
+            return (Supplier<Map<String, String>>) stf.invoke(httpResponse);
+        } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException
+                | SecurityException ex) {
+            throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex);
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java
new file mode 100644
index 000000000..e52f8c668
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+
+/**
+ * <code>BindConstants</code> provide constants for request and response
+ * headers, Xml elements and property names defined by
+ * the BIND specification.
+ */
+public interface BindConstants {
+
+    /**
+     * The namespace
+     */
+    public static final Namespace NAMESPACE = DavConstants.NAMESPACE;
+
+    /**
+     * local names of XML elements used in the request bodies of the methods BIND, REBIND and UNBIND.
+     */
+    public static final String XML_BIND = "bind";
+    public static final String XML_REBIND = "rebind";
+    public static final String XML_UNBIND = "unbind";
+    public static final String XML_SEGMENT = "segment";
+    public static final String XML_HREF = "href";
+    public static final String XML_PARENT = "parent";
+
+    public static final String METHODS = "BIND, REBIND, UNBIND";
+
+    /*
+     * Webdav properties defined by the BIND specification. 
+     */
+    public static final DavPropertyName RESOURCEID = DavPropertyName.create("resource-id");
+    public static final DavPropertyName PARENTSET = DavPropertyName.create("parent-set");
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java
new file mode 100644
index 000000000..627640ebf
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+public class BindInfo implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(BindInfo.class);
+
+    private String segment;
+    private String href;
+
+    public BindInfo(String href, String segment) {
+        this.href = href;
+        this.segment = segment;
+    }
+
+    public String getHref() {
+        return this.href;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>BindInfo</code> object from the root element present
+     * in the request body.
+     *
+     * @param root the root element of the request body
+     * @return a BindInfo object containing segment and href
+     * @throws org.apache.jackrabbit.webdav.DavException if the BIND request is malformed
+     */
+    public static BindInfo createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_BIND, BindConstants.NAMESPACE)) {
+            log.warn("DAV:bind element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String href = null;
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) {
+                if (href == null) {
+                    href = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:href element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (href == null) {
+            log.warn("DAV:href element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new BindInfo(href, segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element bindElt = DomUtil.createElement(document, BindConstants.XML_BIND, BindConstants.NAMESPACE);
+        Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        bindElt.appendChild(hrefElt);
+        bindElt.appendChild(segElt);
+        return bindElt;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java
new file mode 100644
index 000000000..8d6c5168e
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+
+/**
+ * <code>BindServletRequest</code> provides extension useful for functionality
+ * related to BIND specification.
+ */
+public interface BindServletRequest {
+
+    /**
+     * Returns the {@link RebindInfo} present with the request
+     *
+     * @return {@link RebindInfo} object
+     * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body
+     */
+    public RebindInfo getRebindInfo() throws DavException;
+
+    /**
+     * Returns the {@link UnbindInfo} present with the request
+     *
+     * @return {@link UnbindInfo} object
+     * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body
+     */
+    public UnbindInfo getUnbindInfo() throws DavException;
+
+    /**
+     * Returns the {@link BindInfo} present with the request
+     *
+     * @return {@link BindInfo} object
+     * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body
+     */
+    public BindInfo getBindInfo() throws DavException;
+
+    /**
+     * Parses a href and returns the path of the resource.
+     *
+     * @return path of the resource identified by the href.
+     */
+    public DavResourceLocator getHrefLocator(String href) throws DavException;
+
+    /**
+     * Returns the path of the member resource of the request resource which is identified by the segment parameter.
+     *
+     * @return path of internal member resource.
+     */
+    public DavResourceLocator getMemberLocator(String segment);
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java
new file mode 100644
index 000000000..86be8faa3
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import java.util.Set;
+
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+public interface BindableResource {
+
+    /**
+     * Will add a new binding to the given collection referencing this resource.
+     *
+     * @param collection the collection to create the new binding in.
+     * @param newBinding the new binding
+     */
+    public void bind(DavResource collection, DavResource newBinding) throws DavException;
+
+    /**
+     * Will rebind the resource to the given collection. By definition, this is
+     * an atomic move operation.
+     *
+     * @param collection the collection to create the new binding in.
+     * @param newBinding the new binding
+     */
+    public void rebind(DavResource collection, DavResource newBinding) throws DavException;
+
+    /**
+     * Will retrieve a collection of parent elements of the bindable resource
+     * representing the parent set.
+     *
+     * @return newBinding the new binding
+     */
+    public Set<ParentElement> getParentElements();
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java
new file mode 100644
index 000000000..3edd2ab15
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>ParentElement</code> wraps en element of the parent set of a resource. A <code>java.util.Set</code> of
+ * <code>ParentElement</code> objects may serve as the value object of the <code>ParentSet</code> DavProperty.
+ */
+public class ParentElement implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(ParentElement.class);
+
+    private final String href;
+    private final String segment;
+
+    public ParentElement(String href, String segment) {
+        this.href = href;
+        this.segment = segment;
+    }
+
+    public String getHref() {
+        return this.href;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>ParentElement</code> object from an XML element DAV:parent
+     *
+     * @param root the DAV:parent element
+     * @return a ParentElement object
+     * @throws org.apache.jackrabbit.webdav.DavException if the DAV:parent element is malformed
+     */
+    public static ParentElement createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_PARENT, BindConstants.NAMESPACE)) {
+            log.warn("DAV:paret element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String href = null;
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) {
+                if (href == null) {
+                    href = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:href element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (href == null) {
+            log.warn("DAV:href element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new ParentElement(href, segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)  
+     */
+    public Element toXml(Document document) {
+        Element parentElt = DomUtil.createElement(document, BindConstants.XML_PARENT, BindConstants.NAMESPACE);
+        Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        parentElt.appendChild(hrefElt);
+        parentElt.appendChild(segElt);
+        return parentElt;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java
new file mode 100644
index 000000000..01fae4230
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.property.AbstractDavProperty;
+
+import java.util.Collection;
+
+/**
+ * <code>ParentSet</code> represents a DAV:parent-set property.
+ */
+public class ParentSet extends AbstractDavProperty<Collection<ParentElement>> {
+
+    private final Collection<ParentElement> parents;
+
+    /**
+     * Creates a new ParentSet from a collection of <code>ParentElement</code> objects.
+     * @param parents
+     */
+    public ParentSet(Collection<ParentElement> parents) {
+        super(BindConstants.PARENTSET, true);
+        this.parents = parents;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.property.AbstractDavProperty#getValue() 
+     */
+    public Collection<ParentElement> getValue() {
+        return this.parents;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java
new file mode 100644
index 000000000..233b236a7
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+public class RebindInfo implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(RebindInfo.class);
+
+    private String segment;
+    private String href;
+
+    public RebindInfo(String href, String segment) {
+        this.href = href;
+        this.segment = segment;
+    }
+
+    public String getHref() {
+        return this.href;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>RebindInfo</code> object from the root element present
+     * in the request body.
+     *
+     * @param root the root element of the request body
+     * @return a RebindInfo object containing segment and href
+     * @throws org.apache.jackrabbit.webdav.DavException if the REBIND request is malformed 
+     */
+    public static RebindInfo createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_REBIND, BindConstants.NAMESPACE)) {
+            log.warn("DAV:rebind element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String href = null;
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) {
+                if (href == null) {
+                    href = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:href element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (href == null) {
+            log.warn("DAV:href element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new RebindInfo(href, segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element rebindElt = DomUtil.createElement(document, BindConstants.XML_REBIND, BindConstants.NAMESPACE);
+        Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        rebindElt.appendChild(hrefElt);
+        rebindElt.appendChild(segElt);
+        return rebindElt;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java
new file mode 100644
index 000000000..e3c7a3e2d
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.bind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+public class UnbindInfo implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(UnbindInfo.class);
+
+    private String segment;
+
+    private UnbindInfo() {}
+
+    public UnbindInfo(String segment) {
+        this.segment = segment;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>UnbindInfo</code> object from the root element present
+     * in the request body.
+     *
+     * @param root the root element of the request body
+     * @return a UnbindInfo object containing a segment identifier
+     * @throws org.apache.jackrabbit.webdav.DavException if the UNBIND request is malformed
+     */
+    public static UnbindInfo createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_UNBIND, BindConstants.NAMESPACE)) {
+            log.warn("DAV:unbind element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurrence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new UnbindInfo(segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element unbindElt = DomUtil.createElement(document, BindConstants.XML_UNBIND, BindConstants.NAMESPACE);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        unbindElt.appendChild(segElt);
+        return unbindElt;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java
new file mode 100644
index 000000000..05d41820c
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.jackrabbit.webdav.bind;
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java
new file mode 100644
index 000000000..ca365b75f
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.lock.LockDiscovery;
+import org.apache.jackrabbit.webdav.observation.EventDiscovery;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.apache.jackrabbit.webdav.observation.Subscription;
+import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+/**
+ * Base class for HTTP request classes defined in this package.
+ */
+public abstract class BaseDavRequest extends HttpEntityEnclosingRequestBase {
+
+    private static Logger log = LoggerFactory.getLogger(BaseDavRequest.class);
+
+    public BaseDavRequest(URI uri) {
+        super();
+        super.setURI(uri);
+    }
+
+    /**
+     * Gets a {@link Document} representing the response body.
+     * @return document or {@code null} for null entity
+     * @throws IOException in case of I/O or XMP pasting problems 
+     */
+    public Document getResponseBodyAsDocument(HttpEntity entity) throws IOException {
+
+        if (entity == null) {
+            return null;
+        } else {
+            // read response and try to build a xml document
+            InputStream in = entity.getContent();
+            try {
+                return DomUtil.parseDocument(in);
+            } catch (ParserConfigurationException ex) {
+                throw new IOException("XML parser configuration error", ex);
+            } catch (SAXException ex) {
+                throw new IOException("XML parsing error", ex);
+            } finally {
+                in.close();
+            }
+        }
+    }
+
+    /**
+     * Return response body as {@link MultiStatus} object.
+     * @throws IllegalStateException when response does not represent a {@link MultiStatus}
+     * @throws DavException for failures in obtaining/parsing the response body
+     */
+    public MultiStatus getResponseBodyAsMultiStatus(HttpResponse response) throws DavException {
+        try {
+            Document doc = getResponseBodyAsDocument(response.getEntity());
+            if (doc == null) {
+                throw new DavException(response.getStatusLine().getStatusCode(), "no response body");
+            }
+            return MultiStatus.createFromXml(doc.getDocumentElement());
+        } catch (IOException ex) {
+            throw new DavException(response.getStatusLine().getStatusCode(), ex);
+        }
+    }
+
+    /**
+     * Return response body as {@link LockDiscovery} object.
+     * @throws IllegalStateException when response does not represent a {@link LockDiscovery}
+     * @throws DavException for failures in obtaining/parsing the response body
+     */
+    public LockDiscovery getResponseBodyAsLockDiscovery(HttpResponse response) throws DavException {
+        try {
+            Document doc = getResponseBodyAsDocument(response.getEntity());
+            if (doc == null) {
+                throw new DavException(response.getStatusLine().getStatusCode(), "no response body");
+            }
+            Element root = doc.getDocumentElement();
+
+            if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE)
+                    && DomUtil.hasChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE)) {
+                throw new DavException(response.getStatusLine().getStatusCode(),
+                        "Missing DAV:prop response body in LOCK response.");
+            }
+
+            Element lde = DomUtil.getChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE);
+            if (!DomUtil.hasChildElement(lde, DavConstants.XML_ACTIVELOCK, DavConstants.NAMESPACE)) {
+                throw new DavException(response.getStatusLine().getStatusCode(),
+                        "The DAV:lockdiscovery must contain a least a single DAV:activelock in response to a successful LOCK request.");
+            }
+
+            return LockDiscovery.createFromXml(lde);
+        } catch (IOException ex) {
+            throw new DavException(response.getStatusLine().getStatusCode(), ex);
+        }
+    }
+
+    /**
+     * Return response body as {@link SubscriptionDiscovery} object.
+     * @throws IllegalStateException when response does not represent a {@link SubscriptionDiscovery}
+     * @throws DavException for failures in obtaining/parsing the response body
+     */
+    public SubscriptionDiscovery getResponseBodyAsSubscriptionDiscovery(HttpResponse response) throws DavException {
+        try {
+            Document doc = getResponseBodyAsDocument(response.getEntity());
+            if (doc == null) {
+                throw new DavException(response.getStatusLine().getStatusCode(), "no response body");
+            }
+            Element root = doc.getDocumentElement();
+
+            if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE)
+                    && DomUtil.hasChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(),
+                            ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) {
+                throw new DavException(response.getStatusLine().getStatusCode(),
+                        "Missing DAV:prop response body in SUBSCRIBE response.");
+            }
+
+            Element sde = DomUtil.getChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(),
+                    ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace());
+            SubscriptionDiscovery sd = SubscriptionDiscovery.createFromXml(sde);
+            if (((Subscription[]) sd.getValue()).length > 0) {
+                return sd;
+            } else {
+                throw new DavException(response.getStatusLine().getStatusCode(),
+                        "Missing 'subscription' elements in SUBSCRIBE response body. At least a single subscription must be present if SUBSCRIBE was successful.");
+            }
+        } catch (IOException ex) {
+            throw new DavException(response.getStatusLine().getStatusCode(), ex);
+        }
+    }
+
+    /**
+     * Return response body as {@link EventDiscovery} object.
+     * @throws IllegalStateException when response does not represent a {@link EventDiscovery}
+     * @throws DavException for failures in obtaining/parsing the response body
+     */
+    public EventDiscovery getResponseBodyAsEventDiscovery(HttpResponse response) throws DavException {
+        try {
+            Document doc = getResponseBodyAsDocument(response.getEntity());
+            if (doc == null) {
+                throw new DavException(response.getStatusLine().getStatusCode(), "no response body");
+            }
+            return EventDiscovery.createFromXml(doc.getDocumentElement());
+        } catch (IOException ex) {
+            throw new DavException(response.getStatusLine().getStatusCode(), ex);
+        }
+    }
+
+    /**
+     * Check the response and throw when it is considered to represent a failure.
+     */
+    public void checkSuccess(HttpResponse response) throws DavException {
+        if (!succeeded(response)) {
+            throw getResponseException(response);
+        }
+    }
+
+    /**
+     * Obtain a {@link DavException} representing the response.
+     * @throws IllegalStateException when the response is considered to be successful
+     */
+    public DavException getResponseException(HttpResponse response) {
+        if (succeeded(response)) {
+            String msg = "Cannot retrieve exception from successful response.";
+            log.warn(msg);
+            throw new IllegalStateException(msg);
+        }
+
+        StatusLine st = response.getStatusLine();
+        Element responseRoot = null;
+        try {
+            responseRoot = getResponseBodyAsDocument(response.getEntity()).getDocumentElement();
+        } catch (IOException e) {
+            // non-parseable body -> use null element
+        }
+
+        return new DavException(st.getStatusCode(), st.getReasonPhrase(), null, responseRoot);
+    }
+
+    /**
+     * Check the provided {@link HttpResponse} for successful execution. The default implementation treats all
+     * 2xx status codes (<a href="http://webdav.org/specs/rfc7231.html#rfc.section.6.3">RFC 7231, Section 6.3</a>).
+     * Implementations can further restrict the accepted range of responses (or even check the response body).
+     */
+    public boolean succeeded(HttpResponse response) {
+        int status = response.getStatusLine().getStatusCode();
+        return status >= 200 && status <= 299;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java
new file mode 100644
index 000000000..4c2161810
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.bind.BindInfo;
+
+/**
+ * Represents an HTTP BIND request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc5842.html#rfc.section.4">RFC 5842, Section 4</a>
+ * @since 2.13.6
+ */
+public class HttpBind extends BaseDavRequest {
+
+    public HttpBind(URI uri, BindInfo info) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(info));
+    }
+
+    public HttpBind(String uri, BindInfo info) throws IOException {
+        this(URI.create(uri), info);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_BIND;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java
new file mode 100644
index 000000000..06b67aec0
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP CHECKIN request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.4.4">RFC 3253, Section 4.4</a>
+ * @since 2.13.6
+ */
+public class HttpCheckin extends BaseDavRequest {
+
+    public HttpCheckin(URI uri) {
+        super(uri);
+    }
+
+    public HttpCheckin(String uri) {
+        this(URI.create(uri));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_CHECKIN;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_CREATED;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java
new file mode 100644
index 000000000..a7f5e009b
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP CHECKOUT request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.4.3">RFC 3253, Section 4.3</a>
+ * @since 2.13.6
+ */
+public class HttpCheckout extends BaseDavRequest {
+
+    public HttpCheckout(URI uri) {
+        super(uri);
+    }
+
+    public HttpCheckout(String uri) {
+        this(URI.create(uri));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_CHECKOUT;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java
new file mode 100644
index 000000000..4f5337b87
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP COPY request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.8">RFC 4918, Section 9.8</a>
+ * @since 2.13.6
+ */
+public class HttpCopy extends BaseDavRequest {
+
+    public HttpCopy(URI uri, URI dest, boolean overwrite, boolean shallow) {
+        super(uri);
+        super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString());
+        if (!overwrite) {
+            super.setHeader(DavConstants.HEADER_OVERWRITE, "F");
+        }
+        if (shallow) {
+            super.setHeader("Depth", "0");
+        }
+    }
+
+    public HttpCopy(String uri, String dest, boolean overwrite, boolean shallow) {
+        this(URI.create(uri), URI.create(dest), overwrite, shallow);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_COPY;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java
new file mode 100644
index 000000000..99c283bab
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.jackrabbit.webdav.DavMethods;
+
+/**
+ * Represents an HTTP DELETE request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc7231.html#rfc.section.4.3.5">RFC 7231, Section 4.3.5</a>
+ * @since 2.13.6
+ */
+public class HttpDelete extends BaseDavRequest {
+
+    public HttpDelete(URI uri){
+        super(uri);
+    }
+
+    public HttpDelete(String uri) {
+        this(URI.create(uri));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_DELETE;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java
new file mode 100644
index 000000000..05c6f48ce
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.DepthHeader;
+import org.apache.jackrabbit.webdav.version.LabelInfo;
+
+/**
+ * Represents an HTTP LABEL request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.8.2">RFC 3253, Section 8.2</a>
+ * @since 2.13.6
+ */
+public class HttpLabel extends BaseDavRequest {
+
+    public HttpLabel(URI uri, LabelInfo labelInfo) throws IOException {
+        super(uri);
+        DepthHeader dh = new DepthHeader(labelInfo.getDepth());
+        super.setHeader(dh.getHeaderName(), dh.getHeaderValue());
+        super.setEntity(XmlEntity.create(labelInfo));
+    }
+
+    public HttpLabel(String uri, LabelInfo labelInfo) throws IOException {
+        this(URI.create(uri), labelInfo);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_LABEL;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java
new file mode 100644
index 000000000..171776d17
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.DepthHeader;
+import org.apache.jackrabbit.webdav.header.IfHeader;
+import org.apache.jackrabbit.webdav.header.TimeoutHeader;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents an HTTP LOCK request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.10">RFC 4918, Section 9.10</a>
+ * @since 2.13.6
+ */
+public class HttpLock extends BaseDavRequest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpLock.class);
+
+    private final boolean isRefresh;
+
+    public HttpLock(URI uri, LockInfo lockInfo) throws IOException {
+        super(uri);
+
+        TimeoutHeader th = new TimeoutHeader(lockInfo.getTimeout());
+        super.setHeader(th.getHeaderName(), th.getHeaderValue());
+        DepthHeader dh = new DepthHeader(lockInfo.isDeep());
+        super.setHeader(dh.getHeaderName(), dh.getHeaderValue());
+
+        super.setEntity(XmlEntity.create(lockInfo));
+
+        isRefresh = false;
+    }
+
+    public HttpLock(String uri, LockInfo lockInfo) throws IOException {
+        this(URI.create(uri), lockInfo);
+    }
+
+    public HttpLock(URI uri, long timeout, String[] lockTokens) {
+        super(uri);
+
+        TimeoutHeader th = new TimeoutHeader(timeout);
+        super.setHeader(th.getHeaderName(), th.getHeaderValue());
+        IfHeader ifh = new IfHeader(lockTokens);
+        super.setHeader(ifh.getHeaderName(), ifh.getHeaderValue());
+        isRefresh = true;
+    }
+
+    public HttpLock(String uri, long timeout, String[] lockTokens) {
+        this(URI.create(uri), timeout, lockTokens);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_LOCK;
+    }
+
+    public String getLockToken(HttpResponse response) {
+        Header[] ltHeader = response.getHeaders(DavConstants.HEADER_LOCK_TOKEN);
+        if (ltHeader == null || ltHeader.length == 0) {
+            return null;
+        } else if (ltHeader.length != 1) {
+            LOG.debug("Multiple 'Lock-Token' header fields in response for " + getURI() + ": " + Arrays.asList(ltHeader));
+            return null;
+        } else {
+            String v = ltHeader[0].getValue().trim();
+            if (!v.startsWith("<") || !v.endsWith(">")) {
+                LOG.debug("Invalid 'Lock-Token' header field in response for " + getURI() + ": " + Arrays.asList(ltHeader));
+                return null;
+            } else {
+                return v.substring(1, v.length() - 1);
+            }
+        }
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        boolean lockTokenHeaderOk = isRefresh || null != getLockToken(response);
+        return lockTokenHeaderOk && (statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED);
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java
new file mode 100644
index 000000000..b8db71dcf
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.version.MergeInfo;
+
+/**
+ * Represents an HTTP MERGE request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.11.2">RFC 3253, Section 11.2</a>
+ * @since 2.13.6
+ */
+public class HttpMerge extends BaseDavRequest {
+
+    public HttpMerge(URI uri, MergeInfo mergeInfo) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(mergeInfo));
+    }
+
+    public HttpMerge(String uri, MergeInfo mergeInfo) throws IOException {
+        this(URI.create(uri), mergeInfo);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_MERGE;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        // TODO: is this correct?
+        return statusCode == DavServletResponse.SC_MULTI_STATUS;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java
new file mode 100644
index 000000000..5ecf6a237
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP MKCOL request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.3">RFC 4918, Section 9.3</a>
+ * @since 2.13.6
+ */
+public class HttpMkcol extends BaseDavRequest {
+
+    public HttpMkcol(URI uri) {
+        super(uri);
+    }
+
+    public HttpMkcol(String uri) {
+        this(URI.create(uri));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_MKCOL;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_CREATED;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java
new file mode 100644
index 000000000..1c14fe52a
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP MKWORKSPACE request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.6.3">RFC 3253, Section 6.3</a>
+ * @since 2.13.6
+ */
+public class HttpMkworkspace extends BaseDavRequest {
+
+    public HttpMkworkspace(URI uri) {
+        super(uri);
+    }
+
+    public HttpMkworkspace(String uri) {
+        this(URI.create(uri));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_MKWORKSPACE;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_CREATED;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java
new file mode 100644
index 000000000..2411e0891
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP MOVE request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.9">RFC 4918, Section 9.9</a>
+ * @since 2.13.6
+ */
+public class HttpMove extends BaseDavRequest {
+
+    public HttpMove(URI uri, URI dest, boolean overwrite) {
+        super(uri);
+        super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString());
+        if (!overwrite) {
+            super.setHeader(DavConstants.HEADER_OVERWRITE, "F");
+        }
+    }
+
+    public HttpMove(String uri, String dest, boolean overwrite) {
+        this(URI.create(uri), URI.create(dest), overwrite);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_MOVE;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java
new file mode 100644
index 000000000..4986ee2b9
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.header.FieldValueParser;
+import org.apache.jackrabbit.webdav.search.SearchConstants;
+
+/**
+ * Represents an HTTP OPTIONS request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc7231.html#rfc.section.4.3.7">RFC 7231, Section 4.3.7</a>
+ * @since 2.13.6
+ */
+public class HttpOptions extends org.apache.http.client.methods.HttpOptions {
+
+    public HttpOptions(URI uri) {
+        super(uri);
+    }
+
+    public HttpOptions(String uri) {
+        super(URI.create(uri));
+    }
+
+    /**
+     * Compute the set of compliance classes returned in the "dav" header field
+     */
+    public Set<String> getDavComplianceClasses(HttpResponse response) {
+        Header[] headers = response.getHeaders(DavConstants.HEADER_DAV);
+        return parseTokenOrCodedUrlheaderField(headers, false);
+    }
+
+    /**
+     * Compute set of search grammars returned in the "dasl" header field
+     */
+    public Set<String> getSearchGrammars(HttpResponse response) {
+        Header[] headers = response.getHeaders(SearchConstants.HEADER_DASL);
+        return parseTokenOrCodedUrlheaderField(headers, true);
+    }
+
+    private Set<String> parseTokenOrCodedUrlheaderField(Header[] headers, boolean removeBrackets) {
+        if (headers == null) {
+            return Collections.emptySet();
+        }
+        else {
+            Set<String> result = new HashSet<String>();
+            for (Header h : headers) {
+                for (String s : FieldValueParser.tokenizeList(h.getValue())) {
+                    if (removeBrackets && s.startsWith("<") && s.endsWith(">")) {
+                        s = s.substring(1, s.length() - 1);
+                    }
+                    result.add(s.trim());
+                }
+            }
+            return Collections.unmodifiableSet(result);
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java
new file mode 100644
index 000000000..0e6f0fbf0
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.ordering.OrderPatch;
+
+/**
+ * Represents an HTTP ORDERPATCH request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3648.html#rfc.section.5">RFC 3648, Section 5</a>
+ * @since 2.13.6
+ */
+public class HttpOrderpatch extends BaseDavRequest {
+
+    public HttpOrderpatch(URI uri, OrderPatch info) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(info));
+    }
+
+    public HttpOrderpatch(String uri, OrderPatch info) throws IOException {
+        this(URI.create(uri), info);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_ORDERPATCH;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        return response.getStatusLine().getStatusCode() == DavServletResponse.SC_OK;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java
new file mode 100644
index 000000000..af7d62084
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.PollTimeoutHeader;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+
+/**
+ * Represents an HTTP POLL request.
+ * <p>
+ * Note that "POLL" is a custom HTTP extension, not defined in a standards paper.
+ * @since 2.13.6
+ */
+public class HttpPoll extends BaseDavRequest {
+
+    public HttpPoll(URI uri, String subscriptionId, long timeout) {
+        super(uri);
+        super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId);
+        if (timeout > 0) {
+            PollTimeoutHeader th = new PollTimeoutHeader(timeout);
+            super.setHeader(th.getHeaderName(), th.getHeaderValue());
+        }
+    }
+
+    public HttpPoll(String uri, String subscriptionId, long timeout) {
+        this(URI.create(uri), subscriptionId, timeout);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_POLL;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java
new file mode 100644
index 000000000..e548db069
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.DepthHeader;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.PropfindInfo;
+
+/**
+ * Represents an HTTP PROPFIND request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.1">RFC 4918, Section 9.1</a>
+ * @since 2.13.6
+ */
+public class HttpPropfind extends BaseDavRequest {
+
+    public HttpPropfind(URI uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException {
+        super(uri);
+
+        DepthHeader dh = new DepthHeader(depth);
+        super.setHeader(dh.getHeaderName(), dh.getHeaderValue());
+
+        PropfindInfo info = new PropfindInfo(propfindType, names);
+        super.setEntity(XmlEntity.create(info));
+    }
+
+    public HttpPropfind(URI uri, DavPropertyNameSet names, int depth) throws IOException {
+        this(uri, DavConstants.PROPFIND_BY_PROPERTY, names, depth);
+    }
+
+    public HttpPropfind(URI uri, int propfindType, int depth) throws IOException {
+        this(uri, propfindType, new DavPropertyNameSet(), depth);
+    }
+
+    public HttpPropfind(String uri, int propfindType, int depth) throws IOException {
+        this(URI.create(uri), propfindType, depth);
+    }
+
+    public HttpPropfind(String uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException {
+        this(URI.create(uri), propfindType, names, depth);
+    }
+
+    public HttpPropfind(String uri, DavPropertyNameSet names, int depth) throws IOException {
+        this(URI.create(uri), names, depth);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_PROPFIND;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java
new file mode 100644
index 000000000..2cd35f8f0
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.PropEntry;
+import org.apache.jackrabbit.webdav.property.ProppatchInfo;
+
+/**
+ * Represents an HTTP PROPPATCH request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.2">RFC 4918, Section 9.2</a>
+ * @since 2.13.6
+ */
+public class HttpProppatch extends BaseDavRequest {
+
+    // private DavPropertyNameSet propertyNames;
+
+    public HttpProppatch(URI uri, ProppatchInfo info) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(info));
+        // this.propertyNames = info.getAffectedProperties();
+    }
+
+    public HttpProppatch(URI uri, List<? extends PropEntry> changeList) throws IOException {
+        this(uri, new ProppatchInfo(changeList));
+    }
+
+    public HttpProppatch(URI uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException {
+        this(uri, new ProppatchInfo(setProperties, removeProperties));
+    }
+
+    public HttpProppatch(String uri, List<? extends PropEntry> changeList) throws IOException {
+        this(URI.create(uri), new ProppatchInfo(changeList));
+    }
+
+    public HttpProppatch(String uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException {
+        this(URI.create(uri), new ProppatchInfo(setProperties, removeProperties));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_PROPPATCH;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS;
+
+        // disabled code that fails for current PROPPATCH behavior of Jackrabbit
+//        MultiStatusResponse responses[] = super.getResponseBodyAsMultiStatus(response).getResponses();
+//        if (responses.length != 1) {
+//            throw new DavException(DavServletResponse.SC_MULTI_STATUS,
+//                    "PROPPATCH failed: Expected exactly one multistatus response element, but got " + responses.length);
+//        }
+//        DavPropertyNameSet okSet = responses[0].getPropertyNames(DavServletResponse.SC_OK);
+//        if (okSet.isEmpty()) {
+//            throw new DavException(DavServletResponse.SC_MULTI_STATUS,
+//                    "PROPPATCH failed: No 'OK' response found for resource " + responses[0].getHref());
+//        } else {
+//            DavPropertyNameIterator it = propertyNames.iterator();
+//            while (it.hasNext()) {
+//                DavPropertyName pn = it.nextPropertyName();
+//                boolean success = okSet.remove(pn);
+//                if (!success) {
+//                    throw new DavException(DavServletResponse.SC_MULTI_STATUS,
+//                            "PROPPATCH failed: Property name not present in multistatus response: " + pn);
+//                }
+//            }
+//        }
+//        if (!okSet.isEmpty()) {
+//            StringBuilder b = new StringBuilder();
+//            DavPropertyNameIterator it = okSet.iterator();
+//            while (it.hasNext()) {
+//                b.append(it.nextPropertyName().toString()).append("; ");
+//            }
+//            throw new DavException(DavServletResponse.SC_MULTI_STATUS,
+//                    "PROPPATCH failed: The following properties outside of the original request where set or removed: " + b.toString());
+//        }
+//        return true;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java
new file mode 100644
index 000000000..e72dea890
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.bind.RebindInfo;
+
+/**
+ * Represents an HTTP REBIND request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc5842.html#rfc.section.6">RFC 5842, Section 6</a>
+ * @since 2.13.6
+ */
+public class HttpRebind extends BaseDavRequest {
+
+    public HttpRebind(URI uri, RebindInfo info) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(info));
+    }
+
+    public HttpRebind(String uri, RebindInfo info) throws IOException {
+        this(URI.create(uri), info);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_REBIND;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java
new file mode 100644
index 000000000..efb20b6ca
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.DepthHeader;
+import org.apache.jackrabbit.webdav.version.report.ReportInfo;
+
+/**
+ * Represents an HTTP REPORT request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.3.6">RFC 3253, Section 3.6</a>
+ * @since 2.13.6
+ */
+public class HttpReport extends BaseDavRequest {
+
+    private final boolean isDeep;
+
+    public HttpReport(URI uri, ReportInfo reportInfo) throws IOException {
+        super(uri);
+        DepthHeader dh = new DepthHeader(reportInfo.getDepth());
+        isDeep = reportInfo.getDepth() > DavConstants.DEPTH_0;
+        super.setHeader(dh.getHeaderName(), dh.getHeaderValue());
+        super.setEntity(XmlEntity.create(reportInfo));
+    }
+
+    public HttpReport(String uri, ReportInfo reportInfo) throws IOException {
+        this(URI.create(uri), reportInfo);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_REPORT;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        if (isDeep) {
+            return statusCode == DavServletResponse.SC_MULTI_STATUS;
+        } else {
+            return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_MULTI_STATUS;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java
new file mode 100644
index 000000000..f230f2dfb
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.search.SearchInfo;
+
+/**
+ * Represents an HTTP SEARCH request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc5323.html#rfc.section.2">RFC 5323, Section 2</a>
+ * @since 2.13.6
+ */
+public class HttpSearch extends BaseDavRequest {
+
+    public HttpSearch(URI uri, SearchInfo searchInfo) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(searchInfo));
+    }
+
+    public HttpSearch(String uri, SearchInfo searchInfo) throws IOException {
+        this(URI.create(uri), searchInfo);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_SEARCH;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_MULTI_STATUS;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java
new file mode 100644
index 000000000..6bdbb7adc
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
+import org.apache.jackrabbit.webdav.header.DepthHeader;
+import org.apache.jackrabbit.webdav.header.TimeoutHeader;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
+
+/**
+ * Represents an HTTP SUBSCRIBE request.
+ * <p>
+ * Note that "SUBSCRIBE" is a custom HTTP extension, not defined in a standards paper.
+ * @since 2.13.6
+ */
+public class HttpSubscribe extends BaseDavRequest {
+
+    public HttpSubscribe(URI uri, SubscriptionInfo info, String subscriptionId) throws IOException {
+        super(uri);
+        if (info == null) {
+            throw new IllegalArgumentException("SubscriptionInfo must not be null.");
+        }
+        // optional subscriptionId (only required to modify an existing
+        // subscription)
+        if (subscriptionId != null) {
+            CodedUrlHeader h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId);
+            super.setHeader(h.getHeaderName(), h.getHeaderValue());
+        }
+        // optional timeout header
+        long to = info.getTimeOut();
+        if (to != DavConstants.UNDEFINED_TIMEOUT) {
+            TimeoutHeader h = new TimeoutHeader(info.getTimeOut());
+            super.setHeader(h.getHeaderName(), h.getHeaderValue());
+        }
+        // always set depth header since value is boolean flag
+        DepthHeader dh = new DepthHeader(info.isDeep());
+        super.setHeader(dh.getHeaderName(), dh.getHeaderValue());
+        super.setEntity(XmlEntity.create(info));
+    }
+
+    public HttpSubscribe(String uri, SubscriptionInfo info, String subscriptionId) throws IOException {
+        this(URI.create(uri), info, subscriptionId);
+    }
+
+    public String getSubscriptionId(HttpResponse response) {
+        org.apache.http.Header sbHeader = response.getFirstHeader(ObservationConstants.HEADER_SUBSCRIPTIONID);
+        if (sbHeader != null) {
+            CodedUrlHeader cuh = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, sbHeader.getValue());
+            return cuh.getCodedUrl();
+        }
+        else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_SUBSCRIBE;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java
new file mode 100644
index 000000000..10e7f4a5b
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.bind.UnbindInfo;
+
+/**
+ * Represents an HTTP UNBIND request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc5842.html#rfc.section.5">RFC 5842, Section 5</a>
+ * @since 2.13.6
+ */
+public class HttpUnbind extends BaseDavRequest {
+
+    public HttpUnbind(URI uri, UnbindInfo info) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(info));
+    }
+
+    public HttpUnbind(String uri, UnbindInfo info) throws IOException {
+        this(URI.create(uri), info);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_UNBIND;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java
new file mode 100644
index 000000000..aee347365
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
+
+/**
+ * Represents an HTTP UNLOCK request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc4918.html#rfc.section.9.11">RFC 4918, Section 9.11</a>
+ * @since 2.13.6
+ */
+public class HttpUnlock extends BaseDavRequest {
+
+    public HttpUnlock(URI uri, String lockToken) {
+        super(uri);
+        CodedUrlHeader lth = new CodedUrlHeader(DavConstants.HEADER_LOCK_TOKEN, lockToken);
+        super.setHeader(lth.getHeaderName(), lth.getHeaderValue());
+    }
+
+    public HttpUnlock(String uri, String lockToken) {
+        this(URI.create(uri), lockToken);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_UNLOCK;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java
new file mode 100644
index 000000000..522f17fce
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+
+/**
+ * Represents an HTTP UNSUBSCRIBE request.
+ * <p>
+ * Note that "UNSUBSCRIBE" is a custom HTTP extension, not defined in a standards paper.
+ * @since 2.13.6
+ */
+public class HttpUnsubscribe extends BaseDavRequest {
+
+    public HttpUnsubscribe(URI uri, String subscriptionId) {
+        super(uri);
+        super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId);
+    }
+
+    public HttpUnsubscribe(String uri, String subscriptionId) {
+        this(URI.create(uri), subscriptionId);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_UNSUBSCRIBE;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_NO_CONTENT;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java
new file mode 100644
index 000000000..019a24fff
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.version.UpdateInfo;
+
+/**
+ * Represents an HTTP UPDATE request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.7.1">RFC 3253, Section 7.1</a>
+ * @since 2.13.6
+ */
+public class HttpUpdate extends BaseDavRequest {
+
+    public HttpUpdate(URI uri, UpdateInfo updateInfo) throws IOException {
+        super(uri);
+        super.setEntity(XmlEntity.create(updateInfo));
+    }
+
+    public HttpUpdate(String uri, UpdateInfo updateInfo) throws IOException {
+        this(URI.create(uri), updateInfo);
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_UPDATE;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_MULTI_STATUS;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java
new file mode 100644
index 000000000..e23a601be
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.net.URI;
+
+import org.apache.http.HttpResponse;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+/**
+ * Represents an HTTP VERSION-CONTROL request.
+ * 
+ * @see <a href="http://webdav.org/specs/rfc3253.html#rfc.section.3.5">RFC 3253, Section 3.5</a>
+ * @since 2.13.6
+ */
+public class HttpVersionControl extends BaseDavRequest {
+
+    public HttpVersionControl(URI uri) {
+        super(uri);
+    }
+
+    public HttpVersionControl(String uri) {
+        this(URI.create(uri));
+    }
+
+    @Override
+    public String getMethod() {
+        return DavMethods.METHOD_VERSION_CONTROL;
+    }
+
+    @Override
+    public boolean succeeded(HttpResponse response) {
+        int statusCode = response.getStatusLine().getStatusCode();
+        return statusCode == DavServletResponse.SC_OK;
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java
new file mode 100644
index 000000000..859bbe404
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.client.methods;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * Utility methods for creating request entities from {@link Document}s or {@link XmlSerializable}s.
+ */
+public class XmlEntity {
+
+    private static Logger LOG = LoggerFactory.getLogger(XmlEntity.class);
+
+    private static ContentType CT = ContentType.create("application/xml", "UTF-8");
+
+    public static HttpEntity create(Document doc) throws IOException {
+        try {
+            ByteArrayOutputStream xml = new ByteArrayOutputStream();
+            DomUtil.transformDocument(doc, xml);
+            return new ByteArrayEntity(xml.toByteArray(), CT);
+        } catch (TransformerException ex) {
+            LOG.error(ex.getMessage());
+            throw new IOException(ex);
+        } catch (SAXException ex) {
+            LOG.error(ex.getMessage());
+            throw new IOException(ex);
+        }
+    }
+
+    public static HttpEntity create(XmlSerializable payload) throws IOException {
+        try {
+            Document doc = DomUtil.createDocument();
+            doc.appendChild(payload.toXml(doc));
+            return create(doc);
+        } catch (ParserConfigurationException ex) {
+            LOG.error(ex.getMessage());
+            throw new IOException(ex);
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java
new file mode 100644
index 000000000..b667d39c6
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides classes for use with the Apache HttpClient, supporting WebDAV
+ * request methods.
+ * <p>
+ * This version also contains classes for use with the obsolete "Commons
+ * HttpClient"; they have been marked "deprecated" and will be removed in the
+ * next major release.
+ * 
+ * @see <a href="https://issues.apache.org/jira/browse/JCR-2406">JCR-2406</a>
+ * @see <a href=
+ *      "https://hc.apache.org/httpcomponents-client-4.5.x/">https://hc.apache.org/httpcomponents-client-4.5.x/</a>
+ */
+@org.osgi.annotation.versioning.Version("2.0.0")
+package org.apache.jackrabbit.webdav.client.methods;
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java
new file mode 100644
index 000000000..edbe8aed9
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * <code>CodedUrlHeader</code>...
+ */
+public class CodedUrlHeader implements Header {
+
+    private static Logger log = LoggerFactory.getLogger(CodedUrlHeader.class);
+
+    private final String headerName;
+    private final String headerValue;
+
+    public CodedUrlHeader(String headerName, String headerValue) {
+        this.headerName = headerName;
+        if (headerValue != null && !(headerValue.startsWith("<") && headerValue.endsWith(">"))) {
+            headerValue = "<" + headerValue + ">";
+        }
+        this.headerValue = headerValue;
+    }
+
+    /**
+     * Return the name of the header
+     *
+     * @return header name
+     * @see Header#getHeaderName()
+     */
+    public String getHeaderName() {
+	return headerName;
+    }
+
+    /**
+     * Return the value of the header
+     *
+     * @return value
+     * @see Header#getHeaderValue()
+     */
+    public String getHeaderValue() {
+        return headerValue;
+    }
+
+    /**
+     * Returns the token present in the header value or <code>null</code>.
+     * If the header contained multiple tokens separated by ',' the first value
+     * is returned.
+     *
+     * @return token present in the CodedURL header or <code>null</code> if
+     * the header is not present.
+     * @see #getCodedUrls()
+     */
+    public String getCodedUrl() {
+        String[] codedUrls = getCodedUrls();
+        return (codedUrls != null) ? codedUrls[0] : null;
+    }
+
+    /**
+     * Return an array of coded urls as present in the header value or <code>null</code> if
+     * no value is present.
+     *
+     * @return array of coded urls
+     */
+    public String[] getCodedUrls() {
+        String[] codedUrls = null;
+        if (headerValue != null) {
+            String[] values = headerValue.split(",");
+            codedUrls = new String[values.length];
+            for (int i = 0; i < values.length; i++) {
+                int p1 = values[i].indexOf('<');
+                if (p1<0) {
+                    throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]);
+                }
+                int p2 = values[i].indexOf('>', p1);
+                if (p2<0) {
+                    throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]);
+                }
+                codedUrls[i] = values[i].substring(p1+1, p2);
+            }
+	}
+        return codedUrls;
+    }
+
+    /**
+     * Retrieves the header with the given name and builds a new <code>CodedUrlHeader</code>.
+     *
+     * @param request
+     * @param headerName
+     * @return new <code>CodedUrlHeader</code> instance
+     */
+    public static CodedUrlHeader parse(HttpServletRequest request, String headerName) {
+        String headerValue = request.getHeader(headerName);
+        return new CodedUrlHeader(headerName, headerValue);
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java
new file mode 100644
index 000000000..9b74194a5
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * <code>DepthHeader</code>...
+ */
+public class DepthHeader implements Header, DavConstants {
+
+    private static Logger log = LoggerFactory.getLogger(DepthHeader.class);
+
+    private final int depth;
+
+    /**
+     * Create a new <code>DepthHeader</code> from the given integer.
+     *
+     * @param depth
+     */
+    public DepthHeader(int depth) {
+	if (depth == DEPTH_0 || depth == DEPTH_1 || depth == DEPTH_INFINITY) {
+	    this.depth = depth;
+	} else {
+	    throw new IllegalArgumentException("Invalid depth: " + depth);
+	}
+    }
+
+    /**
+     * Create a new <code>DepthHeader</code> with either value {@link #DEPTH_0 0}
+     * or {@link #DEPTH_INFINITY infinity}.
+     *
+     * @param isDeep
+     */
+    public DepthHeader(boolean isDeep) {
+        this.depth = (isDeep) ? DEPTH_INFINITY : DEPTH_0;
+    }
+
+    /**
+     * @return integer representation of the depth indicated by the given header.
+     */
+    public int getDepth() {
+        return depth;
+    }
+
+    /**
+     * Return {@link DavConstants#HEADER_DEPTH Depth}
+     *
+     * @return {@link DavConstants#HEADER_DEPTH Depth}
+     * @see DavConstants#HEADER_DEPTH
+     * @see Header#getHeaderName()
+     */
+    public String getHeaderName() {
+	return DavConstants.HEADER_DEPTH;
+    }
+
+    /**
+     * Returns the header value.
+     *
+     * @return header value
+     * @see Header#getHeaderValue()
+     */
+    public String getHeaderValue() {
+        if (depth == DavConstants.DEPTH_0 || depth == DavConstants.DEPTH_1) {
+	    return String.valueOf(depth);
+	} else {
+	    return DavConstants.DEPTH_INFINITY_S;
+	}
+    }
+
+    /**
+     * Retrieve the Depth header from the given request object and parse the
+     * value. If no header is present or the value is empty String, the
+     * defaultValue is used ot build a new <code>DepthHeader</code> instance.
+     *
+     * @param request
+     * @param defaultValue
+     * @return a new <code>DepthHeader</code> instance
+     */
+    public static DepthHeader parse(HttpServletRequest request, int defaultValue) {
+        String headerValue = request.getHeader(HEADER_DEPTH);
+        if (headerValue == null || "".equals(headerValue)) {
+	    return new DepthHeader(defaultValue);
+	} else {
+	    return new DepthHeader(depthToInt(headerValue));
+	}
+    }
+
+    /**
+     * Convert the String depth value to an integer.
+     *
+     * @param depth
+     * @return integer representation of the given depth String
+     * @throws IllegalArgumentException if the String does not represent a valid
+     * depth.
+     */
+    private static int depthToInt(String depth) {
+        int d;
+	if (depth.equalsIgnoreCase(DavConstants.DEPTH_INFINITY_S)) {
+	    d = DavConstants.DEPTH_INFINITY;
+	} else if (depth.equals(DavConstants.DEPTH_0+"")) {
+	    d = DavConstants.DEPTH_0;
+	} else if (depth.equals(DavConstants.DEPTH_1+"")) {
+	    d = DavConstants.DEPTH_1;
+	} else {
+	    throw new IllegalArgumentException("Invalid depth value: " + depth);
+	}
+        return d;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java
new file mode 100644
index 000000000..6f3052168
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class FieldValueParser {
+
+    /**
+     * Tokenize lists of token and quoted-url
+     * @param list field value
+     */
+    public static List<String> tokenizeList(String list) {
+
+        String[] split = list.split(",");
+        if (split.length == 1) {
+            return Collections.singletonList(split[0].trim());
+        } else {
+            List<String> result = new ArrayList<String>();
+            String inCodedUrl = null;
+            for (String t : split) {
+                String trimmed = t.trim();
+                // handle quoted-url containing ","
+                if (trimmed.startsWith("<") && !trimmed.endsWith(">")) {
+                    inCodedUrl = trimmed + ",";
+                } else if (inCodedUrl != null && trimmed.endsWith(">")) {
+                    inCodedUrl += trimmed;
+                    result.add(inCodedUrl);
+                    inCodedUrl = null;
+                } else {
+                    if (trimmed.length() != 0) {
+                        result.add(trimmed);
+                    }
+                }
+            }
+            return Collections.unmodifiableList(result);
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/Header.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/Header.java
new file mode 100644
index 000000000..f61a07e90
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/Header.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+/**
+ * <code>Header</code>...
+ */
+public interface Header {
+
+    public String getHeaderName();
+
+    public String getHeaderValue();
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java
new file mode 100644
index 000000000..43ff4dbac
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java
@@ -0,0 +1,905 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The <code>IfHeader</code> class represents the state lists defined
+ * through the HTTP <em>If</em> header, which is specified in RFC 2518 as
+ * follows :
+ * <pre>
+     If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
+     No-tag-list = List
+     Tagged-list = Resource 1*List
+     Resource = Coded-URL
+     List = "(" 1*(["Not"](State-etag | "[" entity-tag "]")) ")"
+     State-etag = Coded-URL
+     Coded-URL = "&lt;" absoluteURI "&gt;"
+ * </pre>
+ * <p>
+ * Reformulating this specification into proper EBNF as specified by N. Wirth
+ * we get the following productions, which map to the parse METHODS of this
+ * class. Any whitespace is ignored except for white space surrounding and
+ * within words which is considered significant.
+ * <pre>
+     If = "If:" ( Tagged | Untagged ).
+     Tagged = { "&lt;" Word "&gt;" Untagged } .
+     Untagged = { "(" IfList ")" } .
+     IfList = { [ "Not" ] ( ("&lt;" Word "&gt;" ) | ( "[" Word "]" ) ) } .
+     Word = characters .
+ * </pre>
+ * <p>
+ * An <em>If</em> header either contains untagged <em>IfList</em> entries or
+ * tagged <em>IfList</em> entries but not a mixture of both. An <em>If</em>
+ * header containing tagged entries is said to be of <em>tagged</em> type while
+ * an <em>If</em> header containing untagged entries is said to be of
+ * <em>untagged</em> type.
+ * <p>
+ * An <em>IfList</em> is a list of tokens - words enclosed in <em>&lt; &gt;</em>
+ * - and etags - words enclosed in <em>[ ]</em>. An <em>IfList</em> matches a
+ * (token, etag) tuple if all entries in the list match. If an entry in the list
+ * is prefixed with the word <em>Not</em> (parsed case insensitively) the entry
+ * must not match the concrete token or etag.
+ * <p>
+ * Example: The <em>ifList</em> <code>(&lt;token&gt; [etag])</code> only matches
+ * if the concret token has the value <code>token</code> and the conrete etag
+ * has the value <code>etag</code>. On the other hand, the <em>ifList</em>
+ * <code>(Not &lt;notoken&gt;)</code> matches any token which is not
+ * <code>notoken</code> (in this case the concrete value of the etag is
+ * not taken into consideration).
+ *
+ * @author Felix Meschberger
+ */
+public class IfHeader implements Header {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(IfHeader.class);
+
+    /**
+     * The string representation of the header value
+     */
+    private final String headerValue;
+
+    /**
+     * The list of untagged state entries
+     */
+    private final IfHeaderInterface ifHeader;
+
+    /**
+     * The list of all positive tokens present in the If header.
+     */
+    private List<String> allTokens = new ArrayList<String>();
+    /**
+     * The list of all NOT tokens present in the If header.
+     */
+    private List<String> allNotTokens = new ArrayList<String>();
+
+    private String uriPrefix;
+
+    /**
+     * Create a Untagged <code>IfHeader</code> if the given lock tokens.
+     *
+     * @param tokens
+     */
+    public IfHeader(String[] tokens) {
+        allTokens.addAll(Arrays.asList(tokens));
+        StringBuffer b = new StringBuffer();
+        for (String token : tokens) {
+            b.append("(").append("<");
+            b.append(token);
+            b.append(">").append(")");
+        }
+        headerValue = b.toString();
+        ifHeader = parse();
+    }
+
+    /**
+     * Parses the <em>If</em> header and creates and internal representation
+     * which is easy to query.
+     *
+     * @param req The request object
+     */
+    public IfHeader(HttpServletRequest req) {
+        String host = req.getHeader("Host");
+        String scheme = req.getScheme();
+        uriPrefix = scheme + "://" + host + req.getContextPath();
+        headerValue = req.getHeader(DavConstants.HEADER_IF);
+        ifHeader = parse();
+    }
+
+    /**
+     * Return {@link DavConstants#HEADER_IF If}
+     *
+     * @return {@link DavConstants#HEADER_IF If}
+     * @see DavConstants#HEADER_IF
+     */
+    public String getHeaderName() {
+        return DavConstants.HEADER_IF;
+    }
+
+    /**
+     * Return the String representation of the If header present on
+     * the given request or <code>null</code>.
+     *
+     * @return If header value as String or <code>null</code>.
+     */
+    public String getHeaderValue() {
+        return headerValue;
+    }
+
+    /**
+     * Returns true if an If header was present in the given request. False otherwise.
+     *
+     * @return  true if an If header was present.
+     */
+    public boolean hasValue() {
+        return ifHeader != null;
+    }
+
+    /**
+     * Tries to match the contents of the <em>If</em> header with the given
+     * token and etag values with the restriction to only check for the tag.
+     * <p>
+     * If the <em>If</em> header is of untagged type, the untagged <em>IfList</em>
+     * is matched against the token and etag given: A match of the token and
+     * etag is found if at least one of the <em>IfList</em> entries match the
+     * token and etag tuple.
+     *
+     * @param tag The tag to identify the <em>IfList</em> to match the token
+     * and etag against.
+     * @param token The token to compare.
+     * @param etag The ETag value to compare.
+     *
+     * @return If the <em>If</em> header is of untagged type the result is
+     *      <code>true</code> if any of the <em>IfList</em> entries matches
+     *      the token and etag values. For tagged type <em>If</em> header the
+     *      result is <code>true</code> if either no entry for the given tag
+     *      exists in the <em>If</em> header or if the <em>IfList</em> for the
+     *      given tag matches the token and etag given.
+     */
+    public boolean matches(String tag, String token, String etag) {
+        if (ifHeader == null) {
+            log.debug("matches: No If header, assume match");
+            return true;
+        } else {
+            return ifHeader.matches(tag, token, etag);
+        }
+    }
+
+    /**
+     * @return an iterator over all tokens present in the if header, that were
+     * not denied by a leading NOT statement.
+     */
+    public Iterator<String> getAllTokens() {
+        return allTokens.iterator();
+    }
+
+    /**
+     * @return an iterator over all NOT tokens present in the if header, that
+     * were explicitly denied.
+     */
+    public Iterator<String> getAllNotTokens() {
+        return allNotTokens.iterator();
+    }
+
+    /**
+     * Parse the original header value and build the internal IfHeaderInterface
+     * object that is easy to query.
+     */
+    private IfHeaderInterface parse() {
+        IfHeaderInterface ifHeader;
+        if (headerValue != null && headerValue.length() > 0) {
+            StringReader reader = null;
+            int firstChar = 0;
+
+            try {
+                reader = new StringReader(headerValue);
+                // get the first character to decide - expect '(' or '<'
+                try {
+                    reader.mark(1);
+                    firstChar = readWhiteSpace(reader);
+                    reader.reset();
+                } catch (IOException ignore) {
+                    // may be thrown according to API but is only thrown by the
+                    // StringReader class if the reader is already closed.
+                }
+
+                if (firstChar == '(') {
+                    ifHeader = parseUntagged(reader);
+                } else if (firstChar == '<') {
+                    ifHeader = parseTagged(reader);
+                } else {
+                    logIllegalState("If", firstChar, "(<", null);
+                    ifHeader = null;
+                }
+
+            } finally  {
+                if (reader != null) {
+                    reader.close();
+                }
+            }
+
+        } else {
+            log.debug("IfHeader: No If header in request");
+            ifHeader = null;
+        }
+        return ifHeader;
+    }
+
+    //---------- internal IF header parser -------------------------------------
+    /**
+     * Parses a tagged type <em>If</em> header. This method implements the
+     * <em>Tagged</em> production given in the class comment :
+     * <pre>
+         Tagged = { "<" Word ">" Untagged } .
+     * </pre>
+     *
+     * @param reader
+     * @return
+     */
+    private IfHeaderMap parseTagged(StringReader reader) {
+        IfHeaderMap map = new IfHeaderMap();
+        try {
+            while (true) {
+                // read next non-white space
+                int c = readWhiteSpace(reader);
+                if (c < 0) {
+                    // end of input, no more entries
+                    break;
+                } else if (c == '<') {
+                    // start a tag with an IfList
+                    String resource = readWord(reader, '>');
+                    if (resource != null) {
+                        // go to untagged after reading the resource
+                        map.put(resource, parseUntagged(reader));
+                    } else {
+                        break;
+                    }
+                } else {
+                    // unexpected character
+                    // catchup to end of input or start of a tag
+                    logIllegalState("Tagged", c, "<", reader);
+                }
+            }
+        } catch (IOException ioe) {
+            log.error("parseTagged: Problem parsing If header: "+ioe.toString());
+        }
+
+        return map;
+    }
+
+    /**
+     * Parses an untagged type <em>If</em> header. This method implements the
+     * <em>Untagged</em> production given in the class comment :
+     * <pre>
+         Untagged = { "(" IfList ")" } .
+     * </pre>
+     *
+     * @param reader The <code>StringReader</code> to read from for parsing
+     *
+     * @return An <code>ArrayList</code> of {@link IfList} entries.
+     */
+    private IfHeaderList parseUntagged(StringReader reader) {
+        IfHeaderList list = new IfHeaderList();
+        try {
+            while (true) {
+                // read next non white space
+                reader.mark(1);
+                int c = readWhiteSpace(reader);
+                if (c < 0) {
+                    // end of input, no more IfLists
+                    break;
+
+                } else if (c == '(') {
+                    // start of an IfList, parse
+                    list.add(parseIfList(reader));
+
+                } else if (c == '<') {
+                    // start of a tag, return current list
+                    reader.reset();
+                    break;
+
+                } else {
+                    // unexpected character
+                    // catchup to end of input or start of an IfList
+                    logIllegalState("Untagged", c, "(", reader);
+                }
+            }
+        } catch (IOException ioe) {
+            log.error("parseUntagged: Problem parsing If header: "+ioe.toString());
+        }
+        return list;
+    }
+
+    /**
+     * Parses an <em>IfList</em> in the <em>If</em> header. This method
+     * implements the <em>Tagged</em> production given in the class comment :
+     * <pre>
+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * </pre>
+     *
+     * @param reader The <code>StringReader</code> to read from for parsing
+     *
+     * @return The {@link IfList} for the input <em>IfList</em>.
+     *
+     * @throws IOException if a problem occurs during reading.
+     */
+    private IfList parseIfList(StringReader reader) throws IOException {
+        IfList res = new IfList();
+        boolean positive = true;
+        String word;
+
+        ReadLoop:
+        while (true) {
+            int nextChar = readWhiteSpace(reader);
+            switch (nextChar) {
+                case 'N':
+                case 'n':
+                    // read not
+
+                    // check whether o or O
+                    int not = reader.read();
+                    if (not != 'o' && not != 'O') {
+                        logIllegalState("IfList-Not", not, "o", null);
+                        break;
+                    }
+
+                    // check whether t or T
+                    not = reader.read();
+                    if (not !='t' && not != 'T') {
+                        logIllegalState("IfList-Not", not, "t", null);
+                        break;
+                    }
+
+                    // read Not ok
+                    positive = false;
+                    break;
+
+                case '<':
+                    // state token
+                    word = readWord(reader, '>');
+                    if (word != null) {
+                        res.add(new IfListEntryToken(word, positive));
+                        // also add the token to the list of all tokens
+                        if (positive) {
+                            allTokens.add(word);
+                        } else {
+                            allNotTokens.add(word);
+                        }
+                        positive = true;
+                    }
+                    break;
+
+                case '[':
+                    // etag
+                    word = readWord(reader, ']');
+                    if (word != null) {
+                        res.add(new IfListEntryEtag(word, positive));
+                        positive = true;
+                    }
+                    break;
+
+                case ')':
+                    // correct end of list, end the loop
+                    log.debug("parseIfList: End of If list, terminating loop");
+                    break ReadLoop;
+
+                default:
+                    logIllegalState("IfList", nextChar, "nN<[)", reader);
+
+                    // abort loop if EOF
+                    if (nextChar < 0) {
+                        break ReadLoop;
+                    }
+
+                    break;
+            }
+        }
+
+        // return the current list anyway
+        return res;
+    }
+
+    /**
+     * Returns the first non-whitespace character from the reader or -1 if
+     * the end of the reader is encountered.
+     *
+     * @param reader The <code>Reader</code> to read from
+     *
+     * @return The first non-whitespace character or -1 in case of EOF.
+     *
+     * @throws IOException if a problem occurs during reading.
+     */
+    private int readWhiteSpace(Reader reader) throws IOException {
+        int c = reader.read();
+        while (c >= 0 && Character.isWhitespace((char) c)) {
+             c = reader.read();
+        }
+        return c;
+    }
+
+    /**
+     * Reads from the input until the end character is encountered and returns
+     * the string up to but not including this end character. If the end of input
+     * is reached before reading the end character <code>null</code> is
+     * returned.
+     * <p>
+     * Note that this method does not support any escaping.
+     *
+     * @param reader The <code>Reader</code> to read from
+     * @param end The ending character limiting the word.
+     *
+     * @return The string read up to but not including the ending character or
+     *      <code>null</code> if the end of input is reached before the ending
+     *      character has been read.
+     *
+     * @throws IOException if a problem occurs during reading.
+     */
+    private String readWord(Reader reader, char end) throws IOException {
+        StringBuffer buf = new StringBuffer();
+
+        // read the word value
+        int c = reader.read();
+        for (; c >= 0 && c != end; c=reader.read()) {
+            buf.append((char) c);
+        }
+
+        // check whether we succeeded
+        if (c < 0) {
+            log.error("readWord: Unexpected end of input reading word");
+            return null;
+        }
+
+        // build the string and return it
+        return buf.toString();
+    }
+
+    /**
+     * Logs an unexpected character with the corresponding state and list of
+     * expected characters. If the reader parameter is not null, characters
+     * are read until either the end of the input is reached or any of the
+     * characters in the expChar string is read.
+     *
+     * @param state The name of the current parse state. This method logs this
+     *      name in the message. The intended value would probably be the
+     *      name of the EBNF production during which the error occurs.
+     * @param effChar The effective character read.
+     * @param expChar The list of characters acceptable in the current state.
+     * @param reader The reader to be caught up to any of the expected
+     *      characters. If <code>null</code> the input is not caught up to
+     *      any of the expected characters (of course ;-).
+     */
+    private void logIllegalState(String state, int effChar, String expChar,
+                                 StringReader reader) {
+
+        // format the effective character to be logged
+        String effString = (effChar < 0) ? "<EOF>" : String.valueOf((char) effChar);
+
+        // log the error
+        log.error("logIllegalState: Unexpected character '"+effString+"' in state "+state+", expected any of "+expChar);
+
+        // catch up if a reader is given
+        if (reader != null && effChar >= 0) {
+            try {
+                log.debug("logIllegalState: Catch up to any of "+expChar);
+                do {
+                    reader.mark(1);
+                    effChar = reader.read();
+                } while (effChar >= 0 && expChar.indexOf(effChar) < 0);
+                if (effChar >= 0) {
+                    reader.reset();
+                }
+            } catch (IOException ioe) {
+                log.error("logIllegalState: IO Problem catching up to any of "+expChar);
+            }
+        }
+    }
+
+    //---------- internal If header structure ----------------------------------
+
+    /**
+     * The <code>IfListEntry</code> abstract class is the base class for
+     * entries in an <em>IfList</em> production. This abstract base class
+     * provides common functionality to both types of entries, namely tokens
+     * enclosed in angle brackets (<code>&lt; &gt;</code>) and etags enclosed
+     * in square brackets (<code>[ ]</code>).
+     */
+    private static abstract class IfListEntry {
+
+        /**
+         * The entry string value - the semantics of this value depends on the
+         * implementing class.
+         */
+        protected final String value;
+
+        /** Flag to indicate, whether this is a positive match or not */
+        protected final boolean positive;
+
+        /** The cached result of the {@link #toString} method. */
+        protected String stringValue;
+
+        /**
+         * Sets up the final fields of this abstract class. The meaning of
+         * value parameter depends solely on the implementing class. From the
+         * point of view of this abstract class, it is simply a string value.
+         *
+         * @param value The string value of this instance
+         * @param positive <code>true</code> if matches are positive
+         */
+        protected IfListEntry(String value, boolean positive) {
+            this.value = value;
+            this.positive = positive;
+        }
+
+        /**
+         * Matches the value from the parameter to the internal string value.
+         * If the parameter and the {@link #value} field match, the method
+         * returns <code>true</code> for positive matches and <code>false</code>
+         * for negative matches.
+         * <p>
+         * This helper method can be called by implementations to evaluate the
+         * concrete match on the correct value parameter. See
+         * {@link #match(String, String)} for the external API method.
+         *
+         * @param value The string value to compare to the {@link #value}
+         *      field.
+         *
+         * @return <code>true</code> if the value parameter and the
+         *      {@link #value} field match and the {@link #positive} field is
+         *      <code>true</code> or if the values do not match and the
+         *      {@link #positive} field is <code>false</code>.
+         */
+        protected boolean match(String value) {
+            return positive == this.value.equals(value);
+        }
+
+        /**
+         * Matches the entry's value to the the token or etag. Depending on the
+         * concrete implementation, only one of the parameters may be evaluated
+         * while the other may be ignored.
+         * <p>
+         * Implementing METHODS may call the helper method {@link #match(String)}
+         * for the actual matching.
+         *
+         * @param token The token value to compare
+         * @param etag The etag value to compare
+         *
+         * @return <code>true</code> if the token/etag matches the <em>IfList</em>
+         *      entry.
+         */
+        public abstract boolean match(String token, String etag);
+
+        /**
+         * Returns a short type name for the implementation. This method is
+         * used by the {@link #toString} method to build the string representation
+         * if the instance.
+         *
+         * @return The type name of the implementation.
+         */
+        protected abstract String getType();
+
+        /**
+         * Returns the value of this entry.
+         *
+         * @return the value
+         */
+        protected String getValue() {
+            return value;
+        }
+
+        /**
+         * Returns the String representation of this entry. This method uses the
+         * {@link #getType} to build the string representation.
+         *
+         * @return the String representation of this entry.
+         */
+        @Override
+        public String toString() {
+            if (stringValue == null) {
+                stringValue = getType() + ": " + (positive?"":"!") + value;
+            }
+            return stringValue;
+        }
+    }
+
+    /**
+     * The <code>IfListEntryToken</code> extends the {@link IfListEntry}
+     * abstract class to represent an entry for token matching.
+     */
+    private static class IfListEntryToken extends IfListEntry {
+
+        /**
+         * Creates a token matching entry.
+         *
+         * @param token The token value pertinent to this instance.
+         * @param positive <code>true</code> if this is a positive match entry.
+         */
+        IfListEntryToken(String token, boolean positive) {
+            super(token, positive);
+        }
+
+        /**
+         * Matches the token parameter to the stored token value and returns
+         * <code>true</code> if the values match and if the match is positive.
+         * <code>true</code> is also returned for negative matches if the values
+         * do not match.
+         *
+         * @param token The token value to compare
+         * @param etag The etag value to compare, which is ignored in this
+         *      implementation.
+         *
+         * @return <code>true</code> if the token matches the <em>IfList</em>
+         *      entry's token value.
+         */
+        @Override
+        public boolean match(String token, String etag) {
+            return token == null || super.match(token);
+        }
+
+        /**
+         * Returns the type name of this implementation, which is fixed to
+         * be <em>Token</em>.
+         *
+         * @return The fixed string <em>Token</em> as the type name.
+         */
+        @Override
+        protected String getType() {
+            return "Token";
+        }
+    }
+
+    /**
+     * The <code>IfListEntryToken</code> extends the {@link IfListEntry}
+     * abstract class to represent an entry for etag matching.
+     */
+    private static class IfListEntryEtag extends IfListEntry {
+
+        /**
+         * Creates an etag matching entry.
+         *
+         * @param etag The etag value pertinent to this instance.
+         * @param positive <code>true</code> if this is a positive match entry.
+         */
+        IfListEntryEtag(String etag, boolean positive) {
+            super(etag, positive);
+        }
+
+        /**
+         * Matches the etag parameter to the stored etag value and returns
+         * <code>true</code> if the values match and if the match is positive.
+         * <code>true</code> is also returned for negative matches if the values
+         * do not match.
+         *
+         * @param token The token value to compare, which is ignored in this
+         *      implementation.
+         * @param etag The etag value to compare
+         *
+         * @return <code>true</code> if the etag matches the <em>IfList</em>
+         *      entry's etag value.
+         */
+        @Override
+        public boolean match(String token, String etag) {
+            return super.match(etag);
+        }
+
+        /**
+         * Returns the type name of this implementation, which is fixed to
+         * be <em>ETag</em>.
+         *
+         * @return The fixed string <em>ETag</em> as the type name.
+         */
+        @Override
+        protected String getType() {
+            return "ETag";
+        }
+    }
+
+    /**
+     * The <code>IfList</code> class extends the <code>ArrayList</code> class
+     * with the limitation to only support adding {@link IfListEntry} objects
+     * and adding a {@link #match} method.
+     * <p>
+     * This class is a container for data contained in the <em>If</em>
+     * production <em>IfList</em>
+     * <pre>
+         IfList = { [ "Not" ] ( ("&lt;" Word "&gt;" ) | ( "[" Word "]" ) ) } .
+     * </pre>
+     * <p>
+     */
+    private static class IfList extends ArrayList<IfListEntry> {
+
+        /**
+         * Adds the {@link IfListEntry} at the end of the list.
+         *
+         * @param entry The {@link IfListEntry} to add to the list
+         *
+         * @return <code>true</code> (as per the general contract of Collection.add).
+         */
+        @Override
+        public boolean add(IfListEntry entry) {
+            return super.add(entry);
+        }
+
+        /**
+         * Adds the {@link IfListEntry} at the indicated position of the list.
+         *
+         * @param index
+         * @param entry
+         *
+         * @throws IndexOutOfBoundsException if index is out of range
+         *      <code>(index &lt; 0 || index &gt; size())</code>.
+         */
+        @Override
+        public void add(int index, IfListEntry entry) {
+            super.add(index, entry);
+        }
+
+        /**
+         * Returns <code>true</code> if all {@link IfListEntry} objects in the
+         * list match the given token and etag. If the list is entry, it is
+         * considered to match the token and etag.
+         *
+         * @param token The token to compare.
+         * @param etag The etag to compare.
+         *
+         * @return <code>true</code> if all entries in the list match the
+         *      given tag and token.
+         */
+        public boolean match(String token, String etag) {
+            log.debug("match: Trying to match token="+token+", etag="+etag);
+            for (int i=0; i < size(); i++) {
+                IfListEntry ile = get(i);
+                if (!ile.match(token, etag)) {
+                    log.debug("match: Entry "+i+"-"+ile+" does not match");
+                    return false;
+                }
+            }
+            // invariant: all entries matched
+
+            return true;
+        }
+    }
+
+    /**
+     * The <code>IfHeaderInterface</code> interface abstracts away the difference of
+     * tagged and untagged <em>If</em> header lists. The single method provided
+     * by this interface is to check whether a request may be applied to a
+     * resource with given token and etag.
+     */
+    private static interface IfHeaderInterface {
+
+        /**
+         * Matches the resource, token, and etag against this
+         * <code>IfHeaderInterface</code> instance.
+         *
+         * @param resource The resource to match this instance against. This
+         *      must be absolute URI of the resource as defined in Section 3
+         *      (URI Syntactic Components) of RFC 2396 Uniform Resource
+         *      Identifiers (URI): Generic Syntax.
+         * @param token The resource's lock token to match
+         * @param etag The resource's etag to match
+         *
+         * @return <code>true</code> if the header matches the resource with
+         *      token and etag, which means that the request is applicable
+         *      to the resource according to the <em>If</em> header.
+         */
+        public boolean matches(String resource, String token, String etag);
+    }
+
+    /**
+     * The <code>IfHeaderList</code> class implements the {@link IfHeaderInterface}
+     * interface to support untagged lists of {@link IfList}s. This class
+     * implements the data container for the production :
+     * <pre>
+         Untagged = { "(" IfList ")" } .
+     * </pre>
+     */
+    private static class IfHeaderList extends ArrayList<IfList> implements IfHeaderInterface {
+
+        /**
+         * Matches a list of {@link IfList}s against the token and etag. If any of
+         * the {@link IfList}s matches, the method returns <code>true</code>.
+         * On the other hand <code>false</code> is only returned if non of the
+         * {@link IfList}s match.
+         *
+         * @param resource The resource to match, which is ignored by this
+         *      implementation. A value of <code>null</code> is therefor
+         *      acceptable.
+         * @param token The token to compare.
+         * @param etag The ETag value to compare.
+         *
+         * @return <code>True</code> if any of the {@link IfList}s matches the token
+         *      and etag, else <code>false</code> is returned.
+         */
+        public boolean matches(String resource, String token, String etag) {
+            log.debug("matches: Trying to match token="+token+", etag="+etag);
+
+            for (IfList il : this) {
+                if (il.match(token, etag)) {
+                    log.debug("matches: Found match with " + il);
+                    return true;
+                }
+            }
+            // invariant: no match found
+
+            return false;
+        }
+    }
+
+    /**
+     * The <code>IfHeaderMap</code> class implements the {@link IfHeaderInterface}
+     * interface to support tagged lists of {@link IfList}s. This class
+     * implements the data container for the production :
+     * <pre>
+         Tagged = { "&lt;" Word "&gt;" "(" IfList ")" } .
+     * </pre>
+     */
+    private class IfHeaderMap extends HashMap<String, IfHeaderList> implements IfHeaderInterface {
+
+        /**
+         * Matches the token and etag for the given resource. If the resource is
+         * not mentioned in the header, a match is assumed and <code>true</code>
+         * is returned in this case.
+         *
+         * @param resource The absolute URI of the resource for which to find
+         *      a match.
+         * @param token The token to compare.
+         * @param etag The etag to compare.
+         *
+         * @return <code>true</code> if either no entry exists for the resource
+         *      or if the entry for the resource matches the token and etag.
+         */
+        public boolean matches(String resource, String token, String etag) {
+            log.debug("matches: Trying to match resource="+resource+", token="+token+","+etag);
+
+            String uri;
+            String path;
+            if (resource.startsWith("/")) {
+                path = resource;
+                uri = IfHeader.this.uriPrefix + resource;
+            } else {
+                path = resource.substring(IfHeader.this.uriPrefix.length());
+                uri = resource;
+            }
+            IfHeaderList list = get(path);
+            if (list == null) {
+                list = get(uri);
+            }
+            if (list == null) {
+                log.debug("matches: No entry for tag "+resource+", assuming mismatch");
+                return false;
+            } else {
+                return list.matches(resource, token, etag);
+            }
+        }
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java
new file mode 100644
index 000000000..723df11ec
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.util.EncodeUtil;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>LabelHeader</code>...
+ */
+public class LabelHeader implements Header {
+
+    private static Logger log = LoggerFactory.getLogger(LabelHeader.class);
+
+    private final String label;
+
+    public LabelHeader(String label) {
+        if (label == null) {
+            throw new IllegalArgumentException("null is not a valid label.");
+        }
+        this.label = label;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public String getHeaderName() {
+        return DeltaVConstants.HEADER_LABEL;
+    }
+
+    public String getHeaderValue() {
+        return EncodeUtil.escape(label);
+    }
+
+    public static LabelHeader parse(WebdavRequest request) {
+        String hv = request.getHeader(DeltaVConstants.HEADER_LABEL);
+        if (hv == null) {
+            return null;
+        } else {
+            return new LabelHeader(EncodeUtil.unescape(hv));
+        }
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java
new file mode 100644
index 000000000..1de797411
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * <code>OverwriteHeader</code>...
+ */
+public class OverwriteHeader implements Header {
+
+    private static Logger log = LoggerFactory.getLogger(OverwriteHeader.class);
+
+    public static final String OVERWRITE_TRUE = "T";
+    public static final String OVERWRITE_FALSE = "F";
+
+    /**
+     * Set 'doOverwrite' to <code>true</code> by default. See RFC 2518:
+     * "If the overwrite header is not included in a COPY or MOVE request then
+     * the resource MUST treat the request as if it has an overwrite header of
+     * value {@link #OVERWRITE_TRUE}".
+     */
+    private final boolean doOverwrite;
+
+    public OverwriteHeader(boolean doOverwrite) {
+        this.doOverwrite = doOverwrite;
+    }
+
+    /**
+     * Create a new <code>OverwriteHeader</code> for the given request object.
+     * If the latter does not contain an "Overwrite" header field, the default
+     * applies, which is {@link #OVERWRITE_TRUE} according to RFC 2518.
+     *
+     * @param request
+     */
+    public OverwriteHeader(HttpServletRequest request) {
+        String overwriteHeader = request.getHeader(DavConstants.HEADER_OVERWRITE);
+        if (overwriteHeader != null) {
+            doOverwrite = overwriteHeader.equalsIgnoreCase(OVERWRITE_TRUE);
+        } else {
+            // no Overwrite header -> default is 'true'
+            doOverwrite = true;
+        }
+    }
+
+    public String getHeaderName() {
+        return DavConstants.HEADER_OVERWRITE;
+    }
+
+    public String getHeaderValue() {
+        return (doOverwrite) ? OVERWRITE_TRUE : OVERWRITE_FALSE;
+    }
+
+    public boolean isOverwrite() {
+        return doOverwrite;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java
new file mode 100644
index 000000000..73d638053
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.apache.jackrabbit.webdav.observation.ObservationConstants;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * <code>PollTimeoutHeader</code> implements a timeout header for subscription
+ * polling.
+ */
+public class PollTimeoutHeader extends TimeoutHeader {
+
+    public PollTimeoutHeader(long timeout) {
+        super(timeout);
+    }
+
+    @Override
+    public String getHeaderName() {
+        return ObservationConstants.HEADER_POLL_TIMEOUT;
+    }
+
+    /**
+     * Parses the request timeout header and converts it into a new
+     * <code>PollTimeoutHeader</code> object.<br>The default value is used as
+     * fallback if the String is not parseable.
+     *
+     * @param request
+     * @param defaultValue
+     * @return a new PollTimeoutHeader object.
+     */
+    public static PollTimeoutHeader parseHeader(HttpServletRequest request, long defaultValue) {
+        String timeoutStr = request.getHeader(ObservationConstants.HEADER_POLL_TIMEOUT);
+        long timeout = parse(timeoutStr, defaultValue);
+        return new PollTimeoutHeader(timeout);
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java
new file mode 100644
index 000000000..0e5525359
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.header;
+
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * <code>TimeoutHeader</code>...
+ */
+public class TimeoutHeader implements Header, DavConstants {
+
+    private static Logger log = LoggerFactory.getLogger(TimeoutHeader.class);
+
+    private final long timeout;
+
+    public TimeoutHeader(long timeout) {
+        this.timeout = timeout;
+    }
+
+    public String getHeaderName() {
+        return DavConstants.HEADER_TIMEOUT;
+    }
+
+    public String getHeaderValue() {
+        if (timeout == INFINITE_TIMEOUT) {
+            return TIMEOUT_INFINITE;
+        } else {
+            return "Second-" + (timeout / 1000);
+        }
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    /**
+     * Parses the request timeout header and converts it into a new
+     * <code>TimeoutHeader</code> object.<br>The default value is used as
+     * fallback if the String is not parseable.
+     *
+     * @param request
+     * @param defaultValue
+     * @return a new TimeoutHeader object.
+     */
+    public static TimeoutHeader parse(HttpServletRequest request, long defaultValue) {
+        String timeoutStr = request.getHeader(HEADER_TIMEOUT);
+        long timeout = parse(timeoutStr, defaultValue);
+        return new TimeoutHeader(timeout);
+    }
+
+    /**
+     * Parses the given timeout String and converts the timeout value
+     * into a long indicating the number of milliseconds until expiration time
+     * is reached.<br>
+     * NOTE: If the timeout String equals to {@link #TIMEOUT_INFINITE 'infinite'}
+     * {@link Integer#MAX_VALUE} is returned. If the Sting is invalid or is in an
+     * invalid format that cannot be parsed, the default value is returned.
+     *
+     * @param timeoutStr
+     * @param defaultValue
+     * @return long representing the timeout present in the header or the default
+     * value if the header is missing or could not be parsed.
+     */
+    public static long parse(String timeoutStr, long defaultValue) {
+        long timeout = defaultValue;
+        if (timeoutStr != null && timeoutStr.length() > 0) {
+            int secondsInd = timeoutStr.indexOf("Second-");
+            if (secondsInd >= 0) {
+                secondsInd += 7; // read over "Second-"
+                int i = secondsInd;
+                while (i < timeoutStr.length() && Character.isDigit(timeoutStr.charAt(i))) {
+                    i++;
+                }
+                try {
+                    timeout = 1000L * Long.parseLong(timeoutStr.substring(secondsInd, i));
+                } catch (NumberFormatException ignore) {
+                    // ignore and return 'undefined' timeout
+                    log.error("Invalid timeout format: " + timeoutStr);
+                }
+            } else if (timeoutStr.equalsIgnoreCase(TIMEOUT_INFINITE)) {
+                timeout = INFINITE_TIMEOUT;
+            }
+        }
+        return timeout;
+    }
+}
\ No newline at end of file
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java
new file mode 100644
index 000000000..3c834230d
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@org.osgi.annotation.versioning.Version("1.1.0")
+package org.apache.jackrabbit.webdav.header;
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java
new file mode 100644
index 000000000..7faaf32fb
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.io;
+
+import java.io.InputStream;
+
+/**
+ * <code>InputContext</code>...
+ */
+public interface InputContext {
+
+    /**
+     * Return true, if there are any data to be imported (and not only properties)
+     *
+     * @return
+     */
+    public boolean hasStream();
+
+    /**
+     * Returns the input stream of the resource to import.
+     *
+     * @return the input stream.
+     */
+    public InputStream getInputStream();
+
+    /**
+     * Returns the modification time of the resource or the current time if
+     * the modification time has not been set.
+     *
+     * @return the modification time.
+     */
+    public long getModificationTime();
+
+    /**
+     * Returns the content language or <code>null</code>
+     *
+     * @return contentLanguage
+     */
+    public String getContentLanguage();
+
+    /**
+     * Returns the length of the data or -1 if the contentlength could not be
+     * determined.
+     *
+     * @return the content length
+     */
+    public long getContentLength();
+
+    /**
+     * Return the content type or <code>null</code>
+     *
+     * @return
+     */
+    public String getContentType();
+
+    /**
+     * Returns the value of the given property or <code>null</code> if this property does
+     * not exist.
+     *
+     * @param propertyName
+     * @return String property value or <code>null</code>
+     */
+    public String getProperty(String propertyName);
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java
new file mode 100644
index 000000000..592eecc1e
--- /dev/null
+++ b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.webdav.io;
+
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.io.InputStream;
+import java.util.Date;
+
+/**
+ * <code>InputContextImpl</code> class encapsulates the <code>InputStream</code>
+ * and some header values as present in the POST, PUT or MKCOL request.
+ */
+public class InputContextImpl implements InputContext {
+
+    private static Logger log = LoggerFactory.getLogger(InputContextImpl.class);
+
+    private final HttpServletRequest request;
+    private final InputStream in;
+
+    public InputContextImpl(HttpServletRequest request, InputStream in) {
+        if (request == null) {
+            throw new IllegalArgumentException("DavResource and Request must not be null.");
+        }
+
+        this.request = request;
+        this.in = in;
+    }
+
+    public boolean hasStream() {
+        return in != null;
+    }
+
+    /**
+     * Returns the input stream of the resource to import.
+     *
+     * @return the input stream.
+     */
+    public InputStream getInputStream() {
+        return in;
+    }
+
+    public long getModificationTime() {
+        return new Date().getTime();
+    }
+
+    /**
+     * Returns the content language or <code>null</code>.
+     *
+     * @return contentLanguage
+     */
+    public String getContentLanguage() {
+        return request.getHeader(DavConstants.HEADER_CONTENT_LANGUAGE);
+    }
+
+    /**
+     * @return content length or -1 when unknown
+     */
+    public long getContentLength() {
+        String length = request.getHeader(DavConstants.HEADER_CONTENT_LENGTH);
+        if (length == null) {
+            // header not present
+            return -1;
+        } else {
+            try {
+                return Long.parseLong(length);
+            } catch (NumberFormatException ex) {
+                log.error("broken Content-Length header: " + length);
+                return -1;
+            }
+        }
+    }
+
+    public String getContentType() {
+        return request.getHeader(DavConstants.HEADER_CONTENT_TYPE);
+    }
+
+    public String getProperty(String propertyName) {
+        return request.getHeader(propertyName);
+    }
+}
diff --git a/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java b/openmeetings-service/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java
new file mode 100644
index 000000000..a5a25eff5
--- /dev/null
... 18212 lines suppressed ...