private async Task <XmlDocument> GetCreatedEntity(HttpResponseMessage postResponse, PostNewImageResult result)
        {
            result.editUri = postResponse.Headers["Location"];
            string contentLocation = postResponse.Headers["Content-Location"];

            if (string.IsNullOrEmpty(result.editUri) || result.editUri != contentLocation)
            {
                XmlRestRequestHelper.XmlRequestResult xmlResult = new XmlRestRequestHelper.XmlRequestResult();

                xmlResult.uri = postResponse.RequestMessage.RequestUri;
                if (!string.IsNullOrEmpty(result.editUri))
                {
                    xmlResult.uri = new Uri(result.editUri);
                }
                XmlDocument doc = await xmlRestRequestHelper.Get(_requestFilter, xmlResult);

                result.etag = xmlResult.responseHeaders["ETag"];
                return(doc);
            }
            else
            {
                result.etag = postResponse.Headers["ETag"];
                XmlDocument xmlDoc = new XmlDocument();

                var xml = await postResponse.Content.ReadAsStringAsync();

                xmlDoc.LoadXml(xml);

                XmlHelper.ApplyBaseUri(xmlDoc, postResponse.RequestMessage.RequestUri);
                return(xmlDoc);
            }
        }
Ejemplo n.º 2
0
        public async Task <BlogPost> GetPost(string blogId, string postId)
        {
            Login();

            FixupBlogId(ref blogId);

            XmlRestRequestHelper.XmlRequestResult result = new XmlRestRequestHelper.XmlRequestResult();

            result.uri             = PostIdToPostUri(postId);
            result.responseHeaders = new HttpResponseMessage().Headers;
            var doc = await xmlRestRequestHelper.Get(RequestFilter, result);

            XmlDocument remotePost = (XmlDocument)doc.CloneNode(true);
            XmlElement  entryNode  = doc.SelectSingleNodeNS("/atom:entry", _nsMgr.ToNSMethodFormat()) as XmlElement;

            if (entryNode == null)
            {
                throw new BlogClientInvalidServerResponseException("GetPost", "No post entry returned from server", doc.GetXml());
            }

            BlogPost post = Parse(entryNode, true, result.uri);

            post.Id             = postId;
            post.ETag           = FilterWeakEtag(result.responseHeaders["ETag"]);
            post.AtomRemotePost = remotePost;
            return(post);
        }
Ejemplo n.º 3
0
        protected virtual async Task <XmlDocument> GetCategoryXml(string blogId)
        {
            // Get the service document
            Login();

            FixupBlogId(ref blogId);

            XmlRestRequestHelper.XmlRequestResult result = new XmlRestRequestHelper.XmlRequestResult();
            result.uri = FeedServiceUrl;
            var xmlDoc = await xmlRestRequestHelper.Get(RequestFilter, result);

            foreach (XmlElement entryEl in xmlDoc.SelectNodesNS("app:service/app:workspace/app:collection", _nsMgr.ToNSMethodFormat()))
            {
                string href = XmlHelper.GetUrl(entryEl, "@href", result.uri);
                if (blogId == href)
                {
                    XmlDocument results     = new XmlDocument();
                    XmlElement  rootElement = results.CreateElement("categoryInfo");
                    results.AppendChild(rootElement);
                    foreach (XmlElement categoriesNode in entryEl.SelectNodesNS("app:categories", _nsMgr.ToNSMethodFormat()))
                    {
                        await AddCategoriesXml(categoriesNode, rootElement, result);
                    }
                    return(results);
                }
            }
            //Debug.Fail("Couldn't find collection in service document:\r\n" + xmlDoc.OuterXml);
            return(new XmlDocument());
        }
        protected virtual async Task UpdateImage(bool allowWriteStreamBuffering, string editMediaUri, string path, string editEntryUri, string etag, bool getEditInfo, PostNewImageResult result)
        {
            HttpResponseMessage response = null;

            try
            {
                response = await RedirectHelper.GetResponse(editMediaUri,
                                                            new RedirectHelper.RequestFactory(new ImageUploadHelper(this, path, "PUT", etag, allowWriteStreamBuffering).Create));
            }
            catch (WebException we)
            {
                bool recovered = false;

                if (we.Status == WebExceptionStatus.ProtocolError && we.Response != null)
                {
                    HttpWebResponse errResponse = we.Response as HttpWebResponse;
                    if (errResponse != null && errResponse.StatusCode == HttpStatusCode.PreconditionFailed)
                    {
                        string newEtag = await AtomClient.GetEtag(editMediaUri, _requestFilter);

                        if (newEtag != null && newEtag.Length > 0 && newEtag != etag)
                        {
                            if (!AtomClient.ConfirmOverwrite())
                            {
                                throw new BlogClientOperationCancelledException();
                            }

                            try
                            {
                                response = await RedirectHelper.GetResponse(editMediaUri,
                                                                            new RedirectHelper.RequestFactory(new ImageUploadHelper(this, path, "PUT", newEtag, allowWriteStreamBuffering).Create));
                            }
                            finally
                            {
                                if (response != null)
                                {
                                    response.Dispose();
                                }
                            }

                            recovered = true;
                        }
                    }
                    else if (!allowWriteStreamBuffering)
                    {
                        // The error may have been due to the server requiring stream buffering (WinLive 114314, 252175)
                        // Try again with stream buffering.
                        await UpdateImage(true, editMediaUri, path, editEntryUri, etag, getEditInfo, result);

                        recovered = true;
                    }
                }
                if (!recovered)
                {
                    throw;
                }
            }

            // Check to see if we are going to get the src url and the etag, in most cases we will want to get this
            // information, but in the case of a photo album, since we never edit the image or link directly to them
            // we don't need the information and it can saves an http request.
            if (getEditInfo)
            {
                string selfPage;

                XmlRestRequestHelper.XmlRequestResult xmlResult = new XmlRestRequestHelper.XmlRequestResult();
                xmlResult.uri = new Uri(editEntryUri);
                XmlDocument mediaLinkEntry = await xmlRestRequestHelper.Get(_requestFilter, xmlResult);

                ParseResponse(mediaLinkEntry, result);
            }
            else
            {
                //thumbnailSmall = null;
                //thumbnailLarge = null;
                //srcUrl = null;
            }
        }
Ejemplo n.º 5
0
        public async Task <string> NewPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish, PostResult postResult)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                //Debug.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            Login();

            FixupBlogId(ref blogId);

            XmlDocument doc       = new XmlDocument();
            XmlElement  entryNode = doc.CreateElementNS(_atomNS.Uri, _atomNS.Prefix + ":entry");

            doc.AppendChild(entryNode);
            Populate(post, null, entryNode, publish);

            string slug = null;

            if (Options.SupportsSlug)
            {
                slug = post.Slug;
            }

            XmlRestRequestHelper.XmlRequestResult xmlResult2 = new XmlRestRequestHelper.XmlRequestResult();
            xmlResult2.uri = new Uri(blogId);
            XmlDocument result = await xmlRestRequestHelper.Post(
                new HttpAsyncRequestFilter(new NewPostRequest(this, slug).RequestFilter),
                ENTRY_CONTENT_TYPE,
                doc,
                _clientOptions.CharacterSet,
                xmlResult2);

            postResult.ETag = FilterWeakEtag(xmlResult2.responseHeaders["ETag"]);
            string location = xmlResult2.responseHeaders["Location"];

            if (string.IsNullOrEmpty(location))
            {
                throw new BlogClientInvalidServerResponseException("POST", "The HTTP response was missing the required Location header.", "");
            }
            if (location != xmlResult2.responseHeaders["Content-Location"] || result == null)
            {
                XmlRestRequestHelper.XmlRequestResult xmlResult = new XmlRestRequestHelper.XmlRequestResult();
                xmlResult.uri = new Uri(location);
                result        = await xmlRestRequestHelper.Get(RequestFilter, xmlResult);

                postResult.ETag = FilterWeakEtag(xmlResult.responseHeaders["ETag"]);
            }

            postResult.AtomRemotePost = (XmlDocument)result.CloneNode(true);
            Parse(result.DocumentElement, true, xmlResult2.uri);

            if (Options.SupportsNewCategories)
            {
                foreach (BlogPostCategory category in post.NewCategories)
                {
                    newCategoryContext.NewCategoryAdded(category);
                }
            }

            return(PostUriToPostId(location));
        }
Ejemplo n.º 6
0
        protected async Task <BlogInfo[]> GetUsersBlogsInternal()
        {
            XmlRestRequestHelper.XmlRequestResult xmlResult = new XmlRestRequestHelper.XmlRequestResult();
            xmlResult.uri = FeedServiceUrl;
            XmlDocument xmlDoc = await xmlRestRequestHelper.Get(RequestFilter, xmlResult);

            // Either the FeedServiceUrl points to a service document OR a feed.

            if (xmlDoc.SelectSingleNodeNS("/app:service", _nsMgr.ToNSMethodFormat()) != null)
            {
                ArrayList blogInfos = new ArrayList();
                foreach (XmlElement coll in xmlDoc.SelectNodesNS("/app:service/app:workspace/app:collection", _nsMgr.ToNSMethodFormat()))
                {
                    bool promote = ShouldPromote(coll);

                    // does this collection accept entries?
                    XmlNodeList acceptNodes    = coll.SelectNodesNS("app:accept", _nsMgr.ToNSMethodFormat());
                    bool        acceptsEntries = false;
                    if (acceptNodes.Count == 0)
                    {
                        acceptsEntries = true;
                    }
                    else
                    {
                        foreach (XmlElement acceptNode in acceptNodes)
                        {
                            if (AcceptsEntry(acceptNode.InnerText))
                            {
                                acceptsEntries = true;
                                break;
                            }
                        }
                    }

                    if (acceptsEntries)
                    {
                        string feedUrl = XmlHelper.GetUrl(coll, "@href", xmlResult.uri);
                        if (feedUrl == null || feedUrl.Length == 0)
                        {
                            continue;
                        }

                        // form title
                        StringBuilder titleBuilder = new StringBuilder();
                        foreach (XmlElement titleContainerNode in new XmlElement[] { coll.ParentNode as XmlElement, coll })
                        {
                            Debug.Assert(titleContainerNode != null);
                            if (titleContainerNode != null)
                            {
                                XmlElement titleNode = titleContainerNode.SelectSingleNodeNS("atom:title", _nsMgr.ToNSMethodFormat()) as XmlElement;
                                if (titleNode != null)
                                {
                                    string titlePart = _atomVer.TextNodeToPlaintext(titleNode);
                                    if (titlePart.Length != 0)
                                    {
                                        //Res.LOCME("loc the separator between parts of the blog name");
                                        if (titleBuilder.Length != 0)
                                        {
                                            titleBuilder.Append(" - ");
                                        }
                                        titleBuilder.Append(titlePart);
                                    }
                                }
                            }
                        }

                        // get homepage URL
                        string homepageUrl = "";
                        string dummy       = "";


                        XmlRestRequestHelper.XmlRequestResult xmlResult2 = new XmlRestRequestHelper.XmlRequestResult();
                        xmlResult2.uri = new Uri(feedUrl);
                        XmlDocument feedDoc = await xmlRestRequestHelper.Get(RequestFilter, xmlResult2);

                        ParseFeedDoc(feedDoc, xmlResult2.uri, false, ref homepageUrl, ref dummy);

                        // TODO: Sniff out the homepage URL
                        BlogInfo blogInfo = new BlogInfo(feedUrl, titleBuilder.ToString().Trim(), homepageUrl);
                        if (promote)
                        {
                            blogInfos.Insert(0, blogInfo);
                        }
                        else
                        {
                            blogInfos.Add(blogInfo);
                        }
                    }
                }

                return((BlogInfo[])blogInfos.ToArray(typeof(BlogInfo)));
            }
            else
            {
                string title       = string.Empty;
                string homepageUrl = string.Empty;

                ParseFeedDoc(xmlDoc, xmlResult.uri, true, ref homepageUrl, ref title);

                return(new BlogInfo[] { new BlogInfo(UrlHelper.SafeToAbsoluteUri(FeedServiceUrl), title, homepageUrl) });
            }
        }
Ejemplo n.º 7
0
        public virtual async Task <bool> EditPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish, EditPostResult result)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                //Debug.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            Login();

            FixupBlogId(ref blogId);

            XmlDocument doc       = post.AtomRemotePost;
            XmlElement  entryNode = doc.SelectSingleNodeNS("/atom:entry", _nsMgr.ToNSMethodFormat()) as XmlElement;

            // No documentUri is needed because we ensure xml:base is set on the root
            // when we retrieve from XmlRestRequestHelper
            Populate(post, null, entryNode, publish);
            string etagToMatch = FilterWeakEtag(post.ETag);

            try
            {
retry:
                try
                {
                    XmlRestRequestHelper.XmlRequestResult xmlResult2 = new XmlRestRequestHelper.XmlRequestResult();
                    xmlResult2.uri = PostIdToPostUri(post.Id);
                    await xmlRestRequestHelper.Put(etagToMatch, RequestFilter, ENTRY_CONTENT_TYPE, doc, _clientOptions.CharacterSet, true, xmlResult2);
                }
                catch (WebException we)
                {
                    if (we.Status == WebExceptionStatus.ProtocolError)
                    {
                        if (((HttpWebResponse)we.Response).StatusCode == HttpStatusCode.PreconditionFailed)
                        {
                            if (etagToMatch != null && etagToMatch.Length > 0)
                            {
                                HttpRequestHelper.LogException(we);

                                string currentEtag = await GetEtag(UrlHelper.SafeToAbsoluteUri(PostIdToPostUri(post.Id)));

                                if (currentEtag != null && currentEtag.Length > 0 &&
                                    currentEtag != etagToMatch)
                                {
                                    if (ConfirmOverwrite())
                                    {
                                        etagToMatch = currentEtag;
                                        goto retry;
                                    }
                                    else
                                    {
                                        throw new BlogClientOperationCancelledException();
                                    }
                                }
                            }
                        }
                    }
                    throw;
                }
            }
            catch (Exception e)
            {
                if (!AttemptEditPostRecover(e, blogId, post, newCategoryContext, publish, result))
                {
                    // convert to a provider exception if this is a 404 (allow us to
                    // catch this case explicitly and attempt a new post to recover)
                    if (e is WebException)
                    {
                        WebException    webEx    = e as WebException;
                        HttpWebResponse response = webEx.Response as HttpWebResponse;
                        if (response != null && response.StatusCode == HttpStatusCode.NotFound)
                        {
                            throw new BlogClientProviderException("404", e.Message);
                        }
                    }

                    // no special handling, just re-throw
                    throw;
                }
            }

            XmlRestRequestHelper.XmlRequestResult xmlResult = new XmlRestRequestHelper.XmlRequestResult();
            xmlResult.uri             = PostIdToPostUri(post.Id);
            xmlResult.responseHeaders = new HttpResponseMessage().Headers;
            result.remotePost         = await xmlRestRequestHelper.Get(RequestFilter, xmlResult);

            result.etag = FilterWeakEtag(xmlResult.responseHeaders["ETag"]);
            //Debug.Assert(remotePost != null, "After successful PUT, remote post could not be retrieved");

            if (Options.SupportsNewCategories)
            {
                foreach (BlogPostCategory category in post.NewCategories)
                {
                    newCategoryContext.NewCategoryAdded(category);
                }
            }

            return(true);
        }
Ejemplo n.º 8
0
        protected async Task <BlogPost[]> GetRecentPostsInternal(string blogId, int maxPosts, bool includeCategories, DateTime?now)
        {
            Login();

            FixupBlogId(ref blogId);

            HashSet <string> seenIds = new HashSet <string>();

            ArrayList blogPosts = new ArrayList();

            try
            {
                while (true)
                {
                    XmlDocument doc;
                    XmlRestRequestHelper.XmlRequestResult result = new XmlRestRequestHelper.XmlRequestResult();
                    result.uri = new Uri(blogId);

                    // This while-loop nonsense is necessary because New Blogger has a bug
                    // where the official URL for getting recent posts doesn't work when
                    // the orderby=published flag is set, but there's an un-official URL
                    // that will work correctly. Therefore, subclasses need the ability
                    // to inspect exceptions that occur, along with the URI that was used
                    // to make the request, and determine whether an alternate URI should
                    // be used.
                    while (true)
                    {
                        try
                        {
                            doc = await xmlRestRequestHelper.Get(RequestFilter, result);

                            break;
                        }
                        catch (Exception e)
                        {
                            //Debug.WriteLine(e.ToString());
                            if (AttemptAlternateGetRecentPostUrl(e, ref blogId))
                            {
                                continue;
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }

                    XmlNodeList nodeList = doc.SelectNodesNS("/atom:feed/atom:entry", _nsMgr.ToNSMethodFormat());
                    if (nodeList.Count == 0)
                    {
                        break;
                    }
                    foreach (XmlElement node in nodeList)
                    {
                        BlogPost blogPost = this.Parse(node, includeCategories, result.uri);
                        if (blogPost != null)
                        {
                            if (seenIds.Contains(blogPost.Id))
                            {
                                throw new DuplicateEntryIdException();
                            }
                            seenIds.Add(blogPost.Id);

                            if (!now.HasValue || blogPost.DatePublished.CompareTo(now.Value) < 0)
                            {
                                blogPosts.Add(blogPost);
                            }
                        }
                        if (blogPosts.Count >= maxPosts)
                        {
                            break;
                        }
                    }
                    if (blogPosts.Count >= maxPosts)
                    {
                        break;
                    }

                    XmlElement nextNode = doc.SelectSingleNodeNS("/atom:feed/atom:link[@rel='next']", _nsMgr.ToNSMethodFormat()) as XmlElement;
                    if (nextNode == null)
                    {
                        break;
                    }
                    blogId = XmlHelper.GetUrl(nextNode, "@href", result.uri);
                    if (blogId.Length == 0)
                    {
                        break;
                    }
                }
            }
            catch (DuplicateEntryIdException)
            {
                //if (ApplicationDiagnostics.AutomationMode)
                //    Debug.WriteLine("Duplicate IDs detected in feed");
                //else
                //    Debug.Fail("Duplicate IDs detected in feed");
            }
            return((BlogPost[])blogPosts.ToArray(typeof(BlogPost)));
        }
Ejemplo n.º 9
0
        private async Task AddCategoriesXml(XmlElement categoriesNode, XmlElement containerNode, XmlRestRequestHelper.XmlRequestResult result)
        {
            if (categoriesNode.Attributes.Any(a => a.NodeName == "href"))
            {
                string href = XmlHelper.GetUrl(categoriesNode, "@href", result.uri);
                if (href != null && href.Length > 0)
                {
                    Uri uri = new Uri(href);
                    if (result.uri == null || !uri.Equals(result.uri)) // detect simple cycles
                    {
                        XmlDocument doc = await xmlRestRequestHelper.Get(RequestFilter, result);

                        XmlElement categories = (XmlElement)doc.SelectSingleNodeNS(@"app:categories", _nsMgr.ToNSMethodFormat());
                        if (categories != null)
                        {
                            await AddCategoriesXml(categories, containerNode, result);
                        }
                    }
                }
            }
            else
            {
                containerNode.AppendChild(containerNode.OwnerDocument.ImportNode(categoriesNode, true));
            }
        }