private BlogEditingTemplate ParseBlogPostIntoTemplate(BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress, string postUrl)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate));

            BlogPostRegions regions            = regionLocator.LocateRegionsOnUIThread(progress, postUrl);
            IHTMLElement    primaryTitleRegion = GetPrimaryEditableTitleElement(regions.BodyRegion, regions.Document, regions.TitleRegions);

            // IF
            //   - primaryTitleRegion is not null (title found)
            //   - BodyRegion is null (no post body found)
            //   - AND primaryTitleRegion is a link
            if (primaryTitleRegion != null && regions.BodyRegion == null && primaryTitleRegion.tagName.ToLower() == "a")
            {
                // Title region was detected, but body region was not.
                // It is possible that only titles are shown on the homepage
                // Try requesting the post itself, and loading regions from the post itself

                // HACK Somewhere the 'about:' protocol replaces http/https, replace it again with the correct protocol
                var pathMatch = new Regex("^about:(.*)$").Match((primaryTitleRegion as IHTMLAnchorElement).href);
                Debug.Assert(pathMatch.Success);                                             // Assert that this URL is to the format we expect
                var newPostPath = pathMatch.Groups[1].Value;                                 // Grab the path from the URL
                var homepageUri = new Uri(_blogHomepageUrl);
                var newPostUrl  = $"{homepageUri.Scheme}://{homepageUri.Host}{newPostPath}"; // Recreate the full post URL

                // Set the NextTryPostUrl flag in the region locater
                // This will indicate to the other thread that another page should be parsed
                _nextTryPostUrl = newPostUrl;
                return(null);
            }

            BlogEditingTemplate template = GenerateBlogTemplate((IHTMLDocument3)regions.Document, primaryTitleRegion, regions.TitleRegions, regions.BodyRegion);

            progress.UpdateProgress(100, 100);
            return(template);
        }
예제 #2
0
        private BlogEditingTemplate ParseBlogPostIntoTemplate(BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate));

            BlogPostRegions     regions            = regionLocator.LocateRegionsOnUIThread(progress);
            IHTMLElement        primaryTitleRegion = GetPrimaryEditableTitleElement(regions.BodyRegion, regions.Document, regions.TitleRegions);
            BlogEditingTemplate template           = GenerateBlogTemplate((IHTMLDocument3)regions.Document, primaryTitleRegion, regions.TitleRegions, regions.BodyRegion);

            progress.UpdateProgress(100, 100);
            return(template);
        }
        /// <summary>
        /// Parses a webpage into an editing template using a marshalled callback on the UI context's thread.
        /// </summary>
        /// <param name="uiContext"></param>
        /// <param name="progress"></param>
        /// <returns></returns>
        private string ParseWebpageIntoEditingTemplate_OnUIThread(Control uiContext, BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress, string postUrl)
        {
            BlogEditingTemplate blogEditingTemplate = (BlogEditingTemplate)uiContext.Invoke(
                new TemplateParser(ParseBlogPostIntoTemplate),
                new object[] {
                regionLocator,
                new ProgressTick(progress, 1, 100),
                postUrl
            });

            return(blogEditingTemplate?.Template);
        }
        /// <summary>
        /// Creates a set of BlogTemplateFiles using a specific region locator strategy.
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="regionLocatorStrategy"></param>
        /// <param name="templateStrategies"></param>
        /// <param name="templateTypes"></param>
        /// <param name="targetUrl">
        /// The URL to analyze. If a post can be located, but not the body, this is used
        /// to reiterate into the post it fetch it's content directly.
        /// </param>
        /// <returns></returns>
        private BlogEditingTemplateFile[] GetBlogTemplateFiles(IProgressHost progress, BlogPostRegionLocatorStrategy regionLocatorStrategy, BlogEditingTemplateStrategy[] templateStrategies, BlogEditingTemplateType[] templateTypes, string targetUrl)
        {
            BlogEditingTemplateFile[] blogTemplateFiles = null;
            try
            {
                regionLocatorStrategy.PrepareRegions(new ProgressTick(progress, 25, 100));

                ArrayList    templateFiles = new ArrayList();
                ProgressTick tick          = new ProgressTick(progress, 50, 100);
                for (int i = 0; i < templateTypes.Length; i++)
                {
                    ProgressTick parseTick = new ProgressTick(tick, 1, templateTypes.Length);
                    try
                    {
                        CheckCancelRequested(parseTick);
                        templateStrategy = templateStrategies[i];

                        // Clear _nextTryPostUrl flag
                        _nextTryPostUrl = null;

                        // Parse the blog post HTML into an editing template.
                        // Note: we can't use MarkupServices to parse the document from a non-UI thread,
                        // so we have to execute the parsing portion of the template download operation on the UI thread.
                        string editingTemplate = ParseWebpageIntoEditingTemplate_OnUIThread(_parentControl, regionLocatorStrategy, new ProgressTick(parseTick, 1, 5), targetUrl);

                        // If there's no editing template, there should be a URL to try next
                        Debug.Assert(editingTemplate != null || (editingTemplate == null && _nextTryPostUrl != null));

                        // If the homepage has just been analysed and the _nextTryPostUrl flag is set
                        if (targetUrl == _blogHomepageUrl && _nextTryPostUrl != null && regionLocatorStrategy.CanRefetchPage)
                        {
                            // Try fetching the URL that has been specified, and reparse
                            progress.UpdateProgress(Res.Get(StringId.ProgressDownloadingWeblogEditingStyleDeep));
                            // Fetch the post page
                            regionLocatorStrategy.FetchTemporaryPostPage(SilentProgressHost.Instance, _nextTryPostUrl);
                            // Parse out the template
                            editingTemplate = ParseWebpageIntoEditingTemplate_OnUIThread(_parentControl, regionLocatorStrategy, new ProgressTick(parseTick, 1, 5), _nextTryPostUrl);
                        }

                        // check for cancel
                        CheckCancelRequested(parseTick);

                        string baseUrl = HTMLDocumentHelper.GetBaseUrl(editingTemplate, _blogHomepageUrl);

                        // Download the template stylesheets and embedded resources (this lets the editing template load faster..and works offline!)
                        string templateFile = DownloadTemplateFiles(editingTemplate, baseUrl, new ProgressTick(parseTick, 4, 5));
                        templateFiles.Add(new BlogEditingTemplateFile(templateTypes[i], templateFile));
                    }
                    catch (BlogClientAbortGettingTemplateException)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.CurrentCulture, "Failed to download template {0}.  Aborting getting further templates", templateTypes[i].ToString()));
                        throw;
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.CurrentCulture, "Failed to download template {0}: {1}", templateTypes[i].ToString(), e.ToString()));
                    }
                }
                if (templateFiles.Count > 0)
                {
                    blogTemplateFiles = (BlogEditingTemplateFile[])templateFiles.ToArray(typeof(BlogEditingTemplateFile));
                }
            }
            finally
            {
                regionLocatorStrategy.CleanupRegions(new ProgressTick(progress, 25, 100));
            }
            return(blogTemplateFiles);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="targetTemplateTypes"></param>
        /// <param name="templateStrategies">equivalent strategies for manipulating the blog homepage DOM into an editing template type</param>
        /// <returns></returns>
        private BlogEditingTemplateFile[] DetectTemplates(IProgressHost progress, BlogEditingTemplateType[] targetTemplateTypes, BlogEditingTemplateStrategy[] templateStrategies)
        {
            RecentPostRegionLocatorStrategy recentPostLocatorStrategy =
                new RecentPostRegionLocatorStrategy(_blogClient, _blogAccount, _credentials, _blogHomepageUrl,
                                                    new PageDownloader(RequestPageDownload));

            TemporaryPostRegionLocatorStrategy tempPostLocatorStrategy =
                new TemporaryPostRegionLocatorStrategy(_blogClient, _blogAccount, _credentials, _blogHomepageUrl,
                                                       new PageDownloader(RequestPageDownload), new BlogPostRegionLocatorBooleanCallback(recentPostLocatorStrategy.HasBlogPosts));

            //setup the strategies for locating the title/body regions in the blog homepage.
            BlogPostRegionLocatorStrategy[] regionLocatorStrategies = new BlogPostRegionLocatorStrategy[]
            {
                recentPostLocatorStrategy,
                tempPostLocatorStrategy
            };

            // template files to return
            BlogEditingTemplateFile[] blogTemplateFiles = null;

            // try each strategy as necessary
            for (int i = 0; i < regionLocatorStrategies.Length && blogTemplateFiles == null; i++)
            {
                CheckCancelRequested(progress);

                //reset the progress for each iteration
                BlogPostRegionLocatorStrategy regionLocatorStrategy = regionLocatorStrategies[i];
                try
                {
                    blogTemplateFiles = GetBlogTemplateFiles(progress, regionLocatorStrategy, templateStrategies, targetTemplateTypes, _blogHomepageUrl);
                    progress.UpdateProgress(100, 100);

                    //if any exception occurred along the way, clear them since one of the template strategies
                    //was successful.
                    _exception = null;
                }
                catch (OperationCancelledException)
                {
                    // cancel just means our template will be String.Empty
                    _exception = null;
                }
                catch (BlogClientOperationCancelledException e)
                {
                    // cancel just means our template will be String.Empty
                    // (setting this exception here means that at least the user
                    // will be notified that they won't be able to edit with style)
                    _exception = e;
                }
                catch (BlogClientAbortGettingTemplateException e)
                {
                    _exception = e;
                    //Do not proceed with the other strategies if getting the template was aborted.
                    break;
                }
                catch (WebException e)
                {
                    _exception = e;
                    Trace.WriteLine("Error occurred while downloading weblog style: " + e.ToString());
                    if (e.Response != null)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.InvariantCulture, "Blogpost homepage request failed: {0}", _blogHomepageUrl));
                        //Debug.WriteLine(HttpRequestHelper.DumpResponse((HttpWebResponse)e.Response));
                    }
                }
                catch (Exception e)
                {
                    _exception = e;
                    Trace.WriteLine("Error occurred while downloading weblog style: " + e.ToString());
                }
            }

            // return the detected templates
            return(blogTemplateFiles);
        }
예제 #6
0
        /// <summary>
        /// Creates a set of BlogTemplateFiles using a specific region locator strategy.
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="regionLocatorStrategy"></param>
        /// <param name="templateStrategies"></param>
        /// <param name="templateTypes"></param>
        /// <returns></returns>
        private BlogEditingTemplateFile[] GetBlogTemplateFiles(IProgressHost progress, BlogPostRegionLocatorStrategy regionLocatorStrategy, BlogEditingTemplateStrategy[] templateStrategies, BlogEditingTemplateType[] templateTypes)
        {
            BlogEditingTemplateFile[] blogTemplateFiles = null;
            try
            {
                regionLocatorStrategy.PrepareRegions(new ProgressTick(progress, 25, 100));

                ArrayList    templateFiles = new ArrayList();
                ProgressTick tick          = new ProgressTick(progress, 50, 100);
                for (int i = 0; i < templateTypes.Length; i++)
                {
                    ProgressTick parseTick = new ProgressTick(tick, 1, templateTypes.Length);
                    try
                    {
                        CheckCancelRequested(parseTick);
                        templateStrategy = templateStrategies[i];

                        // Parse the blog post HTML into an editing template.
                        // Note: we can't use MarkupServices to parse the document from a non-UI thread,
                        // so we have to execute the parsing portion of the template download operation on the UI thread.
                        string editingTemplate = ParseWebpageIntoEditingTemplate_OnUIThread(_parentControl, regionLocatorStrategy, new ProgressTick(parseTick, 1, 5));

                        // check for cancel
                        CheckCancelRequested(parseTick);

                        string baseUrl = HTMLDocumentHelper.GetBaseUrl(editingTemplate, _blogHomepageUrl);

                        // Download the template stylesheets and embedded resources (this lets the editing template load faster..and works offline!)
                        string templateFile = DownloadTemplateFiles(editingTemplate, baseUrl, new ProgressTick(parseTick, 4, 5));
                        templateFiles.Add(new BlogEditingTemplateFile(templateTypes[i], templateFile));
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.CurrentCulture, "Failed to download template {0}: {1}", templateTypes[i].ToString(), e.ToString()));
                    }
                }
                if (templateFiles.Count > 0)
                {
                    blogTemplateFiles = (BlogEditingTemplateFile[])templateFiles.ToArray(typeof(BlogEditingTemplateFile));
                }
            }
            finally
            {
                regionLocatorStrategy.CleanupRegions(new ProgressTick(progress, 25, 100));
            }
            return(blogTemplateFiles);
        }
        private BlogEditingTemplate ParseBlogPostIntoTemplate(BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate));

            BlogPostRegions regions = regionLocator.LocateRegionsOnUIThread(progress);
            IHTMLElement primaryTitleRegion = GetPrimaryEditableTitleElement(regions.BodyRegion, regions.Document, regions.TitleRegions);
            BlogEditingTemplate template = GenerateBlogTemplate((IHTMLDocument3)regions.Document, primaryTitleRegion, regions.TitleRegions, regions.BodyRegion);

            progress.UpdateProgress(100, 100);
            return template;
        }
 /// <summary>
 /// Parses a webpage into an editing template using a marshalled callback on the UI context's thread.
 /// </summary>
 /// <param name="uiContext"></param>
 /// <param name="progress"></param>
 /// <returns></returns>
 private string ParseWebpageIntoEditingTemplate_OnUIThread(Control uiContext, BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress)
 {
     BlogEditingTemplate blogEditingTemplate = (BlogEditingTemplate)uiContext.Invoke(new TemplateParser(ParseBlogPostIntoTemplate), new object[] { regionLocator, new ProgressTick(progress, 1, 100) });
     return blogEditingTemplate.Template;
 }
        /// <summary>
        /// Creates a set of BlogTemplateFiles using a specific region locator strategy.
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="regionLocatorStrategy"></param>
        /// <param name="templateStrategies"></param>
        /// <param name="templateTypes"></param>
        /// <returns></returns>
        private BlogEditingTemplateFile[] GetBlogTemplateFiles(IProgressHost progress, BlogPostRegionLocatorStrategy regionLocatorStrategy, BlogEditingTemplateStrategy[] templateStrategies, BlogEditingTemplateType[] templateTypes)
        {
            BlogEditingTemplateFile[] blogTemplateFiles = null;
            try
            {
                regionLocatorStrategy.PrepareRegions(new ProgressTick(progress, 25, 100));

                ArrayList templateFiles = new ArrayList();
                ProgressTick tick = new ProgressTick(progress, 50, 100);
                for (int i = 0; i < templateTypes.Length; i++)
                {
                    ProgressTick parseTick = new ProgressTick(tick, 1, templateTypes.Length);
                    try
                    {
                        CheckCancelRequested(parseTick);
                        templateStrategy = templateStrategies[i];

                        // Parse the blog post HTML into an editing template.
                        // Note: we can't use MarkupServices to parse the document from a non-UI thread,
                        // so we have to execute the parsing portion of the template download operation on the UI thread.
                        string editingTemplate = ParseWebpageIntoEditingTemplate_OnUIThread(_parentControl, regionLocatorStrategy, new ProgressTick(parseTick, 1, 5));

                        // check for cancel
                        CheckCancelRequested(parseTick);

                        string baseUrl = HTMLDocumentHelper.GetBaseUrl(editingTemplate, _blogHomepageUrl);

                        // Download the template stylesheets and embedded resources (this lets the editing template load faster..and works offline!)
                        string templateFile = DownloadTemplateFiles(editingTemplate, baseUrl, new ProgressTick(parseTick, 4, 5));
                        templateFiles.Add(new BlogEditingTemplateFile(templateTypes[i], templateFile));

                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.CurrentCulture, "Failed to download template {0}: {1}", templateTypes[i].ToString(), e.ToString()));
                    }
                }
                if (templateFiles.Count > 0)
                    blogTemplateFiles = (BlogEditingTemplateFile[])templateFiles.ToArray(typeof(BlogEditingTemplateFile));
            }
            finally
            {
                regionLocatorStrategy.CleanupRegions(new ProgressTick(progress, 25, 100));
            }
            return blogTemplateFiles;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="targetTemplateTypes"></param>
        /// <param name="templateStrategies">equivalent strategies for manipulating the blog homepage DOM into an editing template type</param>
        /// <returns></returns>
        private BlogEditingTemplateFile[] DetectTemplates(IProgressHost progress, BlogEditingTemplateType[] targetTemplateTypes, BlogEditingTemplateStrategy[] templateStrategies)
        {
            RecentPostRegionLocatorStrategy recentPostLocatorStrategy =
                new RecentPostRegionLocatorStrategy(_blogClient, _blogAccount, _credentials, _blogHomepageUrl,
                                                    new PageDownloader(RequestPageDownload));

            TemporaryPostRegionLocatorStrategy tempPostLocatorStrategy =
                new TemporaryPostRegionLocatorStrategy(_blogClient, _blogAccount, _credentials, _blogHomepageUrl,
                                                       new PageDownloader(RequestPageDownload), new BlogPostRegionLocatorBooleanCallback(recentPostLocatorStrategy.HasBlogPosts));

            //setup the strategies for locating the title/body regions in the blog homepage.
            BlogPostRegionLocatorStrategy[] regionLocatorStrategies = new BlogPostRegionLocatorStrategy[]
                {
                    recentPostLocatorStrategy,
                    tempPostLocatorStrategy
                };

            // template files to return
            BlogEditingTemplateFile[] blogTemplateFiles = null;

            // try each strategy as necessary
            for (int i = 0; i < regionLocatorStrategies.Length && blogTemplateFiles == null; i++)
            {
                CheckCancelRequested(progress);

                //reset the progress for each iteration
                BlogPostRegionLocatorStrategy regionLocatorStrategy = regionLocatorStrategies[i];
                try
                {
                    blogTemplateFiles = GetBlogTemplateFiles(progress, regionLocatorStrategy, templateStrategies, targetTemplateTypes);
                    progress.UpdateProgress(100, 100);

                    //if any exception occured along the way, clear them since one of the template strategies
                    //was successful.
                    _exception = null;
                }
                catch (OperationCancelledException)
                {
                    // cancel just means our template will be String.Empty
                    _exception = null;
                }
                catch (BlogClientOperationCancelledException e)
                {
                    // cancel just means our template will be String.Empty
                    // (setting this exception here means that at least the user
                    // will be notified that they won't be able to edit with style)
                    _exception = e;
                }
                catch (WebException e)
                {
                    _exception = e;
                    Trace.WriteLine("Error occurred while downloading weblog style: " + e.ToString());
                    if (e.Response != null)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.InvariantCulture, "Blogpost homepage request failed: {0}", _blogHomepageUrl));
                        //Debug.WriteLine(HttpRequestHelper.DumpResponse((HttpWebResponse)e.Response));
                    }
                }
                catch (Exception e)
                {
                    _exception = e;
                    Trace.WriteLine("Error occurred while downloading weblog style: " + e.ToString());
                }

            }

            // return the detected tempaltes
            return blogTemplateFiles;
        }