Советы по Delphi




FTP4W32.DLL и Delphi 2.0


Вот модуль, который у меня работает. Сейчас я работаю над компонентом, инкапсулирующим данную DLL. Если кто хочет потестировать данный код, направьте мне письмо по адресу bstowers@pobox.com и я вышлю Вам демонстрационный проект.

    unit FTP4W;
{ Обновлено в феврале 1997 Брадом Стоверсом (Brad Stowers               }
{ bstowers@pobox.com) для использования с FTP4W v2.6.                   }
{ Добавлены новые функции, исправлены некоторые ошибки, включен         }
{ "cleaner (стиратель)" и переделано для работы c Delphi 2. Т.к. я      }
{ уже не использую Delphi 1, существует большая вероятность, что данный }
{ модуль не сможет быть откомпилен в Delphi 1, например, из-за наличия  }
{ директивы 'stdcall'. В паскалевском файле-оболочке 'UseFTP4W.pas'     }
{ Delphi 1 удалил все директивы 'stdcall'. Данный код основан на на     }
{ разработках следующих людей:                                          }

{ Barbara Tikart Polarwolf Hard & Software, D-63906 Erlenbach am Main   }
{ и AStA Uni Konstanz (AStA = Allgemeiner Studierenden Ausschuss)       }
{ eMail для Andreas.Tikart@uni-konstanz.de или AStA@uni-konstanz.de     }
{ Требования к FTP: 'FTP4W' версии 2.2g или выше                        }
{ Предназначено для свободного распространения                          }
{ Последняя версия модуля доступна по адресу                            }
{ http://www.uni-konstanz.de/studis/asta/software/index.html            }


interface

uses
Windows, WinSock, SysUtils;


const
FTP4W_Loaded: boolean = FALSE;        { Проверка загруженности DLL        } FTP4W_RightVersion: boolean = FALSE;  { Проверка корректности версии DLL. }

const
{ Режим передачи. }
TYPE_A       = 'A'; { ASCII } TYPE_I       = 'I'; { Изображение (Двоичный) } TYPE_L8      = 'L'; { Локальная 8 } TYPE_DEFAULT = #0;  { Значение по умолчанию для сервера. }
{ Зарегистрированные действия пользователя.... Какими они могут быть? }
FTP_STORE_ON_SERVER  = 65; FTP_APPEND_ON_SERVER = 87; FTP_GET_FROM_SERVER  = 223;
{ Возможный тип брэндмауэра. }
FTP4W_FWSITE          = 100; FTP4W_FWPROXY         = 103; FTP4W_FWUSERWITHLOGON = 106; FTP4W_FWUSERNOLOGON   = 109;
{ Коды, возвращаемые FTP-функциями }
FTPERR_OK            = 0; { успешное завершение функции                              } FTPERR_ENTERPASSWORD = 1; { требуется пароль для userid                              } FTPERR_ENTERACCOUNT  = 2; { user/pass OK, но требуется бюджет пользователя (account) } FTPERR_ACCOUNTNEEDED = 2; { user/pass OK, но требуется бюджет пользователя (account) } FTPERR_RESTARTOK     = 3; { успешная команда перезапуска                             } FTPERR_ENDOFDATA     = 4; { сервер закончил передачу данных                          } FTPERR_CANCELBYUSER = -1; { передача данных прервана пользователем (FtpAbort)        }

{ Ошибки пользователя или программиста }
FTPERR_INVALIDPARAMETER    = 1000; { Ошибка в параметрах } FTPERR_SESSIONUSED         = 1001; { Пользователь уже имеет сеанс FTP } FTPERR_NOTINITIALIZED      = 1002; { Отсутствует инициализация (не вызван FtpInit) } FTPERR_NOTCONNECTED        = 1003; { Пользователь не подключен к серверу } FTPERR_CANTOPENFILE        = 1004; { невозможно открыть определенный файл } FTPERR_CANTWRITE           = 1005; { невозможно передать файл (переполнен диск?) } FTPERR_NOACTIVESESSION     = 1006; { FtpRelease без FtpInit } FTPERR_STILLCONNECTED      = 1007; { FtpRelease без какого-либо Close } FTPERR_SERVERCANTEXECUTE   = 1008; { неудачное действие с файлом } FTPERR_LOGINREFUSED        = 1009; { Сервер отверг usrid/passwd } FTPERR_NOREMOTEFILE        = 1010; { сервер не может открыть файл } FTPERR_TRANSFERREFUSED     = 1011; { Сервер отклонил передачу } FTPERR_WINSOCKNOTUSABLE    = 1012; { Требуется winsock.DLL версии 1.1 } FTPERR_CANTCLOSE           = 1013; { неудачное закрытие (осуществляетcя cmd) } FTPERR_FILELOCKED          = 1014; { ошибка удаления файла (FtpDelete) } FTPERR_FWLOGINREFUSED      = 1015; { Брэндмауэр отверг usrid/passwd } FTPERR_ASYNCMODE           = 1016; { FtpMGet только в синхронном режиме }
{ Ошибки TCP }
FTPERR_UNKNOWNHOST         = 2001; { сервер по адресу не найден } FTPERR_NOREPLY             = 2002; { сервер не отвечает на запрос } FTPERR_CANTCONNECT         = 2003; { Ошибка во время связи } FTPERR_CONNECTREJECTED     = 2004; { сервер не поддерживает FTP } FTPERR_SENDREFUSED         = 2005; { невозможна передача данных (сеть недоступна) } FTPERR_DATACONNECTION      = 2006; { ошибка связи с портом данных } FTPERR_TIMEOUT             = 2007; { время ожидания истекло } FTPERR_FWCANTCONNECT       = 2008; { Ошибка с брандмауэром в течение сеанса } FTPERR_FWCONNECTREJECTED   = 2009; { Брэндмауэр не поддерживает FTP-соединений }
{ Ошибки FTP }
FTPERR_UNEXPECTEDANSWER    = 3001; { истек срок ожидания ответа } FTPERR_CANNOTCHANGETYPE    = 3002; { сервер отверг команду TYPE } FTPERR_CMDNOTIMPLEMENTED   = 3003; { сервер признал, но не смог осуществить команду } FTPERR_PWDBADFMT           = 3004; { Пароль опознан, но команды не проходят } FTPERR_PASVCMDNOTIMPL      = 3005; { Сервер не поддерживает пассивный режим }
{ Ошибки ресурсов }
FTPERR_CANTCREATEWINDOW    = 5002; { Недостаточно свободных ресурсов } FTPERR_INSMEMORY           = 5003; { Недостаточная куча памяти } FTPERR_CANTCREATESOCKET    = 5004; { нет свободного гнезда (socket) } FTPERR_CANTBINDSOCKET      = 5005; { Неудача связи (bind) } FTPERR_SYSTUNKNOWN         = 5006; { сервер отсутствует в списке }

{ Внутренние структуры данных FTP4W. Но это Вам вряд ли понадобится. }
const
FTP_DATABUFFER = 4096; { хорошая величина для X25/Ethernet/Token Ring}
type
PFtp_FtpData = ^TFtp_FtpData; TFtp_FtpData = packed record ctrl_socket: TSocket;             { управляющий поток    init INVALID_SOCKET }
data_socket: TSocket;             { поток данных         init INVALID_SOCKET }
cType: Char;                      { тип (ASCII/двоичный) init TYPE_A }
bVerbose: Bool;                   { режим избыточности   init FALSE } bPassif: Bool;                    { VRAI -> пассивный режим }
nPort: u_short;                   { порт связи           init FTP_DEFPORT    }
nTimeOut: u_int;                  { TimeOut в секундах   init FTP_DEFTIMEOUT }
hLogFile: HFile;                  { Журнальный файл }
szInBuf: Array [0..2047] of Char; { входной буфер }
saSockAddr: TSockAddrIn;          { никогда не используется }
saAcceptAddr: TSockAddrIn;        { никогда не используется }
end; { TFtp_FtpData }
PFtp_FileTrf = ^TFtp_FileTrf; TFtp_FileTrf = packed record hf: HFile;          { дескриптор передаваемого файла                                   } nCount: uint;       { число записей/считываний блоков файла                            } nAsyncAlone: uint;  { пауза каждого N-го кадра в ассинхронном режиме (по умолчанию 40) } nAsyncMulti: uint;  { Возможное количество FTP-сеансов (по умолчанию 10)               } nDelay: uint;       { время паузы в миллисекундах                                      } bAborted: Bool;     { передача данных была отменена                                    } szBuf : Array [0..FTP_DataBuffer-1] Of Char; { Буфер данных                            } bNotify: Bool;      { приложение получает сообщение с каждым пакетом данных            } bAsyncMode: Bool;   { синхронный или асинхронный режим                                 } lPos: LongInt;      { Передано байтов                                                  } lTotal: LongInt;    { должно быть передано байтов                                      } end; { TFtp_FileTrf }
PFtp_Msg = ^TFtp_Msg; TFtp_MSG = packed record hParentWnd: hWnd;        { окно, которому предназначено сообщение } nCompletedMessage: uint; { сообщение, посланное в конце функции   } end; { TFtp_Msg }
PFtp_Verbose = ^TFtp_Verbose; TFtp_Verbose = packed record hVerboseWnd: hWnd;  { окно, которому предназначено сообщение                  } nVerboseMsg: uint;  { сообщение, посылающееся каждый раз при получении строки } end; { TFtp_Verbose }
PFtp_ProcData = ^TFtp_ProcData; TFtp_ProcData = packed record { Данные задачи } hTask: HTask;              { Идентификатор задачи                       } hFtpWindow: hWnd;          { Дескриптор собственного (внутреннего) окна } hParentWnd: hWnd;          { Дескриптор функции FtpInit                 } hInstance: HInst;          { Экземпляр задачи                           } bRelease:  Bool;           { Для вызова FtpRelease                      } { Информация о сообщении } MSG: TFtp_Msg; VMSG: TFtp_Verbose; { Информация о файле } FileTrf: TFtp_FileTrf; {Ftp-информация} Ftp: TFtp_FtpData; {Список связей} Next, Prev: PFtp_ProcData; end; { TFtp_ProcData }
{ Тип функции обратной связи FtpMGet. }
TFtpMGetCallback = Function (szRemFile, szLocalFile: PChar; Rc: integer): bool; stdcall;


{ FTP4W-функции }

var
{ Вспомогательные функции }
FtpDataPtr:     function: PFtp_ProcData; stdcall; FtpBufferPtr:   function: PChar; stdcall; FtpErrorString: function(Rc: integer): PChar; stdcall; Ftp4wVer:       function(szVerStr: PChar; nStrSize: integer): Integer; stdcall;

{ Изменение параметров по умолчанию }
FtpSetVerboseMode:       function(bVerboseMode: bool; hWindow: hWnd; wMsg: UINT): Integer; stdcall; FtpBytesTransferred:     function: LongInt; stdcall; FtpBytesToBeTransferred: function: LongInt; stdcall; FtpSetDefaultTimeOut:    procedure(nTo_in_sec: Integer); stdcall; FtpSetDefaultPort:       procedure(nDefPort: Integer); stdcall; FtpSetAsynchronousMode:  procedure; stdcall; FtpSetSynchronousMode:   procedure; stdcall; FtpIsAsynchronousMode:   function: Bool; stdcall; FtpSetNewDelay:          procedure(X: Integer); stdcall; FtpSetNewSlices:         procedure(X, Y: Integer); stdcall; FtpSetPassiveMode:       procedure(bPassive: Bool); stdcall; FtpLogTo:                procedure(hLogFile: HFile); stdcall;
{ Функции инициализации }
FtpRelease: function: Integer; stdcall; FtpInit:    function(hWindow: hWnd): Integer; stdcall; FtpFlush:   function: Integer; stdcall;
{ Соединение }
FtpLogin:           function(Host, User, Password: PChar; hWindow: hWnd; wMSG: UINT): Integer; stdcall;
FtpOpenConnection:  function(Host: PChar): Integer; stdcall; FtpCloseConnection: function: Integer; stdcall; FtpLocalClose:      function: Integer; stdcall;
{ Аутентификация }
FtpSendUserName: function(UserName: PChar): Integer; stdcall; FtpSendPasswd:   function(Passwd: PChar): Integer; stdcall; FtpSendAccount:  function(Acct: PChar): integer; stdcall;
{ Команды }
FtpHelp:       function(Arg, Buf: PChar; BufSize: UINT): Integer; stdcall;
FtpDeleteFile: function(szRemoteFile: PChar): Integer; stdcall; FtpRenameFile: function(szFrom, szTo: PChar): Integer; stdcall; FtpQuote:      function(Cmd, ReplyBuf: PChar; BufSize: UINT): Integer; stdcall;
FtpSyst:       function(var szSystemStr: PChar): Integer; stdcall; FtpSetType:    function(cType: char): Integer; stdcall; FtpCWD:        function(Path: PChar): Integer; stdcall; FtpCDUP:       function: Integer; stdcall; FtpPWD:        function(szBuf: PChar; uBufSize: UINT): Integer; stdcall; FtpMKD:        function(szPath, szFullDir: PChar; uBufSize: UINT): Integer; stdcall;
FtpRMD:        function(szPath: PChar): Integer; stdcall;
{ передача файла } FtpAbort:              function: Integer; stdcall; FtpSendFile:           function(Local, Remote: PChar; cType: char; Notify: Bool;
hWindow: hWnd; wMSG: UINT): Integer; stdcall;
FtpAppendToRemoteFile: function(Local, Remote: PChar; cType: char; Notify: Bool;
hWindow: hWnd; wMSG: UINT): Integer; stdcall;
FtpRecvFile:           function(Remote, Lcl: PChar; cType: char; Notify: Bool;
hWindow: hWnd; wMSG: UINT): Integer; stdcall;
FtpAppendToLocalFile:  function(Remote, Lcl: PChar; cType: char; Notify: Bool;
hWindow: hWnd; wMSG: UINT): Integer; stdcall;
FtpGetFileSize:        function: DWORD; stdcall; FtpMGet:               function(szFilter: PChar; cType: char; bNotify: bool;
Callback: TFtpMGetCallback): integer; stdcall;
FtpRestart:            function(ByteCount: longint): integer; stdcall; FtpRestartSendFile:    function(hLocal: HFile; szRemote: PChar; cType: char;
bNotify: bool; ByteCount: Longint; hWindow: hWnd; wMsg: UINT): integer; stdcall;
FtpRestartRecvFile:    function(szRemote: PChar; hLocal: HFile; cType: char;
bNotify: bool; ByteCount: Longint; hWindow: hWnd; wMsg: UINT): integer; stdcall;

{ Каталог }
FtpDir: function (Def, LocalFile: PChar; LongDir: Bool; hWindow: hWnd; wMSG: UINT): Integer; stdcall;
{ Дополнительно }
FtpOpenDataConnection:        function(szRemote: pchar; nAction: integer; cType: char): integer; stdcall; FtpRecvThroughDataConnection: function(szBuf: Pchar; var BufSize: UINT): integer; stdcall;
FtpSendThroughDataConnection: function(szBuf: PChar; BufSize: UINT): integer; stdcall;
FtpCloseDataConnection:       function: integer; stdcall;
{ Брэндмауэр }
FtpFirewallLogin: function (szFWHost, szFWUser, szFWPass, szRemHost, szRemUser,
szRemPass: PChar; nFirewallType: integer; hParentWnd: hWnd; wMsg: UINT): integer; stdcall;

{ Прочее }
InitFtpGetAnswerCode: function: integer; stdcall;

implementation

const
ftp4wdll = 'FTP4W32.dll'; { Имя DLL-файла }
var
hFtp4W: THandle; { Дескриптор DLL }

{ Загрузка DLL и получение адресов всех процедур. }
function LoadFtp4WDLL: boolean;
var
OldMode: UINT; begin
if hFtp4W <> 0 then FreeLibrary (hFtp4W); OldMode := SetErrorMode(SEM_NOOPENFILEERRORBOX); { Если DLL не грузится, запрещаем вывод системных сообщений. }
hFtp4W := LoadLibrary (ftp4wdll); Result := hFtp4W <> 0; SetErrorMode(OldMode); if not Result then exit;
{ Получаем адреса всех функций } @FtpDataPtr :=                   GetProcAddress(hFtp4W, 'FtpDataPtr'); @FtpBufferPtr :=                 GetProcAddress(hFtp4W, 'FtpBufferPtr'); @FtpErrorString :=               GetProcAddress(hFtp4W, 'FtpErrorString'); @Ftp4wVer :=                     GetProcAddress(hFtp4W, 'Ftp4wVer'); @FtpSetVerboseMode :=            GetProcAddress(hFtp4W, 'FtpSetVerboseMode'); @FtpBytesTransferred :=          GetProcAddress(hFtp4W, 'FtpBytesTransferred'); @FtpBytesToBeTransferred :=      GetProcAddress(hFtp4W, 'FtpBytesToBeTransferred'); @FtpSetDefaultTimeOut :=         GetProcAddress(hFtp4W, 'FtpSetDefaultTimeOut'); @FtpSetDefaultPort :=            GetProcAddress(hFtp4W, 'FtpSetDefaultPort'); @FtpSetAsynchronousMode :=       GetProcAddress(hFtp4W, 'FtpSetAsynchronousMode'); @FtpSetSynchronousMode :=        GetProcAddress(hFtp4W, 'FtpSetSynchronousMode'); @FtpIsAsynchronousMode :=        GetProcAddress(hFtp4W, 'FtpIsAsynchronousMode');
@FtpSetNewDelay :=               GetProcAddress(hFtp4W, 'FtpSetNewDelay');
@FtpSetNewSlices :=              GetProcAddress(hFtp4W, 'FtpSetNewSlices');
@FtpSetPassiveMode :=            GetProcAddress(hFtp4W, 'FtpSetPassiveMode');
@FtpLogTo :=                     GetProcAddress(hFtp4W, 'FtpLogTo'); @FtpRelease :=                   GetProcAddress(hFtp4W, 'FtpRelease'); @FtpInit :=                      GetProcAddress(hFtp4W, 'FtpInit'); @FtpFlush :=                     GetProcAddress(hFtp4W, 'FtpFlush'); @FtpLogin :=                     GetProcAddress(hFtp4W, 'FtpLogin'); @FtpOpenConnection :=            GetProcAddress(hFtp4W, 'FtpOpenConnection');
@FtpCloseConnection :=           GetProcAddress(hFtp4W, 'FtpCloseConnection');
>@FtpLocalClose :=               GetProcAddress(hFtp4W, 'FtpLocalClose'); @FtpSendUserName :=              GetProcAddress(hFtp4W, 'FtpSendUserName');
@FtpSendPasswd :=                GetProcAddress(hFtp4W, 'FtpSendPasswd'); @FtpSendAccount :=               GetProcAddress(hFtp4W, 'FtpSendAccount');
@FtpHelp :=                      GetProcAddress(hFtp4W, 'FtpHelp'); @FtpDeleteFile :=                GetProcAddress(hFtp4W, 'FtpDeleteFile'); @FtpRenameFile :=                GetProcAddress(hFtp4W, 'FtpRenameFile'); @FtpQuote :=                     GetProcAddress(hFtp4W, 'FtpQuote'); @FtpSyst :=                      GetProcAddress(hFtp4W, 'FtpSyst'); @FtpSetType :=                   GetProcAddress(hFtp4W, 'FtpSetType'); @FtpCWD :=                       GetProcAddress(hFtp4W, 'FtpCWD'); @FtpCDUP :=                      GetProcAddress(hFtp4W, 'FtpCDUP'); @FtpPWD :=                       GetProcAddress(hFtp4W, 'FtpPWD'); @FtpMKD :=                       GetProcAddress(hFtp4W, 'FtpMKD'); @FtpRMD :=                       GetProcAddress(hFtp4W, 'FtpRMD'); @FtpAbort :=                     GetProcAddress(hFtp4W, 'FtpAbort'); @FtpSendFile :=                  GetProcAddress(hFtp4W, 'FtpSendFile'); @FtpAppendToRemoteFile :=        GetProcAddress(hFtp4W, 'FtpAppendToRemoteFile');
@FtpRecvFile :=                  GetProcAddress(hFtp4W, 'FtpRecvFile'); @FtpAppendToLocalFile :=         GetProcAddress(hFtp4W, 'FtpAppendToLocalFile');
@FtpGetFileSize :=               GetProcAddress(hFtp4W, 'FtpGetFileSize');
@FtpMGet :=                      GetProcAddress(hFtp4W, 'FtpMGet'); @FtpRestart :=                   GetProcAddress(hFtp4W, 'FtpRestart'); @FtpRestartSendFile :=           GetProcAddress(hFtp4W, 'FtpRestartSendFile');
@FtpRestartRecvFile :=           GetProcAddress(hFtp4W, 'FtpRestartRecvFile');
@FtpDir :=                       GetProcAddress(hFtp4W, 'FtpDir'); @FtpOpenDataConnection :=        GetProcAddress(hFtp4W, 'FtpOpenDataConnection');
@FtpRecvThroughDataConnection := GetProcAddress(hFtp4W, 'FtpRecvThroughDataConnection');
@FtpSendThroughDataConnection := GetProcAddress(hFtp4W, 'FtpSendThroughDataConnection');
@FtpCloseDataConnection :=       GetProcAddress(hFtp4W, 'FtpCloseDataConnection');
@FtpFirewallLogin :=             GetProcAddress(hFtp4W, 'FtpFirewallLogin');
@InitFtpGetAnswerCode :=         GetProcAddress(hFtp4W, 'InitFtpGetAnswerCode');
end;

{ Вызов процедуры при завершении модуля, т.е. при закрытии приложения. }
procedure MyExitProc; far;
begin
if hFtp4W <> 0 then begin { Необходимо убедиться что все закрыто и FTP4W выгружена из памяти. } FtpAbort; FtpFlush; FtpCloseConnection; FtpLocalClose; FTPRelease; { Выгружаем DLL. } FreeLibrary(hFtp4W) end; end;


var
VerInfo: array[0..100] of char; FVer: integer; Begin
hFtp4W := 0; AddExitProc(MyExitProc); FTP4W_Loaded := LoadFtp4WDLL; if FTP4W_Loaded then begin { Проверка корректности версии DLL. } if @Ftp4wVer = NIL then FVer := 0 else FVer := Ftp4wVer(VerInfo, sizeof(VerInfo)); FTP4W_RightVersion := not ((HiByte(FVer) < 2) or ((HiByte(FVer) = 2) and (LoByte(FVer) < 96)));
end; end.

[000082]




Содержание    Вперед