Ejemplo n.º 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);
        }
        /// <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>
        /// <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="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>
        /// 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>
        /// 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;
        }
Ejemplo n.º 7
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);
        }
        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:\"", "");
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
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);
        }
        /// <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>
        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();
        }
Ejemplo n.º 13
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();
        }
        /// <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>
        /// 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>
        /// 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(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>
        ///     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>
        ///     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();
        }