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); }
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); }
/// <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; }