MODULE FTP;
IMPORT
FTPClient, Commands, Streams, Files, Texts, TextUtilities;
CONST
BufSize = 16*1024;
LocalFileNotFound = -2;
VAR ftp : FTPClient.FTPClient;
PROCEDURE PutFile(ftp : FTPClient.FTPClient; local, remote : ARRAY OF CHAR; VAR res : LONGINT);
VAR buf: ARRAY BufSize OF CHAR; len: LONGINT;
f : Files.File; r : Files.Reader;
w : Streams.Writer;
BEGIN
f := Files.Old(local);
IF f = NIL THEN res := LocalFileNotFound; RETURN END;
Files.OpenReader(r, f, 0);
ftp.OpenPut(remote, w, res);
IF res = 0 THEN
REPEAT
r.Bytes(buf, 0, BufSize, len); w.Bytes(buf, 0, len);
UNTIL r.res # 0;
w.Update;
ftp.ClosePut(res);
END;
END PutFile;
PROCEDURE PutText(ftp : FTPClient.FTPClient; local, remote : ARRAY OF CHAR; VAR res : LONGINT);
VAR w : Streams.Writer;
text: Texts.Text;
r: Texts.TextReader;
ch: Texts.Char32;
i: LONGINT;
BEGIN
NEW(text);
TextUtilities.LoadOberonText(text, local, res);
IF res # 0 THEN res:= LocalFileNotFound; RETURN END;
text.AcquireRead;
NEW(r, text);
ftp.OpenPut(remote, w, res);
IF res = 0 THEN
FOR i := 0 TO text.GetLength() - 1 DO
r.ReadCh(ch);
IF (ch >= 0) & (ch < 128) THEN w.Char(CHR(ch)) END;
END;
w.Update;
ftp.ClosePut(res)
END;
text.ReleaseRead
END PutText;
PROCEDURE GetFile(ftp : FTPClient.FTPClient; remote, local : ARRAY OF CHAR; VAR res : LONGINT);
VAR buf: ARRAY BufSize OF CHAR; len: LONGINT;
f : Files.File; w : Files.Writer;
r : Streams.Reader;
BEGIN
f := Files.New(local);
Files.OpenWriter(w, f, 0);
ftp.OpenGet(remote, r, res);
IF res = 0 THEN
REPEAT
r.Bytes(buf, 0, BufSize, len); w.Bytes(buf, 0, len);
UNTIL r.res # 0;
w.Update;
Files.Register(f);
ftp.CloseGet(res)
END;
END GetFile;
PROCEDURE Open*(context : Commands.Context);
VAR
host, user, password : ARRAY 256 OF CHAR;
res : LONGINT;
BEGIN
IF ftp # NIL THEN
context.out.String("Already open"); context.out.Ln;
RETURN;
END;
context.arg.SkipWhitespace; context.arg.String(host);
context.arg.SkipWhitespace; context.arg.String(user);
context.arg.SkipWhitespace; context.arg.String(password);
context.out.String("host = "); context.out.String(host); context.out.Ln;
context.out.String("user = "); context.out.String(user); context.out.Ln;
context.out.String("password = "); context.out.String(password); context.out.Ln;
NEW(ftp);
ftp.Open(host, user, password, 21, res);
context.out.String(ftp.msg);
IF res = 0 THEN
context.out.String("Connected"); context.out.Ln;
ELSE
ftp := NIL;
context.out.String("Connecting failed"); context.out.Ln;
END;
END Open;
PROCEDURE PutFiles*(context : Commands.Context);
VAR
local, path, remote : ARRAY 256 OF CHAR;
tok : ARRAY 8 OF CHAR;
res : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not connected"); context.out.Ln;
RETURN;
END;
REPEAT
context.arg.SkipWhitespace; context.arg.String(local);
Files.SplitPath(local, path, remote);
context.arg.SkipWhitespace;
IF context.arg.Peek() = "=" THEN
context.arg.Token(tok);
IF tok # "=>" THEN
context.out.String("=> expected");
RETURN;
END;
context.arg.SkipWhitespace; context.arg.String(remote)
END;
IF (local # "") & (remote # "") THEN
PutFile(ftp, local, remote, res);
IF res = 0 THEN context.out.String(local); context.out.String(" copied to "); context.out.String(remote); context.out.Ln
ELSIF res = LocalFileNotFound THEN context.out.String("Local file "); context.out.String(local); context.out.String(" not found "); context.out.Ln
ELSE context.out.String("upload failed on remote file "); context.out.String(remote); context.out.Ln
END;
END
UNTIL context.arg.res # 0;
END PutFiles;
PROCEDURE PutTexts*(context : Commands.Context);
VAR
local, path, remote : ARRAY 256 OF CHAR;
tok : ARRAY 8 OF CHAR;
res : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not connected"); context.out.Ln;
RETURN;
END;
REPEAT
context.arg.SkipWhitespace; context.arg.String(local);
Files.SplitPath(local, path, remote);
context.arg.SkipWhitespace;
IF context.arg.Peek() = "=" THEN
context.arg.Token(tok);
IF tok # "=>" THEN
context.out.String("=> expected");
RETURN;
END;
context.arg.SkipWhitespace; context.arg.String(remote);
END;
IF (local # "") & (remote # "") THEN
PutText(ftp, local, remote, res);
IF res = 0 THEN context.out.String(local); context.out.String(" copied to "); context.out.String(remote); context.out.Ln
ELSIF res = LocalFileNotFound THEN context.out.String("Local file "); context.out.String(local); context.out.String(" not found "); context.out.Ln
ELSE context.out.String("upload failed on remote file "); context.out.String(remote); context.out.Ln
END;
END
UNTIL context.arg.res # 0;
END PutTexts;
PROCEDURE GetFiles*(context : Commands.Context);
VAR
local, remote : ARRAY 256 OF CHAR;
tok : ARRAY 8 OF CHAR;
res : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not connected"); context.out.Ln;
RETURN;
END;
REPEAT
context.arg.SkipWhitespace; context.arg.String(remote);
COPY(remote, local);
context.arg.SkipWhitespace;
IF context.arg.Peek() = "=" THEN
context.arg.Token(tok);
IF tok # "=>" THEN
context.out.String("=> expected");
RETURN;
END;
context.arg.SkipWhitespace; context.arg.String(local);
END;
IF (local # "") & (remote # "") THEN
GetFile(ftp, remote, local, res);
IF res = 0 THEN context.out.String(remote); context.out.String(" downloaded to "); context.out.String(local); context.out.Ln
ELSE context.out.String("download failed on remote file "); context.out.String(remote); context.out.Ln
END;
END
UNTIL context.arg.res # 0;
END GetFiles;
PROCEDURE MakeDir*(context : Commands.Context);
VAR
path : ARRAY 256 OF CHAR;
res : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not open"); context.out.Ln;
RETURN;
END;
context.arg.String(path);
ftp.MakeDir(path, res);
IF res = 0 THEN context.out.String("Directory created."); context.out.Ln
ELSE context.out.String("Failed creating directory."); context.out.Ln
END;
END MakeDir;
PROCEDURE ChangeDir*(context : Commands.Context);
VAR
path : ARRAY 256 OF CHAR;
res : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not open"); context.out.Ln;
RETURN;
END;
context.arg.String(path);
ftp.ChangeDir(path, res);
IF res = 0 THEN context.out.String("Directory changed."); context.out.Ln
ELSE context.out.String("Failed changing directory."); context.out.Ln
END;
ftp.GetCurrentDir(path, res);
IF res = 0 THEN context.out.String("New remote dir is : "); context.out.String(path); context.out.Ln END;
END ChangeDir;
PROCEDURE Directory*(context : Commands.Context);
VAR i : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not open"); context.out.Ln;
RETURN;
END;
ftp.EnumerateDir("");
FOR i := 0 TO ftp.nofEntries-1 DO
context.out.String(ftp.listing[i].full); context.out.Ln;
END;
END Directory;
PROCEDURE Close*(context : Commands.Context);
VAR res : LONGINT;
BEGIN
IF ftp = NIL THEN
context.out.String("not connected"); context.out.Ln;
RETURN;
END;
ftp.Close(res);
context.out.String("closed."); context.out.String(ftp.msg); context.out.Ln;
ftp := NIL;
END Close;
END FTP.
FTP.Open www.ocp.inf.ethz.ch "ocp" "download" ~
FTP.Directory ~
FTP.ChangeDir <directoryname> ~
FTP.PutFiles <list of filenames> ~
FTP.GetFiles <list of filenames> ~
FTP.Close ~
SystemTools.Free FTP FTPClient ~