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.
101
2004/06/
04
08
:
29
:
30
_cvs_
stephen
Exp $
+
* $Id: ftp.pike,v 2.
102
2004/06/
06
22
:
04
:
33
_cvs_
dirix
Exp $
* * Henrik Grubbström <grubba@roxen.com> */ /* * TODO: * * How much is supposed to be logged? */
Roxen.git/server/plugins/protocols/ftp.pike:641:
{ User user; foreach(master_session->conf->user_databases(), UserDB user_db) { if (user = user_db->find_user_from_uid(uid)) { return user->name(); } } return (uid?((string)uid):"root"); }
-
string ls_l(string file,
array
st)
+
string ls_l(string file,
Stdio.Stat
st)
{ DWRITE("ls_l(\"%s\")\n", file);
-
int mode = st
[0]
& 007777;
+
int mode = st
->mode
& 007777;
array(string) perm = "----------"/"";
-
if (st
[1]
< 0) {
+
if (st
->size
< 0) {
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
[3]
);
+
mapping lt = localtime(st
->mtime
);
// NOTE: SiteBuilder may set st[5] and st[6] to strings.
-
string user = (string)st
[5]
;
-
string group = (string)st
[6]
;
+
string user = (string)st
->uid
;
+
string group = (string)st
->gid
;
if (!(flags & LS_FLAG_n)) { // Use symbolic names for uid and gid.
-
if (!stringp(st
[5]
)) {
-
user = name_from_uid(st
[5]
);
+
if (!stringp(st
->uid
)) {
+
user = name_from_uid(st
-uid
);
} // FIXME: Convert st[6] to symbolic group name. } string ts; int now = time(1); // Half a year: // 365.25*24*60*60/2 = 15778800
-
if ((st
[3]
<= now - 15778800) || (st
[3]
> now)) {
+
if ((st
->mtime
<= now - 15778800) || (st
->mtime
> now)) {
// Month Day Year ts = sprintf("%s %02d %04d", 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
[1]
<0? 512:st
[1]
),
+
user, (st
->type
<0? 512:st
-type
),
ts, file); } else { return sprintf("%s 1 %-10s %-6s %12d %s %s\n", perm*"",
-
user, group, (st
[1]
<0? 512:st
[1]
),
+
user, group, (st
->type
<0? 512:st
->type
),
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;
-
static
array|object stat_
file(string long, RequestID|void session)
+
Stdio.Stat
file_
stat(string long, RequestID|void session)
{
-
array|object
st = stat_cache[long];
+
Stdio.Stat
st = stat_cache[long];
if (zero_type(st)) { session = RequestID2(session || master_session); session->method = "DIR"; long = replace(long, "//", "/");
-
st = session->conf->
stat_
file(long, session);
+
st = session->conf->
file_
stat(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++) {
-
array|object
st =
stat_
file(combine_path(dir, files[i]));
+
Stdio.Stat
st =
file_
stat(combine_path(dir, files[i]));
if (st) {
-
sizes[i] = st
[1]
;
+
sizes[i] = st
->type
;
} 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++) {
-
array|object
st =
stat_
file(combine_path(dir, files[i]));
+
Stdio.Stat
st =
file_
stat(combine_path(dir, files[i]));
if (st) {
-
times[i] = -st
[
-
4]
; // Note: Negative time.
+
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);
-
array|object
st =
stat_
file(long);
+
Stdio.Stat
st =
file_
stat(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
[1]
< 0) {
+
if (st
->type
< 0) {
// Directory short += "/";
-
} else if (st
[0]
& 0111) {
+
} else if (st
->type
& 0111) {
// Executable short += "*"; } } int blocks = 1;
-
if (st
[1]
>= 0) {
-
blocks = (st
[1]
+ 1023)/1024; // Blocks are 1KB.
+
if (st
->type
>= 0) {
+
blocks = (st
->type
+ 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[".."] =
stat_
file(combine_path(long,"../"));
+
dir[".."] =
file_
stat(combine_path(long,"../"));
} else {
-
dir = ([ "..":
stat_
file(combine_path(long,"../")) ]);
+
dir = ([ "..":
file_
stat(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
[1]
< 0)) {
+
if (st && (st
->type
< 0)) {
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);
-
array|object
st =
stat_
file(long, session);
+
Stdio.Stat
st =
file_
stat(long, session);
if (st) {
-
if ((< -2, -3 >)[st
[1
]
]
&&
+
if ((< -2, -3 >)[st
->type
] &&
(!(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
mapping|array|object
stat_
file(string fname,
+
static private
Stdio.Stat
file_
stat(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->
stat_
file(fname, session);
+
file = conf->
file_
stat(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) {
-
object|array|mapping
file;
+
Stdio.Stat
file
= file_stat(fname, session)
;
-
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)) {
-
array|object
st = file;
+
Stdio.Stat
st = file;
file = 0;
-
if (st && (st
[1]
< 0) && !((<"RMD", "XRMD", "CHMOD">)[cmd])) {
+
if (st && (st
->type
< 0) && !((<"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:2329:
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->
stat_
file(id->not_query, id);
+
id->conf->
file_
stat(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
[0]
;
+
facts["UNIX.mode"] = st
->mode
;
-
if (st
[1]
>= 0) {
-
facts->size = (string)st
[1]
;
+
if (st
->type
>= 0) {
+
facts->size = (string)st
->type
;
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
[3]
);
+
facts->modify = make_MDTM(st
->mtime
);
facts->charset = "8bit"; // Construct and return the answer. return(Array.map(indices(facts), lambda(string s, mapping f) { return s + "=" + f[s]; }, facts) * ";" + " " + f); }
Roxen.git/server/plugins/protocols/ftp.pike:2809:
string home = auth_user->homedir(); if ((home == "") || (home[-1] != '/')) { home += "/"; } // Compatibility... master_session->misc->home = home; object session = RequestID2(master_session); session->method = "STAT";
-
array(int)|object
st = conf->
stat_
file(home, session);
+
Stdio.Stat
st = conf->
file_
stat(home, session);
destruct(session);
-
if (st && (st
[1]
< 0)) {
+
if (st && (st
->type
< 0)) {
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:2837:
string ncwd = fix_path(args); if ((ncwd == "") || (ncwd[-1] != '/')) { ncwd += "/"; } object session = RequestID2(master_session); session->method = "CWD"; session->not_query = ncwd;
-
array|object
st = conf->
stat_
file(ncwd, session);
+
Stdio.Stat
st = conf->
file_
stat(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
[1
]
]
) {
+
if (!(< -2, -3 >)[st
-type
]) {
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) {
-
array|object
st = conf->
stat_
file(replace(cwd + f, "//", "/"),
+
Stdio.Stat
st = conf->
file_
stat(replace(cwd + f, "//", "/"),
session);
-
if (st && (st
[1]
>= 0)) {
+
if (st && (st
->type
>= 0)) {
reply = ({ sprintf("Please read the file %s.", f), sprintf("It was last modified %s - %d days ago.",
-
ctime(st
[3]
) - "\n",
-
(time(1) - st
[3]
)/86400),
+
ctime(st
->mtime
) - "\n",
+
(time(1) - st
->mtime
)/86400),
"" }) + reply; } } } string message; catch { message = conf->try_get_file(cwd + ".message", session); }; if (message) { reply = (message/"\n")+({ "" })+reply;
Roxen.git/server/plugins/protocols/ftp.pike:3249:
static private string rename_from; // rename from void ftp_RNFR(string args) { if (!expect_argument("RNFR", args)) { return; } args = fix_path(args);
-
if (
stat_
file(args)) {
+
if (
file_
stat(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:3306:
} void ftp_MLST(string args) { args = fix_path(args || "."); RequestID session = RequestID2(master_session); session->method = "DIR";
-
array|object
st =
stat_
file(args, session);
+
Stdio.Stat
st =
file_
stat(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";
-
array|object
st =
stat_
file(args, session);
+
Stdio.Stat
st =
file_
stat(args, session);
-
if (st && (st
[1]
< 0)) {
+
if (st && (st
->type
< 0)) {
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:3383:
args = fix_path(args); RequestID session = RequestID2(master_session); session->data = 0; session->misc->len = 0; session->method = "DELETE"; session->not_query = args;
-
array|object
st =
stat_
file(args, session);
+
Stdio.Stat
st =
file_
stat(args, session);
if (!st) { send_error("RMD", args, session->file, session); destruct(session); return;
-
} else if (st
[1]
!= -2) {
-
if (st
[1]
== -3) {
+
} else if (st
->type
!= -2) {
+
if (st
->type
== -3) {
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:3479:
send(211, ({ "The following features are supported:" }) + a + ({ "END" })); } void ftp_MDTM(string args) { if (!expect_argument("MDTM", args)) { return; } args = fix_path(args);
-
mapping|array|object
st =
stat_
file(args);
+
Stdio.Stat
st =
file_
stat(args);
if (!arrayp(st) && !objectp(st)) { send_error("MDTM", args, st, master_session); } else {
-
send(213, ({ make_MDTM(st
[3]
) }));
+
send(213, ({ make_MDTM(st
->mtime
) }));
} } void ftp_SIZE(string args) { if (!expect_argument("SIZE", args)) { return; } args = fix_path(args);
-
mapping|array|object
st =
stat_
file(args);
+
Stdio.Stat
st =
file_
stat(args);
if (!arrayp(st) && !objectp(st)) { send_error("SIZE", args, st, master_session); return; }
-
int size = st
[1]
;
+
int size = st
->type
;
if (size < 0) { send_error("SIZE", args, ([ "error":405, ]), master_session); // size = 512; } else { send(213, ({ (string)size })); } } void ftp_STAT(string args) {
Roxen.git/server/plugins/protocols/ftp.pike:3550:
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);
-
mapping|array|object
st =
stat_
file(long);
+
Stdio.Stat
st =
file_
stat(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"); }