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

📄 mod_proxy_ftp.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
                }            }            else {                /* and try the regular way */                apr_socket_close(data_sock);            }        }    }/*bypass:*/    /* set up data connection - PORT */    if (!connect) {        apr_sockaddr_t *local_addr;        char *local_ip;        apr_port_t local_port;        unsigned int h0, h1, h2, h3, p0, p1;        if ((rv = apr_socket_create(&local_sock, connect_addr->family, SOCK_STREAM, 0, r->pool)) != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "proxy: FTP: error creating local socket");            proxy_ftp_cleanup(r, backend);            return HTTP_INTERNAL_SERVER_ERROR;        }        apr_socket_addr_get(&local_addr, APR_LOCAL, sock);        local_port = local_addr->port;        apr_sockaddr_ip_get(&local_ip, local_addr);        if ((rv = apr_socket_opt_set(local_sock, APR_SO_REUSEADDR, one))                != APR_SUCCESS) {#ifndef _OSD_POSIX              /* BS2000 has this option "always on" */            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "proxy: FTP: error setting reuseaddr option");            proxy_ftp_cleanup(r, backend);            return HTTP_INTERNAL_SERVER_ERROR;#endif                          /* _OSD_POSIX */        }        apr_sockaddr_info_get(&local_addr, local_ip, APR_UNSPEC, local_port, 0, r->pool);        if ((rv = apr_socket_bind(local_sock, local_addr)) != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,            "proxy: FTP: error binding to ftp data socket %pI", local_addr);            proxy_ftp_cleanup(r, backend);            return HTTP_INTERNAL_SERVER_ERROR;        }        /* only need a short queue */        if ((rv = apr_socket_listen(local_sock, 2)) != APR_SUCCESS) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "proxy: FTP: error listening to ftp data socket %pI", local_addr);            proxy_ftp_cleanup(r, backend);            return HTTP_INTERNAL_SERVER_ERROR;        }/* 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);            rc = proxy_ftp_command(apr_psprintf(p, "PORT %d,%d,%d,%d,%d,%d" CRLF, h3, h2, h1, h0, p1, p0),                           r, origin, bb, &ftpmessage);            /* 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. */            if (rc == -1 || rc == 421) {                return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,                                      "Error reading from remote server");            }            if (rc != 200) {                return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, buffer);            }            /* signal that we must use the EPRT/PORT loop */            use_port = 1;        }        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 ftp_proxyerror(r, backend, HTTP_NOT_IMPLEMENTED,                                  "Connect to IPV6 ftp server using EPRT not supported. Enable EPSV.");        }    }    /*     * V: Set The Headers -------------------     *     * Get the size of the request, set up the environment for HTTP.     */    /* set request; "path" holds last path component */    len = decodeenc(path);    if (strchr(path, '/')) { /* are there now any '/' characters? */       return ftp_proxyerror(r, backend, HTTP_BAD_REQUEST,                             "Use of /%2f is only allowed at the base directory");    }    /* If len == 0 then it must be a directory (you can't RETR nothing)     * Also, don't allow to RETR by wildcard. Instead, create a dirlisting     */    if (len == 0 || ftp_check_globbingchars(path)) {        dirlisting = 1;    }    else {        /* (from FreeBSD ftpd):         * SIZE is not in RFC959, but Postel has blessed it and         * it will be in the updated RFC.         *         * Return size of file in a format suitable for         * using with RESTART (we just count bytes).         */        /* from draft-ietf-ftpext-mlst-14.txt:         * This value will         * change depending on the current STRUcture, MODE and TYPE of the data         * connection, or a data connection which would be created were one         * created now.  Thus, the result of the SIZE command is dependent on         * the currently established STRU, MODE and TYPE parameters.         */        /* Therefore: switch to binary if the user did not specify ";type=a" */        ftp_set_TYPE(xfer_type, r, origin, bb, &ftpmessage);        rc = proxy_ftp_command(apr_pstrcat(p, "SIZE ",                           ftp_escape_globbingchars(p, path), CRLF, NULL),                           r, origin, bb, &ftpmessage);        if (rc == -1 || rc == 421) {            return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,                                  "Error reading from remote server");        }        else if (rc == 213) {/* Size command ok */            int j;            for (j = 0; apr_isdigit(ftpmessage[j]); j++)                ;            ftpmessage[j] = '\0';            if (ftpmessage[0] != '\0')                 size = ftpmessage; /* already pstrdup'ed: no copy necessary */        }        else if (rc == 550) {    /* Not a regular file */            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                             "proxy: FTP: SIZE shows this is a directory");            dirlisting = 1;            rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",                           ftp_escape_globbingchars(p, path), CRLF, NULL),                           r, origin, bb, &ftpmessage);            /* 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. */            if (rc == -1 || rc == 421) {                return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,                                      "Error reading from remote server");            }            if (rc == 550) {                return ftp_proxyerror(r, backend, HTTP_NOT_FOUND, ftpmessage);            }            if (rc != 250) {                return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage);            }            path = "";            len = 0;        }    }    cwd = ftp_get_PWD(r, origin, bb);    if (cwd != NULL) {        apr_table_set(r->notes, "Directory-PWD", cwd);    }    if (dirlisting) {        ftp_set_TYPE('A', r, origin, bb, NULL);        /* If the current directory contains no slash, we are talking to         * a non-unix ftp system. Try LIST instead of "LIST -lag", it         * should return a long listing anyway (unlike NLST).         * Some exotic FTP servers might choke on the "-lag" switch.         */        /* Note that we do not escape the path here, to allow for         * queries like: ftp://user@host/apache/src/server/http_*.c         */        if (len != 0)            buf = apr_pstrcat(p, "LIST ", path, CRLF, NULL);        else if (cwd == NULL || strchr(cwd, '/') != NULL)            buf = apr_pstrcat(p, "LIST -lag", CRLF, NULL);        else            buf = "LIST" CRLF;    }    else {        /* switch to binary if the user did not specify ";type=a" */        ftp_set_TYPE(xfer_type, r, origin, bb, &ftpmessage);#if defined(USE_MDTM) && (defined(HAVE_TIMEGM) || defined(HAVE_GMTOFF))        /* from draft-ietf-ftpext-mlst-14.txt:         *   The FTP command, MODIFICATION TIME (MDTM), can be used to determine         *   when a file in the server NVFS was last modified.     <..>         *   The syntax of a time value is:         *           time-val       = 14DIGIT [ "." 1*DIGIT ]      <..>         *     Symbolically, a time-val may be viewed as         *           YYYYMMDDHHMMSS.sss         *     The "." and subsequent digits ("sss") are optional. <..>         *     Time values are always represented in UTC (GMT)         */        rc = proxy_ftp_command(apr_pstrcat(p, "MDTM ", ftp_escape_globbingchars(p, path), CRLF, NULL),                               r, origin, bb, &ftpmessage);        /* then extract the Last-Modified time from it (YYYYMMDDhhmmss or YYYYMMDDhhmmss.xxx GMT). */        if (rc == 213) {        struct {            char YYYY[4+1];        char MM[2+1];        char DD[2+1];        char hh[2+1];        char mm[2+1];        char ss[2+1];        } time_val;        if (6 == sscanf(ftpmessage, "%4[0-9]%2[0-9]%2[0-9]%2[0-9]%2[0-9]%2[0-9]",            time_val.YYYY, time_val.MM, time_val.DD, time_val.hh, time_val.mm, time_val.ss)) {                struct tm tms;        memset (&tms, '\0', sizeof tms);        tms.tm_year = atoi(time_val.YYYY) - 1900;        tms.tm_mon  = atoi(time_val.MM)   - 1;        tms.tm_mday = atoi(time_val.DD);        tms.tm_hour = atoi(time_val.hh);        tms.tm_min  = atoi(time_val.mm);        tms.tm_sec  = atoi(time_val.ss);#ifdef HAVE_TIMEGM /* Does system have timegm()? */        mtime = timegm(&tms);        mtime *= APR_USEC_PER_SEC;#elif HAVE_GMTOFF /* does struct tm have a member tm_gmtoff? */                /* mktime will subtract the local timezone, which is not what we want.         * Add it again because the MDTM string is GMT         */        mtime = mktime(&tms);        mtime += tms.tm_gmtoff;        mtime *= APR_USEC_PER_SEC;#else        mtime = 0L;#endif            }    }#endif /* USE_MDTM *//* FIXME: Handle range requests - send REST */        buf = apr_pstrcat(p, "RETR ", ftp_escape_globbingchars(p, path), CRLF, NULL);    }    rc = proxy_ftp_command(buf, r, origin, bb, &ftpmessage);    /* rc is an intermediate response for the LIST or RETR commands */    /*     * RETR: 110, 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 530,     * 550 NLST: 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 502,     * 530     */    /* 110 Restart marker reply. */    /* 125 Data connection already open; transfer starting. */    /* 150 File status okay; about to open data connection. */    /* 226 Closing data connection. */    /* 250 Requested file action okay, completed. */    /* 421 Service not available, closing control connection. */    /* 425 Can't open data connection. */    /* 426 Connection closed; transfer aborted. */    /* 450 Requested file action not taken. */    /* 451 Requested action aborted. Local error in processing. */    /* 500 Syntax error, command unrecognized. */    /* 501 Syntax error in parameters or arguments. */    /* 530 Not logged in. */    /* 550 Requested action not taken. */    if (rc == -1 || rc == 421) {        return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,                              "Error reading from remote server");    }    if (rc == 550) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: FTP: RETR failed, trying LIST instead");        /* Directory Listings should always be fetched in ASCII mode */        dirlisting = 1;        ftp_set_TYPE('A', r, origin, bb, NULL);        rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",                               ftp_escape_globbingchars(p, path), CRLF, NULL),                               r, origin, bb, &ftpmessage);        /* 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. */        if (rc == -1 || rc == 421) {            return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,                                  "Error reading from remote server");        }        if (rc == 550) {            return ftp_proxyerror(r, backend, HTTP_NOT_FOUND, ftpmessage);        }        if (rc != 250) {            return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage);        }        /* Update current directory after CWD */        cwd = ftp_get_PWD(r, origin, bb);        if (cwd != NULL) {            apr_table_set(r->notes, "Directory-PWD", cwd);        }        /* See above for the "LIST" vs. "LIST -lag" discussion. */        rc = proxy_ftp_command((cwd == NULL || strchr(cwd, '/') != NULL)                               ? "LIST -lag" CRLF : "LIST" CRLF,                               r, origin, bb, &ftpmessage);        /* rc is an intermediate response for the LIST command (125 transfer starting, 150 opening data connection) */        if (rc == -1 || rc == 421)            return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,                                  "Error reading from remote server");    }    if (rc != 125 && rc != 150 && rc != 226 && rc != 250) {        return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage);    }    r->status = HTTP_OK;    r->status_line = "200 OK";    apr_rfc822_date(dates, r->request_time);    apr_table_setn(r->headers_out, "Date", dates);    apr_table_setn(r->headers_out, "Server", ap_get_server_banner());    /* set content-type */    if (dirlisting) {        proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,

⌨️ 快捷键说明

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