private bool AddCategoriesIfNecessary(string blogId, BlogPost post, INewCategoryContext newCategoryContext)
        {
            // this blog doesn't support adding categories
            if (!Options.SupportsNewCategories)
                return false;

            // no new categories to add
            if (post.NewCategories.Length == 0)
                return false;

            // we support inline category addition and we don't require a special
            // api for heirarchical categories (inline api can't handle parent specification)
            if (Options.SupportsNewCategoriesInline && !Options.SupportsHierarchicalCategories)
                return false;

            // add the categories and update their ids
            ArrayList newCategories = new ArrayList();
            foreach (BlogPostCategory category in post.NewCategories)
            {
                string categoryId = AddCategory(blogId, category);
                BlogPostCategory newCategory = new BlogPostCategory(categoryId, category.Name, category.Parent);
                newCategories.Add(newCategory);
                newCategoryContext.NewCategoryAdded(newCategory);
            }
            post.NewCategories = newCategories.ToArray(typeof(BlogPostCategory)) as BlogPostCategory[];
            return true;
        }
        /// <summary>
        /// Edit an existing entry
        /// </summary>
        /// <param name="blog">blog</param>
        /// <param name="postId">post id</param>
        /// <param name="account">account to post to</param>
        /// <param name="entry">entry to post</param>
        /// <param name="publish">publish now?</param>
        /// <returns>was the entry successfully edited</returns>
        public override bool EditPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                Trace.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            bool addCategoriesOutOfBand = AddCategoriesIfNecessary(blogId, post, newCategoryContext);

            bool result;
            if (Options.SupportsCategoriesInline)
            {
                result = MetaweblogEditPost(blogId, post, publish);
                if (Options.SupportsHierarchicalCategories)
                    MovableTypeSetPostCategories(post.Id, ArrayHelper.Concat(post.Categories, post.NewCategories));
            }
            else
            {
                result = MovableTypeEditPost(blogId, post, publish);
            }

            // if we succeeded then note addition of categories if appropriate
            if (!addCategoriesOutOfBand)
            {
                foreach (BlogPostCategory category in post.NewCategories)
                    newCategoryContext.NewCategoryAdded(category);
            }

            return result;
        }
        public string NewPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish, out string etag, out XmlDocument remotePost)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                Trace.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            Login();

            FixupBlogId(ref blogId);

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

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

            string slug = null;

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

            WebHeaderCollection responseHeaders;
            Uri         uri    = new Uri(blogId);
            XmlDocument result = xmlRestRequestHelper.Post(
                ref uri,
                new HttpRequestFilter(new NewPostRequest(this, slug).RequestFilter),
                ENTRY_CONTENT_TYPE,
                doc,
                _clientOptions.CharacterSet,
                out responseHeaders);

            etag = FilterWeakEtag(responseHeaders["ETag"]);
            string location = responseHeaders["Location"];

            if (string.IsNullOrEmpty(location))
            {
                throw new BlogClientInvalidServerResponseException("POST", "The HTTP response was missing the required Location header.", "");
            }
            if (location != responseHeaders["Content-Location"] || result == null)
            {
                Uri locationUri = new Uri(location);
                WebHeaderCollection getResponseHeaders;
                result = xmlRestRequestHelper.Get(ref locationUri, RequestFilter, out getResponseHeaders);
                etag   = FilterWeakEtag(getResponseHeaders["ETag"]);
            }

            remotePost = (XmlDocument)result.Clone();
            Parse(result.DocumentElement, true, uri);

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

            return(PostUriToPostId(location));
        }
        public virtual bool EditPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish, out string etag, out XmlDocument remotePost)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                Trace.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            Login();

            FixupBlogId(ref blogId);

            XmlDocument doc       = post.AtomRemotePost;
            XmlElement  entryNode = doc.SelectSingleNode("/atom:entry", _nsMgr) 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
                {
                    Uri uri = PostIdToPostUri(post.Id);
                    WebHeaderCollection responseHeaders;
                    xmlRestRequestHelper.Put(ref uri, etagToMatch, RequestFilter, ENTRY_CONTENT_TYPE, doc, _clientOptions.CharacterSet, true, out responseHeaders);
                }
                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 = 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, out etag, out remotePost))
                {
                    // 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;
                }
            }

            Uri getUri = PostIdToPostUri(post.Id);
            WebHeaderCollection getResponseHeaders;

            remotePost = xmlRestRequestHelper.Get(ref getUri, RequestFilter, out getResponseHeaders);
            etag       = FilterWeakEtag(getResponseHeaders["ETag"]);
            Trace.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);
        }
Example #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));
        }
        public string NewPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish, out string etag, out XmlDocument remotePost)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                Trace.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            Login();

            FixupBlogId(ref blogId);

            XmlDocument doc = new XmlDocument();
            XmlElement entryNode = doc.CreateElement(_atomNS.Prefix, "entry", _atomNS.Uri);
            doc.AppendChild(entryNode);
            Populate(post, null, entryNode, publish);

            string slug = null;
            if (Options.SupportsSlug)
                slug = post.Slug;

            WebHeaderCollection responseHeaders;
            Uri uri = new Uri(blogId);
            XmlDocument result = xmlRestRequestHelper.Post(
                ref uri,
                new HttpRequestFilter(new NewPostRequest(this, slug).RequestFilter),
                ENTRY_CONTENT_TYPE,
                doc,
                _clientOptions.CharacterSet,
                out responseHeaders);

            etag = FilterWeakEtag(responseHeaders["ETag"]);
            string location = responseHeaders["Location"];
            if (string.IsNullOrEmpty(location))
            {
                throw new BlogClientInvalidServerResponseException("POST", "The HTTP response was missing the required Location header.", "");
            }
            if (location != responseHeaders["Content-Location"] || result == null)
            {
                Uri locationUri = new Uri(location);
                WebHeaderCollection getResponseHeaders;
                result = xmlRestRequestHelper.Get(ref locationUri, RequestFilter, out getResponseHeaders);
                etag = FilterWeakEtag(getResponseHeaders["ETag"]);
            }

            remotePost = (XmlDocument)result.Clone();
            Parse(result.DocumentElement, true, uri);

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

            return PostUriToPostId(location);
        }
        public virtual bool EditPost(string blogId, BlogPost post, INewCategoryContext newCategoryContext, bool publish, out string etag, out XmlDocument remotePost)
        {
            if (!publish && !Options.SupportsPostAsDraft)
            {
                Trace.Fail("Post to draft not supported on this provider");
                throw new BlogClientPostAsDraftUnsupportedException();
            }

            Login();

            FixupBlogId(ref blogId);

            XmlDocument doc = post.AtomRemotePost;
            XmlElement entryNode = doc.SelectSingleNode("/atom:entry", _nsMgr) 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
                {
                    Uri uri = PostIdToPostUri(post.Id);
                    WebHeaderCollection responseHeaders;
                    xmlRestRequestHelper.Put(ref uri, etagToMatch, RequestFilter, ENTRY_CONTENT_TYPE, doc, _clientOptions.CharacterSet, true, out responseHeaders);
                }
                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 = 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, out etag, out remotePost))
                {
                    // 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;
                }
            }

            Uri getUri = PostIdToPostUri(post.Id);
            WebHeaderCollection getResponseHeaders;
            remotePost = xmlRestRequestHelper.Get(ref getUri, RequestFilter, out getResponseHeaders);
            etag = FilterWeakEtag(getResponseHeaders["ETag"]);
            Trace.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;
        }