Пример #1
0
        /// <summary>
        /// Gives the
        /// <see cref="XmlElement" /> of a
        /// <see cref="WebDavProperty" />
        /// with or without values
        /// or with or without child elements
        /// </summary>
        /// <param name="webDavProperty">The <see cref="WebDavProperty" /></param>
        /// <param name="xmlDocument">The <see cref="XmlDocument" /> containing the response body</param>
        /// <param name="iWebDavStoreItem">The <see cref="IWebDavStoreItem" /></param>
        /// <param name="isPropname">The boolean defining the Propfind propname request</param>
        /// <returns>
        /// The <see cref="XmlElement" /> of the <see cref="WebDavProperty" /> containing a value or child elements
        /// </returns>
        private static XmlElement PropChildElement(WebDavProperty webDavProperty, XmlDocument xmlDocument, IWebDavStoreItem iWebDavStoreItem, bool isPropname)
        {
            // If Propfind request contains a propname element
            if (isPropname)
            {
                webDavProperty.Value = String.Empty;
                return(webDavProperty.ToXmlElement(xmlDocument));
            }

            // If not, add the values to webDavProperty
            webDavProperty.Value = GetWebDavPropertyValue(iWebDavStoreItem, webDavProperty);
            XmlElement xmlElement = webDavProperty.ToXmlElement(xmlDocument);


            // If the webDavProperty is the resourcetype property
            // and the webDavStoreItem is a collection
            // add the collection XmlElement as a child to the xmlElement
            if (webDavProperty.Name != "resourcetype" || !iWebDavStoreItem.IsCollection)
            {
                return(xmlElement);
            }

            WebDavProperty collectionProperty = new WebDavProperty("collection", String.Empty);

            xmlElement.AppendChild(collectionProperty.ToXmlElement(xmlDocument));
            return(xmlElement);
        }
Пример #2
0
        public async Task <OcsDirectoryInfo> GetDirectoryInfo(string name)
        {
            PropfindResponse response = await this.webDav.Propfind(name)
                                        .ConfigureAwait(false);

            if (!response.IsSuccessful)
            {
                return(null);
            }

            WebDavResource resource = response.Resources
                                      .OrderBy(r => r.Uri.Length)
                                      .FirstOrDefault();

            if (resource == null)
            {
                return new OcsDirectoryInfo {
                           Name = name
                }
            }
            ;

            WebDavProperty usedProperty      = resource.Properties.FirstOrDefault(p => p.Name.LocalName == "quota-used-bytes");
            WebDavProperty availableProperty = resource.Properties.FirstOrDefault(p => p.Name.LocalName == "quota-available-bytes");

            long used, avail;

            if (usedProperty == null || !long.TryParse(usedProperty.Value, out used))
            {
                used = long.MinValue;
            }

            if (availableProperty == null || !long.TryParse(availableProperty.Value, out avail))
            {
                avail = long.MinValue;
            }

            long?quota = null;

            if (used != long.MinValue && avail != long.MinValue)
            {
                quota = used + avail;
            }

            return(new OcsDirectoryInfo
            {
                Name = name,
                QuotaBytes = quota,
                SizeBytes = used != long.MinValue ? used : default(long?)
            });
        }
Пример #3
0
        /// <summary>
        /// Returns the XML Format according to RFC
        /// Name:
        ///    lockdiscovery
        /// Purpose:
        ///     Describes the active locks on a resource
        /// Protected:
        ///     MUST be protected. Clients change the list of locks through LOCK and UNLOCK, not through PROPPATCH.
        /// COPY/MOVE behavior:
        ///     The value of this property depends on the lock state of the destination, not on the locks of the source resource. Recall
        ///     that locks are not moved in a MOVE operation.
        /// Description:
        ///     Returns a listing of who has a lock, what type of lock he has, the timeout type and the time remaining on the timeout,
        ///     and the associated lock token. Owner information MAY be omitted if it is considered sensitive. If there are no locks, but
        ///     the server supports locks, the property will be present but contain zero 'activelock' elements. If there are one or more locks,
        ///     an 'activelock' element appears for each lock on the resource. This property is NOT lockable with respect to write locks (Section 7).
        /// </summary>
        /// <param name="path"></param>
        /// <param name="responsedoc"></param>
        /// <returns></returns>
        private static XmlNode LockDiscovery(Uri path, ref XmlDocument responsedoc)
        {
            XmlNode node = new WebDavProperty("lockdiscovery").ToXmlElement(responsedoc);

            foreach (var ilock in WebDavStoreItemLock.GetLocks(path))
            {
                XmlNode activelock = new WebDavProperty("activelock").ToXmlElement(responsedoc);
                node.AppendChild(activelock);

                XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc);
                activelock.AppendChild(locktype);

                XmlNode locktypeitem = new WebDavProperty(ilock.LockType.ToString().ToLower()).ToXmlElement(responsedoc);
                locktype.AppendChild(locktypeitem);

                XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc);
                activelock.AppendChild(lockscope);

                XmlNode lockscopeitem = new WebDavProperty(ilock.LockScope.ToString().ToLower()).ToXmlElement(responsedoc);
                lockscope.AppendChild(lockscopeitem);

                XmlNode depth = new WebDavProperty("depth").ToXmlElement(responsedoc);
                depth.InnerText = ilock.Depth.ToString(CultureInfo.InvariantCulture);
                activelock.AppendChild(depth);

                XmlNode owner = new WebDavProperty("owner").ToXmlElement(responsedoc);
                owner.InnerText = ilock.Owner;
                activelock.AppendChild(owner);

                XmlNode timeout = new WebDavProperty("timeout").ToXmlElement(responsedoc);
                timeout.InnerText = ilock.RequestedTimeout;
                activelock.AppendChild(timeout);

                XmlNode locktoken = new WebDavProperty("locktoken").ToXmlElement(responsedoc);
                activelock.AppendChild(locktoken);

                XmlNode tokenhref = new WebDavProperty("href").ToXmlElement(responsedoc);
                tokenhref.InnerText = ilock.Token;
                locktoken.AppendChild(tokenhref);

                XmlNode lockroot = new WebDavProperty("lockroot").ToXmlElement(responsedoc);
                activelock.AppendChild(lockroot);

                XmlNode lockroothref = new WebDavProperty("href").ToXmlElement(responsedoc);
                lockroothref.InnerText = ilock.Path.ToString();
                lockroot.AppendChild(lockroothref);
            }

            return(node);
        }
Пример #4
0
        /// <summary>
        /// Returns an XML Fragment which details the supported locks on this implementation.
        /// 15.10 supportedlock Property
        /// Name:
        ///     supportedlock
        /// Purpose:
        ///     To provide a listing of the lock capabilities supported by the resource.
        /// Protected:
        ///     MUST be protected. Servers, not clients, determine what lock mechanisms are supported.
        /// COPY/MOVE behavior:
        ///    This property value is dependent on the kind of locks supported at the destination, not on the value of the property at the source resource. Servers attempting to COPY to a destination should not attempt to set this property at the destination.
        /// Description:
        ///     Returns a listing of the combinations of scope and access types that may be specified in a lock request on the resource. Note that the actual contents are themselves controlled by access controls, so a server is not required to provide information the client is not authorized to see. This property is NOT lockable with respect to write locks (Section 7).
        /// </summary>
        /// <param name="responsedoc"></param>
        /// <returns></returns>
        private static XmlNode SupportedLocks(ref XmlDocument responsedoc)
        {
            XmlNode node = new WebDavProperty("supportedlock").ToXmlElement(responsedoc);

            XmlNode lockentry = new WebDavProperty("lockentry").ToXmlElement(responsedoc);

            node.AppendChild(lockentry);

            XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc);

            lockentry.AppendChild(lockscope);

            XmlNode exclusive = new WebDavProperty("exclusive").ToXmlElement(responsedoc);

            lockscope.AppendChild(exclusive);

            XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc);

            lockentry.AppendChild(locktype);

            XmlNode write = new WebDavProperty("write").ToXmlElement(responsedoc);

            locktype.AppendChild(write);

            XmlNode lockentry1 = new WebDavProperty("lockentry").ToXmlElement(responsedoc);

            node.AppendChild(lockentry1);

            XmlNode lockscope1 = new WebDavProperty("lockscope").ToXmlElement(responsedoc);

            lockentry1.AppendChild(lockscope1);

            XmlNode shared = new WebDavProperty("shared").ToXmlElement(responsedoc);

            lockscope1.AppendChild(shared);

            XmlNode locktype1 = new WebDavProperty("locktype").ToXmlElement(responsedoc);

            lockentry1.AppendChild(locktype1);

            XmlNode write1 = new WebDavProperty("write").ToXmlElement(responsedoc);

            locktype1.AppendChild(write1);

            return(node);
        }
Пример #5
0
        /// <summary>
        /// Gets the correct value for a <see cref="WebDavProperty" />
        /// </summary>
        /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param>
        /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param>
        /// <returns>
        /// A <see cref="string" /> containing the value
        /// </returns>
        private string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty)
        {
            switch (davProperty.Name)
            {
            case "creationdate":
                return(webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z");

            case "displayname":
                return(webDavStoreItem.Name);

            case "getcontentlanguage":
                // still to implement !!!
                return(String.Empty);

            case "getcontentlength":
                return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Size : "");

            case "getcontenttype":
                return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).MimeType : "");

            case "getetag":
                return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Etag : "");

            case "getlastmodified":
                return(webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R"));

            case "lockdiscovery":
                // still to implement !!!
                return(String.Empty);

            case "resourcetype":
                return("");

            case "supportedlock":
                // still to implement !!!
                return("");

            //webDavProperty.Value = "<D:lockentry><D:lockscope><D:shared/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry>";
            case "ishidden":
                return("" + webDavStoreItem.Hidden);

            default:
                return(String.Empty);
            }
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <param name="response"></param>
        /// <param name="request"></param>
        protected override void OnProcessRequest(
            WebDavServer server,
            IHttpListenerContext context,
            IWebDavStore store,
            XmlDocument request,
            XmlDocument response)
        {
            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // Get the URI to the location
            Uri requestUri = context.Request.Url;

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager          = null;
            XmlNode             propNode         = null;
            XDocument           requestXDocument = null;

            // try to read the body
            try
            {
                StreamReader reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                string       requestBody = reader.ReadToEnd();

                if (!String.IsNullOrEmpty(requestBody))
                {
                    request.LoadXml(requestBody);

                    if (request.DocumentElement != null)
                    {
                        if (request.DocumentElement.LocalName != "propertyupdate")
                        {
                            WebDavServer.Log.Debug("PROPPATCH method without propertyupdate element in xml document");
                        }

                        manager = new XmlNamespaceManager(request.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        propNode = request.DocumentElement.SelectSingleNode("D:set/D:prop", manager);
                    }

                    requestXDocument = XDocument.Parse(requestBody);
                }
            }
            catch (Exception ex)
            {
                WebDavServer.Log.Warning(ex.Message);
            }

            /***************************************************************************************************
            * Take action
            ***************************************************************************************************/

            // Get the parent collection of the item
            IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);

            // Get the item from the collection
            IWebDavStoreItem item = GetItemFromCollection(collection, context.Request.Url);

            //we need to get properties to set
            List <WebDavProperty> propertiesToSet = new List <WebDavProperty>();

            if (requestXDocument != null)
            {
                foreach (XElement propertySet in requestXDocument.Descendants()
                         .Where(n => n.Name.LocalName == "set"))
                {
                    //this is a property to set
                    var allPropertiesToSet = propertySet.Elements().First().Elements();
                    foreach (var propSetNode in allPropertiesToSet)
                    {
                        propertiesToSet.Add(new WebDavProperty()
                        {
                            Name      = propSetNode.Name.LocalName,
                            Namespace = propSetNode.Name.NamespaceName,
                            Value     = propSetNode.Value
                        });
                    }
                }
            }
            item.SetProperties(propertiesToSet);

            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:multistatus " +
                                       "xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\">" +
                                       "<D:response></D:response></D:multistatus>";

            response.LoadXml(responseXml);

            // Select the response node
            XmlNode responseNode = response.DocumentElement.SelectSingleNode("D:response", manager);

            // Add the elements

            // The href element
            WebDavProperty hrefProperty = new WebDavProperty("href", requestUri.ToString());

            responseNode.AppendChild(hrefProperty.ToXmlElement(response));

            // The propstat element
            WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
            XmlElement     propstatElement  = propstatProperty.ToXmlElement(response);

            // The propstat/status element
            WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " +
                                                               HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));

            propstatElement.AppendChild(statusProperty.ToXmlElement(response));

            // The other propstat children
            foreach (WebDavProperty property in from XmlNode child in propNode.ChildNodes
                     where child.Name.ToLower()
                     .Contains("creationtime") || child.Name.ToLower()
                     .Contains("fileattributes") || child.Name.ToLower()
                     .Contains("lastaccesstime") || child.Name.ToLower()
                     .Contains("lastmodifiedtime")
                     let node = propNode.SelectSingleNode(child.Name, manager)

                                select new WebDavProperty(child.LocalName, string.Empty, node != null ? node.NamespaceURI : string.Empty))
            {
                propstatElement.AppendChild(property.ToXmlElement(response));
            }

            responseNode.AppendChild(propstatElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            string resp = response.InnerXml;

            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
            context.Response.StatusCode        = (int)WebDavStatusCode.MultiStatus;
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)WebDavStatusCode.MultiStatus);

            // set the headers of the response
            context.Response.ContentLength64             = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
 /// <summary>
 /// Gets the correct value for a <see cref="WebDavProperty" />
 /// </summary>
 /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param>
 /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param>
 /// <returns>
 /// A <see cref="string" /> containing the value
 /// </returns>
 private string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty)
 {
     switch (davProperty.Name)
     {
         case "creationdate":
             return webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z";
         case "displayname":
             return webDavStoreItem.Name;
         case "getcontentlanguage":
             // still to implement !!!
             return String.Empty;
         case "getcontentlength":
             return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument) webDavStoreItem).Size : "");
         case "getcontenttype":
             return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument) webDavStoreItem).MimeType : "");
         case "getetag":
             return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument) webDavStoreItem).Etag : "");
         case "getlastmodified":
             return webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R");
         case "lockdiscovery":
             // still to implement !!!
             return String.Empty;
         case "resourcetype":
             return "";
         case "supportedlock":
             // still to implement !!!
             return "";
             //webDavProperty.Value = "<D:lockentry><D:lockscope><D:shared/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry>";
         case "ishidden":
             return "" + webDavStoreItem.Hidden;
         default:
             return String.Empty;
     }
 }
        /// <summary>
        /// Gives the 
        /// <see cref="XmlElement" /> of a 
        /// <see cref="WebDavProperty" />
        /// with or without values
        /// or with or without child elements
        /// </summary>
        /// <param name="webDavProperty">The <see cref="WebDavProperty" /></param>
        /// <param name="xmlDocument">The <see cref="XmlDocument" /> containing the response body</param>
        /// <param name="iWebDavStoreItem">The <see cref="IWebDavStoreItem" /></param>
        /// <param name="isPropname">The boolean defining the Propfind propname request</param>
        /// <returns>
        /// The <see cref="XmlElement" /> of the <see cref="WebDavProperty" /> containing a value or child elements
        /// </returns>
        private XmlElement PropChildElement(WebDavProperty webDavProperty, XmlDocument xmlDocument, IWebDavStoreItem iWebDavStoreItem, bool isPropname)
        {
            // If Propfind request contains a propname element
            if (isPropname)
            {
                webDavProperty.Value = String.Empty;
                return webDavProperty.ToXmlElement(xmlDocument);
            }
            // If not, add the values to webDavProperty
            webDavProperty.Value = GetWebDavPropertyValue(iWebDavStoreItem, webDavProperty);
            XmlElement xmlElement = webDavProperty.ToXmlElement(xmlDocument);

                // If the webDavProperty is the resourcetype property
                // and the webDavStoreItem is a collection
                // add the collection XmlElement as a child to the xmlElement
            if (webDavProperty.Name != "resourcetype" || !iWebDavStoreItem.IsCollection)
                return xmlElement;

            WebDavProperty collectionProperty = new WebDavProperty("collection", "");
            xmlElement.AppendChild(collectionProperty.ToXmlElement(xmlDocument));
            return xmlElement;
        }
Пример #9
0
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="context">The
        /// <see cref="IWebDavContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        public void ProcessRequest(IWebDavContext context, IWebDavStore store)
        {
            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // read the headers
            int    depth     = GetDepthHeader(context.Request);
            string timeout   = GetTimeoutHeader(context.Request);
            string locktoken = GetLockTokenIfHeader(context.Request);
            int    lockResult;
            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager;
            XmlNode             lockscopeNode, locktypeNode, ownerNode;
            XmlDocument         requestDocument = new XmlDocument();

            if (string.IsNullOrEmpty(locktoken))
            {
                #region New Lock
                // try to read the body
                try
                {
                    StreamReader reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                    string       requestBody = reader.ReadToEnd();

                    if (!requestBody.Equals("") && requestBody.Length != 0)
                    {
                        requestDocument.LoadXml(requestBody);

                        if (requestDocument.DocumentElement != null &&
                            requestDocument.DocumentElement.LocalName != "prop" &&
                            requestDocument.DocumentElement.LocalName != "lockinfo")
                        {
                            WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                        }

                        manager = new XmlNamespaceManager(requestDocument.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        // Get the lockscope, locktype and owner as XmlNodes from the XML document
                        lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                        locktypeNode  = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                        ownerNode     = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                    }
                    else
                    {
                        throw new WebDavPreconditionFailedException();
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }


                /***************************************************************************************************
                * Lock the file or folder
                ***************************************************************************************************/


                // Get the parent collection of the item
                IWebDavStoreCollection collection = GetParentCollection(store, context, context.Request.Url);

                WebDavLockScope lockscope = (lockscopeNode.InnerXml.StartsWith("<D:exclusive"))
                    ? WebDavLockScope.Exclusive
                    : WebDavLockScope.Shared;

                //Only lock available at this time is a Write Lock according to RFC
                WebDavLockType locktype = (locktypeNode.InnerXml.StartsWith("<D:write")) ? WebDavLockType.Write : WebDavLockType.Write;

                string lockuser = ownerNode.InnerText;

                WindowsIdentity Identity = (WindowsIdentity)Thread.GetData(Thread.GetNamedDataSlot(Constants.HttpUser));

                lockResult = WebDavStoreItemLock.Lock(context.Request.Url, lockscope, locktype, Identity.Name, ref timeout,
                                                      out locktoken, requestDocument, depth);

                // Get the item from the collection
                try
                {
                    GetItemFromCollection(collection, context.Request.Url);
                }
                catch (Exception)
                {
                    lockResult = (int)HttpStatusCode.Created;
                }
                #endregion
            }
            else
            {
                #region Refreshing a lock
                //Refresh lock will ref us back the original XML document which was used to request this lock, from
                //this we will grab the data we need to build the response to the lock refresh request.
                lockResult = WebDavStoreItemLock.RefreshLock(context.Request.Url, locktoken, ref timeout, out requestDocument);
                if (requestDocument == null)
                {
                    context.SetStatusCode(409);
                    return;
                }

                try
                {
                    if (requestDocument.DocumentElement != null &&
                        requestDocument.DocumentElement.LocalName != "prop" &&
                        requestDocument.DocumentElement.LocalName != "lockinfo")
                    {
                        WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(requestDocument.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode  = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode     = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }

                #endregion
            }

            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            XmlDocument  responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            responseDoc.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = responseDoc.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(responseDoc.ImportNode(lockscopeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(locktypeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);// timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(responseDoc));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(responseDoc));

            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", string.Empty);
            XmlElement     locktokenElement  = locktokenProperty.ToXmlElement(responseDoc);
            WebDavProperty hrefProperty      = new WebDavProperty("href", locktoken);//"opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));


            activelock.AppendChild(locktokenElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            string resp          = responseDoc.InnerXml;
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);

            context.SetStatusCode(lockResult);
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(lockResult);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AppendHeader("ContentType", "text/xml");

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
        }
        /// <summary>
        ///     Returns the XML Format according to RFC
        ///     Name:
        ///     lockdiscovery
        ///     Purpose:
        ///     Describes the active locks on a resource
        ///     Protected:
        ///     MUST be protected. Clients change the list of locks through LOCK and UNLOCK, not through PROPPATCH.
        ///     COPY/MOVE behavior:
        ///     The value of this property depends on the lock state of the destination, not on the locks of the source resource.
        ///     Recall
        ///     that locks are not moved in a MOVE operation.
        ///     Description:
        ///     Returns a listing of who has a lock, what type of lock he has, the timeout type and the time remaining on the
        ///     timeout,
        ///     and the associated lock token. Owner information MAY be omitted if it is considered sensitive. If there are no
        ///     locks, but
        ///     the server supports locks, the property will be present but contain zero 'activelock' elements. If there are one or
        ///     more locks,
        ///     an 'activelock' element appears for each lock on the resource. This property is NOT lockable with respect to write
        ///     locks (Section 7).
        /// </summary>
        /// <param name="storeItem"></param>
        /// <param name="responsedoc"></param>
        /// <param name="lockSystem"></param>
        /// <returns></returns>
        private static XmlNode LockDiscovery(IWebDavStoreItem storeItem, ref XmlDocument responsedoc, IWebDavStoreItemLock lockSystem)
        {
            XmlNode node = new WebDavProperty("lockdiscovery").ToXmlElement(responsedoc);
            foreach (IWebDavStoreItemLockInstance ilock in lockSystem.GetLocks(storeItem))
            {
                XmlNode activelock = new WebDavProperty("activelock").ToXmlElement(responsedoc);
                node.AppendChild(activelock);

                XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc);
                activelock.AppendChild(locktype);

                XmlNode locktypeitem = new WebDavProperty(ilock.LockType.ToString().ToLower()).ToXmlElement(responsedoc);
                locktype.AppendChild(locktypeitem);

                XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc);
                activelock.AppendChild(lockscope);

                XmlNode lockscopeitem = new WebDavProperty(ilock.LockScope.ToString().ToLower()).ToXmlElement(responsedoc);
                lockscope.AppendChild(lockscopeitem);

                XmlNode depth = new WebDavProperty("depth").ToXmlElement(responsedoc);
                depth.InnerText = ilock.Depth.ToString(CultureInfo.InvariantCulture);
                activelock.AppendChild(depth);

                XmlNode owner = new WebDavProperty("owner").ToXmlElement(responsedoc);
                owner.InnerText = ilock.Owner;
                activelock.AppendChild(owner);

                XmlNode timeout = new WebDavProperty("timeout").ToXmlElement(responsedoc);
                timeout.InnerText = ilock.RequestedTimeout;
                activelock.AppendChild(timeout);

                XmlNode locktoken = new WebDavProperty("locktoken").ToXmlElement(responsedoc);
                activelock.AppendChild(locktoken);

                XmlNode tokenhref = new WebDavProperty("href").ToXmlElement(responsedoc);
                tokenhref.InnerText = ilock.Token.ToLockToken();
                locktoken.AppendChild(tokenhref);

                XmlNode lockroot = new WebDavProperty("lockroot").ToXmlElement(responsedoc);
                activelock.AppendChild(lockroot);

                XmlNode lockroothref = new WebDavProperty("href").ToXmlElement(responsedoc);
                lockroothref.InnerText = ilock.Path;
                lockroot.AppendChild(lockroothref);
            }

            return node;
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        public void ProcessRequest(WebDavServer server, IHttpListenerContext context, IWebDavStore store)
        {
            //ILog log = LogManager.GetCurrentClassLogger();
            var log = LogManager.GetLogger(GetType().Name);

            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // Get the URI to the location
            var requestUri = context.Request.Url;

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager  = null;
            XmlNode             propNode = null;

            // try to read the body
            try
            {
                var reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                var requestBody = reader.ReadToEnd();

                if (!String.IsNullOrEmpty(requestBody))
                {
                    var requestDocument = new XmlDocument();
                    requestDocument.LoadXml(requestBody);

                    if (requestDocument.DocumentElement != null)
                    {
                        if (requestDocument.DocumentElement.LocalName != "propertyupdate")
                        {
                            log.Debug("PROPPATCH method without propertyupdate element in xml document");
                        }

                        manager = new XmlNamespaceManager(requestDocument.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        propNode = requestDocument.DocumentElement.SelectSingleNode("D:set/D:prop", manager);
                    }
                }
            }
            catch (Exception ex)
            {
                log.Warn(ex.Message);
            }

            /***************************************************************************************************
            * Take action
            ***************************************************************************************************/

            // Get the parent collection of the item
            var collection = GetParentCollection(server, store, context.Request.Url);

            // Get the item from the collection
            var item = GetItemFromCollection(collection, context.Request.Url);

            var fileInfo = new FileInfo(item.ItemPath);

            if (propNode != null && fileInfo.Exists)
            {
                foreach (XmlNode node in propNode.ChildNodes)
                {
                    switch (node.LocalName)
                    {
                    case "Win32CreationTime":
                        fileInfo.CreationTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                        break;

                    case "Win32LastAccessTime":
                        fileInfo.LastAccessTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                        break;

                    case "Win32LastModifiedTime":
                        fileInfo.LastWriteTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                        break;

                    case "Win32FileAttributes":
                        //fileInfo.Attributes =
                        //fileInfo.Attributes = Convert.ToDateTime(node.InnerText);
                        break;
                    }
                }
            }


            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            var          responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:multistatus " +
                                       "xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\">" +
                                       "<D:response></D:response></D:multistatus>";

            responseDoc.LoadXml(responseXml);

            // Select the response node
            var responseNode = responseDoc.DocumentElement.SelectSingleNode("D:response", manager);

            // Add the elements

            // The href element
            var hrefProperty = new WebDavProperty("href", requestUri.ToString());

            responseNode.AppendChild(hrefProperty.ToXmlElement(responseDoc));

            // The propstat element
            var propstatProperty = new WebDavProperty("propstat", "");
            var propstatElement  = propstatProperty.ToXmlElement(responseDoc);

            // Using Dot.Net Core APIs
            // The propstat/status element
            //WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " + HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
            var HttpWorkerRequest = "HTTP/1.1 " + context.Response.StatusCode + " " + context.Response.StatusDescription;
            var statusProperty    = new WebDavProperty("status", HttpWorkerRequest);

            propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

            // The other propstat children
            foreach (var property in from XmlNode child in propNode.ChildNodes
                     where child.Name.ToLower()
                     .Contains("creationtime") || child.Name.ToLower()
                     .Contains("fileattributes") || child.Name.ToLower()
                     .Contains("lastaccesstime") || child.Name.ToLower()
                     .Contains("lastmodifiedtime")
                     let node = propNode.SelectSingleNode(child.Name, manager)
                                select node != null
                    ? new WebDavProperty(child.LocalName, "", node.NamespaceURI)
                    : new WebDavProperty(child.LocalName, "", ""))
            {
                propstatElement.AppendChild(property.ToXmlElement(responseDoc));
            }

            responseNode.AppendChild(propstatElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            var resp          = responseDoc.InnerXml;
            var responseBytes = Encoding.UTF8.GetBytes(resp);

            // Using Dot.Net Core APIs
            // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
            context.Response.StatusCode = (int)WebDavStatusCode.MultiStatus;
            //context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)WebDavStatusCode.MultiStatus);
            context.Response.StatusDescription = WebDavStatusCode.MultiStatus.ToString();

            // set the headers of the response
            context.Response.ContentLength64             = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        /// <param name="response"></param>
        /// <param name="request"></param>
        protected override void OnProcessRequest(
          WebDavServer server,
          IHttpListenerContext context,
          IWebDavStore store,
          XmlDocument request,
          XmlDocument response)
        {

            if (!WebDavStoreItemLock.LockEnabled) throw new WebDavNotImplementedException("Lock support disabled");
            /***************************************************************************************************
             * Retreive al the information from the request
             ***************************************************************************************************/

            // read the headers
            int depth = GetDepthHeader(context.Request);
            string timeout = GetTimeoutHeader(context.Request);
            string locktoken = GetLockTokenIfHeader(context.Request);
            int lockResult = 0;
            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager;
            XmlNode lockscopeNode, locktypeNode, ownerNode;

            if (string.IsNullOrEmpty(locktoken))
            {
                #region New Lock

                // try to read the body
                try
                {
                    StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                    string requestBody = reader.ReadToEnd();

                    if (!requestBody.Equals("") && requestBody.Length != 0)
                    {

                        request.LoadXml(requestBody);

                        if (request.DocumentElement != null &&
                            request.DocumentElement.LocalName != "prop" &&
                            request.DocumentElement.LocalName != "lockinfo")
                        {
                            WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                        }

                        manager = new XmlNamespaceManager(request.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        // Get the lockscope, locktype and owner as XmlNodes from the XML document
                        lockscopeNode = request.DocumentElement.SelectSingleNode("D:lockscope", manager);
                        locktypeNode = request.DocumentElement.SelectSingleNode("D:locktype", manager);
                        ownerNode = request.DocumentElement.SelectSingleNode("D:owner", manager);
                    }
                    else
                    {
                        throw new WebDavPreconditionFailedException();
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }


                /***************************************************************************************************
                 * Lock the file or folder
                 ***************************************************************************************************/


                // Get the parent collection of the item
                IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);

                WebDavLockScope lockscope = (lockscopeNode.InnerXml.StartsWith("<D:exclusive"))
                    ? WebDavLockScope.Exclusive
                    : WebDavLockScope.Shared;

                //Only lock available at this time is a Write Lock according to RFC
                WebDavLockType locktype = (locktypeNode.InnerXml.StartsWith("<D:write"))
                    ? WebDavLockType.Write
                    : WebDavLockType.Write;

                string userAgent = context.Request.Headers["User-Agent"];

                WindowsIdentity Identity = (WindowsIdentity)Thread.GetData(Thread.GetNamedDataSlot(WebDavServer.HttpUser));

                // Get the item from the collection
                try
                {
                    var item = GetItemFromCollection(collection, context.Request.Url);
                    String lockLogicalKey = context.Request.Url.AbsoluteUri;
                    if (item != null)
                    {
                        lockLogicalKey = item.LockLogicalKey;
                    }
                    if (item != null && !item.Lock())
                    {
                        lockResult = 423; //Resource cannot be locked
                    }
                    else
                    {
                        //try acquiring a standard lock, 
                        lockResult = WebDavStoreItemLock.Lock(
                            context.Request.Url, 
                            lockLogicalKey,
                            lockscope, 
                            locktype, 
                            Identity.Name, 
                            userAgent,
                            ref timeout, 
                            out locktoken, 
                            request, 
                            depth);
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer._log.Error(String.Format("Error occourred while acquiring lock {0}", context.Request.Url), ex);
                    lockResult = 423; //Resource cannot be locked some exception occurred
                }
                #endregion
            }
            else
            {
                #region Refreshing a lock
                //Refresh lock will ref us back the original XML document which was used to request this lock, from
                //this we will grab the data we need to build the response to the lock refresh request.
                lockResult = WebDavStoreItemLock.RefreshLock(context.Request.Url, locktoken, ref timeout, out request);
                if (request == null)
                {
                    context.SendSimpleResponse(409);
                    return;
                }

                try
                {
                    if (request.DocumentElement != null &&
                        request.DocumentElement.LocalName != "prop" &&
                        request.DocumentElement.LocalName != "lockinfo")
                    {
                        WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(request.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = request.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode = request.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode = request.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }

                #endregion
            }

            /***************************************************************************************************
             * Create the body for the response
             ***************************************************************************************************/

            // Create the basic response XmlDocument
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            response.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = response.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(response.ImportNode(lockscopeNode, true));
            activelock.AppendChild(response.ImportNode(locktypeNode, true));
            activelock.AppendChild(response.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);// timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(response));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(response));

            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", string.Empty);
            XmlElement locktokenElement = locktokenProperty.ToXmlElement(response);
            WebDavProperty hrefProperty = new WebDavProperty("href", locktoken);//"opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(response));
            activelock.AppendChild(locktokenElement);

            // The lockroot element
            WebDavProperty lockRootProperty = new WebDavProperty("lockroot", string.Empty);
            XmlElement lockRootElement = lockRootProperty.ToXmlElement(response);
            WebDavProperty hrefRootProperty = new WebDavProperty("href", context.Request.Url.AbsoluteUri);//"lockroot
            lockRootElement.AppendChild(hrefRootProperty.ToXmlElement(response));
            activelock.AppendChild(lockRootElement);

            /***************************************************************************************************
             * Send the response
             ***************************************************************************************************/

            // convert the StringBuilder
            string resp = response.InnerXml;
            if (WebDavServer.Log.IsDebugEnabled)
            {
                WebDavServer.Log.DebugFormat(
@"Request {0}:{1}:{2}
Request
{3}
Response:
{4}",
                context.Request.HttpMethod, context.Request.RemoteEndPoint, context.Request.Url,
                request.Beautify(),
                response.Beautify());
            }


            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            context.Response.StatusCode = lockResult;
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(lockResult);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="context">The
        /// <see cref="IWebDavContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        public void ProcessRequest(IWebDavContext context, IWebDavStore store)
        {
            /***************************************************************************************************
             * Retreive al the information from the request
             ***************************************************************************************************/

            // read the headers
            int depth = GetDepthHeader(context.Request);
            string timeout = GetTimeoutHeader(context.Request);
            string locktoken = GetLockTokenIfHeader(context.Request);
            int lockResult;
            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager;
            XmlNode lockscopeNode, locktypeNode, ownerNode;
            XmlDocument requestDocument = new XmlDocument();

            if (string.IsNullOrEmpty(locktoken))
            {
                #region New Lock
                // try to read the body
                try
                {
                    StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                    string requestBody = reader.ReadToEnd();

                    if (!requestBody.Equals("") && requestBody.Length != 0)
                    {

                        requestDocument.LoadXml(requestBody);

                        if (requestDocument.DocumentElement != null &&
                            requestDocument.DocumentElement.LocalName != "prop" &&
                            requestDocument.DocumentElement.LocalName != "lockinfo")
                        {
                            WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                        }

                        manager = new XmlNamespaceManager(requestDocument.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        // Get the lockscope, locktype and owner as XmlNodes from the XML document
                        lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                        locktypeNode = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                        ownerNode = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                    }
                    else
                    {
                        throw new WebDavPreconditionFailedException();
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }


                /***************************************************************************************************
                * Lock the file or folder
                ***************************************************************************************************/


                // Get the parent collection of the item
            IWebDavStoreCollection collection = GetParentCollection(store, context, context.Request.Url);

                WebDavLockScope lockscope = (lockscopeNode.InnerXml.StartsWith("<D:exclusive"))
                    ? WebDavLockScope.Exclusive
                    : WebDavLockScope.Shared;

                //Only lock available at this time is a Write Lock according to RFC
                WebDavLockType locktype = (locktypeNode.InnerXml.StartsWith("<D:write")) ? WebDavLockType.Write : WebDavLockType.Write;

                string lockuser = ownerNode.InnerText;

                WindowsIdentity Identity = (WindowsIdentity)Thread.GetData(Thread.GetNamedDataSlot(Constants.HttpUser));

                lockResult = WebDavStoreItemLock.Lock(context.Request.Url, lockscope, locktype, Identity.Name, ref timeout,
                    out locktoken, requestDocument, depth);

                // Get the item from the collection
                try
                {
                    GetItemFromCollection(collection, context.Request.Url);
                }
                catch (Exception)
                {
                    lockResult = (int)HttpStatusCode.Created;
                }
                #endregion
            }
            else
            {
                #region Refreshing a lock
                //Refresh lock will ref us back the original XML document which was used to request this lock, from
                //this we will grab the data we need to build the response to the lock refresh request.
                lockResult = WebDavStoreItemLock.RefreshLock(context.Request.Url, locktoken, ref timeout, out requestDocument);
                if (requestDocument == null)
                {
                    context.SetStatusCode(409);
                    return;
                }

                try
                {
                    if (requestDocument.DocumentElement != null &&
                        requestDocument.DocumentElement.LocalName != "prop" &&
                        requestDocument.DocumentElement.LocalName != "lockinfo")
                    {
                        WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(requestDocument.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warn(ex.Message);
                    throw;
                }

                #endregion
            }

            /***************************************************************************************************
             * Create the body for the response
             ***************************************************************************************************/

            // Create the basic response XmlDocument
            XmlDocument responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            responseDoc.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = responseDoc.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(responseDoc.ImportNode(lockscopeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(locktypeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);// timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(responseDoc));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(responseDoc));

            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", string.Empty);
            XmlElement locktokenElement = locktokenProperty.ToXmlElement(responseDoc);
            WebDavProperty hrefProperty = new WebDavProperty("href", locktoken);//"opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));


            activelock.AppendChild(locktokenElement);

            /***************************************************************************************************
             * Send the response
             ***************************************************************************************************/

            // convert the StringBuilder
            string resp = responseDoc.InnerXml;
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);

            context.SetStatusCode(lockResult);
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(lockResult);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AppendHeader("ContentType", "text/xml");

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
        }
Пример #14
0
        /// <summary>
        /// Gets the correct value for a <see cref="WebDavProperty" />
        /// </summary>
        /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param>
        /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param>
        /// <returns>
        /// A <see cref="string" /> containing the value
        /// </returns>
        private static string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty)
        {
            switch (davProperty.Name)
            {
            case "creationdate":
                return(webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z");

            case "displayname":
                return(webDavStoreItem.Name);

            case "getcontentlanguage":
                //todo getcontentlanguage
                return(String.Empty);

            case "getcontentlength":
                return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Size : string.Empty);

            case "getcontenttype":
                return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).MimeType : string.Empty);

            case "getetag":
                return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Etag : string.Empty);

            case "getlastmodified":
                return(webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R"));

            case "resourcetype":
                //todo Add resourceType
                return("");

            case "ishidden":
                return(webDavStoreItem.Hidden.ToString(CultureInfo.InvariantCulture));

            default:
                return(String.Empty);
            }
        }
Пример #15
0
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        /// <param name="response"></param>
        /// <param name="request"></param>
        protected override void OnProcessRequest(
            WebDavServer server,
            IHttpListenerContext context,
            IWebDavStore store,
            XmlDocument request,
            XmlDocument response)
        {
            if (!WebDavStoreItemLock.LockEnabled)
            {
                throw new WebDavNotImplementedException("Lock support disabled");
            }

            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // read the headers
            int    depth      = GetDepthHeader(context.Request);
            string timeout    = GetTimeoutHeader(context.Request);
            string locktoken  = GetLockTokenIfHeader(context.Request);
            int    lockResult = 0;
            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager;
            XmlNode             lockscopeNode, locktypeNode, ownerNode;

            if (string.IsNullOrEmpty(locktoken))
            {
                #region New Lock

                // try to read the body
                try
                {
                    StreamReader reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                    string       requestBody = reader.ReadToEnd();

                    if (!requestBody.Equals("") && requestBody.Length != 0)
                    {
                        request.LoadXml(requestBody);

                        if (request.DocumentElement != null &&
                            request.DocumentElement.LocalName != "prop" &&
                            request.DocumentElement.LocalName != "lockinfo")
                        {
                            WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                        }

                        manager = new XmlNamespaceManager(request.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        // Get the lockscope, locktype and owner as XmlNodes from the XML document
                        lockscopeNode = request.DocumentElement.SelectSingleNode("D:lockscope", manager);
                        locktypeNode  = request.DocumentElement.SelectSingleNode("D:locktype", manager);
                        ownerNode     = request.DocumentElement.SelectSingleNode("D:owner", manager);
                    }
                    else
                    {
                        throw new WebDavPreconditionFailedException();
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warning(ex.Message);
                    throw;
                }

                /***************************************************************************************************
                * Lock the file or folder
                ***************************************************************************************************/

                // Get the parent collection of the item
                IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);

                WebDavLockScope lockscope = (lockscopeNode.InnerXml.StartsWith("<D:exclusive"))
                    ? WebDavLockScope.Exclusive
                    : WebDavLockScope.Shared;

                //Only lock available at this time is a Write Lock according to RFC
                WebDavLockType locktype = (locktypeNode.InnerXml.StartsWith("<D:write"))
                    ? WebDavLockType.Write
                    : WebDavLockType.Write;

                string userAgent = context.Request.Headers["User-Agent"];

                WindowsIdentity Identity = (WindowsIdentity)Thread.GetData(Thread.GetNamedDataSlot(WebDavServer.HttpUser));

                // Get the item from the collection
                try
                {
                    var    item           = GetItemFromCollection(collection, context.Request.Url);
                    String lockLogicalKey = context.Request.Url.AbsoluteUri;
                    if (item != null)
                    {
                        lockLogicalKey = item.LockLogicalKey;
                    }
                    if (item != null && !item.Lock())
                    {
                        lockResult = 423; //Resource cannot be locked
                    }
                    else
                    {
                        //try acquiring a standard lock,
                        lockResult = WebDavStoreItemLock.Lock(
                            context.Request.Url,
                            lockLogicalKey,
                            lockscope,
                            locktype,
                            Identity.Name,
                            userAgent,
                            ref timeout,
                            out locktoken,
                            request,
                            depth);
                    }
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Error(String.Format("Error occourred while acquiring lock {0}", context.Request.Url), ex);
                    lockResult = 423; //Resource cannot be locked some exception occurred
                }
                #endregion
            }
            else
            {
                #region Refreshing a lock
                //Refresh lock will ref us back the original XML document which was used to request this lock, from
                //this we will grab the data we need to build the response to the lock refresh request.
                lockResult = WebDavStoreItemLock.RefreshLock(context.Request.Url, locktoken, ref timeout, out request);
                if (request == null)
                {
                    context.SendSimpleResponse(409);
                    return;
                }

                try
                {
                    if (request.DocumentElement != null &&
                        request.DocumentElement.LocalName != "prop" &&
                        request.DocumentElement.LocalName != "lockinfo")
                    {
                        WebDavServer.Log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(request.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = request.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode  = request.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode     = request.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                catch (Exception ex)
                {
                    WebDavServer.Log.Warning(ex.Message);
                    throw;
                }

                #endregion
            }

            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            response.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = response.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(response.ImportNode(lockscopeNode, true));
            activelock.AppendChild(response.ImportNode(locktypeNode, true));
            activelock.AppendChild(response.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);// timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(response));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(response));

            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", string.Empty);
            XmlElement     locktokenElement  = locktokenProperty.ToXmlElement(response);
            WebDavProperty hrefProperty      = new WebDavProperty("href", locktoken);//"opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(response));
            activelock.AppendChild(locktokenElement);

            // The lockroot element
            WebDavProperty lockRootProperty = new WebDavProperty("lockroot", string.Empty);
            XmlElement     lockRootElement  = lockRootProperty.ToXmlElement(response);
            WebDavProperty hrefRootProperty = new WebDavProperty("href", context.Request.Url.AbsoluteUri);//"lockroot
            lockRootElement.AppendChild(hrefRootProperty.ToXmlElement(response));
            activelock.AppendChild(lockRootElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            string resp = response.InnerXml;
            if (WebDavServer.Log.IsEnabled(Serilog.Events.LogEventLevel.Debug))
            {
                WebDavServer.Log.Debug(
                    @"Request {0}:{1}:{2}
Request
{3}
Response:
{4}",
                    context.Request.HttpMethod, context.Request.RemoteEndPoint, context.Request.Url,
                    request.Beautify(),
                    response.Beautify());
            }


            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            context.Response.StatusCode        = lockResult;
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(lockResult);

            // set the headers of the response
            context.Response.ContentLength64             = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
Пример #16
0
        /// <summary>
        /// Builds the <see cref="XmlDocument" /> containing the response body
        /// </summary>
        /// <param name="context">The <see cref="IHttpListenerContext" /></param>
        /// <param name="propname">The boolean defining the Propfind propname request</param>
        /// <returns>
        /// The <see cref="XmlDocument" /> containing the response body
        /// </returns>
        private XmlDocument ResponseDocument(IWebDavContext context, bool propname)
        {
            // Create the basic response XmlDocument
            XmlDocument  responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\"></D:multistatus>";

            responseDoc.LoadXml(responseXml);

            // Generate the manager
            XmlNamespaceManager manager = new XmlNamespaceManager(responseDoc.NameTable);

            manager.AddNamespace("D", "DAV:");
            manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
            manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
            manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

            int count = 0;

            foreach (IWebDavStoreItem webDavStoreItem in _webDavStoreItems)
            {
                // Create the response element
                WebDavProperty responseProperty = new WebDavProperty("response", string.Empty);
                XmlElement     responseElement  = responseProperty.ToXmlElement(responseDoc);

                // The href element
                Uri result;
                if (count == 0)
                {
                    Uri.TryCreate(_requestUri, string.Empty, out result);
                }
                else
                {
                    Uri.TryCreate(_requestUri, webDavStoreItem.Name, out result);
                }
                WebDavProperty hrefProperty = new WebDavProperty("href", result.AbsoluteUri);
                responseElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
                count++;

                // The propstat element
                WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
                XmlElement     propstatElement  = propstatProperty.ToXmlElement(responseDoc);

                // The prop element
                WebDavProperty propProperty = new WebDavProperty("prop", string.Empty);
                XmlElement     propElement  = propProperty.ToXmlElement(responseDoc);

                //All properties but lockdiscovery and supportedlock can be handled here.
                foreach (WebDavProperty davProperty in _requestedProperties.Where(d => d.Name != "lockdiscovery" && d.Name != "supportedlock"))
                {
                    propElement.AppendChild(PropChildElement(davProperty, responseDoc, webDavStoreItem, propname));
                }

                //Since lockdiscovery returns an xml tree, we need to process it seperately.
                if (_requestedProperties.FirstOrDefault(d => d.Name == "lockdiscovery") != null)
                {
                    propElement.AppendChild(LockDiscovery(result, ref responseDoc));
                }

                //Since supportedlock returns an xml tree, we need to process it seperately.
                if (_requestedProperties.FirstOrDefault(d => d.Name == "supportedlock") != null)
                {
                    propElement.AppendChild(SupportedLocks(ref responseDoc));
                }

                // Add the prop element to the propstat element
                propstatElement.AppendChild(propElement);

                // The status element
                WebDavProperty statusProperty = new WebDavProperty("status",
                                                                   "HTTP/1.1 " + context.Response.StatusCode + " " +
                                                                   HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
                propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

                // Add the propstat element to the response element
                responseElement.AppendChild(propstatElement);

                // Add the response element to the multistatus element
                responseDoc.DocumentElement.AppendChild(responseElement);
            }

            return(responseDoc);
        }
Пример #17
0
        /// <summary>
        /// Builds the <see cref="XmlDocument" /> containing the response body
        /// </summary>
        /// <param name="context">The <see cref="IHttpListenerContext" /></param>
        /// <param name="propname">The boolean defining the Propfind propname request</param>
        /// <returns>
        /// The <see cref="XmlDocument" /> containing the response body
        /// </returns>
        private XmlDocument ResponseDocument(IHttpListenerContext context, bool propname)
        {
            // Create the basic response XmlDocument
            XmlDocument  responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\"></D:multistatus>";

            responseDoc.LoadXml(responseXml);

            // Generate the manager
            XmlNamespaceManager manager = new XmlNamespaceManager(responseDoc.NameTable);

            manager.AddNamespace("D", "DAV:");
            manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
            manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
            manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

            int count = 0;

            foreach (IWebDavStoreItem webDavStoreItem in _webDavStoreItems)
            {
                // Create the response element
                WebDavProperty responseProperty = new WebDavProperty("response", "");
                XmlElement     responseElement  = responseProperty.ToXmlElement(responseDoc);

                // The href element
                Uri result;
                if (count == 0)
                {
                    Uri.TryCreate(_requestUri, "", out result);
                }
                else
                {
                    Uri.TryCreate(_requestUri, webDavStoreItem.Name, out result);
                }
                WebDavProperty hrefProperty = new WebDavProperty("href", result.AbsoluteUri);
                responseElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
                count++;

                // The propstat element
                WebDavProperty propstatProperty = new WebDavProperty("propstat", "");
                XmlElement     propstatElement  = propstatProperty.ToXmlElement(responseDoc);

                // The prop element
                WebDavProperty propProperty = new WebDavProperty("prop", "");
                XmlElement     propElement  = propProperty.ToXmlElement(responseDoc);

                foreach (WebDavProperty davProperty in _requestedProperties)
                {
                    propElement.AppendChild(PropChildElement(davProperty, responseDoc, webDavStoreItem, propname));
                }

                // Add the prop element to the propstat element
                propstatElement.AppendChild(propElement);

                // The status element
                WebDavProperty statusProperty = new WebDavProperty("status",
                                                                   "HTTP/1.1 " + context.Response.StatusCode + " " +
                                                                   HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
                propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

                // Add the propstat element to the response element
                responseElement.AppendChild(propstatElement);

                // Add the response element to the multistatus element
                responseDoc.DocumentElement.AppendChild(responseElement);
            }

            return(responseDoc);
        }
 /// <summary>
 /// Set properties, it should be implemented by derived classes
 /// </summary>
 /// <param name="property">The property we want to retrieve value</param>
 public virtual String GetProperty(WebDavProperty property)
 {
     return(String.Empty);
 }
        internal string CreateFragment(bool isRoot, XmlDocument responseDoc, IWebDavStoreItem webDavStoreItem, IHttpListenerContext context, bool propname, Uri requestUri, List<WebDavProperty> requestedProperties, IWebDavStoreItemLock lockSystem)
        {
            // Create the response element
            WebDavProperty responseProperty = new WebDavProperty("response", Empty);
            XmlElement responseElement = responseProperty.ToXmlElement(responseDoc);

            // The href element
            Uri result;
            if (isRoot)
                Uri.TryCreate(requestUri, Empty, out result);
            else
                Uri.TryCreate(requestUri, webDavStoreItem.Name, out result);

            WebDavProperty hrefProperty = new WebDavProperty("href", result.AbsoluteUri);
            responseElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));

            // The propstat element
            WebDavProperty propstatProperty = new WebDavProperty("propstat", Empty);
            XmlElement propstatElement = propstatProperty.ToXmlElement(responseDoc);

            // The prop element
            WebDavProperty propProperty = new WebDavProperty("prop", Empty);
            XmlElement propElement = propProperty.ToXmlElement(responseDoc);


            //All properties but lockdiscovery and supportedlock can be handled here.
            foreach (WebDavProperty davProperty in requestedProperties)
            {
                XmlNode toAdd;
                switch (davProperty.Name)
                {
                    case "lockdiscovery":
                        toAdd = LockDiscovery(webDavStoreItem, ref responseDoc, lockSystem);
                        break;
                    case "supportedlock":
                        toAdd = SupportedLocks(ref responseDoc);
                        break;
                    default:
                        toAdd = PropChildElement(davProperty, responseDoc, webDavStoreItem, propname);
                        break;
                }

                if (toAdd != null)
                    propElement.AppendChild(toAdd);
            }


            // Add the prop element to the propstat element
            propstatElement.AppendChild(propElement);

            // The status element
            WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " + HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
            propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

            // Add the propstat element to the response element
            responseElement.AppendChild(propstatElement);

            if (responseDoc.DocumentElement == null)
                throw new Exception("Not Possible.");

            return responseElement.OuterXml.Replace("xmlns:D=\"DAV:\"", "");
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        public void ProcessRequest(WebDavServer server, IHttpListenerContext context, IWebDavStore store)
        {
            ILog log = LogManager.GetCurrentClassLogger();

            /***************************************************************************************************
             * Retreive al the information from the request
             ***************************************************************************************************/

            // read the headers
            int depth = GetDepthHeader(context.Request);
            string timeout = GetTimeoutHeader(context.Request);

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager = null;
            XmlNode lockscopeNode = null, locktypeNode = null, ownerNode = null;

            // try to read the body
            try
            {
                StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                string requestBody = reader.ReadToEnd();

                if (!requestBody.Equals("") && requestBody.Length != 0)
                {
                    XmlDocument requestDocument = new XmlDocument();
                    requestDocument.LoadXml(requestBody);

                    if (requestDocument.DocumentElement != null && requestDocument.DocumentElement.LocalName != "prop" &&
                        requestDocument.DocumentElement.LocalName != "lockinfo")
                    {
                        log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(requestDocument.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                else
                {
                    throw new WebDavPreconditionFailedException();
                }
            }
            catch (Exception ex)
            {
                log.Warn(ex.Message);
                throw;
            }

            /***************************************************************************************************
             * Lock the file or folder
             ***************************************************************************************************/

            bool isNew = false;

            // Get the parent collection of the item
            IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);

            try
            {
                // Get the item from the collection
                IWebDavStoreItem item = GetItemFromCollection(collection, context.Request.Url);
            }
            catch (Exception)
            {
                collection.CreateDocument(context.Request.Url.Segments.Last().TrimEnd('/', '\\'));
                isNew = true;
            }
           
            

            /***************************************************************************************************
             * Create the body for the response
             ***************************************************************************************************/

            // Create the basic response XmlDocument
            XmlDocument responseDoc = new XmlDocument();
            string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop " +
                "xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
            responseDoc.LoadXml(responseXml);

            // Select the activelock XmlNode
            XmlNode activelock = responseDoc.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(responseDoc.ImportNode(lockscopeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(locktypeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            WebDavProperty timeoutProperty = new WebDavProperty("timeout", timeout);
            activelock.AppendChild(timeoutProperty.ToXmlElement(responseDoc));

            // The depth element
            WebDavProperty depthProperty = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));
            activelock.AppendChild(depthProperty.ToXmlElement(responseDoc));
            
            // The locktoken element
            WebDavProperty locktokenProperty = new WebDavProperty("locktoken", "");
            XmlElement locktokenElement = locktokenProperty.ToXmlElement(responseDoc);
            WebDavProperty hrefProperty = new WebDavProperty("href", "opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
            locktokenElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
            activelock.AppendChild(locktokenElement);

            /***************************************************************************************************
             * Send the response
             ***************************************************************************************************/
            
            // convert the StringBuilder
            string resp = responseDoc.InnerXml;
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);

            if (isNew)
            {
                // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
                context.Response.StatusCode = (int)HttpStatusCode.Created;
                context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)HttpStatusCode.Created);
            }
            else
            {
                // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)HttpStatusCode.OK);
            }
            

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
 /// <summary>
 ///     Gets the correct value for a <see cref="WebDavProperty" />
 /// </summary>
 /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param>
 /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param>
 /// <returns>
 ///     A <see cref="string" /> containing the value
 /// </returns>
 private static string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty)
 {
     if (webDavStoreItem is IWebDavStoreCollection && davProperty.StoreItemType == WebDavProperty.StoreItemTypeFlag.Document)
         return null;
     if (webDavStoreItem is IWebDavStoreDocument && davProperty.StoreItemType == WebDavProperty.StoreItemTypeFlag.Collection)
         return null;
     switch (davProperty.Name)
     {
         case "creationdate":
             return webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z";
         case "displayname":
             return webDavStoreItem.Name;
         case "getcontentlanguage":
             //todo getcontentlanguage
             return Empty;
         case "getcontentlength":
             return webDavStoreItem.Size.ToString(CultureInfo.InvariantCulture);
         case "getcontenttype":
             return webDavStoreItem.MimeType;
         case "getetag":
             return "\"{" + webDavStoreItem.Etag + "},0\"";
         case "getlastmodified":
             return webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R");
         case "resourcetype":
             //todo Add resourceType
             return "";
         case "ishidden":
             return webDavStoreItem.GetFileInfo().Hidden ? "1" : "0";
         case "win32fileattributes":
             string s = Convert.ToString((int) webDavStoreItem.GetFileInfo().GetAttributes(), 16);
             char[] bits = s.PadLeft(8, '0').ToCharArray();
             return new string(bits);
         case "isfolder":
             return (webDavStoreItem is IWebDavStoreCollection) ? "t" : "";
         case "iscollection":
             return (webDavStoreItem is IWebDavStoreCollection) ? "1" : "0";
         case "authoritative-directory":
             return "t";
         case "repl-uid":
             return "rid:{" + webDavStoreItem.GetRepl_uId() + "}";
         case "resourcetag":
             return "rt:" + webDavStoreItem.GetRepl_uId() + "@00000000000";
         default:
             return Empty;
     }
 }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The 
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <param name="response"></param>
        /// <param name="request"></param>
        protected override void OnProcessRequest(
           WebDavServer server,
           IHttpListenerContext context,
           IWebDavStore store,
           XmlDocument request,
           XmlDocument response)
        {
            /***************************************************************************************************
             * Retreive al the information from the request
             ***************************************************************************************************/

            // Get the URI to the location
            Uri requestUri = context.Request.Url;

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager = null;
            XmlNode propNode = null;
            XDocument requestXDocument = null;
            // try to read the body
            try
            {
                StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                string requestBody = reader.ReadToEnd();

                if (!String.IsNullOrEmpty(requestBody))
                {
                    request.LoadXml(requestBody);

                    if (request.DocumentElement != null)
                    {
                        if (request.DocumentElement.LocalName != "propertyupdate")
                        {
                            WebDavServer.Log.Debug("PROPPATCH method without propertyupdate element in xml document");
                        }

                        manager = new XmlNamespaceManager(request.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        propNode = request.DocumentElement.SelectSingleNode("D:set/D:prop", manager);
                    }

                    requestXDocument = XDocument.Parse(requestBody);
                }
            }
            catch (Exception ex)
            {
                WebDavServer.Log.Warn(ex.Message);
            }

            /***************************************************************************************************
             * Take action
             ***************************************************************************************************/

            // Get the parent collection of the item
            IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);

            // Get the item from the collection
            IWebDavStoreItem item = GetItemFromCollection(collection, context.Request.Url);

            //we need to get properties to set 
            List<WebDavProperty> propertiesToSet = new List<WebDavProperty>();
            if (requestXDocument != null)
            {
                foreach (XElement propertySet in requestXDocument.Descendants()
                    .Where(n => n.Name.LocalName == "set"))
                {
                    //this is a property to set
                    var allPropertiesToSet = propertySet.Elements().First().Elements();
                    foreach (var propSetNode in allPropertiesToSet)
                    {
                        propertiesToSet.Add(new WebDavProperty()
                        {
                            Name = propSetNode.Name.LocalName,
                            Namespace = propSetNode.Name.NamespaceName,
                            Value = propSetNode.Value
                        });
                    }
                   
                }
            }
            item.SetProperties(propertiesToSet);
          
            /***************************************************************************************************
             * Create the body for the response
             ***************************************************************************************************/

            // Create the basic response XmlDocument
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:multistatus " +
                                       "xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\">" +
                                       "<D:response></D:response></D:multistatus>";
            response.LoadXml(responseXml);

            // Select the response node
            XmlNode responseNode = response.DocumentElement.SelectSingleNode("D:response", manager);

            // Add the elements

            // The href element
            WebDavProperty hrefProperty = new WebDavProperty("href", requestUri.ToString());
            responseNode.AppendChild(hrefProperty.ToXmlElement(response));

            // The propstat element
            WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
            XmlElement propstatElement = propstatProperty.ToXmlElement(response);

            // The propstat/status element
            WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " +
                    HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
            propstatElement.AppendChild(statusProperty.ToXmlElement(response));

            // The other propstat children
            foreach (WebDavProperty property in from XmlNode child in propNode.ChildNodes
                where child.Name.ToLower()
                    .Contains("creationtime") || child.Name.ToLower()
                        .Contains("fileattributes") || child.Name.ToLower()
                            .Contains("lastaccesstime") || child.Name.ToLower()
                                .Contains("lastmodifiedtime")
                let node = propNode.SelectSingleNode(child.Name, manager)

                select new WebDavProperty(child.LocalName, string.Empty, node != null ? node.NamespaceURI : string.Empty))

                propstatElement.AppendChild(property.ToXmlElement(response));

            responseNode.AppendChild(propstatElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/
            
            // convert the StringBuilder
            string resp = response.InnerXml;
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
            context.Response.StatusCode = (int)WebDavStatusCode.MultiStatus;
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)WebDavStatusCode.MultiStatus);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">The
        /// <see cref="IHttpListenerContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        /// <exception cref="WebDAVSharp.Server.Exceptions.WebDavPreconditionFailedException"></exception>
        public void ProcessRequest(WebDavServer server, IHttpListenerContext context, IWebDavStore store)
        {
            //ILog log = LogManager.GetCurrentClassLogger();
            var log = LogManager.GetLogger(GetType().Name);

            /***************************************************************************************************
            * Retreive al the information from the request
            ***************************************************************************************************/

            // read the headers
            var depth   = GetDepthHeader(context.Request);
            var timeout = GetTimeoutHeader(context.Request);

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager = null;
            XmlNode             lockscopeNode = null, locktypeNode = null, ownerNode = null;

            // try to read the body
            try
            {
                var reader      = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                var requestBody = reader.ReadToEnd();

                if (!requestBody.Equals("") && requestBody.Length != 0)
                {
                    var requestDocument = new XmlDocument();
                    requestDocument.LoadXml(requestBody);

                    if (requestDocument.DocumentElement != null && requestDocument.DocumentElement.LocalName != "prop" &&
                        requestDocument.DocumentElement.LocalName != "lockinfo")
                    {
                        log.Debug("LOCK method without prop or lockinfo element in xml document");
                    }

                    manager = new XmlNamespaceManager(requestDocument.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                    // Get the lockscope, locktype and owner as XmlNodes from the XML document
                    lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
                    locktypeNode  = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
                    ownerNode     = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
                }
                else
                {
                    throw new WebDavPreconditionFailedException();
                }
            }
            catch (Exception ex)
            {
                log.Warn(ex.Message);
                throw;
            }

            /***************************************************************************************************
            * Lock the file or folder
            ***************************************************************************************************/

            var isNew            = false;

            // Get the parent collection of the item
            var collection       = GetParentCollection(server, store, context.Request.Url);

            try
            {
                // Get the item from the collection
                var item = GetItemFromCollection(collection, context.Request.Url);
            }
            catch (Exception)
            {
                collection.CreateDocument(context.Request.Url.Segments.Last().TrimEnd('/', '\\'));
                isNew = true;
            }



            /***************************************************************************************************
            * Create the body for the response
            ***************************************************************************************************/

            // Create the basic response XmlDocument
            var responseDoc      = new XmlDocument();
            var responseXml      = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop " +
                                   "xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";

            responseDoc.LoadXml(responseXml);

            // Select the activelock XmlNode
            var activelock       = responseDoc.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);

            // Import the given nodes
            activelock.AppendChild(responseDoc.ImportNode(lockscopeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(locktypeNode, true));
            activelock.AppendChild(responseDoc.ImportNode(ownerNode, true));

            // Add the additional elements, e.g. the header elements

            // The timeout element
            var timeoutProperty  = new WebDavProperty("timeout", timeout);

            activelock.AppendChild(timeoutProperty.ToXmlElement(responseDoc));

            // The depth element
            var depthProperty    = new WebDavProperty("depth", (depth == 0 ? "0" : "Infinity"));

            activelock.AppendChild(depthProperty.ToXmlElement(responseDoc));

            // The locktoken element
            var locktokenProperty = new WebDavProperty("locktoken", "");
            var locktokenElement = locktokenProperty.ToXmlElement(responseDoc);
            var hrefProperty     = new WebDavProperty("href", "opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");

            locktokenElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
            activelock.AppendChild(locktokenElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            // convert the StringBuilder
            var resp          = responseDoc.InnerXml;
            var responseBytes = Encoding.UTF8.GetBytes(resp);

            if (isNew)
            {
                // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
                context.Response.StatusCode = (int)HttpStatusCode.Created;
                //context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)HttpStatusCode.Created);
                context.Response.StatusDescription = HttpStatusCode.Created.ToString();
            }
            else
            {
                // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                //context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)HttpStatusCode.OK);
                context.Response.StatusDescription = HttpStatusCode.OK.ToString();
            }


            // set the headers of the response
            context.Response.ContentLength64             = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="context">The 
        /// <see cref="IWebDavContext" /> object containing both the request and response
        /// objects to use.</param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        public void ProcessRequest(IWebDavContext context, IWebDavStore store)
        {
            /***************************************************************************************************
             * Retreive al the information from the request
             ***************************************************************************************************/

            // Get the URI to the location
            Uri requestUri = context.Request.Url;

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNamespaceManager manager = null;
            XmlNode propNode = null;

            // try to read the body
            try
            {
                StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
                string requestBody = reader.ReadToEnd();

                if (!String.IsNullOrEmpty(requestBody))
                {
                    XmlDocument requestDocument = new XmlDocument();
                    requestDocument.LoadXml(requestBody);

                    if (requestDocument.DocumentElement != null)
                    {
                        if (requestDocument.DocumentElement.LocalName != "propertyupdate")
                        {
                            WebDavServer.Log.Debug("PROPPATCH method without propertyupdate element in xml document");
                        }

                        manager = new XmlNamespaceManager(requestDocument.NameTable);
                        manager.AddNamespace("D", "DAV:");
                        manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                        manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                        manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

                        propNode = requestDocument.DocumentElement.SelectSingleNode("D:set/D:prop", manager);
                    }
                }
            }
            catch (Exception ex)
            {
                WebDavServer.Log.Warn(ex.Message);
            }

            /***************************************************************************************************
             * Take action
             ***************************************************************************************************/

            // Get the parent collection of the item
            IWebDavStoreCollection collection = GetParentCollection(store, context, context.Request.Url);

            // Get the item from the collection
            IWebDavStoreItem item = GetItemFromCollection(collection, context.Request.Url);

            FileInfo fileInfo = new FileInfo(item.ItemPath);

            if (propNode != null && fileInfo.Exists)
            {
                foreach (XmlNode node in propNode.ChildNodes)
                {
                    switch (node.LocalName)
                    {
                        case "Win32CreationTime":
                            fileInfo.CreationTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                            break;
                        case "Win32LastAccessTime":
                            fileInfo.LastAccessTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                            break;
                        case "Win32LastModifiedTime":
                            fileInfo.LastWriteTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                            break;
                        case "Win32FileAttributes":
                            //todo Win32FileAttributes
                            //fileInfo.Attributes = 
                            //fileInfo.Attributes = Convert.ToDateTime(node.InnerText);
                            break;
                    }
                }
            }


            /***************************************************************************************************
             * Create the body for the response
             ***************************************************************************************************/

            // Create the basic response XmlDocument
            XmlDocument responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:multistatus " +
                                       "xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\">" +
                                       "<D:response></D:response></D:multistatus>";
            responseDoc.LoadXml(responseXml);

            // Select the response node
            XmlNode responseNode = responseDoc.DocumentElement.SelectSingleNode("D:response", manager);

            // Add the elements

            // The href element
            WebDavProperty hrefProperty = new WebDavProperty("href", requestUri.ToString());
            responseNode.AppendChild(hrefProperty.ToXmlElement(responseDoc));

            // The propstat element
            WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
            XmlElement propstatElement = propstatProperty.ToXmlElement(responseDoc);

            // The propstat/status element
            WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " +
                    HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
            propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

            // The other propstat children
            foreach (WebDavProperty property in from XmlNode child in propNode.ChildNodes
                where child.Name.ToLower()
                    .Contains("creationtime") || child.Name.ToLower()
                        .Contains("fileattributes") || child.Name.ToLower()
                            .Contains("lastaccesstime") || child.Name.ToLower()
                                .Contains("lastmodifiedtime")
                let node = propNode.SelectSingleNode(child.Name, manager)

                select new WebDavProperty(child.LocalName, string.Empty, node != null ? node.NamespaceURI : string.Empty))

                propstatElement.AppendChild(property.ToXmlElement(responseDoc));

            responseNode.AppendChild(propstatElement);

            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/
            
            // convert the StringBuilder
            string resp = responseDoc.InnerXml;
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
            context.SetStatusCode((int)WebDavStatusCode.MultiStatus);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AppendHeader("Content-Type", "text/xml");

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }
        /// <summary>
        /// Builds the <see cref="XmlDocument" /> containing the response body
        /// </summary>
        /// <param name="context">The <see cref="IHttpListenerContext" /></param>
        /// <param name="propname">The boolean defining the Propfind propname request</param>
        /// <returns>
        /// The <see cref="XmlDocument" /> containing the response body
        /// </returns>
        private XmlDocument ResponseDocument(IWebDavContext context, bool propname)
        {
            // Create the basic response XmlDocument
            XmlDocument responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\"></D:multistatus>";
            responseDoc.LoadXml(responseXml);

            // Generate the manager
            XmlNamespaceManager manager = new XmlNamespaceManager(responseDoc.NameTable);
            manager.AddNamespace("D", "DAV:");
            manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
            manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
            manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

            int count = 0;

            foreach (IWebDavStoreItem webDavStoreItem in _webDavStoreItems)
            {
                // Create the response element
                WebDavProperty responseProperty = new WebDavProperty("response", string.Empty);
                XmlElement responseElement = responseProperty.ToXmlElement(responseDoc);

                // The href element
                Uri result;
                if (count == 0)
                {
                    Uri.TryCreate(_requestUri, string.Empty, out result);
                }
                else
                {
                    Uri.TryCreate(_requestUri, webDavStoreItem.Name, out result);
                }
                WebDavProperty hrefProperty = new WebDavProperty("href", result.AbsoluteUri);
                responseElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
                count++;

                // The propstat element
                WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
                XmlElement propstatElement = propstatProperty.ToXmlElement(responseDoc);

                // The prop element
                WebDavProperty propProperty = new WebDavProperty("prop", string.Empty);
                XmlElement propElement = propProperty.ToXmlElement(responseDoc);

                //All properties but lockdiscovery and supportedlock can be handled here.
                foreach (WebDavProperty davProperty in _requestedProperties.Where(d => d.Name != "lockdiscovery" && d.Name != "supportedlock"))
                    propElement.AppendChild(PropChildElement(davProperty, responseDoc, webDavStoreItem, propname));

                //Since lockdiscovery returns an xml tree, we need to process it seperately.
                if (_requestedProperties.FirstOrDefault(d => d.Name == "lockdiscovery") != null)
                    propElement.AppendChild(LockDiscovery(result, ref responseDoc));

                //Since supportedlock returns an xml tree, we need to process it seperately.
                if (_requestedProperties.FirstOrDefault(d => d.Name == "supportedlock") != null)
                    propElement.AppendChild(SupportedLocks(ref responseDoc));

                // Add the prop element to the propstat element
                propstatElement.AppendChild(propElement);

                // The status element
                WebDavProperty statusProperty = new WebDavProperty("status",
                    "HTTP/1.1 " + context.Response.StatusCode + " " +
                    HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
                propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

                // Add the propstat element to the response element
                responseElement.AppendChild(propstatElement);

                // Add the response element to the multistatus element
                responseDoc.DocumentElement.AppendChild(responseElement);
            }

            return responseDoc;
        }
        /// <summary>
        ///     Gives the
        ///     <see cref="XmlElement" /> of a
        ///     <see cref="WebDavProperty" />
        ///     with or without values
        ///     or with or without child elements
        /// </summary>
        /// <param name="webDavProperty">The <see cref="WebDavProperty" /></param>
        /// <param name="xmlDocument">The <see cref="XmlDocument" /> containing the response body</param>
        /// <param name="iWebDavStoreItem">The <see cref="IWebDavStoreItem" /></param>
        /// <param name="isPropname">The boolean defining the Propfind propname request</param>
        /// <returns>
        ///     The <see cref="XmlElement" /> of the <see cref="WebDavProperty" /> containing a value or child elements
        /// </returns>
        private static XmlElement PropChildElement(WebDavProperty webDavProperty, XmlDocument xmlDocument, IWebDavStoreItem iWebDavStoreItem, bool isPropname)
        {
            // If Propfind request contains a propname element
            if (isPropname)
            {
                webDavProperty.Value = Empty;
                return webDavProperty.ToXmlElement(xmlDocument);
            }

            // If not, add the values to webDavProperty
            webDavProperty.Value = GetWebDavPropertyValue(iWebDavStoreItem, webDavProperty);
            if (webDavProperty.Value == null)
                return null;

            XmlElement xmlElement = webDavProperty.ToXmlElement(xmlDocument);


            // If the webDavProperty is the resourcetype property
            // and the webDavStoreItem is a collection
            // add the collection XmlElement as a child to the xmlElement
            if (!webDavProperty.Name.Equals("resourcetype", StringComparison.InvariantCultureIgnoreCase) || !iWebDavStoreItem.IsCollection)
                return xmlElement;

            WebDavProperty collectionProperty = new WebDavProperty("collection", Empty);
            xmlElement.AppendChild(collectionProperty.ToXmlElement(xmlDocument));
            return xmlElement;
        }
 /// <summary>
 /// Gets the correct value for a <see cref="WebDavProperty" />
 /// </summary>
 /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param>
 /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param>
 /// <returns>
 /// A <see cref="string" /> containing the value
 /// </returns>
 private static string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty)
 {
     switch (davProperty.Name)
     {
         case "creationdate":
             return webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z";
         case "displayname":
             return webDavStoreItem.Name;
         case "getcontentlanguage":
             //todo getcontentlanguage
             return String.Empty;
         case "getcontentlength":
             return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Size : string.Empty);
         case "getcontenttype":
             return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).MimeType : string.Empty);
         case "getetag":
             return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Etag : string.Empty);
         case "getlastmodified":
             return webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R");
         case "resourcetype":
             //todo Add resourceType
             return "";
         case "ishidden":
             return webDavStoreItem.Hidden.ToString(CultureInfo.InvariantCulture);
         default:
             return String.Empty;
     }
 }
        /// <summary>
        ///     Returns an XML Fragment which details the supported locks on this implementation.
        ///     15.10 supportedlock Property
        ///     Name:
        ///     supportedlock
        ///     Purpose:
        ///     To provide a listing of the lock capabilities supported by the resource.
        ///     Protected:
        ///     MUST be protected. Servers, not clients, determine what lock mechanisms are supported.
        ///     COPY/MOVE behavior:
        ///     This property value is dependent on the kind of locks supported at the destination, not on the value of the
        ///     property at the source resource. Servers attempting to COPY to a destination should not attempt to set this
        ///     property at the destination.
        ///     Description:
        ///     Returns a listing of the combinations of scope and access types that may be specified in a lock request on the
        ///     resource. Note that the actual contents are themselves controlled by access controls, so a server is not required
        ///     to provide information the client is not authorized to see. This property is NOT lockable with respect to write
        ///     locks (Section 7).
        /// </summary>
        /// <param name="responsedoc"></param>
        /// <returns></returns>
        private static XmlNode SupportedLocks(ref XmlDocument responsedoc)
        {
            XmlNode node = new WebDavProperty("supportedlock").ToXmlElement(responsedoc);

            XmlNode lockentry = new WebDavProperty("lockentry").ToXmlElement(responsedoc);
            node.AppendChild(lockentry);

            XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc);
            lockentry.AppendChild(lockscope);

            XmlNode exclusive = new WebDavProperty("exclusive").ToXmlElement(responsedoc);
            lockscope.AppendChild(exclusive);

            XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc);
            lockentry.AppendChild(locktype);

            XmlNode write = new WebDavProperty("write").ToXmlElement(responsedoc);
            locktype.AppendChild(write);

            XmlNode lockentry1 = new WebDavProperty("lockentry").ToXmlElement(responsedoc);
            node.AppendChild(lockentry1);

            XmlNode lockscope1 = new WebDavProperty("lockscope").ToXmlElement(responsedoc);
            lockentry1.AppendChild(lockscope1);

            XmlNode shared = new WebDavProperty("shared").ToXmlElement(responsedoc);
            lockscope1.AppendChild(shared);

            XmlNode locktype1 = new WebDavProperty("locktype").ToXmlElement(responsedoc);
            lockentry1.AppendChild(locktype1);

            XmlNode write1 = new WebDavProperty("write").ToXmlElement(responsedoc);
            locktype1.AppendChild(write1);

            return node;
        }
        /// <summary>
        /// Builds the <see cref="XmlDocument" /> containing the response body
        /// </summary>
        /// <param name="context">The <see cref="IHttpListenerContext" /></param>
        /// <param name="propname">The boolean defining the Propfind propname request</param>
        /// <returns>
        /// The <see cref="XmlDocument" /> containing the response body
        /// </returns>
        private XmlDocument ResponseDocument(IHttpListenerContext context, bool propname)
        {
            // Create the basic response XmlDocument
            XmlDocument responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\"?><D:multistatus xmlns:D=\"DAV:\"></D:multistatus>";
            responseDoc.LoadXml(responseXml);

            // Generate the manager
            XmlNamespaceManager manager = new XmlNamespaceManager(responseDoc.NameTable);
            manager.AddNamespace("D", "DAV:");
            manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
            manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
            manager.AddNamespace("Z", "urn:schemas-microsoft-com:");

            int count = 0;

            foreach (IWebDavStoreItem webDavStoreItem in _webDavStoreItems)
            {
                // Create the response element
                WebDavProperty responseProperty = new WebDavProperty("response", "");
                XmlElement responseElement = responseProperty.ToXmlElement(responseDoc);

                // The href element
                Uri result;
                if (count == 0)
                {
                    Uri.TryCreate(_requestUri, "", out result);
                }
                else
                {
                    Uri.TryCreate(_requestUri, webDavStoreItem.Name, out result);
                }
                WebDavProperty hrefProperty = new WebDavProperty("href", result.AbsoluteUri);
                responseElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
                count++;

                // The propstat element
                WebDavProperty propstatProperty = new WebDavProperty("propstat", "");
                XmlElement propstatElement = propstatProperty.ToXmlElement(responseDoc);

                // The prop element
                WebDavProperty propProperty = new WebDavProperty("prop", "");
                XmlElement propElement = propProperty.ToXmlElement(responseDoc);

                foreach (WebDavProperty davProperty in _requestedProperties)
                {
                    propElement.AppendChild(PropChildElement(davProperty, responseDoc, webDavStoreItem, propname));
                }

                // Add the prop element to the propstat element
                propstatElement.AppendChild(propElement);

                // The status element
                WebDavProperty statusProperty = new WebDavProperty("status",
                    "HTTP/1.1 " + context.Response.StatusCode + " " +
                    HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
                propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

                // Add the propstat element to the response element
                responseElement.AppendChild(propstatElement);

                // Add the response element to the multistatus element
                responseDoc.DocumentElement.AppendChild(responseElement);
            }

            return responseDoc;
        }
 /// <summary>
 /// Set properties, it should be implemented by derived classes
 /// </summary>
 /// <param name="property">The property we want to retrieve value</param>
 public virtual String GetProperty(WebDavProperty property)
 {
     return String.Empty;
 }
        /// <summary>
        ///     Processes the request.
        /// </summary>
        /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
        /// <param name="context">
        ///     The
        ///     <see cref="IHttpListenerContext" /> object containing both the request and response
        ///     objects to use.
        /// </param>
        /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
        public override void ProcessRequest(WebDavServer server, IHttpListenerContext context, IWebDavStore store)
        {
            /***************************************************************************************************
             * Retreive al the information from the request
             ***************************************************************************************************/

            // Get the URI to the location
            Uri requestUri = context.Request.Url;

            // Initiate the XmlNamespaceManager and the XmlNodes
            XmlNode propNode = null;


            StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
            string requestBody = reader.ReadToEnd();

            if (!IsNullOrEmpty(requestBody))
            {
                XmlDocument requestDocument = new XmlDocument();
                requestDocument.LoadXml(requestBody);

                if (requestDocument.DocumentElement != null)
                {
                    var manager = new XmlNamespaceManager(requestDocument.NameTable);
                    manager.AddNamespace("D", "DAV:");
                    manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
                    manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
                    manager.AddNamespace("Z", "urn:schemas-microsoft-com:");
                    propNode = requestDocument.DocumentElement.SelectSingleNode("D:set/D:prop", manager);
                }
            }


            /***************************************************************************************************
             * Take action
             ***************************************************************************************************/
            // Get the parent collection of the item
            IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);
            // Get the item from the collection
            IWebDavStoreItem item = GetItemFromCollection(collection, context.Request.Url);


            IWebDavFileInfo fileInfo = item.GetFileInfo();

            if (propNode != null && fileInfo.Exists)
            {
                foreach (XmlNode node in propNode.ChildNodes)
                {
                    switch (node.LocalName)
                    {
                        case "Win32CreationTime":
                            fileInfo.CreationTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                            break;
                        case "Win32LastAccessTime":
                            fileInfo.LastAccessTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                            break;
                        case "Win32LastModifiedTime":
                            fileInfo.LastWriteTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
                            break;
                        case "Win32FileAttributes":
                            FileAttributes fa = //(FileAttributes)int.Parse(node.InnerText);
                                (FileAttributes) Convert.ToInt32(node.InnerText, 16);
                            //(node.InnerText.All(c => c == '0' && c == '1')) ?
                            //(FileAttributes)BitConverter.ToInt32(GetBytes(node.InnerText), 0);// :
                            // (FileAttributes)int.Parse(node.InnerText);
                            fileInfo.ApplyAttributes(fa);
                            fileInfo.Apply();
                            break;
                    }
                }
            }
#if DoNotRun

    /***************************************************************************************************
             * Create the body for the response
             ***************************************************************************************************/

    // Create the basic response XmlDocument
            XmlDocument responseDoc = new XmlDocument();
            const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:multistatus " +
                                       "xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\">" +
                                       "<D:response></D:response></D:multistatus>";
            responseDoc.LoadXml(responseXml);

            // Select the response node
            XmlNode responseNode = responseDoc.DocumentElement.SelectSingleNode("D:response", manager);

            // Add the elements

            // The href element
            WebDavProperty hrefProperty = new WebDavProperty("href", requestUri.ToString());
            responseNode.AppendChild(hrefProperty.ToXmlElement(responseDoc));

            // The propstat element
            WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
            XmlElement propstatElement = propstatProperty.ToXmlElement(responseDoc);

            // The propstat/status element
            WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " +
                                                                         HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
            propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));

            // The other propstat children
            foreach (WebDavProperty property in from XmlNode child in propNode.ChildNodes
                                                where 
                                                    child.Name.ToLower().Contains("creationtime") || 
                                                    child.Name.ToLower().Contains("fileattributes") || 
                                                    child.Name.ToLower().Contains("lastaccesstime") || 
                                                    child.Name.ToLower().Contains("lastmodifiedtime")

                                                let node = propNode.SelectSingleNode(child.Name, manager)
                                                select new WebDavProperty(child.LocalName, string.Empty, node != null ? node.NamespaceURI : string.Empty))

                propstatElement.AppendChild(property.ToXmlElement(responseDoc));

            responseNode.AppendChild(propstatElement);


            /***************************************************************************************************
            * Send the response
            ***************************************************************************************************/

            //</D:propstat>

            // convert the StringBuilder
            string resp = responseDoc.InnerXml;
#else
            StringBuilder sb = new StringBuilder(4000);
            sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?><D:multistatus xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\"><D:response><D:href>");
            sb.Append(requestUri);
            sb.Append("</D:href>");
            if (propNode != null)
            {
                string statusCode = context.Response.StatusCode.ToString();
                string statusCodeDesc = HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode);
                foreach (XmlNode child in propNode.ChildNodes.Cast<XmlNode>().Where(child => child.Name.ToLower().Contains("creationtime") || child.Name.ToLower().Contains("fileattributes") || child.Name.ToLower().Contains("lastaccesstime") || child.Name.ToLower().Contains("lastmodifiedtime")))
                {
                    sb.Append("<D:propstat><D:prop>");
                    sb.Append(child.LocalName);
                    sb.Append("</D:prop><D:status>HTTP/1.1 ");
                    sb.Append(statusCode);
                    sb.Append(" ");
                    sb.Append(statusCodeDesc);
                    sb.Append("</D:status></D:propstat>");
                }
            }
            sb.Append("</D:response></D:multistatus>");
            string resp = sb.ToString();

#endif
            byte[] responseBytes = Encoding.UTF8.GetBytes(resp);


            // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
            context.Response.StatusCode = (int) WebDavStatusCode.MultiStatus;
            context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int) WebDavStatusCode.MultiStatus);

            // set the headers of the response
            context.Response.ContentLength64 = responseBytes.Length;
            context.Response.AdaptedInstance.ContentType = "text/xml";

            // the body
            context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);

            context.Response.Close();
        }