WebDAVProppatchMethodHandler.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Web;
  7. using System.Xml;
  8. using WebDAVSharp.Server.Adapters;
  9. using WebDAVSharp.Server.Stores;
  10. using WebDAVSharp.Server.Utilities;
  11. using static System.String;
  12. namespace WebDAVSharp.Server.MethodHandlers
  13. {
  14. /// <summary>
  15. /// This class implements the <c>PROPPATCH</c> HTTP method for WebDAV#.
  16. /// </summary>
  17. internal class WebDavProppatchMethodHandler : WebDavMethodHandlerBase
  18. {
  19. #region Properties
  20. /// <summary>
  21. /// Gets the collection of the names of the HTTP methods handled by this instance.
  22. /// </summary>
  23. /// <value>
  24. /// The names.
  25. /// </value>
  26. public override IEnumerable<string> Names => new[]
  27. {
  28. "PROPPATCH"
  29. };
  30. #endregion
  31. #region Functions
  32. private static byte[] GetBytes(string bitString)
  33. {
  34. int i = Convert.ToInt32(bitString, 2);
  35. return BitConverter.GetBytes(i);
  36. //return
  37. // Enumerable.Range(0, bitString.Length / 8).
  38. // Select(pos => Convert.ToByte(
  39. // bitString.Substring(pos * 8, 8),
  40. // 2)
  41. // ).ToArray();
  42. }
  43. /// <summary>
  44. /// Processes the request.
  45. /// </summary>
  46. /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
  47. /// <param name="context">
  48. /// The
  49. /// <see cref="IHttpListenerContext" /> object containing both the request and response
  50. /// objects to use.
  51. /// </param>
  52. /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
  53. public override void ProcessRequest(WebDavServer server, IHttpListenerContext context, IWebDavStore store)
  54. {
  55. /***************************************************************************************************
  56. * Retreive al the information from the request
  57. ***************************************************************************************************/
  58. // Get the URI to the location
  59. Uri requestUri = context.Request.Url;
  60. // Initiate the XmlNamespaceManager and the XmlNodes
  61. XmlNode propNode = null;
  62. StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
  63. string requestBody = reader.ReadToEnd();
  64. if (!IsNullOrEmpty(requestBody))
  65. {
  66. XmlDocument requestDocument = new XmlDocument();
  67. requestDocument.LoadXml(requestBody);
  68. if (requestDocument.DocumentElement != null)
  69. {
  70. var manager = new XmlNamespaceManager(requestDocument.NameTable);
  71. manager.AddNamespace("D", "DAV:");
  72. manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
  73. manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
  74. manager.AddNamespace("Z", "urn:schemas-microsoft-com:");
  75. propNode = requestDocument.DocumentElement.SelectSingleNode("D:set/D:prop", manager);
  76. }
  77. }
  78. /***************************************************************************************************
  79. * Take action
  80. ***************************************************************************************************/
  81. // Get the parent collection of the item
  82. IWebDavStoreCollection collection = GetParentCollection(server, store, context.Request.Url);
  83. // Get the item from the collection
  84. IWebDavStoreItem item = GetItemFromCollection(collection, context.Request.Url);
  85. IWebDavFileInfo fileInfo = item.GetFileInfo();
  86. if (propNode != null && fileInfo.Exists)
  87. {
  88. foreach (XmlNode node in propNode.ChildNodes)
  89. {
  90. switch (node.LocalName)
  91. {
  92. case "Win32CreationTime":
  93. fileInfo.CreationTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
  94. break;
  95. case "Win32LastAccessTime":
  96. fileInfo.LastAccessTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
  97. break;
  98. case "Win32LastModifiedTime":
  99. fileInfo.LastWriteTime = Convert.ToDateTime(node.InnerText).ToUniversalTime();
  100. break;
  101. case "Win32FileAttributes":
  102. FileAttributes fa = //(FileAttributes)int.Parse(node.InnerText);
  103. (FileAttributes) Convert.ToInt32(node.InnerText, 16);
  104. //(node.InnerText.All(c => c == '0' && c == '1')) ?
  105. //(FileAttributes)BitConverter.ToInt32(GetBytes(node.InnerText), 0);// :
  106. // (FileAttributes)int.Parse(node.InnerText);
  107. fileInfo.ApplyAttributes(fa);
  108. fileInfo.Apply();
  109. break;
  110. }
  111. }
  112. }
  113. #if DoNotRun
  114. /***************************************************************************************************
  115. * Create the body for the response
  116. ***************************************************************************************************/
  117. // Create the basic response XmlDocument
  118. XmlDocument responseDoc = new XmlDocument();
  119. const string responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:multistatus " +
  120. "xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\">" +
  121. "<D:response></D:response></D:multistatus>";
  122. responseDoc.LoadXml(responseXml);
  123. // Select the response node
  124. XmlNode responseNode = responseDoc.DocumentElement.SelectSingleNode("D:response", manager);
  125. // Add the elements
  126. // The href element
  127. WebDavProperty hrefProperty = new WebDavProperty("href", requestUri.ToString());
  128. responseNode.AppendChild(hrefProperty.ToXmlElement(responseDoc));
  129. // The propstat element
  130. WebDavProperty propstatProperty = new WebDavProperty("propstat", string.Empty);
  131. XmlElement propstatElement = propstatProperty.ToXmlElement(responseDoc);
  132. // The propstat/status element
  133. WebDavProperty statusProperty = new WebDavProperty("status", "HTTP/1.1 " + context.Response.StatusCode + " " +
  134. HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode));
  135. propstatElement.AppendChild(statusProperty.ToXmlElement(responseDoc));
  136. // The other propstat children
  137. foreach (WebDavProperty property in from XmlNode child in propNode.ChildNodes
  138. where
  139. child.Name.ToLower().Contains("creationtime") ||
  140. child.Name.ToLower().Contains("fileattributes") ||
  141. child.Name.ToLower().Contains("lastaccesstime") ||
  142. child.Name.ToLower().Contains("lastmodifiedtime")
  143. let node = propNode.SelectSingleNode(child.Name, manager)
  144. select new WebDavProperty(child.LocalName, string.Empty, node != null ? node.NamespaceURI : string.Empty))
  145. propstatElement.AppendChild(property.ToXmlElement(responseDoc));
  146. responseNode.AppendChild(propstatElement);
  147. /***************************************************************************************************
  148. * Send the response
  149. ***************************************************************************************************/
  150. //</D:propstat>
  151. // convert the StringBuilder
  152. string resp = responseDoc.InnerXml;
  153. #else
  154. StringBuilder sb = new StringBuilder(4000);
  155. sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?><D:multistatus xmlns:Z=\"urn:schemas-microsoft-com:\" xmlns:D=\"DAV:\"><D:response><D:href>");
  156. sb.Append(requestUri);
  157. sb.Append("</D:href>");
  158. if (propNode != null)
  159. {
  160. string statusCode = context.Response.StatusCode.ToString();
  161. string statusCodeDesc = HttpWorkerRequest.GetStatusDescription(context.Response.StatusCode);
  162. 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")))
  163. {
  164. sb.Append("<D:propstat><D:prop>");
  165. sb.Append(child.LocalName);
  166. sb.Append("</D:prop><D:status>HTTP/1.1 ");
  167. sb.Append(statusCode);
  168. sb.Append(" ");
  169. sb.Append(statusCodeDesc);
  170. sb.Append("</D:status></D:propstat>");
  171. }
  172. }
  173. sb.Append("</D:response></D:multistatus>");
  174. string resp = sb.ToString();
  175. #endif
  176. byte[] responseBytes = Encoding.UTF8.GetBytes(resp);
  177. // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
  178. context.Response.StatusCode = (int) WebDavStatusCode.MultiStatus;
  179. context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int) WebDavStatusCode.MultiStatus);
  180. // set the headers of the response
  181. context.Response.ContentLength64 = responseBytes.Length;
  182. context.Response.AdaptedInstance.ContentType = "text/xml";
  183. // the body
  184. context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
  185. context.Response.Close();
  186. }
  187. #endregion
  188. }
  189. }