diff --git a/urlmatch.c b/urlmatch.c index 4f38cc7bc6..1db76c89bc 100644 --- a/urlmatch.c +++ b/urlmatch.c @@ -466,3 +466,70 @@ int match_urls(const struct url_info *url, *exactusermatch = usermatched; 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; +} diff --git a/urlmatch.h b/urlmatch.h index b67f57f86f..b461dfd3df 100644 --- a/urlmatch.h +++ b/urlmatch.h @@ -33,4 +33,22 @@ 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); +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 */