Describes a file that is to be downloaded.
This is simply a friendly representation of the HTTP headers of the file.
			/// <summary>
			/// A simple constructor that initializes the object with the given values.
			/// </summary>
			/// <param name="p_fdrFileDownloader">The <see cref="FileDownloader"/> from which to retrieve the block this
			/// downloader will download.</param>
			/// <param name="p_fmdInfo">The metadata of the to be downloaded.</param>
			/// <param name="p_fwrWriter">The writer to use to write the file to the disk.</param>
			/// <param name="p_intBufferSize">The size of the buffer to send to the file writer.</param>
			/// <param name="p_strUserAgent">The current User Agent.</param>
			public BlockDownloader(FileDownloader p_fdrFileDownloader, FileMetadata p_fmdInfo, FileWriter p_fwrWriter, Int32 p_intBufferSize, string p_strUserAgent)
			{
				m_fdrFileDownloader = p_fdrFileDownloader;
				m_fmdInfo = p_fmdInfo;
				m_fwrWriter = p_fwrWriter;
				m_intBufferSize = p_intBufferSize;
				m_strUserAgent = p_strUserAgent;
				m_fwrWriter.UnableToWrite += new EventHandler(FileWriter_UnableToWrite);
			}
		/// <summary>
		/// Gets the file's metadata.
		/// </summary>
		/// <returns>The file's metadata.</returns>
		protected FileMetadata GetMetadata()
		{
			Trace.TraceInformation(String.Format("[{0}] Retreiving metadata.", m_uriURL.ToString()));
			HttpWebRequest hwrFileMetadata = (HttpWebRequest)WebRequest.Create(m_uriURL);
			CookieContainer ckcCookies = new CookieContainer();
			foreach (KeyValuePair<string, string> kvpCookie in Cookies)
				ckcCookies.Add(new Cookie(kvpCookie.Key, kvpCookie.Value, "/", m_uriURL.Host));
			hwrFileMetadata.CookieContainer = ckcCookies;
			hwrFileMetadata.Method = "HEAD";
			hwrFileMetadata.AddRange(0, 1);
			hwrFileMetadata.AllowAutoRedirect = true;
			hwrFileMetadata.UserAgent = m_strUserAgent;

			FileMetadata fmiInfo = null;
			try
			{
				using (HttpWebResponse wrpFileMetadata = (HttpWebResponse)hwrFileMetadata.GetResponse())
				{
					if ((wrpFileMetadata.StatusCode == HttpStatusCode.OK) || (wrpFileMetadata.StatusCode == HttpStatusCode.PartialContent))
						fmiInfo = new FileMetadata(wrpFileMetadata.Headers);
				}
			}
			catch (WebException e)
			{
				using (HttpWebResponse wrpDownload = (HttpWebResponse)e.Response)
				{
					if (wrpDownload != null)
						switch (wrpDownload.StatusCode)
						{
							case HttpStatusCode.ServiceUnavailable:
								fmiInfo = new FileMetadata(e.Response.Headers);
								break;
							case HttpStatusCode.NotFound:
								fmiInfo = new FileMetadata();
								fmiInfo.NotFound = true;
								break;
						}
				}
			}
			if (fmiInfo == null)
				fmiInfo = new FileMetadata();
			if (String.IsNullOrEmpty(fmiInfo.SuggestedFileName))
				fmiInfo.SuggestedFileName = Uri.UnescapeDataString(m_uriURL.Segments[m_uriURL.Segments.Length - 1]);
			return fmiInfo;
		}
		/// <summary>
		/// Sets up the initial values of the downloader.
		/// </summary>
		/// <param name="p_strSavePath">The path to which to save the file.
		/// If <paramref name="p_booUseDefaultFileName"/> is <c>false</c>, this value should be a complete
		/// path, including filename. If <paramref name="p_booUseDefaultFileName"/> is <c>true</c>,
		/// this value should be the directory in which to save the file.</param>
		/// <param name="p_booUseDefaultFileName">Whether to use the file name suggested by the server.</param>
		private void Initialize(string p_strSavePath, bool p_booUseDefaultFileName)
		{
			m_fmdInfo = GetMetadata();

			string strFilename = p_booUseDefaultFileName ? m_fmdInfo.SuggestedFileName : Path.GetFileName(p_strSavePath);

			strFilename = Uri.UnescapeDataString(strFilename);

			foreach (char chrInvalid in Path.GetInvalidFileNameChars())
				strFilename = strFilename.Replace(chrInvalid, '_');
			p_strSavePath = Path.Combine(p_strSavePath, strFilename);

			m_strSavePath = p_strSavePath + ".partial";
			m_strFileMetadataPath = p_strSavePath + ".parts";

			if (!m_fmdInfo.SupportsResume)
			{
				File.Delete(m_strFileMetadataPath);
				File.Delete(m_strSavePath);
			}

			//get the list of ranges we have already downloaded
			RangeSet rgsRanges = new RangeSet();
			if (File.Exists(m_strFileMetadataPath))
			{
				string[] strRanges = File.ReadAllLines(m_strFileMetadataPath);
				foreach (string strRange in strRanges)
				{
					string strCleanRange = strRange.Trim().Trim('\0');
					if (String.IsNullOrEmpty(strCleanRange))
						continue;
					rgsRanges.AddRange(Range.Parse(strCleanRange));
				}
			}
			m_intInitialByteCount = rgsRanges.TotalSize;
			m_intInitialDownloadedByteCount = rgsRanges.TotalSize / 1024;
		}