⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_proxy_ftp.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* FTP routines for Apache proxy */#include "mod_proxy.h"#if APR_HAVE_TIME_H#include <time.h>#endif#include "apr_version.h"#if (APR_MAJOR_VERSION < 1)#undef apr_socket_create#define apr_socket_create apr_socket_create_ex#endif#define AUTODETECT_PWD/* Automatic timestamping (Last-Modified header) based on MDTM is used if: * 1) the FTP server supports the MDTM command and * 2) HAVE_TIMEGM (preferred) or HAVE_GMTOFF is available at compile time */#define USE_MDTMmodule AP_MODULE_DECLARE_DATA proxy_ftp_module;/* * Decodes a '%' escaped string, and returns the number of characters */static int decodeenc(char *x){    int i, j, ch;    if (x[0] == '\0')        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;    }    x[j] = '\0';    return j;}/* * Escape the globbing characters in a path used as argument to * the FTP commands (SIZE, CWD, RETR, MDTM, ...). * ftpd assumes '\\' as a quoting character to escape special characters. * Returns: escaped string */#define FTP_GLOBBING_CHARS "*?[{~"static char *ftp_escape_globbingchars(apr_pool_t *p, const char *path){    char *ret = apr_palloc(p, 2*strlen(path)+sizeof(""));    char *d;    for (d = ret; *path; ++path) {        if (strchr(FTP_GLOBBING_CHARS, *path) != NULL)            *d++ = '\\';        *d++ = *path;    }    *d = '\0';    return ret;}/* * Check for globbing characters in a path used as argument to * the FTP commands (SIZE, CWD, RETR, MDTM, ...). * ftpd assumes '\\' as a quoting character to escape special characters. * Returns: 0 (no globbing chars, or all globbing chars escaped), 1 (globbing chars) */static int ftp_check_globbingchars(const char *path){    for ( ; *path; ++path) {        if (*path == '\\')        ++path;        if (*path != '\0' && strchr(FTP_GLOBBING_CHARS, *path) != NULL)            return TRUE;    }    return FALSE;}/* * checks an encoded ftp string for bad characters, namely, CR, LF or * non-ascii character */static int ftp_check_string(const char *x){    int i, ch = 0;#if APR_CHARSET_EBCDIC    char buf[1];#endif    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;        }#if !APR_CHARSET_EBCDIC        if (ch == '\015' || ch == '\012' || (ch & 0x80))#else                           /* APR_CHARSET_EBCDIC */        if (ch == '\r' || ch == '\n')            return 0;        buf[0] = ch;        ap_xlate_proto_to_ascii(buf, 1);        if (buf[0] & 0x80)#endif                          /* APR_CHARSET_EBCDIC */            return 0;    }    return 1;}/* * Canonicalise ftp URLs. */static int proxy_ftp_canon(request_rec *r, char *url){    char *user, *password, *host, *path, *parms, *strp, sport[7];    apr_pool_t *p = r->pool;    const char *err;    apr_port_t port, def_port;    /* */    if (strncasecmp(url, "ftp:", 4) == 0) {        url += 4;    }    else {        return DECLINED;    }    def_port = apr_uri_port_of_scheme("ftp");    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy: FTP: canonicalising URL %s", url);    port = def_port;    err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port);    if (err)        return HTTP_BAD_REQUEST;    if (user != NULL && !ftp_check_string(user))        return HTTP_BAD_REQUEST;    if (password != NULL && !ftp_check_string(password))        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 (but not     * query args) has already been decoded. This gives rise to the problem     * of a ; being decoded into the path.     */    strp = strchr(url, ';');    if (strp != NULL) {        *(strp++) = '\0';        parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm, 0,                                  r->proxyreq);        if (parms == NULL)            return HTTP_BAD_REQUEST;    }    else        parms = "";    path = ap_proxy_canonenc(p, url, strlen(url), enc_path, 0, r->proxyreq);    if (path == NULL)        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, r->proxyreq);            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, r->proxyreq);            if (strp == NULL)                return HTTP_BAD_REQUEST;            path = apr_pstrcat(p, path, "?", strp, NULL);        }        r->args = NULL;    }/* now, rebuild URL */    if (port != def_port)        apr_snprintf(sport, sizeof(sport), ":%d", port);    else        sport[0] = '\0';    if (ap_strchr_c(host, ':')) { /* if literal IPv6 address */        host = apr_pstrcat(p, "[", host, "]", NULL);    }    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);    return OK;}/* we chop lines longer than 80 characters */#define MAX_LINE_LEN 80/* * 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 *ftp_ctrl, apr_bucket_brigade *bb, char *msgbuf, int msglen){    int status;    char response[MAX_LINE_LEN];    char buff[5];    char *mb = msgbuf, *me = &msgbuf[msglen];    apr_status_t rv;    int 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, 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;    else        status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0';    mb = apr_cpystrn(mb, response + 4, me - mb);    if (response[3] == '-') {        memcpy(buff, response, 3);        buff[3] = ' ';        do {            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);        } while (memcmp(response, buff, 4) != 0);    }    return status;}/* this is a filter that turns a raw ASCII directory listing into pretty HTML *//* ideally, mod_proxy should simply send the raw directory list up the filter * stack to mod_autoindex, which in theory should turn the raw ascii into * pretty html along with all the bells and whistles it provides... * * all in good time...! :) */typedef struct {    apr_bucket_brigade *in;    char buffer[MAX_STRING_LEN];    enum {        HEADER, BODY, FOOTER    }    state;}      proxy_dir_ctx_t;/* fallback regex for ls -s1;  ($0..$2) == 3 */#define LS_REG_PATTERN "^ *([0-9]+) +([^ ]+)$"#define LS_REG_MATCH   3static apr_status_t proxy_send_dir_filter(ap_filter_t *f,                                          apr_bucket_brigade *in){    request_rec *r = f->r;    conn_rec *c = r->connection;    apr_pool_t *p = r->pool;    apr_bucket_brigade *out = apr_brigade_create(p, c->bucket_alloc);    apr_status_t rv;    register int n;    char *dir, *path, *reldir, *site, *str, *type;    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;    if (!ctx) {        f->ctx = ctx = apr_pcalloc(p, sizeof(*ctx));        ctx->in = apr_brigade_create(p, c->bucket_alloc);        ctx->buffer[0] = 0;        ctx->state = HEADER;    }    /* combine the stored and the new */    APR_BRIGADE_CONCAT(ctx->in, in);    if (HEADER == ctx->state) {        /* basedir is either "", or "/%2f" for the "squid %2f hack" */        const char *basedir = "";  /* By default, path is relative to the $HOME dir */        char *wildcard = NULL;        const char *escpath;        /* Save "scheme://site" prefix without password */        site = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITPASSWORD | APR_URI_UNP_OMITPATHINFO);        /*         * In the reverse proxy case we usually have no site. So contruct         * one.         */        if ((*site == '\0') && (r->proxyreq == PROXYREQ_REVERSE)) {            site = ap_construct_url(p, "", r);        }        /* ... and path without query args */        path = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITSITEPART | APR_URI_UNP_OMITQUERY);        /* If path began with /%2f, change the basedir */        if (strncasecmp(path, "/%2f", 4) == 0) {            basedir = "/%2f";        }        /* Strip off a type qualifier. It is ignored for dir listings */        if ((type = strstr(path, ";type=")) != NULL)            *type++ = '\0';        (void)decodeenc(path);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -