Roxen.git / server / plugins / protocols / ftp.pike

version» Context lines:

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.92 2004/05/17 13:17:23 mani Exp $ +  * $Id: ftp.pike,v 2.93 2004/05/17 13:20:05 mani Exp $    *    * Henrik Grubbström <grubba@roxen.com>    */      /*    * TODO:    *    * How much is supposed to be logged?    */   
Roxen.git/server/plugins/protocols/ftp.pike:165: Inside #if defined(FTP_REQUESTID_DEBUG)
   {   #ifdef FTP_REQUESTID_DEBUG    report_debug("REQUESTID: Destroy request id #%d.\n", _num);   #endif    }       void create(object|void m_rid)    {   #ifdef FTP_REQUESTID_DEBUG    _num = ++__num[0]; -  report_debug("REQUESTID: New request id #%d.\n", _num); +  if (m_rid) { +  report_debug("REQUESTID: New request id #%d (CHILD to #%d).\n", +  _num, m_rid->_num); +  } else { +  report_debug("REQUESTID: New request id #%d (MASTER).\n", _num); +  }   #else    DWRITE("REQUESTID: New request id.\n");   #endif       if (m_rid) {    this_program o = this;    foreach(indices(m_rid), string var) {    if (!(< "create", "connection", "configuration",    "__INIT", "clone_me", "end", "ready_to_receive",    "send", "scan_for_query", "send_result", "misc",
Roxen.git/server/plugins/protocols/ftp.pike:705:    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)    {    array|object st = stat_cache[long];    if (zero_type(st)) { -  if (!session) { -  session = RequestID2(master_session); +  session = RequestID2(session || master_session);    session->method = "DIR"; -  } +     long = replace(long, "//", "/");    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)) {    // ls is always ASCII-mode...    s = replace(s, "\n", "\r\n");
Roxen.git/server/plugins/protocols/ftp.pike:872:    }    RequestID session = RequestID2(master_session);    session->method = "DIR";       mixed err;    mapping(string:array) dir;    err = catch {    dir = session->conf->find_dir_stat(long, session);    };    +  destruct(session); +     if (err) {    report_error("FTP: LSFile->list_next_directory(): "    "find_dir_stat(\"%s\") failed:\n"    "%s\n", long, describe_backtrace(err));    }       DWRITE("FTP: LSFile->list_next_directory(): "    "find_dir_stat(\"%s\") => %O\n", long, dir);       // Put them in the stat cache.
Roxen.git/server/plugins/protocols/ftp.pike:1039:    (!(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);    } +  destruct(session);    }       DWRITE("FTP: LSFile: %d files, %d directories\n",    n_files, dir_stack->ptr);       if (n_files) {    if (n_files < sizeof(files)) {    files -= ({ 0 });    }    string s = list_files(files, cwd); // May modify dir_stack (-R)    output(s);    RequestID session = RequestID2(master_session);    session->not_query = Array.map(files, fix_path) * " ";    session->method = "LIST";    session->conf->sent = sizeof(s);    session->conf->log(([ "error":200, "len":sizeof(s) ]), session); -  +  destruct(session);    }    if (dir_stack->ptr) {    name_directories = dir_stack->ptr &&    ((dir_stack->ptr > 1) || n_files);       list_next_directory();    } else {    output(0);    }    }
Roxen.git/server/plugins/protocols/ftp.pike:1787:    fd = 0;    //BACKEND_CLOSE(fd);    }    curr_pipe = 0;       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,    object|void session)    {    mapping file;    -  if (!session) { -  session = RequestID2(master_session); +  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, "//", "/"); -  return(conf->stat_file(fname, session)); +  file = conf->stat_file(fname, session);    } -  return(file); +  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;    }    return 1;    }
Roxen.git/server/plugins/protocols/ftp.pike:1951:    send(150, ({ sprintf("Opening %s data connection for %s (%d bytes).",    modes[file->mode], file->full_path, file->len) }));    } else {    send(150, ({ sprintf("Opening %s mode data connection for %s",    modes[file->mode], file->full_path) }));    }    }    else    {    send(425, ({ "Can't build data connect: Connection refused." })); +  destruct(session);    return;    }    switch(file->mode) {    case "A":    if (file->data) {    file->data = replace(file->data,    ({ "\r\n", "\n", "\r" }),    ({ "\r\n", "\r\n", "\r\n" }));    }    if(objectp(file->file) && file->file->set_nonblocking)
Roxen.git/server/plugins/protocols/ftp.pike:2074:    break;    case 501:    send(502, ({ sprintf("%s: Command not implemented.", args) }));    break;    default:    send(550, ({ sprintf("%s: Error opening file.", args) }));    break;    }    session->conf->sent = session->file->len;    session->conf->log(session->file, session); +  destruct(session);    return;    }    master_session->file = session->file;    } else {    // Error message has already been sent.    if (fd) {    BACKEND_CLOSE(fd);    } -  +  destruct(session);    }    }       static private void discard_data_connection() {    if(pasv_port && sizeof(pasv_accepted))    pasv_accepted = pasv_accepted[1..];    }       static private void connect_and_send(mapping file, object session)    {
Roxen.git/server/plugins/protocols/ftp.pike:2273:    }    foreach(sort(dir), string f) {    array(string) arr = my_combine_path_array(path, f);    string p = arr*"/";    if (!paths[p]) {    paths[p] = 1;    new_matches += ({ arr });    }    }    } +  destruct(id);    }    matches = new_matches;    } else {    // No glob    // Just add the part. Modify matches in-place.    for(i=0; i<sizeof(matches); i++) {    matches[i] = my_combine_path_array(matches[i], part);    string path = matches[i]*"/";    if (paths[path]) {    matches[i] = 0;
Roxen.git/server/plugins/protocols/ftp.pike:2305:    for (i=0; i < sizeof(matches); i++) {    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); -  return(id->conf->stat_file(id->not_query, -  id)); +  mapping res = +  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    args[index] = ({ my_combine_path("", args[index]) });    }
Roxen.git/server/plugins/protocols/ftp.pike:2785:    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); +  destruct(session);       if (st && (st[1] < 0)) {    cwd = home;    }    }    logged_in = 1;    send(230, ({ sprintf("User %s logged in.", user) }));    conf->log(([ "error":202 ]), master_session);    }   
Roxen.git/server/plugins/protocols/ftp.pike:2818:    session->method = "CWD";    session->not_query = ncwd;       array|object 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[1]]) {    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
Roxen.git/server/plugins/protocols/ftp.pike:2865:    message = conf->try_get_file(cwd + ".message", session);    };    if (message) {    reply = (message/"\n")+({ "" })+reply;    }       session->method = "CWD"; // Restore it again.    send(250, reply);    session->conf->sent = sizeof(reply * "\n");    session->conf->log(([ "error":200, "len":session->conf->sent ]), session); +  destruct(session);    }       void ftp_XCWD(string args)    {    ftp_CWD(args);    }       void ftp_CDUP(string args)    {    ftp_CWD("../");
Roxen.git/server/plugins/protocols/ftp.pike:3150:    restart_point -= sizeof(session->file->data);    m_delete(session->file, "data");    }    }    if (restart_point) {    if (!(session->file->file && session->file->file->seek &&    (session->file->file->seek(restart_point) != -1))) {    restart_point = 0;    send(550, ({ "'RETR': Error restoring restart point." }));    discard_data_connection(); +  destruct(session);    return;    }    restart_point = 0;    }    }       connect_and_send(session->file, session);    } -  else +  else {    discard_data_connection(); -  +  destruct(session);    } -  +  }       void ftp_STOR(string args)    {    if (!expect_argument("STOR", args)) {    return;    }       args = fix_path(args);       connect_and_receive(args);
Roxen.git/server/plugins/protocols/ftp.pike:3227:    RequestID session = RequestID2(master_session);       session->method = "STAT";       if (stat_file(args, session)) {    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) }) );    } +  destruct(session);    }       void ftp_RNTO(string args)    {    if(!rename_from) {    send(503, ({ "RNFR needed before RNTO." }));    return;    }    if (!expect_argument("RNTO", args)) {    return;
Roxen.git/server/plugins/protocols/ftp.pike:3250:    RequestID session = RequestID2(master_session);       session->method = "MV";    session->misc->move_from = rename_from;    session->not_query = args;    if (open_file(args, session, "MOVE")) {    send(250, ({ sprintf("%s moved to %s.", rename_from, args) }));    session->conf->log(([ "error":200 ]), session);    }    rename_from = 0; +  destruct(session);    }          void ftp_NLST(string args)    {    // ftp_MLST(args); return;       array(string) argv = glob_expand_command_line("/usr/bin/ls " + (args||""));       call_ls(argv);
Roxen.git/server/plugins/protocols/ftp.pike:3286:       array|object 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";   
Roxen.git/server/plugins/protocols/ftp.pike:3313:    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;    }    send_error("MLSD", args, session->file, session);    discard_data_connection();    } +  destruct(session);    }       void ftp_DELE(string args)    {    if (!expect_argument("DELE", args)) {    return;    }       args = fix_path(args);       RequestID session = RequestID2(master_session);       session->data = 0;    session->misc->len = 0;    session->method = "DELETE";       if (open_file(args, session, "DELE")) {    send(250, ({ sprintf("%s deleted.", args) }));    session->conf->log(([ "error":200 ]), session); -  return; +     } -  +  destruct(session);    }       void ftp_RMD(string args)    {    if (!expect_argument("RMD", args)) {    return;    }       args = fix_path(args);       RequestID session = RequestID2(master_session);       session->data = 0;    session->misc->len = 0;    session->method = "DELETE";       array|object st = stat_file(args, session);       if (!st) {    send_error("RMD", args, session->file, session); -  +  destruct(session);    return;    } else if (st[1] != -2) {    if (st[1] == -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;    }       if (open_file(args, session, "RMD")) {    send(250, ({ sprintf("%s deleted.", args) }));    session->conf->log(([ "error":200 ]), session); -  return; +     } -  +  destruct(session);    }       void ftp_XRMD(string args)    {    ftp_RMD(args);    }       void ftp_MKD(string args)    {    if (!expect_argument("MKD", args)) {
Roxen.git/server/plugins/protocols/ftp.pike:3395:       RequestID session = RequestID2(master_session);       session->method = "MKDIR";    session->data = 0;    session->misc->len = 0;       if (open_file(args, session, "MKD")) {    send(257, ({ sprintf("\"%s\" created.", args) }));    session->conf->log(([ "error":200 ]), session); -  return; +     } -  +  destruct(session);    }       void ftp_XMKD(string args)    {    ftp_MKD(args);    }       void ftp_SYST(string args)    {    send(215, ({ "UNIX Type: L8: ChiliMoon Internet Server"}));
Roxen.git/server/plugins/protocols/ftp.pike:3449:    if (!expect_argument("MDTM", args)) {    return;    }    args = fix_path(args);    RequestID session = RequestID2(master_session);    session->method = "STAT";    mapping|array|object st = stat_file(args, session);       if (!arrayp(st) && !objectp(st)) {    send_error("MDTM", args, st, session); -  return; -  } +  } else {    send(213, ({ make_MDTM(st[3]) }));    } -  +  destruct(session); +  }       void ftp_SIZE(string args)    {    if (!expect_argument("SIZE", args)) {    return;    }    args = fix_path(args);       RequestID session = RequestID2(master_session);    session->method = "STAT";    mapping|array|object st = stat_file(args, session);       if (!arrayp(st) && !objectp(st)) {    send_error("SIZE", args, st, session); -  +  destruct(session);    return;    }    int size = st[1];    if (size < 0) {    send_error("SIZE", args, ([ "error":405, ]), session); -  return; +     // size = 512; -  } +  } else {    send(213, ({ (string)size }));    } -  +  destruct(session); +  }       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)    // in which case the server will respond with the status of the    // operation in progress, [...]
Roxen.git/server/plugins/protocols/ftp.pike:3524:    )/"\n");    return;    }    string long = fix_path(args);    RequestID session = RequestID2(master_session);    session->method = "STAT";    mapping|array|object st = stat_file(long);       if (!arrayp(st) && !objectp(st)) {    send_error("STAT", long, st, session); -  return; -  } -  +  } 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");    } -  +  destruct(session); +  }       void ftp_NOOP(string args)    {    send(200, ({ "Nothing done ok" }));    }       void ftp_HELP(string args)    {    if ((< "", 0 >)[args]) {    send(214, ({
Roxen.git/server/plugins/protocols/ftp.pike:3643:    RequestID session = RequestID2(master_session);       session->method = "CHMOD";    session->misc->mode = mode;    session->not_query = fname;    if (open_file(fname, session, "CHMOD")) {    send(250, ({ sprintf("Changed permissions of %s to 0%o.",    fname, mode) }));    session->conf->log(([ "error":200 ]), session);    } +  destruct(session);    }       void ftp_SITE_UMASK(array(string) args)    {    if (sizeof(args) < 1) {    send(501, ({ sprintf("'SITE UMASK %s': incorrect arguments",    args*" ") }));    return;    }   
Roxen.git/server/plugins/protocols/ftp.pike:3832:    destruct();    }       void destroy()    {    DWRITE("FTP2: destroy()\n");       logout();       port_obj->sessions--; +  if (master_session) { +  destruct(master_session);    } -  +  }       void create(object fd, object c)    {    port_obj = c;       // FIXME: Only supports one configuration!    conf = port_obj->urls[port_obj->sorted_urls[0]]->conf;       // Support delayed loading.    if (!conf->inited) {