아래화일은 화일전송프로그램입니다.
아래것은 서버에 있는것을 가지고 올수만있더군요..
이것을 어떤방법을 서버로 전송도 가능하게 만들수 있을까요.
참고로 이 소스는 인터넷 서핑해서 찾은겁니다...아마 한델인것 같은데.
도움 바랍니다.
unit FTPGetFile;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, StdCtrls, Dialogs, Buttons, ComCtrls, ExtCtrls, Winsock;
type
// FTP control에서 사용될 상수
// 비동기적으로 호출되는 Command_Proc에서 현재 작업의 상태를 알기위해
TCommand = (PUT_USER, PUT_PASS, PUT_CWD, PUT_QUIT, PUT_TYPE, PUT_RETR,
PUT_STOR, PUT_DELE, PUT_RMD, PUT_MKD, PUT_LIST, PUT_NLST,
PUT_HELP, PUT_PORT, PUT_PWD, PUT_SYST, PUT_ACCT, GET_MESSAGE,
CHK_REST, PRX_OPEN1, PRX_SITE1, PRX_SITE2, PRX_SITE3);
const
// 함수에서 사용할 네트워크 메시지
WM_CONNECT_MSG = WM_USER + 100; // 호스트의 포트에 연결시 발생되는 원도우즈 메시지
// (주의) 이 프로그램의 비동기 통신방법
// 1. connect() : WSAAsyncSelect() 함수 사용
// 2. accept(), recv(), send() : select() 함수 사용
// 3. 호스트 이름 resolve : WSAAsyncGetHostByName(), WSAAsyncGetHostByAddr() 함수 사용
type
TFTPGetForm = class(TForm)
BB_Stop: TBitBtn;
Label2: TLabel;
L_Rfile: TLabel;
Label5: TLabel;
L_Rsize: TLabel;
Label3: TLabel;
ProgressBar1: TProgressBar;
CB_Message: TComboBox;
Panel1: TPanel;
Timer1: TTimer;
L_Speed: TLabel;
Image_update: TImage;
Image_new: TImage;
procedure FormActivate(Sender: TObject);
procedure BB_StopClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
private
{ Private declarations }
{Message Handler}
procedure ConnectMessage(var Msg: TMessage); message WM_CONNECT_MSG;
{FTP부분에 사용되는 기본 method}
function Send_Command(cStr: String): Boolean;
procedure AllCloseSocket;
function GetFTPListenSocket: Tsocket;
procedure DOclosesocket(var socket_id: Tsocket);
procedure DOAddLine(str: String);
function GetReply: Boolean;
procedure Process_ReplyMessage;
procedure asyncselect(synsocket: Tsocket; readsock: Boolean);
procedure asyncconnect(synsocket: Tsocket; synsocket_in: TSockAddrIn; trytimes: Integer);
function AbortCom: Boolean;
function Get_Value(Str, cSpr:String; nPos: Integer): String;
public
{ Public declarations }
HOST_IP : String; {호스트 IP}
USER_ID : String; {사용자 ID}
PASSWORD : String; {비밀번호}
PASSIVE_MODE : Boolean; {passive mode}
SEND_FILENAME, RECV_FILENAME, TRAN_MODE: String;
FTPTransfered : Boolean; {전송완료 여부}
{WSAGetLastError함수에 의해 리턴된 에러번호에 해당하는 메시지를 구한다}
// function GetWinsockError(error: Integer):String;
function FTP_connect: Boolean;
function Send_HostFile(SendFile, RecvFile: String; BinFile: Boolean): Boolean;
end;
const
SEND_BYTE = (4096 - 1); {전송 버퍼의 크기}
RECV_BYTE = (4096 - 1); {수신 버퍼의 크기}
SERVER_PORT = 21; {FTP port}
ASYNC_TIMEOUT_SEC = 60; {default timeout}
TRANS_STEPBY = 5; {transfer step}
{ Macro = 'Indicate code' (FTP 서버의 respond message) }
C150 = '150'; {Opening data connection for xxxxxxxx.xxxx}
C200 = '200'; {일반명령어의 실행 성공}
C213 = '213'; {Fise Size}
C220 = '220'; {Service ready}
C226 = '226'; {Transfer complete}
C227 = '227'; {Entering Passive Mode (130,33,2,28,4,62)}
C250 = '250'; {DELE or RMD or CWD command successful}
C331 = '331'; {Password required for xxxx} {331 Anonymous access allowed, send identity (e-mail name) as password}
C230 = '230'; {User xxxx logged in}
C257 = '257'; {"xxxxxx" is current directory} {MKD command successful}
C350 = '350'; {File exists,ready for destination name}
C500 = '500'; {command not understood.}
C502 = '502'; {REST command not implemented.}
C530 = '530'; {Login incorrect}
C550 = '550'; {"xxxxxx": Permission denied.}
C553 = '553'; {"xxxxxx": Permission denied or Cannot rename to /c:/insa/bin/aaa/WHATSNEW.TXT}
var
FTPGetForm: TFTPGetForm;
ctrl_skt, Listen_skt, Data_skt: Tsocket;
Server_in, Local_In, Listen_in, Data_in: TSockAddrIn;
ReplyMsg : String; {reply message}
SendBuff : array[0..SEND_BYTE] of Char; {명령어 전송용 버퍼}
RecvBuff : array[0..RECV_BYTE] of Char; {메시지(응답) 수신용 버퍼}
Comd : TCommand;
RecvFileSize: LongInt;
trans_time, trans_bps: Real;
// select() 함수에서 사용하는 변수
Start_Time: Longint;
readfds, writefds: TFDSet;
readycomm: Integer;
timeval: TTimeVal;
implementation
{$R *.DFM}
function TFTPGetForm.FTP_connect: Boolean;
var
Address: DWord; // 이진의 네트워크 IP주소(4 bytes)
i: Integer;
begin
Result := False;
DOAddLine('Connecting to '+HOST_IP+' port '+IntToStr(SERVER_PORT));
// 인터넷의 IP주소를 의미하는 문자열은 네 개의 숫자와 그들을 구분하는 도트(".')
// 로 구성된다. 그래서 inet_addr은 그 문자열에 해당하는 네트워크 바이트 순서로
// 된 이진의 IP주소를 리턴한다(4 bytes).
Address := inet_addr(PChar(HOST_IP));
// inet_addr은 인자로 전달된 도트 표현의 IP주소에서 4개의 숫자 가운데
// 255를 넘는 값이 있다거나 기타 이유로 이진 IP주소로 변환될 수 없는
// 문제가 있는 문자열인 경우 INADDR_NONE 값을 리턴한다.
if Address = INADDR_NONE then
begin
DOAddLine('Connection failed '+HOST_IP);
DOAddLine('호스트를 알 수 없습니다. 호스트 주소를 확인하세요.');
System.Exit;
end;
// 서버연결을 위한 상대방의 주소 지정
with Server_in do
begin
FillChar(Server_in, SizeOf(Server_in), #0);
sin_family := PF_INET; // 주소 영역은 현재 PF_INET 뿐이다
sin_addr.s_addr := Address; // 이진의 IP주소(네트워크 바이트 순서의 4 bytes)
sin_port := htons(SERVER_PORT); // 네트워크 바이트 순서의 FTP port 번호(well-known port numer)
end;
{Control Connection port 21(ftpd)}
ctrl_skt := INVALID_SOCKET;
ctrl_skt := socket(PF_INET, SOCK_STREAM, 0); // PF_INET 주소 영역의 TCP 프로토콜을 사용
if ctrl_skt = INVALID_SOCKET then
begin
DOAddLine('Connection failed '+HOST_IP);
DOAddLine('통신오류: 소켓핸들을 얻을 수 없습니다.');
System.Exit;
end;
// 비동기 접속
asyncconnect(ctrl_skt, Server_in, ASYNC_TIMEOUT_SEC);
if BB_Stop.Tag = 1 then // 중지비튼을 눌렀다
begin
DOAddLine('Connection failed '+HOST_IP);
DOAddLine('중지버튼을 눌렀습니다.');
DOclosesocket(ctrl_skt);
System.Exit;
end
else if BB_Stop.Tag = 2 then // 연결시도중 에러발생
begin
DOAddLine('Connection failed '+HOST_IP);
DOAddLine('FTP서버에 연결을 못했습니다.');
DOclosesocket(ctrl_skt);
System.Exit;
end
else if BB_Stop.Tag <> 5 then
begin
DOAddLine('Connection failed '+HOST_IP);
DOAddLine('FTP서버에 연결을 못했습니다. (시간제한 초과)');
DOclosesocket(ctrl_skt);
System.Exit;
end;
BB_Stop.Tag := 0;
if GetReply then // Get banner
begin
// Intermediate 검사 (예, welcome banner)
// 응답의 4번째에 '-'문자를 넣어 comment 를 보내온다
// Intermediate인 경우는 다시 메시지를 받아야 한다
if Copy(ReplyMsg,4,1) = '-' then
GetReply;
if CompareStr(C220, Copy(ReplyMsg,1,3)) <> 0 then
begin
DOAddLine('Connection failed '+HOST_IP);
DOAddLine('FTP서버에 연결을 못했습니다.');
DOclosesocket(ctrl_skt);
System.Exit;
end;
end;
if BB_Stop.Tag <> 0 then
begin
DOAddLine('Connection failed '+HOST_IP);
DOclosesocket(ctrl_skt);
System.Exit;
end;
DOAddLine('Connected to '+HOST_IP+' port '+IntToStr(SERVER_PORT));
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
Comd := PUT_USER;
if not Send_Command('USER ' + USER_ID) then
begin
DOAddLine('Connection failed '+HOST_IP);
DOclosesocket(ctrl_skt);
System.Exit;
end;
if not Send_Command('TYPE '+TRAN_MODE) then
begin
DOAddLine('전송실패: TYPE 명령어를 실행할 수 없습니다');
DOclosesocket(ctrl_skt);
System.Exit;
end;
i := SizeOf(Local_in);
// GetSockname() 함수는 현재 소켓에 할당된 내쪽 주소(IP주소+포트번호)를 얻어내는 함수이다
// 이 함수는 bind()로 내쪽 주소를 지정하지 않고 connect()를 이용하여 연결이 이루어진 후
// TCP/IP 커널에 의해 할당된 내쪽 주소를 알아낼때 사용한다
// 만약 연결(connect)이 이루어지지 않은 상태에서 이 함수를 호출하면 내쪽 IP 주소가 할당되지
// 않기 때문에 INADDR_ANY에 해당하는 값의 주소가 리턴된다.
if GetSockname(ctrl_skt, Local_in, i) = SOCKET_ERROR then // Local_in 은 여기서 한번만 setting된다
begin
DOAddLine('통신오류: Packet Driver 에러로 로컬주소를 얻지못했습니다.');
DOclosesocket(ctrl_skt);
System.Exit;
end;
Send_HostFile(SEND_FILENAME, RECV_FILENAME, True);
if CompareStr(C226, Copy(ReplyMsg,1,3)) = 0 then // 226 = Transfer complete
Result := True;
end;
// 하나의 host file을 Local로 전송(SendFile, RecvFile은 full path로 지정되있다)
function TFTPGetForm.Send_HostFile(SendFile, RecvFile: String; BinFile: Boolean): Boolean;
var
OutF: file;
i, iNumRead, iNumWrite: Integer;
cnt, accum: Integer;
MsgBuf: array[0..RECV_BYTE] of Char; {전송 버퍼}
begin
Result := False; // 전송실패
{$I-}
FileMode := 1; {write Only}
AssignFile(OutF, RecvFile); // full path
ReWrite(OutF, 1); {Record Size 1(byte단위)}
{$I+}
if IOResult <> 0 then
begin
DOAddLine('로컬에 파일 '''+RecvFile+''' 를 만들 수 없습니다.');
System.CloseFile(OutF);
System.Exit;
end;
if GetFTPListenSocket = INVALID_SOCKET then {listen socket을 얻은후 "PORT"명령을 보내는 함수호출후 비교}
begin
System.CloseFile(OutF);
System.Exit;
end;
if PASSIVE_MODE then // passive mode
begin
// PASV 명령에의해 서버로 부터 할당받은 IP와 port번호로 직접 접속하여
// 자료를 가져온다(data_skt은 GetFTPListenSocket 에서 생성시켰음)
// 비동기 접속
asyncconnect(data_skt, Data_in, ASYNC_TIMEOUT_SEC);
if BB_Stop.Tag = 1 then // 중지비튼을 눌렀다
begin
System.CloseFile(OutF);
DOclosesocket(data_skt);
System.Exit;
end
else if BB_Stop.Tag = 2 then // 연결시도중 에러발생
begin
System.CloseFile(OutF);
DOAddLine('통신오류: 데이타를 수신할 수 없는 상태입니다.');
System.Exit;
end
else if BB_Stop.Tag = 3 then // Timeout
begin
System.CloseFile(OutF);
DOclosesocket(data_skt);
DOAddLine('통신오류: 데이타 수신이 지연됩니다.');
System.Exit;
end;
Comd := PUT_RETR; {파일size를 구한다}
if not Send_Command('RETR '+SendFile) then // full path
begin
System.CloseFile(OutF);
DoCloseSocket(data_skt);
if (BB_Stop.Tag = 1) and (CompareStr(C226, Copy(ReplyMsg,1,3)) <> 0) then // 226 = Transfer complete
begin
AbortCom;
end;
System.Exit;
end;
if Copy(ReplyMsg,1,1) = '5' then
begin
System.CloseFile(OutF);
DoCloseSocket(data_skt);
MessageDlg('서버에 실행파일이 없거나 사용할 수 없습니다',
mtInformation, [mbOk], 0);
Timer1.Enabled := True; // 약간 지연시킨후 종료
System.Exit;
end;
if RecvFileSize < 0 then
begin
System.CloseFile(OutF);
DoCloseSocket(data_skt);
System.Exit;
end;
end
else
begin
Comd := PUT_RETR; {파일size를 구한다}
if not Send_Command('RETR '+SendFile) then // full path
begin
DoCloseSocket(listen_skt);
System.CloseFile(OutF);
if (BB_Stop.Tag = 1) and (CompareStr(C226, Copy(ReplyMsg,1,3)) <> 0) then // 226 = Transfer complete
begin
AbortCom;
end;
System.Exit;
end;
if Copy(ReplyMsg,1,1) = '5' then
begin
System.CloseFile(OutF);
DoCloseSocket(data_skt);
MessageDlg('서버에 실행파일이 없거나 사용할 수 없습니다',
mtInformation, [mbOk], 0);
Timer1.Enabled := True; // 약간 지연시킨후 종료
System.Exit;
end;
if RecvFileSize < 0 then
begin
DoCloseSocket(listen_skt);
System.CloseFile(OutF);
System.Exit;
end;
asyncselect(listen_skt, True); // 두번째가 True인것은 지정한 소켓이 recv용 소켓임을 표시
if BB_Stop.Tag <> 0 then
begin
DoCloseSocket(listen_skt);
System.CloseFile(OutF);
if (BB_Stop.Tag = 1) and (CompareStr(C226, Copy(ReplyMsg,1,3)) <> 0) then // 226 = Transfer complete
begin
AbortCom;
end;
System.Exit;
end;
accum := SizeOf(Data_in);
Data_skt := accept(listen_skt, @Data_in, @accum); {listen socket에서 대기}
if Data_skt = INVALID_SOCKET then
begin
DoCloseSocket(listen_skt);
DoCloseSocket(Data_skt);
System.CloseFile(OutF);
System.Exit;
end;
DoCloseSocket(listen_skt); {data송수신시 Listen socket은 필요없으므로 닫는다}
end;
L_Rsize.Caption := '0/'+IntToStr(RecvFileSize div 1024)+' KB';
iNumRead := 0;
iNumWrite := 0;
accum := 0;
cnt := TRANS_STEPBY - 1;
trans_bps := 0;
while True do
begin
trans_time := GetTickCount; // 시작 TimeOut
asyncselect(Data_skt, True); // 두번째가 True인것은 지정한 소켓이 recv용 소켓임을 표시
if BB_Stop.Tag <> 0 then
begin
Break;
end;
iNumRead := recv(Data_skt, MsgBuf, SizeOf(MsgBuf), 0);
if iNumRead = SOCKET_ERROR then
begin
System.CloseFile(OutF);
DOAddLine('통신오류: 데이터를 받을 수 없습니다.');
System.Exit;
end;
if iNumRead <= 0 then
Break;
BlockWrite(OutF, MsgBuf, iNumRead, iNumWrite);
Inc(accum, iNumWrite);
trans_time := (GetTickCount - trans_time) / 1000; // 종료 TimeOut
if RecvFileSize > 0 then
begin
ProgressBar1.Position := (accum * 100) div RecvFileSize;
L_Rsize.Caption := IntToStr(accum div 1024)+'/'+IntToStr(RecvFileSize div 1024)+' KB';
if trans_time > 0 then
begin
Inc(cnt);
trans_bps := trans_bps + (iNumRead / trans_time);
if (cnt mod TRANS_STEPBY) = 0 then
begin
trans_bps := trans_bps / TRANS_STEPBY; // 평균을 구한다
if trans_bps > 1024 then
L_Speed.Caption := Format('at %.1f Kbps',[trans_bps / 1024])
else if trans_bps > 0 then
L_Speed.Caption := Format('at %.0f bps',[trans_bps]);
end;
end;
end;
Application.ProcessMessages;
if BB_Stop.Tag <> 0 then {Cancel이 click되면}
Break;
end; {while}
System.CloseFile(OutF);
if BB_Stop.Tag = 1 then // 중지이면 Abort 메시지를 보내서 data connection을 취소
begin
DoCloseSocket(Data_skt); {data control 소켓을 닫는다}
if CompareStr(C226, Copy(ReplyMsg,1,3)) <> 0 then // 226 = Transfer complete
begin
AbortCom;
end;
System.Exit;
end
else if BB_Stop.Tag = 2 then // 에러
begin
DOAddLine('통신오류: 데이타를 수신할 수 없는 상태입니다.');
system.Exit;
end;
ProgressBar1.Position := 100;
DoCloseSocket(Data_skt); {data control 소켓을 닫는다}
if CompareStr(C226, Copy(ReplyMsg,1,3)) <> 0 then // 226 = Transfer complete
if GetReply then
begin
if Copy(ReplyMsg,4,1) = '-' then
GetReply;
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
end;
Result := True;
end;
{Data Connection(listen socket을 얻는다)}
function TFTPGetForm.GetFTPListenSocket: TSocket;
var
i: Integer;
a, p: PChar; {a:address, p:port}
passiveIP: String;
PasvAddress: DWord; // 이진의 IP주소(4 bytes)
PasvPort: Word;
begin
// GetFTPListenSocket() 의 리턴값은 PASV 모드인 경우는 data_skt 을
// 그렇지 않으면 listen_skt 을 리턴한다
DOclosesocket(Listen_skt); {이전 소켓이 열려있을 수 있으므로 닫는다}
DOclosesocket(Data_skt);
Result := INVALID_SOCKET;
// Use PASV Mode
// PASV mode is supported as a firewall option.
// This feature simply reverses the connection between host and server,
// thus allowing many users that reside behind firewalls to use this program.
// PASV mode ftp is what most of the browsers like Netscape,
// and Microsoft use to initiate ftp transfers.
if PASSIVE_MODE then // PASV 모드
begin
Comd := GET_MESSAGE;
if not Send_Command('PASV') then {Use PASV Mode}
System.Exit;
if CompareStr(C227, Copy(ReplyMsg,1,3)) <> 0 then {C227 = "Entering Passive Mode (130,33,2,28,4,62)"}
begin
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
Result := INVALID_SOCKET;
end
else
begin
passiveIP := copy(ReplyMsg, pos('(', ReplyMsg) + 1, length(ReplyMsg));
passiveIP := copy(passiveIP, 1, pos(')', passiveIP) - 1); // passiveIP = "130,33,2,28,4,62"
// 인터넷의 IP주소를 의미하는 문자열은 네 개의 숫자와 그들을 구분하는 도트(".')
// 로 구성된다. 그래서 inet_addr은 그 문자열에 해당하는 네트워크 바이트 순서로
// 된 이진의 IP주소를 리턴한다(4 bytes).
PasvAddress := inet_addr(PChar(Get_Value(passiveIP,',',1)+'.'+
Get_Value(passiveIP,',',2)+'.'+
Get_Value(passiveIP,',',3)+'.'+
Get_Value(passiveIP,',',4)));
PasvPort := StrToIntDef(Get_Value(passiveIP,',',5),0) shl 8 +
StrToIntDef(Get_Value(passiveIP,',',6),0); // 네트워크 바이트 순서의 port 번호
Data_skt := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if Data_skt = INVALID_SOCKET then
begin
DOAddLine('통신오류: 데이터 소켓핸들을 얻을 수 없습니다.');
Result := INVALID_SOCKET;
System.Exit;
end;
Result := Data_skt;
// passive mode 에서는 data socket의 IP와 port 번호를 서버가 임의로
// 할당하므로 이를 이용하여 listen, accept하지 않고 바로 data socket으로
// connect하여 자료를 가져온다
with Data_in do
begin
FillChar(Data_in, SizeOf(Data_in), #0);
sin_family := PF_INET;
sin_addr.s_addr := PasvAddress; // 서버가 할당한 IP
sin_port := htons(PasvPort); // 서버가 할당한 port number (data port)
end;
end;
end
else // PORT 모드
begin
Listen_skt := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if Listen_skt = INVALID_SOCKET then
begin
DOAddLine('통신오류: 데이터 소켓핸들을 얻을 수 없습니다.');
Result := INVALID_SOCKET;
System.Exit;
end;
// 만일 IP주소가 INADDR_ANY 이면 실제 이 소켓이 사용될 때는 내 호스트가 연결된
// 여러 개의 네트워크 가운데 상대방 호스트에 따라 적합한 네트워크를 선택하고
// 그에 해당하는 주소로 바뀐다
with Listen_in do
begin
FillChar(Listen_in, SizeOf(Listen_in), #0);
sin_family := PF_INET;
sin_addr.s_addr := htonl(INADDR_ANY);
sin_port := htons(0);
end;
// bind()함수는 스트림 소켓과 데이터그램 소켓 등 양쪽 형태의 아직 연결이 되지 않은
// 소켓에 대해 connect()나 listen() 함수를 호출하기 이전에 내쪽의 주소(IP, port)
// 를 구체적으로 지정하기 위해 사용
if bind(Listen_skt, Listen_in, SizeOf(Listen_in)) = SOCKET_ERROR then
begin
DOAddLine('통신오류: 데이터 바인딩을 못했습니다.');
Result := INVALID_SOCKET;
System.Exit;
end;
i := SizeOf(Listen_in);
if getsockname(Listen_skt, Listen_in, i) < 0 then {내쪽의 주소(IP + port)를 알아낸다}
begin
DOAddLine('통신오류: 데이터 포트번호를 얻지 못했습니다.(data control)');
Result := INVALID_SOCKET;
System.Exit;
end;
// listen() 함수는 스트림 소켓의 TCP 상태를 LISTEN 상태, 즉 연결을 기다리는 상태로 만든다
// 따라서 listen()은 연결을 지원하는 스트림 소켓에만 적용되는 함수이다
if Listen(Listen_skt, 1) = SOCKET_ERROR then
begin
DOAddLine('통신오류: 데이터를 받을 수 없습니다.');
Result := INVALID_SOCKET;
System.Exit;
end;
{port번호를 생성하여 "PORT"명령을 송신하여 클라이언트의 receive 포트를 서버에 알린다}
a := PChar(@(Local_in.sin_addr)); {local IP address, login 시 구해놨음}
p := PChar(@(Listen_in.sin_port)); {listen socket(htons(0)에 의해 생성된 port}
Comd := PUT_PORT;
if not Send_Command(
Format('PORT %d,%d,%d,%d,%d,%d',[Byte(a[0]) and $00ff
,Byte(a[1]) and $00ff
,Byte(a[2]) and $00ff
,Byte(a[3]) and $00ff
,Byte(p[0]) and $00ff
,Byte(p[1]) and $00ff])) then
begin
DOclosesocket(Listen_skt);
DOclosesocket(Data_skt);
if BB_Stop.Tag = 1 then
begin
AbortCom;
end;
System.Exit;
end;
if CompareStr(C200, Copy(ReplyMsg,1,3)) <> 0 then {C200 = "200 PORT command successful."}
Result := INVALID_SOCKET
else
Result := Listen_skt;
end;
end;
function TFTPGetForm.AbortCom: Boolean;
begin
Result := False;
BB_Stop.Tag := 0;
Comd := GET_MESSAGE;
if not Send_Command('ABOR') then
begin
DOAddLine('transfer failed');
DOAddLine('전송이 취소되었습니다');
System.Exit;
end;
if GetReply then
begin
if Copy(ReplyMsg,4,1) = '-' then
GetReply;
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
end;
Result := True;
end;
{Command전송후 reply message를 처리
multiline 메시지수신(첫번째 message만 ReplyMsg변수에 받고 나머지는 삭제}
procedure TFTPGetForm.Process_ReplyMessage;
var
i, j: integer;
SubStr: String;
begin
if (ctrl_skt = SOCKET_ERROR) then
begin
BB_Stop.Tag := 2;
System.Exit;
end;
case Comd of {Comd 전역변수에는 현재 FTP명령어의 종류를 저장하고 있음}
PUT_USER:
begin
if ReplyMsg = '' then // 응답이 없었다면(가끔 proxy서버에서 발생) 다시 받는다
begin
if GetReply then // Get banner
begin
if Copy(ReplyMsg,4,1) = '-' then
GetReply;
end;
end;
if Copy(ReplyMsg,1,1) = '2' then {"230 User 사용자ID logged in."}
begin
DOAddLine(ReplyMsg);
end
else if Copy(ReplyMsg,1,1) = '3' then {"331 Password required for 사용자ID"}
begin
DOAddLine(ReplyMsg);
Comd := PUT_PASS;
if not Send_Command('PASS ' + PASSWORD) then {password전송}
begin
BB_Stop.Tag := 2;
System.Exit;
end;
end
else // 530 User ... Unknown
begin
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
DOAddLine('사용자ID가 틀립니다.');
BB_Stop.Tag := 2;
end;
end;
PUT_PASS:
begin
if Copy(ReplyMsg,1,1) = '2' then {"230 User 사용자ID logged in."}
begin
DOAddLine(ReplyMsg);
end
else if Copy(ReplyMsg,1,1) = '3' then {계정필요}
begin
DOAddLine(ReplyMsg);
Comd := PUT_ACCT;
if not Send_Command('ACCT '+USER_ID) then
begin
BB_Stop.Tag := 2;
System.Exit;
end;
end
else // 530 Login incorrect
begin
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
DOAddLine('사용자ID의 비밀번호가 틀립니다.');
BB_Stop.Tag := 2;
end;
end;
PUT_ACCT:
begin
if Copy(ReplyMsg,1,1) = '2' then {"230 User 사용자ID logged in."}
begin
DOAddLine(ReplyMsg);
end
else // 530 Login incorrect
begin
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
DOAddLine('사용자ID의 계정(Account)이 틀립니다.');
BB_Stop.Tag := 2;
end;
end;
PUT_PORT:
begin
if CompareStr(C200, Copy(ReplyMsg,1,3)) <> 0 then {C200 = "일반명령어의 실행 성공"}
DOclosesocket(Listen_skt);
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
end;
PUT_RETR:
begin
RecvFileSize := -1; // -1은 에러, 0은 파일 크기가 0인것을 의미
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
if CompareStr(C150, Copy(ReplyMsg,1,3)) = 0 then {C150 = "Opening data connection for xxxxxxxx.xxxx"}
begin
for i := Length(ReplyMsg) downto 1 do
if ReplyMsg[i] = '(' then
begin
ReplyMsg := Copy(ReplyMsg, i, MAX_PATH); // (99999) 만 뽑아낸다
Break;
end;
i := Pos('(', ReplyMsg); {메시지에서 Retrieve할 파일의 size를 추출}
if i > 0 then
begin
SubStr := '';
for j := i+1 to System.Length(ReplyMsg) do
if ReplyMsg[j] in ['0','1','2','3','4','5','6','7','8','9'] then
AppendStr(SubStr,ReplyMsg[j]);
RecvFileSize := StrToIntDef(SubStr, 0);
end
else
begin
// "150 Opening data connection for xxxx" 에 파일 사이즈를 안주는 서버가 있음
// 이때는 RecvFileSize 의 최대 크기를 주어 파일은 받게한다
RecvFileSize := High(RecvFileSize);
end;
end
else if CompareStr(C226, Copy(ReplyMsg,1,3)) = 0 then // 226 = Transfer complete
begin
// RETR 하자마자 "226 = Transfer complete" 이 오는것은 파일의 크기가 너무 작을때 발생한다
RecvFileSize := RECV_BYTE; // -1은 에러, 0은 파일 크기가 0인것을 의미
end;
end;
GET_MESSAGE:
begin
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
end;
PUT_QUIT: {program end}
begin
if ReplyMsg <> '' then
DOAddLine(ReplyMsg);
end;
end; {case}
end;
{FTP서버에 명령어 전송 프로시져}
function TFTPGetForm.Send_Command(cStr: String): Boolean;
begin
Result := False;
if ctrl_skt = INVALID_SOCKET then
begin
System.Exit;
end;
asyncselect(ctrl_skt, False); // 두번째가 False인것은 지정한 소켓이 send용 소켓임을 표시
if BB_Stop.Tag <> 0 then
begin
System.Exit;
end;
if Copy(cStr,1,4) = 'PASS' then
DOAddLine('PASS (hidden)') // password를 보여주지 않고 감춘다
else
DOAddLine(cStr);
FillChar(SendBuff, SizeOf(SendBuff), #0);
AppendStr(cStr, #13#10); {CR/LF문자 추가}
StrPcopy(SendBuff, cStr);
if Send(ctrl_skt, SendBuff, StrLen(SendBuff), 0) = SOCKET_ERROR then
begin
System.Exit;
end;
if GetReply then
begin
// Intermediate 검사 (예, welcome banner)
// 응답의 4번째에 '-'문자를 넣어 comment 를 보내온다
// Intermediate인 경우는 다시 메시지를 받아야 한다
if Copy(ReplyMsg,4,1) = '-' then
GetReply;
Process_ReplyMessage;
end;
if BB_Stop.Tag <> 0 then
begin
System.Exit;
end;
Result := True;
end;
{reply message를 메시지 listbox에 출력}
procedure TFTPGetForm.DOAddLine(str: String);
begin
CB_Message.ItemIndex := CB_Message.Items.Add(str);
Application.ProcessMessages;
end;
{FTP서버로 부터의 메시지를 받는 함수}
function TFTPGetForm.GetReply: Boolean;
var
i, iNumByte: Integer;
begin
// 복수 메시지일 경우 마지막 메시지를 응답으로 처리한다
ReplyMsg := '';
Result := False;
if ctrl_skt = INVALID_SOCKET then
begin
BB_Stop.Tag := 2;
System.Exit;
end;
if BB_Stop.Tag <> 0 then
begin
System.Exit;
end;
asyncselect(ctrl_skt, True); // 두번째가 True인것은 지정한 소켓이 recv용 소켓임을 표시
if BB_Stop.Tag <> 0 then
begin
System.Exit;
end;
FillChar(RecvBuff, SizeOf(RecvBuff), #0);
iNumByte := recv(ctrl_skt, RecvBuff, SizeOf(RecvBuff), 0);
if iNumByte = SOCKET_ERROR then
begin
BB_Stop.Tag := 2;
System.Exit;
end;
for i := 0 to iNumByte - 1 do
if (RecvBuff[i] = #0) or (RecvBuff[i] = #10) then {각 message의 구분문자}
begin
if i = (iNumByte - 1) then // 하나의 메시지만 있는경우
begin
Break;
end;
// * 마지막 메시지가 아닌것은 그냥 화면에 보여준다 *
// Intermediate 검사 (예, welcome banner)
// 응답의 4번째에 '-'문자를 넣어 comment 를 보내온다
// Intermediate인 경우는 다시 메시지를 받아야 한다
if Trim(ReplyMsg) <> '' then
DOAddLine(Trim(ReplyMsg));
ReplyMsg := '';
end
else
ReplyMsg := ReplyMsg + RecvBuff[i];
ReplyMsg := Trim(ReplyMsg); // 문자열에 #13(CR)이 포함될 수 있으므로 제거하는 의미에서 Trim 시킴
Result := True;
end;
{열려있는 모든 소켓을 닫는다}
procedure TFTPGetForm.AllCloseSocket;
begin
if ctrl_skt <> INVALID_SOCKET then
DOclosesocket(ctrl_skt);
if listen_skt <> INVALID_SOCKET then
DOclosesocket(listen_skt);
if Data_skt <> INVALID_SOCKET then
DOclosesocket(Data_skt);
end;
procedure TFTPGetForm.asyncselect(synsocket: Tsocket; readsock: Boolean);
// 이 함수는 원래 WSAAsyncSelect() 함수를 사용하여 비동기 원속 메시지를
// 처리하여야 하지만 이 프로그램에서는 BSD 계열의 소켓 함수인 select()
// 함수를 사용하여 비동기 처리를 하였습니다
begin
if readsock = True then // recv
FD_ZERO(readfds)
else
FD_ZERO(writefds);
// select() 함수는 BSD 계열의 소켓 함수(소켓함수는 크게 3가지로 분류하는데
// BSD 계열의 함수, 데이터베이스 함수, 원도우즈 지원함수로 분류) 로
// 지정된 하나 또는 여러 개의 소켓에 대해 수신된 데이터가 있는지,
// 송신이 가능한지, OOB(대역외 데이터) 가 수신되었는지를 체크하기 의한
// 폴링(polling)함수이다
// 함수의 리턴값은 select()가 성공적으로 이루어지면 리턴된 readfds,
// writefds, exceptfds 중에 어느 하나라도 지정된 동작이 가능한 소켓의
// 총 수가 리턴된다. 지정된 시간동안 어떤 소켓에 대해서도 지정한 동작의
// 가능성이 없었다면 select()는 0으로 곧바로 리턴한다. 만일 select()에 체크
// 하라고 지정한 스트림(stream) 소켓 중 하나라도 연결이 끊어진 상태라면
// select()는 SOCKET_ERROR 를 리턴하며 에러 코드가 설정된다
TimeVal.tv_sec := 0; // 대기시간 없음
TimeVal.tv_usec := 0;
readycomm := 0;
while True do
begin
Application.ProcessMessages; // 대기상태인동안 원도우즈의 메세지처리
if readsock = True then // recv
begin
FD_SET(synsocket, readfds);
readycomm := select(synsocket+1, @readfds, nil, nil, @TimeVal) // 0..synsocket까지의 socket 검사
end
else
begin
FD_SET(synsocket, writefds);
readycomm := select(synsocket+1, nil, @writefds, nil, @TimeVal);
end;
if BB_stop.Tag = 1 then {중지버튼 클릭}
System.Exit;
if (readycomm > 0) then // 지정된 동작을 할 수 있는 소켓의 갯수
begin
if (readsock = True) and (FD_ISSET(synsocket, readfds) = True) then
begin
BB_Stop.Tag := 0;
System.Exit;
end
else if (readsock = False) and (FD_ISSET(synsocket, writefds) = True) then
begin
BB_Stop.Tag := 0;
System.Exit;
end
end;
end;
end;
procedure TFTPGetForm.asyncconnect(synsocket: Tsocket; synsocket_in: TSockAddrIn; trytimes: Integer);
var
argp: Longint;
begin
// WSAAsyncSelect()은 네트워크 이벤트(FD_ACCEPT, FD_READ, FD_WRITE, FD_CLOSE...)중 하나라도 소켓에 발생했을때
// 지정된 원도우에 메시지를 보낸다. 이 함수를 호출하면 소켓은 자동적으로 Non-Blocking 모드로 바뀐다.
// 이 메시지의 wParam에는 소켓이, lParam의 하위 16비트에는 발생한 이벤트, 상위 16비트에는 에러코드가
// 저장된다.
// 여러개의 네트워크 이벤트가 동시에 발생했다면, 원도우는 각 이벤트에 대하여 각각의 메시지를 받게 된다
WSAAsyncSelect(synsocket, Self.Handle, WM_CONNECT_MSG, FD_CONNECT);
Start_Time := GetTickCount; // 시작 TimeOut
if Connect(synsocket, synsocket_in, sizeof(synsocket_in)) = SOCKET_ERROR then
if WSAGetLastError <> WSAEWOULDBLOCK then
begin
BB_Stop.Tag := 2;
System.Exit;
end;
repeat
Application.ProcessMessages; {allowing access to other controls, etc.}
if BB_Stop.Tag <> 0 then // 중지비튼을 눌렀거나 연결되거나 에러발생(BB_Stop.Tag의 값은 AppMessage에서 바꿈)
Break;
until ((GetTickCount-Start_Time) >= Longint(trytimes * 1000)); // TimeOut 검사
if (BB_Stop.Tag <> 1) and (BB_Stop.Tag <> 2) and (BB_Stop.Tag <> 5) then // 에러나 연결이 아니면 시간초과
begin
BB_Stop.Tag := 3;
System.Exit;
end;
// WSAAsyncSelect()함수를 호출하면 소켓은 자동적으로 Non-Blocking 모드로 바뀌는데
// 이를 Blocking모드로 다시 변경한다
// 소켓을 Blocking 모드로 다시 전환하기 위해서는 먼저 WSAAsyncSelect()의 lEvent 인자를 0으로
// 하여 호출하고 ioctlsocket() 함수를 호출해야 한다
WSAAsyncSelect(synsocket, Self.Handle, 0, 0);
argp := 0; // Non-Blocking 모드 해제
ioctlsocket(synsocket, FIONBIO, argp);
end;
procedure TFTPGetForm.ConnectMessage(var Msg: TMessage);
begin
if (WSAGetSelectEvent(Msg.lParam) = FD_CONNECT) and // 이전에 요청한 연결이 이루어짐
(WSAGetSelectError(Msg.lParam) = 0) // 상위 16비트에는 에러코드가 있음
then
BB_Stop.Tag := 5 // 0:초기/정상, 1:중지, 2:에러, 5:연결
else
BB_Stop.Tag := 2;
end;
{parameter로 지정한 소켓을 강제로 즉시 닫는다(블록킹 해제됨)}
procedure TFTPGetForm.DOclosesocket(var socket_id: TSocket);
begin
// 블록킹(blocking)된 소켓함수가 있다면 이를 취소시킨다
// 어느 경우에나 WSACancelBlockingCall() 이 호출되면 Block이 진행 중이던
// 원래의 함수는 에러로 리턴하고, 이 때 에러 코드는 WSAEINTR이 된다
// 이식성이 높은 응용 프로그램을 개발하기 위하여 WSACancelBlockingCall() 후에
// closesocket() 이외의 다른 소켓 함수 호출은 하지 않는 것이 좋다.
if socket_id <> INVALID_SOCKET then
if WSAISBlocking then // 어떤 소켓 함수가 Block 상태에 있는 가를 검사
begin
WSACancelBlockingCall;
DOAddLine('Cancelled blocking call');
end;
CloseSocket(socket_id);
socket_id := INVALID_SOCKET;
end;
{cSpr 문자로 분리된 문자열에서 nPos번째 문자열을 return}
function TFTPGetForm.Get_Value(Str, cSpr:String; nPos: Integer): String;
var
i, j, cnt: Integer;
begin
if Pos(cSpr, Str) = 0 then
begin
Result := Str;
System.Exit;
end;
i := 1;
j := 1;
cnt := 1; {cSpr 문자 갯수}
while i <= Length(Str) do
begin
if Str[i] = cSpr then
begin
if cnt = nPos then
begin
Result := Copy(Str, j, i - j);
System.Exit;
end;
Inc(cnt);
j := i + 1;
end;
Inc(i);
end;
if nPos = cnt then {맨 마지막 문자열을 원했을때}
Result := Copy(Str, j, i - j + 1)
else
Result := ''; {해당값 없음}
end;
procedure TFTPGetForm.FormActivate(Sender: TObject);
var
ImsiFile: String;
begin
ImsiFile := ExtractFilePath(RECV_FILENAME)+
Copy(ExtractFileName(RECV_FILENAME),1,Pos('.',ExtractFileName(RECV_FILENAME))-1)+'.bak';
if FileExists(RECV_FILENAME) or FileExists(ImsiFile) then // 해당파일이나 backup파일이 있다면 Update!
Image_update.Visible := True
else
Image_new.Visible := True;
Application.ProcessMessages;
BB_Stop.Tag := 0;
BB_Stop.Caption := '중지(&C)';
ProgressBar1.Position := 0;
L_Rsize.Caption := '';
CB_Message.Items.Clear;
Application.ProcessMessages;
FTPTransfered := FTP_connect;
Application.ProcessMessages;
AllCloseSocket;
BB_Stop.caption := '닫기(&C)';
if FTPTransfered then // 전송완료
begin
Timer1.Enabled := True; // 약간 지연시킨후 종료
end;
end;
procedure TFTPGetForm.BB_StopClick(Sender: TObject);
begin
BB_Stop.Tag := 1;
Application.ProcessMessages;
Close;
end;
procedure TFTPGetForm.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
Close;
end;
procedure TFTPGetForm.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
Image_update.Visible := False;
Image_new.Visible := False;
CanClose := True;
end;
end.
이거 ftp관련댄게 데모에 이뜨라구여. 그래서 일케 쓰는데 분석은 못하구여--;;
여기 업로드 기능 이뜨라구여. 그거 보시구 하믄 대겐네여 ^^;
아공 위치는 C:Program FilesBolandDelphi5DemosFastNetFtp 네요.
구럼 도움이 되시길 간절히 바라면서 ㅜ.ㅜ 초보는 물러갑니당...
///////////////////////////////////////////////////////////////////////////
// //
// Copyright ?1997-1998, NetMasters, L.L.C //
// - All rights reserved worldwide. - //
// Portions may be Copyright ?Inprise. //
// //
// FTP Demo Unit 1 : (UNIT1.PAS) //
// //
// DESCRIPTION: //
// //
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY //
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR //
// PURPOSE. //
// //
///////////////////////////////////////////////////////////////////////////
//
// Revision History
//
// //
///////////////////////////////////////////////////////////////////////////
unit FTPDem;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Forms, Dialogs,
ComCtrls, StdCtrls, Psock, NMFtp, Controls;
type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
TabSheet4: TTabSheet;
HostTxt: TEdit;
PortTxt: TEdit;
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
StatusBar1: TStatusBar;
Memo1: TMemo;
Button3: TButton;
Button4: TButton;
NMFTP1: TNMFTP;
UserTxt: TEdit;
Label3: TLabel;
PassTxt: TEdit;
Label4: TLabel;
DirTxt: TEdit;
Label5: TLabel;
Label6: TLabel;
Button5: TButton;
RemoteTxt: TEdit;
Label7: TLabel;
LocalTxt: TEdit;
Label8: TLabel;
Button6: TButton;
Button7: TButton;
TabSheet6: TTabSheet;
Edit3: TEdit;
Label11: TLabel;
Label12: TLabel;
Edit4: TEdit;
Button10: TButton;
Button11: TButton;
Button8: TButton;
Button9: TButton;
Button12: TButton;
Button13: TButton;
PosTxt: TEdit;
Label9: TLabel;
TabSheet5: TTabSheet;
Edit1: TEdit;
Label10: TLabel;
Edit2: TEdit;
Label13: TLabel;
Button14: TButton;
Button15: TButton;
TabSheet7: TTabSheet;
Edit5: TEdit;
Label14: TLabel;
Button16: TButton;
TabSheet8: TTabSheet;
Button17: TButton;
Label15: TLabel;
CheckBox1: TCheckBox;
Edit6: TEdit;
Edit7: TEdit;
Label16: TLabel;
Label17: TLabel;
TabSheet9: TTabSheet;
Edit8: TEdit;
Edit9: TEdit;
Label18: TLabel;
Label19: TLabel;
Button18: TButton;
procedure NMFTP1Success(Trans_Type: TCmdType);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure NMFTP1ListItem(Listing: String);
procedure TabSheet3MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Button5Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure NMFTP1PacketRecvd(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
procedure Button11Click(Sender: TObject);
procedure Button12Click(Sender: TObject);
procedure Button13Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button14Click(Sender: TObject);
procedure Button15Click(Sender: TObject);
procedure Button16Click(Sender: TObject);
procedure Button17Click(Sender: TObject);
procedure NMFTP1Connect(Sender: TObject);
procedure NMFTP1Failure(var handled: Boolean; Trans_Type: TCmdType);
procedure NMFTP1TransactionStop(Sender: TObject);
procedure NMFTP1HostResolved(Sender: TComponent);
procedure NMFTP1InvalidHost(var handled: Boolean);
procedure NMFTP1PacketSent(Sender: TObject);
procedure NMFTP1TransactionStart(Sender: TObject);
procedure NMFTP1Disconnect(Sender: TObject);
procedure NMFTP1Error(Sender: TComponent; Errno: Word; Errmsg: String);
procedure NMFTP1Status(Sender: TComponent; Status: String);
procedure Button18Click(Sender: TObject);
procedure NMFTP1UnSupportedFunction(Trans_Type: TCmdType);
procedure NMFTP1ConnectionFailed(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
var
Q: Integer;
procedure TForm1.NMFTP1Success(Trans_Type: TCmdType);
begin
Case Trans_Type of
cmdChangeDir: StatusBar1.SimpleText := 'ChangeDir success';
cmdMakeDir: StatusBar1.SimpleText := 'MakeDir success';
cmdDelete: StatusBar1.SimpleText := 'Delete success';
cmdRemoveDir: StatusBar1.SimpleText := 'RemoveDir success';
cmdList: StatusBar1.SimpleText := 'List success';
cmdRename: StatusBar1.SimpleText := 'Rename success';
cmdUpRestore: StatusBar1.SimpleText := 'UploadRestore success';
cmdDownRestore: StatusBar1.SimpleText := 'DownloadRestore success';
cmdDownload: StatusBar1.SimpleText := 'Download success';
cmdUpload: StatusBar1.SimpleText := 'Upload success';
cmdAppend: StatusBar1.SimpleText := 'UploadAppend success';
cmdReInit: StatusBar1.SimpleText := 'ReInit success';
cmdAllocate: StatusBar1.SimpleText := 'Allocate success';
cmdNList: StatusBar1.SimpleText := 'NList success';
cmdDoCommand: StatusBar1.SimpleText := 'DoCommand success';
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
If CheckBox1.Checked then
Begin
NMFTP1.Proxy := Edit6.Text;
NMFTP1.ProxyPort := StrToInt(Edit7.Text);
End;
NMFTP1.Host := HostTxt.Text;
NMFTP1.Port := StrToInt(PortTxt.Text);
NMFTP1.Timeout := 5000;
NMFTP1.UserID := UserTxt.Text;
NMFTP1.Password := PassTxt.Text;
try
NMFTP1.Connect;
except
On E:Exception do
writeln(E.message);
end
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
NMFTP1.Disconnect;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Q := 1;
try NMFTP1.Nlist; except end;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
Q := 1;
try NMFTP1.List; except end;
end;
procedure TForm1.NMFTP1ListItem(Listing: String);
begin
Memo1.Lines.Add(IntToStr(Q)+': '+Listing);
Inc(Q);
end;
procedure TForm1.TabSheet3MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Label5.Caption := 'Current Dir: ';
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
NMFTP1.ChangeDir(DirTxt.Text);
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
NMFTP1.DownloadRestore(RemoteTxt.Text, LocalTxt.Text);
end;
procedure TForm1.NMFTP1PacketRecvd(Sender: TObject);
begin
StatusBar1.SimpleText := IntToStr(NMFTP1.BytesRecvd)+' of '+IntToStr(NMFTP1.BytesTotal);
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
NMFTP1.Abort;
end;
procedure TForm1.Button10Click(Sender: TObject);
begin
try NMFTP1.Upload(Edit3.Text, Edit4.Text); except end;
end;
procedure TForm1.Button11Click(Sender: TObject);
begin
try NMFTP1.UploadAppend(Edit3.Text, Edit4.Text); except end;
end;
procedure TForm1.Button12Click(Sender: TObject);
begin
try NMFTP1.UploadUnique(Edit3.Text); except end;
end;
procedure TForm1.Button13Click(Sender: TObject);
begin
try NMFTP1.UploadRestore(Edit3.Text,Edit4.Text,StrToInt(PosTxt.Text)); except end;
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
try NMFTP1.Download(RemoteTxt.Text, LocalTxt.Text); except end;
end;
procedure TForm1.Button14Click(Sender: TObject);
begin
NMFTP1.MakeDirectory(Edit1.Text);
end;
procedure TForm1.Button15Click(Sender: TObject);
begin
NMFTP1.RemoveDir(Edit2.Text);
end;
procedure TForm1.Button16Click(Sender: TObject);
begin
NMFTP1.Delete(Edit5.Text);
end;
procedure TForm1.Button17Click(Sender: TObject);
begin
NMFTP1.Reinitialize;
PageControl1.ActivePage := TabSheet2;
end;
procedure TForm1.NMFTP1Connect(Sender: TObject);
begin
StatusBar1.SimpleText := 'Connected';
end;
procedure TForm1.NMFTP1Failure(var handled: Boolean; Trans_Type: TCmdType);
begin
Case Trans_Type of
cmdChangeDir: StatusBar1.SimpleText := 'ChangeDir failure';
cmdMakeDir: StatusBar1.SimpleText := 'MakeDir failure';
cmdDelete: StatusBar1.SimpleText := 'Delete failure';
cmdRemoveDir: StatusBar1.SimpleText := 'RemoveDir failure';
cmdList: StatusBar1.SimpleText := 'List failure';
cmdRename: StatusBar1.SimpleText := 'Rename failure';
cmdUpRestore: StatusBar1.SimpleText := 'UploadRestore failure';
cmdDownRestore: StatusBar1.SimpleText := 'DownloadRestore failure';
cmdDownload: StatusBar1.SimpleText := 'Download failure';
cmdUpload: StatusBar1.SimpleText := 'Upload failure';
cmdAppend: StatusBar1.SimpleText := 'UploadAppend failure';
cmdReInit: StatusBar1.SimpleText := 'ReInit failure';
cmdAllocate: StatusBar1.SimpleText := 'Allocate failure';
cmdNList: StatusBar1.SimpleText := 'NList failure';
cmdDoCommand: StatusBar1.SimpleText := 'DoCommand failure';
end;
end;
procedure TForm1.NMFTP1TransactionStop(Sender: TObject);
begin
StatusBar1.SimpleText := 'Data Transfer Complete';
end;
procedure TForm1.NMFTP1HostResolved(Sender: TComponent);
begin
StatusBar1.SimpleText := 'Host resolved';
end;
procedure TForm1.NMFTP1InvalidHost(var handled: Boolean);
begin
ShowMessage('Invalid Host');
end;
procedure TForm1.NMFTP1PacketSent(Sender: TObject);
begin
StatusBar1.SimpleText := IntToStr(NMFTP1.BytesSent)+' of '+IntToStr(NMFTP1.BytesTotal);
end;
procedure TForm1.NMFTP1TransactionStart(Sender: TObject);
begin
StatusBar1.SimpleText := 'Beginning Data Transfer';
end;
procedure TForm1.NMFTP1Disconnect(Sender: TObject);
begin
If StatusBar1 <> nil then
StatusBar1.SimpleText := 'Disconnected';
end;
procedure TForm1.NMFTP1Error(Sender: TComponent; Errno: Word;
Errmsg: String);
begin
ShowMessage('Error '+IntToStr(Errno)+': '+Errmsg);
end;
procedure TForm1.NMFTP1Status(Sender: TComponent; Status: String);
begin
// If StatusBar1 <> nil then
// StatusBar1.SimpleText := status;
end;
procedure TForm1.Button18Click(Sender: TObject);
begin
NMFTP1.Rename(Edit8.Text,Edit9.Text);
end;
procedure TForm1.NMFTP1UnSupportedFunction(Trans_Type: TCmdType);
begin
Case Trans_Type of
cmdChangeDir: ShowMessage('ChangeDir unsupported');
cmdMakeDir: ShowMessage('MakeDir unsupported');
cmdDelete: ShowMessage('Delete unsupported');
cmdRemoveDir: ShowMessage('RemoveDir unsupported');
cmdList: ShowMessage('List unsupported');
cmdRename: ShowMessage('Rename unsupported');
cmdUpRestore: ShowMessage('UploadRestore unsupported');
cmdDownRestore: ShowMessage('DownloadRestore unsupported');
cmdDownload: ShowMessage('Download unsupported');
cmdUpload: ShowMessage('Upload unsupported');
cmdAppend: ShowMessage('UploadAppend unsupported');
cmdReInit: ShowMessage('ReInit unsupported');
cmdAllocate: ShowMessage('Allocate unsupported');
cmdNList: ShowMessage('NList unsupported');
cmdDoCommand: ShowMessage('DoCommand unsupported');
end;
end;
procedure TForm1.NMFTP1ConnectionFailed(Sender: TObject);
begin
ShowMessage('Connection Failed');
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
NMFTP1.Abort;
end;
end.