private IReadOnlyList <EntityVersion <WebResourceName, string> > ExtractVersions(XmlDocumentWithNamespaceManager responseXml)
        {
            var responseNodes = responseXml.XmlDocument.SelectNodes("/D:multistatus/D:response", responseXml.XmlNamespaceManager);

            if (responseNodes == null)
            {
                return(new EntityVersion <WebResourceName, string> [0]);
            }

            var entities = new List <EntityVersion <WebResourceName, string> >();

            // ReSharper disable once LoopCanBeConvertedToQuery
            // ReSharper disable once PossibleNullReferenceException
            foreach (XmlElement responseElement in responseNodes)
            {
                var urlNode  = responseElement.SelectSingleNode("D:href", responseXml.XmlNamespaceManager);
                var etagNode = responseElement.SelectSingleNode("D:propstat/D:prop/D:getetag", responseXml.XmlNamespaceManager);
                if (urlNode != null &&
                    etagNode != null &&
                    _serverUrl.AbsolutePath != UriHelper.DecodeUrlString(urlNode.InnerText))
                {
                    var uri  = new WebResourceName(urlNode.InnerText);
                    var etag = HttpUtility.GetQuotedEtag(etagNode.InnerText);
                    if (s_logger.IsDebugEnabled)
                    {
                        s_logger.DebugFormat($"Got version '{uri}': '{etag}'");
                    }
                    entities.Add(EntityVersion.Create(uri, etag));
                }
            }

            return(entities);
        }
Exemple #2
0
        public async Task <IReadOnlyList <EntityVersion <WebResourceName, string> > > GetVersions(IEnumerable <WebResourceName> eventUrls)
        {
            WebResourceName firstResourceNameOrNull = null;

            var requestBody = @"<?xml version=""1.0""?>
			                    <C:calendar-multiget xmlns:C=""urn:ietf:params:xml:ns:caldav"" xmlns:D=""DAV:"">
			                        <D:prop>
			                            <D:getetag/>
			                        </D:prop>
                                        " +
                              String.Join(
                "\r\n",
                eventUrls.Select(u =>
            {
                if (firstResourceNameOrNull == null)
                {
                    firstResourceNameOrNull = u;
                }
                return($"<D:href>{SecurityElement.Escape(u.OriginalAbsolutePath)}</D:href>");
            })) + @"
                                    </C:calendar-multiget>";

            var responseXml = await _webDavClient.ExecuteWebDavRequestAndReadResponse(
                UriHelper.AlignServerUrl(_serverUrl, firstResourceNameOrNull),
                "REPORT",
                1,
                null,
                null,
                "application/xml",
                requestBody
                );

            XmlNodeList responseNodes = responseXml.XmlDocument.SelectNodes("/D:multistatus/D:response", responseXml.XmlNamespaceManager);

            var entities = new List <EntityVersion <WebResourceName, string> >();

            if (responseNodes == null)
            {
                return(entities);
            }

            // ReSharper disable once LoopCanBeConvertedToQuery
            // ReSharper disable once PossibleNullReferenceException
            foreach (XmlElement responseElement in responseNodes)
            {
                var urlNode  = responseElement.SelectSingleNode("D:href", responseXml.XmlNamespaceManager);
                var etagNode = responseElement.SelectSingleNode("D:propstat/D:prop/D:getetag", responseXml.XmlNamespaceManager);
                if (urlNode != null && etagNode != null)
                {
                    entities.Add(EntityVersion.Create(new WebResourceName(urlNode.InnerText),
                                                      HttpUtility.GetQuotedEtag(etagNode.InnerText)));
                }
            }

            return(entities);
        }
Exemple #3
0
        private IReadOnlyList <EntityVersion <WebResourceName, string> > ExtractVersions(XmlDocumentWithNamespaceManager responseXml)
        {
            s_logger.Debug("Entered ExtractVersions.");

            var entities = new List <EntityVersion <WebResourceName, string> > ();

            XmlNodeList responseNodes = responseXml.XmlDocument.SelectNodes("/D:multistatus/D:response", responseXml.XmlNamespaceManager);

            // ReSharper disable once LoopCanBeConvertedToQuery
            // ReSharper disable once PossibleNullReferenceException
            foreach (XmlElement responseElement in responseNodes)
            {
                var urlNode         = responseElement.SelectSingleNode("D:href", responseXml.XmlNamespaceManager);
                var etagNode        = responseElement.SelectSingleNode("D:propstat/D:prop/D:getetag", responseXml.XmlNamespaceManager);
                var contentTypeNode = responseElement.SelectSingleNode("D:propstat/D:prop/D:getcontenttype", responseXml.XmlNamespaceManager);

                if (urlNode != null && etagNode != null)
                {
                    string contentType = contentTypeNode?.InnerText ?? string.Empty;

                    var eTag = HttpUtility.GetQuotedEtag(etagNode.InnerText);
                    // the directory is also included in the list. It has a etag of '"None"' and is skipped
                    // in Owncloud eTag is empty for directory
                    // Yandex returns some eTag and the urlNode for the directory itself, so we need to filter that out aswell
                    // TODO: add vlist support but for now filter out sogo vlists since we can't parse them atm

                    if (!string.IsNullOrEmpty(eTag) &&
                        String.Compare(eTag, @"""None""", StringComparison.OrdinalIgnoreCase) != 0 &&
                        _serverUrl.AbsolutePath != UriHelper.DecodeUrlString(urlNode.InnerText) &&
                        _contentTypePredicate(contentType)
                        )
                    {
                        if (s_logger.IsDebugEnabled)
                        {
                            s_logger.DebugFormat($"'{urlNode.InnerText}': '{eTag}'");
                        }
                        entities.Add(EntityVersion.Create(new WebResourceName(urlNode.InnerText), eTag));
                    }
                }
            }

            s_logger.Debug("Exiting ExtractVersions.");
            return(entities);
        }
Exemple #4
0
        private async Task <string> GetEtagViaPropfind(Uri url)
        {
            var document = await _webDavClient.ExecuteWebDavRequestAndReadResponse(
                url,
                "PROPFIND",
                0,
                null,
                null,
                "application/xml",
                @"<?xml version='1.0'?>
                        <D:propfind xmlns:D=""DAV:"">
                          <D:prop>
                            <D:getetag/>
                          </D:prop>
                        </D:propfind>
                 "
                );

            XmlNode eTagNode = document.XmlDocument.SelectSingleNode("/D:multistatus/D:response/D:propstat/D:prop/D:getetag", document.XmlNamespaceManager);

            return(HttpUtility.GetQuotedEtag(eTagNode.InnerText));
        }
Exemple #5
0
        private async Task <IReadOnlyList <EntityVersion <WebResourceName, string> > > GetVersions(DateTimeRange?range, string entityType)
        {
            var entities = new List <EntityVersion <WebResourceName, string> >();

            try
            {
                var responseXml = await _webDavClient.ExecuteWebDavRequestAndReadResponse(
                    _serverUrl,
                    "REPORT",
                    1,
                    null,
                    null,
                    "application/xml",
                    string.Format(
                        @"<?xml version=""1.0""?>
                    <C:calendar-query xmlns:C=""urn:ietf:params:xml:ns:caldav"">
                        <D:prop xmlns:D=""DAV:"">
                            <D:getetag/>
                        </D:prop>
                        <C:filter>
                            <C:comp-filter name=""VCALENDAR"">
                                <C:comp-filter name=""{0}"">
                                  {1}
                                </C:comp-filter>
                            </C:comp-filter>
                        </C:filter>
                    </C:calendar-query>
                    ",
                        entityType,
                        range == null ? string.Empty : string.Format(@"<C:time-range start=""{0}"" end=""{1}""/>",
                                                                     range.Value.From.ToString(s_calDavDateTimeFormatString),
                                                                     range.Value.To.ToString(s_calDavDateTimeFormatString))
                        ));


                XmlNodeList responseNodes = responseXml.XmlDocument.SelectNodes("/D:multistatus/D:response", responseXml.XmlNamespaceManager);

                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once PossibleNullReferenceException
                foreach (XmlElement responseElement in responseNodes)
                {
                    var urlNode  = responseElement.SelectSingleNode("D:href", responseXml.XmlNamespaceManager);
                    var etagNode = responseElement.SelectSingleNode("D:propstat/D:prop/D:getetag", responseXml.XmlNamespaceManager);
                    if (urlNode != null &&
                        etagNode != null &&
                        _serverUrl.AbsolutePath != UriHelper.DecodeUrlString(urlNode.InnerText))
                    {
                        var uri = new WebResourceName(urlNode.InnerText);
                        entities.Add(EntityVersion.Create(uri, HttpUtility.GetQuotedEtag(etagNode.InnerText)));
                    }
                }
            }
            catch (WebDavClientException x)
            {
                // Workaround for Synology NAS, which returns 404 insteaod of an empty response if no events are present
                if (x.StatusCode == HttpStatusCode.NotFound && await IsResourceCalender())
                {
                    return(entities);
                }

                throw;
            }

            return(entities);
        }
Exemple #6
0
        public async Task <IReadOnlyList <EntityVersion <Uri, string> > > GetContacts()
        {
            var entities = new List <EntityVersion <Uri, string> >();

            try
            {
                var responseXml = await _webDavClient.ExecuteWebDavRequestAndReadResponse(
                    _serverUrl,
                    "PROPFIND",
                    1,
                    null,
                    null,
                    "application/xml",
                    @"<?xml version='1.0'?>
                        <D:propfind xmlns:D=""DAV:"">
                            <D:prop>
                              <D:getetag/>
                              <D:getcontenttype/>
                            </D:prop>
                        </D:propfind>
                 "
                    );

                XmlNodeList responseNodes = responseXml.XmlDocument.SelectNodes("/D:multistatus/D:response", responseXml.XmlNamespaceManager);

                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once PossibleNullReferenceException
                foreach (XmlElement responseElement in responseNodes)
                {
                    var urlNode         = responseElement.SelectSingleNode("D:href", responseXml.XmlNamespaceManager);
                    var etagNode        = responseElement.SelectSingleNode("D:propstat/D:prop/D:getetag", responseXml.XmlNamespaceManager);
                    var contentTypeNode = responseElement.SelectSingleNode("D:propstat/D:prop/D:getcontenttype", responseXml.XmlNamespaceManager);

                    if (urlNode != null && etagNode != null)
                    {
                        string contentType = contentTypeNode.InnerText ?? string.Empty;
                        var    eTag        = HttpUtility.GetQuotedEtag(etagNode.InnerText);
                        // the directory is also included in the list. It has a etag of '"None"' and is skipped
                        // in Owncloud eTag is empty for directory
                        // Yandex returns some eTag and the urlNode for the directory itself, so we need to filter that out aswell
                        // TODO: add vlist support but for now filter out sogo vlists since we can't parse them atm

                        if (!string.IsNullOrEmpty(eTag) &&
                            String.Compare(eTag, @"""None""", StringComparison.OrdinalIgnoreCase) != 0 &&
                            _serverUrl.AbsolutePath != UriHelper.DecodeUrlString(urlNode.InnerText) &&
                            contentType != "text/x-vlist"
                            )
                        {
                            var uri = UriHelper.UnescapeRelativeUri(_serverUrl, urlNode.InnerText);
                            entities.Add(EntityVersion.Create(uri, eTag));
                        }
                    }
                }
            }
            catch (WebException x)
            {
                if (x.Response != null)
                {
                    var httpWebResponse = (HttpWebResponse)x.Response;

                    if (httpWebResponse.StatusCode == HttpStatusCode.NotFound)
                    {
                        return(entities);
                    }
                }

                throw;
            }
            return(entities);
        }