Esempio n. 1
0
 public void Tick()
 {
     if (_currentTicks < _ticks)
     {
         _progress.UpdateProgress(++_currentTicks, _ticks);
     }
 }
Esempio n. 2
0
        private BlogPost PostTemplate(IProgressHost progress)
        {
            progress.UpdateProgress(50, 100);
            // make a test post that we can use to do analysis
            BlogPost testPost = new BlogPost();

            testPost.IsTemporary = true;
            testPost.Title       = TEMPORARY_POST_TITLE;

            //plant a <p> around the contents so that the blog provider doesn't try to add their own
            //and so we'll know it can be safely removed later
            //Note: this fixes an issue where the editor's postBody <div> was being parented improperly by
            //a <p> element that the blog service was adding...
            string postContents = String.Format(CultureInfo.InvariantCulture, "<p>{0}</p>", TEMPORARY_POST_BODY);

            testPost.Contents = postContents;

            string      etag;
            XmlDocument remotePost;

            testPost.Id             = _blogClient.NewPost(_blogAccount.BlogId, testPost, new IgnoreNewCategoryContext(), true, out etag, out remotePost);
            testPost.ETag           = etag;
            testPost.AtomRemotePost = remotePost;
            progress.UpdateProgress(100, 100);
            return(testPost);
        }
        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 string DownloadTemplateFiles(string templateContents, string templateUrl, IProgressHost progress)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressDownloadingSupportingFiles));
            FileBasedSiteStorage files = new FileBasedSiteStorage(_blogTemplateDir);

            // convert the string to a stream
            MemoryStream templateStream = new MemoryStream();
            StreamWriter writer         = new StreamWriter(templateStream, Encoding.UTF8);

            writer.Write(templateContents);
            writer.Flush();
            templateStream.Seek(0, SeekOrigin.Begin);

            //read the stream into a lightweight HTML.  Note that we use from LightWeightHTMLDocument.FromIHTMLDocument2
            //instead of LightWeightHTMLDocument.FromStream because from stream improperly shoves a saveFrom declaration
            //above the docType (bug 289357)
            IHTMLDocument2          doc  = HTMLDocumentHelper.StreamToHTMLDoc(templateStream, templateUrl, true);
            LightWeightHTMLDocument ldoc = LightWeightHTMLDocument.FromIHTMLDocument2(doc, templateUrl, true, false);

            PageDownloadContext downloadContext = new PageDownloadContext(0);

            ApplyCredentials(downloadContext, templateUrl);
            using (PageToDownloadFactory downloadFactory = new PageToDownloadFactory(ldoc, downloadContext, _parentControl))
            {
                //calculate the dependent styles and resources
                ProgressTick tick = new ProgressTick(progress, 50, 100);
                downloadFactory.CreatePagesToDownload(tick);
                tick.UpdateProgress(100, 100);

                //download the dependent styles and resources
                tick = new ProgressTick(progress, 50, 100);
                PageAndReferenceDownloader downloader = new PageAndReferenceDownloader(downloadFactory.PagesToDownload, files);
                this.ApplyCredentials(downloader, templateUrl);
                downloader.Download(tick);
                tick.UpdateProgress(100, 100);

                //Expand out the relative paths in the downloaded HTML file with absolute paths.
                //Note: this is necessary so that template resources are not improperly resolved relative
                //      to the location of the file the editor is editing.
                string blogTemplateFile = Path.Combine(_blogTemplateDir, files.RootFile);
                string origFile         = blogTemplateFile + ".token";
                File.Move(blogTemplateFile, origFile);
                string absPath = String.Format(CultureInfo.InvariantCulture, "file:///{0}/{1}", _blogTemplateDir.Replace('\\', '/'), downloader.PathToken);
                TextHelper.ReplaceInFile(origFile, downloader.PathToken, blogTemplateFile, absPath);
                File.Delete(origFile);

                //fix up the files
                FixupDownloadedFiles(blogTemplateFile, files, downloader.PathToken);

                //complete the progress.
                progress.UpdateProgress(100, 100);

                File.WriteAllText(blogTemplateFile + ".path", absPath);
                return(blogTemplateFile);
            }
        }
Esempio n. 5
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);
        }
Esempio n. 6
0
 public void UpdateProgress(int complete, int total, string message)
 {
     ConvertTicksToParent(ref complete, ref total);
     // If they send back a bogus progress value, just ignore the values
     if (complete < 0)
     {
         ParentProgress.UpdateProgress(message);
     }
     else
     {
         ParentProgress.UpdateProgress(complete, total, message);
     }
 }
Esempio n. 7
0
 private void DeletePost(BlogPost post, IProgressHost progress)
 {
     try
     {
         progress.UpdateProgress(Res.Get(StringId.ProgressFinalizingEditingTemplateConfig));
         _blogClient.DeletePost(_blogAccount.BlogId, post.Id, true);
         progress.UpdateProgress(100, 100);
     }
     catch (Exception ex)
     {
         Trace.Fail("Unexpected exception occurred while deleting temporary post: " + ex.ToString());
         //show a message that user needs to delete their post
         DisplayMessage.Show(MessageId.TempPostDeleteFailed);
     }
 }
Esempio n. 8
0
 public void UpdateProgress(int complete, int total, string message)
 {
     if (Allowed(MessageType.UpdateCompletion) && Allowed(MessageType.UpdateMessage))
     {
         pHost.UpdateProgress(complete, total, message);
     }
     else if (Allowed(MessageType.UpdateCompletion))
     {
         pHost.UpdateProgress(complete, total);
     }
     else if (Allowed(MessageType.UpdateMessage))
     {
         pHost.UpdateProgress(message);
     }
 }
        /// <summary>
        /// Initiate a download, using the progressHost to provide progress feedback
        /// </summary>
        /// <param name="progressHost">The progressHost to provide feedback to</param>
        /// <returns>this</returns>
        public object DownloadHTMLDocument(IProgressHost progressHost)
        {
            _downloadComplete = false;

            // Call the download method on the parent STA thread
            // Then wait for it to complete (the Monitor will be pulsed upon completion)
            _parentControl.Invoke(new Download(DoDownload), new object[] { progressHost });

            lock (this)
            {
                if (_downloadComplete)
                {
                    return(this);
                }

                DateTime endDateTime = DateTime.Now.AddMilliseconds(TimeoutMs);
                while (!_downloadComplete)
                {
                    if (!Monitor.Wait(this, Math.Max(0, (int)endDateTime.Subtract(DateTime.Now).TotalMilliseconds)))
                    {
                        throw new OperationTimedOutException();
                    }
                }

                if (_downloader.Result.Exception != null)
                {
                    throw _downloader.Result.Exception;
                }

                progressHost.UpdateProgress(1, 1);
                return(this);
            }
        }
Esempio n. 10
0
        protected void UpdateProgress(IProgressHost progressHost, int percent, string message)
        {
            //if ( CancelRequested )
            //	throw new OperationCancelledException() ;

            progressHost.UpdateProgress(percent, 100, message);
        }
Esempio n. 11
0
        public override void CleanupRegions(IProgressHost progress)
        {
            if (blogHomepageContents != null)
            {
                blogHomepageContents.Close();
                blogHomepageContents = null;
            }

            progress.UpdateProgress(100, 100);
        }
Esempio n. 12
0
        public override BlogPostRegions LocateRegionsOnUIThread(IProgressHost progress)
        {
            blogHomepageContents.Seek(0, SeekOrigin.Begin);
            IHTMLDocument2 doc2 = HTMLDocumentHelper.GetHTMLDocumentFromStream(blogHomepageContents, _blogHomepageUrl);

            // Ensure that the document is fully loaded.
            // If it is not fully loaded, then viewing its current style is non-deterministic.
            DateTime startedDoingEvents = DateTime.Now;

            while (!progress.CancelRequested && !HTMLDocumentHelper.IsReady(doc2))
            {
                if (DateTime.Now.Subtract(startedDoingEvents).TotalMilliseconds > 10000)
                {
                    // Timing out here is not fatal.
                    Trace.WriteLine("Timed out while loading blog homepage for theme detection.");
                    break;
                }

                Application.DoEvents();
            }

            //The Google/Blogger dynamic templates load the pages dynmaically usig Ajax, so we dont have any template to use.
            if (IsUsingDynamicTemplate(doc2))
            {
                throw new BlogClientAbortGettingTemplateException();
            }

            IHTMLElement[] titles = FindText(_titleText, doc2.body);
            IHTMLElement[] bodies = FindText(_bodyText, doc2.body);
            if (titles.Length == 0 || bodies.Length == 0)
            {
                throw new Exception("Unable to locate blog post elements using most recent post");
            }

            if (IsSmartContent(bodies[0]))
            {
                throw new Exception("Most recent post is smart content");
            }

            BlogPostRegions regions = new BlogPostRegions();

            regions.TitleRegions = titles;

            //scrub the post body element to avoid improperly including extraneous parent elements
            regions.BodyRegion = ScrubPostBodyRegionParentElements(bodies[0]);
            regions.Document   = doc2;

            progress.UpdateProgress(100, 100);

            return(regions);
        }
Esempio n. 13
0
        private BlogPostRegions ParseBlogPostIntoTemplate(Stream stream, string postSourceUrl, IProgressHost progress)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate));

            //parse the document to create the blog template
            IHTMLDocument2 doc2 = HTMLDocumentHelper.GetHTMLDocumentFromStream(stream, postSourceUrl);
            IHTMLDocument3 doc  = (IHTMLDocument3)doc2;

            IHTMLElement[] titleElements = HTMLDocumentHelper.FindElementsContainingText(doc2, TEMPORARY_POST_TITLE_GUID);

            IHTMLElement bodyElement = HTMLDocumentHelper.FindElementContainingText(doc2, TEMPORARY_POST_BODY_GUID);

            if (bodyElement != null && bodyElement.tagName == "P")
            {
                //the body element is the <p> we planted, so replace it with a DIV since that will be the safest
                //element to have a as parent to all post content.
                IHTMLElement div = doc2.createElement("div");
                (bodyElement.parentElement as IHTMLDOMNode).replaceChild(div as IHTMLDOMNode, bodyElement as IHTMLDOMNode);
                bodyElement = div;
            }

            //locate the title element.  Note that is there are more than 1 copies of the title text detected, we use the one
            //that is anchored closest to the left or the body element.
            if (titleElements.Length > 0)
            {
                BlogPostRegions regions = new BlogPostRegions();
                regions.Document     = (IHTMLDocument)doc;
                regions.TitleRegions = titleElements;
                regions.BodyRegion   = bodyElement;

                progress.UpdateProgress(100, 100);
                return(regions);
            }
            else
            {
                throw new Exception("unable to access test post.");
            }
        }
        private string DownloadManifestTemplate(IProgressHost progress, string manifestTemplateUrl)
        {
            try
            {
                // update progress
                progress.UpdateProgress(0, 100, Res.Get(StringId.ProgressDownloadingEditingTemplate));

                // process any parameters within the url
                string templateUrl = BlogClientHelper.FormatUrl(manifestTemplateUrl, _blogHomepageUrl, _blogAccount.PostApiUrl, _blogAccount.BlogId);

                // download the url
                using (StreamReader streamReader = new StreamReader(_blogClient.SendAuthenticatedHttpRequest(templateUrl, 20000, null).GetResponseStream()))
                    return(streamReader.ReadToEnd());
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Exception occurred while attempting to download template from " + manifestTemplateUrl + " :" + ex.ToString());
                return(null);
            }
            finally
            {
                progress.UpdateProgress(100, 100);
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Fetch a blog page from the URL specified and transfer it into blogPageContents
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="url"></param>
        public override void FetchTemporaryPostPage(IProgressHost progress, string url)
        {
            blogPageContents = new MemoryStream();

            // Download the webpage that is contains the temporary blog post
            // WARNING, DownloadBlogPage uses an MSHTML Document on a non-UI thread...which is a no-no!
            //   its been this way through several betas without problem, so we'll keep it that way for now, but
            //   it needs to be fixed eventually.
            Stream postHtmlContents = DownloadBlogPage(url, progress);

            CheckCancelRequested(progress);

            using (postHtmlContents)
            {
                StreamHelper.Transfer(postHtmlContents, blogPageContents);
            }
            progress.UpdateProgress(100, 100);
        }
Esempio n. 16
0
        /// <summary>
        /// The moniker calls this method repeatedly to indicate the current progress of the bind
        /// operation, typically at reasonable intervals during a lengthy operation.
        ///
        /// The client can use the progress notification to provide progress information to the
        /// user from the ulProgress, ulProgressMax, and szStatusText parameters, or to make
        /// programmatic decisions based on the ulStatusCode parameter.
        /// </summary>
        int IBindStatusCallback.OnProgress(uint ulProgress, uint ulProgressMax, BINDSTATUS ulStatusCode, string szStatusText)
        {
            //Debug.WriteLine( String.Format( "IBindStatusCallback.OnProgress {0}: {1} ({2}/{3})", ulStatusCode, szStatusText != null ? szStatusText : String.Empty, ulProgress, ulProgressMax ) ) ;

            // check for timeout
            if (TimeoutMs != NO_TIMEOUT)
            {
                if (DateTime.Now > _timeoutTime)
                {
                    _timedOut = true;
                    return(HRESULT.E_ABORT);
                }
            }

            if (ulStatusCode == BINDSTATUS.ENDDOWNLOADDATA)
            {
                // We've completed the download of the file
                return(HRESULT.S_OK);
            }
            else if (ulStatusCode == BINDSTATUS.MIMETYPEAVAILABLE)
            {
                // record the mime type
                m_contentType = szStatusText;
            }
            else if (ulStatusCode == BINDSTATUS.REDIRECTING)
            {
                _finalUrl = szStatusText;
            }
            else if ((ProgressHost != null && ProgressHost.CancelRequested) || ThreadHelper.Interrupted)
            {
                // Cancel this operation
                return(HRESULT.E_ABORT);
            }
            else
            {
                if (ProgressHost != null)
                {
                    // UrlDownloadToFile can sometimes return progress that exceeds 100%- stop this from happening
                    ProgressHost.UpdateProgress((int)(Math.Min(ulProgressMax, ulProgress)), (int)ulProgressMax, String.Format(CultureInfo.CurrentCulture, Res.Get(StringId.ProgressDownloading), Url));
                }
            }

            return(HRESULT.S_OK);
        }
Esempio n. 17
0
        private void PrepareRegionsUsingTemporaryPost(IProgressHost progress)
        {
            // Publish a temporary post so that we can examine HTML that will surround posts created with the editor
            temporaryPost = PostTemplate(new ProgressTick(progress, 25, 100));
            CheckCancelRequested(progress);

            blogHomepageContents = new MemoryStream();

            // Download the webpage that is contains the temporary blog post
            // WARNING, DownloadBlogPage uses an MSHTML Document on a non-UI thread...which is a no-no!
            //   its been this way through several betas without problem, so we'll keep it that way for now, but
            //   it needs to be fixed eventually.
            Stream postHtmlContents = DownloadBlogPage(_blogHomepageUrl, progress);

            CheckCancelRequested(progress);

            using (postHtmlContents)
            {
                StreamHelper.Transfer(postHtmlContents, blogHomepageContents);
            }
            progress.UpdateProgress(100, 100);
        }
        public object DetectSettings(IProgressHost progressHost)
        {
            using (_silentMode ? new BlogClientUIContextSilentMode() : null)
            {
                if (IncludeButtons || IncludeOptionOverrides || IncludeImages)
                {
                    using (new ProgressContext(progressHost, 40, Res.Get(StringId.ProgressDetectingWeblogSettings)))
                    {
                        // attempt to download editing manifest
                        WriterEditingManifest editingManifest = SafeDownloadEditingManifest();

                        if (editingManifest != null)
                        {
                            // always update the download info
                            if (editingManifest.DownloadInfo != null)
                                _context.ManifestDownloadInfo = editingManifest.DownloadInfo;

                            // images
                            if (IncludeImages)
                            {
                                // image if provided
                                if (editingManifest.Image != null)
                                    _context.Image = editingManifest.Image;

                                // watermark if provided
                                if (editingManifest.Watermark != null)
                                    _context.WatermarkImage = editingManifest.Watermark;
                            }

                            // buttons if provided
                            if (IncludeButtons && (editingManifest.ButtonDescriptions != null))
                                _context.ButtonDescriptions = editingManifest.ButtonDescriptions;

                            // option overrides if provided
                            if (IncludeOptionOverrides)
                            {
                                if (editingManifest.ClientType != null)
                                    _context.ClientType = editingManifest.ClientType;

                                if (editingManifest.OptionOverrides != null)
                                    _context.OptionOverrides = editingManifest.OptionOverrides;
                            }
                        }
                    }
                }

                using (new ProgressContext(progressHost, 40, Res.Get(StringId.ProgressDetectingWeblogCharSet)))
                {
                    if (IncludeOptionOverrides && IncludeHomePageSettings)
                    {
                        DetectHomePageSettings();
                    }
                }

                IBlogClient blogClient = CreateBlogClient();
                if (IncludeInsecureOperations || blogClient.IsSecure)
                {
                    if (blogClient is ISelfConfiguringClient)
                    {
                        // This must happen before categories detection but after manifest!!
                        ((ISelfConfiguringClient)blogClient).DetectSettings(_context, this);
                    }

                    // detect categories
                    if (IncludeCategories)
                    {
                        using (
                            new ProgressContext(progressHost, 20, Res.Get(StringId.ProgressDetectingWeblogCategories)))
                        {
                            BlogPostCategory[] categories = SafeDownloadCategories();
                            if (categories != null)
                                _context.Categories = categories;

                            BlogPostKeyword[] keywords = SafeDownloadKeywords();
                            if (keywords != null)
                                _context.Keywords = keywords;
                        }
                    }

                    // detect favicon (only if requested AND we don't have a PNG already
                    // for the small image size)
                    if (IncludeFavIcon)
                    {
                        using (new ProgressContext(progressHost, 10, Res.Get(StringId.ProgressDetectingWeblogIcon)))
                        {
                            byte[] favIcon = SafeDownloadFavIcon();
                            if (favIcon != null)
                                _context.FavIcon = favIcon;
                        }
                    }

                    if (IncludeImageEndpoints)
                    {
                        Debug.WriteLine("Detecting image endpoints");
                        ITemporaryBlogSettingsDetectionContext tempContext =
                            _context as ITemporaryBlogSettingsDetectionContext;
                        Debug.Assert(tempContext != null,
                                     "IncludeImageEndpoints=true but non-temporary context (type " +
                                     _context.GetType().Name + ") was used");
                        if (tempContext != null)
                        {
                            tempContext.AvailableImageEndpoints = null;
                            try
                            {
                                BlogInfo[] imageEndpoints = blogClient.GetImageEndpoints();
                                tempContext.AvailableImageEndpoints = imageEndpoints;
                                Debug.WriteLine(imageEndpoints.Length + " image endpoints detected");
                            }
                            catch (NotImplementedException)
                            {
                                Debug.WriteLine("Image endpoints not implemented");
                            }
                            catch (Exception e)
                            {
                                Trace.Fail("Exception detecting image endpoints: " + e.ToString());
                            }
                        }
                    }
                }
                // completed
                progressHost.UpdateProgress(100, 100, Res.Get(StringId.ProgressCompletedSettingsDetection));
            }

            return this;
        }
        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;
        }
        private string DownloadTemplateFiles(string templateContents, string templateUrl, IProgressHost progress)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressDownloadingSupportingFiles));
            FileBasedSiteStorage files = new FileBasedSiteStorage(_blogTemplateDir);

            // convert the string to a stream
            MemoryStream templateStream = new MemoryStream();
            StreamWriter writer = new StreamWriter(templateStream, Encoding.UTF8);
            writer.Write(templateContents);
            writer.Flush();
            templateStream.Seek(0, SeekOrigin.Begin);

            //read the stream into a lightweight HTML.  Note that we use from LightWeightHTMLDocument.FromIHTMLDocument2
            //instead of LightWeightHTMLDocument.FromStream because from stream improperly shoves a saveFrom declaration
            //above the docType (bug 289357)
            IHTMLDocument2 doc = HTMLDocumentHelper.StreamToHTMLDoc(templateStream, templateUrl, true);
            LightWeightHTMLDocument ldoc = LightWeightHTMLDocument.FromIHTMLDocument2(doc, templateUrl, true, false);

            PageDownloadContext downloadContext = new PageDownloadContext(0);
            ApplyCredentials(downloadContext, templateUrl);
            using (PageToDownloadFactory downloadFactory = new PageToDownloadFactory(ldoc, downloadContext, _parentControl))
            {
                //calculate the dependent styles and resources
                ProgressTick tick = new ProgressTick(progress, 50, 100);
                downloadFactory.CreatePagesToDownload(tick);
                tick.UpdateProgress(100, 100);

                //download the dependent styles and resources
                tick = new ProgressTick(progress, 50, 100);
                PageAndReferenceDownloader downloader = new PageAndReferenceDownloader(downloadFactory.PagesToDownload, files);
                this.ApplyCredentials(downloader, templateUrl);
                downloader.Download(tick);
                tick.UpdateProgress(100, 100);

                //Expand out the relative paths in the downloaded HTML file with absolute paths.
                //Note: this is necessary so that template resources are not improperly resolved relative
                //      to the location of the file the editor is editing.
                string blogTemplateFile = Path.Combine(_blogTemplateDir, files.RootFile);
                string origFile = blogTemplateFile + ".token";
                File.Move(blogTemplateFile, origFile);
                string absPath = String.Format(CultureInfo.InvariantCulture, "file:///{0}/{1}", _blogTemplateDir.Replace('\\', '/'), downloader.PathToken);
                TextHelper.ReplaceInFile(origFile, downloader.PathToken, blogTemplateFile, absPath);
                File.Delete(origFile);

                //fix up the files
                FixupDownloadedFiles(blogTemplateFile, files, downloader.PathToken);

                //complete the progress.
                progress.UpdateProgress(100, 100);

                File.WriteAllText(blogTemplateFile + ".path", absPath);
                return blogTemplateFile;
            }
        }
        private BlogPost PostTemplate(IProgressHost progress)
        {
            progress.UpdateProgress(50, 100);
            // make a test post that we can use to do analysis
            BlogPost testPost = new BlogPost();
            testPost.IsTemporary = true;
            testPost.Title = TEMPORARY_POST_TITLE;

            //plant a <p> around the contents so that the blog provider doesn't try to add their own
            //and so we'll know it can be safely removed later
            //Note: this fixes an issue where the editor's postBody <div> was being parented improperly by
            //a <p> element that the blog service was adding...
            string postContents = String.Format(CultureInfo.InvariantCulture, "<p>{0}</p>", TEMPORARY_POST_BODY);
            testPost.Contents = postContents;

            string etag;
            XmlDocument remotePost;
            testPost.Id = _blogClient.NewPost(_blogAccount.BlogId, testPost, new IgnoreNewCategoryContext(), true, out etag, out remotePost);
            testPost.ETag = etag;
            testPost.AtomRemotePost = remotePost;
            progress.UpdateProgress(100, 100);
            return testPost;
        }
 private void DeletePost(BlogPost post, IProgressHost progress)
 {
     try
     {
         progress.UpdateProgress(Res.Get(StringId.ProgressFinalizingEditingTemplateConfig));
         _blogClient.DeletePost(_blogAccount.BlogId, post.Id, true);
         progress.UpdateProgress(100, 100);
     }
     catch (Exception ex)
     {
         Trace.Fail("Unexpected exception occurred while deleting temporary post: " + ex.ToString());
         //show a message that user needs to delete their post
         DisplayMessage.Show(MessageId.TempPostDeleteFailed);
     }
 }
        /// <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;
        }
        private BlogPostRegions ParseBlogPostIntoTemplate(Stream stream, string postSourceUrl, IProgressHost progress)
        {
            progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate));

            //parse the document to create the blog template
            IHTMLDocument2 doc2 = HTMLDocumentHelper.GetHTMLDocumentFromStream(stream, postSourceUrl);
            IHTMLDocument3 doc = (IHTMLDocument3)doc2;
            IHTMLElement[] titleElements = HTMLDocumentHelper.FindElementsContainingText(doc2, TEMPORARY_POST_TITLE_GUID);

            IHTMLElement bodyElement = HTMLDocumentHelper.FindElementContainingText(doc2, TEMPORARY_POST_BODY_GUID);
            if (bodyElement != null && bodyElement.tagName == "P")
            {
                //the body element is the <p> we planted, so replace it with a DIV since that will be the safest
                //element to have a as parent to all post content.
                IHTMLElement div = doc2.createElement("div");
                (bodyElement.parentElement as IHTMLDOMNode).replaceChild(div as IHTMLDOMNode, bodyElement as IHTMLDOMNode);
                bodyElement = div;
            }

            //locate the title element.  Note that is there are more than 1 copies of the title text detected, we use the one
            //that is anchored closest to the left or the body element.
            if (titleElements.Length > 0)
            {
                BlogPostRegions regions = new BlogPostRegions();
                regions.Document = (IHTMLDocument)doc;
                regions.TitleRegions = titleElements;
                regions.BodyRegion = bodyElement;

                progress.UpdateProgress(100, 100);
                return regions;
            }
            else
            {
                throw new Exception("unable to access test post.");
            }
        }
        private BlogEditingTemplateFiles SafeGetTemplates(IProgressHost progress)
        {
            WriterEditingManifest editingManifest = null;
            BlogEditingTemplateFiles templateFiles = new BlogEditingTemplateFiles();
            try
            {
                // if we have a manifest url then try to get our manifest
                if (_manifestDownloadInfo != null)
                {
                    // try to get the editing manifest
                    string manifestUrl = _manifestDownloadInfo.SourceUrl;
                    editingManifest = WriterEditingManifest.FromUrl(
                        new Uri(manifestUrl),
                        _blogClient,
                        _credentials,
                        true);

                    // progress
                    CheckCancelRequested(progress);
                    progress.UpdateProgress(20, 100);
                }

                // if we have no editing manifest then probe (if allowed)
                if ((editingManifest == null) && _probeForManifest)
                {
                    editingManifest = WriterEditingManifest.FromHomepage(
                        new LazyHomepageDownloader(_blogHomepageUrl, new HttpRequestHandler(_blogClient.SendAuthenticatedHttpRequest)),
                        new Uri(_blogHomepageUrl),
                        _blogClient,
                        _credentials);
                }

                // progress
                CheckCancelRequested(progress);
                progress.UpdateProgress(40, 100);

                // if we got one then return templates from it as-appropriate
                if (editingManifest != null)
                {
                    if (editingManifest.WebLayoutUrl != null)
                    {
                        string webLayoutTemplate = DownloadManifestTemplate(new ProgressTick(progress, 10, 100), editingManifest.WebLayoutUrl);
                        if (BlogEditingTemplate.ValidateTemplate(webLayoutTemplate))
                        {
                            // download supporting files
                            string templateFile = DownloadTemplateFiles(webLayoutTemplate, _blogHomepageUrl, new ProgressTick(progress, 20, 100));

                            // return the template
                            templateFiles.FramedTemplate = new BlogEditingTemplateFile(BlogEditingTemplateType.Framed, templateFile);
                        }
                        else
                        {
                            Trace.WriteLine("Invalid webLayoutTemplate specified in manifest");
                        }
                    }

                    if (editingManifest.WebPreviewUrl != null)
                    {
                        string webPreviewTemplate = DownloadManifestTemplate(new ProgressTick(progress, 10, 100), editingManifest.WebPreviewUrl);
                        if (BlogEditingTemplate.ValidateTemplate(webPreviewTemplate))
                        {
                            // download supporting files
                            string templateFile = DownloadTemplateFiles(webPreviewTemplate, _blogHomepageUrl, new ProgressTick(progress, 20, 100));

                            // return the template
                            templateFiles.WebPageTemplate = new BlogEditingTemplateFile(BlogEditingTemplateType.Webpage, templateFile);
                        }
                        else
                        {
                            Trace.WriteLine("Invalid webPreviewTemplate specified in manifest");
                        }
                    }
                }
            }
            catch
            {
            }
            finally
            {
                progress.UpdateProgress(100, 100);
            }

            return templateFiles;
        }
        /// <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);
        }
        public object DetectTemplate(IProgressHost progress)
        {
            // if our context has not been set then just return without doing anything
            // (supports this being an optional step at the end of a chain of
            // other progress operations)
            if (_contextSet == false)
            {
                return(this);
            }

            using (BlogClientUIContextScope uiContextScope = new BlogClientUIContextScope(_uiContext))
            {
                // initial progress
                progress.UpdateProgress(Res.Get(StringId.ProgressDetectingWeblogEditingStyle));

                // build list of detected templates
                ArrayList blogTemplateFiles = new ArrayList();

                // build list of template types that we need to auto-detect
                ArrayList detectionTargetTypes      = new ArrayList();
                ArrayList detectionTargetStrategies = new ArrayList();

                // try explicit detection of templates
                BlogEditingTemplateFiles templateFiles = SafeGetTemplates(new ProgressTick(progress, 50, 100));

                // see if we got the FramedTemplate
                if (templateFiles.FramedTemplate != null)
                {
                    blogTemplateFiles.Add(templateFiles.FramedTemplate);
                }
                else
                {
                    detectionTargetTypes.Add(BlogEditingTemplateType.Framed);
                    detectionTargetStrategies.Add(BlogEditingTemplateStrategies.GetTemplateStrategy(BlogEditingTemplateStrategies.StrategyType.NoSiblings));
                }

                // see if we got the WebPageTemplate
                if (templateFiles.WebPageTemplate != null)
                {
                    blogTemplateFiles.Add(templateFiles.WebPageTemplate);
                }
                else
                {
                    detectionTargetTypes.Add(BlogEditingTemplateType.Webpage);
                    detectionTargetStrategies.Add(BlogEditingTemplateStrategies.GetTemplateStrategy(BlogEditingTemplateStrategies.StrategyType.Site));
                }

                // perform detection if we have detection targets
                if (detectionTargetTypes.Count > 0)
                {
                    BlogEditingTemplateFile[] detectedBlogTemplateFiles = DetectTemplates(new ProgressTick(progress, 50, 100),
                                                                                          detectionTargetTypes.ToArray(typeof(BlogEditingTemplateType)) as BlogEditingTemplateType[],
                                                                                          detectionTargetStrategies.ToArray(typeof(BlogEditingTemplateStrategy)) as BlogEditingTemplateStrategy[]);
                    if (detectedBlogTemplateFiles != null)
                    {
                        blogTemplateFiles.AddRange(detectedBlogTemplateFiles);
                    }
                }

                // updates member if we succeeded
                if (blogTemplateFiles.Count > 0)
                {
                    // capture template files
                    _blogTemplateFiles = blogTemplateFiles.ToArray(typeof(BlogEditingTemplateFile)) as BlogEditingTemplateFile[];

                    // if we got at least one template by some method then clear any exception
                    // that occurs so we can at least update that template
                    _exception = null;
                }

                foreach (BlogEditingTemplateFile file in blogTemplateFiles)
                {
                    if (file.TemplateType == BlogEditingTemplateType.Webpage)
                    {
                        _postBodyBackgroundColor = BackgroundColorDetector.DetectColor(UrlHelper.SafeToAbsoluteUri(new Uri(file.TemplateFile)), _postBodyBackgroundColor);
                    }
                }

                // return
                return(this);
            }
        }
Esempio n. 28
0
 public ProgressContext(IProgressHost progressHost, int complete, string message)
 {
     _progressHost = progressHost;
     _progressHost.UpdateProgress(complete, 100, message);
 }
        public override void CleanupRegions(IProgressHost progress)
        {
            if (blogHomepageContents != null)
            {
                blogHomepageContents.Close();
                blogHomepageContents = null;
            }

            progress.UpdateProgress(100, 100);
        }
        public object DetectTemplate(IProgressHost progress)
        {
            // if our context has not been set then just return without doing anything
            // (supports this being an optional step at the end of a chain of
            // other progress operations)
            if (_contextSet == false)
                return this;

            using (BlogClientUIContextScope uiContextScope = new BlogClientUIContextScope(_uiContext))
            {
                // initial progress
                progress.UpdateProgress(Res.Get(StringId.ProgressDetectingWeblogEditingStyle));

                // build list of detected templates
                ArrayList blogTemplateFiles = new ArrayList();

                // build list of template types that we need to auto-detect
                ArrayList detectionTargetTypes = new ArrayList();
                ArrayList detectionTargetStrategies = new ArrayList();

                // try explicit detection of templates
                BlogEditingTemplateFiles templateFiles = SafeGetTemplates(new ProgressTick(progress, 50, 100));

                // see if we got the FramedTempalte
                if (templateFiles.FramedTemplate != null)
                    blogTemplateFiles.Add(templateFiles.FramedTemplate);
                else
                {
                    detectionTargetTypes.Add(BlogEditingTemplateType.Framed);
                    detectionTargetStrategies.Add(BlogEditingTemplateStrategies.GetTemplateStrategy(BlogEditingTemplateStrategies.StrategyType.NoSiblings));
                }

                // see if we got the WebPageTemplate
                if (templateFiles.WebPageTemplate != null)
                    blogTemplateFiles.Add(templateFiles.WebPageTemplate);
                else
                {
                    detectionTargetTypes.Add(BlogEditingTemplateType.Webpage);
                    detectionTargetStrategies.Add(BlogEditingTemplateStrategies.GetTemplateStrategy(BlogEditingTemplateStrategies.StrategyType.Site));
                }

                // perform detection if we have detection targets
                if (detectionTargetTypes.Count > 0)
                {
                    BlogEditingTemplateFile[] detectedBlogTemplateFiles = DetectTemplates(new ProgressTick(progress, 50, 100),
                        detectionTargetTypes.ToArray(typeof(BlogEditingTemplateType)) as BlogEditingTemplateType[],
                        detectionTargetStrategies.ToArray(typeof(BlogEditingTemplateStrategy)) as BlogEditingTemplateStrategy[]);
                    if (detectedBlogTemplateFiles != null)
                        blogTemplateFiles.AddRange(detectedBlogTemplateFiles);
                }

                // updates member if we succeeded
                if (blogTemplateFiles.Count > 0)
                {
                    // capture template files
                    _blogTemplateFiles = blogTemplateFiles.ToArray(typeof(BlogEditingTemplateFile)) as BlogEditingTemplateFile[];

                    // if we got at least one template by some method then clear any exception
                    // that occurs so we can at least update that tempalte
                    _exception = null;
                }

                foreach (BlogEditingTemplateFile file in blogTemplateFiles)
                {
                    if (file.TemplateType == BlogEditingTemplateType.Webpage)
                    {
                        _postBodyBackgroundColor = BackgroundColorDetector.DetectColor(UrlHelper.SafeToAbsoluteUri(new Uri(file.TemplateFile)), _postBodyBackgroundColor);
                    }
                }

                // return
                return this;
            }
        }
        /// <summary>
        /// Actually downloads the pages
        /// </summary>
        private PageToDownload[] DownloadPages(IProgressHost progress, string url, LightWeightHTMLDocument lightWeightDocument, PageToDownload parentPageToDownload)
        {
            // Check for cancel
            if (progress.CancelRequested)
                throw new OperationCancelledException();

            _currentDepth++;
            ArrayList downloadedPages = new ArrayList();

            // Set up our progress
            int thisPageTicks = FIRSTPAGETICKS;
            if (_context.Depth == _currentDepth)
                thisPageTicks = TOTALTICKS;
            ProgressTick firstPagedownloadProgress = new ProgressTick(progress, thisPageTicks, TOTALTICKS);

            string safeUrl = UrlHelper.GetUrlWithoutAnchorIdentifier(url);

            // Look up the content type of this pageToDownload
            UrlContentTypeInfo headerInfo = null;
            if (_headerInfo.ContainsKey(safeUrl))
            {
                headerInfo = (UrlContentTypeInfo)_headerInfo[safeUrl];
            }
            else
            {
                if (lightWeightDocument != null)
                    headerInfo = new UrlContentTypeInfo("text/html", url);
                else if (headerInfo == null && !_context.IsTimedOutUrl(url) && _context.ShouldDownloadThisUrl(url))
                {
                    progress.UpdateProgress(string.Format(CultureInfo.CurrentCulture, Res.Get(StringId.ProgressDeterminingType), url));
                    if (lightWeightDocument == null)
                        headerInfo = ContentTypeHelper.ExpensivelyGetUrlContentType(url, _context.TimeoutMS);
                    else
                        headerInfo = ContentTypeHelper.InexpensivelyGetUrlContentType(url);
                }
                _headerInfo.Add(safeUrl, headerInfo);
            }

            // If this is a web page and we should download it, do it!
            if ((lightWeightDocument != null && IsDownloadablePageResource(headerInfo)) ||
                (lightWeightDocument == null && IsDownloadablePageResource(headerInfo) && _context.ShouldDownloadThisUrl(headerInfo))
                )
            {
                bool downloadWorked = false;
                int downloadAttempts = -1;
                bool timedOut = true;

                // Max sure we are retrying the correct number of times
                ProgressTick pageDownloadProgress = new ProgressTick(firstPagedownloadProgress, 80, 100);
                while (!downloadWorked && downloadAttempts++ < _context.RetryCount && timedOut)
                {
                    timedOut = false;

                    pageDownloadProgress.UpdateProgress(0, 1);
                    try
                    {
                        // If we haven't downloaded this page yet download it
                        PageToDownload thisPageToDownload = null;

                        if (!_context.UrlAlreadyDownloaded(safeUrl))
                        {
                            if (lightWeightDocument == null)
                                thisPageToDownload = DownloadUrl(url, parentPageToDownload, pageDownloadProgress);
                            else
                            {
                                LightWeightHTMLDocument htmlDoc = lightWeightDocument;

                                // Only redownload if we absolutely need to
                                if (htmlDoc.HasFramesOrStyles && (htmlDoc.Frames == null || htmlDoc.StyleResourcesUrls == null))
                                {

                                    string html = htmlDoc.GenerateHtml();
                                    string tempFile = TempFileManager.Instance.CreateTempFile("temp.htm");
                                    using (StreamWriter writer = new StreamWriter(tempFile, false, Encoding.UTF8))
                                        writer.Write(html);
                                    using (HTMLDocumentDownloader downloader = new HTMLDocumentDownloader(_parentControl, UrlHelper.GetLocalFileUrl(tempFile), htmlDoc.Title, _context.CookieString, _context.TimeoutMS, false))
                                    {
                                        downloader.DownloadHTMLDocument(pageDownloadProgress);

                                        htmlDoc.UpdateBasedUponHTMLDocumentData(downloader.HtmlDocument, url);
                                    }
                                }
                                thisPageToDownload = new PageToDownload(htmlDoc, url, null, parentPageToDownload);
                                if (htmlDoc.StyleResourcesUrls != null)
                                    foreach (HTMLDocumentHelper.ResourceUrlInfo styleUrl in htmlDoc.StyleResourcesUrls)
                                        thisPageToDownload.AddReference(new ReferenceToDownload(styleUrl.ResourceUrl, thisPageToDownload, styleUrl.ResourceAbsoluteUrl));
                            }
                            // Add this page to our lists
                            _context.AddPageToDownload(safeUrl, thisPageToDownload, true);
                            downloadedPages.Add(thisPageToDownload);

                        }
                        else
                            thisPageToDownload = (PageToDownload)_context.CreatedPageToDownloadTable[safeUrl];

                        // If we're downloading a site, add a second copy of the root page in the references subdir
                        // This was, if the root page gets renamed, links back to it will still work correctly
                        // This is a bit of a hack, but otherwise, we'll need to escape urls whenever we output
                        // the site and change the root file name
                        if (thisPageToDownload.IsRootPage && _context.Depth > 0)
                        {
                            PageToDownload copyOfThisPageToDownload = new PageToDownload(thisPageToDownload.LightWeightHTMLDocument.Clone(), thisPageToDownload.UrlToReplace, thisPageToDownload.FileName, thisPageToDownload);
                            downloadedPages.Add(copyOfThisPageToDownload);
                        }

                        // enumerate the frames of this page and add them to the list of pages
                        PageToDownload[] subFramesToDownload = GetFramePagesToDownload(thisPageToDownload);
                        downloadedPages.AddRange(subFramesToDownload);
                        foreach (PageToDownload pageToDownload in subFramesToDownload)
                            _context.AddPageToDownload(pageToDownload.AbsoluteUrl, pageToDownload, false);

                        // Now drill down based upon the depth configuration
                        if (_context.ShouldContinue(_currentDepth))
                        {
                            ProgressTick otherPagesdownloadProgress = new ProgressTick(progress, TOTALTICKS - thisPageTicks, TOTALTICKS);
                            downloadedPages.AddRange(GetSubPagesToDownload(otherPagesdownloadProgress, downloadedPages, thisPageToDownload));
                        }
                        downloadWorked = true;
                        firstPagedownloadProgress.UpdateProgress(1, 1);

                    }
                    catch (OperationTimedOutException)
                    {
                        timedOut = true;
                    }
                    catch (WebPageDownloaderException htex)
                    {
                        HandleException(new Exception(htex.Message, htex));
                    }
                    catch (Exception ex)
                    {
                        HandleException(new Exception(String.Format(CultureInfo.CurrentCulture, "{0} could not be downloaded", _url), ex));
                    }
                }

                // If we never got the download to succeed, add it to the list of timed out Urls
                if (!downloadWorked && timedOut)
                {
                    _context.AddTimedOutUrl(_url);
                    firstPagedownloadProgress.UpdateProgress(1, 1);

                }
            }
            // If it isn't a page we'll just add the file to the reference list for the parent page
            // There is not an else, because we could be looking at a reference, but a reference that
            // should not be downloaded (in which case we just ignore it)
            else if (headerInfo != null && _context.ShouldDownloadThisUrl(headerInfo))
            {
                parentPageToDownload.AddReference(new ReferenceToDownload(url, parentPageToDownload));
                progress.UpdateProgress(1, 1);
            }

            progress.UpdateProgress(1, 1);

            _currentDepth--;
            return (PageToDownload[])downloadedPages.ToArray(typeof(PageToDownload));
        }
        private BlogEditingTemplateFiles SafeGetTemplates(IProgressHost progress)
        {
            WriterEditingManifest    editingManifest = null;
            BlogEditingTemplateFiles templateFiles   = new BlogEditingTemplateFiles();

            try
            {
                // if we have a manifest url then try to get our manifest
                if (_manifestDownloadInfo != null)
                {
                    // try to get the editing manifest
                    string manifestUrl = _manifestDownloadInfo.SourceUrl;
                    editingManifest = WriterEditingManifest.FromUrl(
                        new Uri(manifestUrl),
                        _blogClient,
                        _credentials,
                        true);

                    // progress
                    CheckCancelRequested(progress);
                    progress.UpdateProgress(20, 100);
                }

                // if we have no editing manifest then probe (if allowed)
                if ((editingManifest == null) && _probeForManifest)
                {
                    editingManifest = WriterEditingManifest.FromHomepage(
                        new LazyHomepageDownloader(_blogHomepageUrl, new HttpRequestHandler(_blogClient.SendAuthenticatedHttpRequest)),
                        new Uri(_blogHomepageUrl),
                        _blogClient,
                        _credentials);
                }

                // progress
                CheckCancelRequested(progress);
                progress.UpdateProgress(40, 100);

                // if we got one then return templates from it as-appropriate
                if (editingManifest != null)
                {
                    if (editingManifest.WebLayoutUrl != null)
                    {
                        string webLayoutTemplate = DownloadManifestTemplate(new ProgressTick(progress, 10, 100), editingManifest.WebLayoutUrl);
                        if (BlogEditingTemplate.ValidateTemplate(webLayoutTemplate))
                        {
                            // download supporting files
                            string templateFile = DownloadTemplateFiles(webLayoutTemplate, _blogHomepageUrl, new ProgressTick(progress, 20, 100));

                            // return the template
                            templateFiles.FramedTemplate = new BlogEditingTemplateFile(BlogEditingTemplateType.Framed, templateFile);
                        }
                        else
                        {
                            Trace.WriteLine("Invalid webLayoutTemplate specified in manifest");
                        }
                    }

                    if (editingManifest.WebPreviewUrl != null)
                    {
                        string webPreviewTemplate = DownloadManifestTemplate(new ProgressTick(progress, 10, 100), editingManifest.WebPreviewUrl);
                        if (BlogEditingTemplate.ValidateTemplate(webPreviewTemplate))
                        {
                            // download supporting files
                            string templateFile = DownloadTemplateFiles(webPreviewTemplate, _blogHomepageUrl, new ProgressTick(progress, 20, 100));

                            // return the template
                            templateFiles.WebPageTemplate = new BlogEditingTemplateFile(BlogEditingTemplateType.Webpage, templateFile);
                        }
                        else
                        {
                            Trace.WriteLine("Invalid webPreviewTemplate specified in manifest");
                        }
                    }
                }
            }
            catch
            {
            }
            finally
            {
                progress.UpdateProgress(100, 100);
            }

            return(templateFiles);
        }
        private void PrepareRegionsUsingTemporaryPost(IProgressHost progress)
        {
            // Publish a temporary post so that we can examine HTML that will surround posts created with the editor
            temporaryPost = PostTemplate(new ProgressTick(progress, 25, 100));
            CheckCancelRequested(progress);

            blogHomepageContents = new MemoryStream();

            // Download the webpage that is contains the temporary blog post
            // WARNING, DownloadBlogPage uses an MSHTML Document on a non-UI thread...which is a no-no!
            //   its been this way through several betas without problem, so we'll keep it that way for now, but
            //   it needs to be fixed eventually.
            Stream postHtmlContents = DownloadBlogPage(_blogHomepageUrl, progress);
            CheckCancelRequested(progress);

            using (postHtmlContents)
            {
                StreamHelper.Transfer(postHtmlContents, blogHomepageContents);
            }
            progress.UpdateProgress(100, 100);
        }
        /// <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);
        }
        public override BlogPostRegions LocateRegionsOnUIThread(IProgressHost progress)
        {
            blogHomepageContents.Seek(0, SeekOrigin.Begin);
            IHTMLDocument2 doc2 = HTMLDocumentHelper.GetHTMLDocumentFromStream(blogHomepageContents, _blogHomepageUrl);

            // Ensure that the document is fully loaded.
            // If it is not fully loaded, then viewing its current style is non-deterministic.
            DateTime startedDoingEvents = DateTime.Now;
            while (!progress.CancelRequested && !HTMLDocumentHelper.IsReady(doc2))
            {
                if (DateTime.Now.Subtract(startedDoingEvents).TotalMilliseconds > 10000)
                {
                    // Timing out here is not fatal.
                    Trace.WriteLine("Timed out while loading blog homepage for theme detection.");
                    break;
                }

                Application.DoEvents();
            }

            IHTMLElement[] titles = FindText(_titleText, doc2.body);
            IHTMLElement[] bodies = FindText(_bodyText, doc2.body);
            if (titles.Length == 0 || bodies.Length == 0)
                throw new Exception("Unable to locate blog post elements using most recent post");

            if (IsSmartContent(bodies[0]))
                throw new Exception("Most recent post is smart content");

            BlogPostRegions regions = new BlogPostRegions();
            regions.TitleRegions = titles;

            //scrub the post body element to avoid improperly including extraneous parent elements
            regions.BodyRegion = ScrubPostBodyRegionParentElements(bodies[0]);
            regions.Document = doc2;

            progress.UpdateProgress(100, 100);

            return regions;
        }
        /// <summary>
        /// Downloads the pages and their references, providing progress feedback
        /// </summary>
        /// <param name="progressHost">The progresshost to use for feedback</param>
        /// <returns>this</returns>
        public object Download(IProgressHost progressHost)
        {
            // Prepare the list of references to download
            progressHost.UpdateProgress(Res.Get(StringId.ProgressPreparingListOfFiles));
            foreach (PageToDownload pageToDownload in _pagesToDownload)
            {
                // Lay down a placeholder file with the correct file name
                try
                {
                    string destination = Path.Combine(_siteStorage.BasePath, pageToDownload.RelativePath);
                    destination = PathHelper.GetNonConflictingPath(destination);
                    pageToDownload.FileName = Path.GetFileName(destination);

                    using (Stream htmlStream = _siteStorage.Open(destination, AccessMode.Write)) { }
                }
                catch (Exception e)
                {
                    HandleException(e);
                }

                foreach (ReferenceToDownload reference in pageToDownload.References)
                {
                    // Don't add the same item more than once
                    if (!_referencesToDownload.ContainsKey(reference.AbsoluteUrl))
                        _referencesToDownload.Add(reference.AbsoluteUrl, reference);
                }
            }

            // Enqueue the work items
            progressHost.UpdateProgress(Res.Get(StringId.ProgressStartingDownloadOfReferences));
            IProgressHost[] progressHosts = new JointProgressHosts(progressHost, _referencesToDownload.Count, 8000, 10000).ProgressHosts;
            int tickNum = 0;
            foreach (ReferenceToDownload reference in _referencesToDownload.Values)
                workQueue.Enqueue(new DownloadWorkItem(reference, _siteStorage, progressHosts[tickNum++]));

            // Start up the parallel execution of the downloads
            ParallelExecution parallelExecution = new ParallelExecution(new ThreadStart(WorkerThreadStart), 2);
            parallelExecution.Execute();
            parallelExecution = null;

            // Now go through and get HTML for each page, and emit the HTML to disk
            ProgressTick allPagesProgress = new ProgressTick(progressHost, 2000, 10000);
            for (int i = 0; i < _pagesToDownload.Length; i++)
            {
                try
                {
                    allPagesProgress.UpdateProgress(i, _pagesToDownload.Length, string.Format(CultureInfo.CurrentCulture, Res.Get(StringId.ProgressSaving), _pagesToDownload[i].FileName));
                    WriteHtmlToDisk(_pagesToDownload[i], _siteStorage);
                }
                catch (Exception e)
                {
                    HandleException(e);
                }
                if (allPagesProgress.CancelRequested)
                    throw new OperationCancelledException();
            }

            // We're complete!
            progressHost.UpdateProgress(1, 1, Res.Get(StringId.ProgressDownloadFinished));

            return this;
        }
        private string DownloadManifestTemplate(IProgressHost progress, string manifestTemplateUrl)
        {
            try
            {
                // update progress
                progress.UpdateProgress(0, 100, Res.Get(StringId.ProgressDownloadingEditingTemplate));

                // process any parameters within the url
                string templateUrl = BlogClientHelper.FormatUrl(manifestTemplateUrl, _blogHomepageUrl, _blogAccount.PostApiUrl, _blogAccount.BlogId);

                // download the url
                using (StreamReader streamReader = new StreamReader(_blogClient.SendAuthenticatedHttpRequest(templateUrl, 20000, null).GetResponseStream()))
                    return streamReader.ReadToEnd();
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Exception occurred while attempting to download template from " + manifestTemplateUrl + " :" + ex.ToString());
                return null;
            }
            finally
            {
                progress.UpdateProgress(100, 100);
            }
        }
Esempio n. 38
0
        public object DetectSettings(IProgressHost progressHost)
        {
            using (_silentMode ? new BlogClientUIContextSilentMode() : null)
            {
                if (IncludeButtons || IncludeOptionOverrides || IncludeImages)
                {
                    using (new ProgressContext(progressHost, 40, Res.Get(StringId.ProgressDetectingWeblogSettings)))
                    {
                        // attempt to download editing manifest
                        WriterEditingManifest editingManifest = SafeDownloadEditingManifest();

                        if (editingManifest != null)
                        {
                            // always update the download info
                            if (editingManifest.DownloadInfo != null)
                            {
                                _context.ManifestDownloadInfo = editingManifest.DownloadInfo;
                            }

                            // images
                            if (IncludeImages)
                            {
                                // image if provided
                                if (editingManifest.Image != null)
                                {
                                    _context.Image = editingManifest.Image;
                                }

                                // watermark if provided
                                if (editingManifest.Watermark != null)
                                {
                                    _context.WatermarkImage = editingManifest.Watermark;
                                }
                            }

                            // buttons if provided
                            if (IncludeButtons && (editingManifest.ButtonDescriptions != null))
                            {
                                _context.ButtonDescriptions = editingManifest.ButtonDescriptions;
                            }

                            // option overrides if provided
                            if (IncludeOptionOverrides)
                            {
                                if (editingManifest.ClientType != null)
                                {
                                    _context.ClientType = editingManifest.ClientType;
                                }

                                if (editingManifest.OptionOverrides != null)
                                {
                                    _context.OptionOverrides = editingManifest.OptionOverrides;
                                }
                            }
                        }
                    }
                }

                using (new ProgressContext(progressHost, 40, Res.Get(StringId.ProgressDetectingWeblogCharSet)))
                {
                    if (IncludeOptionOverrides && IncludeHomePageSettings)
                    {
                        DetectHomePageSettings();
                    }
                }

                IBlogClient blogClient = CreateBlogClient();
                if (IncludeInsecureOperations || blogClient.IsSecure)
                {
                    if (blogClient is ISelfConfiguringClient)
                    {
                        // This must happen before categories detection but after manifest!!
                        ((ISelfConfiguringClient)blogClient).DetectSettings(_context, this);
                    }

                    // detect categories
                    if (IncludeCategories)
                    {
                        using (
                            new ProgressContext(progressHost, 20, Res.Get(StringId.ProgressDetectingWeblogCategories)))
                        {
                            BlogPostCategory[] categories = SafeDownloadCategories();
                            if (categories != null)
                            {
                                _context.Categories = categories;
                            }

                            BlogPostKeyword[] keywords = SafeDownloadKeywords();
                            if (keywords != null)
                            {
                                _context.Keywords = keywords;
                            }
                        }
                    }

                    // detect favicon (only if requested AND we don't have a PNG already
                    // for the small image size)
                    if (IncludeFavIcon)
                    {
                        using (new ProgressContext(progressHost, 10, Res.Get(StringId.ProgressDetectingWeblogIcon)))
                        {
                            byte[] favIcon = SafeDownloadFavIcon();
                            if (favIcon != null)
                            {
                                _context.FavIcon = favIcon;
                            }
                        }
                    }

                    if (IncludeImageEndpoints)
                    {
                        Debug.WriteLine("Detecting image endpoints");
                        ITemporaryBlogSettingsDetectionContext tempContext =
                            _context as ITemporaryBlogSettingsDetectionContext;
                        Debug.Assert(tempContext != null,
                                     "IncludeImageEndpoints=true but non-temporary context (type " +
                                     _context.GetType().Name + ") was used");
                        if (tempContext != null)
                        {
                            tempContext.AvailableImageEndpoints = null;
                            try
                            {
                                BlogInfo[] imageEndpoints = blogClient.GetImageEndpoints();
                                tempContext.AvailableImageEndpoints = imageEndpoints;
                                Debug.WriteLine(imageEndpoints.Length + " image endpoints detected");
                            }
                            catch (NotImplementedException)
                            {
                                Debug.WriteLine("Image endpoints not implemented");
                            }
                            catch (Exception e)
                            {
                                Trace.Fail("Exception detecting image endpoints: " + e.ToString());
                            }
                        }
                    }
                }
                // completed
                progressHost.UpdateProgress(100, 100, Res.Get(StringId.ProgressCompletedSettingsDetection));
            }

            return(this);
        }
        /// <summary>
        /// Downloads the pages and their references, providing progress feedback
        /// </summary>
        /// <param name="progressHost">The progresshost to use for feedback</param>
        /// <returns>this</returns>
        public object Download(IProgressHost progressHost)
        {
            // Prepare the list of references to download
            progressHost.UpdateProgress(Res.Get(StringId.ProgressPreparingListOfFiles));
            foreach (PageToDownload pageToDownload in _pagesToDownload)
            {
                // Lay down a placeholder file with the correct file name
                try
                {
                    string destination = Path.Combine(_siteStorage.BasePath, pageToDownload.RelativePath);
                    destination             = PathHelper.GetNonConflictingPath(destination);
                    pageToDownload.FileName = Path.GetFileName(destination);

                    using (Stream htmlStream = _siteStorage.Open(destination, AccessMode.Write)) { }
                }
                catch (Exception e)
                {
                    HandleException(e);
                }

                foreach (ReferenceToDownload reference in pageToDownload.References)
                {
                    // Don't add the same item more than once
                    if (!_referencesToDownload.ContainsKey(reference.AbsoluteUrl))
                    {
                        _referencesToDownload.Add(reference.AbsoluteUrl, reference);
                    }
                }
            }

            // Enqueue the work items
            progressHost.UpdateProgress(Res.Get(StringId.ProgressStartingDownloadOfReferences));
            IProgressHost[] progressHosts = new JointProgressHosts(progressHost, _referencesToDownload.Count, 8000, 10000).ProgressHosts;
            int             tickNum       = 0;

            foreach (ReferenceToDownload reference in _referencesToDownload.Values)
            {
                workQueue.Enqueue(new DownloadWorkItem(reference, _siteStorage, progressHosts[tickNum++]));
            }

            // Start up the parallel execution of the downloads
            ParallelExecution parallelExecution = new ParallelExecution(new ThreadStart(WorkerThreadStart), 2);

            parallelExecution.Execute();
            parallelExecution = null;

            // Now go through and get HTML for each page, and emit the HTML to disk
            ProgressTick allPagesProgress = new ProgressTick(progressHost, 2000, 10000);

            for (int i = 0; i < _pagesToDownload.Length; i++)
            {
                try
                {
                    allPagesProgress.UpdateProgress(i, _pagesToDownload.Length, string.Format(CultureInfo.CurrentCulture, Res.Get(StringId.ProgressSaving), _pagesToDownload[i].FileName));
                    WriteHtmlToDisk(_pagesToDownload[i], _siteStorage);
                }
                catch (Exception e)
                {
                    HandleException(e);
                }
                if (allPagesProgress.CancelRequested)
                {
                    throw new OperationCancelledException();
                }
            }

            // We're complete!
            progressHost.UpdateProgress(1, 1, Res.Get(StringId.ProgressDownloadFinished));

            return(this);
        }
        protected void UpdateProgress(IProgressHost progressHost, int percent, string message)
        {
            if (CancelRequested)
                throw new OperationCancelledException();

            progressHost.UpdateProgress(percent, 100, message);
        }
Esempio n. 41
0
        /// <summary>
        /// Actually downloads the pages
        /// </summary>
        private PageToDownload[] DownloadPages(IProgressHost progress, string url, LightWeightHTMLDocument lightWeightDocument, PageToDownload parentPageToDownload)
        {
            // Check for cancel
            if (progress.CancelRequested)
            {
                throw new OperationCancelledException();
            }

            _currentDepth++;
            ArrayList downloadedPages = new ArrayList();

            // Set up our progress
            int thisPageTicks = FIRSTPAGETICKS;

            if (_context.Depth == _currentDepth)
            {
                thisPageTicks = TOTALTICKS;
            }
            ProgressTick firstPagedownloadProgress = new ProgressTick(progress, thisPageTicks, TOTALTICKS);

            string safeUrl = UrlHelper.GetUrlWithoutAnchorIdentifier(url);

            // Look up the content type of this pageToDownload
            UrlContentTypeInfo headerInfo = null;

            if (_headerInfo.ContainsKey(safeUrl))
            {
                headerInfo = (UrlContentTypeInfo)_headerInfo[safeUrl];
            }
            else
            {
                if (lightWeightDocument != null)
                {
                    headerInfo = new UrlContentTypeInfo("text/html", url);
                }
                else if (headerInfo == null && !_context.IsTimedOutUrl(url) && _context.ShouldDownloadThisUrl(url))
                {
                    progress.UpdateProgress(string.Format(CultureInfo.CurrentCulture, Res.Get(StringId.ProgressDeterminingType), url));
                    if (lightWeightDocument == null)
                    {
                        headerInfo = ContentTypeHelper.ExpensivelyGetUrlContentType(url, _context.TimeoutMS);
                    }
                    else
                    {
                        headerInfo = ContentTypeHelper.InexpensivelyGetUrlContentType(url);
                    }
                }
                _headerInfo.Add(safeUrl, headerInfo);
            }

            // If this is a web page and we should download it, do it!
            if ((lightWeightDocument != null && IsDownloadablePageResource(headerInfo)) ||
                (lightWeightDocument == null && IsDownloadablePageResource(headerInfo) && _context.ShouldDownloadThisUrl(headerInfo))
                )
            {
                bool downloadWorked   = false;
                int  downloadAttempts = -1;
                bool timedOut         = true;

                // Max sure we are retrying the correct number of times
                ProgressTick pageDownloadProgress = new ProgressTick(firstPagedownloadProgress, 80, 100);
                while (!downloadWorked && downloadAttempts++ < _context.RetryCount && timedOut)
                {
                    timedOut = false;

                    pageDownloadProgress.UpdateProgress(0, 1);
                    try
                    {
                        // If we haven't downloaded this page yet download it
                        PageToDownload thisPageToDownload = null;

                        if (!_context.UrlAlreadyDownloaded(safeUrl))
                        {
                            if (lightWeightDocument == null)
                            {
                                thisPageToDownload = DownloadUrl(url, parentPageToDownload, pageDownloadProgress);
                            }
                            else
                            {
                                LightWeightHTMLDocument htmlDoc = lightWeightDocument;

                                // Only redownload if we absolutely need to
                                if (htmlDoc.HasFramesOrStyles && (htmlDoc.Frames == null || htmlDoc.StyleResourcesUrls == null))
                                {
                                    string html     = htmlDoc.GenerateHtml();
                                    string tempFile = TempFileManager.Instance.CreateTempFile("temp.htm");
                                    using (StreamWriter writer = new StreamWriter(tempFile, false, Encoding.UTF8))
                                        writer.Write(html);
                                    using (HTMLDocumentDownloader downloader = new HTMLDocumentDownloader(_parentControl, UrlHelper.GetLocalFileUrl(tempFile), htmlDoc.Title, _context.CookieString, _context.TimeoutMS, false))
                                    {
                                        downloader.DownloadHTMLDocument(pageDownloadProgress);

                                        htmlDoc.UpdateBasedUponHTMLDocumentData(downloader.HtmlDocument, url);
                                    }
                                }
                                thisPageToDownload = new PageToDownload(htmlDoc, url, null, parentPageToDownload);
                                if (htmlDoc.StyleResourcesUrls != null)
                                {
                                    foreach (HTMLDocumentHelper.ResourceUrlInfo styleUrl in htmlDoc.StyleResourcesUrls)
                                    {
                                        thisPageToDownload.AddReference(new ReferenceToDownload(styleUrl.ResourceUrl, thisPageToDownload, styleUrl.ResourceAbsoluteUrl));
                                    }
                                }
                            }
                            // Add this page to our lists
                            _context.AddPageToDownload(safeUrl, thisPageToDownload, true);
                            downloadedPages.Add(thisPageToDownload);
                        }
                        else
                        {
                            thisPageToDownload = (PageToDownload)_context.CreatedPageToDownloadTable[safeUrl];
                        }

                        // If we're downloading a site, add a second copy of the root page in the references subdir
                        // This was, if the root page gets renamed, links back to it will still work correctly
                        // This is a bit of a hack, but otherwise, we'll need to escape urls whenever we output
                        // the site and change the root file name
                        if (thisPageToDownload.IsRootPage && _context.Depth > 0)
                        {
                            PageToDownload copyOfThisPageToDownload = new PageToDownload(thisPageToDownload.LightWeightHTMLDocument.Clone(), thisPageToDownload.UrlToReplace, thisPageToDownload.FileName, thisPageToDownload);
                            downloadedPages.Add(copyOfThisPageToDownload);
                        }

                        // enumerate the frames of this page and add them to the list of pages
                        PageToDownload[] subFramesToDownload = GetFramePagesToDownload(thisPageToDownload);
                        downloadedPages.AddRange(subFramesToDownload);
                        foreach (PageToDownload pageToDownload in subFramesToDownload)
                        {
                            _context.AddPageToDownload(pageToDownload.AbsoluteUrl, pageToDownload, false);
                        }

                        // Now drill down based upon the depth configuration
                        if (_context.ShouldContinue(_currentDepth))
                        {
                            ProgressTick otherPagesdownloadProgress = new ProgressTick(progress, TOTALTICKS - thisPageTicks, TOTALTICKS);
                            downloadedPages.AddRange(GetSubPagesToDownload(otherPagesdownloadProgress, downloadedPages, thisPageToDownload));
                        }
                        downloadWorked = true;
                        firstPagedownloadProgress.UpdateProgress(1, 1);
                    }
                    catch (OperationTimedOutException)
                    {
                        timedOut = true;
                    }
                    catch (WebPageDownloaderException htex)
                    {
                        HandleException(new Exception(htex.Message, htex));
                    }
                    catch (Exception ex)
                    {
                        HandleException(new Exception(String.Format(CultureInfo.CurrentCulture, "{0} could not be downloaded", _url), ex));
                    }
                }

                // If we never got the download to succeed, add it to the list of timed out Urls
                if (!downloadWorked && timedOut)
                {
                    _context.AddTimedOutUrl(_url);
                    firstPagedownloadProgress.UpdateProgress(1, 1);
                }
            }
            // If it isn't a page we'll just add the file to the reference list for the parent page
            // There is not an else, because we could be looking at a reference, but a reference that
            // should not be downloaded (in which case we just ignore it)
            else if (headerInfo != null && _context.ShouldDownloadThisUrl(headerInfo))
            {
                parentPageToDownload.AddReference(new ReferenceToDownload(url, parentPageToDownload));
                progress.UpdateProgress(1, 1);
            }

            progress.UpdateProgress(1, 1);

            _currentDepth--;
            return((PageToDownload[])downloadedPages.ToArray(typeof(PageToDownload)));
        }
 public ProgressContext(IProgressHost progressHost, int complete, string message)
 {
     _progressHost = progressHost;
     _progressHost.UpdateProgress(complete, 100, message);
 }
        /// <summary>
        /// Initiate a download, using the progressHost to provide progress feedback
        /// </summary>
        /// <param name="progressHost">The progressHost to provide feedback to</param>
        /// <returns>this</returns>
        public object DownloadHTMLDocument(IProgressHost progressHost)
        {
            _downloadComplete = false;

            // Call the download method on the parent STA thread
            // Then wait for it to complete (the Monitor will be pulsed upon completion)
            _parentControl.Invoke(new Download(DoDownload), new object[] { progressHost });

            lock (this)
            {
                if (_downloadComplete)
                    return this;

                DateTime endDateTime = DateTime.Now.AddMilliseconds(TimeoutMs);
                while (!_downloadComplete)
                {
                    if (!Monitor.Wait(this, Math.Max(0, (int)endDateTime.Subtract(DateTime.Now).TotalMilliseconds)))
                        throw new OperationTimedOutException();

                }

                if (_downloader.Result.Exception != null)
                    throw _downloader.Result.Exception;

                progressHost.UpdateProgress(1, 1);
                return this;
            }
        }