proxy_ftp.c revision 443f96ac390c06ca4fa763d3bfcfbc8f757bd756
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * notice, this list of conditions and the following disclaimer in
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * the documentation and/or other materials provided with the
2d71630471d1c23f0137309e3c3957c633ecbfd6rbb * distribution.
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * 3. The end-user documentation included with the redistribution,
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * if any, must include the following acknowledgment:
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * "This product includes software developed by the
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * Apache Software Foundation (http://www.apache.org/)."
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * Alternately, this acknowledgment may appear in the software itself,
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * if and wherever such third-party acknowledgments normally appear.
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * 4. The names "Apache" and "Apache Software Foundation" must
3f4d7fdb598d64d80ab8656852276246f2f3b502rbb * not be used to endorse or promote products derived from this
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * software without prior written permission. For written
813bf7d72e14d04d4f40d4c5a6a2d93f203bf900wrowe * permission, please contact apache@apache.org.
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * 5. Products derived from this software may not be called "Apache",
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * nor may "Apache" appear in their name, without prior written
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * permission of the Apache Software Foundation.
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
e4afb803ff9a51f9ec7969f232b7fd4a4e94d5d4rbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * SUCH DAMAGE.
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * ====================================================================
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar * This software consists of voluntary contributions made by many
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * individuals on behalf of the Apache Software Foundation. For more
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * information on the Apache Software Foundation, please see
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * Portions of this software are based upon public domain software
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * originally written at the National Center for Supercomputing Applications,
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * University of Illinois, Urbana-Champaign.
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe/* FTP routines for Apache proxy */
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe } while(c != '\n');
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * Decodes a '%' escaped string, and returns the number of characters
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowestatic int decodeenc(char *x)
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe int i, j, ch;
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe if (x[0] == '\0')
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe return 0; /* special case for no characters */
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe for (i = 0, j = 0; x[i] != '\0'; i++, j++) {
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe/* decode it if not already done */
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe if (ch == '%' && apr_isxdigit(x[i + 1]) && apr_isxdigit(x[i + 2])) {
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe x[j] = '\0';
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * checks an encoded ftp string for bad characters, namely, CR, LF or
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * non-ascii character
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowestatic int ftp_check_string(const char *x)
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe for (i = 0; x[i] != '\0'; i++) {
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe if (ch == '%' && apr_isxdigit(x[i + 1]) && apr_isxdigit(x[i + 2])) {
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe#else /*CHARSET_EBCDIC*/
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80))
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe#endif /*CHARSET_EBCDIC*/
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * Canonicalise ftp URLs.
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe char *user, *password, *host, *path, *parms, *strp, sport[7];
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben const char *err;
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port);
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe/* now parse path/parameters args, according to rfc1738 */
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe/* N.B. if this isn't a true proxy request, then the URL path
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * (but not query args) has already been decoded.
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe * This gives rise to the problem of a ; being decoded into the
b931e2cf90d43b0894c2e2927a2a42aca46f277erpluem parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm, r->proxyreq);
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe path = ap_proxy_canonenc(p, url, strlen(url), enc_path, r->proxyreq);
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, 1);
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1);
ac00100e1ead618f1d91b77ba2d8a468782a23b7jorton/* now, rebuild URL */
e46d12b7a404d93e9ed9d09299e98b9431d95800wrowe r->filename = apr_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "",
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben * Returns the ftp status code;
e8f95a682820a599fe41b22977010636be5c2717jim * or -1 on I/O error, 0 on data error
6e8fa9b44c6d5f5b3ac9dab52c4734259bcd8335coar return -1;
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe/* check format */
2bf9d434b718368d72c1be69ede336cf19162902ben if (len < 5 || !apr_isdigit(linebuff[0]) || !apr_isdigit(linebuff[1]) ||
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben !apr_isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-'))
f05787953018140838ad51456c86c965d6a86267jim status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0';
c6e3de48da56d5a2d6298585b895cf75e3ffada2ben/* skip continuation lines */
skiplf(f);
return status;
status = 0;
skiplf(f);
skiplf(f);
return status;
char *filename;
int searchidx = 0;
unsigned long total_bytes_sent = 0;
/* print "ftp://host/" */
++reldir;
if (c != NULL) {
ap_proxy_cache_error(&c);
filename--;
apr_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s %s</A>\n", buf, filename, filename, link_ptr);
*(filename++) = 0;
firstfile = 0;
total_bytes_sent += n;
ap_proxy_cache_error(&c);
return total_bytes_sent;
* ftp://user@host part of the reqest (sans password if supplied but invalid-)
r->proxyreq = 0;
if (log_it)
return HTTP_UNAUTHORIZED;
const long int zero = 0L;
unsigned short pport;
int pasvmode = 0;
char *npaddr;
return HTTP_NOT_IMPLEMENTED;
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR;
#ifdef CHARSET_EBCDIC
i = ftp_getrc(f);
return HTTP_BAD_GATEWAY;
return ftp_unauthorized (r, 0);
ap_bflush(f);
i = ftp_getrc(f);
return HTTP_BAD_GATEWAY;
ap_bflush(f);
i = ftp_getrc(f);
return HTTP_NOT_FOUND;
return HTTP_BAD_GATEWAY;
ap_bflush(f);
i = ftp_getrc(f);
return HTTP_BAD_GATEWAY;
ap_bclose(f);
return HTTP_INTERNAL_SERVER_ERROR;
ap_bflush(f);
ap_bclose(f);
return HTTP_INTERNAL_SERVER_ERROR;
ap_bclose(f);
return HTTP_INTERNAL_SERVER_ERROR;
ap_bclose(f);
return HTTP_INTERNAL_SERVER_ERROR;
ap_bclose(f);
return HTTP_INTERNAL_SERVER_ERROR;
if (len == 0) {
ap_bflush(f);
ap_bflush(f);
i = ftp_getrc(f);
return HTTP_NOT_FOUND;
return HTTP_BAD_GATEWAY;
len = 0;
#ifdef AUTODETECT_PWD
ap_bflush(f);
return HTTP_NOT_FOUND;
if (len != 0)
ap_bflush(f);
ap_bflush(f);
return HTTP_NOT_FOUND;
return HTTP_BAD_GATEWAY;
#ifdef AUTODETECT_PWD
ap_bflush(f);
return HTTP_NOT_FOUND;
ap_bflush(f);
return HTTP_BAD_GATEWAY;
ap_proxy_cache_error(&c);
case APR_EINTR:
case APR_SUCCESS:
ap_bclose(f);
return HTTP_BAD_GATEWAY;
if (!r->assbackwards)
ap_proxy_cache_error(&c);
if (!r->assbackwards)
ap_proxy_cache_error(&c);
if (!r->header_only) {
ap_proxy_cache_error(&c);
ap_bflush(f);
if (!pasvmode)
i = ftp_getrc(f);
ap_bflush(f);
i = ftp_getrc(f);
if (pasvmode)
ap_bclose(f);
if(c) ap_proxy_cache_update(c);
return OK;