/// <summary>
        /// Downloads the contents at the URL and save them to a temporary file.
        /// </summary>
        /// <param name="url">The URL that specifies what to download.</param>
        /// <returns>The file name it was saved to.</returns>
        public string DownloadZipFile(DownloadInfo downloadInfo, BackgroundWorker workerThread)
        {
            CookieContainer cookieContainer = null;
            HttpWebRequest webRequest = null;
            HttpWebResponse webResponse = null;
            Stream responseStream = null;
            FileStream fileStream = null;
            string fileName = "";
            
            // we can't get the size of the download because it's not included in the response header
            // so we will estimate that it's 500k
            long estimatedSize = 500000;

            try
            {
                // create the cookie container
                cookieContainer = new CookieContainer();
                cookieContainer.Add(new Uri("http://www.codeproject.com/"), downloadInfo.Cookies);
                // Create the web request
                webRequest = (HttpWebRequest)HttpWebRequest.Create(downloadInfo.ProjectUrl);
                // Set default authentication for retrieving the file
                webRequest.Credentials = CredentialCache.DefaultCredentials;
                // identifies itself
                webRequest.UserAgent = "CPBrowser";
                // apply the session cookies
                webRequest.CookieContainer = cookieContainer;
                // Get the response
                webResponse = (HttpWebResponse)webRequest.GetResponse();
                // Get the response stream
                responseStream = webResponse.GetResponseStream();
                // get the name from the url
                fileName = ExtractNameFromUrl(downloadInfo.ProjectUrl.ToString()) + ".zip";
                fileName = Path.Combine(Path.GetTempPath(), fileName);
                // write it to a temporary file in 1000 byte chunks
                fileStream = new FileStream(fileName, FileMode.Create);

                int bytesRead = 0;
                int totalBytesRead = 0;
                int progress = 15;
                byte[] data = new byte[1000];
                // keep looping until we read nothing
                do
                {
                    // read the next 1000 bytes of data
                    bytesRead = responseStream.Read(data, 0, 1000);
                    // write the data to the file
                    fileStream.Write(data, 0, bytesRead);

                    // report the progress
                    totalBytesRead += bytesRead;
                    // because this is an estimation, if the downloaded amount goes over the
                    // estimated amount, just loop back to 0
                    if (totalBytesRead >= estimatedSize)
                        totalBytesRead = 0;
                    progress = (int)(((float)totalBytesRead / (float)estimatedSize) * 99.0f);
                    workerThread.ReportProgress(progress);
                }
                while (bytesRead > 0);

                // report that we're done
                workerThread.ReportProgress(100);
            }
            catch (Exception ex)
            {
                string errMsg = "Error downloading file: ";

                // check if the user is logged in
                bool isLoggedIn = IsUserLoggedIn(downloadInfo.Cookies);
                if (isLoggedIn == false)
                    errMsg += "Make sure you are logged in to the web site.";
                else
                    errMsg += ex.Message;
                throw new Exception(errMsg);
            }
            finally
            {
                // free any resources
                if (fileStream != null)
                {
                    fileStream.Close();
                    fileStream.Dispose();
                }
                if (responseStream != null)
                {
                    responseStream.Close();
                    responseStream.Dispose();
                }
                if (webResponse != null)
                    webResponse.Close();
            }
            // return the file name
            return fileName;
        }
        /// <summary>
        /// This is the event handler which is called when the web browser control 
        /// begins navigating to an URL.  We want to intercept this navigation when the 
        /// URL ends in .zip, which indicates that a sample project may be being 
        /// downloaded.  If the URL ends with a .zip extension, ask if the user wants to
        /// open the sample directly in Visual Studio.  If so, then cancel IE's handling
        /// of this message, otherwise do nothing.
        /// </summary>
        private void WebBrowserCtl_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            try
            {
                string originalUrl = e.Url.ToString();
                // check the extension of the link
                string extension = Path.GetExtension(originalUrl);
                if (String.Compare(extension, ".zip", true) == 0)
                {
                    // if our worker thread os busy, just pass
                    if (m_downloadWorkerThread.IsBusy == true)
                    {
                        e.Cancel = true;
                        return;
                    }

                    // ask the user if they want to open the project directly
                    DialogResult dr = MessageBox.Show("Would you like to open this with the Code Project Browser?", "Code Project Browser", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                    if (dr == DialogResult.Yes)
                    {
                        try
                        {
                            ShowBusy();
                            // set the status bar
                            m_dte.StatusBar.Text = "Downloading Code Project file...";
                            // create the download info
                            string cookieString = "";
                            if (WebBrowserCtl.Document != null)
                                cookieString = WebBrowserCtl.Document.Cookie;
                            DownloadInfo downloadInfo = new DownloadInfo(e.Url, WebBrowserCtl.Url, WebBrowserCtl.Document);
                            // download the zip file asynchronously
                            m_downloadWorkerThread.RunWorkerAsync(downloadInfo);
                        }
                        catch (Exception ex)
                        {
                            ShowNotBusy();
                            string errMsg = "Error: " + ex.Message;
                            MessageBox.Show(errMsg, "Code Project Browser", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                        // tell IE not to go any further with this request
                        e.Cancel = true;
                    }
                    else if (dr == DialogResult.Cancel)
                    {
                        // tell IE not to go any further with this request
                        e.Cancel = true;
                    }
                }
                else if (IsArticleURL(e.Url) == true)
                {
                    ShowBusy();
                    // add the url to the combo box
                    ComboURL.Text = originalUrl;
                    m_navigating = true;
                }
            }
            catch (Exception ex)
            {
                ShowNotBusy();
                // show the error message
                MessageBox.Show("Unable to navigate: " + ex.Message, "Code Project Browser", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }