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

(-)httpd-2.4.33/modules/mappers/mod_alias.c (-31 / +79 lines)
Lines 46-65 Link Here
46
} alias_entry;
46
} alias_entry;
47
47
48
typedef struct {
48
typedef struct {
49
    apr_array_header_t *aliases;
49
    apr_array_header_t *aliases;
50
    apr_array_header_t *redirects;
50
    apr_array_header_t *redirects;
51
} alias_server_conf;
51
} alias_server_conf;
52
52
53
typedef struct {
53
typedef struct {
54
    unsigned int alias_set:1;
54
    unsigned int alias_set:1;
55
    unsigned int redirect_set:1;
55
    unsigned int redirect_set:1;
56
    apr_array_header_t *aliases;
56
    apr_array_header_t *redirects;
57
    apr_array_header_t *redirects;
57
    const ap_expr_info_t *alias;
58
    const ap_expr_info_t *alias;
58
    char *handler;
59
    char *handler;
59
    const ap_expr_info_t *redirect;
60
    const ap_expr_info_t *redirect;
60
    int redirect_status;                /* 301, 302, 303, 410, etc */
61
    int redirect_status;                /* 301, 302, 303, 410, etc */
61
} alias_dir_conf;
62
} alias_dir_conf;
62
63
63
module AP_MODULE_DECLARE_DATA alias_module;
64
module AP_MODULE_DECLARE_DATA alias_module;
64
65
65
static char magic_error_value;
66
static char magic_error_value;
Lines 72-91 Link Here
72
73
73
    a->aliases = apr_array_make(p, 20, sizeof(alias_entry));
74
    a->aliases = apr_array_make(p, 20, sizeof(alias_entry));
74
    a->redirects = apr_array_make(p, 20, sizeof(alias_entry));
75
    a->redirects = apr_array_make(p, 20, sizeof(alias_entry));
75
    return a;
76
    return a;
76
}
77
}
77
78
78
static void *create_alias_dir_config(apr_pool_t *p, char *d)
79
static void *create_alias_dir_config(apr_pool_t *p, char *d)
79
{
80
{
80
    alias_dir_conf *a =
81
    alias_dir_conf *a =
81
    (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
82
    (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
83
    a->aliases = apr_array_make(p, 2, sizeof(alias_entry));
82
    a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
84
    a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
83
    return a;
85
    return a;
84
}
86
}
85
87
86
static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv)
88
static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv)
87
{
89
{
88
    alias_server_conf *a =
90
    alias_server_conf *a =
89
    (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
91
    (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
90
    alias_server_conf *base = (alias_server_conf *) basev;
92
    alias_server_conf *base = (alias_server_conf *) basev;
91
    alias_server_conf *overrides = (alias_server_conf *) overridesv;
93
    alias_server_conf *overrides = (alias_server_conf *) overridesv;
Lines 95-203 Link Here
95
    return a;
97
    return a;
96
}
98
}
97
99
98
static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv)
100
static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv)
99
{
101
{
100
    alias_dir_conf *a =
102
    alias_dir_conf *a =
101
    (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
103
    (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
102
    alias_dir_conf *base = (alias_dir_conf *) basev;
104
    alias_dir_conf *base = (alias_dir_conf *) basev;
103
    alias_dir_conf *overrides = (alias_dir_conf *) overridesv;
105
    alias_dir_conf *overrides = (alias_dir_conf *) overridesv;
104
106
107
    a->aliases = apr_array_append(p, overrides->aliases, base->aliases);
105
    a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
108
    a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
106
109
107
    a->alias = (overrides->alias_set == 0) ? base->alias : overrides->alias;
110
    a->alias = (overrides->alias_set == 0) ? base->alias : overrides->alias;
108
    a->handler = (overrides->alias_set == 0) ? base->handler : overrides->handler;
111
    a->handler = (overrides->alias_set == 0) ? base->handler : overrides->handler;
109
    a->alias_set = overrides->alias_set || base->alias_set;
112
    a->alias_set = overrides->alias_set || base->alias_set;
110
113
111
    a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect;
114
    a->redirect = (overrides->redirect_set == 0) ? base->redirect : overrides->redirect;
112
    a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status;
115
    a->redirect_status = (overrides->redirect_set == 0) ? base->redirect_status : overrides->redirect_status;
113
    a->redirect_set = overrides->redirect_set || base->redirect_set;
116
    a->redirect_set = overrides->redirect_set || base->redirect_set;
114
117
115
    return a;
118
    return a;
116
}
119
}
117
120
118
/* need prototype for overlap check */
121
/* need prototype for overlap check */
119
static int alias_matches(const char *uri, const char *alias_fakename);
122
static int alias_matches(const char *uri, const char *alias_fakename);
120
123
121
static const char *add_alias_internal(cmd_parms *cmd, void *dummy,
124
static const char *add_alias_internal(cmd_parms *cmd, alias_dir_conf *dirconf,
122
                                      const char *fake, const char *real,
125
                                      const char *fake, const char *real,
123
                                      int use_regex)
126
                                      int use_regex)
124
{
127
{
128
    alias_entry *new;
125
    server_rec *s = cmd->server;
129
    server_rec *s = cmd->server;
126
    alias_server_conf *conf = ap_get_module_config(s->module_config,
130
    alias_server_conf *serverconf = ap_get_module_config(s->module_config,
127
                                                   &alias_module);
131
                                                         &alias_module);
128
    alias_entry *new = apr_array_push(conf->aliases);
129
    alias_entry *entries = (alias_entry *)conf->aliases->elts;
130
    int i;
131
132
132
    /* XXX: real can NOT be relative to DocumentRoot here... compat bug. */
133
    /* XXX: real can NOT be relative to DocumentRoot here... compat bug. */
133
134
134
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT);
135
    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT);
135
136
136
    if (err != NULL) {
137
    if (err != NULL) {
137
        return err;
138
        return err;
138
    }
139
    }
139
140
140
    if (use_regex) {
141
        new->regexp = ap_pregcomp(cmd->pool, fake, AP_REG_EXTENDED);
142
        if (new->regexp == NULL)
143
            return "Regular expression could not be compiled.";
144
        new->real = real;
145
    }
146
    else {
147
        /* XXX This may be optimized, but we must know that new->real
148
         * exists.  If so, we can dir merge later, trusing new->real
149
         * and just canonicalizing the remainder.  Not till I finish
150
         * cleaning out the old ap_canonical stuff first.
151
         */
152
        new->real = real;
153
    }
154
    new->fake = fake;
155
    new->handler = cmd->info;
156
157
    /* check for overlapping (Script)Alias directives
141
    /* check for overlapping (Script)Alias directives
158
     * and throw a warning if found one
142
     * and throw a warning if found one
159
     */
143
     */
160
    if (!use_regex) {
144
    if (!use_regex) {
161
        for (i = 0; i < conf->aliases->nelts - 1; ++i) {
145
        int num_server_elts = serverconf->aliases->nelts;
162
            alias_entry *alias = &entries[i];
146
        int num_dir_elts = dirconf->aliases->nelts;
147
        int total_elts = num_server_elts + num_dir_elts;
148
        int i;
149
150
        for (i = 0; i < total_elts; ++i) {
151
            alias_entry *alias;
152
            if (i < num_server_elts) {
153
                alias = &serverconf->aliases->elts[i];
154
            }
155
            else {
156
                alias = &dirconf->aliases->elts[i - num_server_elts];
157
            }
163
158
164
            if (  (!alias->regexp &&  alias_matches(fake, alias->fake) > 0)
159
            if (  (!alias->regexp &&  alias_matches(fake, alias->fake) > 0)
165
                || (alias->regexp && !ap_regexec(alias->regexp, fake, 0, NULL, 0))) {
160
                || (alias->regexp && !ap_regexec(alias->regexp, fake, 0, NULL, 0))) {
166
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00671)
161
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00671)
167
                             "The %s directive in %s at line %d will probably "
162
                             "The %s directive in %s at line %d will probably "
168
                             "never match because it overlaps an earlier "
163
                             "never match because it overlaps an earlier "
169
                             "%sAlias%s.",
164
                             "%sAlias%s.",
170
                             cmd->cmd->name, cmd->directive->filename,
165
                             cmd->cmd->name, cmd->directive->filename,
171
                             cmd->directive->line_num,
166
                             cmd->directive->line_num,
172
                             alias->handler ? "Script" : "",
167
                             alias->handler ? "Script" : "",
173
                             alias->regexp ? "Match" : "");
168
                             alias->regexp ? "Match" : "");
174
169
175
                break; /* one warning per alias should be sufficient */
170
                break; /* one warning per alias should be sufficient */
176
            }
171
            }
177
        }
172
        }
178
    }
173
    }
179
174
175
    /* Add a new entry for the alias in either the server or per-directory
176
     * (including e.g. <If> section) configuration, as appropriate.
177
     */
178
    if (cmd->path) {
179
        new = apr_array_push(dirconf->aliases);
180
    }
181
    else {
182
        new = apr_array_push(serverconf->aliases);
183
    }
184
185
    if (use_regex) {
186
        new->regexp = ap_pregcomp(cmd->pool, fake, AP_REG_EXTENDED);
187
        if (new->regexp == NULL)
188
            return "Regular expression could not be compiled.";
189
        new->real = real;
190
    }
191
    else {
192
        /* XXX This may be optimized, but we must know that new->real
193
         * exists.  If so, we can dir merge later, trusing new->real
194
         * and just canonicalizing the remainder.  Not till I finish
195
         * cleaning out the old ap_canonical stuff first.
196
         */
197
        new->real = real;
198
    }
199
    new->fake = fake;
200
    new->handler = cmd->info;
201
180
    return NULL;
202
    return NULL;
181
}
203
}
182
204
183
static const char *add_alias(cmd_parms *cmd, void *dummy, const char *fake,
205
static const char *add_alias(cmd_parms *cmd, void *dirconfv, const char *fake,
184
        const char *real)
206
        const char *real)
185
{
207
{
208
    alias_dir_conf *dirconf = (alias_dir_conf *) dirconfv;
186
    if (real) {
209
    if (real) {
187
210
188
        return add_alias_internal(cmd, dummy, fake, real, 0);
211
        return add_alias_internal(cmd, dirconf, fake, real, 0);
189
212
190
    }
213
    }
191
    else {
214
    else {
192
        alias_dir_conf *dirconf = (alias_dir_conf *) dummy;
193
194
        const char *err = ap_check_cmd_context(cmd, NOT_IN_DIRECTORY|NOT_IN_FILES);
215
        const char *err = ap_check_cmd_context(cmd, NOT_IN_DIRECTORY|NOT_IN_FILES);
195
216
196
        if (err != NULL) {
217
        if (err != NULL) {
197
            return err;
218
            return err;
198
        }
219
        }
199
220
200
        if (!cmd->path) {
221
        if (!cmd->path) {
201
            return "Alias must have two arguments when used globally";
222
            return "Alias must have two arguments when used globally";
202
        }
223
        }
203
224
Lines 211-234 Link Here
211
        }
232
        }
212
233
213
        dirconf->handler = cmd->info;
234
        dirconf->handler = cmd->info;
214
        dirconf->alias_set = 1;
235
        dirconf->alias_set = 1;
215
236
216
        return NULL;
237
        return NULL;
217
238
218
    }
239
    }
219
}
240
}
220
241
221
static const char *add_alias_regex(cmd_parms *cmd, void *dummy,
242
static const char *add_alias_regex(cmd_parms *cmd, void *dirconfv,
222
                                   const char *fake, const char *real)
243
                                   const char *fake, const char *real)
223
{
244
{
224
    return add_alias_internal(cmd, dummy, fake, real, 1);
245
    return add_alias_internal(cmd, (alias_dir_conf *) dirconfv, fake, real, 1);
225
}
246
}
226
247
227
static const char *add_redirect_internal(cmd_parms *cmd,
248
static const char *add_redirect_internal(cmd_parms *cmd,
228
                                         alias_dir_conf *dirconf,
249
                                         alias_dir_conf *dirconf,
229
                                         const char *arg1, const char *arg2,
250
                                         const char *arg1, const char *arg2,
230
                                         const char *arg3, int use_regex)
251
                                         const char *arg3, int use_regex)
231
{
252
{
232
    alias_entry *new;
253
    alias_entry *new;
233
    server_rec *s = cmd->server;
254
    server_rec *s = cmd->server;
234
    alias_server_conf *serverconf = ap_get_module_config(s->module_config,
255
    alias_server_conf *serverconf = ap_get_module_config(s->module_config,
Lines 598-626 Link Here
598
619
599
    }
620
    }
600
621
601
    return NULL;
622
    return NULL;
602
}
623
}
603
624
604
static int translate_alias_redir(request_rec *r)
625
static int translate_alias_redir(request_rec *r)
605
{
626
{
606
    ap_conf_vector_t *sconf = r->server->module_config;
627
    ap_conf_vector_t *sconf = r->server->module_config;
607
    alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module);
628
    alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module);
629
    void *dconf = r->per_dir_config;
630
    alias_dir_conf *dirconf =
631
        (alias_dir_conf *) ap_get_module_config(dconf, &alias_module);
608
    char *ret;
632
    char *ret;
609
    int status;
633
    int status;
610
634
611
    if (r->uri[0] != '/' && r->uri[0] != '\0') {
635
    if (r->uri[0] != '/' && r->uri[0] != '\0') {
612
        return DECLINED;
636
        return DECLINED;
613
    }
637
    }
614
638
639
    /* Look for matching redirections in the following order:
640
     * - The whole-<Location> redirect in the <Location> that is relevant to
641
     *   this request, if there is one.
642
     * - An unconditional server / vhost redirect.
643
     * - A per-directory redirect at the top-level for the server / vhost,
644
     *   which may have come from a conditional <If> section -- we only expect
645
     *   that much to have been merged into r->per_dir_config at this point,
646
     *   since we are still translating URLs and mapping them to the file
647
     *   system.
648
     */
615
    if ((ret = try_redirect(r, &status)) != NULL
649
    if ((ret = try_redirect(r, &status)) != NULL
616
            || (ret = try_alias_list(r, serverconf->redirects, 1, &status))
650
            || (ret = try_alias_list(r, serverconf->redirects, 1, &status))
651
                    != NULL
652
            || (ret = try_alias_list(r, dirconf->redirects, 1, &status))
617
                    != NULL) {
653
                    != NULL) {
618
        if (ret == PREGSUB_ERROR)
654
        if (ret == PREGSUB_ERROR)
619
            return HTTP_INTERNAL_SERVER_ERROR;
655
            return HTTP_INTERNAL_SERVER_ERROR;
620
        if (ap_is_HTTP_REDIRECT(status)) {
656
        if (ap_is_HTTP_REDIRECT(status)) {
621
            if (ret[0] == '/') {
657
            if (ret[0] == '/') {
622
                char *orig_target = ret;
658
                char *orig_target = ret;
623
659
624
                ret = ap_construct_url(r->pool, ret, r);
660
                ret = ap_construct_url(r->pool, ret, r);
625
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673)
661
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00673)
626
                              "incomplete redirection target of '%s' for "
662
                              "incomplete redirection target of '%s' for "
Lines 640-661 Link Here
640
                 */
676
                 */
641
                if (r->args && !ap_strchr(ret, '?')) {
677
                if (r->args && !ap_strchr(ret, '?')) {
642
                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
678
                    ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
643
                }
679
                }
644
                apr_table_setn(r->headers_out, "Location", ret);
680
                apr_table_setn(r->headers_out, "Location", ret);
645
            }
681
            }
646
        }
682
        }
647
        return status;
683
        return status;
648
    }
684
    }
649
685
686
    /* Look for matching aliases in the following order:
687
     * - The whole-<Location> alias in the <Location> that is relevant to this
688
     *   request, if there is one.
689
     * - An unconditional server / vhost alias.
690
     * - A per-directory alias at the top-level for the server / vhost,
691
     *   which may have come from a conditional <If> section -- we only expect
692
     *   that much to have been merged into r->per_dir_config since at this
693
     *   point we are translating URLs, before mapping to the file system can
694
     *   occur.
695
     */
650
    if ((ret = try_alias(r)) != NULL
696
    if ((ret = try_alias(r)) != NULL
651
            || (ret = try_alias_list(r, serverconf->aliases, 0, &status))
697
            || (ret = try_alias_list(r, serverconf->aliases, 0, &status))
698
                    != NULL
699
            || (ret = try_alias_list(r, dirconf->aliases, 0, &status))
652
                    != NULL) {
700
                    != NULL) {
653
        r->filename = ret;
701
        r->filename = ret;
654
        return OK;
702
        return OK;
655
    }
703
    }
656
704
657
    return DECLINED;
705
    return DECLINED;
658
}
706
}
659
707
660
static int fixup_redir(request_rec *r)
708
static int fixup_redir(request_rec *r)
661
{
709
{

Return to bug 57337