Return-Path: Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: (qmail 83761 invoked from network); 13 Jul 2009 23:54:22 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 13 Jul 2009 23:54:22 -0000 Received: (qmail 21535 invoked by uid 500); 13 Jul 2009 23:54:31 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 21440 invoked by uid 500); 13 Jul 2009 23:54:31 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 21431 invoked by uid 99); 13 Jul 2009 23:54:31 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Jul 2009 23:54:31 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Jul 2009 23:54:26 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id A0A4E2388897; Mon, 13 Jul 2009 23:54:05 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r793756 - in /httpd/mod_ftp/trunk: STATUS-FTP include/mod_ftp.h modules/ftp/ftp_commands.c modules/ftp/ftp_internal.h modules/ftp/ftp_protocol.c modules/ftp/mod_ftp.c Date: Mon, 13 Jul 2009 23:54:05 -0000 To: cvs@httpd.apache.org From: wrowe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090713235405.A0A4E2388897@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: wrowe Date: Mon Jul 13 23:54:04 2009 New Revision: 793756 URL: http://svn.apache.org/viewvc?rev=793756&view=rev Log: Refactor HELP and FEAT to work around a roadblock. This patch further; * introduces FTP_NO_HELP for commands registered for the FEAT list only * introduces FTP_NEW_FEAT for commands which must be reported via FEAT * adds REST STREAM, EPRT, EPSV to the FEAT results as required by spec * drops HELP mention of experimental LPRT/LPSV and antique MAIL commands Modified: httpd/mod_ftp/trunk/STATUS-FTP httpd/mod_ftp/trunk/include/mod_ftp.h httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c httpd/mod_ftp/trunk/modules/ftp/ftp_internal.h httpd/mod_ftp/trunk/modules/ftp/ftp_protocol.c httpd/mod_ftp/trunk/modules/ftp/mod_ftp.c Modified: httpd/mod_ftp/trunk/STATUS-FTP URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/STATUS-FTP?rev=793756&r1=793755&r2=793756&view=diff ============================================================================== --- httpd/mod_ftp/trunk/STATUS-FTP (original) +++ httpd/mod_ftp/trunk/STATUS-FTP Mon Jul 13 23:54:04 2009 @@ -39,18 +39,7 @@ RELEASE SHOWSTOPPERS: - * (1.0 stopper) - API change, the register new function should take an - arguement suitable for display in the FEAT response, such that the - implementor of FOO could display OPT1,OPT2 to FEAT. The immediate - case for this API change is registration of the EPRT/EPSV commands - (and essentially, anything that appears after RFC 959). - - * (1.0 stopper) - API change, OPTS needs to be implemented and extensible, - such that various registered command handlers accept their corresponding - OPTS behavior. RFC 2389 further requires that OPTS is implemented when - ever FEAT is implemented, so this implementation is nonconforming. - Consider a few other commands such as AUTH might need sub-delegation - facilities, as well. + CURRENT RELEASE NOTES: Modified: httpd/mod_ftp/trunk/include/mod_ftp.h URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/include/mod_ftp.h?rev=793756&r1=793755&r2=793756&view=diff ============================================================================== --- httpd/mod_ftp/trunk/include/mod_ftp.h (original) +++ httpd/mod_ftp/trunk/include/mod_ftp.h Mon Jul 13 23:54:04 2009 @@ -211,11 +211,19 @@ * FTP_TAKE1 - This command takes a single argument. * FTP_NEED_LOGIN - The user needs to be logged in to execute this command. * FTP_DATA_INTR - The current data transfer is interrupted by this command. + * FTP_NEW_FEAT - This command was introduced following RFC 2389, show in FEAT list + * Register a NULL hook function for extended names with spaces + * E.g. register "AUTH" with a hook function, and also register + * "AUTH TLS" as the specific FTP_NEW_FEAT with a NULL hook function. + * FTP_NO_HELP - Implicit if the command key contains a space, this flag omits + * a given FTP command from the HELP listing. */ #define FTP_TAKE0 (1 << 0) #define FTP_TAKE1 (1 << 1) #define FTP_NEED_LOGIN (1 << 2) #define FTP_DATA_INTR (1 << 3) +#define FTP_NEW_FEAT (1 << 4) +#define FTP_NO_HELP (1 << 5) /* FTP command handler ordering */ #define FTP_HOOK_FIRST 10 Modified: httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c?rev=793756&r1=793755&r2=793756&view=diff ============================================================================== --- httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c (original) +++ httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c Mon Jul 13 23:54:04 2009 @@ -43,6 +43,27 @@ static apr_hash_t *FTPMethodHash; static apr_pool_t *FTPMethodPool; +static const char *FTPHelpText; +static apr_size_t FTPHelpTextLen; +static const char *FTPFeatText; +static apr_size_t FTPFeatTextLen; + +/* + * The FTP command structure contains useful information about the FTP + * handler. This information is filled out when a command is registered + * using ftp_hook_cmd(), which also puts the handler into the global hash. + */ +typedef struct ftp_cmd_entry +{ + const char *key; /* The key, e.g. "DELE" */ + ftp_hook_fn *pf; /* Pointer to the handler */ + const char *alias; /* The aliased command e.g. "CDUP" */ + int order; /* Handler ordering */ + int flags; /* Flags for this command. See FTP_CMD_ */ + const char *help; /* Help string for this command */ + struct ftp_cmd_entry *next; /* Pointer to the next handler */ +} ftp_cmd_entry; + FTP_DECLARE(void) ftp_hook_cmd_any(const char *key, ftp_hook_fn *pf, const char *alias, int order, @@ -56,6 +77,12 @@ key = apr_pstrdup(FTPMethodPool, key); help = apr_pstrdup(FTPMethodPool, help); + /* Commands with a space are only for FTP_NEW_FEAT display, so + * we fix this display bit for convenience at registration time + */ + if (strchr(key, ' ')) + flags |= FTP_NO_HELP; + cmd->key = key; cmd->pf = pf; cmd->alias = alias; @@ -182,6 +209,50 @@ return key; } +void ftp_cmd_finalize(apr_pool_t *pool, apr_pool_t *ptemp) +{ + ftp_cmd_entry *cmd, *basecmd; + apr_hash_index_t *hi; + void *val; + int i; + + FTPHelpText = apr_psprintf(ptemp, "%d-%s", FTP_REPLY_HELP_MESSAGE, + "The following commands are recognized " + "(* =>'s unimplemented)."); + + FTPFeatText = apr_psprintf(ptemp, "%d-%s", FTP_REPLY_SYSTEM_STATUS, + "Extensions supported"); + + for (hi = apr_hash_first(ptemp, FTPMethodHash), i = 0; hi; + hi = apr_hash_next(hi), i++) + { + apr_hash_this(hi, NULL, NULL, &val); + cmd = (struct ftp_cmd_entry *) val; + + if (cmd->alias) + basecmd = apr_hash_get(FTPMethodHash, cmd->alias, APR_HASH_KEY_STRING); + else + basecmd = cmd; + + if (!(cmd->flags & FTP_NO_HELP)) + FTPHelpText = apr_psprintf(ptemp, "%s%s %c%-4s", + FTPHelpText, (i % 8) ? "" : CRLF, + (basecmd->pf) ? ' ' : '*', cmd->key); + else + --i; + + if (cmd->flags & FTP_NEW_FEAT) + FTPFeatText = apr_pstrcat(ptemp, FTPFeatText, CRLF " ", + cmd->key, NULL); + } + + FTPHelpText = apr_pstrcat(pool, FTPHelpText, CRLF, NULL); + FTPHelpTextLen = strlen(FTPHelpText); + + FTPFeatText = apr_pstrcat(pool, FTPFeatText, CRLF, NULL); + FTPFeatTextLen = strlen(FTPFeatText); +} + /* ftp_parse2: Parse a FTP request that is expected to have 2 arguments. * * Arguments: pool - Pool to allocate from @@ -500,6 +571,21 @@ static int ftp_cmd_feat(request_rec *r, const char *arg) { + ftp_connection *fc = ftp_get_module_config(r->connection->conn_config); + conn_rec *c = r->connection; + apr_bucket_brigade *bb; + apr_bucket *b; + + bb = apr_brigade_create(r->pool, c->bucket_alloc); + b = apr_bucket_immortal_create(FTPFeatText, FTPFeatTextLen, c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + fc->traffic += FTPFeatTextLen; + + b = apr_bucket_flush_create(c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + ap_pass_brigade(c->output_filters, bb); + + fc->response_notes = "End"; return FTP_REPLY_SYSTEM_STATUS; } @@ -507,9 +593,10 @@ { ftp_connection *fc = ftp_get_module_config(r->connection->conn_config); conn_rec *c = r->connection; + apr_bucket_brigade *bb; + apr_bucket *b; ftp_cmd_entry *cmd; - int i; - char *method, *buf = ""; + char *method; if (*arg) { method = ftp_toupper(r->pool, arg); @@ -525,65 +612,20 @@ return FTP_REPLY_COMMAND_NOT_IMPLEMENTED; } } - else { - apr_status_t rv; - apr_bucket_brigade *bb; - apr_hash_index_t *hi; - ftp_cmd_entry *cmd; - apr_size_t nbytes; - apr_bucket *b; - void *val; - char supported; - - buf = apr_psprintf(r->pool, "%d-%s" CRLF, FTP_REPLY_HELP_MESSAGE, - "The following commands are recognized " - "(* =>'s unimplemented)."); - - for (hi = apr_hash_first(r->pool, FTPMethodHash), i = 0; hi; - hi = apr_hash_next(hi), i++) { - - apr_hash_this(hi, NULL, NULL, &val); - cmd = (struct ftp_cmd_entry *) val; - - if (cmd->alias) { - ftp_cmd_entry *basecmd; - basecmd = apr_hash_get(FTPMethodHash, cmd->alias, APR_HASH_KEY_STRING); - - if (basecmd && basecmd->pf) - supported = ' '; - else - supported = '*'; - } - else if (cmd->pf) - supported = ' '; - else - supported = '*'; - - method = apr_psprintf(r->pool, " %c%-4s", - supported, cmd->key); - buf = apr_pstrcat(r->pool, buf, method, NULL); - - if (((i + 1) % 8) == 0) - buf = apr_pstrcat(r->pool, buf, CRLF, NULL); - } - - buf = apr_pstrcat(r->pool, buf, CRLF, NULL); - - bb = apr_brigade_create(r->pool, c->bucket_alloc); - nbytes = strlen(buf); - rv = apr_brigade_write(bb, ap_filter_flush, r->output_filters, - buf, nbytes); - fc->traffic += nbytes; + /* given no argument, pre-prepared HELP message */ + bb = apr_brigade_create(r->pool, c->bucket_alloc); + b = apr_bucket_immortal_create(FTPHelpText, FTPHelpTextLen, c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + fc->traffic += FTPHelpTextLen; - b = apr_bucket_flush_create(c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, b); - ap_pass_brigade(c->output_filters, bb); + b = apr_bucket_flush_create(c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + ap_pass_brigade(c->output_filters, bb); - fc->response_notes = apr_psprintf(r->pool, FTP_MSG_HELP, - r->server->server_admin); - return FTP_REPLY_HELP_MESSAGE; - } + fc->response_notes = apr_psprintf(r->pool, FTP_MSG_HELP, + r->server->server_admin); + return FTP_REPLY_HELP_MESSAGE; } static int ftp_cmd_nlst(request_rec *r, const char *arg); @@ -2344,11 +2386,12 @@ } else { /* - * XXX: big bug - going back to the beginning. We should compute - * size rather than stating the file... this could be done trivially - * with a request to a null 'data' port which simply counts up the - * bytes. Will be implemented as a special-case of the ftp_core_data + * XXX: big bug - going back to the beginning. We must compute size + * rather than stating the file... this could be done trivially with + * a request to a null 'data' port which simply counts up the bytes. + * Will be implemented as a special-case of the ftp_core_data * connection endpoint-filter. + * See RFC3659 - especially with respect to TYPE A/I */ fc->response_notes = apr_psprintf(r->pool, "%" APR_OFF_T_FMT, rr->finfo.size); @@ -2840,6 +2883,11 @@ FTP_TAKE1, " mechanism-name"); + /* Register the AUTH TLS mechanism for FEAT advertising */ + ftp_hook_cmd("AUTH TLS", NULL, FTP_HOOK_LAST, + FTP_NEW_FEAT, + " mechanism-name"); + ftp_hook_cmd("CDUP", ftp_cmd_cdup, FTP_HOOK_LAST, FTP_NEED_LOGIN | FTP_TAKE0, "change to parent directory"); @@ -2853,15 +2901,15 @@ " file-name"); ftp_hook_cmd("EPRT", ftp_cmd_eprt, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE1, + FTP_NEED_LOGIN | FTP_TAKE1 | FTP_NEW_FEAT, " afaddrport"); ftp_hook_cmd("EPSV", ftp_cmd_epsv, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0 | FTP_TAKE1, + FTP_NEED_LOGIN | FTP_TAKE0 | FTP_TAKE1 | FTP_NEW_FEAT, "[ af|ALL ]"); ftp_hook_cmd("FEAT", ftp_cmd_feat, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, + FTP_TAKE0, "show server features"); ftp_hook_cmd("HELP", ftp_cmd_help, FTP_HOOK_LAST, @@ -2872,46 +2920,18 @@ FTP_NEED_LOGIN | FTP_TAKE0 | FTP_TAKE1, "[ path-name ]"); - ftp_hook_cmd("LPRT", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE1, - " af, hal, h1, h2, h3,..., pal, p1, p2..."); - - ftp_hook_cmd("LPSV", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, - "(set server in passive mode)"); - - ftp_hook_cmd("MAIL", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, - "(mail to user)"); - ftp_hook_cmd("MDTM", ftp_cmd_mdtm, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE1, + FTP_NEED_LOGIN | FTP_TAKE1 | FTP_NEW_FEAT, " path-name"); ftp_hook_cmd("MKD", ftp_cmd_mkd, FTP_HOOK_LAST, FTP_NEED_LOGIN | FTP_TAKE1, " path-name"); - ftp_hook_cmd("MLFL", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, - "(mail file)"); - ftp_hook_cmd("MODE", NULL, FTP_HOOK_LAST, FTP_NEED_LOGIN | FTP_TAKE0, "(specify transfer mode)"); - ftp_hook_cmd("MSAM", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, - "(mail send to terminal and mailbox)"); - - ftp_hook_cmd("MSND", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, - "(mail send to terminal)"); - - ftp_hook_cmd("MSOM", NULL, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE0, - "(mail send to terminal or mailbox"); - ftp_hook_cmd("NLST", ftp_cmd_nlst, FTP_HOOK_LAST, FTP_NEED_LOGIN | FTP_TAKE0 | FTP_TAKE1, "[ path-name ]"); @@ -2930,7 +2950,7 @@ /* PBSZ does not require a user to be logged in */ ftp_hook_cmd("PBSZ", ftp_cmd_pbsz, FTP_HOOK_LAST, - FTP_TAKE1, + FTP_TAKE1 | FTP_NEW_FEAT, " decimal-integer"); ftp_hook_cmd("PORT", ftp_cmd_port, FTP_HOOK_LAST, @@ -2939,7 +2959,7 @@ /* PROT does not require a user to be logged in */ ftp_hook_cmd("PROT", ftp_cmd_prot, FTP_HOOK_LAST, - FTP_TAKE1, + FTP_TAKE1 | FTP_NEW_FEAT, " prot-code"); ftp_hook_cmd("PWD", ftp_cmd_pwd, FTP_HOOK_LAST, @@ -2958,6 +2978,11 @@ FTP_NEED_LOGIN | FTP_TAKE1, " offset (restart command)"); + /* Register the REST STREAM mechanism for FEAT advertising */ + ftp_hook_cmd("REST STREAM", ftp_cmd_rest, FTP_HOOK_LAST, + FTP_NEW_FEAT, + " offset (restart command)"); + ftp_hook_cmd("RETR", ftp_cmd_retr, FTP_HOOK_LAST, FTP_NEED_LOGIN | FTP_TAKE1, " file-name"); @@ -2979,7 +3004,7 @@ "site-cmd [ arguments ]"); ftp_hook_cmd("SIZE", ftp_cmd_size, FTP_HOOK_LAST, - FTP_NEED_LOGIN | FTP_TAKE1, + FTP_NEED_LOGIN | FTP_TAKE1 | FTP_NEW_FEAT, " path-name"); ftp_hook_cmd("SMNT", NULL, FTP_HOOK_LAST, Modified: httpd/mod_ftp/trunk/modules/ftp/ftp_internal.h URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/modules/ftp/ftp_internal.h?rev=793756&r1=793755&r2=793756&view=diff ============================================================================== --- httpd/mod_ftp/trunk/modules/ftp/ftp_internal.h (original) +++ httpd/mod_ftp/trunk/modules/ftp/ftp_internal.h Mon Jul 13 23:54:04 2009 @@ -115,6 +115,8 @@ #define FTP_MSG_HELP "Direct comments to %s" #define FTP_MSG_NOTIMPL "%s: Command not implemented" #define FTP_MSG_NOTALLOWED "Permission denied: %s not allowed here" +#define FTP_MSG_SESSIONLIMIT "Maximum number of concurrent sessions reached," \ + " closing connection." #define FTP_DEFAULT_DBFILE "logs/ftplogins" /* @@ -331,25 +333,8 @@ */ int ftp_cmd_abort_data(const char *key); -typedef struct ftp_cmd_entry ftp_cmd_entry; - -/* - * The FTP command structure contains useful information about the FTP - * handler. This information is filled out when a command is registered - * using ftp_hook_cmd(), which also puts the handler into the global hash. - */ -struct ftp_cmd_entry -{ - const char *key; /* The key, e.g. "DELE" */ - ftp_hook_fn *pf; /* Pointer to the handler */ - const char *alias; /* The aliased command e.g. "CDUP" */ - int order; /* Handler ordering */ - int flags; /* Flags for this command. See FTP_ - * defines above - */ - const char *help; /* Help string for this command */ - struct ftp_cmd_entry *next; /* Pointer to the next handler */ -}; +/* Finalizes ftp_cmd_help and ftp_cmd_feat messages */ +void ftp_cmd_finalize(apr_pool_t *p, apr_pool_t *ptemp); /* FTP low-numbered-port allocation daemon * Modified: httpd/mod_ftp/trunk/modules/ftp/ftp_protocol.c URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/modules/ftp/ftp_protocol.c?rev=793756&r1=793755&r2=793756&view=diff ============================================================================== --- httpd/mod_ftp/trunk/modules/ftp/ftp_protocol.c (original) +++ httpd/mod_ftp/trunk/modules/ftp/ftp_protocol.c Mon Jul 13 23:54:04 2009 @@ -729,17 +729,6 @@ } switch (status) { - case FTP_REPLY_SYSTEM_STATUS: - ftp_reply(fc, c->output_filters, r->pool, FTP_REPLY_SYSTEM_STATUS, 1, - "Extensions supported:\n" - " AUTH TLS\n" - " PBSZ\n" - " PROT\n" - " SIZE\n" - " MDTM"); - ftp_reply(fc, c->output_filters, r->pool, FTP_REPLY_SYSTEM_STATUS, 0, - "END"); - break; case FTP_REPLY_SYSTEM_TYPE: ftp_reply(fc, c->output_filters, r->pool, FTP_REPLY_SYSTEM_TYPE, 0, apr_pstrcat(r->pool, "UNIX Type: L8 System: \"", Modified: httpd/mod_ftp/trunk/modules/ftp/mod_ftp.c URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/modules/ftp/mod_ftp.c?rev=793756&r1=793755&r2=793756&view=diff ============================================================================== --- httpd/mod_ftp/trunk/modules/ftp/mod_ftp.c (original) +++ httpd/mod_ftp/trunk/modules/ftp/mod_ftp.c Mon Jul 13 23:54:04 2009 @@ -86,6 +86,9 @@ ap_add_version_component(p, FTP_SERVER_STRING); + /* Finalize ftp_cmd_help and ftp_cmd_feat messages */ + ftp_cmd_finalize(p, ptemp); + /* * Fixup global values, then base server and virtual host values */