1
0
mirror of https://github.com/rkd77/elinks.git synced 2025-02-02 15:09:23 -05:00

Add domain-specific options saving and look-up

Note that this is the infrastructure, but all relevant get_opt_* calls must be changed to pass the session so that the domain-specific options are looked up.

Add @want_domain parameter to parse_set_common and read in the domain-name if the flag is set.

Add parse_set_domain wrapper for parse_set_common.

Add "set_domain" configuration directive with the following syntax: set_domain domain option = value

Modify create_config_string and smart_config_output_fn to spit out domain-specific option trees.

Add @smart_config_output_fn_domain global variable to facilitate this.

Define structure domain_tree and define list @domain_trees.

Add routine get_domain_tree to find or, if necessary, create the shadow tree for the given domain name.

Add routine get_domain_option search for an option in all domain shadow-trees and return the option in the best matching domain tree.

Modify get_opt_ to use get_domain_option to check for domain-specific options.

Add clean-up routine done_domain_trees, called on exit, to free any domain trees.
This commit is contained in:
Miciah Dashiel Butler Masters 2007-08-30 20:29:40 +00:00 committed by Miciah Dashiel Butler Masters
parent 5ada24f3ef
commit 06adbbc524
3 changed files with 184 additions and 5 deletions

View File

@ -88,15 +88,30 @@ skip_white(unsigned char *start, int *line)
static enum parse_error static enum parse_error
parse_set_common(struct option *opt_tree, unsigned char **file, int *line, parse_set_common(struct option *opt_tree, unsigned char **file, int *line,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf, int want_domain)
{ {
unsigned char *orig_pos = *file; unsigned char *orig_pos = *file;
unsigned char *domain_name;
unsigned char *optname; unsigned char *optname;
unsigned char bin; unsigned char bin;
*file = skip_white(*file, line); *file = skip_white(*file, line);
if (!**file) return ERROR_PARSE; if (!**file) return ERROR_PARSE;
if (want_domain) {
domain_name = *file;
while (isident(**file) || **file == '*' || **file == '.' || **file == '+')
(*file)++;
bin = **file;
**file = '\0';
domain_name = stracpy(domain_name);
**file = bin;
if (!domain_name) return ERROR_NOMEM;
*file = skip_white(*file, line);
}
/* Option name */ /* Option name */
optname = *file; optname = *file;
while (isident(**file) || **file == '*' || **file == '.' || **file == '+') while (isident(**file) || **file == '*' || **file == '.' || **file == '+')
@ -124,7 +139,35 @@ parse_set_common(struct option *opt_tree, unsigned char **file, int *line,
struct option *opt; struct option *opt;
unsigned char *val; unsigned char *val;
if (want_domain && *domain_name) {
struct option *domain_tree;
domain_tree = get_domain_tree(domain_name);
if (!domain_tree) {
mem_free(domain_name);
mem_free(optname);
return ERROR_NOMEM;
}
if (mirror) {
opt = get_opt_rec_real(domain_tree, optname);
} else {
opt = get_opt_rec(opt_tree, optname);
if (opt) {
opt = get_option_shadow(opt, opt_tree,
domain_tree);
if (!opt) {
mem_free(domain_name);
mem_free(optname);
return ERROR_NOMEM;
}
}
}
} else {
opt = mirror ? get_opt_rec_real(opt_tree, optname) : get_opt_rec(opt_tree, optname); opt = mirror ? get_opt_rec_real(opt_tree, optname) : get_opt_rec(opt_tree, optname);
}
if (want_domain)
mem_free(domain_name);
mem_free(optname); mem_free(optname);
if (!opt || (opt->flags & OPT_HIDDEN)) if (!opt || (opt->flags & OPT_HIDDEN))
@ -158,11 +201,18 @@ parse_set_common(struct option *opt_tree, unsigned char **file, int *line,
return ERROR_NONE; return ERROR_NONE;
} }
static enum parse_error
parse_set_domain(struct option *opt_tree, unsigned char **file, int *line,
struct string *mirror, int is_system_conf)
{
return parse_set_common(opt_tree, file, line, mirror, is_system_conf, 1);
}
static enum parse_error static enum parse_error
parse_set(struct option *opt_tree, unsigned char **file, int *line, parse_set(struct option *opt_tree, unsigned char **file, int *line,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf)
{ {
return parse_set_common(opt_tree, file, line, mirror, is_system_conf); return parse_set_common(opt_tree, file, line, mirror, is_system_conf, 0);
} }
@ -344,6 +394,7 @@ struct parse_handler {
}; };
static struct parse_handler parse_handlers[] = { static struct parse_handler parse_handlers[] = {
{ "set_domain", parse_set_domain },
{ "set", parse_set }, { "set", parse_set },
{ "unset", parse_unset }, { "unset", parse_unset },
{ "bind", parse_bind }, { "bind", parse_bind },
@ -570,6 +621,8 @@ add_indent_to_string(struct string *string, int depth)
add_xchar_to_string(string, ' ', depth * indentation); add_xchar_to_string(string, ' ', depth * indentation);
} }
static unsigned char *smart_config_output_fn_domain;
static void static void
smart_config_output_fn(struct string *string, struct option *option, smart_config_output_fn(struct string *string, struct option *option,
unsigned char *path, int depth, int do_print_comment, unsigned char *path, int depth, int do_print_comment,
@ -652,7 +705,13 @@ split:
if (option->flags & OPT_DELETED) { if (option->flags & OPT_DELETED) {
add_to_string(string, "un"); add_to_string(string, "un");
} }
if (smart_config_output_fn_domain) {
add_to_string(string, "set_domain ");
add_to_string(string, smart_config_output_fn_domain);
add_char_to_string(string, ' ');
} else {
add_to_string(string, "set "); add_to_string(string, "set ");
}
if (path) { if (path) {
add_to_string(string, path); add_to_string(string, path);
add_char_to_string(string, '.'); add_char_to_string(string, '.');
@ -774,6 +833,22 @@ create_config_string(unsigned char *prefix, unsigned char *name)
origlen = tmpstring.length; origlen = tmpstring.length;
smart_config_string(&tmpstring, 2, i18n, options->value.tree, NULL, 0, smart_config_string(&tmpstring, 2, i18n, options->value.tree, NULL, 0,
smart_config_output_fn); smart_config_output_fn);
{
struct domain_tree *domain;
foreach (domain, domain_trees) {
smart_config_output_fn_domain = domain->name;
smart_config_string(&tmpstring, 2, i18n,
domain->tree->value.tree,
NULL, 0,
smart_config_output_fn);
unmark_options_tree(domain->tree->value.tree);
}
smart_config_output_fn_domain = NULL;
}
if (tmpstring.length > origlen) if (tmpstring.length > origlen)
add_string_to_string(&config, &tmpstring); add_string_to_string(&config, &tmpstring);
done_string(&tmpstring); done_string(&tmpstring);

View File

@ -23,6 +23,8 @@
#include "main/main.h" /* shrink_memory() */ #include "main/main.h" /* shrink_memory() */
#include "main/select.h" #include "main/select.h"
#include "network/connection.h" #include "network/connection.h"
#include "protocol/uri.h"
#include "session/location.h"
#include "session/session.h" #include "session/session.h"
#include "terminal/color.h" #include "terminal/color.h"
#include "terminal/screen.h" #include "terminal/screen.h"
@ -32,6 +34,7 @@
#include "util/memory.h" #include "util/memory.h"
#include "util/string.h" #include "util/string.h"
#include "viewer/text/draw.h" #include "viewer/text/draw.h"
#include "viewer/text/vs.h"
/* TODO? In the past, covered by shadow and legends, remembered only by the /* TODO? In the past, covered by shadow and legends, remembered only by the
@ -241,6 +244,8 @@ get_opt_rec_real(struct option *tree, const unsigned char *name)
return opt; return opt;
} }
static struct option *get_domain_option(unsigned char *, int, unsigned char *);
/* Fetch pointer to value of certain option. It is guaranteed to never return /* Fetch pointer to value of certain option. It is guaranteed to never return
* NULL. Note that you are supposed to use wrapper get_opt(). */ * NULL. Note that you are supposed to use wrapper get_opt(). */
union option_value * union option_value *
@ -257,7 +262,14 @@ get_opt_(
if (ses && ses->option) if (ses && ses->option)
opt = get_opt_rec_real(ses->option, name); opt = get_opt_rec_real(ses->option, name);
/* TODO: Look for a domain-specific option. */ /* If given a session, the session has a location, and we can find
* an options tree for the location's domain, return the shadow. */
if (ses && have_location(ses)) {
struct uri *uri = cur_loc(ses)->vs.uri;
if (uri->host && uri->hostlen)
opt = get_domain_option(uri->host, uri->hostlen, name);
}
/* Else, return the real option. */ /* Else, return the real option. */
if (!opt) if (!opt)
@ -698,6 +710,82 @@ get_option_shadow(struct option *option, struct option *tree,
return shadow_option; return shadow_option;
} }
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(unsigned char *domain_name, int domain_len,
unsigned 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;
}
/* 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(unsigned 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 = 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);
}
}
LIST_OF(struct option) * LIST_OF(struct option) *
init_options_tree(void) init_options_tree(void)
{ {
@ -765,6 +853,7 @@ free_options_tree(LIST_OF(struct option) *tree, int recursive)
void void
done_options(void) done_options(void)
{ {
done_domain_trees();
unregister_options(config_options_info, config_options); unregister_options(config_options_info, config_options);
unregister_options(cmdline_options_info, cmdline_options); unregister_options(cmdline_options_info, cmdline_options);
config_options->box_item = NULL; config_options->box_item = NULL;

View File

@ -178,8 +178,23 @@ enum copy_option_flags {
}; };
extern struct option *copy_option(struct option *, int); extern struct option *copy_option(struct option *, int);
struct option *get_option_shadow(struct option *, struct option *, struct option *get_option_shadow(struct option *, struct option *,
struct option *); struct option *);
struct domain_tree {
LIST_HEAD(struct domain_tree);
struct option *tree;
int len;
unsigned char name[1]; /* Must be at end of struct. */
};
extern LIST_OF(struct domain_tree) domain_trees;
struct option *get_domain_tree(unsigned char *);
extern void delete_option(struct option *); extern void delete_option(struct option *);
void mark_option_as_deleted(struct option *); void mark_option_as_deleted(struct option *);