Roxen.git
/
server
/
plugins
/
protocols
/
ftp.pike
version
»
Context lines:
10
20
40
80
file
none
3
Roxen.git/server/plugins/protocols/ftp.pike:1:
// This is a roxen protocol module. // Copyright © 1997 - 2001, Roxen IS. /* * FTP protocol mk 2 *
-
* $Id: ftp.pike,v 2.
102
2004/06/
06
22
:
04
:
33
_cvs_
dirix
Exp $
+
* $Id: ftp.pike,v 2.
103
2004/06/
07
10
:
48
:
42
_cvs_
stephen
Exp $
* * Henrik Grubbström <grubba@roxen.com> */ /* * TODO: * * How much is supposed to be logged? */
Roxen.git/server/plugins/protocols/ftp.pike:648:
return (uid?((string)uid):"root"); } string ls_l(string file, Stdio.Stat st) { DWRITE("ls_l(\"%s\")\n", file); int mode = st->mode & 007777; array(string) perm = "----------"/"";
-
if (st->
size < 0
) {
+
if (st->
isdir
) {
perm[0] = "d"; } foreach(decode_mode, array(string|int) info) { if ((mode & info[0]) == info[1]) { perm[info[2]] = info[3]; } } mapping lt = localtime(st->mtime);
Roxen.git/server/plugins/protocols/ftp.pike:689:
months[lt->mon], lt->mday, 1900+lt->year); } else { // Month Day Hour:minute ts = sprintf("%s %02d %02d:%02d", months[lt->mon], lt->mday, lt->hour, lt->min); } if (flags & LS_FLAG_G) { // No group. return sprintf("%s 1 %-10s %12d %s %s\n", perm*"",
-
user,
(
st->
type<0? 512:st-type)
,
+
user, st->
size
,
ts, file); } else { return sprintf("%s 1 %-10s %-6s %12d %s %s\n", perm*"",
-
user, group,
(
st->
type<0? 512:st->type)
,
+
user, group, st->
size
,
ts, file); } } } class LSFile { static inherit LS_L; static string cwd;
Roxen.git/server/plugins/protocols/ftp.pike:715:
static object ftpsession; static array(string) output_queue = ({}); static int output_pos; static string output_mode = "A"; static mapping(string:array|object) stat_cache = ([]); static object conv;
-
Stdio.Stat
file_
stat(string long, RequestID|void session)
+
Stdio.Stat
stat_
file(string long, RequestID|void session)
{ Stdio.Stat st = stat_cache[long]; if (zero_type(st)) { session = RequestID2(session || master_session); session->method = "DIR"; long = replace(long, "//", "/");
-
st = session->conf->
file_
stat(long, session);
+
st = session->conf->
stat_
file(long, session);
stat_cache[long] = st; destruct(session); } return st; } // FIXME: Should convert output somewhere below. static void output(string s) { if(stringp(s)) {
Roxen.git/server/plugins/protocols/ftp.pike:771:
{ dir = dir || cwd; DWRITE("FTP: LSFile->list_files(%O, \"%s\"\n", files, dir); if (!(flags & LS_FLAG_U)) { if (flags & LS_FLAG_S) { array(int) sizes = allocate(sizeof(files)); int i; for (i=0; i < sizeof(files); i++) {
-
Stdio.Stat st =
file_
stat(combine_path(dir, files[i]));
+
Stdio.Stat st =
stat_
file(combine_path(dir, files[i]));
if (st) {
-
sizes[i] = st->
type
;
+
sizes[i] = st->
size
;
} else { // Should not happen, but... files -= ({ files[i] }); } } sort(sizes, files); } else if (flags & LS_FLAG_t) { array(int) times = allocate(sizeof(files)); int i; for (i=0; i < sizeof(files); i++) {
-
Stdio.Stat st =
file_
stat(combine_path(dir, files[i]));
+
Stdio.Stat st =
stat_
file(combine_path(dir, files[i]));
if (st) { times[i] = -st->mtime; // Note: Negative time. } else { // Should not happen, but... files -= ({ files[i] }); } } sort(times, files); } else { sort(files); } if (flags & LS_FLAG_r) { files = reverse(files); } } string res = ""; int total; foreach(files, string short) { string long = combine_path(dir, short);
-
Stdio.Stat st =
file_
stat(long);
+
Stdio.Stat st =
stat_
file(long);
if (st) { if (flags & LS_FLAG_Q) { // Enclose in quotes. // Space needs to be quoted to be compatible with -m short = "\"" + replace(short, ({ "\n", "\r", "\\", "\"", "\'", " " }), ({ "\\n", "\\r", "\\\\", "\\\"", "\\\'", "\\020" })) + "\""; } if (flags & LS_FLAG_F) {
-
if (st->
type < 0
) {
+
if (
!
st->
isreg
) {
// Directory short += "/";
-
} else if (st->
type
& 0111) {
+
} else if (st->
mode
& 0111) {
// Executable short += "*"; } } int blocks = 1;
-
if (st->
type >= 0
) {
-
blocks = (st->
type
+ 1023)/1024; // Blocks are 1KB.
+
if (st->
isreg
) {
+
blocks = (st->
size
+ 1023)/1024; // Blocks are 1KB.
} total += blocks; if (flags & LS_FLAG_s) { res += sprintf("%7d ", blocks); } if (flags & LS_FLAG_b) { short = quote_non_print(short); } if (flags & LS_FLAG_l) { res += ls_l(short, st);
Roxen.git/server/plugins/protocols/ftp.pike:904:
"find_dir_stat(\"%s\") => %O\n", long, dir); // Put them in the stat cache. foreach(indices(dir||({})), string f) { stat_cache[combine_path(long, f)] = dir[f]; } if ((flags & LS_FLAG_a) && (long != "/")) { if (dir) {
-
dir[".."] =
file_
stat(combine_path(long,"../"));
+
dir[".."] =
stat_
file(combine_path(long,"../"));
} else {
-
dir = ([ "..":
file_
stat(combine_path(long,"../")) ]);
+
dir = ([ "..":
stat_
file(combine_path(long,"../")) ]);
} } string listing = ""; if (dir && sizeof(dir)) { if (!(flags & LS_FLAG_A)) { foreach(indices(dir), string f) { if (sizeof(f) && (f[0] == '.')) { m_delete(dir, f); } }
Roxen.git/server/plugins/protocols/ftp.pike:928:
foreach(indices(dir), string f) { if ((< ".", ".." >)[f]) { m_delete(dir, f); } } } if (flags & LS_FLAG_R) { foreach(indices(dir), string f) { if (!((<".","..">)[f])) { array(mixed) st = dir[f];
-
if (st &&
(
st->
type < 0
)
)
{
+
if (st &&
!
st->
isreg
) {
if (short[-1] == '/') { dir_stack->push(short + f); } else { dir_stack->push(short + "/" + f); } } } } } if (sizeof(dir)) {
Roxen.git/server/plugins/protocols/ftp.pike:1041:
conv = Locale.Charset.encoder("EBCDIC-US", ""); } array(string) files = allocate(sizeof(argv)); int n_files; foreach(argv, string short) { RequestID session = RequestID2(master_session); session->method = "LIST"; string long = fix_path(short);
-
Stdio.Stat st =
file_
stat(long, session);
+
Stdio.Stat st =
stat_
file(long, session);
if (st) {
-
if ((
<
-
2,
-3
>)[
st->
type]
&&
+
if ((
st
-
>isdir
||
st->
islnk)
&&
(!(flags & LS_FLAG_d))) { // Directory dir_stack->push(short); } else { files[n_files++] = short; } } else { output(short + ": not found\n"); session->conf->log(([ "error":404 ]), session); }
Roxen.git/server/plugins/protocols/ftp.pike:1808:
if (session && session->file) { session->file->len = amount; session->conf->log(session->file, session); session->file = 0; } destruct(session); send(226, ({ "Transfer complete." })); }
-
static private Stdio.Stat
file_
stat(string fname,
+
static private Stdio.Stat
stat_
file(string fname,
object|void session) { mapping file; session = RequestID2(session || master_session); session->method = "STAT"; session->not_query = fname; foreach(conf->first_modules(), function funp) { if ((file = funp(session))) { break; } } if (!file) { fname = replace(fname, "//", "/");
-
file = conf->
file_
stat(fname, session);
+
file = conf->
stat_
file(fname, session);
} destruct(session); return file; } static private int expect_argument(string cmd, string args) { if ((< "", 0 >)[args]) { send(504, ({ sprintf("Syntax: %s %s", cmd, cmd_help[cmd]) })); return 0;
Roxen.git/server/plugins/protocols/ftp.pike:1883:
send(550, ({ sprintf("'%s': %s: No such file or directory.", cmd, f) })); break; } session->conf->sent = file->len; session->conf->log(file, session); } static private int open_file(string fname, object session, string cmd) {
-
Stdio.Stat file =
file_
stat(fname, session);
+
Stdio.Stat file =
stat_
file(fname, session);
// The caller is assumed to have made a new session object for us // but not to set not_query in it.. session->not_query = fname; if (objectp(file) || arrayp(file)) { Stdio.Stat st = file; file = 0;
-
if (st &&
(
st->
type
< 0)
&& !((<"RMD", "XRMD", "CHMOD">)[cmd])) {
+
if (st &&
!
st->
isreg
&& !((<"RMD", "XRMD", "CHMOD">)[cmd])) {
send(550, ({ sprintf("%s: not a plain file.", fname) })); return 0; } mixed err; if ((err = catch(file = conf->get_file(session)))) { report_error("FTP: Error opening file \"%s\"\n" "%s\n", fname, describe_backtrace(err)); send(550, ({ sprintf("%s: Error, can't open file.", fname) })); return 0; }
Roxen.git/server/plugins/protocols/ftp.pike:2327:
matches[i] *= "/"; } // Filter out non-existing or forbiden files/directories matches = Array.filter(matches, lambda(string short, string cwd, object m_id) { object id = RequestID2(m_id); id->method = "LIST"; id->not_query = combine_path(cwd, short); mapping res =
-
id->conf->
file_
stat(id->not_query, id);
+
id->conf->
stat_
file(id->not_query, id);
destruct(id); return res; }, cwd, master_session); if (sizeof(matches)) { args[index] = matches; } } } if (stringp(args[index])) { // No glob
Roxen.git/server/plugins/protocols/ftp.pike:2524:
string make_MLSD_fact(string f, mapping(string:array) dir, object session) { array st = dir[f]; mapping(string:string) facts = ([]); // Construct the facts here. facts["UNIX.mode"] = st->mode;
-
if (st->
type >= 0
) {
-
facts->size = (string)st->
type
;
+
if (st->
isreg
) {
+
facts->size = (string)st->
size
;
facts->type = "File"; facts["media-type"] = session->conf->type_from_filename(f) || "application/octet-stream"; } else { facts->type = ([ "..":"pdir", ".":"cdir" ])[f] || "dir"; } facts->modify = make_MDTM(st->mtime); facts->charset = "8bit";
Roxen.git/server/plugins/protocols/ftp.pike:2807:
string home = auth_user->homedir(); if ((home == "") || (home[-1] != '/')) { home += "/"; } // Compatibility... master_session->misc->home = home; object session = RequestID2(master_session); session->method = "STAT";
-
Stdio.Stat st = conf->
file_
stat(home, session);
+
Stdio.Stat st = conf->
stat_
file(home, session);
destruct(session);
-
if (st &&
(
st->
type < 0
)
)
{
+
if (st &&
!
st->
isreg
) {
cwd = home; } } logged_in = 1; send(230, ({ sprintf("User %s logged in.", user) })); conf->log(([ "error":202 ]), master_session); } void ftp_CWD(string args) {
Roxen.git/server/plugins/protocols/ftp.pike:2835:
string ncwd = fix_path(args); if ((ncwd == "") || (ncwd[-1] != '/')) { ncwd += "/"; } object session = RequestID2(master_session); session->method = "CWD"; session->not_query = ncwd;
-
Stdio.Stat st = conf->
file_
stat(ncwd, session);
+
Stdio.Stat st = conf->
stat_
file(ncwd, session);
ncwd = session->not_query; // Makes internal redirects to work. if (!st) { send(550, ({ sprintf("%s: No such file or directory, or access denied.", ncwd) })); session->conf->sent = session->file && session->file->len; session->conf->log(session->file || ([ "error":404 ]), session); destruct(session); return; }
-
if (!
(<
-
2,
-3
>)[
st-
type]
) {
+
if (!
st
-
>isdir
&&
!
st-
>islnk
) {
send(504, ({ sprintf("%s: Not a directory.", ncwd) })); session->conf->log(([ "error":400 ]), session); destruct(session); return; } // CWD Successfull cwd = ncwd; array(string) reply = ({ sprintf("Current directory is now %s.", cwd) }); // Check for .messages etc session->method = "GET"; // Important array(string) files = conf->find_dir(cwd, session); if (files) { files = reverse(sort(Array.filter(files, lambda(string s) { return(s[..5] == "README"); }))); foreach(files, string f) {
-
Stdio.Stat st = conf->
file_
stat(replace(cwd + f, "//", "/"),
+
Stdio.Stat st = conf->
stat_
file(replace(cwd + f, "//", "/"),
session);
-
if (st &&
(
st->
type >= 0
)
)
{
+
if (st && st->
isreg
) {
reply = ({ sprintf("Please read the file %s.", f), sprintf("It was last modified %s - %d days ago.", ctime(st->mtime) - "\n", (time(1) - st->mtime)/86400), "" }) + reply; } } } string message; catch {
Roxen.git/server/plugins/protocols/ftp.pike:3247:
static private string rename_from; // rename from void ftp_RNFR(string args) { if (!expect_argument("RNFR", args)) { return; } args = fix_path(args);
-
if (
file_
stat(args)) {
+
if (
stat_
file(args)) {
send(350, ({ sprintf("%s ok, waiting for destination name.", args) }) ); rename_from = args; } else { send(550, ({ sprintf("%s: no such file or permission denied.",args) }) ); } } void ftp_RNTO(string args) { if(!rename_from) {
Roxen.git/server/plugins/protocols/ftp.pike:3304:
} void ftp_MLST(string args) { args = fix_path(args || "."); RequestID session = RequestID2(master_session); session->method = "DIR";
-
Stdio.Stat st =
file_
stat(args, session);
+
Stdio.Stat st =
stat_
file(args, session);
if (st) { session->file = ([]); session->file->full_path = args; send_MLST_response(([ args:st ]), session); } else { send_error("MLST", args, session->file, session); } destruct(session); } void ftp_MLSD(string args) { args = fix_path(args || "."); RequestID session = RequestID2(master_session); session->method = "DIR";
-
Stdio.Stat st =
file_
stat(args, session);
+
Stdio.Stat st =
stat_
file(args, session);
-
if (st &&
(
st->
type < 0
)
)
{
+
if (st &&
!
st->
isreg
) {
if (args[-1] != '/') { args += "/"; } session->file = ([]); session->file->full_path = args; send_MLSD_response(session->conf->find_dir_stat(args, session), session); } else { if (st) { session->file->error = 405;
Roxen.git/server/plugins/protocols/ftp.pike:3381:
args = fix_path(args); RequestID session = RequestID2(master_session); session->data = 0; session->misc->len = 0; session->method = "DELETE"; session->not_query = args;
-
Stdio.Stat st =
file_
stat(args, session);
+
Stdio.Stat st =
stat_
file(args, session);
if (!st) { send_error("RMD", args, session->file, session); destruct(session); return;
-
} else if (st->
type != -2
) {
-
if (st->
type == -3
) {
+
} else if (st->
isdir
) {
+
if (st->
islnk
) {
send(504, ({ sprintf("%s is a module mountpoint.", args) })); session->conf->log(([ "error":405 ]), session); } else { send(504, ({ sprintf("%s is not a directory.", args) })); session->conf->log(([ "error":405 ]), session); } destruct(session); return; }
Roxen.git/server/plugins/protocols/ftp.pike:3477:
send(211, ({ "The following features are supported:" }) + a + ({ "END" })); } void ftp_MDTM(string args) { if (!expect_argument("MDTM", args)) { return; } args = fix_path(args);
-
Stdio.Stat st =
file_
stat(args);
+
Stdio.Stat st =
stat_
file(args);
if (!arrayp(st) && !objectp(st)) { send_error("MDTM", args, st, master_session); } else { send(213, ({ make_MDTM(st->mtime) })); } } void ftp_SIZE(string args) { if (!expect_argument("SIZE", args)) { return; } args = fix_path(args);
-
Stdio.Stat st =
file_
stat(args);
+
Stdio.Stat st =
stat_
file(args);
if (!arrayp(st) && !objectp(st)) { send_error("SIZE", args, st, master_session); return; }
-
int
size =
st->
type;
-
if (size < 0
) {
+
if
(!
st->
isreg
) {
send_error("SIZE", args, ([ "error":405, ]), master_session); // size = 512; } else {
-
send(213, ({ (string)size }));
+
send(213, ({ (string)
st->
size }));
} } void ftp_STAT(string args) { // According to RFC 1123 4.1.3.3, this command can be sent during // a file-transfer. // RFC 959 4.1.3: // The command may be sent during a file transfer (along with the // Telnet IP and Synch signals--see the Section on FTP Commands)
Roxen.git/server/plugins/protocols/ftp.pike:3548:
user?sprintf("as %s", user):"anonymously", (["A":"ASCII", "E":"EBCDIC", "I":"IMAGE", "L":"LOCAL"]) [mode], "Non-Print", "File", "Stream" )/"\n"); return; } string long = fix_path(args);
-
Stdio.Stat st =
file_
stat(long);
+
Stdio.Stat st =
stat_
file(long);
if (!arrayp(st) && !objectp(st)) { send_error("STAT", long, st, master_session); } else { string s = LS_L(master_session)->ls_l(args, st); send(213, sprintf("status of \"%s\":\n" "%s" "End of Status", args, s)/"\n"); }