View | Details | Raw Unified | Return to bug 46798
Collapse All | Expand All

(-)docs/manual/mod/mod_proxy.xml (+41 lines)
Lines 389-394 Link Here
389
</usage>
389
</usage>
390
</directivesynopsis>
390
</directivesynopsis>
391
391
392
<directivesynopsis>
393
<name>ProxyFtpListOnWildcard</name>
394
<description>Whether wildcards in requested filenames trigger a file listing</description>
395
<syntax>ProxyFtpListOnWildcard [on|off]</syntax>
396
<default>on</default>
397
<contextlist><context>server config</context><context>virtual host</context>
398
  <context>directory</context></contextlist>
399
<compatibility>Available in IHS 7.0.0.5 and later</compatibility>  ????
400
401
<usage>
402
  <p>The <directive>ProxyFtpListOnWildcard</directive> directive
403
    controls whether wildcard characters ("*?[{~") in requested
404
    filenames cause <module>mod_proxy_ftp</module> to return a listing
405
    of files instead of downloading a file.  By default (value on),
406
    they do.  Set to "off" to allow downloading files even if they
407
    have wildcard characters in their names.</p>
408
</usage>
409
</directivesynopsis>
410
411
<directivesynopsis>
412
<name>ProxyFtpEscapeWildcards</name>
413
<description>Whether wildcards in requested filenames are escaped when sent to the FTP server</description>
414
<syntax>ProxyFtpEscapeWildcards [on|off]</syntax>
415
<default>on</default>
416
<contextlist><context>server config</context><context>virtual host</context>
417
  <context>directory</context></contextlist>
418
<compatibility>Available in IHS 7.0.0.5 and later</compatibility>  ????
419
420
<usage>
421
  <p>The <directive>ProxyFtpEscapeWildcards</directive> directive
422
    controls whether wildcard characters ("*?[{~") in requested
423
    filenames are escaped with backslash before sending them to the
424
    FTP server.  That is the default behavior, but many FTP servers
425
    don't know about the escaping and try to serve the literal filenames
426
    they were sent, including the backslashes in the names.  </p>
427
    <p>Set to "off" to allow downloading files with wildcards
428
    in their names from FTP servers that don't understand wildcard
429
    escaping.</p>
430
</usage>
431
</directivesynopsis>
432
392
<directivesynopsis type="section">
433
<directivesynopsis type="section">
393
<name>ProxyMatch</name>
434
<name>ProxyMatch</name>
394
<description>Container for directives applied to regular-expression-matched 
435
<description>Container for directives applied to regular-expression-matched 
(-)docs/manual/mod/mod_proxy_ftp.xml (+11 lines)
Lines 144-148 Link Here
144
      </note>
144
      </note>
145
    </section> <!-- /ftppass -->
145
    </section> <!-- /ftppass -->
146
146
147
    <section id="wildcard"><title>Why do I get a file listing when I expected
148
        a file to be downloaded?</title>
149
      <p>In order to allow both browsing the directories on an FTP server and
150
        downloading files, Apache looks at the request URL.  If it looks like
151
        a directory, or contains wildcard characters ("*?[{~"), then it
152
        guesses that a listing is wanted instead of a download.</p>
153
      <p>You can disable the special handling of names with wildcard characters.
154
        See the <directive>ProxyFtpListOnWildcard</directive> directive.
155
      </p>
156
    </section> <!-- /wildcard -->
157
       
147
158
148
</modulesynopsis>
159
</modulesynopsis>
(-)modules/proxy/mod_proxy.c (+39 lines)
Lines 1163-1168 Link Here
1163
    new->cookie_path_str = apr_strmatch_precompile(p, "path=", 0);
1163
    new->cookie_path_str = apr_strmatch_precompile(p, "path=", 0);
1164
    new->cookie_domain_str = apr_strmatch_precompile(p, "domain=", 0);
1164
    new->cookie_domain_str = apr_strmatch_precompile(p, "domain=", 0);
1165
    new->interpolate_env = -1; /* unset */
1165
    new->interpolate_env = -1; /* unset */
1166
    new->ftp_list_on_wildcard = 1;
1167
    new->ftp_escape_wildcards = 1;
1166
1168
1167
    return (void *) new;
1169
    return (void *) new;
1168
}
1170
}
Lines 1190-1195 Link Here
1190
    new->ftp_directory_charset = add->ftp_directory_charset ?
1192
    new->ftp_directory_charset = add->ftp_directory_charset ?
1191
                                 add->ftp_directory_charset :
1193
                                 add->ftp_directory_charset :
1192
                                 base->ftp_directory_charset;
1194
                                 base->ftp_directory_charset;
1195
    new->ftp_list_on_wildcard = add->ftp_list_on_wildcard_set ?
1196
                                add->ftp_list_on_wildcard :
1197
                                base->ftp_list_on_wildcard;
1198
    new->ftp_list_on_wildcard_set = add->ftp_list_on_wildcard_set ?
1199
                                1 :
1200
                                base->ftp_list_on_wildcard_set;
1201
    new->ftp_escape_wildcards = add->ftp_escape_wildcards_set ?
1202
                                add->ftp_escape_wildcards :
1203
                                base->ftp_escape_wildcards;
1204
    new->ftp_escape_wildcards_set = add->ftp_escape_wildcards_set ?
1205
                                1 :
1206
                                base->ftp_escape_wildcards_set;
1207
1193
    return new;
1208
    return new;
1194
}
1209
}
1195
1210
Lines 1915-1920 Link Here
1915
    return NULL;
1930
    return NULL;
1916
}
1931
}
1917
1932
1933
static const char *set_ftp_list_on_wildcard(cmd_parms *cmd, void *dconf,
1934
                                            int flag)
1935
{
1936
    proxy_dir_conf *conf = dconf;
1937
1938
    conf->ftp_list_on_wildcard = flag;
1939
    conf->ftp_list_on_wildcard_set = 1;
1940
    return NULL;
1941
}
1942
1943
static const char *set_ftp_escape_wildcards(cmd_parms *cmd, void *dconf,
1944
                                            int flag)
1945
{
1946
    proxy_dir_conf *conf = dconf;
1947
1948
    conf->ftp_escape_wildcards = flag;
1949
    conf->ftp_escape_wildcards_set = 1;
1950
    return NULL;
1951
}
1952
1918
static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config)
1953
static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config)
1919
{
1954
{
1920
    proxy_server_conf *sconf = ap_get_module_config(s->module_config,
1955
    proxy_server_conf *sconf = ap_get_module_config(s->module_config,
Lines 2126-2131 Link Here
2126
     "A balancer or worker name with list of params"),
2161
     "A balancer or worker name with list of params"),
2127
    AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
2162
    AP_INIT_TAKE1("ProxyFtpDirCharset", set_ftp_directory_charset, NULL,
2128
     RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
2163
     RSRC_CONF|ACCESS_CONF, "Define the character set for proxied FTP listings"),
2164
    AP_INIT_FLAG("ProxyFtpListOnWildcard", set_ftp_list_on_wildcard, NULL,
2165
     RSRC_CONF|ACCESS_CONF, "Whether wildcard characters in a path cause mod_proxy_ftp to list the files instead of trying to get them."),
2166
    AP_INIT_FLAG("ProxyFtpEscapeWildcards", set_ftp_escape_wildcards, NULL,
2167
     RSRC_CONF|ACCESS_CONF, "Whether the proxy should escape wildcards in paths before sending them to the FTP server.  Defaults to on, but most FTP servers will need it turned off if you need to manage paths that contain wildcard characters."),
2129
    {NULL}
2168
    {NULL}
2130
};
2169
};
2131
2170
(-)modules/proxy/mod_proxy.h (+4 lines)
Lines 213-218 Link Here
213
    const apr_strmatch_pattern* cookie_domain_str;
213
    const apr_strmatch_pattern* cookie_domain_str;
214
    const char *ftp_directory_charset;
214
    const char *ftp_directory_charset;
215
    int interpolate_env;
215
    int interpolate_env;
216
    int ftp_list_on_wildcard;
217
    int ftp_list_on_wildcard_set;
218
    int ftp_escape_wildcards;
219
    int ftp_escape_wildcards_set;
216
} proxy_dir_conf;
220
} proxy_dir_conf;
217
221
218
/* if we interpolate env vars per-request, we'll need a per-request
222
/* if we interpolate env vars per-request, we'll need a per-request
(-)modules/proxy/mod_proxy_ftp.c (-13 / +21 lines)
Lines 63-75 Link Here
63
 * Escape the globbing characters in a path used as argument to
63
 * Escape the globbing characters in a path used as argument to
64
 * the FTP commands (SIZE, CWD, RETR, MDTM, ...).
64
 * the FTP commands (SIZE, CWD, RETR, MDTM, ...).
65
 * ftpd assumes '\\' as a quoting character to escape special characters.
65
 * ftpd assumes '\\' as a quoting character to escape special characters.
66
 * Just returns the original string if ProxyFtpEscapeWildcards has been
67
 * configured "off".
66
 * Returns: escaped string
68
 * Returns: escaped string
67
 */
69
 */
68
#define FTP_GLOBBING_CHARS "*?[{~"
70
#define FTP_GLOBBING_CHARS "*?[{~"
69
static char *ftp_escape_globbingchars(apr_pool_t *p, const char *path)
71
static const char *ftp_escape_globbingchars(apr_pool_t *p, const char *path, proxy_dir_conf *dconf)
70
{
72
{
71
    char *ret = apr_palloc(p, 2*strlen(path)+sizeof(""));
73
    char *ret;
72
    char *d;
74
    char *d;
75
    
76
    if (!dconf->ftp_escape_wildcards) {
77
        return path;
78
    }
79
80
    ret = apr_palloc(p, 2*strlen(path)+sizeof(""));
73
    for (d = ret; *path; ++path) {
81
    for (d = ret; *path; ++path) {
74
        if (strchr(FTP_GLOBBING_CHARS, *path) != NULL)
82
        if (strchr(FTP_GLOBBING_CHARS, *path) != NULL)
75
            *d++ = '\\';
83
            *d++ = '\\';
Lines 809-814 Link Here
809
#if defined(USE_MDTM) && (defined(HAVE_TIMEGM) || defined(HAVE_GMTOFF))
817
#if defined(USE_MDTM) && (defined(HAVE_TIMEGM) || defined(HAVE_GMTOFF))
810
    apr_time_t mtime = 0L;
818
    apr_time_t mtime = 0L;
811
#endif
819
#endif
820
    proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
821
                                                 &proxy_module);
812
822
813
    /* stuff for PASV mode */
823
    /* stuff for PASV mode */
814
    int connect = 0, use_port = 0;
824
    int connect = 0, use_port = 0;
Lines 1157-1163 Link Here
1157
         * We could also have extended gen_test_char.c with a special T_ESCAPE_FTP_PATH
1167
         * We could also have extended gen_test_char.c with a special T_ESCAPE_FTP_PATH
1158
         */
1168
         */
1159
        rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
1169
        rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
1160
                           ftp_escape_globbingchars(p, path), CRLF, NULL),
1170
                           ftp_escape_globbingchars(p, path, dconf), CRLF, NULL),
1161
                           r, origin, bb, &ftpmessage);
1171
                           r, origin, bb, &ftpmessage);
1162
        *strp = '/';
1172
        *strp = '/';
1163
        /* responses: 250, 421, 500, 501, 502, 530, 550 */
1173
        /* responses: 250, 421, 500, 501, 502, 530, 550 */
Lines 1480-1488 Link Here
1480
    }
1490
    }
1481
1491
1482
    /* If len == 0 then it must be a directory (you can't RETR nothing)
1492
    /* If len == 0 then it must be a directory (you can't RETR nothing)
1483
     * Also, don't allow to RETR by wildcard. Instead, create a dirlisting
1493
     * Also, don't allow to RETR by wildcard. Instead, create a dirlisting,
1494
     * unless ProxyFtpListOnWildcard is off.
1484
     */
1495
     */
1485
    if (len == 0 || ftp_check_globbingchars(path)) {
1496
    if (len == 0 || (ftp_check_globbingchars(path) && dconf->ftp_list_on_wildcard)) {
1486
        dirlisting = 1;
1497
        dirlisting = 1;
1487
    }
1498
    }
1488
    else {
1499
    else {
Lines 1503-1509 Link Here
1503
        /* Therefore: switch to binary if the user did not specify ";type=a" */
1514
        /* Therefore: switch to binary if the user did not specify ";type=a" */
1504
        ftp_set_TYPE(xfer_type, r, origin, bb, &ftpmessage);
1515
        ftp_set_TYPE(xfer_type, r, origin, bb, &ftpmessage);
1505
        rc = proxy_ftp_command(apr_pstrcat(p, "SIZE ",
1516
        rc = proxy_ftp_command(apr_pstrcat(p, "SIZE ",
1506
                           ftp_escape_globbingchars(p, path), CRLF, NULL),
1517
                           ftp_escape_globbingchars(p, path, dconf), CRLF, NULL),
1507
                           r, origin, bb, &ftpmessage);
1518
                           r, origin, bb, &ftpmessage);
1508
        if (rc == -1 || rc == 421) {
1519
        if (rc == -1 || rc == 421) {
1509
            return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,
1520
            return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,
Lines 1522-1528 Link Here
1522
                             "proxy: FTP: SIZE shows this is a directory");
1533
                             "proxy: FTP: SIZE shows this is a directory");
1523
            dirlisting = 1;
1534
            dirlisting = 1;
1524
            rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
1535
            rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
1525
                           ftp_escape_globbingchars(p, path), CRLF, NULL),
1536
                           ftp_escape_globbingchars(p, path, dconf), CRLF, NULL),
1526
                           r, origin, bb, &ftpmessage);
1537
                           r, origin, bb, &ftpmessage);
1527
            /* possible results: 250, 421, 500, 501, 502, 530, 550 */
1538
            /* possible results: 250, 421, 500, 501, 502, 530, 550 */
1528
            /* 250 Requested file action okay, completed. */
1539
            /* 250 Requested file action okay, completed. */
Lines 1583-1589 Link Here
1583
         *     The "." and subsequent digits ("sss") are optional. <..>
1594
         *     The "." and subsequent digits ("sss") are optional. <..>
1584
         *     Time values are always represented in UTC (GMT)
1595
         *     Time values are always represented in UTC (GMT)
1585
         */
1596
         */
1586
        rc = proxy_ftp_command(apr_pstrcat(p, "MDTM ", ftp_escape_globbingchars(p, path), CRLF, NULL),
1597
        rc = proxy_ftp_command(apr_pstrcat(p, "MDTM ", ftp_escape_globbingchars(p, path, dconf), CRLF, NULL),
1587
                               r, origin, bb, &ftpmessage);
1598
                               r, origin, bb, &ftpmessage);
1588
        /* then extract the Last-Modified time from it (YYYYMMDDhhmmss or YYYYMMDDhhmmss.xxx GMT). */
1599
        /* then extract the Last-Modified time from it (YYYYMMDDhhmmss or YYYYMMDDhhmmss.xxx GMT). */
1589
        if (rc == 213) {
1600
        if (rc == 213) {
Lines 1622-1628 Link Here
1622
    }
1633
    }
1623
#endif /* USE_MDTM */
1634
#endif /* USE_MDTM */
1624
/* FIXME: Handle range requests - send REST */
1635
/* FIXME: Handle range requests - send REST */
1625
        buf = apr_pstrcat(p, "RETR ", ftp_escape_globbingchars(p, path), CRLF, NULL);
1636
        buf = apr_pstrcat(p, "RETR ", ftp_escape_globbingchars(p, path, dconf), CRLF, NULL);
1626
    }
1637
    }
1627
    rc = proxy_ftp_command(buf, r, origin, bb, &ftpmessage);
1638
    rc = proxy_ftp_command(buf, r, origin, bb, &ftpmessage);
1628
    /* rc is an intermediate response for the LIST or RETR commands */
1639
    /* rc is an intermediate response for the LIST or RETR commands */
Lines 1659-1665 Link Here
1659
        ftp_set_TYPE('A', r, origin, bb, NULL);
1670
        ftp_set_TYPE('A', r, origin, bb, NULL);
1660
1671
1661
        rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
1672
        rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
1662
                               ftp_escape_globbingchars(p, path), CRLF, NULL),
1673
                               ftp_escape_globbingchars(p, path, dconf), CRLF, NULL),
1663
                               r, origin, bb, &ftpmessage);
1674
                               r, origin, bb, &ftpmessage);
1664
        /* possible results: 250, 421, 500, 501, 502, 530, 550 */
1675
        /* possible results: 250, 421, 500, 501, 502, 530, 550 */
1665
        /* 250 Requested file action okay, completed. */
1676
        /* 250 Requested file action okay, completed. */
Lines 1709-1717 Link Here
1709
1720
1710
    /* set content-type */
1721
    /* set content-type */
1711
    if (dirlisting) {
1722
    if (dirlisting) {
1712
        proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
1713
                                                     &proxy_module);
1714
1715
        ap_set_content_type(r, apr_pstrcat(p, "text/html;charset=",
1723
        ap_set_content_type(r, apr_pstrcat(p, "text/html;charset=",
1716
                                           dconf->ftp_directory_charset ?
1724
                                           dconf->ftp_directory_charset ?
1717
                                           dconf->ftp_directory_charset :
1725
                                           dconf->ftp_directory_charset :

Return to bug 46798