/* Domain-specific options infrastructure */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "elinks.h" #include "config/domain.h" #include "config/options.h" #include "protocol/uri.h" #include "session/location.h" #include "session/session.h" #include "util/lists.h" #include "viewer/text/vs.h" INIT_LIST_OF(struct domain_tree, domain_trees); /* Look for the option with the given name in all domain shadow-trees that * match the given domain-name. Return the option from the the shadow tree * that best matches the given domain name. */ static struct option * get_domain_option(char *domain_name, int domain_len, const char *name) { struct option *opt, *longest_match_opt = NULL; struct domain_tree *longest_match = NULL; struct domain_tree *domain; assert(domain_name); assert(*domain_name); foreach (domain, domain_trees) if ((!longest_match || domain->len > longest_match->len) && is_in_domain(domain->name, domain_name, domain_len) && (opt = get_opt_rec_real(domain->tree, name))) { longest_match = domain; longest_match_opt = opt; } return longest_match_opt; } struct option * get_domain_option_from_session(const char *name, struct session *ses) { struct uri *uri; assert(ses); assert(name); if (!have_location(ses)) return NULL; uri = cur_loc(ses)->vs.uri; if (!uri->host || !uri->hostlen) return NULL; return get_domain_option(uri->host, uri->hostlen, name); } /* Return the shadow shadow tree for the given domain name, and * if the domain does not yet have a shadow tree, create it. */ struct option * get_domain_tree(char *domain_name) { struct domain_tree *domain; int domain_len; assert(domain_name); assert(*domain_name); foreach (domain, domain_trees) if (!strcasecmp(domain->name, domain_name)) return domain->tree; domain_len = strlen(domain_name); /* One byte is reserved for domain in struct domain_tree. */ domain = (struct domain_tree *)mem_alloc(sizeof(*domain) + domain_len); if (!domain) return NULL; domain->tree = copy_option(config_options, CO_SHALLOW | CO_NO_LISTBOX_ITEM); if (!domain->tree) { mem_free(domain); return NULL; } memcpy(domain->name, domain_name, domain_len + 1); domain->len = domain_len; add_to_list(domain_trees, domain); return domain->tree; } void done_domain_trees(void) { struct domain_tree *domain, *next; foreachsafe (domain, next, domain_trees) { delete_option(domain->tree); domain->tree = NULL; del_from_list(domain); mem_free(domain); } }