using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml;
using Common.Logging;
using WebDAVSharp.Server.Adapters;
using WebDAVSharp.Server.Stores;
using WebDAVSharp.Server.Utilities;
namespace WebDAVSharp.Server.MethodHandlers {
///
/// This class implements the PROPPATCH HTTP method for WebDAV#.
///
internal class WebDavProppatchMethodHandler : WebDavMethodHandlerBase, IWebDavMethodHandler {
///
/// Gets the collection of the names of the HTTP methods handled by this instance.
///
///
/// The names.
///
public IEnumerable Names {
get {
return new[]
{
"PROPPATCH"
};
}
}
///
/// 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 void ProcessRequest(WebDavServer server, HttpContext context, IWebDavStore store, String fileName) {
ILog log = LogManager.GetCurrentClassLogger();
/***************************************************************************************************
* Retreive al the information from the request
***************************************************************************************************/
// Get the URI to the location
//Uri requestUri = context.Request.Url2;
// 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") {
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
IWebDavStoreCollection collection = GetParentCollection(server, store, fileName);
// Get the item from the collection
IWebDavStoreItem item = GetItemFromCollection(collection, fileName);
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":
//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 = "" +
"";
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", server.ServiceUrl + fileName);
responseNode.AppendChild(hrefProperty.ToXmlElement(responseDoc));
// The propstat element
WebDavProperty propstatProperty = new WebDavProperty("propstat", "");
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 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
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.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";
context.Response.ContentType = "text/xml";
// the body
context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
//context.Response.Close();
}
}
}