1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

FTP directory filter works now.

Many FIXME notes added.
Much overhauling of proxy_ftp.c
PR:
Obtained from:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88817 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Graham Leggett
2001-04-12 01:57:48 +00:00
parent 3cba58c98f
commit 07e7e196f4
5 changed files with 318 additions and 163 deletions

View File

@@ -410,8 +410,6 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s)
ps->noproxies = ap_make_array(p, 10, sizeof(struct noproxy_entry)); ps->noproxies = ap_make_array(p, 10, sizeof(struct noproxy_entry));
ps->dirconn = ap_make_array(p, 10, sizeof(struct dirconn_entry)); ps->dirconn = ap_make_array(p, 10, sizeof(struct dirconn_entry));
ps->allowed_connect_ports = ap_make_array(p, 10, sizeof(int)); ps->allowed_connect_ports = ap_make_array(p, 10, sizeof(int));
/* ps->client_socket = NULL;*/
ps->connection = NULL;
ps->domain = NULL; ps->domain = NULL;
ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */ ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */
ps->viaopt_set = 0; /* 0 means default */ ps->viaopt_set = 0; /* 0 means default */
@@ -721,7 +719,7 @@ static void register_hooks(apr_pool_t *p)
/* filename-to-URI translation */ /* filename-to-URI translation */
ap_hook_translate_name(proxy_trans, NULL, NULL, APR_HOOK_FIRST); ap_hook_translate_name(proxy_trans, NULL, NULL, APR_HOOK_FIRST);
/* filters */ /* filters */
ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_CONNECTION); ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_CONTENT);
/* fixups */ /* fixups */
ap_hook_fixups(proxy_fixup, NULL, NULL, APR_HOOK_FIRST); ap_hook_fixups(proxy_fixup, NULL, NULL, APR_HOOK_FIRST);
/* post read_request handling */ /* post read_request handling */

View File

@@ -167,11 +167,6 @@ typedef struct {
apr_array_header_t *noproxies; apr_array_header_t *noproxies;
apr_array_header_t *dirconn; apr_array_header_t *dirconn;
apr_array_header_t *allowed_connect_ports; apr_array_header_t *allowed_connect_ports;
long id;
const char *connectname;
apr_port_t connectport;
/* apr_socket_t *client_socket;*/
conn_rec *connection;
const char *domain; /* domain name to use in absence of a domain name in the request */ const char *domain; /* domain name to use in absence of a domain name in the request */
int req; /* true if proxy requests are enabled */ int req; /* true if proxy requests are enabled */
char req_set; char req_set;
@@ -215,7 +210,8 @@ int ap_proxy_connect_handler(request_rec *r, char *url,
int ap_proxy_ftp_canon(request_rec *r, char *url); int ap_proxy_ftp_canon(request_rec *r, char *url);
int ap_proxy_ftp_handler(request_rec *r, char *url); int ap_proxy_ftp_handler(request_rec *r, char *url);
apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *bb); apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f,
apr_bucket_brigade *bb);
/* proxy_http.c */ /* proxy_http.c */
@@ -248,7 +244,7 @@ int ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
int ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p); int ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
int ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr); int ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
int ap_proxy_pre_http_connection(conn_rec *c, request_rec *r); int ap_proxy_pre_http_connection(conn_rec *c, request_rec *r);
apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen); apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
void ap_proxy_reset_output_filters(conn_rec *c); void ap_proxy_reset_output_filters(conn_rec *c);
#endif /*MOD_PROXY_H*/ #endif /*MOD_PROXY_H*/

View File

@@ -198,9 +198,9 @@ static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade *bb, char *msgbuf, int
char *mb = msgbuf, char *mb = msgbuf,
*me = &msgbuf[msglen]; *me = &msgbuf[msglen];
apr_status_t rv; apr_status_t rv;
int eos;
if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) {
if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response)))) {
return -1; return -1;
} }
if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) || if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) ||
@@ -215,7 +215,7 @@ static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade *bb, char *msgbuf, int
memcpy(buff, response, 3); memcpy(buff, response, 3);
buff[3] = ' '; buff[3] = ' ';
do { do {
if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response)))) { if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) {
return -1; return -1;
} }
mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb); mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb);
@@ -234,81 +234,156 @@ static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade *bb, char *msgbuf, int
* all in good time...! :) * all in good time...! :)
*/ */
apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *bb) typedef struct {
apr_bucket_brigade *in;
char buffer[MAX_STRING_LEN];
enum {HEADER, BODY, FOOTER} state;
} proxy_dir_ctx_t;
apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in)
{ {
conn_rec *c = f->r->connection; request_rec *r = f->r;
apr_pool_t *p = f->r->pool; apr_pool_t *p = r->pool;
apr_bucket *e; apr_bucket *e;
char buf[MAX_STRING_LEN]; apr_bucket_brigade *out = apr_brigade_create(p);
char buf2[MAX_STRING_LEN]; apr_status_t rv;
char *filename;
int searchidx = 0;
char *searchptr = NULL;
int firstfile = 1;
register int n; register int n;
char *dir, *path, *reldir, *site; char *dir, *path, *reldir, *site, *str;
char *cwd = NULL; const char *pwd = apr_table_get(r->notes, "Directory-PWD");
const char *readme = apr_table_get(r->notes, "Directory-README");
proxy_dir_ctx_t *ctx = f->ctx;
/* Save "scheme://site" prefix without password */ if (!ctx) {
site = ap_unparse_uri_components(p, &f->r->parsed_uri, UNP_OMITPASSWORD|UNP_OMITPATHINFO); f->ctx = ctx = apr_pcalloc(p, sizeof(*ctx));
/* ... and path without query args */ ctx->in = apr_brigade_create(p);
path = ap_unparse_uri_components(p, &f->r->parsed_uri, UNP_OMITSITEPART|UNP_OMITQUERY); ctx->buffer[0] = 0;
(void)decodeenc(path); ctx->state = HEADER;
/* Copy path, strip (all except the last) trailing slashes */
path = dir = apr_pstrcat(p, path, "/", NULL);
while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/')
path[n-1] = '\0';
/* print "ftp://host/" */
n = apr_snprintf(buf, sizeof(buf), DOCTYPE_HTML_3_2
"<HTML><HEAD><TITLE>%s%s</TITLE>\n"
"<BASE HREF=\"%s%s\"></HEAD>\n"
"<BODY><H2>Directory of "
"<A HREF=\"/\">%s</A>/",
site, path, site, path, site);
e = apr_bucket_pool_create(buf, n, p);
APR_BRIGADE_INSERT_TAIL(bb, e);
while ((dir = strchr(dir+1, '/')) != NULL)
{
*dir = '\0';
if ((reldir = strrchr(path+1, '/'))==NULL)
reldir = path+1;
else
++reldir;
/* print "path/" component */
n = apr_snprintf(buf, sizeof(buf), "<A HREF=\"/%s/\">%s</A>/", path+1, reldir);
e = apr_bucket_pool_create(buf, n, p);
APR_BRIGADE_INSERT_TAIL(bb, e);
*dir = '/';
} }
/* If the caller has determined the current directory, and it differs */
/* from what the client requested, then show the real name */ /* combine the stored and the new */
if (cwd == NULL || strncmp (cwd, path, strlen(cwd)) == 0) { APR_BRIGADE_CONCAT(ctx->in, in);
n = apr_snprintf(buf, sizeof(buf), "</H2>\n<HR><PRE>");
} else { if (HEADER == ctx->state) {
n = apr_snprintf(buf, sizeof(buf), "</H2>\n(%s)\n<HR><PRE>", cwd);
/* Save "scheme://site" prefix without password */
site = ap_unparse_uri_components(p, &f->r->parsed_uri, UNP_OMITPASSWORD|UNP_OMITPATHINFO);
/* ... and path without query args */
path = ap_unparse_uri_components(p, &f->r->parsed_uri, UNP_OMITSITEPART|UNP_OMITQUERY);
(void)decodeenc(path);
/* Copy path, strip (all except the last) trailing slashes */
path = dir = apr_pstrcat(p, path, "/", NULL);
while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/')
path[n-1] = '\0';
/* print "ftp://host/" */
str = apr_psprintf(p, DOCTYPE_HTML_3_2
"\n\n<HTML>\n<HEAD>\n<TITLE>%s%s</TITLE>\n"
"<BASE HREF=\"%s%s\">\n</HEAD>\n\n"
"<BODY>\n\n<H2>Directory of "
"<A HREF=\"/\">%s</A>/",
site, path, site, path, site);
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
while ((dir = strchr(dir+1, '/')) != NULL)
{
*dir = '\0';
if ((reldir = strrchr(path+1, '/'))==NULL)
reldir = path+1;
else
++reldir;
/* print "path/" component */
str = apr_psprintf(p, "<A HREF=\"/%s/\">%s</A>/", path+1, reldir);
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
*dir = '/';
}
/* If the caller has determined the current directory, and it differs */
/* from what the client requested, then show the real name */
if (pwd == NULL || strncmp (pwd, path, strlen(pwd)) == 0) {
str = apr_psprintf(p, "</H2>\n\n<HR></HR>\n\n<PRE>");
} else {
str = apr_psprintf(p, "</H2>\n\n(%s)\n\n<HR></HR>\n\n<PRE>", pwd);
}
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
/* print README */
if (readme) {
str = apr_psprintf(p, "%s\n</PRE>\n\n<HR></HR>\n\n<PRE>\n",
readme);
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
}
/* make sure page intro gets sent out */
e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(out, e);
if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
return rv;
}
apr_brigade_cleanup(out);
ctx->state = BODY;
} }
e = apr_bucket_pool_create(buf, n, p);
APR_BRIGADE_INSERT_TAIL(bb, e);
e = apr_bucket_flush_create(); /* loop through each line of directory */
APR_BRIGADE_INSERT_TAIL(bb, e); while (BODY == ctx->state) {
char *filename;
int found = 0;
int eos = 0;
ctx->buffer[0] = 0;
while (!c->aborted) { /* get a complete line */
n = ap_getline(buf, sizeof(buf), f->r, 0); while (!found && !APR_BRIGADE_EMPTY(ctx->in)) {
if (n == -1) { /* input error */ char *pos, *response;
apr_size_t len, max;
e = APR_BRIGADE_FIRST(ctx->in);
if (APR_BUCKET_IS_EOS(e)) {
eos = 1;
break;
}
if (APR_SUCCESS != (rv = apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ))) {
return rv;
}
pos = memchr(response, APR_ASCII_LF, len);
if (pos != NULL) {
if ((pos - response + 1) != len) {
apr_bucket_split(e, pos - response + 1);
}
found = 1;
}
max = sizeof(ctx->buffer)-strlen(ctx->buffer)-1;
if (len > max) {
len = max;
}
apr_cpystrn(ctx->buffer+strlen(ctx->buffer), response, len);
APR_BUCKET_REMOVE(e);
apr_bucket_destroy(e);
}
/* EOS? jump to footer */
if (eos) {
ctx->state = FOOTER;
break; break;
} }
if (n == 0) {
break; /* EOF */ /* not complete? leave and try get some more */
if (!found) {
return APR_SUCCESS;
} }
if (buf[0] == 'l' && (filename=strstr(buf, " -> ")) != NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: directory line: [%s]", ctx->buffer);
/* a symlink? */
if (ctx->buffer[0] == 'l' && (filename=strstr(ctx->buffer, " -> ")) != NULL) {
char *link_ptr = filename; char *link_ptr = filename;
do { do {
@@ -318,65 +393,76 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *bb)
*(link_ptr++) = '\0'; *(link_ptr++) = '\0';
if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n') if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
link_ptr[n - 1] = '\0'; link_ptr[n - 1] = '\0';
apr_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s %s</A>\n", buf, filename, filename, link_ptr); str = apr_psprintf(p, "%s <A HREF=\"%s\">%s %s</A>\n", ctx->buffer, filename, filename, link_ptr);
apr_cpystrn(buf, buf2, sizeof(buf));
n = strlen(buf);
} }
else if (buf[0] == 'd' || buf[0] == '-' || buf[0] == 'l' || apr_isdigit(buf[0])) {
if (apr_isdigit(buf[0])) { /* handle DOS dir */ /* a directory/file? */
searchptr = strchr(buf, '<'); else if (ctx->buffer[0] == 'd' || ctx->buffer[0] == '-' || ctx->buffer[0] == 'l' || apr_isdigit(ctx->buffer[0])) {
int searchidx = 0;
char *searchptr = NULL;
int firstfile = 1;
if (apr_isdigit(ctx->buffer[0])) { /* handle DOS dir */
searchptr = strchr(ctx->buffer, '<');
if (searchptr != NULL) if (searchptr != NULL)
*searchptr = '['; *searchptr = '[';
searchptr = strchr(buf, '>'); searchptr = strchr(ctx->buffer, '>');
if (searchptr != NULL) if (searchptr != NULL)
*searchptr = ']'; *searchptr = ']';
} }
filename = strrchr(buf, ' '); filename = strrchr(ctx->buffer, ' ');
*(filename++) = 0; *(filename++) = 0;
filename[strlen(filename) - 1] = 0; filename[strlen(filename) - 1] = 0;
/* handle filenames with spaces in 'em */ /* handle filenames with spaces in 'em */
if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) { if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
firstfile = 0; firstfile = 0;
searchidx = filename - buf; searchidx = filename - ctx->buffer;
} }
else if (searchidx != 0 && buf[searchidx] != 0) { else if (searchidx != 0 && ctx->buffer[searchidx] != 0) {
*(--filename) = ' '; *(--filename) = ' ';
buf[searchidx - 1] = 0; ctx->buffer[searchidx - 1] = 0;
filename = &buf[searchidx]; filename = &ctx->buffer[searchidx];
} }
/* Special handling for '.' and '..' */ /* Special handling for '.' and '..' */
if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') { if (!strcmp(filename, ".") || !strcmp(filename, "..") || ctx->buffer[0] == 'd') {
apr_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s/\">%s</A>\n", str = apr_psprintf(p, "%s <A HREF=\"%s/\">%s</A>\n",
buf, filename, filename); ctx->buffer, filename, filename);
} }
else { else {
apr_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s</A>\n", buf, filename, filename); str = apr_psprintf(p, "%s <A HREF=\"%s\">%s</A>\n",
ctx->buffer, filename, filename);
} }
apr_cpystrn(buf, buf2, sizeof(buf));
n = strlen(buf);
} }
e = apr_bucket_pool_create(buf, n, p); e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(bb, e); APR_BRIGADE_INSERT_TAIL(out, e);
e = apr_bucket_flush_create(); e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e); APR_BRIGADE_INSERT_TAIL(out, e);
if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
return rv;
}
apr_brigade_cleanup(out);
} }
n = apr_snprintf(buf, sizeof(buf), "</PRE><HR>\n%s</BODY></HTML>\n", ap_psignature("", f->r)); if (FOOTER == ctx->state) {
e = apr_bucket_pool_create(buf, n, p); str = apr_psprintf(p, "</PRE>\n\n<HR></HR>\n\n%s\n\n</BODY>\n</HTML>\n", ap_psignature("", r));
APR_BRIGADE_INSERT_TAIL(bb, e); e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
e = apr_bucket_eos_create(); e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e); APR_BRIGADE_INSERT_TAIL(out, e);
/* probably not necessary */ e = apr_bucket_eos_create();
/* e = apr_bucket_flush_create(); APR_BRIGADE_INSERT_TAIL(out, e);
APR_BRIGADE_INSERT_TAIL(bb, e);
*/ if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
return rv;
}
apr_brigade_destroy(out);
}
return APR_SUCCESS; return APR_SUCCESS;
} }
@@ -420,6 +506,7 @@ static int ftp_unauthorized (request_rec *r, int log_it)
int ap_proxy_ftp_handler(request_rec *r, char *url) int ap_proxy_ftp_handler(request_rec *r, char *url)
{ {
apr_pool_t *p = r->pool; apr_pool_t *p = r->pool;
conn_rec *c = r->connection;
apr_socket_t *sock, *local_sock, *remote_sock; apr_socket_t *sock, *local_sock, *remote_sock;
apr_sockaddr_t *connect_addr; apr_sockaddr_t *connect_addr;
apr_status_t rv; apr_status_t rv;
@@ -432,7 +519,6 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
apr_port_t connectport; apr_port_t connectport;
char buffer[MAX_STRING_LEN]; char buffer[MAX_STRING_LEN];
char *path, *strp, *parms; char *path, *strp, *parms;
char *cwd = NULL;
char *user = NULL; char *user = NULL;
/* char *account = NULL; how to supply an account in a URL? */ /* char *account = NULL; how to supply an account in a URL? */
const char *password = NULL; const char *password = NULL;
@@ -448,6 +534,16 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
proxy_server_conf *conf = proxy_server_conf *conf =
(proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
proxy_conn_rec *backend =
(proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_module);
if (!backend) {
backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
backend->connection = NULL;
backend->hostname = NULL;
backend->port = 0;
ap_set_module_config(c->conn_config, &proxy_module, backend);
}
/* /*
* I: Who Do I Connect To? * I: Who Do I Connect To?
@@ -616,15 +712,10 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* if a keepalive connection is floating around, close it first! */ /* if a keepalive connection is floating around, close it first! */
/* we might support ftp keepalives later, but not now... */ /* we might support ftp keepalives later, but not now... */
if ((conf->id == r->connection->id) && conf->connection) { if (backend->connection) {
apr_socket_close(conf->connection->client_socket); apr_socket_close(backend->connection->client_socket);
conf->connection = NULL; backend->connection = NULL;
} }
conf->id = r->connection->id;
/* allocate this out of the connection pool - the check on r->connection->id makes
* sure that this string does not get accessed past the connection lifetime */
conf->connectname = apr_pstrdup(r->connection->pool, connectname);
conf->connectport = connectport;
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: connection complete"); "proxy: connection complete");
@@ -647,7 +738,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 421 Service not available, closing control connection. */ /* 421 Service not available, closing control connection. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: initial connect returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server"); return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server");
} }
@@ -695,7 +786,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 530 Not logged in. */ /* 530 Not logged in. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server"); return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server");
} }
@@ -728,8 +819,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 503 Bad sequence of commands. */ /* 503 Bad sequence of commands. */
/* 530 Not logged in. */ /* 530 Not logged in. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d [%s]", i, buffer); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -776,8 +867,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 530 Not logged in. */ /* 530 Not logged in. */
/* 550 Requested action not taken. */ /* 550 Requested action not taken. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -791,6 +882,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
path = strp + 1; path = strp + 1;
} }
apr_table_set(r->notes, "Directory-README", buffer);
if (parms != NULL && strncasecmp(parms, "type=a", 6) == 0) { if (parms != NULL && strncasecmp(parms, "type=a", 6) == 0) {
parms = "A"; parms = "A";
@@ -817,8 +909,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 504 Command not implemented for that parameter. */ /* 504 Command not implemented for that parameter. */
/* 530 Not logged in. */ /* 530 Not logged in. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -838,16 +930,23 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
* *
* Try PASV, if that fails try normally. * Try PASV, if that fails try normally.
*/ */
/* this temporarily switches off PASV */
/*goto bypass;*/ /*goto bypass;*/
/* try to set up PASV data connection first */ /* try to set up PASV data connection first */
/* IPV6 FIXME:
* The EPSV command replaces PASV where both IPV4 and IPV6 is supported. Only
* the port is returned, the IP address is always the same as that on the
* control connection. Example:
* Entering Extended Passive Mode (|||6446|)
*/
buf = apr_pstrcat(p, "PASV", CRLF, NULL); buf = apr_pstrcat(p, "PASV", CRLF, NULL);
e = apr_bucket_pool_create(buf, strlen(buf), p); e = apr_bucket_pool_create(buf, strlen(buf), p);
APR_BRIGADE_INSERT_TAIL(bb, e); APR_BRIGADE_INSERT_TAIL(bb, e);
e = apr_bucket_flush_create(); e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e); APR_BRIGADE_INSERT_TAIL(bb, e);
ap_pass_brigade(origin->output_filters, bb); ap_pass_brigade(origin->output_filters, bb);
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: PASV"); "proxy: FTP: PASV");
/* possible results: 227, 421, 500, 501, 502, 530 */ /* possible results: 227, 421, 500, 501, 502, 530 */
/* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
@@ -857,8 +956,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 502 Command not implemented. */ /* 502 Command not implemented. */
/* 530 Not logged in. */ /* 530 Not logged in. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -870,6 +969,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
unsigned int h0, h1, h2, h3, p0, p1; unsigned int h0, h1, h2, h3, p0, p1;
char *pstr; char *pstr;
/* FIXME: Check PASV against RFC1123 */
pstr = apr_pstrdup(p, buffer); pstr = apr_pstrdup(p, buffer);
pstr = strtok(pstr, " "); /* separate result code */ pstr = strtok(pstr, " "); /* separate result code */
if (pstr != NULL) { if (pstr != NULL) {
@@ -883,7 +984,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
} }
} }
/* FIXME: Only supports IPV4 */ /* FIXME: Only supports IPV4 - fix in RFC2428 */
if (pstr != NULL && (sscanf(pstr, if (pstr != NULL && (sscanf(pstr,
"%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) { "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) {
@@ -932,13 +1033,14 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
apr_sockaddr_t *local_addr; apr_sockaddr_t *local_addr;
char *local_ip; char *local_ip;
apr_port_t local_port; apr_port_t local_port;
unsigned int h0, h1, h2, h3, p0, p1;
if ((apr_socket_create(&local_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) { if ((apr_socket_create(&local_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: FTP: error creating local socket"); "proxy: FTP: error creating local socket");
return HTTP_INTERNAL_SERVER_ERROR; return HTTP_INTERNAL_SERVER_ERROR;
} }
apr_socket_addr_get(&local_addr, APR_LOCAL, local_sock); apr_socket_addr_get(&local_addr, APR_LOCAL, sock);
apr_sockaddr_port_get(&local_port, local_addr); apr_sockaddr_port_get(&local_port, local_addr);
apr_sockaddr_ip_get(&local_ip, local_addr); apr_sockaddr_ip_get(&local_ip, local_addr);
@@ -950,7 +1052,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
#endif /*_OSD_POSIX*/ #endif /*_OSD_POSIX*/
} }
if (apr_sockaddr_info_get(&local_addr, local_ip, APR_INET, if (apr_sockaddr_info_get(&local_addr, local_ip, APR_UNSPEC,
local_port, 0, r->pool) != APR_SUCCESS) { local_port, 0, r->pool) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: FTP: error creating local socket address"); "proxy: FTP: error creating local socket address");
@@ -965,6 +1067,49 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* only need a short queue */ /* only need a short queue */
apr_listen(local_sock, 2); apr_listen(local_sock, 2);
/* FIXME: Sent PORT here */
if (local_ip && (sscanf(local_ip,
"%d.%d.%d.%d", &h3, &h2, &h1, &h0) == 4)) {
p1 = (local_port >> 8);
p0 = (local_port & 0xFF);
buf = apr_psprintf(p, "PORT %d,%d,%d,%d,%d,%d" CRLF, h3, h2, h1, h0, p1, p0);
e = apr_bucket_pool_create(buf, strlen(buf), p);
APR_BRIGADE_INSERT_TAIL(bb, e);
e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e);
ap_pass_brigade(origin->output_filters, bb);
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: PORT %d,%d,%d,%d,%d,%d", h3, h2, h1, h0, p1, p0);
/* possible results: 200, 421, 500, 501, 502, 530 */
/* 200 Command okay. */
/* 421 Service not available, closing control connection. */
/* 500 Syntax error, command unrecognized. */
/* 501 Syntax error in parameters or arguments. */
/* 502 Command not implemented. */
/* 530 Not logged in. */
rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: %d %s", rc, buffer);
if (rc == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server");
}
if (rc != 200) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
}
}
else {
/* IPV6 FIXME:
* The EPRT command replaces PORT where both IPV4 and IPV6 is supported. The first
* number (1,2) indicates the protocol type. Examples:
* EPRT |1|132.235.1.2|6275|
* EPRT |2|1080::8:800:200C:417A|5282|
*/
return ap_proxyerror(r, HTTP_NOT_IMPLEMENTED, "Connect to IPV6 ftp server not supported");
}
} }
@@ -993,7 +1138,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: SIZE %s", path); "proxy: FTP: SIZE %s", path);
i = ftp_getrc_msg(origin, cbb, buffer, sizeof buffer); i = ftp_getrc_msg(origin, cbb, buffer, sizeof buffer);
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d with response %s", i, buffer); "proxy: FTP: returned status %d with response %s", i, buffer);
if (i != 500) { /* Size command not recognized */ if (i != 500) { /* Size command not recognized */
if (i == 550) { /* Not a regular file */ if (i == 550) { /* Not a regular file */
@@ -1017,8 +1162,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 502 Command not implemented. */ /* 502 Command not implemented. */
/* 530 Not logged in. */ /* 530 Not logged in. */
/* 550 Requested action not taken. */ /* 550 Requested action not taken. */
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1) { if (i == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -1060,8 +1205,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 502 Command not implemented. */ /* 502 Command not implemented. */
/* 550 Requested action not taken. */ /* 550 Requested action not taken. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: PWD returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1 || i == 421) { if (i == -1 || i == 421) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -1071,7 +1216,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
} }
if (i == 257) { if (i == 257) {
const char *dirp = buffer; const char *dirp = buffer;
cwd = ap_getword_conf(r->pool, &dirp); apr_table_set(r->notes, "Directory-PWD", ap_getword_conf(r->pool, &dirp));
} }
#endif /*AUTODETECT_PWD*/ #endif /*AUTODETECT_PWD*/
@@ -1084,6 +1229,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
"proxy: FTP: LIST %s", (len == 0 ? "-lag" : path)); "proxy: FTP: LIST %s", (len == 0 ? "-lag" : path));
} }
else { else {
/* FIXME: Handle range requests - send REST */
buf = apr_pstrcat(p, "RETR ", path, CRLF, NULL); buf = apr_pstrcat(p, "RETR ", path, CRLF, NULL);
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: RETR %s", path); "proxy: FTP: RETR %s", path);
@@ -1110,8 +1256,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 530 Not logged in. */ /* 530 Not logged in. */
/* 550 Requested action not taken. */ /* 550 Requested action not taken. */
rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", rc); "proxy: FTP: %d %s", rc, buffer);
if (rc == -1) { if (rc == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -1137,8 +1283,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 530 Not logged in. */ /* 530 Not logged in. */
/* 550 Requested action not taken. */ /* 550 Requested action not taken. */
rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", rc); "proxy: FTP: %d %s", rc, buffer);
if (rc == -1) { if (rc == -1) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -1167,8 +1313,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 502 Command not implemented. */ /* 502 Command not implemented. */
/* 550 Requested action not taken. */ /* 550 Requested action not taken. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: PWD returned status %d", i); "proxy: FTP: %d %s", i, buffer);
if (i == -1 || i == 421) { if (i == -1 || i == 421) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -1178,7 +1324,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
} }
if (i == 257) { if (i == 257) {
const char *dirp = buffer; const char *dirp = buffer;
cwd = ap_getword_conf(r->pool, &dirp); apr_table_set(r->notes, "Directory-PWD", ap_getword_conf(r->pool, &dirp));
} }
#endif /*AUTODETECT_PWD*/ #endif /*AUTODETECT_PWD*/
@@ -1188,11 +1334,11 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
e = apr_bucket_flush_create(); e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e); APR_BRIGADE_INSERT_TAIL(bb, e);
ap_pass_brigade(origin->output_filters, bb); ap_pass_brigade(origin->output_filters, bb);
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: LIST -lag"); "proxy: FTP: LIST -lag");
rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", rc); "proxy: FTP: %d %s", rc, buffer);
if (rc == -1) if (rc == -1)
return ap_proxyerror(r, HTTP_BAD_GATEWAY, return ap_proxyerror(r, HTTP_BAD_GATEWAY,
"Error reading from remote server"); "Error reading from remote server");
@@ -1208,8 +1354,10 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
apr_table_setn(r->headers_out, "Date", dates); apr_table_setn(r->headers_out, "Date", dates);
apr_table_setn(r->headers_out, "Server", ap_get_server_version()); apr_table_setn(r->headers_out, "Server", ap_get_server_version());
if (parms[0] == 'd') if (parms[0] == 'd') {
apr_table_setn(r->headers_out, "Content-Type", "text/plain"); r->content_type = "text/html";
apr_table_setn(r->headers_out, "Content-Type", r->content_type);
}
else { else {
if (r->content_type != NULL) { if (r->content_type != NULL) {
apr_table_setn(r->headers_out, "Content-Type", r->content_type); apr_table_setn(r->headers_out, "Content-Type", r->content_type);
@@ -1226,9 +1374,11 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
"proxy: FTP: Content-Length set to %s", size); "proxy: FTP: Content-Length set to %s", size);
} }
} }
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: Content-Type set to %s", r->content_type);
if (r->content_encoding != NULL && r->content_encoding[0] != '\0') { if (r->content_encoding != NULL && r->content_encoding[0] != '\0') {
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: Content-Encoding set to %s", r->content_encoding); "proxy: FTP: Content-Encoding set to %s", r->content_encoding);
apr_table_setn(r->headers_out, "Content-Encoding", r->content_encoding); apr_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
} }
@@ -1236,6 +1386,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
if (!pasvmode) { if (!pasvmode) {
for(;;) for(;;)
{ {
/* FIXME: this does not return, despite the incoming connection being accepted */
switch(apr_accept(&remote_sock, local_sock, r->pool)) switch(apr_accept(&remote_sock, local_sock, r->pool))
{ {
case APR_EINTR: case APR_EINTR:
@@ -1250,6 +1401,9 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
} }
} }
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"proxy: FTP: ready to suck data");
/* the transfer socket is now open, create a new connection */ /* the transfer socket is now open, create a new connection */
remote = ap_new_connection(p, r->server, remote_sock, r->connection->id); remote = ap_new_connection(p, r->server, remote_sock, r->connection->id);
if (!remote) { if (!remote) {
@@ -1263,8 +1417,6 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* set up the connection filters */ /* set up the connection filters */
ap_proxy_pre_http_connection(remote, NULL); ap_proxy_pre_http_connection(remote, NULL);
/* XXX temporary end here while testing */
/*return HTTP_NOT_IMPLEMENTED;*/
/* /*
* VI: Receive the Response * VI: Receive the Response
@@ -1277,12 +1429,13 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* send response */ /* send response */
r->sent_bodyct = 1; r->sent_bodyct = 1;
#ifdef FTP_FILTER /* read till EOF */
if (parms[0] == 'd') { c->remain = -1;
if (parms[0] == 'd') {
/* insert directory filter */ /* insert directory filter */
ap_add_output_filter("PROXY_SEND_DIR", NULL, r, r->connection); ap_add_output_filter("PROXY_SEND_DIR", NULL, r, r->connection);
} }
#endif
/* send body */ /* send body */
if (!r->header_only) { if (!r->header_only) {
@@ -1293,6 +1446,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* read the body, pass it to the output filters */ /* read the body, pass it to the output filters */
while (ap_get_brigade(remote->input_filters, bb, AP_MODE_BLOCKING) == APR_SUCCESS) { while (ap_get_brigade(remote->input_filters, bb, AP_MODE_BLOCKING) == APR_SUCCESS) {
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e);
ap_pass_brigade(r->output_filters, bb); ap_pass_brigade(r->output_filters, bb);
break; break;
} }
@@ -1301,8 +1456,7 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
} }
apr_brigade_cleanup(bb); apr_brigade_cleanup(bb);
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP end body send"); "proxy: FTP: end body send");
} }
else { else {
@@ -1324,8 +1478,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 501 Syntax error in parameters or arguments. */ /* 501 Syntax error in parameters or arguments. */
/* 502 Command not implemented. */ /* 502 Command not implemented. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: returned status %d", i); "proxy: FTP: %d %s", i, buffer);
} }
@@ -1350,8 +1504,8 @@ int ap_proxy_ftp_handler(request_rec *r, char *url)
/* 221 Service closing control connection. */ /* 221 Service closing control connection. */
/* 500 Syntax error, command unrecognized. */ /* 500 Syntax error, command unrecognized. */
i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
"proxy: FTP: QUIT: status %d", i); "proxy: FTP: %d %s", i, buffer);
apr_brigade_destroy(bb); apr_brigade_destroy(bb);
return OK; return OK;

View File

@@ -175,7 +175,7 @@ int ap_proxy_http_handler(request_rec *r, char *url,
apr_sockaddr_t *connect_addr; apr_sockaddr_t *connect_addr;
char server_portstr[32]; char server_portstr[32];
apr_socket_t *sock; apr_socket_t *sock;
int i, len, backasswards, close=0, failed=0, new=0; int i, len, backasswards, eos, close=0, failed=0, new=0;
apr_status_t err, rv; apr_status_t err, rv;
apr_array_header_t *headers_in_array; apr_array_header_t *headers_in_array;
apr_table_entry_t *headers_in; apr_table_entry_t *headers_in;
@@ -587,7 +587,7 @@ int ap_proxy_http_handler(request_rec *r, char *url,
apr_brigade_cleanup(bb); apr_brigade_cleanup(bb);
if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer)))) { if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer), &eos))) {
apr_socket_close(sock); apr_socket_close(sock);
backend->connection = NULL; backend->connection = NULL;
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
@@ -733,6 +733,8 @@ int ap_proxy_http_handler(request_rec *r, char *url,
/* read the body, pass it to the output filters */ /* read the body, pass it to the output filters */
while (ap_get_brigade(rp->input_filters, bb, AP_MODE_BLOCKING) == APR_SUCCESS) { while (ap_get_brigade(rp->input_filters, bb, AP_MODE_BLOCKING) == APR_SUCCESS) {
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
e = apr_bucket_flush_create();
APR_BRIGADE_INSERT_TAIL(bb, e);
ap_pass_brigade(r->output_filters, bb); ap_pass_brigade(r->output_filters, bb);
break; break;
} }

View File

@@ -1082,7 +1082,8 @@ int ap_proxy_pre_http_connection(conn_rec *c, request_rec *r)
} }
/* converts a series of buckets into a string */ /* converts a series of buckets into a string */
apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen) apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb,
char *buff, size_t bufflen, int *eos)
{ {
apr_bucket *e; apr_bucket *e;
apr_status_t rv; apr_status_t rv;
@@ -1093,6 +1094,7 @@ apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buf
/* start with an empty string */ /* start with an empty string */
buff[0] = 0; buff[0] = 0;
*eos = 0;
/* get line-at-a-time */ /* get line-at-a-time */
c->remain = 0; c->remain = 0;
@@ -1108,6 +1110,9 @@ apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buf
/* loop through each bucket */ /* loop through each bucket */
while (!found && !APR_BRIGADE_EMPTY(bb)) { while (!found && !APR_BRIGADE_EMPTY(bb)) {
e = APR_BRIGADE_FIRST(bb); e = APR_BRIGADE_FIRST(bb);
if (APR_BUCKET_IS_EOS(e)) {
*eos = 1;
}
if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) { if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) {
return rv; return rv;
} }