Mega Code Archive

 
Categories / Delphi / LAN Web TCP
 

FTP Server

Title: FTP Server Question: IMplement an FTP server using INDY FTP Answer: unit FTP; interface uses Classes, windows, sysutils, IdFTPList, IdFTPServer, idtcpserver, IdSocketHandle, idglobal, IdHashCRC, ValLogonW2000, Registry; type TSystemasFTP = (ftpsOther, ftpsDOS, ftpsUNIX, ftpsVAX); TServidorFTP = class private { Private declarations } IdFTPServer: tIdFTPServer; Directorio: String; procedure IdFTPServer1UserLogin( ASender: TIdFTPServerThread; const AUsername, APassword: string; var AAuthenticated: Boolean ) ; procedure IdFTPServer1ListDirectory( ASender: TIdFTPServerThread; const APath: string; ADirectoryListing: TIdFTPListItems ) ; procedure IdFTPServer1RenameFile( ASender: TIdFTPServerThread; const ARenameFromFile, ARenameToFile: string ) ; procedure IdFTPServer1RetrieveFile( ASender: TIdFTPServerThread; const AFilename: string; var VStream: TStream ) ; procedure IdFTPServer1StoreFile( ASender: TIdFTPServerThread; const AFilename: string; AAppend: Boolean; var VStream: TStream ) ; procedure IdFTPServer1RemoveDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ; procedure IdFTPServer1MakeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ; procedure IdFTPServer1GetFileSize( ASender: TIdFTPServerThread; const AFilename: string; var VFileSize: Int64 ) ; procedure IdFTPServer1DeleteFile( ASender: TIdFTPServerThread; const APathname: string ) ; procedure IdFTPServer1ChangeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ; procedure IdFTPServer1CommandXCRC( ASender: TIdCommand ) ; procedure IdFTPServer1DisConnect( AThread: TIdPeerThread ) ; protected function TransLatePath( const APathname, homeDir: string ) : string; public constructor Create(_Directorio:String;_Anonimos: Boolean;_Sistema: TIdFTPSystems); reintroduce; destructor Destroy; override; end; implementation constructor TServidorFTP.Create(_Directorio:String;_Anonimos: Boolean;_Sistema: TIdFTPSystems); begin IdFTPServer := tIdFTPServer.create(nil); Directorio:= _Directorio; if Directorio[Length(Directorio)]='\' then Directorio:= _Directorio else Directorio:= _Directorio+'\'; IdFTPServer.DefaultPort := 21; IdFTPServer.AllowAnonymousLogin := _Anonimos; IdFTPServer.EmulateSystem := _Sistema; IdFTPServer.HelpReply.text := 'La ayuda no esta implementada.'; IdFTPServer.OnChangeDirectory := IdFTPServer1ChangeDirectory; IdFTPServer.OnChangeDirectory := IdFTPServer1ChangeDirectory; IdFTPServer.OnGetFileSize := IdFTPServer1GetFileSize; IdFTPServer.OnListDirectory := IdFTPServer1ListDirectory; IdFTPServer.OnUserLogin := IdFTPServer1UserLogin; IdFTPServer.OnRenameFile := IdFTPServer1RenameFile; IdFTPServer.OnDeleteFile := IdFTPServer1DeleteFile; IdFTPServer.OnRetrieveFile := IdFTPServer1RetrieveFile; IdFTPServer.OnStoreFile := IdFTPServer1StoreFile; IdFTPServer.OnMakeDirectory := IdFTPServer1MakeDirectory; IdFTPServer.OnRemoveDirectory := IdFTPServer1RemoveDirectory; IdFTPServer.Greeting.NumericCode := 220; IdFTPServer.OnDisconnect := IdFTPServer1DisConnect; IdFTPServer.Greeting.Text.Text:= 'Servidor Ftp '+IdFTPServer.LocalName; with IdFTPServer.CommandHandlers.add do begin Command := 'XCRC'; OnCommand := IdFTPServer1CommandXCRC; end; IdFTPServer.Active := true; end; function CalculateCRC( const path: string ) : string; var f: tfilestream; value: dword; IdHashCRC32: TIdHashCRC32; begin IdHashCRC32 := nil; f := nil; try IdHashCRC32 := TIdHashCRC32.create; f := TFileStream.create( path, fmOpenRead or fmShareDenyWrite ) ; value := IdHashCRC32.HashValue( f ) ; result := inttohex( value, 8 ) ; finally f.free; IdHashCRC32.free; end; end; procedure TServidorFTP.IdFTPServer1CommandXCRC( ASender: TIdCommand ) ; var s: string; begin with TIdFTPServerThread( ASender.Thread ) do begin if Authenticated then begin try s := ProcessPath( CurrentDir, ASender.UnparsedParams ) ; s := TransLatePath( s, TIdFTPServerThread( ASender.Thread ) .HomeDir ) ; ASender.Reply.SetReply( 213, CalculateCRC( s ) ) ; except ASender.Reply.SetReply( 500, 'error de fichero' ) ; end; end; end; end; destructor TServidorFTP.Destroy; begin IdFTPServer.free; inherited destroy; end; function StartsWith( const str, substr: string ) : boolean; begin result := copy( str, 1, length( substr ) ) = substr; end; function BackSlashToSlash( const str: string ) : string; var a: dword; begin result := str; for a := 1 to length( result ) do if result[a] = '\' then result[a] := '/'; end; function SlashToBackSlash( const str: string ) : string; var a: dword; begin result := str; for a := 1 to length( result ) do if result[a] = '/' then result[a] := '\'; end; function TServidorFTP.TransLatePath( const APathname, homeDir: string ) : string; var tmppath: string; begin result := SlashToBackSlash( homeDir ) ; tmppath := SlashToBackSlash( APathname ) ; if homedir = '/' then begin result := tmppath; exit; end; if length( APathname ) = 0 then exit; if result[length( result ) ] = '\' then result := copy( result, 1, length( result ) - 1 ) ; if tmppath[1] '\' then result := result + '\'; result := result + tmppath; end; function GetSizeOfFile( const APathname: string ) : int64; begin result := FileSizeByName( APathname ) ; end; function GetNewDirectory( old, action: string ) : string; var a: integer; begin if action = '../' then begin if old = '/' then begin result := old; exit; end; a := length( old ) - 1; while ( old[a] '\' ) and ( old[a] '/' ) do dec( a ) ; result := copy( old, 1, a ) ; exit; end; if ( action[1] = '/' ) or ( action[1] = '\' ) then result := action else result := old + action; end; procedure TServidorFTP.IdFTPServer1UserLogin( ASender: TIdFTPServerThread; const AUsername, APassword: string; var AAuthenticated: Boolean ) ; function GetNTDomainName: string; var hReg: TRegistry; begin hReg := TRegistry.Create; hReg.RootKey := HKEY_LOCAL_MACHINE; hReg.OpenKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon', false ); Result := hReg.ReadString( 'DefaultDomainName' ); hReg.CloseKey; hReg.Destroy; end; begin AAuthenticated := LogonUserSSPI(AUsername,GetNTDomainName,APassword) ; if not AAuthenticated then exit; ASender.HomeDir := Directorio; asender.currentdir := Directorio; end; procedure TServidorFTP.IdFTPServer1ListDirectory( ASender: TIdFTPServerThread; const APath: string; ADirectoryListing: TIdFTPListItems ) ; procedure AddlistItem( aDirectoryListing: TIdFTPListItems; Filename: string; ItemType: TIdDirItemType; size: int64; date: tdatetime ) ; var listitem: TIdFTPListItem; begin listitem := aDirectoryListing.Add; listitem.ItemType := ItemType; listitem.FileName := Filename; listitem.OwnerName := ASender.Username; listitem.GroupName := 'all'; listitem.OwnerPermissions := '---'; listitem.GroupPermissions := '---'; listitem.UserPermissions := '---'; listitem.Size := size; listitem.ModifiedDate := date; end; var f: tsearchrec; a: integer; begin ADirectoryListing.DirectoryName := apath; a := FindFirst( TransLatePath( apath, ASender.HomeDir ) + '*.*', faAnyFile, f ) ; while ( a = 0 ) do begin if ( f.Attr and faDirectory 0 ) then AddlistItem( ADirectoryListing, f.Name, ditDirectory, f.size, FileDateToDateTime( f.Time ) ) else AddlistItem( ADirectoryListing, f.Name, ditFile, f.size, FileDateToDateTime( f.Time ) ) ; a := FindNext( f ) ; end; FindClose( f ) ; end; procedure TServidorFTP.IdFTPServer1RenameFile( ASender: TIdFTPServerThread; const ARenameFromFile, ARenameToFile: string ) ; begin if not MoveFile( pchar( TransLatePath( ARenameFromFile, ASender.HomeDir ) ) , pchar( TransLatePath( ARenameToFile, ASender.HomeDir ) ) ) then RaiseLastWin32Error; end; procedure TServidorFTP.IdFTPServer1RetrieveFile( ASender: TIdFTPServerThread; const AFilename: string; var VStream: TStream ) ; begin VStream := TFileStream.create( translatepath( AFilename, ASender.HomeDir ) , fmopenread or fmShareDenyWrite ) ; end; procedure TServidorFTP.IdFTPServer1StoreFile( ASender: TIdFTPServerThread; const AFilename: string; AAppend: Boolean; var VStream: TStream ) ; begin if FileExists( translatepath( AFilename, ASender.HomeDir ) ) and AAppend then begin VStream := TFileStream.create( translatepath( AFilename, ASender.HomeDir ) , fmOpenWrite or fmShareExclusive ) ; VStream.Seek( 0, soFromEnd ) ; end else VStream := TFileStream.create( translatepath( AFilename, ASender.HomeDir ) , fmCreate or fmShareExclusive ) ; end; procedure TServidorFTP.IdFTPServer1RemoveDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ; begin RmDir( TransLatePath( VDirectory, ASender.HomeDir ) ) ; end; procedure TServidorFTP.IdFTPServer1MakeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ; begin MkDir( TransLatePath( VDirectory, ASender.HomeDir ) ) ; end; procedure TServidorFTP.IdFTPServer1GetFileSize( ASender: TIdFTPServerThread; const AFilename: string; var VFileSize: Int64 ) ; begin VFileSize := GetSizeOfFile( TransLatePath( AFilename, ASender.HomeDir ) ) ; end; procedure TServidorFTP.IdFTPServer1DeleteFile( ASender: TIdFTPServerThread; const APathname: string ) ; begin DeleteFile( pchar( TransLatePath( ASender.CurrentDir + '/' + APathname, ASender.HomeDir ) ) ) ; end; procedure TServidorFTP.IdFTPServer1ChangeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ; begin VDirectory := GetNewDirectory( ASender.CurrentDir, VDirectory ) ; end; procedure TServidorFTP.IdFTPServer1DisConnect( AThread: TIdPeerThread ) ; begin //** end; end.