$ include "seed7_05.s7i";
include "osfiles.s7i";
include "fileutil.s7i";
include "ftp.s7i";
include "keybd.s7i";
include "console.s7i";
include "editline.s7i";
const proc: writeHelp is func
begin
writeln("Accepted commands:");
writeln(" ascii, binary, bye, cd, delete, dir, exit, get, help, lcd, ls, ls -l,");
writeln(" mkdir, modtime, put, pwd, quit, rename, rmdir, size");
writeln;
end func;
const proc: longFileListing (inout fileSys: aFileSys, in var string: directory) is func
local
var array string: dir is 0 times "";
var integer: currentYear is 0;
var string: fileName is "";
var string: filePath is "";
var boolean: continue is TRUE;
var string: line is "";
var fileType: aFileType is FILE_ABSENT;
var time: modificationTime is time.value;
const string: fileTypeIndicator is " ?-dcbfls";
const array string: monthName is [1] (
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
begin
if directory = "" then
dir := readDir(aFileSys, ".");
else
dir := readDir(aFileSys, directory);
directory &:= "/";
end if;
currentYear := time(NOW).year;
for fileName range dir do
if getc(KEYBOARD, NO_WAIT) = KEY_CTL_C then
writeln(" ***** Terminated.");
continue := FALSE;
end if;
if continue then
filePath := directory & fileName;
aFileType := fileType(aFileSys, filePath);
line := str(fileTypeIndicator[succ(aFileType)]);
line &:= "rwxrwxrwx 1 user users ";
if aFileType = FILE_ABSENT then
line &:= 0 lpad 10 <& " ";
modificationTime := time(NOW);
else
line &:= bigFileSize(aFileSys, filePath) lpad 10 <& " ";
modificationTime := getMTime(aFileSys, filePath);
end if;
line &:= monthName[modificationTime.month];
line &:= modificationTime.day lpad 3;
if modificationTime.year = currentYear then
line &:= modificationTime.hour lpad 3 <& ":";
line &:= modificationTime.minute lpad0 2;
else
line &:= modificationTime.year lpad 6;
end if;
line &:= " ";
line &:= noCtrlChars(fileName);
writeln(line);
end if;
end for;
end func;
const proc: fileListing (inout fileSys: aFileSys, in string: directory) is func
local
var array string: dir is 0 times "";
var string: name is "";
var boolean: continue is TRUE;
begin
if directory = "" then
dir := readDir(aFileSys, ".");
else
dir := readDir(aFileSys, directory);
end if;
for name range dir do
if getc(KEYBOARD, NO_WAIT) = KEY_CTL_C then
writeln(" ***** Terminated.");
continue := FALSE;
end if;
if continue then
writeln(noCtrlChars(name));
end if;
end for;
end func;
const proc: directoryListing (inout ftpFileSys: ftp, in string: directory) is func
local
var array string: dir is 0 times "";
var string: line is "";
var boolean: continue is TRUE;
begin
if directory = "" then
dir := listDir(ftp, ".");
else
dir := listDir(ftp, directory);
end if;
for line range dir do
if getc(KEYBOARD, NO_WAIT) = KEY_CTL_C then
writeln(" ***** Terminated.");
continue := FALSE;
end if;
if continue then
writeln(noCtrlChars(line));
end if;
end for;
end func;
const proc: copyFtpFile (inout fileSys: sourceSys, in string: sourcePath,
inout fileSys: destSys, in string: destPath, in boolean: asciiTransfer) is func
local
var string: asciiMode is "";
var file: source is STD_NULL;
var file: dest is STD_NULL;
begin
if asciiTransfer then
asciiMode := "t";
end if;
source := open(sourceSys, sourcePath, "r" & asciiMode);
if source <> STD_NULL then
dest := open(destSys, destPath, "w" & asciiMode);
if dest <> STD_NULL then
copyFile(source, dest);
close(dest);
else
writeln(" ***** Cannot open destination: " <& destPath);
end if;
close(source);
else
writeln(" ***** Cannot open source: " <& sourcePath);
end if;
end func;
const proc: execute (inout ftpFileSys: ftp, in string: command) is func
local
var array string: dir is 0 times "";
var string: name is "";
var integer: blankPos is 0;
var boolean: continue is TRUE;
begin
if startsWith(command, "ls -l") then
longFileListing(ftp, trim(command[7 ..]));
elsif startsWith(command, "ls") then
fileListing(ftp, trim(command[4 ..]));
elsif startsWith(command, "dir") then
directoryListing(ftp, trim(command[5 ..]));
elsif startsWith(command, "cd ") then
chdir(ftp, trim(command[4 ..]));
elsif startsWith(command, "mkdir ") then
makeDir(ftp, trim(command[7 ..]));
elsif startsWith(command, "rmdir ") then
rmdir(ftp, trim(command[7 ..]));
elsif startsWith(command, "delete ") then
removeFile(ftp, trim(command[8 ..]));
elsif startsWith(command, "rename ") then
name := trim(command[8 ..]);
if name = "" then
writeln(" ***** From-name missing");
else
blankPos := pos(name, ' ');
if blankPos <> 0 then
moveFile(ftp, name[.. pred(blankPos)], name[succ(blankPos) ..]);
else
writeln(" ***** To-name missing");
end if;
end if;
elsif command = "pwd" then
writeln(getcwd(ftp));
elsif startsWith(command, "size ") then
writeln(fileSize(ftp, trim(command[6 ..])));
elsif startsWith(command, "modtime ") then
writeln(getMTime(ftp, trim(command[9 ..])));
elsif startsWith(command, "lcd ") then
chdir(trim(command[5 ..]));
elsif startsWith(command, "ascii") then
setAsciiTransfer(ftp, TRUE);
elsif startsWith(command, "binary") then
setAsciiTransfer(ftp, FALSE);
elsif startsWith(command, "get ") then
copyFtpFile(ftp, trim(command[5 ..]), osFiles, trim(command[5 ..]),
getAsciiTransfer(ftp));
elsif startsWith(command, "put ") then
copyFtpFile(osFiles, trim(command[5 ..]), ftp, trim(command[5 ..]),
getAsciiTransfer(ftp));
elsif startsWith(command, "!ls -l") or startsWith(command, "!dir") then
longFileListing(osFiles, trim(command[7 ..]));
elsif startsWith(command, "!ls") then
fileListing(osFiles, trim(command[4 ..]));
elsif command = "!pwd" then
writeln(getcwd(osFiles));
elsif startsWith(command, "!mkdir ") then
makeDir(osFiles, trim(command[7 ..]));
elsif startsWith(command, "!rmdir ") then
rmdir(osFiles, trim(command[7 ..]));
elsif startsWith(command, "help") then
writeHelp;
elsif command <> "" then
writeln(" ***** Invalid command.");
end if;
end func;
const proc: main is func
local
var string: command is "";
var integer: ftpControlPort is defaultFtpControlPort;
var ftpFileSys: ftp is fileSys.value;
begin
writeln("Ftp7 Version 1.0 - FTP internet file transfer program");
writeln("Copyright (C) 2011 Thomas Mertes");
writeln("This is free software; see the source for copying conditions. There is NO");
writeln("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
writeln("Ftp7 is written in the Seed7 programming language");
writeln("Homepage: http://seed7.sourceforge.net");
writeln;
writeln("usage: ftp7 host [port]");
writeln;
if length(argv(PROGRAM)) = 0 then
writeln("Use ftp7 -? to get more information about ftp7.");
writeln;
elsif length(argv(PROGRAM)) = 1 and argv(PROGRAM)[1] = "-?" then
writeHelp;
else
writeHelp;
OUT := STD_CONSOLE;
IN := openEditLine(KEYBOARD, OUT);
if length(argv(PROGRAM)) >= 2 and isDigitString(argv(PROGRAM)[2]) then
block
ftpControlPort := integer(argv(PROGRAM)[2]);
exception
catch RANGE_ERROR: writeln(" ***** Port number too big. Port " <&
defaultFtpControlPort <& " used instead.");
end block;
end if;
ftp := openFtp(argv(PROGRAM)[1], ftpControlPort);
if ftp = fileSys.value then
writeln(" ***** Could not connect to " <& argv(PROGRAM)[1] <&
" at port " <& ftpControlPort <& ".");
else
writeln("Connected with: " <& argv(PROGRAM)[1] <&
" at port " <& ftpControlPort <& ".");
write("ftp7> ");
readln(command);
while command <> "exit" and command <> "bye" and command <> "quit" do
block
execute(ftp, command);
exception
catch FILE_ERROR: writeln(" ***** Command failed.");
end block;
write("ftp7> ");
readln(command);
end while;
close(ftp);
end if;
end if;
end func;