public override void SendResponse( System.Web.HttpResponse response )
        {
            this.CheckConnector();

            try
            {
                this.CheckRequest();
            }
            catch ( ConnectorException connectorException )
            {
                response.AddHeader( "X-CKFinder-Error", ( connectorException.Number ).ToString() );
                response.StatusCode = 403;
                response.End();
                return;
            }
            catch
            {
                response.AddHeader( "X-CKFinder-Error", ( (int)Errors.Unknown ).ToString() );
                response.StatusCode = 403;
                response.End();
                return;
            }

            if ( !Config.Current.Thumbnails.Enabled )
            {
                response.AddHeader( "X-CKFinder-Error", ((int)Errors.ThumbnailsDisabled).ToString() );
                response.StatusCode = 403;
                response.End();
                return;
            }

            if ( !this.CurrentFolder.CheckAcl( AccessControlRules.FileView ) )
            {
                response.AddHeader( "X-CKFinder-Error", ( (int)Errors.Unauthorized ).ToString() );
                response.StatusCode = 403;
                response.End();
                return;
            }

            bool is304 = false;

            string fileName = HttpContext.Current.Request[ "FileName" ];

            string thumbFilePath = System.IO.Path.Combine( this.CurrentFolder.ThumbsServerPath, fileName );

            if ( !Connector.CheckFileName( fileName ) )
            {
                response.AddHeader( "X-CKFinder-Error", ( (int)Errors.InvalidRequest ).ToString() );
                response.StatusCode = 403;
                response.End();
                return;
            }

            if ( Config.Current.CheckIsHiddenFile( fileName ) )
            {
                response.AddHeader( "X-CKFinder-Error", ( (int)Errors.FileNotFound ).ToString() + " - Hidden folder" );
                response.StatusCode = 404;
                response.End();
                return;
            }

            // If the thumbnail file doesn't exists, create it now.
            if ( !Achilles.Acme.Storage.IO.File.Exists( thumbFilePath ) )
            {
                string sourceFilePath = System.IO.Path.Combine( this.CurrentFolder.ServerPath, fileName );

                if ( !Achilles.Acme.Storage.IO.File.Exists( sourceFilePath ) )
                {
                    response.AddHeader( "X-CKFinder-Error", ( (int)Errors.FileNotFound ).ToString() );
                    response.StatusCode = 404;
                    response.End();
                    return;
                }

                // TJT: Utilize Stream IO here
                ImageTools.ResizeImage( sourceFilePath, thumbFilePath, Config.Current.Thumbnails.MaxWidth, Config.Current.Thumbnails.MaxHeight, true, Config.Current.Thumbnails.Quality );
            }

            Achilles.Acme.Storage.IO.FileInfo thumbfile = new Achilles.Acme.Storage.IO.FileInfo( thumbFilePath ) ;

            string eTag = thumbfile.LastWriteTime.Ticks.ToString( "X" ) + "-" + thumbfile.Length.ToString( "X" );

            string chachedETag = Request.ServerVariables[ "HTTP_IF_NONE_MATCH" ];
            if ( chachedETag != null && chachedETag.Length > 0 && eTag == chachedETag )
            {
                is304 = true ;
            }

            if ( !is304 )
            {
                string cachedTimeStr = Request.ServerVariables[ "HTTP_IF_MODIFIED_SINCE" ];
                if ( cachedTimeStr != null && cachedTimeStr.Length > 0 )
                {
                    try
                    {
                        DateTime cachedTime = DateTime.Parse( cachedTimeStr );

                        if ( cachedTime >= thumbfile.LastWriteTime )
                            is304 = true;
                    }
                    catch
                    {
                        is304 = false;
                    }
                }
            }

            if ( is304 )
            {
                response.StatusCode = 304;
                response.End();
                return;
            }

            string thumbFileExt = System.IO.Path.GetExtension( thumbFilePath ).TrimStart( '.' ).ToLower() ;

            if ( thumbFilePath == ".jpg" )
                response.ContentType = "image/jpeg";
            else
                response.ContentType = "image/" + thumbFileExt;

            response.Cache.SetETag( eTag );
            response.Cache.SetLastModified( thumbfile.LastWriteTime );
            response.Cache.SetCacheability( HttpCacheability.Private );

            // TJT: We need to access the file stream and read the contents into memory
            System.IO.Stream thumbStream = Achilles.Acme.Storage.IO.File.OpenRead( thumbFilePath );

            int bufferSize = (int)thumbStream.Length;
            if ( bufferSize > 0 )
            {
                byte[] buffer = new byte[bufferSize];
                int count = thumbStream.Read( buffer, 0, bufferSize );

                response.BinaryWrite( buffer );
            }
        }
        protected override void BuildXml()
        {
            if ( Request.Form["CKFinderCommand"] != "true" )
            {
                ConnectorException.Throw( Errors.InvalidRequest );
            }

            if ( !this.CurrentFolder.CheckAcl( AccessControlRules.FileRename | AccessControlRules.FileUpload | AccessControlRules.FileDelete ) )
            {
                ConnectorException.Throw( Errors.Unauthorized );
            }

            if ( Request.Form["files[0][type]"] == null )
            {
                ConnectorException.Throw( Errors.InvalidRequest );
            }

            int moved = 0;
            int movedAll = 0;
            if ( Request.Form["moved"] != null )
            {
                movedAll = Int32.Parse( Request.Form["moved"] );
            }
            Settings.ResourceType resourceType;
            Hashtable resourceTypeConfig = new Hashtable();
            Hashtable checkedPaths = new Hashtable();

            int iFileNum = 0;
            while ( Request.Form["files[" + iFileNum.ToString() + "][type]"] != null && Request.Form["files[" + iFileNum.ToString() + "][type]"].Length > 0 )
            {
                string name = Request.Form["files[" + iFileNum.ToString() + "][name]"];
                string type = Request.Form["files[" + iFileNum.ToString() + "][type]"];
                string path = Request.Form["files[" + iFileNum.ToString() + "][folder]"];
                string options = "";

                if ( name == null || name.Length < 1 || type == null || type.Length < 1 || path == null || path.Length < 1 )
                {
                    ConnectorException.Throw( Errors.InvalidRequest );
                    return;
                }

                if ( Request.Form["files[" + iFileNum.ToString() + "][options]"] != null )
                {
                    options = Request.Form["files[" + iFileNum.ToString() + "][options]"];
                }
                iFileNum++;

                // check #1 (path)
                if ( !Connector.CheckFileName( name ) || Regex.IsMatch( path, @"(/\.)|(\.\.)|(//)|([\\:\*\?""\<\>\|])" ) )
                {
                    ConnectorException.Throw( Errors.InvalidRequest );
                    return;
                }

                // get resource type config for current file
                if ( !resourceTypeConfig.ContainsKey( type ) )
                {
                    resourceTypeConfig[type] = Config.Current.GetResourceTypeConfig( type );
                }

                // check #2 (resource type)
                if ( resourceTypeConfig[type] == null )
                {
                    ConnectorException.Throw( Errors.InvalidRequest );
                    return;
                }

                resourceType = (Settings.ResourceType)resourceTypeConfig[type];
                FolderHandler folder = new FolderHandler( type, path );
                string sourceFilePath = System.IO.Path.Combine( folder.ServerPath, name );

                // check #3 (extension)
                if ( !resourceType.CheckExtension( System.IO.Path.GetExtension( name ) ) )
                {
                    this.appendErrorNode( Errors.InvalidExtension, name, type, path );
                    continue;
                }

                // check #4 (extension) - when moving to another resource type, double check extension
                if ( this.CurrentFolder.ResourceTypeName != type )
                {
                    if ( !this.CurrentFolder.ResourceTypeInfo.CheckExtension( System.IO.Path.GetExtension( name ) ) )
                    {
                        this.appendErrorNode( Errors.InvalidExtension, name, type, path );
                        continue;
                    }
                }

                // check #5 (hidden folders)
                if ( !checkedPaths.ContainsKey( path ) )
                {
                    checkedPaths[path] = true;
                    if ( Config.Current.CheckIsHidenPath( path ) )
                    {
                        ConnectorException.Throw( Errors.InvalidRequest );
                        return;
                    }
                }

                // check #6 (hidden file name)
                if ( Config.Current.CheckIsHiddenFile( name ) )
                {
                    ConnectorException.Throw( Errors.InvalidRequest );
                    return;
                }

                // check #7 (Access Control, need file view permission to source files)
                if ( !folder.CheckAcl( AccessControlRules.FileView ) )
                {
                    ConnectorException.Throw( Errors.Unauthorized );
                    return;
                }

                // check #8 (invalid file name)
                if ( !Achilles.Acme.Storage.IO.File.Exists( sourceFilePath ) || Achilles.Acme.Storage.IO.Directory.Exists( sourceFilePath ) )
                {
                    this.appendErrorNode( Errors.FileNotFound, name, type, path );
                    continue;
                }

                // check #9 (max size)
                if ( this.CurrentFolder.ResourceTypeName != type )
                {
                    Achilles.Acme.Storage.IO.FileInfo fileInfo = new Achilles.Acme.Storage.IO.FileInfo( sourceFilePath );
                    if ( this.CurrentFolder.ResourceTypeInfo.MaxSize > 0 && fileInfo.Length > this.CurrentFolder.ResourceTypeInfo.MaxSize )
                    {
                        this.appendErrorNode( Errors.UploadedTooBig, name, type, path );
                        continue;
                    }
                }

                string destinationFilePath = System.IO.Path.Combine( this.CurrentFolder.ServerPath, name );

                // finally, no errors so far, we may attempt to copy a file
                // protection against copying files to itself
                if ( sourceFilePath == destinationFilePath )
                {
                    this.appendErrorNode( Errors.SourceAndTargetPathEqual, name, type, path );
                    continue;
                }
                // check if file exists if we don't force overwriting
                else if ( Achilles.Acme.Storage.IO.File.Exists( destinationFilePath ) )
                {
                    if ( options.Contains( "overwrite" ) )
                    {
                        try
                        {
                            Achilles.Acme.Storage.IO.File.Delete( destinationFilePath );
                        }
                        catch ( Exception )
                        {
                            this.appendErrorNode( Errors.AccessDenied, name, type, path );
                            continue;
                        }
                        try
                        {
                            Achilles.Acme.Storage.IO.File.Move( sourceFilePath, destinationFilePath );
                            moved++;
                        }
                        catch ( Exception )
                        {
                            this.appendErrorNode( Errors.AccessDenied, name, type, path );
                            continue;
                        }
                    }
                    else if ( options.Contains( "autorename" ) )
                    {
                        int iCounter = 1;
                        string fileName;
                        string sFileNameNoExt = System.IO.Path.GetFileNameWithoutExtension( name );
                        while ( true )
                        {
                            fileName = sFileNameNoExt + "(" + iCounter.ToString() + ")" + System.IO.Path.GetExtension( name );
                            destinationFilePath = System.IO.Path.Combine( this.CurrentFolder.ServerPath, fileName );
                            if ( !Achilles.Acme.Storage.IO.File.Exists( destinationFilePath ) )
                                break;
                            else
                                iCounter++;
                        }
                        try
                        {
                            Achilles.Acme.Storage.IO.File.Move( sourceFilePath, destinationFilePath );
                            moved++;
                        }
                        catch ( ArgumentException )
                        {
                            this.appendErrorNode( Errors.InvalidName, name, type, path );
                            continue;
                        }
                        catch ( System.IO.PathTooLongException )
                        {
                            this.appendErrorNode( Errors.InvalidName, name, type, path );
                            continue;
                        }
                        catch ( Exception )
                        {
            #if DEBUG
                            throw;
            #else
                            this.appendErrorNode( Errors.AccessDenied, name, type, path );
                            continue;
            #endif
                        }
                    }
                    else
                    {
                        this.appendErrorNode( Errors.AlreadyExist, name, type, path );
                        continue;
                    }
                }
                else
                {
                    try
                    {
                        Achilles.Acme.Storage.IO.File.Move( sourceFilePath, destinationFilePath );
                        moved++;
                    }
                    catch ( ArgumentException )
                    {
                        this.appendErrorNode( Errors.InvalidName, name, type, path );
                        continue;
                    }
                    catch ( System.IO.PathTooLongException )
                    {
                        this.appendErrorNode( Errors.InvalidName, name, type, path );
                        continue;
                    }
                    catch ( Exception )
                    {
            #if DEBUG
                            throw;
            #else
                        this.appendErrorNode( Errors.AccessDenied, name, type, path );
                        continue;
            #endif
                    }
                }
            }

            XmlNode moveFilesNode = XmlUtil.AppendElement( this.ConnectorNode, "MoveFiles" );
            XmlUtil.SetAttribute( moveFilesNode, "moved", moved.ToString() );
            XmlUtil.SetAttribute( moveFilesNode, "movedTotal", ( movedAll + moved ).ToString() );

            if ( this.ErrorsNode != null )
            {
                ConnectorException.Throw( Errors.MoveFailed );
                return;
            }
        }