using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Web; using System.Xml; using WebDAVSharp.Server.Adapters; using WebDAVSharp.Server.Stores; using WebDAVSharp.Server.Utilities; using static System.String; namespace WebDAVSharp.Server.MethodHandlers { /// /// This class implements the PROPPATCH HTTP method for WebDAV#. /// internal class WebDavProppatchMethodHandler : WebDavMethodHandlerBase { #region Properties /// /// Gets the collection of the names of the HTTP methods handled by this instance. /// /// /// The names. /// public override IEnumerable Names => new[] { "PROPPATCH" }; #endregion #region Functions private static byte[] GetBytes(string bitString) { int i = Convert.ToInt32(bitString, 2); return BitConverter.GetBytes(i); //return // Enumerable.Range(0, bitString.Length / 8). // Select(pos => Convert.ToByte( // bitString.Substring(pos * 8, 8), // 2) // ).ToArray(); } /// /// Processes the request. /// /// The through which the request came in from the client. /// /// The /// object containing both the request and response /// objects to use. /// /// The that the is hosting. 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 = "" + ""; 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; #else StringBuilder sb = new StringBuilder(4000); sb.Append(""); sb.Append(requestUri); sb.Append(""); if (propNode != null) { string statusCode = context.Response.StatusCode.ToString(); string statusCodeDesc = HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode); foreach (XmlNode child in propNode.ChildNodes.Cast().Where(child => child.Name.ToLower().Contains("creationtime") || child.Name.ToLower().Contains("fileattributes") || child.Name.ToLower().Contains("lastaccesstime") || child.Name.ToLower().Contains("lastmodifiedtime"))) { sb.Append(""); sb.Append(child.LocalName); sb.Append("HTTP/1.1 "); sb.Append(statusCode); sb.Append(" "); sb.Append(statusCodeDesc); sb.Append(""); } } sb.Append(""); 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(); } #endregion } }