1251881Speter/* 2251881Speter * config.c : reading configuration information 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter#define APR_WANT_STRFUNC 27251881Speter#define APR_WANT_MEMFUNC 28251881Speter#include <apr_want.h> 29251881Speter 30251881Speter#include <apr_general.h> 31251881Speter#include <apr_lib.h> 32251881Speter#include "svn_hash.h" 33251881Speter#include "svn_error.h" 34251881Speter#include "svn_pools.h" 35251881Speter#include "config_impl.h" 36251881Speter 37251881Speter#include "svn_private_config.h" 38251881Speter#include "private/svn_dep_compat.h" 39251881Speter 40251881Speter 41251881Speter 42251881Speter 43251881Speter/* Section table entries. */ 44251881Spetertypedef struct cfg_section_t cfg_section_t; 45251881Speterstruct cfg_section_t 46251881Speter{ 47251881Speter /* The section name. */ 48251881Speter const char *name; 49251881Speter 50251881Speter /* Table of cfg_option_t's. */ 51251881Speter apr_hash_t *options; 52251881Speter}; 53251881Speter 54251881Speter 55251881Speter/* Option table entries. */ 56251881Spetertypedef struct cfg_option_t cfg_option_t; 57251881Speterstruct cfg_option_t 58251881Speter{ 59251881Speter /* The option name. */ 60251881Speter const char *name; 61251881Speter 62251881Speter /* The option name, converted into a hash key. */ 63251881Speter const char *hash_key; 64251881Speter 65251881Speter /* The unexpanded option value. */ 66251881Speter const char *value; 67251881Speter 68251881Speter /* The expanded option value. */ 69251881Speter const char *x_value; 70251881Speter 71251881Speter /* Expansion flag. If this is TRUE, this value has already been expanded. 72251881Speter In this case, if x_value is NULL, no expansions were necessary, 73251881Speter and value should be used directly. */ 74251881Speter svn_boolean_t expanded; 75251881Speter}; 76251881Speter 77251881Speter 78251881Speter 79251881Spetersvn_error_t * 80251881Spetersvn_config_create2(svn_config_t **cfgp, 81251881Speter svn_boolean_t section_names_case_sensitive, 82251881Speter svn_boolean_t option_names_case_sensitive, 83251881Speter apr_pool_t *result_pool) 84251881Speter{ 85251881Speter svn_config_t *cfg = apr_palloc(result_pool, sizeof(*cfg)); 86251881Speter 87251881Speter cfg->sections = apr_hash_make(result_pool); 88251881Speter cfg->pool = result_pool; 89251881Speter cfg->x_pool = svn_pool_create(result_pool); 90251881Speter cfg->x_values = FALSE; 91251881Speter cfg->tmp_key = svn_stringbuf_create_empty(result_pool); 92251881Speter cfg->tmp_value = svn_stringbuf_create_empty(result_pool); 93251881Speter cfg->section_names_case_sensitive = section_names_case_sensitive; 94251881Speter cfg->option_names_case_sensitive = option_names_case_sensitive; 95251881Speter 96251881Speter *cfgp = cfg; 97251881Speter return SVN_NO_ERROR; 98251881Speter} 99251881Speter 100251881Spetersvn_error_t * 101251881Spetersvn_config_read3(svn_config_t **cfgp, const char *file, 102251881Speter svn_boolean_t must_exist, 103251881Speter svn_boolean_t section_names_case_sensitive, 104251881Speter svn_boolean_t option_names_case_sensitive, 105251881Speter apr_pool_t *result_pool) 106251881Speter{ 107251881Speter svn_config_t *cfg; 108251881Speter svn_error_t *err; 109251881Speter 110251881Speter SVN_ERR(svn_config_create2(&cfg, 111251881Speter section_names_case_sensitive, 112251881Speter option_names_case_sensitive, 113251881Speter result_pool)); 114251881Speter 115251881Speter /* Yes, this is platform-specific code in Subversion, but there's no 116251881Speter practical way to migrate it into APR, as it's simultaneously 117251881Speter Subversion-specific and Windows-specific. Even if we eventually 118251881Speter want to have APR offer a generic config-reading interface, it 119251881Speter makes sense to test it here first and migrate it later. */ 120251881Speter#ifdef WIN32 121251881Speter if (0 == strncmp(file, SVN_REGISTRY_PREFIX, SVN_REGISTRY_PREFIX_LEN)) 122251881Speter err = svn_config__parse_registry(cfg, file + SVN_REGISTRY_PREFIX_LEN, 123251881Speter must_exist, result_pool); 124251881Speter else 125251881Speter#endif /* WIN32 */ 126251881Speter err = svn_config__parse_file(cfg, file, must_exist, result_pool); 127251881Speter 128251881Speter if (err != SVN_NO_ERROR) 129251881Speter return err; 130251881Speter else 131251881Speter *cfgp = cfg; 132251881Speter 133251881Speter return SVN_NO_ERROR; 134251881Speter} 135251881Speter 136251881Spetersvn_error_t * 137251881Spetersvn_config_parse(svn_config_t **cfgp, svn_stream_t *stream, 138251881Speter svn_boolean_t section_names_case_sensitive, 139251881Speter svn_boolean_t option_names_case_sensitive, 140251881Speter apr_pool_t *result_pool) 141251881Speter{ 142251881Speter svn_config_t *cfg; 143251881Speter svn_error_t *err; 144251881Speter apr_pool_t *scratch_pool = svn_pool_create(result_pool); 145251881Speter 146251881Speter err = svn_config_create2(&cfg, 147251881Speter section_names_case_sensitive, 148251881Speter option_names_case_sensitive, 149251881Speter result_pool); 150251881Speter 151251881Speter if (err == SVN_NO_ERROR) 152251881Speter err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool); 153251881Speter 154251881Speter if (err == SVN_NO_ERROR) 155251881Speter *cfgp = cfg; 156251881Speter 157251881Speter svn_pool_destroy(scratch_pool); 158251881Speter 159251881Speter return err; 160251881Speter} 161251881Speter 162251881Speter/* Read various configuration sources into *CFGP, in this order, with 163251881Speter * later reads overriding the results of earlier ones: 164251881Speter * 165251881Speter * 1. SYS_REGISTRY_PATH (only on Win32, but ignored if NULL) 166251881Speter * 167251881Speter * 2. SYS_FILE_PATH (everywhere, but ignored if NULL) 168251881Speter * 169251881Speter * 3. USR_REGISTRY_PATH (only on Win32, but ignored if NULL) 170251881Speter * 171251881Speter * 4. USR_FILE_PATH (everywhere, but ignored if NULL) 172251881Speter * 173251881Speter * Allocate *CFGP in POOL. Even if no configurations are read, 174251881Speter * allocate an empty *CFGP. 175251881Speter */ 176251881Speterstatic svn_error_t * 177251881Speterread_all(svn_config_t **cfgp, 178251881Speter const char *sys_registry_path, 179251881Speter const char *usr_registry_path, 180251881Speter const char *sys_file_path, 181251881Speter const char *usr_file_path, 182251881Speter apr_pool_t *pool) 183251881Speter{ 184251881Speter svn_boolean_t red_config = FALSE; /* "red" is the past tense of "read" */ 185251881Speter 186251881Speter /*** Read system-wide configurations first... ***/ 187251881Speter 188251881Speter#ifdef WIN32 189251881Speter if (sys_registry_path) 190251881Speter { 191251881Speter SVN_ERR(svn_config_read2(cfgp, sys_registry_path, FALSE, FALSE, pool)); 192251881Speter red_config = TRUE; 193251881Speter } 194251881Speter#endif /* WIN32 */ 195251881Speter 196251881Speter if (sys_file_path) 197251881Speter { 198251881Speter if (red_config) 199251881Speter SVN_ERR(svn_config_merge(*cfgp, sys_file_path, FALSE)); 200251881Speter else 201251881Speter { 202251881Speter SVN_ERR(svn_config_read3(cfgp, sys_file_path, 203251881Speter FALSE, FALSE, FALSE, pool)); 204251881Speter red_config = TRUE; 205251881Speter } 206251881Speter } 207251881Speter 208251881Speter /*** ...followed by per-user configurations. ***/ 209251881Speter 210251881Speter#ifdef WIN32 211251881Speter if (usr_registry_path) 212251881Speter { 213251881Speter if (red_config) 214251881Speter SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE)); 215251881Speter else 216251881Speter { 217251881Speter SVN_ERR(svn_config_read2(cfgp, usr_registry_path, 218251881Speter FALSE, FALSE, pool)); 219251881Speter red_config = TRUE; 220251881Speter } 221251881Speter } 222251881Speter#endif /* WIN32 */ 223251881Speter 224251881Speter if (usr_file_path) 225251881Speter { 226251881Speter if (red_config) 227251881Speter SVN_ERR(svn_config_merge(*cfgp, usr_file_path, FALSE)); 228251881Speter else 229251881Speter { 230251881Speter SVN_ERR(svn_config_read3(cfgp, usr_file_path, 231251881Speter FALSE, FALSE, FALSE, pool)); 232251881Speter red_config = TRUE; 233251881Speter } 234251881Speter } 235251881Speter 236251881Speter if (! red_config) 237251881Speter SVN_ERR(svn_config_create2(cfgp, FALSE, FALSE, pool)); 238251881Speter 239251881Speter return SVN_NO_ERROR; 240251881Speter} 241251881Speter 242251881Speter 243251881Speter/* CONFIG_DIR provides an override for the default behavior of reading 244251881Speter the default set of overlay files described by read_all()'s doc 245251881Speter string. */ 246251881Speterstatic svn_error_t * 247251881Speterget_category_config(svn_config_t **cfg, 248251881Speter const char *config_dir, 249251881Speter const char *category, 250251881Speter apr_pool_t *pool) 251251881Speter{ 252251881Speter const char *usr_reg_path = NULL, *sys_reg_path = NULL; 253251881Speter const char *usr_cfg_path, *sys_cfg_path; 254251881Speter svn_error_t *err = NULL; 255251881Speter 256251881Speter *cfg = NULL; 257251881Speter 258251881Speter if (! config_dir) 259251881Speter { 260251881Speter#ifdef WIN32 261251881Speter sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH, 262251881Speter category, NULL); 263251881Speter usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH, 264251881Speter category, NULL); 265251881Speter#endif /* WIN32 */ 266251881Speter 267251881Speter err = svn_config__sys_config_path(&sys_cfg_path, category, pool); 268251881Speter if ((err) && (err->apr_err == SVN_ERR_BAD_FILENAME)) 269251881Speter { 270251881Speter sys_cfg_path = NULL; 271251881Speter svn_error_clear(err); 272251881Speter } 273251881Speter else if (err) 274251881Speter return err; 275251881Speter } 276251881Speter else 277251881Speter sys_cfg_path = NULL; 278251881Speter 279251881Speter SVN_ERR(svn_config_get_user_config_path(&usr_cfg_path, config_dir, category, 280251881Speter pool)); 281251881Speter return read_all(cfg, sys_reg_path, usr_reg_path, 282251881Speter sys_cfg_path, usr_cfg_path, pool); 283251881Speter} 284251881Speter 285251881Speter 286251881Spetersvn_error_t * 287251881Spetersvn_config_get_config(apr_hash_t **cfg_hash, 288251881Speter const char *config_dir, 289251881Speter apr_pool_t *pool) 290251881Speter{ 291251881Speter svn_config_t *cfg; 292251881Speter *cfg_hash = apr_hash_make(pool); 293251881Speter 294251881Speter#define CATLEN (sizeof(SVN_CONFIG_CATEGORY_SERVERS) - 1) 295251881Speter SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS, 296251881Speter pool)); 297251881Speter if (cfg) 298251881Speter apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, CATLEN, cfg); 299251881Speter#undef CATLEN 300251881Speter 301251881Speter#define CATLEN (sizeof(SVN_CONFIG_CATEGORY_CONFIG) - 1) 302251881Speter SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG, 303251881Speter pool)); 304251881Speter if (cfg) 305251881Speter apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, CATLEN, cfg); 306251881Speter#undef CATLEN 307251881Speter 308251881Speter return SVN_NO_ERROR; 309251881Speter} 310251881Speter 311251881Speter 312251881Speter 313251881Speter/* Iterate through CFG, passing BATON to CALLBACK for every (SECTION, OPTION) 314251881Speter pair. Stop if CALLBACK returns TRUE. Allocate from POOL. */ 315251881Speterstatic void 316251881Speterfor_each_option(svn_config_t *cfg, void *baton, apr_pool_t *pool, 317251881Speter svn_boolean_t callback(void *same_baton, 318251881Speter cfg_section_t *section, 319251881Speter cfg_option_t *option)) 320251881Speter{ 321251881Speter apr_hash_index_t *sec_ndx; 322251881Speter for (sec_ndx = apr_hash_first(pool, cfg->sections); 323251881Speter sec_ndx != NULL; 324251881Speter sec_ndx = apr_hash_next(sec_ndx)) 325251881Speter { 326251881Speter void *sec_ptr; 327251881Speter cfg_section_t *sec; 328251881Speter apr_hash_index_t *opt_ndx; 329251881Speter 330251881Speter apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr); 331251881Speter sec = sec_ptr; 332251881Speter 333251881Speter for (opt_ndx = apr_hash_first(pool, sec->options); 334251881Speter opt_ndx != NULL; 335251881Speter opt_ndx = apr_hash_next(opt_ndx)) 336251881Speter { 337251881Speter void *opt_ptr; 338251881Speter cfg_option_t *opt; 339251881Speter 340251881Speter apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr); 341251881Speter opt = opt_ptr; 342251881Speter 343251881Speter if (callback(baton, sec, opt)) 344251881Speter return; 345251881Speter } 346251881Speter } 347251881Speter} 348251881Speter 349251881Speter 350251881Speter 351251881Speterstatic svn_boolean_t 352251881Spetermerge_callback(void *baton, cfg_section_t *section, cfg_option_t *option) 353251881Speter{ 354251881Speter svn_config_set(baton, section->name, option->name, option->value); 355251881Speter return FALSE; 356251881Speter} 357251881Speter 358251881Spetersvn_error_t * 359251881Spetersvn_config_merge(svn_config_t *cfg, const char *file, 360251881Speter svn_boolean_t must_exist) 361251881Speter{ 362251881Speter /* The original config hash shouldn't change if there's an error 363251881Speter while reading the confguration, so read into a temporary table. 364251881Speter ### We could use a tmp subpool for this, since merge_cfg is going 365251881Speter to be tossed afterwards. Premature optimization, though? */ 366251881Speter svn_config_t *merge_cfg; 367251881Speter SVN_ERR(svn_config_read3(&merge_cfg, file, must_exist, 368251881Speter cfg->section_names_case_sensitive, 369251881Speter cfg->option_names_case_sensitive, 370251881Speter cfg->pool)); 371251881Speter 372251881Speter /* Now copy the new options into the original table. */ 373251881Speter for_each_option(merge_cfg, cfg, merge_cfg->pool, merge_callback); 374251881Speter return SVN_NO_ERROR; 375251881Speter} 376251881Speter 377251881Speter 378251881Speter 379251881Speter/* Remove variable expansions from CFG. Walk through the options tree, 380251881Speter killing all expanded values, then clear the expanded value pool. */ 381251881Speterstatic svn_boolean_t 382251881Speterrmex_callback(void *baton, cfg_section_t *section, cfg_option_t *option) 383251881Speter{ 384251881Speter /* Only clear the `expanded' flag if the value actually contains 385251881Speter variable expansions. */ 386251881Speter if (option->expanded && option->x_value != NULL) 387251881Speter { 388251881Speter option->x_value = NULL; 389251881Speter option->expanded = FALSE; 390251881Speter } 391251881Speter 392251881Speter return FALSE; 393251881Speter} 394251881Speter 395251881Speterstatic void 396251881Speterremove_expansions(svn_config_t *cfg) 397251881Speter{ 398251881Speter if (!cfg->x_values) 399251881Speter return; 400251881Speter 401251881Speter for_each_option(cfg, NULL, cfg->x_pool, rmex_callback); 402251881Speter svn_pool_clear(cfg->x_pool); 403251881Speter cfg->x_values = FALSE; 404251881Speter} 405251881Speter 406251881Speter 407251881Speter 408251881Speter/* Canonicalize a string for hashing. Modifies KEY in place. */ 409251881Speterstatic APR_INLINE char * 410251881Spetermake_hash_key(char *key) 411251881Speter{ 412251881Speter register char *p; 413251881Speter for (p = key; *p != 0; ++p) 414251881Speter *p = (char)apr_tolower(*p); 415251881Speter return key; 416251881Speter} 417251881Speter 418251881Speter 419251881Speter/* Return a pointer to an option in CFG, or NULL if it doesn't exist. 420251881Speter if SECTIONP is non-null, return a pointer to the option's section. 421251881Speter OPTION may be NULL. */ 422251881Speterstatic cfg_option_t * 423251881Speterfind_option(svn_config_t *cfg, const char *section, const char *option, 424251881Speter cfg_section_t **sectionp) 425251881Speter{ 426251881Speter void *sec_ptr; 427251881Speter 428251881Speter /* Canonicalize the hash key */ 429251881Speter svn_stringbuf_set(cfg->tmp_key, section); 430251881Speter if (! cfg->section_names_case_sensitive) 431251881Speter make_hash_key(cfg->tmp_key->data); 432251881Speter 433251881Speter sec_ptr = apr_hash_get(cfg->sections, cfg->tmp_key->data, 434251881Speter cfg->tmp_key->len); 435251881Speter if (sectionp != NULL) 436251881Speter *sectionp = sec_ptr; 437251881Speter 438251881Speter if (sec_ptr != NULL && option != NULL) 439251881Speter { 440251881Speter cfg_section_t *sec = sec_ptr; 441251881Speter cfg_option_t *opt; 442251881Speter 443251881Speter /* Canonicalize the option key */ 444251881Speter svn_stringbuf_set(cfg->tmp_key, option); 445251881Speter if (! cfg->option_names_case_sensitive) 446251881Speter make_hash_key(cfg->tmp_key->data); 447251881Speter 448251881Speter opt = apr_hash_get(sec->options, cfg->tmp_key->data, 449251881Speter cfg->tmp_key->len); 450251881Speter /* NOTE: ConfigParser's sections are case sensitive. */ 451251881Speter if (opt == NULL 452251881Speter && apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0) 453251881Speter /* Options which aren't found in the requested section are 454251881Speter also sought after in the default section. */ 455251881Speter opt = find_option(cfg, SVN_CONFIG__DEFAULT_SECTION, option, &sec); 456251881Speter return opt; 457251881Speter } 458251881Speter 459251881Speter return NULL; 460251881Speter} 461251881Speter 462251881Speter 463251881Speter/* Has a bi-directional dependency with make_string_from_option(). */ 464251881Speterstatic void 465251881Speterexpand_option_value(svn_config_t *cfg, cfg_section_t *section, 466251881Speter const char *opt_value, const char **opt_x_valuep, 467251881Speter apr_pool_t *x_pool); 468251881Speter 469251881Speter 470251881Speter/* Set *VALUEP according to the OPT's value. A value for X_POOL must 471251881Speter only ever be passed into this function by expand_option_value(). */ 472251881Speterstatic void 473251881Spetermake_string_from_option(const char **valuep, svn_config_t *cfg, 474251881Speter cfg_section_t *section, cfg_option_t *opt, 475251881Speter apr_pool_t* x_pool) 476251881Speter{ 477251881Speter /* Expand the option value if necessary. */ 478251881Speter if (!opt->expanded) 479251881Speter { 480251881Speter /* before attempting to expand an option, check for the placeholder. 481251881Speter * If none is there, there is no point in calling expand_option_value. 482251881Speter */ 483251881Speter if (opt->value && strchr(opt->value, '%')) 484251881Speter { 485251881Speter apr_pool_t *tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool)); 486251881Speter 487251881Speter expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool); 488251881Speter opt->expanded = TRUE; 489251881Speter 490251881Speter if (!x_pool) 491251881Speter { 492251881Speter /* Grab the fully expanded value from tmp_pool before its 493251881Speter disappearing act. */ 494251881Speter if (opt->x_value) 495251881Speter opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value, 496251881Speter strlen(opt->x_value)); 497251881Speter svn_pool_destroy(tmp_pool); 498251881Speter } 499251881Speter } 500251881Speter else 501251881Speter { 502251881Speter opt->expanded = TRUE; 503251881Speter } 504251881Speter } 505251881Speter 506251881Speter if (opt->x_value) 507251881Speter *valuep = opt->x_value; 508251881Speter else 509251881Speter *valuep = opt->value; 510251881Speter} 511251881Speter 512251881Speter 513251881Speter/* Start of variable-replacement placeholder */ 514251881Speter#define FMT_START "%(" 515251881Speter#define FMT_START_LEN (sizeof(FMT_START) - 1) 516251881Speter 517251881Speter/* End of variable-replacement placeholder */ 518251881Speter#define FMT_END ")s" 519251881Speter#define FMT_END_LEN (sizeof(FMT_END) - 1) 520251881Speter 521251881Speter 522251881Speter/* Expand OPT_VALUE (which may be NULL) in SECTION into *OPT_X_VALUEP. 523251881Speter If no variable replacements are done, set *OPT_X_VALUEP to 524251881Speter NULL. Allocate from X_POOL. */ 525251881Speterstatic void 526251881Speterexpand_option_value(svn_config_t *cfg, cfg_section_t *section, 527251881Speter const char *opt_value, const char **opt_x_valuep, 528251881Speter apr_pool_t *x_pool) 529251881Speter{ 530251881Speter svn_stringbuf_t *buf = NULL; 531251881Speter const char *parse_from = opt_value; 532251881Speter const char *copy_from = parse_from; 533251881Speter const char *name_start, *name_end; 534251881Speter 535251881Speter while (parse_from != NULL 536251881Speter && *parse_from != '\0' 537251881Speter && (name_start = strstr(parse_from, FMT_START)) != NULL) 538251881Speter { 539251881Speter name_start += FMT_START_LEN; 540251881Speter if (*name_start == '\0') 541251881Speter /* FMT_START at end of opt_value. */ 542251881Speter break; 543251881Speter 544251881Speter name_end = strstr(name_start, FMT_END); 545251881Speter if (name_end != NULL) 546251881Speter { 547251881Speter cfg_option_t *x_opt; 548251881Speter apr_size_t len = name_end - name_start; 549251881Speter char *name = apr_pstrmemdup(x_pool, name_start, len); 550251881Speter 551251881Speter x_opt = find_option(cfg, section->name, name, NULL); 552251881Speter 553251881Speter if (x_opt != NULL) 554251881Speter { 555251881Speter const char *cstring; 556251881Speter 557251881Speter /* Pass back the sub-pool originally provided by 558251881Speter make_string_from_option() as an indication of when it 559251881Speter should terminate. */ 560251881Speter make_string_from_option(&cstring, cfg, section, x_opt, x_pool); 561251881Speter 562251881Speter /* Append the plain text preceding the expansion. */ 563251881Speter len = name_start - FMT_START_LEN - copy_from; 564251881Speter if (buf == NULL) 565251881Speter { 566251881Speter buf = svn_stringbuf_ncreate(copy_from, len, x_pool); 567251881Speter cfg->x_values = TRUE; 568251881Speter } 569251881Speter else 570251881Speter svn_stringbuf_appendbytes(buf, copy_from, len); 571251881Speter 572251881Speter /* Append the expansion and adjust parse pointers. */ 573251881Speter svn_stringbuf_appendcstr(buf, cstring); 574251881Speter parse_from = name_end + FMT_END_LEN; 575251881Speter copy_from = parse_from; 576251881Speter } 577251881Speter else 578251881Speter /* Though ConfigParser considers the failure to resolve 579251881Speter the requested expansion an exception condition, we 580251881Speter consider it to be plain text, and look for the start of 581251881Speter the next one. */ 582251881Speter parse_from = name_end + FMT_END_LEN; 583251881Speter } 584251881Speter else 585251881Speter /* Though ConfigParser treats unterminated format specifiers 586251881Speter as an exception condition, we consider them to be plain 587251881Speter text. The fact that there are no more format specifier 588251881Speter endings means we're done parsing. */ 589251881Speter parse_from = NULL; 590251881Speter } 591251881Speter 592251881Speter if (buf != NULL) 593251881Speter { 594251881Speter /* Copy the remainder of the plain text. */ 595251881Speter svn_stringbuf_appendcstr(buf, copy_from); 596251881Speter *opt_x_valuep = buf->data; 597251881Speter } 598251881Speter else 599251881Speter *opt_x_valuep = NULL; 600251881Speter} 601251881Speter 602251881Speterstatic cfg_section_t * 603251881Spetersvn_config_addsection(svn_config_t *cfg, 604251881Speter const char *section) 605251881Speter{ 606251881Speter cfg_section_t *s; 607251881Speter const char *hash_key; 608251881Speter 609251881Speter s = apr_palloc(cfg->pool, sizeof(cfg_section_t)); 610251881Speter s->name = apr_pstrdup(cfg->pool, section); 611251881Speter if(cfg->section_names_case_sensitive) 612251881Speter hash_key = s->name; 613251881Speter else 614251881Speter hash_key = make_hash_key(apr_pstrdup(cfg->pool, section)); 615251881Speter s->options = apr_hash_make(cfg->pool); 616251881Speter svn_hash_sets(cfg->sections, hash_key, s); 617251881Speter 618251881Speter return s; 619251881Speter} 620251881Speter 621251881Speterstatic void 622251881Spetersvn_config_create_option(cfg_option_t **opt, 623251881Speter const char *option, 624251881Speter const char *value, 625251881Speter svn_boolean_t option_names_case_sensitive, 626251881Speter apr_pool_t *pool) 627251881Speter{ 628251881Speter cfg_option_t *o; 629251881Speter 630251881Speter o = apr_palloc(pool, sizeof(cfg_option_t)); 631251881Speter o->name = apr_pstrdup(pool, option); 632251881Speter if(option_names_case_sensitive) 633251881Speter o->hash_key = o->name; 634251881Speter else 635251881Speter o->hash_key = make_hash_key(apr_pstrdup(pool, option)); 636251881Speter 637251881Speter o->value = apr_pstrdup(pool, value); 638251881Speter o->x_value = NULL; 639251881Speter o->expanded = FALSE; 640251881Speter 641251881Speter *opt = o; 642251881Speter} 643251881Speter 644251881Speter 645251881Spetervoid 646251881Spetersvn_config_get(svn_config_t *cfg, const char **valuep, 647251881Speter const char *section, const char *option, 648251881Speter const char *default_value) 649251881Speter{ 650251881Speter *valuep = default_value; 651251881Speter if (cfg) 652251881Speter { 653251881Speter cfg_section_t *sec; 654251881Speter cfg_option_t *opt = find_option(cfg, section, option, &sec); 655251881Speter if (opt != NULL) 656251881Speter { 657251881Speter make_string_from_option(valuep, cfg, sec, opt, NULL); 658251881Speter } 659251881Speter else 660251881Speter /* before attempting to expand an option, check for the placeholder. 661251881Speter * If none is there, there is no point in calling expand_option_value. 662251881Speter */ 663251881Speter if (default_value && strchr(default_value, '%')) 664251881Speter { 665251881Speter apr_pool_t *tmp_pool = svn_pool_create(cfg->x_pool); 666251881Speter const char *x_default; 667251881Speter expand_option_value(cfg, sec, default_value, &x_default, tmp_pool); 668251881Speter if (x_default) 669251881Speter { 670251881Speter svn_stringbuf_set(cfg->tmp_value, x_default); 671251881Speter *valuep = cfg->tmp_value->data; 672251881Speter } 673251881Speter svn_pool_destroy(tmp_pool); 674251881Speter } 675251881Speter } 676251881Speter} 677251881Speter 678251881Speter 679251881Speter 680251881Spetervoid 681251881Spetersvn_config_set(svn_config_t *cfg, 682251881Speter const char *section, const char *option, 683251881Speter const char *value) 684251881Speter{ 685251881Speter cfg_section_t *sec; 686251881Speter cfg_option_t *opt; 687251881Speter 688251881Speter remove_expansions(cfg); 689251881Speter 690251881Speter opt = find_option(cfg, section, option, &sec); 691251881Speter if (opt != NULL) 692251881Speter { 693251881Speter /* Replace the option's value. */ 694251881Speter opt->value = apr_pstrdup(cfg->pool, value); 695251881Speter opt->expanded = FALSE; 696251881Speter return; 697251881Speter } 698251881Speter 699251881Speter /* Create a new option */ 700251881Speter svn_config_create_option(&opt, option, value, 701251881Speter cfg->option_names_case_sensitive, 702251881Speter cfg->pool); 703251881Speter 704251881Speter if (sec == NULL) 705251881Speter { 706251881Speter /* Even the section doesn't exist. Create it. */ 707251881Speter sec = svn_config_addsection(cfg, section); 708251881Speter } 709251881Speter 710251881Speter svn_hash_sets(sec->options, opt->hash_key, opt); 711251881Speter} 712251881Speter 713251881Speter 714251881Speter 715251881Speter/* Set *BOOLP to true or false depending (case-insensitively) on INPUT. 716251881Speter If INPUT is null, set *BOOLP to DEFAULT_VALUE. 717251881Speter 718251881Speter INPUT is a string indicating truth or falsehood in any of the usual 719251881Speter ways: "true"/"yes"/"on"/etc, "false"/"no"/"off"/etc. 720251881Speter 721251881Speter If INPUT is neither NULL nor a recognized string, return an error 722251881Speter with code SVN_ERR_BAD_CONFIG_VALUE; use SECTION and OPTION in 723251881Speter constructing the error string. */ 724251881Speterstatic svn_error_t * 725251881Speterget_bool(svn_boolean_t *boolp, const char *input, svn_boolean_t default_value, 726251881Speter const char *section, const char *option) 727251881Speter{ 728251881Speter svn_tristate_t value = svn_tristate__from_word(input); 729251881Speter 730251881Speter if (value == svn_tristate_true) 731251881Speter *boolp = TRUE; 732251881Speter else if (value == svn_tristate_false) 733251881Speter *boolp = FALSE; 734251881Speter else if (input == NULL) /* no value provided */ 735251881Speter *boolp = default_value; 736251881Speter 737251881Speter else if (section) /* unrecognized value */ 738251881Speter return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, 739251881Speter _("Config error: invalid boolean " 740251881Speter "value '%s' for '[%s] %s'"), 741251881Speter input, section, option); 742251881Speter else 743251881Speter return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, 744251881Speter _("Config error: invalid boolean " 745251881Speter "value '%s' for '%s'"), 746251881Speter input, option); 747251881Speter 748251881Speter return SVN_NO_ERROR; 749251881Speter} 750251881Speter 751251881Speter 752251881Spetersvn_error_t * 753251881Spetersvn_config_get_bool(svn_config_t *cfg, svn_boolean_t *valuep, 754251881Speter const char *section, const char *option, 755251881Speter svn_boolean_t default_value) 756251881Speter{ 757251881Speter const char *tmp_value; 758251881Speter svn_config_get(cfg, &tmp_value, section, option, NULL); 759251881Speter return get_bool(valuep, tmp_value, default_value, section, option); 760251881Speter} 761251881Speter 762251881Speter 763251881Speter 764251881Spetervoid 765251881Spetersvn_config_set_bool(svn_config_t *cfg, 766251881Speter const char *section, const char *option, 767251881Speter svn_boolean_t value) 768251881Speter{ 769251881Speter svn_config_set(cfg, section, option, 770251881Speter (value ? SVN_CONFIG_TRUE : SVN_CONFIG_FALSE)); 771251881Speter} 772251881Speter 773251881Spetersvn_error_t * 774251881Spetersvn_config_get_int64(svn_config_t *cfg, 775251881Speter apr_int64_t *valuep, 776251881Speter const char *section, 777251881Speter const char *option, 778251881Speter apr_int64_t default_value) 779251881Speter{ 780251881Speter const char *tmp_value; 781251881Speter svn_config_get(cfg, &tmp_value, section, option, NULL); 782251881Speter if (tmp_value) 783251881Speter return svn_cstring_strtoi64(valuep, tmp_value, 784251881Speter APR_INT64_MIN, APR_INT64_MAX, 10); 785251881Speter 786251881Speter *valuep = default_value; 787251881Speter return SVN_NO_ERROR; 788251881Speter} 789251881Speter 790251881Spetervoid 791251881Spetersvn_config_set_int64(svn_config_t *cfg, 792251881Speter const char *section, 793251881Speter const char *option, 794251881Speter apr_int64_t value) 795251881Speter{ 796251881Speter svn_config_set(cfg, section, option, 797251881Speter apr_psprintf(cfg->pool, "%" APR_INT64_T_FMT, value)); 798251881Speter} 799251881Speter 800251881Spetersvn_error_t * 801251881Spetersvn_config_get_yes_no_ask(svn_config_t *cfg, const char **valuep, 802251881Speter const char *section, const char *option, 803251881Speter const char* default_value) 804251881Speter{ 805251881Speter const char *tmp_value; 806251881Speter 807251881Speter svn_config_get(cfg, &tmp_value, section, option, NULL); 808251881Speter 809251881Speter if (! tmp_value) 810251881Speter tmp_value = default_value; 811251881Speter 812251881Speter if (tmp_value && (0 == svn_cstring_casecmp(tmp_value, SVN_CONFIG_ASK))) 813251881Speter { 814251881Speter *valuep = SVN_CONFIG_ASK; 815251881Speter } 816251881Speter else 817251881Speter { 818251881Speter svn_boolean_t bool_val; 819251881Speter /* We already incorporated default_value into tmp_value if 820251881Speter necessary, so the FALSE below will be ignored unless the 821251881Speter caller is doing something it shouldn't be doing. */ 822251881Speter SVN_ERR(get_bool(&bool_val, tmp_value, FALSE, section, option)); 823251881Speter *valuep = bool_val ? SVN_CONFIG_TRUE : SVN_CONFIG_FALSE; 824251881Speter } 825251881Speter 826251881Speter return SVN_NO_ERROR; 827251881Speter} 828251881Speter 829251881Spetersvn_error_t * 830251881Spetersvn_config_get_tristate(svn_config_t *cfg, svn_tristate_t *valuep, 831251881Speter const char *section, const char *option, 832251881Speter const char *unknown_value, 833251881Speter svn_tristate_t default_value) 834251881Speter{ 835251881Speter const char *tmp_value; 836251881Speter 837251881Speter svn_config_get(cfg, &tmp_value, section, option, NULL); 838251881Speter 839251881Speter if (! tmp_value) 840251881Speter { 841251881Speter *valuep = default_value; 842251881Speter } 843251881Speter else if (0 == svn_cstring_casecmp(tmp_value, unknown_value)) 844251881Speter { 845251881Speter *valuep = svn_tristate_unknown; 846251881Speter } 847251881Speter else 848251881Speter { 849251881Speter svn_boolean_t bool_val; 850251881Speter /* We already incorporated default_value into tmp_value if 851251881Speter necessary, so the FALSE below will be ignored unless the 852251881Speter caller is doing something it shouldn't be doing. */ 853251881Speter SVN_ERR(get_bool(&bool_val, tmp_value, FALSE, section, option)); 854251881Speter *valuep = bool_val ? svn_tristate_true : svn_tristate_false; 855251881Speter } 856251881Speter 857251881Speter return SVN_NO_ERROR; 858251881Speter} 859251881Speter 860251881Speterint 861251881Spetersvn_config_enumerate_sections(svn_config_t *cfg, 862251881Speter svn_config_section_enumerator_t callback, 863251881Speter void *baton) 864251881Speter{ 865251881Speter apr_hash_index_t *sec_ndx; 866251881Speter int count = 0; 867251881Speter apr_pool_t *subpool = svn_pool_create(cfg->x_pool); 868251881Speter 869251881Speter for (sec_ndx = apr_hash_first(subpool, cfg->sections); 870251881Speter sec_ndx != NULL; 871251881Speter sec_ndx = apr_hash_next(sec_ndx)) 872251881Speter { 873251881Speter void *sec_ptr; 874251881Speter cfg_section_t *sec; 875251881Speter 876251881Speter apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr); 877251881Speter sec = sec_ptr; 878251881Speter ++count; 879251881Speter if (!callback(sec->name, baton)) 880251881Speter break; 881251881Speter } 882251881Speter 883251881Speter svn_pool_destroy(subpool); 884251881Speter return count; 885251881Speter} 886251881Speter 887251881Speter 888251881Speterint 889251881Spetersvn_config_enumerate_sections2(svn_config_t *cfg, 890251881Speter svn_config_section_enumerator2_t callback, 891251881Speter void *baton, apr_pool_t *pool) 892251881Speter{ 893251881Speter apr_hash_index_t *sec_ndx; 894251881Speter apr_pool_t *iteration_pool; 895251881Speter int count = 0; 896251881Speter 897251881Speter iteration_pool = svn_pool_create(pool); 898251881Speter for (sec_ndx = apr_hash_first(pool, cfg->sections); 899251881Speter sec_ndx != NULL; 900251881Speter sec_ndx = apr_hash_next(sec_ndx)) 901251881Speter { 902251881Speter void *sec_ptr; 903251881Speter cfg_section_t *sec; 904251881Speter 905251881Speter apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr); 906251881Speter sec = sec_ptr; 907251881Speter ++count; 908251881Speter svn_pool_clear(iteration_pool); 909251881Speter if (!callback(sec->name, baton, iteration_pool)) 910251881Speter break; 911251881Speter } 912251881Speter svn_pool_destroy(iteration_pool); 913251881Speter 914251881Speter return count; 915251881Speter} 916251881Speter 917251881Speter 918251881Speter 919251881Speterint 920251881Spetersvn_config_enumerate(svn_config_t *cfg, const char *section, 921251881Speter svn_config_enumerator_t callback, void *baton) 922251881Speter{ 923251881Speter cfg_section_t *sec; 924251881Speter apr_hash_index_t *opt_ndx; 925251881Speter int count; 926251881Speter apr_pool_t *subpool; 927251881Speter 928251881Speter find_option(cfg, section, NULL, &sec); 929251881Speter if (sec == NULL) 930251881Speter return 0; 931251881Speter 932251881Speter subpool = svn_pool_create(cfg->x_pool); 933251881Speter count = 0; 934251881Speter for (opt_ndx = apr_hash_first(subpool, sec->options); 935251881Speter opt_ndx != NULL; 936251881Speter opt_ndx = apr_hash_next(opt_ndx)) 937251881Speter { 938251881Speter void *opt_ptr; 939251881Speter cfg_option_t *opt; 940251881Speter const char *temp_value; 941251881Speter 942251881Speter apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr); 943251881Speter opt = opt_ptr; 944251881Speter 945251881Speter ++count; 946251881Speter make_string_from_option(&temp_value, cfg, sec, opt, NULL); 947251881Speter if (!callback(opt->name, temp_value, baton)) 948251881Speter break; 949251881Speter } 950251881Speter 951251881Speter svn_pool_destroy(subpool); 952251881Speter return count; 953251881Speter} 954251881Speter 955251881Speter 956251881Speterint 957251881Spetersvn_config_enumerate2(svn_config_t *cfg, const char *section, 958251881Speter svn_config_enumerator2_t callback, void *baton, 959251881Speter apr_pool_t *pool) 960251881Speter{ 961251881Speter cfg_section_t *sec; 962251881Speter apr_hash_index_t *opt_ndx; 963251881Speter apr_pool_t *iteration_pool; 964251881Speter int count; 965251881Speter 966251881Speter find_option(cfg, section, NULL, &sec); 967251881Speter if (sec == NULL) 968251881Speter return 0; 969251881Speter 970251881Speter iteration_pool = svn_pool_create(pool); 971251881Speter count = 0; 972251881Speter for (opt_ndx = apr_hash_first(pool, sec->options); 973251881Speter opt_ndx != NULL; 974251881Speter opt_ndx = apr_hash_next(opt_ndx)) 975251881Speter { 976251881Speter void *opt_ptr; 977251881Speter cfg_option_t *opt; 978251881Speter const char *temp_value; 979251881Speter 980251881Speter apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr); 981251881Speter opt = opt_ptr; 982251881Speter 983251881Speter ++count; 984251881Speter make_string_from_option(&temp_value, cfg, sec, opt, NULL); 985251881Speter svn_pool_clear(iteration_pool); 986251881Speter if (!callback(opt->name, temp_value, baton, iteration_pool)) 987251881Speter break; 988251881Speter } 989251881Speter svn_pool_destroy(iteration_pool); 990251881Speter 991251881Speter return count; 992251881Speter} 993251881Speter 994251881Speter 995251881Speter 996251881Speter/* Baton for search_groups() */ 997251881Speterstruct search_groups_baton 998251881Speter{ 999251881Speter const char *key; /* Provided by caller of svn_config_find_group */ 1000251881Speter const char *match; /* Filled in by search_groups */ 1001251881Speter apr_pool_t *pool; 1002251881Speter}; 1003251881Speter 1004251881Speter 1005251881Speter/* This is an `svn_config_enumerator_t' function, and BATON is a 1006251881Speter * `struct search_groups_baton *'. 1007251881Speter */ 1008251881Speterstatic svn_boolean_t search_groups(const char *name, 1009251881Speter const char *value, 1010251881Speter void *baton, 1011251881Speter apr_pool_t *pool) 1012251881Speter{ 1013251881Speter struct search_groups_baton *b = baton; 1014251881Speter apr_array_header_t *list; 1015251881Speter 1016251881Speter list = svn_cstring_split(value, ",", TRUE, pool); 1017251881Speter if (svn_cstring_match_glob_list(b->key, list)) 1018251881Speter { 1019251881Speter /* Fill in the match and return false, to stop enumerating. */ 1020251881Speter b->match = apr_pstrdup(b->pool, name); 1021251881Speter return FALSE; 1022251881Speter } 1023251881Speter else 1024251881Speter return TRUE; 1025251881Speter} 1026251881Speter 1027251881Speter 1028251881Speterconst char *svn_config_find_group(svn_config_t *cfg, const char *key, 1029251881Speter const char *master_section, 1030251881Speter apr_pool_t *pool) 1031251881Speter{ 1032251881Speter struct search_groups_baton gb; 1033251881Speter 1034251881Speter gb.key = key; 1035251881Speter gb.match = NULL; 1036251881Speter gb.pool = pool; 1037251881Speter (void) svn_config_enumerate2(cfg, master_section, search_groups, &gb, pool); 1038251881Speter return gb.match; 1039251881Speter} 1040251881Speter 1041251881Speter 1042251881Speterconst char* 1043251881Spetersvn_config_get_server_setting(svn_config_t *cfg, 1044251881Speter const char* server_group, 1045251881Speter const char* option_name, 1046251881Speter const char* default_value) 1047251881Speter{ 1048251881Speter const char *retval; 1049251881Speter svn_config_get(cfg, &retval, SVN_CONFIG_SECTION_GLOBAL, 1050251881Speter option_name, default_value); 1051251881Speter if (server_group) 1052251881Speter { 1053251881Speter svn_config_get(cfg, &retval, server_group, option_name, retval); 1054251881Speter } 1055251881Speter return retval; 1056251881Speter} 1057251881Speter 1058251881Speter 1059251881Spetersvn_error_t * 1060251881Spetersvn_config_dup(svn_config_t **cfgp, 1061251881Speter svn_config_t *src, 1062251881Speter apr_pool_t *pool) 1063251881Speter{ 1064251881Speter apr_hash_index_t *sectidx; 1065251881Speter apr_hash_index_t *optidx; 1066251881Speter 1067251881Speter *cfgp = 0; 1068251881Speter SVN_ERR(svn_config_create2(cfgp, FALSE, FALSE, pool)); 1069251881Speter 1070251881Speter (*cfgp)->x_values = src->x_values; 1071251881Speter (*cfgp)->section_names_case_sensitive = src->section_names_case_sensitive; 1072251881Speter (*cfgp)->option_names_case_sensitive = src->option_names_case_sensitive; 1073251881Speter 1074251881Speter for (sectidx = apr_hash_first(pool, src->sections); 1075251881Speter sectidx != NULL; 1076251881Speter sectidx = apr_hash_next(sectidx)) 1077251881Speter { 1078251881Speter const void *sectkey; 1079251881Speter void *sectval; 1080251881Speter apr_ssize_t sectkeyLength; 1081251881Speter cfg_section_t * srcsect; 1082251881Speter cfg_section_t * destsec; 1083251881Speter 1084251881Speter apr_hash_this(sectidx, §key, §keyLength, §val); 1085251881Speter srcsect = sectval; 1086251881Speter 1087251881Speter destsec = svn_config_addsection(*cfgp, srcsect->name); 1088251881Speter 1089251881Speter for (optidx = apr_hash_first(pool, srcsect->options); 1090251881Speter optidx != NULL; 1091251881Speter optidx = apr_hash_next(optidx)) 1092251881Speter { 1093251881Speter const void *optkey; 1094251881Speter void *optval; 1095251881Speter apr_ssize_t optkeyLength; 1096251881Speter cfg_option_t *srcopt; 1097251881Speter cfg_option_t *destopt; 1098251881Speter 1099251881Speter apr_hash_this(optidx, &optkey, &optkeyLength, &optval); 1100251881Speter srcopt = optval; 1101251881Speter 1102251881Speter svn_config_create_option(&destopt, srcopt->name, srcopt->value, 1103251881Speter (*cfgp)->option_names_case_sensitive, 1104251881Speter pool); 1105251881Speter 1106251881Speter destopt->value = apr_pstrdup(pool, srcopt->value); 1107251881Speter destopt->x_value = apr_pstrdup(pool, srcopt->x_value); 1108251881Speter destopt->expanded = srcopt->expanded; 1109251881Speter apr_hash_set(destsec->options, 1110251881Speter apr_pstrdup(pool, (const char*)optkey), 1111251881Speter optkeyLength, destopt); 1112251881Speter } 1113251881Speter } 1114251881Speter 1115251881Speter return SVN_NO_ERROR; 1116251881Speter} 1117251881Speter 1118251881Spetersvn_error_t * 1119251881Spetersvn_config_copy_config(apr_hash_t **cfg_hash, 1120251881Speter apr_hash_t *src_hash, 1121251881Speter apr_pool_t *pool) 1122251881Speter{ 1123251881Speter apr_hash_index_t *cidx; 1124251881Speter 1125251881Speter *cfg_hash = apr_hash_make(pool); 1126251881Speter for (cidx = apr_hash_first(pool, src_hash); 1127251881Speter cidx != NULL; 1128251881Speter cidx = apr_hash_next(cidx)) 1129251881Speter { 1130251881Speter const void *ckey; 1131251881Speter void *cval; 1132251881Speter apr_ssize_t ckeyLength; 1133251881Speter svn_config_t * srcconfig; 1134251881Speter svn_config_t * destconfig; 1135251881Speter 1136251881Speter apr_hash_this(cidx, &ckey, &ckeyLength, &cval); 1137251881Speter srcconfig = cval; 1138251881Speter 1139251881Speter SVN_ERR(svn_config_dup(&destconfig, srcconfig, pool)); 1140251881Speter 1141251881Speter apr_hash_set(*cfg_hash, 1142251881Speter apr_pstrdup(pool, (const char*)ckey), 1143251881Speter ckeyLength, destconfig); 1144251881Speter } 1145251881Speter 1146251881Speter return SVN_NO_ERROR; 1147251881Speter} 1148251881Speter 1149251881Spetersvn_error_t* 1150251881Spetersvn_config_get_server_setting_int(svn_config_t *cfg, 1151251881Speter const char *server_group, 1152251881Speter const char *option_name, 1153251881Speter apr_int64_t default_value, 1154251881Speter apr_int64_t *result_value, 1155251881Speter apr_pool_t *pool) 1156251881Speter{ 1157251881Speter const char* tmp_value; 1158251881Speter char *end_pos; 1159251881Speter 1160251881Speter tmp_value = svn_config_get_server_setting(cfg, server_group, 1161251881Speter option_name, NULL); 1162251881Speter if (tmp_value == NULL) 1163251881Speter *result_value = default_value; 1164251881Speter else 1165251881Speter { 1166251881Speter /* read tmp_value as an int now */ 1167251881Speter *result_value = apr_strtoi64(tmp_value, &end_pos, 0); 1168251881Speter 1169251881Speter if (*end_pos != 0) 1170251881Speter { 1171251881Speter return svn_error_createf 1172251881Speter (SVN_ERR_BAD_CONFIG_VALUE, NULL, 1173251881Speter _("Config error: invalid integer value '%s'"), 1174251881Speter tmp_value); 1175251881Speter } 1176251881Speter } 1177251881Speter 1178251881Speter return SVN_NO_ERROR; 1179251881Speter} 1180251881Speter 1181251881Spetersvn_error_t * 1182251881Spetersvn_config_get_server_setting_bool(svn_config_t *cfg, 1183251881Speter svn_boolean_t *valuep, 1184251881Speter const char *server_group, 1185251881Speter const char *option_name, 1186251881Speter svn_boolean_t default_value) 1187251881Speter{ 1188251881Speter const char* tmp_value; 1189251881Speter tmp_value = svn_config_get_server_setting(cfg, server_group, 1190251881Speter option_name, NULL); 1191251881Speter return get_bool(valuep, tmp_value, default_value, 1192251881Speter server_group, option_name); 1193251881Speter} 1194251881Speter 1195251881Speter 1196251881Spetersvn_boolean_t 1197251881Spetersvn_config_has_section(svn_config_t *cfg, const char *section) 1198251881Speter{ 1199251881Speter cfg_section_t *sec; 1200251881Speter 1201251881Speter /* Canonicalize the hash key */ 1202251881Speter svn_stringbuf_set(cfg->tmp_key, section); 1203251881Speter if (! cfg->section_names_case_sensitive) 1204251881Speter make_hash_key(cfg->tmp_key->data); 1205251881Speter 1206251881Speter sec = svn_hash_gets(cfg->sections, cfg->tmp_key->data); 1207251881Speter return sec != NULL; 1208251881Speter} 1209