char *url, const char *proxyhost,
apr_port_t proxyport);
apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f,
- apr_bucket_brigade * bb);
+ apr_bucket_brigade *bb);
/*
* Reads response lines, returns both the ftp status code and
* remembers the response message in the supplied buffer
*/
-static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade * bb, char *msgbuf, int msglen)
+static int ftp_getrc_msg(conn_rec *ftp_ctrl, apr_bucket_brigade *bb, char *msgbuf, int msglen)
{
int status;
char response[MAX_LINE_LEN];
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(ftp_ctrl, bb, response, sizeof(response), &eos))) {
return -1;
}
+/*
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, NULL,
+ "proxy: <FTP: %s", response);
+*/
if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) ||
!apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
status = 0;
memcpy(buff, response, 3);
buff[3] = ' ';
do {
- if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) {
+ if (APR_SUCCESS != (rv = ap_proxy_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) {
return -1;
}
mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb);
} state;
} proxy_dir_ctx_t;
-apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in)
+apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in)
{
request_rec *r = f->r;
apr_pool_t *p = r->pool;
/* 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);
+ "\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, ap_escape_uri(p, path),
+ site, ap_escape_html(p, path), site);
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
else
++reldir;
/* print "path/" component */
- str = apr_psprintf(p, "<A HREF=\"/%s/\">%s</A>/", path + 1, reldir);
+ str = apr_psprintf(p, "<a href=\"/%s/\">%s</a>/",
+ ap_escape_uri(p, path + 1),
+ ap_escape_html(p, 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>");
+ str = apr_psprintf(p, "</h2>\n\n<hr />\n\n<pre>");
}
else {
- str = apr_psprintf(p, "</H2>\n\n(%s)\n\n<HR></HR>\n\n<PRE>", pwd);
+ str = apr_psprintf(p, "</h2>\n\n(%s)\n\n<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);
+ str = apr_psprintf(p, "%s\n</pre>\n\n<hr />\n\n<pre>\n",
+ ap_escape_html(p, readme));
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
if ((response + len) != (pos + 1)) {
len = pos - response + 1;
apr_bucket_split(e, pos - response + 1);
-
}
found = 1;
}
do {
filename--;
- } while (filename[0] != ' ');
- *(filename++) = '\0';
+ } while (filename[0] != ' ' && filename > ctx->buffer);
+ if (filename > ctx->buffer)
+ *(filename++) = '\0';
*(link_ptr++) = '\0';
if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
link_ptr[n - 1] = '\0';
- str = apr_psprintf(p, "%s <A HREF=\"%s\">%s %s</A>\n", ctx->buffer, filename, filename, link_ptr);
+ str = apr_psprintf(p, "%s <a href=\"%s\">%s %s</a>\n",
+ ap_escape_html(p, ctx->buffer),
+ ap_escape_uri(p, filename),
+ ap_escape_html(p, filename),
+ ap_escape_html(p, link_ptr));
}
/* a directory/file? */
/* Special handling for '.' and '..' */
if (!strcmp(filename, ".") || !strcmp(filename, "..") || ctx->buffer[0] == 'd') {
- str = apr_psprintf(p, "%s <A HREF=\"%s/\">%s</A>\n",
- ctx->buffer, filename, filename);
+ str = apr_psprintf(p, "%s <a href=\"%s/\">%s</a>\n",
+ ap_escape_html(p, ctx->buffer),
+ ap_escape_uri(p, filename),
+ ap_escape_html(p, filename));
}
else {
- str = apr_psprintf(p, "%s <A HREF=\"%s\">%s</A>\n",
- ctx->buffer, filename, filename);
+ str = apr_psprintf(p, "%s <a href=\"%s\">%s</a>\n",
+ ap_escape_html(p, ctx->buffer),
+ ap_escape_uri(p, filename),
+ ap_escape_html(p, filename));
}
}
else {
- str = apr_pstrdup(p, ctx->buffer);
+ str = ap_escape_html(p, ctx->buffer);
}
/* erase buffer for next time around */
}
if (FOOTER == ctx->state) {
- str = apr_psprintf(p, "</PRE>\n\n<HR></HR>\n\n%s\n\n</BODY>\n</HTML>\n", ap_psignature("", r));
+ str = apr_psprintf(p, "</pre>\n\n<hr />\n\n%s\n\n</body>\n</html>\n", ap_psignature("", r));
e = apr_bucket_pool_create(str, strlen(str), p);
APR_BRIGADE_INSERT_TAIL(out, e);
apr_pool_t *p = r->pool;
conn_rec *c = r->connection;
proxy_conn_rec *backend;
- apr_socket_t *sock, *local_sock, *remote_sock = NULL;
+ apr_socket_t *sock, *local_sock, *data_sock = NULL;
apr_sockaddr_t *connect_addr;
apr_status_t rv;
- conn_rec *origin, *remote;
+ conn_rec *origin, *data;
int err;
apr_bucket *e;
apr_bucket_brigade *bb = apr_brigade_create(p);
/*
* I: Who Do I Connect To? -----------------------
- *
+ *
* Break up the URL to determine the host to connect to
*/
/*
* II: Make the Connection -----------------------
- *
+ *
* We have determined who to connect to. Now make the connection.
*/
* machine to connect to. If configured, reorder this list so that the
* "best candidate" is first try. "best candidate" could mean the least
* loaded server, the fastest responding server, whatever.
- *
+ *
* For now we do nothing, ie we get DNS round robin. XXX FIXME
*/
/*
* III: Send Control Request -------------------------
- *
+ *
* Log into the ftp server, send the username & password, change to the
* correct directory...
*/
if (rc == 120) {
/*
* RFC2616 states: 14.37 Retry-After
- *
+ *
* The Retry-After response-header field can be used with a 503 (Service
* Unavailable) response to indicate how long the service is expected
* to be unavailable to the requesting client. [...] The value of
/*
* IV: Make Data Connection? -------------------------
- *
+ *
* Try EPSV, if that fails... try PASV, if that fails... try PORT.
*/
/* this temporarily switches off EPSV/PASV */
/* set up data connection - EPSV */
{
- apr_sockaddr_t *remote_addr;
- char *remote_ip;
- apr_port_t remote_port;
+ apr_sockaddr_t *data_addr;
+ char *data_ip;
+ apr_port_t data_port;
/*
* The EPSV command replaces PASV where both IPV4 and IPV6 is
if (pstr) {
apr_sockaddr_t *epsv_addr;
- remote_port = atoi(pstr + 3);
+ data_port = atoi(pstr + 3);
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
"proxy: FTP: EPSV contacting remote host on port %d",
- remote_port);
+ data_port);
- if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
+ if ((rv = apr_socket_create(&data_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: FTP: error creating EPSV socket");
return HTTP_INTERNAL_SERVER_ERROR;
}
#if !defined (TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF,
+ if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(data_sock, APR_SO_RCVBUF,
conf->recv_buffer_size))) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
#endif
/* make the connection */
- apr_socket_addr_get(&remote_addr, APR_REMOTE, sock);
- apr_sockaddr_ip_get(&remote_ip, remote_addr);
- apr_sockaddr_info_get(&epsv_addr, remote_ip, APR_INET, remote_port, 0, p);
- rv = apr_connect(remote_sock, epsv_addr);
+ apr_socket_addr_get(&data_addr, APR_REMOTE, sock);
+ apr_sockaddr_ip_get(&data_ip, data_addr);
+ apr_sockaddr_info_get(&epsv_addr, data_ip, APR_INET, data_port, 0, p);
+ rv = apr_connect(data_sock, epsv_addr);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
"proxy: FTP: EPSV attempt to connect to %pI failed - Firewall/NAT?", epsv_addr);
}
else {
/* and try the regular way */
- apr_socket_close(remote_sock);
+ apr_socket_close(data_sock);
}
}
}
"proxy: FTP: PASV contacting host %d.%d.%d.%d:%d",
h3, h2, h1, h0, pasvport);
- if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
+ if ((rv = apr_socket_create(&data_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: error creating PASV socket");
return HTTP_INTERNAL_SERVER_ERROR;
}
#if !defined (TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF,
+ if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(data_sock, APR_SO_RCVBUF,
conf->recv_buffer_size))) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
/* make the connection */
apr_sockaddr_info_get(&pasv_addr, apr_psprintf(p, "%d.%d.%d.%d", h3, h2, h1, h0), APR_INET, pasvport, 0, p);
- rv = apr_connect(remote_sock, pasv_addr);
+ rv = apr_connect(data_sock, pasv_addr);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
"proxy: FTP: PASV attempt to connect to %pI failed - Firewall/NAT?", pasv_addr);
}
else {
/* and try the regular way */
- apr_socket_close(remote_sock);
+ apr_socket_close(data_sock);
}
}
}
/*
* V: Set The Headers -------------------
- *
+ *
* Get the size of the request, set up the environment for HTTP.
*/
/* wait for connection */
if (use_port) {
for (;;) {
- rv = apr_accept(&remote_sock, local_sock, r->pool);
+ rv = apr_accept(&data_sock, local_sock, r->pool);
if (rv == APR_EINTR) {
continue;
}
}
/* the transfer socket is now open, create a new connection */
- remote = ap_new_connection(p, r->server, remote_sock, r->connection->id, r->connection->sbh);
- if (!remote) {
+ data = ap_new_connection(p, r->server, data_sock, r->connection->id, r->connection->sbh);
+ if (!data) {
/*
* the peer reset the connection already; ap_new_connection() closed
* the socket
}
/* set up the connection filters */
- ap_proxy_pre_http_connection(remote);
+ ap_proxy_pre_http_connection(data);
/*
* VI: Receive the Response ------------------------
- *
+ *
* Get response from the remote ftp socket, and pass it up the filter chain.
*/
"proxy: FTP: start body send");
/* read the body, pass it to the output filters */
- while (ap_get_brigade(remote->input_filters, bb, AP_MODE_EXHAUSTIVE,
+ while (ap_get_brigade(data->input_filters, bb, AP_MODE_EXHAUSTIVE,
APR_BLOCK_READ, 0) == APR_SUCCESS) {
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
ap_pass_brigade(r->output_filters, bb);
apr_brigade_cleanup(bb);
}
}
- ap_flush_conn(remote);
- apr_socket_close(remote_sock);
+ ap_flush_conn(data);
+ apr_socket_close(data_sock);
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
"proxy: FTP: Closing Data connection.");
rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
/*
* VII: Clean Up -------------
- *
+ *
* If there are no KeepAlives, or if the connection has been signalled to
* close, close the socket and clean up
*/
return OK;
}
-static void ap_proxy_ftp_register_hook(apr_pool_t * p)
+static void ap_proxy_ftp_register_hook(apr_pool_t *p)
{
/* hooks */
proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE);