/// <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); }
public async Task <OcsDirectoryInfo> GetDirectoryInfo(string name) { PropfindResponse response = await this.webDav.Propfind(name) .ConfigureAwait(false); if (!response.IsSuccessful) { return(null); } WebDavResource resource = response.Resources .OrderBy(r => r.Uri.Length) .FirstOrDefault(); if (resource == null) { return new OcsDirectoryInfo { Name = name } } ; WebDavProperty usedProperty = resource.Properties.FirstOrDefault(p => p.Name.LocalName == "quota-used-bytes"); WebDavProperty availableProperty = resource.Properties.FirstOrDefault(p => p.Name.LocalName == "quota-available-bytes"); long used, avail; if (usedProperty == null || !long.TryParse(usedProperty.Value, out used)) { used = long.MinValue; } if (availableProperty == null || !long.TryParse(availableProperty.Value, out avail)) { avail = long.MinValue; } long?quota = null; if (used != long.MinValue && avail != long.MinValue) { quota = used + avail; } return(new OcsDirectoryInfo { Name = name, QuotaBytes = quota, SizeBytes = used != long.MinValue ? used : default(long?) }); }
/// <summary> /// Returns the XML Format according to RFC /// Name: /// lockdiscovery /// Purpose: /// Describes the active locks on a resource /// Protected: /// MUST be protected. Clients change the list of locks through LOCK and UNLOCK, not through PROPPATCH. /// COPY/MOVE behavior: /// The value of this property depends on the lock state of the destination, not on the locks of the source resource. Recall /// that locks are not moved in a MOVE operation. /// Description: /// Returns a listing of who has a lock, what type of lock he has, the timeout type and the time remaining on the timeout, /// and the associated lock token. Owner information MAY be omitted if it is considered sensitive. If there are no locks, but /// the server supports locks, the property will be present but contain zero 'activelock' elements. If there are one or more locks, /// an 'activelock' element appears for each lock on the resource. This property is NOT lockable with respect to write locks (Section 7). /// </summary> /// <param name="path"></param> /// <param name="responsedoc"></param> /// <returns></returns> private static XmlNode LockDiscovery(Uri path, ref XmlDocument responsedoc) { XmlNode node = new WebDavProperty("lockdiscovery").ToXmlElement(responsedoc); foreach (var ilock in WebDavStoreItemLock.GetLocks(path)) { XmlNode activelock = new WebDavProperty("activelock").ToXmlElement(responsedoc); node.AppendChild(activelock); XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc); activelock.AppendChild(locktype); XmlNode locktypeitem = new WebDavProperty(ilock.LockType.ToString().ToLower()).ToXmlElement(responsedoc); locktype.AppendChild(locktypeitem); XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc); activelock.AppendChild(lockscope); XmlNode lockscopeitem = new WebDavProperty(ilock.LockScope.ToString().ToLower()).ToXmlElement(responsedoc); lockscope.AppendChild(lockscopeitem); XmlNode depth = new WebDavProperty("depth").ToXmlElement(responsedoc); depth.InnerText = ilock.Depth.ToString(CultureInfo.InvariantCulture); activelock.AppendChild(depth); XmlNode owner = new WebDavProperty("owner").ToXmlElement(responsedoc); owner.InnerText = ilock.Owner; activelock.AppendChild(owner); XmlNode timeout = new WebDavProperty("timeout").ToXmlElement(responsedoc); timeout.InnerText = ilock.RequestedTimeout; activelock.AppendChild(timeout); XmlNode locktoken = new WebDavProperty("locktoken").ToXmlElement(responsedoc); activelock.AppendChild(locktoken); XmlNode tokenhref = new WebDavProperty("href").ToXmlElement(responsedoc); tokenhref.InnerText = ilock.Token; locktoken.AppendChild(tokenhref); XmlNode lockroot = new WebDavProperty("lockroot").ToXmlElement(responsedoc); activelock.AppendChild(lockroot); XmlNode lockroothref = new WebDavProperty("href").ToXmlElement(responsedoc); lockroothref.InnerText = ilock.Path.ToString(); lockroot.AppendChild(lockroothref); } return(node); }
/// <summary> /// Returns an XML Fragment which details the supported locks on this implementation. /// 15.10 supportedlock Property /// Name: /// supportedlock /// Purpose: /// To provide a listing of the lock capabilities supported by the resource. /// Protected: /// MUST be protected. Servers, not clients, determine what lock mechanisms are supported. /// COPY/MOVE behavior: /// This property value is dependent on the kind of locks supported at the destination, not on the value of the property at the source resource. Servers attempting to COPY to a destination should not attempt to set this property at the destination. /// Description: /// Returns a listing of the combinations of scope and access types that may be specified in a lock request on the resource. Note that the actual contents are themselves controlled by access controls, so a server is not required to provide information the client is not authorized to see. This property is NOT lockable with respect to write locks (Section 7). /// </summary> /// <param name="responsedoc"></param> /// <returns></returns> private static XmlNode SupportedLocks(ref XmlDocument responsedoc) { XmlNode node = new WebDavProperty("supportedlock").ToXmlElement(responsedoc); XmlNode lockentry = new WebDavProperty("lockentry").ToXmlElement(responsedoc); node.AppendChild(lockentry); XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc); lockentry.AppendChild(lockscope); XmlNode exclusive = new WebDavProperty("exclusive").ToXmlElement(responsedoc); lockscope.AppendChild(exclusive); XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc); lockentry.AppendChild(locktype); XmlNode write = new WebDavProperty("write").ToXmlElement(responsedoc); locktype.AppendChild(write); XmlNode lockentry1 = new WebDavProperty("lockentry").ToXmlElement(responsedoc); node.AppendChild(lockentry1); XmlNode lockscope1 = new WebDavProperty("lockscope").ToXmlElement(responsedoc); lockentry1.AppendChild(lockscope1); XmlNode shared = new WebDavProperty("shared").ToXmlElement(responsedoc); lockscope1.AppendChild(shared); XmlNode locktype1 = new WebDavProperty("locktype").ToXmlElement(responsedoc); lockentry1.AppendChild(locktype1); XmlNode write1 = new WebDavProperty("write").ToXmlElement(responsedoc); locktype1.AppendChild(write1); return(node); }
/// <summary> /// Gets the correct value for a <see cref="WebDavProperty" /> /// </summary> /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param> /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param> /// <returns> /// A <see cref="string" /> containing the value /// </returns> private string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty) { switch (davProperty.Name) { case "creationdate": return(webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z"); case "displayname": return(webDavStoreItem.Name); case "getcontentlanguage": // still to implement !!! return(String.Empty); case "getcontentlength": return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Size : ""); case "getcontenttype": return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).MimeType : ""); case "getetag": return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Etag : ""); case "getlastmodified": return(webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R")); case "lockdiscovery": // still to implement !!! return(String.Empty); case "resourcetype": return(""); case "supportedlock": // still to implement !!! return(""); //webDavProperty.Value = "<D:lockentry><D:lockscope><D:shared/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry>"; case "ishidden": return("" + webDavStoreItem.Hidden); default: return(String.Empty); } }
/// <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> /// Gets the correct value for a <see cref="WebDavProperty" /> /// </summary> /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param> /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param> /// <returns> /// A <see cref="string" /> containing the value /// </returns> private string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty) { switch (davProperty.Name) { case "creationdate": return webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z"; case "displayname": return webDavStoreItem.Name; case "getcontentlanguage": // still to implement !!! return String.Empty; case "getcontentlength": return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument) webDavStoreItem).Size : ""); case "getcontenttype": return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument) webDavStoreItem).MimeType : ""); case "getetag": return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument) webDavStoreItem).Etag : ""); case "getlastmodified": return webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R"); case "lockdiscovery": // still to implement !!! return String.Empty; case "resourcetype": return ""; case "supportedlock": // still to implement !!! return ""; //webDavProperty.Value = "<D:lockentry><D:lockscope><D:shared/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry>"; case "ishidden": return "" + webDavStoreItem.Hidden; default: return String.Empty; } }
/// <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; }
/// <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> /// Returns the XML Format according to RFC /// Name: /// lockdiscovery /// Purpose: /// Describes the active locks on a resource /// Protected: /// MUST be protected. Clients change the list of locks through LOCK and UNLOCK, not through PROPPATCH. /// COPY/MOVE behavior: /// The value of this property depends on the lock state of the destination, not on the locks of the source resource. /// Recall /// that locks are not moved in a MOVE operation. /// Description: /// Returns a listing of who has a lock, what type of lock he has, the timeout type and the time remaining on the /// timeout, /// and the associated lock token. Owner information MAY be omitted if it is considered sensitive. If there are no /// locks, but /// the server supports locks, the property will be present but contain zero 'activelock' elements. If there are one or /// more locks, /// an 'activelock' element appears for each lock on the resource. This property is NOT lockable with respect to write /// locks (Section 7). /// </summary> /// <param name="storeItem"></param> /// <param name="responsedoc"></param> /// <param name="lockSystem"></param> /// <returns></returns> private static XmlNode LockDiscovery(IWebDavStoreItem storeItem, ref XmlDocument responsedoc, IWebDavStoreItemLock lockSystem) { XmlNode node = new WebDavProperty("lockdiscovery").ToXmlElement(responsedoc); foreach (IWebDavStoreItemLockInstance ilock in lockSystem.GetLocks(storeItem)) { XmlNode activelock = new WebDavProperty("activelock").ToXmlElement(responsedoc); node.AppendChild(activelock); XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc); activelock.AppendChild(locktype); XmlNode locktypeitem = new WebDavProperty(ilock.LockType.ToString().ToLower()).ToXmlElement(responsedoc); locktype.AppendChild(locktypeitem); XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc); activelock.AppendChild(lockscope); XmlNode lockscopeitem = new WebDavProperty(ilock.LockScope.ToString().ToLower()).ToXmlElement(responsedoc); lockscope.AppendChild(lockscopeitem); XmlNode depth = new WebDavProperty("depth").ToXmlElement(responsedoc); depth.InnerText = ilock.Depth.ToString(CultureInfo.InvariantCulture); activelock.AppendChild(depth); XmlNode owner = new WebDavProperty("owner").ToXmlElement(responsedoc); owner.InnerText = ilock.Owner; activelock.AppendChild(owner); XmlNode timeout = new WebDavProperty("timeout").ToXmlElement(responsedoc); timeout.InnerText = ilock.RequestedTimeout; activelock.AppendChild(timeout); XmlNode locktoken = new WebDavProperty("locktoken").ToXmlElement(responsedoc); activelock.AppendChild(locktoken); XmlNode tokenhref = new WebDavProperty("href").ToXmlElement(responsedoc); tokenhref.InnerText = ilock.Token.ToLockToken(); locktoken.AppendChild(tokenhref); XmlNode lockroot = new WebDavProperty("lockroot").ToXmlElement(responsedoc); activelock.AppendChild(lockroot); XmlNode lockroothref = new WebDavProperty("href").ToXmlElement(responsedoc); lockroothref.InnerText = ilock.Path; lockroot.AppendChild(lockroothref); } return node; }
/// <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> /// <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> /// Gets the correct value for a <see cref="WebDavProperty" /> /// </summary> /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param> /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param> /// <returns> /// A <see cref="string" /> containing the value /// </returns> private static string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty) { switch (davProperty.Name) { case "creationdate": return(webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z"); case "displayname": return(webDavStoreItem.Name); case "getcontentlanguage": //todo getcontentlanguage return(String.Empty); case "getcontentlength": return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Size : string.Empty); case "getcontenttype": return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).MimeType : string.Empty); case "getetag": return(!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Etag : string.Empty); case "getlastmodified": return(webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R")); case "resourcetype": //todo Add resourceType return(""); case "ishidden": return(webDavStoreItem.Hidden.ToString(CultureInfo.InvariantCulture)); default: return(String.Empty); } }
/// <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> /// 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> /// 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> /// Set properties, it should be implemented by derived classes /// </summary> /// <param name="property">The property we want to retrieve value</param> public virtual String GetProperty(WebDavProperty property) { return(String.Empty); }
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:\"", ""); }
/// <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> /// Gets the correct value for a <see cref="WebDavProperty" /> /// </summary> /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param> /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param> /// <returns> /// A <see cref="string" /> containing the value /// </returns> private static string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty) { if (webDavStoreItem is IWebDavStoreCollection && davProperty.StoreItemType == WebDavProperty.StoreItemTypeFlag.Document) return null; if (webDavStoreItem is IWebDavStoreDocument && davProperty.StoreItemType == WebDavProperty.StoreItemTypeFlag.Collection) return null; switch (davProperty.Name) { case "creationdate": return webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z"; case "displayname": return webDavStoreItem.Name; case "getcontentlanguage": //todo getcontentlanguage return Empty; case "getcontentlength": return webDavStoreItem.Size.ToString(CultureInfo.InvariantCulture); case "getcontenttype": return webDavStoreItem.MimeType; case "getetag": return "\"{" + webDavStoreItem.Etag + "},0\""; case "getlastmodified": return webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R"); case "resourcetype": //todo Add resourceType return ""; case "ishidden": return webDavStoreItem.GetFileInfo().Hidden ? "1" : "0"; case "win32fileattributes": string s = Convert.ToString((int) webDavStoreItem.GetFileInfo().GetAttributes(), 16); char[] bits = s.PadLeft(8, '0').ToCharArray(); return new string(bits); case "isfolder": return (webDavStoreItem is IWebDavStoreCollection) ? "t" : ""; case "iscollection": return (webDavStoreItem is IWebDavStoreCollection) ? "1" : "0"; case "authoritative-directory": return "t"; case "repl-uid": return "rid:{" + webDavStoreItem.GetRepl_uId() + "}"; case "resourcetag": return "rt:" + webDavStoreItem.GetRepl_uId() + "@00000000000"; default: return Empty; } }
/// <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> 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(); }
/// <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(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> /// 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> /// Gets the correct value for a <see cref="WebDavProperty" /> /// </summary> /// <param name="webDavStoreItem">The <see cref="IWebDavStoreItem" /> defines the values</param> /// <param name="davProperty">The <see cref="WebDavProperty" /> that needs a value</param> /// <returns> /// A <see cref="string" /> containing the value /// </returns> private static string GetWebDavPropertyValue(IWebDavStoreItem webDavStoreItem, WebDavProperty davProperty) { switch (davProperty.Name) { case "creationdate": return webDavStoreItem.CreationDate.ToUniversalTime().ToString("s") + "Z"; case "displayname": return webDavStoreItem.Name; case "getcontentlanguage": //todo getcontentlanguage return String.Empty; case "getcontentlength": return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Size : string.Empty); case "getcontenttype": return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).MimeType : string.Empty); case "getetag": return (!webDavStoreItem.IsCollection ? "" + ((IWebDavStoreDocument)webDavStoreItem).Etag : string.Empty); case "getlastmodified": return webDavStoreItem.ModificationDate.ToUniversalTime().ToString("R"); case "resourcetype": //todo Add resourceType return ""; case "ishidden": return webDavStoreItem.Hidden.ToString(CultureInfo.InvariantCulture); default: return String.Empty; } }
/// <summary> /// Returns an XML Fragment which details the supported locks on this implementation. /// 15.10 supportedlock Property /// Name: /// supportedlock /// Purpose: /// To provide a listing of the lock capabilities supported by the resource. /// Protected: /// MUST be protected. Servers, not clients, determine what lock mechanisms are supported. /// COPY/MOVE behavior: /// This property value is dependent on the kind of locks supported at the destination, not on the value of the /// property at the source resource. Servers attempting to COPY to a destination should not attempt to set this /// property at the destination. /// Description: /// Returns a listing of the combinations of scope and access types that may be specified in a lock request on the /// resource. Note that the actual contents are themselves controlled by access controls, so a server is not required /// to provide information the client is not authorized to see. This property is NOT lockable with respect to write /// locks (Section 7). /// </summary> /// <param name="responsedoc"></param> /// <returns></returns> private static XmlNode SupportedLocks(ref XmlDocument responsedoc) { XmlNode node = new WebDavProperty("supportedlock").ToXmlElement(responsedoc); XmlNode lockentry = new WebDavProperty("lockentry").ToXmlElement(responsedoc); node.AppendChild(lockentry); XmlNode lockscope = new WebDavProperty("lockscope").ToXmlElement(responsedoc); lockentry.AppendChild(lockscope); XmlNode exclusive = new WebDavProperty("exclusive").ToXmlElement(responsedoc); lockscope.AppendChild(exclusive); XmlNode locktype = new WebDavProperty("locktype").ToXmlElement(responsedoc); lockentry.AppendChild(locktype); XmlNode write = new WebDavProperty("write").ToXmlElement(responsedoc); locktype.AppendChild(write); XmlNode lockentry1 = new WebDavProperty("lockentry").ToXmlElement(responsedoc); node.AppendChild(lockentry1); XmlNode lockscope1 = new WebDavProperty("lockscope").ToXmlElement(responsedoc); lockentry1.AppendChild(lockscope1); XmlNode shared = new WebDavProperty("shared").ToXmlElement(responsedoc); lockscope1.AppendChild(shared); XmlNode locktype1 = new WebDavProperty("locktype").ToXmlElement(responsedoc); lockentry1.AppendChild(locktype1); XmlNode write1 = new WebDavProperty("write").ToXmlElement(responsedoc); locktype1.AppendChild(write1); return node; }
/// <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> /// Set properties, it should be implemented by derived classes /// </summary> /// <param name="property">The property we want to retrieve value</param> public virtual String GetProperty(WebDavProperty property) { return String.Empty; }
/// <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(); }