config: add generic callback wrapper to parse section.<url>.key
Existing configuration parsing functions (e.g. http_options() in http.c) know how to parse two-level configuration variable names. We would like to exploit them and parse something like this: [http] sslVerify = true [http "https://weak.example.com"] sslVerify = false and pretend as if http.sslVerify were set to false when talking to "https://weak.example.com/path". Introduce `urlmatch_config_entry()` wrapper that: - is called with the target URL (e.g. "https://weak.example.com/path"), and the two-level variable parser (e.g. `http_options`); - uses `url_normalize()` and `match_urls()` to see if configuration data matches the target URL; and - calls the traditional two-level configuration variable parser only for the configuration data whose <url> part matches the target URL (and if there are multiple matches, only do so if the current match is a better match than the ones previously seen). Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
67
urlmatch.c
67
urlmatch.c
@ -466,3 +466,70 @@ int match_urls(const struct url_info *url,
|
|||||||
*exactusermatch = usermatched;
|
*exactusermatch = usermatched;
|
||||||
return pathmatchlen;
|
return pathmatchlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int urlmatch_config_entry(const char *var, const char *value, void *cb)
|
||||||
|
{
|
||||||
|
struct string_list_item *item;
|
||||||
|
struct urlmatch_config *collect = cb;
|
||||||
|
struct urlmatch_item *matched;
|
||||||
|
struct url_info *url = &collect->url;
|
||||||
|
const char *key, *dot;
|
||||||
|
struct strbuf synthkey = STRBUF_INIT;
|
||||||
|
size_t matched_len = 0;
|
||||||
|
int user_matched = 0;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
key = skip_prefix(var, collect->section);
|
||||||
|
if (!key || *(key++) != '.') {
|
||||||
|
if (collect->cascade_fn)
|
||||||
|
return collect->cascade_fn(var, value, cb);
|
||||||
|
return 0; /* not interested */
|
||||||
|
}
|
||||||
|
dot = strrchr(key, '.');
|
||||||
|
if (dot) {
|
||||||
|
char *config_url, *norm_url;
|
||||||
|
struct url_info norm_info;
|
||||||
|
|
||||||
|
config_url = xmemdupz(key, dot - key);
|
||||||
|
norm_url = url_normalize(config_url, &norm_info);
|
||||||
|
free(config_url);
|
||||||
|
if (!norm_url)
|
||||||
|
return 0;
|
||||||
|
matched_len = match_urls(url, &norm_info, &user_matched);
|
||||||
|
free(norm_url);
|
||||||
|
if (!matched_len)
|
||||||
|
return 0;
|
||||||
|
key = dot + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collect->key && strcmp(key, collect->key))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
item = string_list_insert(&collect->vars, key);
|
||||||
|
if (!item->util) {
|
||||||
|
matched = xcalloc(1, sizeof(*matched));
|
||||||
|
item->util = matched;
|
||||||
|
} else {
|
||||||
|
matched = item->util;
|
||||||
|
/*
|
||||||
|
* Is our match shorter? Is our match the same
|
||||||
|
* length, and without user while the current
|
||||||
|
* candidate is with user? Then we cannot use it.
|
||||||
|
*/
|
||||||
|
if (matched_len < matched->matched_len ||
|
||||||
|
((matched_len == matched->matched_len) &&
|
||||||
|
(!user_matched && matched->user_matched)))
|
||||||
|
return 0;
|
||||||
|
/* Otherwise, replace it with this one. */
|
||||||
|
}
|
||||||
|
|
||||||
|
matched->matched_len = matched_len;
|
||||||
|
matched->user_matched = user_matched;
|
||||||
|
strbuf_addstr(&synthkey, collect->section);
|
||||||
|
strbuf_addch(&synthkey, '.');
|
||||||
|
strbuf_addstr(&synthkey, key);
|
||||||
|
retval = collect->collect_fn(synthkey.buf, value, collect->cb);
|
||||||
|
|
||||||
|
strbuf_release(&synthkey);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
18
urlmatch.h
18
urlmatch.h
@ -33,4 +33,22 @@ struct url_info {
|
|||||||
extern char *url_normalize(const char *, struct url_info *);
|
extern char *url_normalize(const char *, struct url_info *);
|
||||||
extern int match_urls(const struct url_info *url, const struct url_info *url_prefix, int *exactusermatch);
|
extern int match_urls(const struct url_info *url, const struct url_info *url_prefix, int *exactusermatch);
|
||||||
|
|
||||||
|
struct urlmatch_item {
|
||||||
|
size_t matched_len;
|
||||||
|
char user_matched;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct urlmatch_config {
|
||||||
|
struct string_list vars;
|
||||||
|
struct url_info url;
|
||||||
|
const char *section;
|
||||||
|
const char *key;
|
||||||
|
|
||||||
|
void *cb;
|
||||||
|
int (*collect_fn)(const char *var, const char *value, void *cb);
|
||||||
|
int (*cascade_fn)(const char *var, const char *value, void *cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int urlmatch_config_entry(const char *var, const char *value, void *cb);
|
||||||
|
|
||||||
#endif /* URL_MATCH_H */
|
#endif /* URL_MATCH_H */
|
||||||
|
Reference in New Issue
Block a user