diff -Nru a/channels/chan_iax2.c b/channels/chan_iax2.c --- a/channels/chan_iax2.c 2005-01-15 19:07:33 -07:00 +++ b/channels/chan_iax2.c 2005-01-15 19:07:33 -07:00 @@ -7395,12 +7395,13 @@ int x; struct iax2_user *user; struct iax2_peer *peer; + struct ast_flags config_flags = {(CONFIG_DUPLICATE_CATEGORIES)}; struct ast_netsock *ns; #if 0 static unsigned short int last_port=0; #endif - cfg = ast_load(config_file); + cfg = ast_load_with_flags(config_file, &config_flags); if (!cfg) { ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); diff -Nru a/channels/chan_sip.c b/channels/chan_sip.c --- a/channels/chan_sip.c 2005-01-15 19:07:33 -07:00 +++ b/channels/chan_sip.c 2005-01-15 19:07:33 -07:00 @@ -8983,12 +8983,13 @@ int oldport = ntohs(bindaddr.sin_port); char iabuf[INET_ADDRSTRLEN]; struct ast_flags dummy; + struct ast_flags config_flags = {(CONFIG_DUPLICATE_CATEGORIES)}; if (gethostname(ourhost, sizeof(ourhost))) { ast_log(LOG_WARNING, "Unable to get hostname, SIP disabled\n"); return 0; } - cfg = ast_load(config); + cfg = ast_load_with_flags(config, &config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { diff -Nru a/config.c b/config.c --- a/config.c 2005-01-15 19:07:33 -07:00 +++ b/config.c 2005-01-15 19:07:33 -07:00 @@ -273,13 +273,18 @@ } *c = '\0'; cur++; - *cat = ast_new_category(cur); + *cat = NULL; + if (!ast_test_flag(tmp, CONFIG_DUPLICATE_CATEGORIES)) + *cat = ast_category_get(tmp, cur); if (!*cat) { - ast_destroy(tmp); - ast_log(LOG_WARNING, "Out of memory, line %d of %s\n", lineno, configfile); - return -1; + *cat = ast_new_category(cur); + if (!*cat) { + ast_destroy(tmp); + ast_log(LOG_WARNING, "Out of memory, line %d of %s\n", lineno, configfile); + return -1; + } + ast_category_append(tmp, *cat); } - ast_category_append(tmp, *cat); } else if (cur[0] == '#') { /* A directive */ cur++; @@ -289,43 +294,73 @@ *c = '\0'; c++; /* Find real argument */ - while(*c && (*c < 33)) c++; + while(*c && (*c < 33)) c++; if (!*c) c = NULL; } else c = NULL; - if (!strcasecmp(cur, "include")) { - /* A #include */ - if (c) { - /* Strip off leading and trailing "'s and <>'s */ - while((*c == '<') || (*c == '>') || (*c == '\"')) c++; - /* Get rid of leading mess */ - cur = c; - while (!ast_strlen_zero(cur)) { - c = cur + strlen(cur) - 1; - if ((*c == '>') || (*c == '<') || (*c == '\"')) - *c = '\0'; - else - break; + if (!strcasecmp(cur, "parser")) { + /* A parser control directive */ + if (!c) { + ast_log(LOG_WARNING, "Directive '#parser' needs an argument (option) at line %d of %s\n", lineno, configfile); + return 0; + } + + /* Find the option and any argument */ + cur = c; + while(*c && (*c > 32)) c++; + if (*c) { + *c = '\0'; + c++; + /* Find real argument */ + while(*c && (*c < 33)) c++; + if (!*c) + c = NULL; + } else + c = NULL; + if (!strcasecmp(cur, "duplicate-categories")) { + if (!c) { + ast_log(LOG_WARNING, "Parser option '%s' requires an argument (yes/no) at line %d of %s\n", cur, lineno, configfile); + return 0; } + ast_set2_flag(tmp, ast_true(c), CONFIG_DUPLICATE_CATEGORIES); + } else { + ast_log(LOG_WARNING, "Unknown parser option '%s' at line %d of %s\n", cur, lineno, configfile); + } + } else if (!strcasecmp(cur, "include")) { + /* A #include */ + if (!c) { + ast_log(LOG_WARNING, "Directive '#include' needs an argument (filename) at line %d of %s\n", lineno, configfile); + return 0; + } - if((c = strchr(cur,':'))) { + /* Strip off leading and trailing "'s and <>'s */ + while((*c == '<') || (*c == '>') || (*c == '\"')) c++; + /* Get rid of leading mess */ + cur = c; + while (!ast_strlen_zero(cur)) { + c = cur + strlen(cur) - 1; + if ((*c == '>') || (*c == '<') || (*c == '\"')) *c = '\0'; - c++; - arg = c; + else + break; + } + + if((c = strchr(cur,':'))) { + *c = '\0'; + c++; + arg = c; + } + + if (includelevel < MAX_INCLUDE_LEVEL) { + if(arg && cur) { + ast_log(LOG_WARNING, "Including files with explicit config engine no longer permitted. Please use extconfig.conf to specify all mappings\n"); + } else { + if (!ast_internal_load(cur, tmp, cat, includelevel + 1)) + return -1; } - - if (includelevel < MAX_INCLUDE_LEVEL) { - if(arg && cur) { - ast_log(LOG_WARNING, "Including files with explicit config engine no longer permitted. Please use extconfig.conf to specify all mappings\n"); - } else { - if (!ast_internal_load(cur, tmp, cat, includelevel + 1)) - return -1; - } - } else - ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", includelevel); } else - ast_log(LOG_WARNING, "Directive '#include' needs an argument (filename) at line %d of %s\n", lineno, configfile); + ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", includelevel); } else ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile); @@ -677,6 +712,21 @@ struct ast_category *category = NULL; return ast_internal_load(configfile, NULL, &category, 0); +} + +struct ast_config *ast_load_with_flags(char *configfile, struct ast_flags *flags) +{ + struct ast_category *category = NULL; + struct ast_config *config = NULL; + + config = ast_new_config(); + + if (config) { + ast_copy_flags(config, flags, AST_FLAGS_ALL); + config = ast_internal_load(configfile, config, &category, 0); + } + + return config; } char *ast_category_browse(struct ast_config *config, char *prev) diff -Nru a/configs/extensions.conf.sample b/configs/extensions.conf.sample --- a/configs/extensions.conf.sample 2005-01-15 19:07:33 -07:00 +++ b/configs/extensions.conf.sample 2005-01-15 19:07:33 -07:00 @@ -140,6 +140,12 @@ ; include => dundi-e164-canonical include => dundi-e164-customers + +; By default, contexts can be repeated (added together). +; This works even across include files, and results in a +; combined context with all the defined entries in the +; order they were seen. +[dundi-e164-local] include => dundi-e164-via-pstn [dundi-e164-switch] diff -Nru a/configs/iax.conf.sample b/configs/iax.conf.sample --- a/configs/iax.conf.sample 2005-01-15 19:07:33 -07:00 +++ b/configs/iax.conf.sample 2005-01-15 19:07:33 -07:00 @@ -6,6 +6,14 @@ ; an option address (the default is to bind to all ; local addresses). ; + +; By default, the IAX2 channel module allows duplicate entries (so that you +; can have a peer and a user with the same name). If you wish to disable this +; (because you have only peers, only users, or only 'friends'), so that +; typographical errors won't be silently ignored, you can use: + +; #parser duplicate-categories off + [general] ;bindport=4569 ; bindport and bindaddr may be specified ;bindaddr=192.168.0.1 ; more than once to bind to multiple diff -Nru a/configs/sip.conf.sample b/configs/sip.conf.sample --- a/configs/sip.conf.sample 2005-01-15 19:07:33 -07:00 +++ b/configs/sip.conf.sample 2005-01-15 19:07:33 -07:00 @@ -20,6 +20,13 @@ ; sip debug Show all SIP messages ; +; By default, the SIP channel module allows duplicate entries (so that you +; can have a peer and a user with the same name). If you wish to disable this +; (because you have only peers, only users, or only 'friends'), so that +; typographical errors won't be silently ignored, you can use: + +; #parser duplicate-categories off + [general] context=default ; Default context for incoming calls ;allowguest=no ; Allow or reject guest calls (default is yes, this can also be set to 'osp' diff -Nru a/include/asterisk/config.h b/include/asterisk/config.h --- a/include/asterisk/config.h 2005-01-15 19:07:33 -07:00 +++ b/include/asterisk/config.h 2005-01-15 19:07:33 -07:00 @@ -19,6 +19,9 @@ #endif struct ast_config; +struct ast_flags; + +#define CONFIG_DUPLICATE_CATEGORIES (1 << 0) /* disallow merging of duplicate categories */ struct ast_comment { struct ast_comment *next; @@ -44,6 +47,16 @@ * Returns NULL on error, or an ast_config data structure on success */ struct ast_config *ast_load(char *configfile); + +//! Load a config file, with flags +/*! + * \param configfile path of file to open. If no preceding '/' character, path is considered relative to AST_CONFIG_DIR + * \param flags Flags chosen from the CONFIG_ namespace to affect the load. + * + * Create a config structure from a given configuration file. + * Returns NULL on error, or an ast_config data structure on success + */ +struct ast_config *ast_load_with_flags(char *configfile, struct ast_flags *flags); /*! Removes a config */ /*! diff -Nru a/include/asterisk/config_pvt.h b/include/asterisk/config_pvt.h --- a/include/asterisk/config_pvt.h 2005-01-15 19:07:33 -07:00 +++ b/include/asterisk/config_pvt.h 2005-01-15 19:07:33 -07:00 @@ -19,6 +19,7 @@ }; struct ast_config { + unsigned int flags; struct ast_category *root; struct ast_category *last; };