/// <summary>
        /// Appends a downloaded external binary file to our MhtBuilder using Base64 encoding
        /// </summary>
        void AppendMhtBinaryFile(MhtWebFile ef)
        {
            AppendMhtBoundary();
            AppendMhtLine("Content-Type: " + ef.ContentType);
            AppendMhtLine("Content-Transfer-Encoding: base64");
            AppendMhtLine("Content-Location: " + ef.Url);
            AppendMhtLine();

            // note that chunk size is equal to maximum line width (expanded = 75 chars)
            int len = ef.DownloadedBytes.Length;

            if (len <= _ChunkSize)
            {
                AppendMhtLine(Convert.ToBase64String(ef.DownloadedBytes, 0, len));
            }
            else
            {
                int i = 0;
                while ((i + _ChunkSize) < len)
                {
                    AppendMhtLine(Convert.ToBase64String(ef.DownloadedBytes, i, _ChunkSize));
                    i += _ChunkSize;
                }
                if (i != len)
                {
                    AppendMhtLine(Convert.ToBase64String(ef.DownloadedBytes, i, len - i));
                }
            }
        }
        /// <summary>
        /// Download a single externally referenced file (if we haven't already downloaded it)
        /// </summary>
        void DownloadExternalFile(string url, string targetFolder, bool recursive)
        {
            bool       isNew;
            MhtWebFile wf;

            // have we already downloaded (or attempted to) this file?
            if (_Builder.WebFiles.Contains(url) || _Builder.Url == url)
            {
                wf    = (MhtWebFile)_Builder.WebFiles[url];
                isNew = false;
            }
            else
            {
                wf    = new MhtWebFile(_Builder, url);
                isNew = true;
            }

            wf.Download();

            if (isNew)
            {
                // add this (possibly) downloaded file to our shared collection
                _Builder.WebFiles.Add(wf.UrlUnmodified, wf);

                // if this is an HTML file, it has dependencies of its own;
                // download them into a subfolder
                if ((wf.IsHtml || wf.IsCss) && recursive)
                {
                    wf.DownloadExternalFiles(recursive);
                }
            }
        }
 /// <summary>
 /// Appends a downloaded external text file to our MhtBuilder using Quoted-Printable encoding
 /// </summary>
 void AppendMhtTextFile(MhtWebFile ef)
 {
     AppendMhtBoundary();
     AppendMhtLine("Content-Type: " + ef.ContentType + ";");
     AppendMhtLine(Convert.ToChar(9).ToString() + @"charset="" + ef.TextEncoding.WebName + @""");
     AppendMhtLine("Content-Transfer-Encoding: quoted-printable");
     AppendMhtLine("Content-Location: " + ef.Url);
     AppendMhtLine();
     AppendMhtLine(QuotedPrintableEncode(ef.ToString(), ef.TextEncoding));
 }
 /// <summary>
 /// Appends a downloaded external file to our MhtBuilder
 /// </summary>
 void AppendMhtFile(MhtWebFile ef)
 {
     if (ef.WasDownloaded && !ef.WasAppended)
     {
         if (ef.IsBinary)
         {
             AppendMhtBinaryFile(ef);
         }
         else
         {
             AppendMhtTextFile(ef);
         }
     }
     ef.WasAppended = true;
 }
        /// <summary>
        /// appends the Mht header, which includes the root HTML
        /// </summary>
        void AppendMhtHeader(MhtWebFile ef)
        {
            // clear the stringbuilder contents
            _MhtBuilder = new StringBuilder();

            //AppendMhtLine("From: <Saved by " + Environment.UserName + " on " + Environment.MachineName + ">");
            //AppendMhtLine("Subject: " + ef.HtmlTitle);
            // For the title, reduces its size if too long and removes line breaks if any.
            string title = ef.HtmlTitle;

            if (title != null)
            {
                if (title.Length > 260)
                {
                    title = title.Substring(0, 260);
                }
                if (title.IndexOf('\n') != -1)
                {
                    title = title.Replace('\n', ' ');
                }
                if (title.IndexOf(Environment.NewLine) != -1)
                {
                    title = title.Replace(Environment.NewLine, " ");
                }
            }

            AppendMhtLine("From: <Saved by " + Environment.UserName + " on " + Environment.MachineName + ">");
            AppendMhtLine("Subject: " + title);

            AppendMhtLine("Date: " + DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz"));
            AppendMhtLine("MIME-Version: 1.0");
            AppendMhtLine("Content-Type: multipart/related;");
            AppendMhtLine(Convert.ToChar(9).ToString() + "type=\"text/html\";");
            AppendMhtLine(Convert.ToChar(9).ToString() + "boundary=\"----=_NextPart_000_00\"");
            AppendMhtLine("X-MimeOLE: Produced by " + this.GetType().ToString() + " " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
            AppendMhtLine("");
            AppendMhtLine("This is a multi-part message in MIME format.");

            AppendMhtFile(ef);
        }
        /// <summary>
        /// converts all external Html files (gif, jpg, css, etc) to local refs
        /// external ref:
        ///    &lt;img src="http://mywebsite/myfolder/myimage.gif"&gt;
        /// into local refs:
        ///    &lt;img src="mypage_files/myimage.gif"&gt;
        /// </summary>
        public void ConvertReferencesToLocal()
        {
            if (!this.IsHtml && !this.IsCss)
            {
                throw new Exception("Converting references only makes sense for HTML or CSS files; this file is of type '" + this.ContentType + "'");
            }

            // get a list of all external references
            string html = this.ToString();
            NameValueCollection fileCollection = this.ExternalHtmlFiles();

            // no external refs? nothing to do
            if (fileCollection.Count == 0)
            {
                return;
            }

            string[] keys = fileCollection.AllKeys;
            for (int idx = 0; idx < keys.Length; idx++)
            {
                string delimitedUrl = keys[idx];
                string fileUrl      = fileCollection[delimitedUrl];
                if (_Builder.WebFiles.Contains(fileUrl))
                {
                    MhtWebFile wf      = (MhtWebFile)_Builder.WebFiles[fileUrl];
                    string     newPath = this.ExternalFilesFolder + "/" + wf.DownloadFilename;
                    string     delimitedReplacement = Regex.Replace(delimitedUrl,
                                                                    @"^(?<StartDelim>""|'|\()*(?<Value>[^'"")]*)(?<EndDelim>""|'|\))*$",
                                                                    "${StartDelim}" + newPath + "${EndDelim}");

                    // correct original Url references in Html so they point to our local files
                    html = html.Replace(delimitedUrl, delimitedReplacement);
                }
            }

            _DownloadedBytes = _TextEncoding.GetBytes(html);
        }
		public MhtBuilder()
		{
			_HtmlFile = new MhtWebFile(this);
		}
		/// <summary>
		/// Appends a downloaded external text file to our MhtBuilder using Quoted-Printable encoding
		/// </summary>
		void AppendMhtTextFile(MhtWebFile ef)
		{
			AppendMhtBoundary();
			AppendMhtLine("Content-Type: " + ef.ContentType + ";");
			AppendMhtLine(Convert.ToChar(9).ToString() + @"charset="" + ef.TextEncoding.WebName + @""");
			AppendMhtLine("Content-Transfer-Encoding: quoted-printable");
			AppendMhtLine("Content-Location: " + ef.Url);
			AppendMhtLine();
			AppendMhtLine(QuotedPrintableEncode(ef.ToString(), ef.TextEncoding));
		}
		/// <summary>
		/// appends the Mht header, which includes the root HTML
		/// </summary>
		void AppendMhtHeader(MhtWebFile ef)
		{
			// clear the stringbuilder contents
			_MhtBuilder = new StringBuilder();

            //AppendMhtLine("From: <Saved by " + Environment.UserName + " on " + Environment.MachineName + ">");
            //AppendMhtLine("Subject: " + ef.HtmlTitle);
            // For the title, reduces its size if too long and removes line breaks if any. 
            string title = ef.HtmlTitle;
            if (title != null)
            {
                if (title.Length > 260)
                    title = title.Substring(0, 260);
                if (title.IndexOf('\n') != -1)
                    title = title.Replace('\n', ' ');
                if (title.IndexOf(Environment.NewLine) != -1)
                    title = title.Replace(Environment.NewLine, " ");
            }

            AppendMhtLine("From: <Saved by " + Environment.UserName + " on " + Environment.MachineName + ">");
            AppendMhtLine("Subject: " + title); 

			AppendMhtLine("Date: " + DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz"));
			AppendMhtLine("MIME-Version: 1.0");
			AppendMhtLine("Content-Type: multipart/related;");
			AppendMhtLine(Convert.ToChar(9).ToString() + "type=\"text/html\";");
			AppendMhtLine(Convert.ToChar(9).ToString() + "boundary=\"----=_NextPart_000_00\"");
			AppendMhtLine("X-MimeOLE: Produced by " + this.GetType().ToString() + " " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
			AppendMhtLine("");
			AppendMhtLine("This is a multi-part message in MIME format.");
   
			AppendMhtFile(ef);
		}
		/// <summary>
		/// Appends a downloaded external file to our MhtBuilder
		/// </summary>
		void AppendMhtFile(MhtWebFile ef)
		{
			if (ef.WasDownloaded && !ef.WasAppended)
			{
				if (ef.IsBinary)
					AppendMhtBinaryFile(ef);
				else
					AppendMhtTextFile(ef);
			}
			ef.WasAppended = true;
		}
		/// <summary>
		/// Appends a downloaded external binary file to our MhtBuilder using Base64 encoding
		/// </summary>
		void AppendMhtBinaryFile(MhtWebFile ef)
		{
			AppendMhtBoundary();
			AppendMhtLine("Content-Type: " + ef.ContentType);
			AppendMhtLine("Content-Transfer-Encoding: base64");
			AppendMhtLine("Content-Location: " + ef.Url);
			AppendMhtLine();
            
			// note that chunk size is equal to maximum line width (expanded = 75 chars)
			int len = ef.DownloadedBytes.Length;
			if (len <= _ChunkSize)
				AppendMhtLine(Convert.ToBase64String(ef.DownloadedBytes, 0, len));
			else
			{
				int i = 0;
				while ((i + _ChunkSize) < len)
				{
					AppendMhtLine(Convert.ToBase64String(ef.DownloadedBytes, i, _ChunkSize));
					i += _ChunkSize;
				}
				if (i != len)
					AppendMhtLine(Convert.ToBase64String(ef.DownloadedBytes, i, len - i));
			}
		}
		/// <summary>
		/// Download a single externally referenced file (if we haven't already downloaded it)
		/// </summary>
		void DownloadExternalFile(string url, string targetFolder, bool recursive)
		{
			bool isNew;
			MhtWebFile wf;
			
			// have we already downloaded (or attempted to) this file?
			if (_Builder.WebFiles.Contains(url) || _Builder.Url == url)
			{
				wf = (MhtWebFile) _Builder.WebFiles[url];
				isNew = false;
			}
			else
			{
				wf = new MhtWebFile(_Builder, url);
				isNew = true;
			}

			wf.Download();
			
			if (isNew)
			{
				// add this (possibly) downloaded file to our shared collection
				_Builder.WebFiles.Add(wf.UrlUnmodified, wf);
				
				// if this is an HTML file, it has dependencies of its own;
				// download them into a subfolder
				if ((wf.IsHtml || wf.IsCss) && recursive)
					wf.DownloadExternalFiles(recursive);
			}
		}
 public MhtBuilder()
 {
     _HtmlFile = new MhtWebFile(this);
 }