/// <summary>
        /// Called when a new request commences (but after authentication).
        /// Preloads the request header and initialises the form stream.
        /// 
        /// We do this after authentication so that the file processor will
        /// have access to the security context if it is required.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event args.</param>
        void Context_AuthenticateRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            HttpWorkerRequest worker = GetWorkerRequest(app.Context);
            int bufferSize;
            string boundary;
            string ct;
            bool statusPersisted = false;

            UploadManager.Instance.ModuleInstalled = true;

            bufferSize = UploadManager.Instance.BufferSize;

            ct = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);

            // Is this a multi-part form which may contain file uploads?
            if (ct != null && string.Compare(ct, 0, C_MARKER, 0, C_MARKER.Length, true, CultureInfo.InvariantCulture) == 0)
            {
                // Get the content length from the header. Don't use Request.ContentLength as this is cached
                // and we don't want it to be calculated until we're done stripping out the files.
                long length = long.Parse(worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));

                if (length > 0)
                {
                    InitStatus(length);

                    boundary = "--" + ct.Substring(ct.IndexOf(B_MARKER) + B_MARKER.Length);

                    using (FormStream fs = new FormStream(GetProcessor(), boundary, app.Request.ContentEncoding))
                    {
                        // Set up events
                        fs.FileCompleted += new FileEventHandler(fs_FileCompleted);
                        fs.FileCompletedError += new FileErrorEventHandler(fs_FileCompletedError);
                        fs.FileStarted += new FileEventHandler(fs_FileStarted);

                        byte[] data = null;
                        int read = 0;
                        int counter = 0;

                        if (worker.GetPreloadedEntityBodyLength() > 0)
                        {
                            // Read the first portion of data from the client
                            data = worker.GetPreloadedEntityBody();

                            fs.Write(data, 0, data.Length);

                            if (!String.IsNullOrEmpty(fs.StatusKey))
                            {
                                if (!statusPersisted) PersistStatus(fs.StatusKey, length, app, worker);
                                statusPersisted = true;

                                _status.UpdateBytes(data.Length, fs.Processor.GetFileName(), fs.Processor.GetIdentifier());
                            }

                            counter = data.Length;
                        }

                        bool disconnected = false;

                        // Read data
                        while (counter < length && worker.IsClientConnected() && !disconnected)
                        {
                            // Let other threads work
                            System.Threading.Thread.Sleep(0);

                            if (counter + bufferSize > length)
                            {
                                bufferSize = (int)length - counter;
                            }

                            data = new byte[bufferSize];
                            read = worker.ReadEntityBody(data, bufferSize);

                            if (read > 0)
                            {
                                counter += read;
                                fs.Write(data, 0, read);

                                if (!String.IsNullOrEmpty(fs.StatusKey))
                                {
                                    if (!statusPersisted) PersistStatus(fs.StatusKey, length, app, worker);
                                    statusPersisted = true;
                                    _status.UpdateBytes(counter, fs.Processor.GetFileName(), fs.Processor.GetIdentifier());
                                }
                            }
                            else
                            {
                                disconnected = true;
                            }
                        }

                        if (!worker.IsClientConnected() || disconnected)
                        {
                            app.Context.Response.End();
                            return;
                        }

                        if (fs.ContentMinusFiles != null)
                        {
                            BindingFlags ba = BindingFlags.Instance | BindingFlags.NonPublic;

                            // Replace the worker process with our own version using reflection
                            UploadWorkerRequest wr = new UploadWorkerRequest(worker, fs.ContentMinusFiles);
                            app.Context.Request.GetType().GetField("_wr", ba).SetValue(app.Context.Request, wr);
                        }

                        // Check that the query key is in the request
                        app.Context.Items[UploadManager.STATUS_KEY] = fs.StatusKey;
                    }
                }

            }
        }
        /// <summary>
        /// Called when a new request commences (but after authentication).
        /// Preloads the request header and initialises the form stream.
        ///
        /// We do this after authentication so that the file processor will
        /// have access to the security context if it is required.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event args.</param>
        void Context_AuthenticateRequest(object sender, EventArgs e)
        {
            HttpApplication   app    = sender as HttpApplication;
            HttpWorkerRequest worker = GetWorkerRequest(app.Context);
            int    bufferSize;
            string boundary;
            string ct;
            bool   statusPersisted = false;

            UploadManager.Instance.ModuleInstalled = true;

            bufferSize = UploadManager.Instance.BufferSize;

            ct = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);

            // Is this a multi-part form which may contain file uploads?
            if (ct != null && string.Compare(ct, 0, C_MARKER, 0, C_MARKER.Length, true, CultureInfo.InvariantCulture) == 0)
            {
                // Get the content length from the header. Don't use Request.ContentLength as this is cached
                // and we don't want it to be calculated until we're done stripping out the files.
                long length = long.Parse(worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));

                if (length > 0)
                {
                    InitStatus(length);

                    boundary = "--" + ct.Substring(ct.IndexOf(B_MARKER) + B_MARKER.Length);

                    using (FormStream fs = new FormStream(GetProcessor(), boundary, app.Request.ContentEncoding))
                    {
                        // Set up events
                        fs.FileCompleted      += new FileEventHandler(fs_FileCompleted);
                        fs.FileCompletedError += new FileErrorEventHandler(fs_FileCompletedError);
                        fs.FileStarted        += new FileEventHandler(fs_FileStarted);

                        byte[] data    = null;
                        int    read    = 0;
                        int    counter = 0;

                        if (worker.GetPreloadedEntityBodyLength() > 0)
                        {
                            // Read the first portion of data from the client
                            data = worker.GetPreloadedEntityBody();

                            fs.Write(data, 0, data.Length);

                            if (!String.IsNullOrEmpty(fs.StatusKey))
                            {
                                if (!statusPersisted)
                                {
                                    PersistStatus(fs.StatusKey, length, app, worker);
                                }
                                statusPersisted = true;

                                _status.UpdateBytes(data.Length, fs.Processor.GetFileName(), fs.Processor.GetIdentifier());
                            }

                            counter = data.Length;
                        }

                        bool disconnected = false;

                        // Read data
                        while (counter < length && worker.IsClientConnected() && !disconnected)
                        {
                            // Let other threads work
                            System.Threading.Thread.Sleep(0);

                            if (counter + bufferSize > length)
                            {
                                bufferSize = (int)length - counter;
                            }

                            data = new byte[bufferSize];
                            read = worker.ReadEntityBody(data, bufferSize);

                            if (read > 0)
                            {
                                counter += read;
                                fs.Write(data, 0, read);

                                if (!String.IsNullOrEmpty(fs.StatusKey))
                                {
                                    if (!statusPersisted)
                                    {
                                        PersistStatus(fs.StatusKey, length, app, worker);
                                    }
                                    statusPersisted = true;
                                    _status.UpdateBytes(counter, fs.Processor.GetFileName(), fs.Processor.GetIdentifier());
                                }
                            }
                            else
                            {
                                disconnected = true;
                            }
                        }

                        if (!worker.IsClientConnected() || disconnected)
                        {
                            app.Context.Response.End();
                            return;
                        }

                        if (fs.ContentMinusFiles != null)
                        {
                            BindingFlags ba = BindingFlags.Instance | BindingFlags.NonPublic;

                            // Replace the worker process with our own version using reflection
                            UploadWorkerRequest wr = new UploadWorkerRequest(worker, fs.ContentMinusFiles);
                            app.Context.Request.GetType().GetField("_wr", ba).SetValue(app.Context.Request, wr);
                        }

                        // Check that the query key is in the request
                        app.Context.Items[UploadManager.STATUS_KEY] = fs.StatusKey;
                    }
                }
            }
        }