Skip to content

Commit 836b6fb

Browse files
committed
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 <[email protected]>
1 parent 3402a8d commit 836b6fb

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

urlmatch.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,70 @@ int match_urls(const struct url_info *url,
466466
*exactusermatch = usermatched;
467467
return pathmatchlen;
468468
}
469+
470+
int urlmatch_config_entry(const char *var, const char *value, void *cb)
471+
{
472+
struct string_list_item *item;
473+
struct urlmatch_config *collect = cb;
474+
struct urlmatch_item *matched;
475+
struct url_info *url = &collect->url;
476+
const char *key, *dot;
477+
struct strbuf synthkey = STRBUF_INIT;
478+
size_t matched_len = 0;
479+
int user_matched = 0;
480+
int retval;
481+
482+
key = skip_prefix(var, collect->section);
483+
if (!key || *(key++) != '.') {
484+
if (collect->cascade_fn)
485+
return collect->cascade_fn(var, value, cb);
486+
return 0; /* not interested */
487+
}
488+
dot = strrchr(key, '.');
489+
if (dot) {
490+
char *config_url, *norm_url;
491+
struct url_info norm_info;
492+
493+
config_url = xmemdupz(key, dot - key);
494+
norm_url = url_normalize(config_url, &norm_info);
495+
free(config_url);
496+
if (!norm_url)
497+
return 0;
498+
matched_len = match_urls(url, &norm_info, &user_matched);
499+
free(norm_url);
500+
if (!matched_len)
501+
return 0;
502+
key = dot + 1;
503+
}
504+
505+
if (collect->key && strcmp(key, collect->key))
506+
return 0;
507+
508+
item = string_list_insert(&collect->vars, key);
509+
if (!item->util) {
510+
matched = xcalloc(1, sizeof(*matched));
511+
item->util = matched;
512+
} else {
513+
matched = item->util;
514+
/*
515+
* Is our match shorter? Is our match the same
516+
* length, and without user while the current
517+
* candidate is with user? Then we cannot use it.
518+
*/
519+
if (matched_len < matched->matched_len ||
520+
((matched_len == matched->matched_len) &&
521+
(!user_matched && matched->user_matched)))
522+
return 0;
523+
/* Otherwise, replace it with this one. */
524+
}
525+
526+
matched->matched_len = matched_len;
527+
matched->user_matched = user_matched;
528+
strbuf_addstr(&synthkey, collect->section);
529+
strbuf_addch(&synthkey, '.');
530+
strbuf_addstr(&synthkey, key);
531+
retval = collect->collect_fn(synthkey.buf, value, collect->cb);
532+
533+
strbuf_release(&synthkey);
534+
return retval;
535+
}

urlmatch.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,22 @@ struct url_info {
3333
extern char *url_normalize(const char *, struct url_info *);
3434
extern int match_urls(const struct url_info *url, const struct url_info *url_prefix, int *exactusermatch);
3535

36+
struct urlmatch_item {
37+
size_t matched_len;
38+
char user_matched;
39+
};
40+
41+
struct urlmatch_config {
42+
struct string_list vars;
43+
struct url_info url;
44+
const char *section;
45+
const char *key;
46+
47+
void *cb;
48+
int (*collect_fn)(const char *var, const char *value, void *cb);
49+
int (*cascade_fn)(const char *var, const char *value, void *cb);
50+
};
51+
52+
extern int urlmatch_config_entry(const char *var, const char *value, void *cb);
53+
3654
#endif /* URL_MATCH_H */

0 commit comments

Comments
 (0)