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:
parent
5ada24f3ef
commit
06adbbc524
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 *);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user