WebDavLockMethodHandler.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Text;
  7. using System.Web;
  8. using System.Xml;
  9. using Mtp2Dav.WebDAVSharp.Server._1d2086a502937936ebc6bfe19cfa15d855be1c31.Adapters;
  10. using Mtp2Dav.WebDAVSharp.Server._1d2086a502937936ebc6bfe19cfa15d855be1c31.Exceptions;
  11. using Mtp2Dav.WebDAVSharp.Server._1d2086a502937936ebc6bfe19cfa15d855be1c31.Stores;
  12. namespace Mtp2Dav.WebDAVSharp.Server._1d2086a502937936ebc6bfe19cfa15d855be1c31.MethodHandlers
  13. {
  14. /// <summary>
  15. /// This class implements the <c>LOCK</c> HTTP method for WebDAV#.
  16. /// </summary>
  17. internal class WebDavLockMethodHandler : WebDavMethodHandlerBase, IWebDavMethodHandler
  18. {
  19. /// <summary>
  20. /// Gets the collection of the names of the HTTP methods handled by this instance.
  21. /// </summary>
  22. /// <value>
  23. /// The names.
  24. /// </value>
  25. public IEnumerable<string> Names => new[]
  26. {
  27. "LOCK"
  28. };
  29. /// <summary>
  30. /// Processes the request.
  31. /// </summary>
  32. /// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
  33. /// <param name="context">
  34. /// The
  35. /// <see cref="IHttpListenerContext" /> object containing both the request and response
  36. /// objects to use.
  37. /// </param>
  38. /// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
  39. /// <exception cref="WebDavPreconditionFailedException"></exception>
  40. public void ProcessRequest(WebDavServer server, IHttpListenerContext context, IWebDavStore store)
  41. {
  42. /***************************************************************************************************
  43. * Retreive al the information from the request
  44. ***************************************************************************************************/
  45. // read the headers
  46. var depth = GetDepthHeader(context.Request);
  47. var timeout = GetTimeoutHeader(context.Request);
  48. // Initiate the XmlNamespaceManager and the XmlNodes
  49. XmlNamespaceManager manager = null;
  50. XmlNode lockscopeNode = null, locktypeNode = null, ownerNode = null;
  51. // try to read the body
  52. try
  53. {
  54. var reader = new StreamReader(context.Request.InputStream, Encoding.UTF8);
  55. var requestBody = reader.ReadToEnd();
  56. if (!requestBody.Equals("") && requestBody.Length != 0)
  57. {
  58. var requestDocument = new XmlDocument();
  59. requestDocument.LoadXml(requestBody);
  60. if (requestDocument.DocumentElement != null && requestDocument.DocumentElement.LocalName != "prop" &&
  61. requestDocument.DocumentElement.LocalName != "lockinfo")
  62. {
  63. }
  64. manager = new XmlNamespaceManager(requestDocument.NameTable);
  65. manager.AddNamespace("D", "DAV:");
  66. manager.AddNamespace("Office", "schemas-microsoft-com:office:office");
  67. manager.AddNamespace("Repl", "http://schemas.microsoft.com/repl/");
  68. manager.AddNamespace("Z", "urn:schemas-microsoft-com:");
  69. // Get the lockscope, locktype and owner as XmlNodes from the XML document
  70. lockscopeNode = requestDocument.DocumentElement.SelectSingleNode("D:lockscope", manager);
  71. locktypeNode = requestDocument.DocumentElement.SelectSingleNode("D:locktype", manager);
  72. ownerNode = requestDocument.DocumentElement.SelectSingleNode("D:owner", manager);
  73. }
  74. else
  75. {
  76. throw new WebDavPreconditionFailedException();
  77. }
  78. }
  79. catch (Exception)
  80. {
  81. throw;
  82. }
  83. /***************************************************************************************************
  84. * Lock the file or folder
  85. ***************************************************************************************************/
  86. var isNew = false;
  87. // Get the parent collection of the item
  88. var collection = GetParentCollection(server, store, context.Request.Url);
  89. try
  90. {
  91. // Get the item from the collection
  92. var item = GetItemFromCollection(collection, context.Request.Url);
  93. }
  94. catch (Exception)
  95. {
  96. collection.CreateDocument(context.Request.Url.Segments.Last().TrimEnd('/', '\\'));
  97. isNew = true;
  98. }
  99. /***************************************************************************************************
  100. * Create the body for the response
  101. ***************************************************************************************************/
  102. // Create the basic response XmlDocument
  103. var responseDoc = new XmlDocument();
  104. var responseXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><D:prop " +
  105. "xmlns:D=\"DAV:\"><D:lockdiscovery><D:activelock/></D:lockdiscovery></D:prop>";
  106. responseDoc.LoadXml(responseXml);
  107. // Select the activelock XmlNode
  108. var activelock = responseDoc.DocumentElement.SelectSingleNode("D:lockdiscovery/D:activelock", manager);
  109. // Import the given nodes
  110. activelock.AppendChild(responseDoc.ImportNode(lockscopeNode, true));
  111. activelock.AppendChild(responseDoc.ImportNode(locktypeNode, true));
  112. activelock.AppendChild(responseDoc.ImportNode(ownerNode, true));
  113. // Add the additional elements, e.g. the header elements
  114. // The timeout element
  115. var timeoutProperty = new WebDavProperty("timeout", timeout);
  116. activelock.AppendChild(timeoutProperty.ToXmlElement(responseDoc));
  117. // The depth element
  118. var depthProperty = new WebDavProperty("depth", depth == 0 ? "0" : "Infinity");
  119. activelock.AppendChild(depthProperty.ToXmlElement(responseDoc));
  120. // The locktoken element
  121. var locktokenProperty = new WebDavProperty("locktoken", "");
  122. var locktokenElement = locktokenProperty.ToXmlElement(responseDoc);
  123. var hrefProperty = new WebDavProperty("href", "opaquelocktoken:e71d4fae-5dec-22df-fea5-00a0c93bd5eb1");
  124. locktokenElement.AppendChild(hrefProperty.ToXmlElement(responseDoc));
  125. activelock.AppendChild(locktokenElement);
  126. /***************************************************************************************************
  127. * Send the response
  128. ***************************************************************************************************/
  129. // convert the StringBuilder
  130. var resp = responseDoc.InnerXml;
  131. var responseBytes = Encoding.UTF8.GetBytes(resp);
  132. if (isNew)
  133. {
  134. // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
  135. context.Response.StatusCode = (int) HttpStatusCode.Created;
  136. context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int) HttpStatusCode.Created);
  137. }
  138. else
  139. {
  140. // HttpStatusCode doesn't contain WebDav status codes, but HttpWorkerRequest can handle these WebDav status codes
  141. context.Response.StatusCode = (int) HttpStatusCode.OK;
  142. context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription((int) HttpStatusCode.OK);
  143. }
  144. // set the headers of the response
  145. context.Response.ContentLength64 = responseBytes.Length;
  146. context.Response.AdaptedInstance.ContentType = "text/xml";
  147. // the body
  148. context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
  149. context.Response.Close();
  150. }
  151. }
  152. }