DocSpace-buildtools/thirdparty/AppLimit.CloudComputing.SharpBox/StorageProvider/WebDav/Logic/WebDavRequestParser.cs
2020-03-13 16:40:58 +03:00

133 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Xml.Linq;
using AppLimit.CloudComputing.SharpBox.Common.Extensions;
using AppLimit.CloudComputing.SharpBox.Common.IO;
using AppLimit.CloudComputing.SharpBox.Common.Net;
using AppLimit.CloudComputing.SharpBox.StorageProvider.API;
using AppLimit.CloudComputing.SharpBox.StorageProvider.BaseObjects;
namespace AppLimit.CloudComputing.SharpBox.StorageProvider.WebDav.Logic
{
internal delegate string NameBaseFilterCallback(string targetUrl, IStorageProviderService service, IStorageProviderSession session, string nameBase);
internal class WebDavRequestResult
{
public BaseFileEntry Self { get; set; }
public List<BaseFileEntry> Childs { get; set; }
public WebDavRequestResult()
{
Childs = new List<BaseFileEntry>();
}
}
internal class WebDavRequestParser
{
private const string DavNamespace = "DAV:";
private const string HttpOk = "HTTP/1.1 200 OK";
public static WebDavRequestResult CreateObjectsFromNetworkStream(Stream data, string targetUrl, IStorageProviderService service, IStorageProviderSession session, NameBaseFilterCallback callback)
{
var config = session.ServiceConfiguration as WebDavConfiguration;
var results = new WebDavRequestResult();
var queryLessUri = HttpUtilityEx.GetPathAndQueryLessUri(config.ServiceLocator).ToString().TrimEnd('/');
var decodedTargetUrl = HttpUtility.UrlDecode(targetUrl);
string s;
using (var streamReader = new StreamReader(data))
{
s = streamReader.ReadToEnd();
}
//todo:
var xDoc = XDocument.Load(new StringReader(s.Replace("d:d:", "d:")));
var responses = xDoc.Descendants(XName.Get("response", DavNamespace));
foreach (var response in responses)
{
var isHidden = false;
var isDirectory = false;
var lastModified = DateTime.Now;
long contentLength = 0;
var href = response.Element(XName.Get("href", DavNamespace)).ValueOrEmpty();
var propstats = response.Descendants(XName.Get("propstat", DavNamespace));
foreach (var propstat in propstats)
{
var prop = propstat.Element(XName.Get("prop", DavNamespace));
var status = propstat.Element(XName.Get("status", DavNamespace)).ValueOrEmpty();
if (!status.Equals(HttpOk) || prop == null) continue;
var strLastModified = prop.Element(XName.Get("getlastmodified", DavNamespace)).ValueOrEmpty();
var strContentLength = prop.Element(XName.Get("getcontentlength", DavNamespace)).ValueOrEmpty();
var resourceType = prop.Element(XName.Get("resourcetype", DavNamespace));
var strIsHidden = prop.Element(XName.Get("ishidden", DavNamespace)).ValueOrEmpty();
if (!string.IsNullOrEmpty(strIsHidden))
{
int code;
if (!int.TryParse(strIsHidden, out code))
code = 0;
isHidden = Convert.ToBoolean(code);
}
if (resourceType != null && resourceType.Element(XName.Get("collection", DavNamespace)) != null)
isDirectory = true;
if (!string.IsNullOrEmpty(strContentLength))
contentLength = Convert.ToInt64(strContentLength);
if (!string.IsNullOrEmpty(strLastModified) && DateTime.TryParse(strLastModified, out lastModified))
{
lastModified = lastModified.ToUniversalTime();
}
}
//entry not to be encluded
if (isHidden) continue;
var nameBase = href;
if (callback != null)
nameBase = callback(targetUrl, service, session, nameBase);
string nameBaseForSelfCheck;
if (nameBase.StartsWith(config.ServiceLocator.ToString()))
{
nameBaseForSelfCheck = HttpUtility.UrlDecode(nameBase);
nameBase = nameBase.Remove(0, config.ServiceLocator.ToString().Length);
}
else
{
nameBaseForSelfCheck = queryLessUri + HttpUtilityEx.PathDecodeUTF8(nameBase);
}
nameBase = nameBase.TrimEnd('/');
nameBaseForSelfCheck = nameBaseForSelfCheck.TrimEnd('/');
if (targetUrl.EndsWith("/"))
nameBaseForSelfCheck += "/";
var isSelf = nameBaseForSelfCheck.Equals(decodedTargetUrl);
var ph = new PathHelper(nameBase);
var resourceName = HttpUtility.UrlDecode(ph.GetFileName());
var entry = !isDirectory
? new BaseFileEntry(resourceName, contentLength, lastModified, service, session)
: new BaseDirectoryEntry(resourceName, contentLength, lastModified, service, session);
if (isSelf)
{
results.Self = entry;
}
else
{
results.Childs.Add(entry);
}
}
return results;
}
}
}