From: Chuck Murcko Date: Sat, 11 Nov 2000 11:05:18 +0000 (+0000) Subject: This is the 1.3.x current proxy into 2.0 - first stage X-Git-Tag: APACHE_2_0_ALPHA_8~100 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=adebe63463f8abcd823fb2049b754ca6d86db3ba;p=apache This is the 1.3.x current proxy into 2.0 - first stage PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86922 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/proxy_ftp.c b/modules/proxy/proxy_ftp.c index 477b6e03bd..d9c38a52ec 100644 --- a/modules/proxy/proxy_ftp.c +++ b/modules/proxy/proxy_ftp.c @@ -58,7 +58,6 @@ /* FTP routines for Apache proxy */ -#include "apr_strings.h" #include "mod_proxy.h" #include "http_main.h" #include "http_log.h" @@ -68,11 +67,11 @@ static void skiplf(BUFF *foo) { - char c; - do - { - c = ap_bgetc(foo); - } while(c != '\n'); + char c; + do + { + c = ap_bgetc(foo); + } while(c != '\n'); } /* @@ -83,15 +82,15 @@ static int decodeenc(char *x) int i, j, ch; if (x[0] == '\0') - return 0; /* special case for no characters */ + return 0; /* special case for no characters */ for (i = 0, j = 0; x[i] != '\0'; i++, j++) { /* decode it if not already done */ - ch = x[i]; - if (ch == '%' && apr_isxdigit(x[i + 1]) && apr_isxdigit(x[i + 2])) { - ch = ap_proxy_hex2c(&x[i + 1]); - i += 2; - } - x[j] = ch; + ch = x[i]; + if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) { + ch = ap_proxy_hex2c(&x[i + 1]); + i += 2; + } + x[j] = ch; } x[j] = '\0'; return j; @@ -103,18 +102,18 @@ static int decodeenc(char *x) */ static int ftp_check_string(const char *x) { - int i, ch; + int i, ch = 0; for (i = 0; x[i] != '\0'; i++) { - ch = x[i]; - if (ch == '%' && apr_isxdigit(x[i + 1]) && apr_isxdigit(x[i + 2])) { - ch = ap_proxy_hex2c(&x[i + 1]); - i += 2; - } + ch = x[i]; + if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) { + ch = ap_proxy_hex2c(&x[i + 1]); + i += 2; + } #ifndef CHARSET_EBCDIC - if (ch == '\015' || ch == '\012' || (ch & 0x80)) + if (ch == '\015' || ch == '\012' || (ch & 0x80)) #else /*CHARSET_EBCDIC*/ - if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80)) + if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80)) #endif /*CHARSET_EBCDIC*/ return 0; } @@ -134,11 +133,11 @@ int ap_proxy_ftp_canon(request_rec *r, char *url) port = DEFAULT_FTP_PORT; err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port); if (err) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; if (user != NULL && !ftp_check_string(user)) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; if (password != NULL && !ftp_check_string(password)) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; /* now parse path/parameters args, according to rfc1738 */ /* N.B. if this isn't a true proxy request, then the URL path @@ -148,48 +147,49 @@ int ap_proxy_ftp_canon(request_rec *r, char *url) */ strp = strchr(url, ';'); if (strp != NULL) { - *(strp++) = '\0'; - parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm, r->proxyreq); - if (parms == NULL) - return HTTP_BAD_REQUEST; + *(strp++) = '\0'; + parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm, + r->proxyreq); + if (parms == NULL) + return HTTP_BAD_REQUEST; } else - parms = ""; + parms = ""; path = ap_proxy_canonenc(p, url, strlen(url), enc_path, r->proxyreq); if (path == NULL) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; if (!ftp_check_string(path)) - return HTTP_BAD_REQUEST; - - if (!r->proxyreq && r->args != NULL) { - if (strp != NULL) { - strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, 1); - if (strp == NULL) - return HTTP_BAD_REQUEST; - parms = apr_pstrcat(p, parms, "?", strp, NULL); - } - else { - strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1); - if (strp == NULL) - return HTTP_BAD_REQUEST; - path = apr_pstrcat(p, path, "?", strp, NULL); - } - r->args = NULL; + return HTTP_BAD_REQUEST; + + if (r->proxyreq && r->args != NULL) { + if (strp != NULL) { + strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, 1); + if (strp == NULL) + return HTTP_BAD_REQUEST; + parms = apr_pstrcat(p, parms, "?", strp, NULL); + } + else { + strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1); + if (strp == NULL) + return HTTP_BAD_REQUEST; + path = apr_pstrcat(p, path, "?", strp, NULL); + } + r->args = NULL; } /* now, rebuild URL */ if (port != DEFAULT_FTP_PORT) - apr_snprintf(sport, sizeof(sport), ":%d", port); + apr_snprintf(sport, sizeof(sport), ":%d", port); else - sport[0] = '\0'; + sport[0] = '\0'; r->filename = apr_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "", - (password != NULL) ? ":" : "", - (password != NULL) ? password : "", - (user != NULL) ? "@" : "", host, sport, "/", path, - (parms[0] != '\0') ? ";" : "", parms, NULL); + (password != NULL) ? ":" : "", + (password != NULL) ? password : "", + (user != NULL) ? "@" : "", host, sport, "/", path, + (parms[0] != '\0') ? ";" : "", parms, NULL); return OK; } @@ -205,30 +205,30 @@ static int ftp_getrc(BUFF *f) len = ap_bgets(linebuff, sizeof linebuff, f); if (len == -1) - return -1; + return -1; /* check format */ if (len < 5 || !apr_isdigit(linebuff[0]) || !apr_isdigit(linebuff[1]) || - !apr_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) - status = 0; + !apr_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + status = 0; else - status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; + status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; if (linebuff[len - 1] != '\n') { - skiplf(f); + skiplf(f); } /* skip continuation lines */ if (linebuff[3] == '-') { - memcpy(buff, linebuff, 3); - buff[3] = ' '; - do { - len = ap_bgets(linebuff, sizeof linebuff, f); - if (len == -1) - return -1; - if (linebuff[len - 1] != '\n') { - skiplf(f); - } - } while (memcmp(linebuff, buff, 4) != 0); + memcpy(buff, linebuff, 3); + buff[3] = ' '; + do { + len = ap_bgets(linebuff, sizeof linebuff, f); + if (len == -1) + return -1; + if (linebuff[len - 1] != '\n') { + skiplf(f); + } + } while (memcmp(linebuff, buff, 4) != 0); } return status; @@ -243,34 +243,34 @@ static int ftp_getrc_msg(BUFF *f, char *msgbuf, int msglen) int len, status; char linebuff[100], buff[5]; char *mb = msgbuf, - *me = &msgbuf[msglen]; + *me = &msgbuf[msglen]; len = ap_bgets(linebuff, sizeof linebuff, f); if (len == -1) - return -1; + return -1; if (len < 5 || !apr_isdigit(linebuff[0]) || !apr_isdigit(linebuff[1]) || - !apr_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) - status = 0; + !apr_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + status = 0; else - status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; + status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; mb = apr_cpystrn(mb, linebuff+4, me - mb); if (linebuff[len - 1] != '\n') - skiplf(f); + skiplf(f); if (linebuff[3] == '-') { - memcpy(buff, linebuff, 3); - buff[3] = ' '; - do { - len = ap_bgets(linebuff, sizeof linebuff, f); - if (len == -1) - return -1; - if (linebuff[len - 1] != '\n') { - skiplf(f); - } - mb = apr_cpystrn(mb, linebuff+4, me - mb); - } while (memcmp(linebuff, buff, 4) != 0); + memcpy(buff, linebuff, 3); + buff[3] = ' '; + do { + len = ap_bgets(linebuff, sizeof linebuff, f); + if (len == -1) + return -1; + if (linebuff[len - 1] != '\n') { + skiplf(f); + } + mb = apr_cpystrn(mb, linebuff+4, me - mb); + } while (memcmp(linebuff, buff, 4) != 0); } return status; } @@ -291,7 +291,7 @@ static long int send_dir(BUFF *f, request_rec *r, ap_cache_el *c, char *cwd) apr_file_t *cachefp = NULL; if(c) ap_cache_el_data(c, &cachefp); - + /* Save "scheme://site" prefix without password */ site = ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD|UNP_OMITPATHINFO); /* ... and path without query args */ @@ -301,119 +301,119 @@ static long int send_dir(BUFF *f, request_rec *r, ap_cache_el *c, char *cwd) /* Copy path, strip (all except the last) trailing slashes */ path = dir = apr_pstrcat(r->pool, path, "/", NULL); while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/') - path[n-1] = '\0'; + path[n-1] = '\0'; /* print "ftp://host/" */ n = apr_snprintf(buf, sizeof(buf), DOCTYPE_HTML_3_2 - "%s%s\n" - "\n" - "

Directory of " - "%s/", - site, path, site, path, site); + "%s%s\n" + "\n" + "

Directory of " + "%s/", + site, path, site, path, site); total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); while ((dir = strchr(dir+1, '/')) != NULL) { - *dir = '\0'; - if ((reldir = strrchr(path+1, '/'))==NULL) - reldir = path+1; - else - ++reldir; - /* print "path/" component */ - apr_snprintf(buf, sizeof(buf), "%s/", path+1, reldir); - total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); - *dir = '/'; + *dir = '\0'; + if ((reldir = strrchr(path+1, '/'))==NULL) + reldir = path+1; + else + ++reldir; + /* print "path/" component */ + apr_snprintf(buf, sizeof(buf), "%s/", path+1, reldir); + total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); + *dir = '/'; } /* If the caller has determined the current directory, and it differs */ /* from what the client requested, then show the real name */ if (cwd == NULL || strncmp (cwd, path, strlen(cwd)) == 0) { - apr_snprintf(buf, sizeof(buf), "

\n
");
+	apr_snprintf(buf, sizeof(buf), "\n
");
     } else {
-    apr_snprintf(buf, sizeof(buf), "\n(%s)\n
", cwd);
+	apr_snprintf(buf, sizeof(buf), "\n(%s)\n
", cwd);
     }
     total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
 
     while (!con->aborted) {
-    n = ap_bgets(buf, sizeof buf, f);
-    if (n == -1) {        /* input error */
-        if (c != NULL) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "proxy: error reading from cache");
-            ap_proxy_cache_error(&c);
-        }
-        break;
-    }
-    if (n == 0)
-        break;        /* EOF */
-    if (buf[0] == 'l' && (filename=strstr(buf, " -> ")) != NULL) {
-        char *link_ptr = filename;
-
-        do {
-        filename--;
-        } while (filename[0] != ' ');
-        *(filename++) = '\0';
-        *(link_ptr++) = '\0';
-        if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
-          link_ptr[n - 1] = '\0';
-        apr_snprintf(buf2, sizeof(buf2), "%s %s %s\n", buf, 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 */
-        searchptr = strchr(buf, '<');
-        if (searchptr != NULL)
-            *searchptr = '[';
-        searchptr = strchr(buf, '>');
-        if (searchptr != NULL)
-            *searchptr = ']';
-        }
-
-        filename = strrchr(buf, ' ');
-        *(filename++) = 0;
-        filename[strlen(filename) - 1] = 0;
-
-        /* handle filenames with spaces in 'em */
-        if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
-        firstfile = 0;
-        searchidx = filename - buf;
-        }
-        else if (searchidx != 0 && buf[searchidx] != 0) {
-        *(--filename) = ' ';
-        buf[searchidx - 1] = 0;
-        filename = &buf[searchidx];
-        }
-
-        /* Special handling for '.' and '..' */
-        if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
-        apr_snprintf(buf2, sizeof(buf2), "%s %s\n",
-            buf, filename, filename);
-        }
-        else {
-        apr_snprintf(buf2, sizeof(buf2), "%s %s\n", buf, filename, filename);
-        }
-        apr_cpystrn(buf, buf2, sizeof(buf));
-        n = strlen(buf);
-    }
-
-    o = 0;
-    total_bytes_sent += n;
-
-    cntr = n;
-    if (cachefp && apr_write(cachefp, buf, &cntr) != APR_SUCCESS) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                      "proxy: error writing to cache");
-        ap_proxy_cache_error(&c);
-        cachefp = NULL;
-    }
-
-    while (n && !r->connection->aborted) {
-        w = ap_bwrite(con->client, &buf[o], n, &cntr);
-        if (w <= 0)
-        break;
-        n -= w;
-        o += w;
-    }
+	n = ap_bgets(buf, sizeof buf, f);
+	if (n == -1) {		/* input error */
+	    if (c != NULL) {
+		ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+		  "proxy: error reading from cache");
+		  ap_proxy_cache_error(&c);
+	    }
+	    break;
+	}
+	if (n == 0)
+	    break;		/* EOF */
+	if (buf[0] == 'l' && (filename=strstr(buf, " -> ")) != NULL) {
+	    char *link_ptr = filename;
+
+	    do {
+		filename--;
+	    } while (filename[0] != ' ');
+	    *(filename++) = '\0';
+	    *(link_ptr++) = '\0';
+	    if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
+	      link_ptr[n - 1] = '\0';
+	    apr_snprintf(buf2, sizeof(buf2), "%s %s %s\n", buf, 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 */
+		searchptr = strchr(buf, '<');
+		if (searchptr != NULL)
+		    *searchptr = '[';
+		searchptr = strchr(buf, '>');
+		if (searchptr != NULL)
+		    *searchptr = ']';
+	    }
+
+	    filename = strrchr(buf, ' ');
+	    *(filename++) = 0;
+	    filename[strlen(filename) - 1] = 0;
+
+	    /* handle filenames with spaces in 'em */
+	    if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
+		firstfile = 0;
+		searchidx = filename - buf;
+	    }
+	    else if (searchidx != 0 && buf[searchidx] != 0) {
+		*(--filename) = ' ';
+		buf[searchidx - 1] = 0;
+		filename = &buf[searchidx];
+	    }
+
+	    /* Special handling for '.' and '..' */
+	    if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
+		apr_snprintf(buf2, sizeof(buf2), "%s %s\n",
+		    buf, filename, filename);
+	    }
+	    else {
+		apr_snprintf(buf2, sizeof(buf2), "%s %s\n", buf, filename, filename);
+	    }
+	    apr_cpystrn(buf, buf2, sizeof(buf));
+	    n = strlen(buf);
+	}
+
+	o = 0;
+	total_bytes_sent += n;
+
+        cntr = n;
+	if (cachefp && apr_write(cachefp, buf, &cntr) != APR_SUCCESS) {
+	   ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+	  "proxy: error writing to cache");
+	   ap_proxy_cache_error(&c);
+	   cachefp = NULL;
+	}
+
+	while (n && !r->connection->aborted) {
+	    w = ap_bwrite(con->client, &buf[o], n, &cntr);
+	    if (w <= 0)
+		break;
+	    n -= w;
+	    o += w;
+	}
     }
 
     total_bytes_sent += ap_proxy_bputs2("

\n", con->client, c); @@ -430,7 +430,7 @@ static long int send_dir(BUFF *f, request_rec *r, ap_cache_el *c, char *cwd) * with username and password (which was presumably queried from the user) * supplied in the Authorization: header. * Note that we "invent" a realm name which consists of the - * ftp://user@host part of the reqest (sans password if supplied but invalid-) + * ftp://user@host part of the reqest (sans password -if supplied but invalid-) */ static int ftp_unauthorized (request_rec *r, int log_it) { @@ -439,16 +439,16 @@ static int ftp_unauthorized (request_rec *r, int log_it) * (log username/password guessing attempts) */ if (log_it) - ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, - "proxy: missing or failed auth to %s", - ap_unparse_uri_components(r->pool, - &r->parsed_uri, UNP_OMITPATHINFO)); + ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, + "proxy: missing or failed auth to %s", + ap_unparse_uri_components(r->pool, + &r->parsed_uri, UNP_OMITPATHINFO)); apr_table_setn(r->err_headers_out, "WWW-Authenticate", apr_pstrcat(r->pool, "Basic realm=\"", - ap_unparse_uri_components(r->pool, &r->parsed_uri, - UNP_OMITPASSWORD|UNP_OMITPATHINFO), - "\"", NULL)); + ap_unparse_uri_components(r->pool, &r->parsed_uri, + UNP_OMITPASSWORD|UNP_OMITPATHINFO), + "\"", NULL)); return HTTP_UNAUTHORIZED; } @@ -459,7 +459,7 @@ static int ftp_unauthorized (request_rec *r, int log_it) * Troy Morrison * PASV added by Chuck */ -int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) +int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) { char *host, *path, *strp, *parms; char *cwd = NULL; @@ -470,14 +470,14 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) int port, i, j, len, rc, nocache = 0; apr_socket_t *csd; struct in_addr destaddr; + apr_table_t *resp_hdrs; BUFF *f; - apr_file_t *cachefp = NULL; BUFF *data = NULL; + apr_file_t *cachefp = NULL; apr_pool_t *p = r->pool; int one = 1; const long int zero = 0L; - apr_table_t *resp_hdrs; - + void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); @@ -489,11 +489,11 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) unsigned short pport; int pasvmode = 0; char pasv[64]; - char *pstr, dates[APR_RFC822_DATE_LEN]; + char *pstr, dates[AP_RFC822_DATE_LEN]; char *npaddr; apr_uint32_t npport; - + /* stuff for responses */ char resp[MAX_STRING_LEN]; char *size = NULL; @@ -501,14 +501,14 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) /* we only support GET and HEAD */ if (r->method_number != M_GET) - return HTTP_NOT_IMPLEMENTED; + return HTTP_NOT_IMPLEMENTED; /* We break the URL into host, port, path-search */ host = r->parsed_uri.hostname; port = (r->parsed_uri.port != 0) - ? r->parsed_uri.port - : ap_default_port_for_request(r); + ? r->parsed_uri.port + : ap_default_port_for_request(r); path = apr_pstrdup(p, r->parsed_uri.path); path = (path != NULL && path[0] != '\0') ? &path[1] : ""; @@ -521,39 +521,39 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) * But chances are still smaller that the URL is logged regularly. */ if ((password = apr_table_get(r->headers_in, "Authorization")) != NULL - && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0 - && (password = ap_pbase64decode(r->pool, password))[0] != ':') { - /* Note that this allocation has to be made from r->connection->pool - * because it has the lifetime of the connection. The other allocations - * are temporary and can be tossed away any time. - */ - user = ap_getword_nulls (r->pool, &password, ':'); - r->ap_auth_type = "Basic"; - r->user = r->parsed_uri.user = user; - nocache = 1; /* This resource only accessible with username/password */ + && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0 + && (password = ap_pbase64decode(r->pool, password))[0] != ':') { + /* Note that this allocation has to be made from r->connection->pool + * because it has the lifetime of the connection. The other allocations + * are temporary and can be tossed away any time. + */ + user = ap_getword_nulls (r->pool, &password, ':'); + r->ap_auth_type = "Basic"; + r->user = r->parsed_uri.user = user; + nocache = 1; /* This resource only accessible with username/password */ } else if ((user = r->parsed_uri.user) != NULL) { - user = apr_pstrdup(p, user); - decodeenc(user); - if ((password = r->parsed_uri.password) != NULL) { - char *tmp = apr_pstrdup(p, password); - decodeenc(tmp); - password = tmp; - } - nocache = 1; /* This resource only accessible with username/password */ + user = apr_pstrdup(p, user); + decodeenc(user); + if ((password = r->parsed_uri.password) != NULL) { + char *tmp = apr_pstrdup(p, password); + decodeenc(tmp); + password = tmp; + } + nocache = 1; /* This resource only accessible with username/password */ } else { - user = "anonymous"; - password = "apache_proxy@"; + user = "anonymous"; + password = "apache_proxy@"; } /* check if ProxyBlock directive on this host */ - destaddr.s_addr = apr_inet_addr(host); + destaddr.s_addr = ap_inet_addr(host); for (i = 0; i < conf->noproxies->nelts; i++) { - if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL) - || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') - return ap_proxyerror(r, HTTP_FORBIDDEN, - "Connect to remote machine blocked"); + if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') + return ap_proxyerror(r, HTTP_FORBIDDEN, + "Connect to remote machine blocked"); } ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, @@ -561,7 +561,7 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) parms = strchr(path, ';'); if (parms != NULL) - *(parms++) = '\0'; + *(parms++) = '\0'; if ((apr_create_tcp_socket(&sock, r->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, @@ -569,25 +569,29 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) return HTTP_INTERNAL_SERVER_ERROR; } - if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,conf->recv_buffer_size)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); +#if !defined(TPF) && !defined(BEOS) + if (conf->recv_buffer_size > 0 + && apr_setsocketopt(sock, APR_SO_RCVBUF, + conf->recv_buffer_size)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } - +#endif + if (apr_setsocketopt(sock, APR_SO_REUSEADDR, one)) { #ifndef _OSD_POSIX /* BS2000 has this option "always on" */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); - apr_close_socket(sock); - return HTTP_INTERNAL_SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); + apr_close_socket(sock); + return HTTP_INTERNAL_SERVER_ERROR; #endif /*_OSD_POSIX*/ } if (ap_proxy_doconnect(sock, host, port, r) == -1) { - apr_close_socket(sock); - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - apr_pstrcat(r->pool, "Could not connect to remote machine: ", - strerror(errno), NULL)); + apr_close_socket(sock); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool, + "Could not connect to remote machine: ", + strerror(errno), NULL)); } f = ap_bcreate(p, B_RDWR); @@ -603,37 +607,37 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) /* 220 Service ready for new user. */ /* 421 Service not available, closing control connection. */ i = ftp_getrc_msg(f, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: returned status %d", i); 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"); } #if 0 if (i == 120) { - /* RFC2068 states: - * 14.38 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 this field can - * be either an HTTP-date or an integer number of seconds (in decimal) - * after the time of the response. - * Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds ) - */ - ap_set_header("Retry-After", apr_psprintf(p, "%u", 60*wait_mins); - return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp); + /* RFC2068 states: + * 14.38 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 this field can + * be either an HTTP-date or an integer number of seconds (in decimal) + * after the time of the response. + * Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds ) + */ + ap_set_header("Retry-After", apr_psprintf(p, "%u", 60*wait_mins); + return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp); } #endif if (i != 220) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, resp); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, resp); } ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: connected."); ap_bvputs(f, "USER ", user, CRLF, NULL); - ap_bflush(f); /* capture any errors */ + ap_bflush(f); /* capture any errors */ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: USER %s", user); @@ -651,48 +655,50 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d", i); 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"); } if (i == 530) { - return ftp_unauthorized (r, 1); /* log it: user name guessing attempt? */ + return ftp_unauthorized (r, 1); /* log it: user name guessing attempt? */ } if (i != 230 && i != 331) { - return HTTP_BAD_GATEWAY; + return HTTP_BAD_GATEWAY; } - if (i == 331) { /* send password */ - if (password == NULL) { - return ftp_unauthorized (r, 0); - } - ap_bvputs(f, "PASS ", password, CRLF, NULL); - ap_bflush(f); + if (i == 331) { /* send password */ + if (password == NULL) { + return ftp_unauthorized (r, 0); + } + ap_bvputs(f, "PASS ", password, CRLF, NULL); + ap_bflush(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: PASS %s", password); /* possible results 202, 230, 332, 421, 500, 501, 503, 530 */ - /* 230 User logged in, proceed. */ - /* 332 Need account for login. */ - /* 421 Service not available, closing control connection. */ - /* 500 Syntax error, command unrecognized. */ - /* 501 Syntax error in parameters or arguments. */ - /* 503 Bad sequence of commands. */ - /* 530 Not logged in. */ - i = ftp_getrc(f); + /* 230 User logged in, proceed. */ + /* 332 Need account for login. */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 503 Bad sequence of commands. */ + /* 530 Not logged in. */ + i = ftp_getrc(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d", i); - if (i == -1) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server"); - } - if (i == 332) { - return ap_proxyerror(r, HTTP_UNAUTHORIZED, "Need account for login"); - } - /* @@@ questionable -- we might as well return a 403 Forbidden here */ - if (i == 530) { - return ftp_unauthorized (r, 1); /* log it: passwd guessing attempt? */ - } - if (i != 230 && i != 202) { - return HTTP_BAD_GATEWAY; - } + if (i == -1) { + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 332) { + return ap_proxyerror(r, HTTP_UNAUTHORIZED, + "Need account for login"); + } + /* @@@ questionable -- we might as well return a 403 Forbidden here */ + if (i == 530) { + return ftp_unauthorized (r, 1); /* log it: passwd guessing attempt? */ + } + if (i != 230 && i != 202) { + return HTTP_BAD_GATEWAY; + } } /* set the directory (walk directory component by component): @@ -700,61 +706,61 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) * machine */ for (;;) { - strp = strchr(path, '/'); - if (strp == NULL) - break; - *strp = '\0'; - - len = decodeenc(path); - ap_bvputs(f, "CWD ", path, CRLF, NULL); - ap_bflush(f); + strp = strchr(path, '/'); + if (strp == NULL) + break; + *strp = '\0'; + + len = decodeenc(path); + ap_bvputs(f, "CWD ", path, CRLF, NULL); + ap_bflush(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: CWD %s", path); - *strp = '/'; + *strp = '/'; /* responses: 250, 421, 500, 501, 502, 530, 550 */ - /* 250 Requested file action okay, completed. */ - /* 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. */ - /* 550 Requested action not taken. */ - i = ftp_getrc(f); + /* 250 Requested file action okay, completed. */ + /* 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. */ + /* 550 Requested action not taken. */ + i = ftp_getrc(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d", i); - if (i == -1) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); - } - if (i == 550) { - return HTTP_NOT_FOUND; - } - if (i != 250) { - return HTTP_BAD_GATEWAY; - } + if (i == -1) { + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + return HTTP_NOT_FOUND; + } + if (i != 250) { + return HTTP_BAD_GATEWAY; + } - path = strp + 1; + path = strp + 1; } if (parms != NULL && strncmp(parms, "type=", 5) == 0) { - parms += 5; - if ((parms[0] != 'd' && parms[0] != 'a' && parms[0] != 'i') || - parms[1] != '\0') - parms = ""; + parms += 5; + if ((parms[0] != 'd' && parms[0] != 'a' && parms[0] != 'i') || + parms[1] != '\0') + parms = ""; } else - parms = ""; + parms = ""; /* changed to make binary transfers the default */ if (parms[0] != 'a') { - /* set type to image */ - /* TM - Added \015\012 to the end of TYPE I, otherwise it hangs the - connection */ - ap_bputs("TYPE I" CRLF, f); - ap_bflush(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: TYPE I"); + /* set type to image */ + /* TM - Added CRLF to the end of TYPE I, otherwise it hangs the + connection */ + ap_bputs("TYPE I" CRLF, f); + ap_bflush(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: TYPE I"); /* responses: 200, 421, 500, 501, 504, 530 */ /* 200 Command okay. */ /* 421 Service not available, closing control connection. */ @@ -762,33 +768,36 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) /* 501 Syntax error in parameters or arguments. */ /* 504 Command not implemented for that parameter. */ /* 530 Not logged in. */ - i = ftp_getrc(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: returned status %d", i); - if (i == -1) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); - } - if (i != 200 && i != 504) { - return HTTP_BAD_GATEWAY; - } + i = ftp_getrc(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: returned status %d", i); + if (i == -1) { + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i != 200 && i != 504) { + return HTTP_BAD_GATEWAY; + } /* Allow not implemented */ - if (i == 504) - parms[0] = '\0'; + if (i == 504) + parms[0] = '\0'; } /* try to set up PASV data connection first */ if ((apr_create_tcp_socket(&dsock, r->pool)) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error creating PASV socket"); - ap_bclose(f); - return HTTP_INTERNAL_SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error creating PASV socket"); + ap_bclose(f); + return HTTP_INTERNAL_SERVER_ERROR; } - if (conf->recv_buffer_size > 0 && apr_setsocketopt(dsock, APR_SO_RCVBUF,conf->recv_buffer_size)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); +#if !defined (TPF) && !defined(BEOS) + if (conf->recv_buffer_size > 0 && apr_setsocketopt(dsock, APR_SO_RCVBUF, + conf->recv_buffer_size)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } +#endif ap_bputs("PASV" CRLF, f); ap_bflush(f); @@ -803,89 +812,87 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) /* 530 Not logged in. */ i = ap_bgets(pasv, sizeof(pasv), f); if (i == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, - "PASV: control connection is toast"); - apr_close_socket(dsock); - ap_bclose(f); - return HTTP_INTERNAL_SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, + "PASV: control connection is toast"); + apr_close_socket(dsock); + ap_bclose(f); + return HTTP_INTERNAL_SERVER_ERROR; } else { - pasv[i - 1] = '\0'; - pstr = strtok(pasv, " "); /* separate result code */ - if (pstr != NULL) { - presult = atoi(pstr); - if (*(pstr + strlen(pstr) + 1) == '=') - pstr += strlen(pstr) + 2; - else - { - pstr = strtok(NULL, "("); /* separate address & port params */ - if (pstr != NULL) - pstr = strtok(NULL, ")"); - } - } - else - presult = atoi(pasv); + pasv[i - 1] = '\0'; + pstr = strtok(pasv, " "); /* separate result code */ + if (pstr != NULL) { + presult = atoi(pstr); + if (*(pstr + strlen(pstr) + 1) == '=') + pstr += strlen(pstr) + 2; + else + { + pstr = strtok(NULL, "("); /* separate address & port params */ + if (pstr != NULL) + pstr = strtok(NULL, ")"); + } + } + else + presult = atoi(pasv); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d", presult); - if (presult == 227 && pstr != NULL && (sscanf(pstr, - "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) { - /* pardon the parens, but it makes gcc happy */ - destaddr.s_addr = htonl((((((h3 << 8) + h2) << 8) + h1) << 8) + h0); - pport = (p1 << 8) + p0; + if (presult == 227 && pstr != NULL && (sscanf(pstr, + "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) { + /* pardon the parens, but it makes gcc happy */ + destaddr.s_addr = htonl((((((h3 << 8) + h2) << 8) + h1) << 8) + h0); + pport = (p1 << 8) + p0; ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: contacting host %d.%d.%d.%d:%d", h3, h2, h1, h0, pport); - if (ap_proxy_doconnect(dsock, inet_ntoa(destaddr), pport, r) == -1) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - apr_pstrcat(r->pool, - "Could not connect to remote machine: ", - strerror(errno), NULL)); - } - else { - pasvmode = 1; - } - } - else - apr_close_socket(dsock); /* and try the regular way */ - } - - if (!pasvmode) { /* set up data connection */ - - if ((apr_create_tcp_socket(&dsock, r->pool)) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error creating socket"); - ap_bclose(f); - return HTTP_INTERNAL_SERVER_ERROR; - } + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + apr_pstrcat(r->pool, + "Could not connect to remote machine: ", + strerror(errno), NULL)); + } + else { + pasvmode = 1; + } + } + else + apr_close_socket(dsock); /* and try the regular way */ + } + + if (!pasvmode) { /* set up data connection */ + if ((apr_create_tcp_socket(&dsock, r->pool)) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error creating socket"); + ap_bclose(f); + return HTTP_INTERNAL_SERVER_ERROR; + } apr_get_local_port(&npport, sock); apr_get_local_ipaddr(&npaddr, sock); apr_set_local_port(dsock, npport); apr_set_local_ipaddr(dsock, npaddr); - - if (apr_setsocketopt(dsock, APR_SO_REUSEADDR, one) != APR_SUCCESS) { + + if (apr_setsocketopt(dsock, APR_SO_REUSEADDR, one) != APR_SUCCESS) { #ifndef _OSD_POSIX /* BS2000 has this option "always on" */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error setting reuseaddr option"); - apr_close_socket(dsock); - ap_bclose(f); - return HTTP_INTERNAL_SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error setting reuseaddr option"); + apr_close_socket(dsock); + ap_bclose(f); + return HTTP_INTERNAL_SERVER_ERROR; #endif /*_OSD_POSIX*/ - } + } - if (apr_bind(dsock) != APR_SUCCESS) { - char buff[22]; + if (apr_bind(dsock) != APR_SUCCESS) { + char buff[22]; - apr_snprintf(buff, sizeof(buff), "%s:%d", npaddr, npport); - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error binding to ftp data socket %s", buff); - ap_bclose(f); - apr_close_socket(dsock); - return HTTP_INTERNAL_SERVER_ERROR; - } - apr_listen(dsock, 2); /* only need a short queue */ + apr_snprintf(buff, sizeof(buff), "%s:%d", npaddr, npport); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error binding to ftp data socket %s", buff); + ap_bclose(f); + apr_close_socket(dsock); + return HTTP_INTERNAL_SERVER_ERROR; + } + apr_listen(dsock, 2); /* only need a short queue */ } /* set request; "path" holds last path component */ @@ -894,57 +901,57 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */ if (len == 0) { - parms = "d"; + parms = "d"; } else { - ap_bvputs(f, "SIZE ", path, CRLF, NULL); - ap_bflush(f); + ap_bvputs(f, "SIZE ", path, CRLF, NULL); + ap_bflush(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: SIZE %s", path); - i = ftp_getrc_msg(f, resp, sizeof resp); + i = ftp_getrc_msg(f, resp, sizeof resp); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d with response %s", i, resp); - if (i != 500) { /* Size command not recognized */ - if (i == 550) { /* Not a regular file */ + if (i != 500) { /* Size command not recognized */ + if (i == 550) { /* Not a regular file */ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: SIZE shows this is a directory"); - parms = "d"; - ap_bvputs(f, "CWD ", path, CRLF, NULL); - ap_bflush(f); + parms = "d"; + ap_bvputs(f, "CWD ", path, CRLF, NULL); + ap_bflush(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: CWD %s", path); - i = ftp_getrc(f); - /* possible results: 250, 421, 500, 501, 502, 530, 550 */ - /* 250 Requested file action okay, completed. */ - /* 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. */ - /* 550 Requested action not taken. */ + i = ftp_getrc(f); + /* possible results: 250, 421, 500, 501, 502, 530, 550 */ + /* 250 Requested file action okay, completed. */ + /* 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. */ + /* 550 Requested action not taken. */ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d", i); - if (i == -1) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); - } - if (i == 550) { - return HTTP_NOT_FOUND; - } - if (i != 250) { - return HTTP_BAD_GATEWAY; - } - path = ""; - len = 0; - } - else if (i == 213) { /* Size command ok */ - for (j = 0; j < sizeof resp && apr_isdigit(resp[j]); j++) - ; - resp[j] = '\0'; - if (resp[0] != '\0') - size = apr_pstrdup(p, resp); - } - } + if (i == -1) { + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + return HTTP_NOT_FOUND; + } + if (i != 250) { + return HTTP_BAD_GATEWAY; + } + path = ""; + len = 0; + } + else if (i == 213) { /* Size command ok */ + for (j = 0; j < sizeof resp && apr_isdigit(resp[j]); j++) + ; + resp[j] = '\0'; + if (resp[0] != '\0') + size = apr_pstrdup(p, resp); + } + } } #ifdef AUTODETECT_PWD @@ -960,33 +967,33 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) /* 502 Command not implemented. */ /* 550 Requested action not taken. */ i = ftp_getrc_msg(f, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: PWD returned status %d", i); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: PWD returned status %d", i); if (i == -1 || i == 421) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); } if (i == 550) { - return HTTP_NOT_FOUND; + return HTTP_NOT_FOUND; } if (i == 257) { - const char *dirp = resp; - cwd = ap_getword_conf(r->pool, &dirp); + const char *dirp = resp; + cwd = ap_getword_conf(r->pool, &dirp); } #endif /*AUTODETECT_PWD*/ if (parms[0] == 'd') { - if (len != 0) - ap_bvputs(f, "LIST ", path, CRLF, NULL); - else - ap_bputs("LIST -lag" CRLF, f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: LIST %s", (len == 0 ? "" : path)); + if (len != 0) + ap_bvputs(f, "LIST ", path, CRLF, NULL); + else + ap_bputs("LIST -lag" CRLF, f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: LIST %s", (len == 0 ? "" : path)); } else { - ap_bvputs(f, "RETR ", path, CRLF, NULL); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: RETR %s", path); + ap_bvputs(f, "RETR ", path, CRLF, NULL); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: RETR %s", path); } ap_bflush(f); /* RETR: 110, 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 530, 550 @@ -1009,127 +1016,137 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: returned status %d", rc); if (rc == -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"); } if (rc == 550) { ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: RETR failed, trying LIST instead"); - parms = "d"; - ap_bvputs(f, "CWD ", path, CRLF, NULL); - ap_bflush(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + parms = "d"; + ap_bvputs(f, "CWD ", path, CRLF, NULL); + ap_bflush(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: CWD %s", path); - /* possible results: 250, 421, 500, 501, 502, 530, 550 */ - /* 250 Requested file action okay, completed. */ - /* 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. */ - /* 550 Requested action not taken. */ - rc = ftp_getrc(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: returned status %d", rc); - if (rc == -1) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); - } - if (rc == 550) { - return HTTP_NOT_FOUND; - } - if (rc != 250) { - return HTTP_BAD_GATEWAY; - } + /* possible results: 250, 421, 500, 501, 502, 530, 550 */ + /* 250 Requested file action okay, completed. */ + /* 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. */ + /* 550 Requested action not taken. */ + rc = ftp_getrc(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: returned status %d", rc); + if (rc == -1) { + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (rc == 550) { + return HTTP_NOT_FOUND; + } + if (rc != 250) { + return HTTP_BAD_GATEWAY; + } #ifdef AUTODETECT_PWD - ap_bvputs(f, "PWD", CRLF, NULL); - ap_bflush(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: PWD"); + ap_bvputs(f, "PWD", CRLF, NULL); + ap_bflush(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: PWD"); /* responses: 257, 500, 501, 502, 421, 550 */ - /* 257 "" */ - /* 421 Service not available, closing control connection. */ - /* 500 Syntax error, command unrecognized. */ - /* 501 Syntax error in parameters or arguments. */ - /* 502 Command not implemented. */ - /* 550 Requested action not taken. */ - i = ftp_getrc_msg(f, resp, sizeof resp); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: PWD returned status %d", i); - if (i == -1 || i == 421) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); - } - if (i == 550) { - return HTTP_NOT_FOUND; - } - if (i == 257) { - const char *dirp = resp; - cwd = ap_getword_conf(r->pool, &dirp); - } + /* 257 "" */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 502 Command not implemented. */ + /* 550 Requested action not taken. */ + i = ftp_getrc_msg(f, resp, sizeof resp); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: PWD returned status %d", i); + if (i == -1 || i == 421) { + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + return HTTP_NOT_FOUND; + } + if (i == 257) { + const char *dirp = resp; + cwd = ap_getword_conf(r->pool, &dirp); + } #endif /*AUTODETECT_PWD*/ - ap_bputs("LIST -lag" CRLF, f); - ap_bflush(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: LIST -lag"); - rc = ftp_getrc(f); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: returned status %d", rc); - if (rc == -1) - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + ap_bputs("LIST -lag" CRLF, f); + ap_bflush(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: LIST -lag"); + rc = ftp_getrc(f); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: returned status %d", rc); + if (rc == -1) + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); } if (rc != 125 && rc != 150 && rc != 226 && rc != 250) - return HTTP_BAD_GATEWAY; + return HTTP_BAD_GATEWAY; r->status = HTTP_OK; r->status_line = "200 OK"; - resp_hdrs = apr_make_table(p, 2); - + resp_hdrs = ap_make_table(p, 2); + apr_rfc822_date(dates, r->request_time); apr_table_setn(resp_hdrs, "Date", dates); apr_table_setn(resp_hdrs, "Server", ap_get_server_version()); if (parms[0] == 'd') - apr_table_setn(resp_hdrs, "Content-Type", "text/html"); - else { - if (r->content_type != NULL) { - apr_table_setn(resp_hdrs, "Content-Type", r->content_type); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: Content-Type set to %s", r->content_type); - } + apr_table_setn(resp_hdrs, "Content-Type", "text/html"); else { - apr_table_setn(resp_hdrs, "Content-Type", ap_default_type(r)); - } - if (parms[0] != 'a' && size != NULL) { - /* We "trust" the ftp server to really serve (size) bytes... */ - apr_table_setn(resp_hdrs, "Content-Length", size); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: Content-Length set to %s", size); - } + if (r->content_type != NULL) { + apr_table_setn(resp_hdrs, "Content-Type", r->content_type); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: Content-Type set to %s", r->content_type); + } + else { + apr_table_setn(resp_hdrs, "Content-Type", ap_default_type(r)); + } + if (parms[0] != 'a' && size != NULL) { + /* We "trust" the ftp server to really serve (size) bytes... */ + apr_table_setn(resp_hdrs, "Content-Length", size); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: Content-Length set to %s", size); + } } if (r->content_encoding != NULL && r->content_encoding[0] != '\0') { - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: Content-Encoding set to %s", r->content_encoding); - apr_table_setn(resp_hdrs, "Content-Encoding", r->content_encoding); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: Content-Encoding set to %s", r->content_encoding); + apr_table_setn(resp_hdrs, "Content-Encoding", r->content_encoding); } - ap_cache_el_header_merge(c, resp_hdrs); - + ap_cache_el_header_merge(c, resp_hdrs); + /* check if NoCache directive on this host */ for (i = 0; i < conf->nocaches->nelts; i++) { - if ((ncent[i].name != NULL && ap_strstr_c(host, ncent[i].name) != NULL) - || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') - nocache = 1; + if ((ncent[i].name != NULL && ap_strstr_c(host, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; } +#if 0 + i = ap_proxy_cache_update(c, resp_hdrs, 0, nocache); + + if (i != DECLINED) { + ap_pclosesocket(p, dsock); + ap_bclose(f); + return i; + } +#endif + if(nocache || !ap_proxy_cache_should_cache(r, resp_hdrs, 0)) ap_proxy_cache_error(&c); else ap_cache_el_data(c, &cachefp); - if (!pasvmode) { /* wait for connection */ + if (!pasvmode) { /* wait for connection */ for(;;) { switch(apr_accept(&inc, dsock, r->pool)) @@ -1151,29 +1168,30 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) ap_bpush_socket(f, csd); } else { - data = ap_bcreate(p, B_RDWR); - ap_bpush_socket(data, dsock); + data = ap_bcreate(p, B_RDWR); + ap_bpush_socket(data, dsock); } /* send response */ /* write status line */ if (!r->assbackwards) - ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); - if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error writing CRLF to cache"); - ap_proxy_cache_error(&c); - cachefp = NULL; + ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); + if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", + r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error writing CRLF to cache"); + c = ap_proxy_cache_error(&c); + cachefp = NULL; } /* send headers */ ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL); if (!r->assbackwards) - ap_rputs(CRLF, r); + ap_rputs(CRLF, r); if (cachefp && apr_puts(CRLF, cachefp) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error writing CRLF to cache"); - ap_proxy_cache_error(&c); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error writing CRLF to cache"); + c = ap_proxy_cache_error(&c); cachefp = NULL; } @@ -1181,28 +1199,27 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) r->sent_bodyct = 1; /* send body */ if (!r->header_only) { - if (parms[0] != 'd') { - /* we don't need no steekin' cache completion*/ - ap_proxy_send_fb(NULL, data, r, c); - } else - send_dir(data, r, c, cwd); + if (parms[0] != 'd') { + ap_proxy_send_fb(NULL, data, r, c); + } else + send_dir(data, r, c, cwd); - if (rc == 125 || rc == 150) - rc = ftp_getrc(f); + if (rc == 125 || rc == 150) + rc = ftp_getrc(f); - /* XXX: we checked for 125||150||226||250 above. This is redundant. */ - if (rc != 226 && rc != 250) + /* XXX: we checked for 125||150||226||250 above. This is redundant. */ + if (rc != 226 && rc != 250) /* XXX: we no longer log an "error writing to c->tempfile" - should we? */ - ap_proxy_cache_error(&c); + ap_proxy_cache_error(&c); } else { /* abort the transfer */ - ap_bputs("ABOR" CRLF, f); - ap_bflush(f); - if (!pasvmode) - ap_bclose(data); - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, - "FTP: ABOR"); + ap_bputs("ABOR" CRLF, f); + ap_bflush(f); + if (!pasvmode) + ap_bclose(data); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, + "FTP: ABOR"); /* responses: 225, 226, 421, 500, 501, 502 */ /* 225 Data connection open; no transfer in progress. */ /* 226 Closing data connection. */ @@ -1226,11 +1243,12 @@ int ap_proxy_ftp_handler(request_rec *r, ap_cache_el *c, char *url) i = ftp_getrc(f); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "FTP: QUIT: status %d", i); + if (pasvmode) - ap_bclose(data); + ap_bclose(data); ap_bclose(f); - ap_rflush(r); /* flush before garbage collection */ + ap_rflush(r); /* flush before garbage collection */ if(c) ap_proxy_cache_update(c); return OK;