mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Change the ap_cfg_getline() and ap_cfg_getc() to return an error code.
Also: - Make ap_cfg_getline() return APR_ENOSPC if a config line is too long. - Add ap_pcfg_strerror() function to convert ap_cfg_getline's return value into a nice message. - Adjust definition of ap_configfile_t accordingly. Not bumping MMN because it has already been bumped today. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1086756 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -101,6 +101,8 @@
|
|||||||
<li>New API to retain data across module unload/load</li>
|
<li>New API to retain data across module unload/load</li>
|
||||||
<li>New check_config hook</li>
|
<li>New check_config hook</li>
|
||||||
<li>New ap_process_fnmatch_configs() to process wildcards</li>
|
<li>New ap_process_fnmatch_configs() to process wildcards</li>
|
||||||
|
<li>Change ap_configfile_t, ap_cfg_getline(), ap_cfg_getc() to return error
|
||||||
|
code, new ap_pcfg_strerror().</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@@ -311,6 +311,8 @@
|
|||||||
connectionPoolTTL (connection_pool_ttl, int->apr_interval_t)
|
connectionPoolTTL (connection_pool_ttl, int->apr_interval_t)
|
||||||
* 20110329.0 (2.3.12-dev) Change single-bit signed fields to unsigned in
|
* 20110329.0 (2.3.12-dev) Change single-bit signed fields to unsigned in
|
||||||
* proxy and cache interfaces.
|
* proxy and cache interfaces.
|
||||||
|
* Change ap_configfile_t/ap_cfg_getline()/
|
||||||
|
* ap_cfg_getc() API, add ap_pcfg_strerror()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
|
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
|
||||||
|
@@ -257,13 +257,18 @@ struct command_struct {
|
|||||||
/** Common structure for reading of config files / passwd files etc. */
|
/** Common structure for reading of config files / passwd files etc. */
|
||||||
typedef struct ap_configfile_t ap_configfile_t;
|
typedef struct ap_configfile_t ap_configfile_t;
|
||||||
struct ap_configfile_t {
|
struct ap_configfile_t {
|
||||||
int (*getch) (void *param); /**< a getc()-like function */
|
/**< an apr_file_getc()-like function */
|
||||||
void *(*getstr) (void *buf, size_t bufsiz, void *param);
|
apr_status_t (*getch) (char *ch, void *param);
|
||||||
/**< a fgets()-like function */
|
/**< an apr_file_gets()-like function */
|
||||||
int (*close) (void *param); /**< a close handler function */
|
apr_status_t (*getstr) (void *buf, size_t bufsiz, void *param);
|
||||||
void *param; /**< the argument passed to getch/getstr/close */
|
/**< a close handler function */
|
||||||
const char *name; /**< the filename / description */
|
apr_status_t (*close) (void *param);
|
||||||
unsigned line_number; /**< current line number, starting at 1 */
|
/**< the argument passed to getch/getstr/close */
|
||||||
|
void *param;
|
||||||
|
/**< the filename / description */
|
||||||
|
const char *name;
|
||||||
|
/**< current line number, starting at 1 */
|
||||||
|
unsigned line_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -765,25 +770,26 @@ AP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg,
|
|||||||
AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(apr_pool_t *p,
|
AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(apr_pool_t *p,
|
||||||
const char *descr,
|
const char *descr,
|
||||||
void *param,
|
void *param,
|
||||||
int(*getc_func)(void*),
|
apr_status_t (*getc_func) (char *ch, void *param),
|
||||||
void *(*gets_func) (void *buf, size_t bufsiz, void *param),
|
apr_status_t (*gets_func) (void *buf, size_t bufsiz, void *param),
|
||||||
int(*close_func)(void *param));
|
apr_status_t (*close_func) (void *param));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read one line from open ap_configfile_t, strip LF, increase line number
|
* Read one line from open ap_configfile_t, strip leading and trailing
|
||||||
|
* whitespace, increase line number
|
||||||
* @param buf place to store the line read
|
* @param buf place to store the line read
|
||||||
* @param bufsize size of the buffer
|
* @param bufsize size of the buffer
|
||||||
* @param cfp File to read from
|
* @param cfp File to read from
|
||||||
* @return 1 on success, 0 on failure
|
* @return error status, APR_ENOSPC if bufsize is too small for the line
|
||||||
*/
|
*/
|
||||||
AP_DECLARE(int) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t *cfp);
|
AP_DECLARE(apr_status_t) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t *cfp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read one char from open configfile_t, increase line number upon LF
|
* Read one char from open configfile_t, increase line number upon LF
|
||||||
* @param cfp The file to read from
|
* @param cfp The file to read from
|
||||||
* @return the character read
|
* @return the character read
|
||||||
*/
|
*/
|
||||||
AP_DECLARE(int) ap_cfg_getc(ap_configfile_t *cfp);
|
AP_DECLARE(apr_status_t) ap_cfg_getc(char *ch, ap_configfile_t *cfp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach from open ap_configfile_t, calling the close handler
|
* Detach from open ap_configfile_t, calling the close handler
|
||||||
@@ -792,6 +798,16 @@ AP_DECLARE(int) ap_cfg_getc(ap_configfile_t *cfp);
|
|||||||
*/
|
*/
|
||||||
AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp);
|
AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a return value from ap_cfg_getline or ap_cfg_getc to a user friendly
|
||||||
|
* string.
|
||||||
|
* @param p The pool to allocate the string from
|
||||||
|
* @param cfp The config file
|
||||||
|
* @return The error string, NULL if rc == APR_SUCCESS
|
||||||
|
*/
|
||||||
|
AP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp,
|
||||||
|
apr_status_t rc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all data between the current <foo> and the matching </foo>. All
|
* Read all data between the current <foo> and the matching </foo>. All
|
||||||
* of this data is forgotten immediately.
|
* of this data is forgotten immediately.
|
||||||
|
@@ -317,8 +317,8 @@ static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf,
|
|||||||
apr_size_t i = 0;
|
apr_size_t i = 0;
|
||||||
|
|
||||||
if (cfg->getstr) {
|
if (cfg->getstr) {
|
||||||
const char *res = (cfg->getstr) (buf, bufsiz, cfg->param);
|
apr_status_t rc = (cfg->getstr) (buf, bufsiz, cfg->param);
|
||||||
if (res) {
|
if (rc == APR_SUCCESS) {
|
||||||
i = strlen(buf);
|
i = strlen(buf);
|
||||||
if (i && buf[i - 1] == '\n')
|
if (i && buf[i - 1] == '\n')
|
||||||
++cfg->line_number;
|
++cfg->line_number;
|
||||||
@@ -330,8 +330,9 @@ static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (i < bufsiz) {
|
while (i < bufsiz) {
|
||||||
int ch = (cfg->getch) (cfg->param);
|
char ch;
|
||||||
if (ch == EOF)
|
apr_status_t rc = (cfg->getch) (&ch, cfg->param);
|
||||||
|
if (rc != APR_SUCCESS)
|
||||||
break;
|
break;
|
||||||
buf[i++] = ch;
|
buf[i++] = ch;
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
|
@@ -1169,6 +1169,7 @@ AP_DECLARE(const char *) ap_build_cont_config(apr_pool_t *p,
|
|||||||
char *bracket;
|
char *bracket;
|
||||||
const char *retval;
|
const char *retval;
|
||||||
ap_directive_t *sub_tree = NULL;
|
ap_directive_t *sub_tree = NULL;
|
||||||
|
apr_status_t rc;
|
||||||
|
|
||||||
/* Since this function can be called recursively, allocate
|
/* Since this function can be called recursively, allocate
|
||||||
* the temporary 8k string buffer from the temp_pool rather
|
* the temporary 8k string buffer from the temp_pool rather
|
||||||
@@ -1177,7 +1178,8 @@ AP_DECLARE(const char *) ap_build_cont_config(apr_pool_t *p,
|
|||||||
l = apr_palloc(temp_pool, MAX_STRING_LEN);
|
l = apr_palloc(temp_pool, MAX_STRING_LEN);
|
||||||
|
|
||||||
bracket = apr_pstrcat(temp_pool, orig_directive + 1, ">", NULL);
|
bracket = apr_pstrcat(temp_pool, orig_directive + 1, ">", NULL);
|
||||||
while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
|
while ((rc = ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))
|
||||||
|
== APR_SUCCESS) {
|
||||||
if (!memcmp(l, "</", 2)
|
if (!memcmp(l, "</", 2)
|
||||||
&& (strcasecmp(l + 2, bracket) == 0)
|
&& (strcasecmp(l + 2, bracket) == 0)
|
||||||
&& (*curr_parent == NULL)) {
|
&& (*curr_parent == NULL)) {
|
||||||
@@ -1196,6 +1198,8 @@ AP_DECLARE(const char *) ap_build_cont_config(apr_pool_t *p,
|
|||||||
sub_tree = *current;
|
sub_tree = *current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rc != APR_EOF && rc != APR_SUCCESS)
|
||||||
|
return ap_pcfg_strerror(temp_pool, parms->config_file, rc);
|
||||||
|
|
||||||
*current = sub_tree;
|
*current = sub_tree;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1290,6 +1294,7 @@ AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
|
|||||||
char *l = apr_palloc (temp_pool, MAX_STRING_LEN);
|
char *l = apr_palloc (temp_pool, MAX_STRING_LEN);
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
ap_directive_t **last_ptr = NULL;
|
ap_directive_t **last_ptr = NULL;
|
||||||
|
apr_status_t rc;
|
||||||
|
|
||||||
if (current != NULL) {
|
if (current != NULL) {
|
||||||
/* If we have to traverse the whole tree again for every included
|
/* If we have to traverse the whole tree again for every included
|
||||||
@@ -1313,7 +1318,8 @@ AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
|
while ((rc = ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))
|
||||||
|
== APR_SUCCESS) {
|
||||||
errmsg = ap_build_config_sub(p, temp_pool, l, parms,
|
errmsg = ap_build_config_sub(p, temp_pool, l, parms,
|
||||||
¤t, &curr_parent, conftree);
|
¤t, &curr_parent, conftree);
|
||||||
if (errmsg != NULL)
|
if (errmsg != NULL)
|
||||||
@@ -1327,6 +1333,8 @@ AP_DECLARE(const char *) ap_build_config(cmd_parms *parms,
|
|||||||
*conftree = current;
|
*conftree = current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rc != APR_EOF && rc != APR_SUCCESS)
|
||||||
|
return ap_pcfg_strerror(temp_pool, parms->config_file, rc);
|
||||||
|
|
||||||
if (curr_parent != NULL) {
|
if (curr_parent != NULL) {
|
||||||
errmsg = "";
|
errmsg = "";
|
||||||
@@ -1499,8 +1507,10 @@ AP_DECLARE(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
|
|||||||
char l[MAX_STRING_LEN];
|
char l[MAX_STRING_LEN];
|
||||||
const char *args;
|
const char *args;
|
||||||
char *cmd_name;
|
char *cmd_name;
|
||||||
|
apr_status_t rc;
|
||||||
|
|
||||||
while(!(ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))) {
|
while((rc = ap_cfg_getline(l, MAX_STRING_LEN, cmd->config_file))
|
||||||
|
== APR_SUCCESS) {
|
||||||
#if RESOLVE_ENV_PER_TOKEN
|
#if RESOLVE_ENV_PER_TOKEN
|
||||||
args = l;
|
args = l;
|
||||||
#else
|
#else
|
||||||
@@ -1533,6 +1543,8 @@ AP_DECLARE(const char *) ap_soak_end_container(cmd_parms *cmd, char *directive)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rc != APR_EOF && rc != APR_SUCCESS)
|
||||||
|
return ap_pcfg_strerror(cmd->temp_pool, cmd->config_file, rc);
|
||||||
|
|
||||||
return apr_pstrcat(cmd->pool, "Expected </",
|
return apr_pstrcat(cmd->pool, "Expected </",
|
||||||
directive + 1, "> before end of configuration",
|
directive + 1, "> before end of configuration",
|
||||||
@@ -1592,31 +1604,31 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
/* arr_elts_getstr() returns the next line from the string array. */
|
/* arr_elts_getstr() returns the next line from the string array. */
|
||||||
static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
|
static apr_status_t arr_elts_getstr(void *buf, size_t bufsiz, void *param)
|
||||||
{
|
{
|
||||||
arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
|
arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
|
||||||
|
char *elt;
|
||||||
|
|
||||||
/* End of array reached? */
|
/* End of array reached? */
|
||||||
if (++arr_param->curr_idx > arr_param->array->nelts)
|
if (++arr_param->curr_idx > arr_param->array->nelts)
|
||||||
return NULL;
|
return APR_EOF;
|
||||||
|
|
||||||
/* return the line */
|
/* return the line */
|
||||||
apr_cpystrn(buf,
|
elt = ((char **)arr_param->array->elts)[arr_param->curr_idx - 1];
|
||||||
((char **)arr_param->array->elts)[arr_param->curr_idx - 1],
|
if (apr_cpystrn(buf, elt, bufsiz) - (char *)buf >= bufsiz - 1)
|
||||||
bufsiz);
|
return APR_ENOSPC;
|
||||||
|
return APR_SUCCESS;
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
|
/* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
|
||||||
static int arr_elts_close(void *param)
|
static apr_status_t arr_elts_close(void *param)
|
||||||
{
|
{
|
||||||
arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
|
arr_elts_param_t *arr_param = (arr_elts_param_t *)param;
|
||||||
|
|
||||||
arr_param->curr_idx = arr_param->array->nelts;
|
arr_param->curr_idx = arr_param->array->nelts;
|
||||||
|
|
||||||
return 0;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *process_command_config(server_rec *s,
|
static const char *process_command_config(server_rec *s,
|
||||||
@@ -1700,9 +1712,12 @@ AP_DECLARE(const char *) ap_process_resource_config(server_rec *s,
|
|||||||
ap_cfg_closefile(cfp);
|
ap_cfg_closefile(cfp);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return apr_psprintf(p, "Syntax error on line %d of %s: %s",
|
if (parms.err_directive)
|
||||||
parms.err_directive->line_num,
|
return apr_psprintf(p, "Syntax error on line %d of %s: %s",
|
||||||
parms.err_directive->filename, error);
|
parms.err_directive->line_num,
|
||||||
|
parms.err_directive->filename, error);
|
||||||
|
else
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1956,10 +1971,11 @@ AP_DECLARE(int) ap_process_config_tree(server_rec *s,
|
|||||||
|
|
||||||
errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
|
errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
|
||||||
if (errmsg) {
|
if (errmsg) {
|
||||||
ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p,
|
if (parms.err_directive)
|
||||||
"Syntax error on line %d of %s:",
|
ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p,
|
||||||
parms.err_directive->line_num,
|
"Syntax error on line %d of %s:",
|
||||||
parms.err_directive->filename);
|
parms.err_directive->line_num,
|
||||||
|
parms.err_directive->filename);
|
||||||
ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p,
|
ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, p,
|
||||||
"%s", errmsg);
|
"%s", errmsg);
|
||||||
return HTTP_INTERNAL_SERVER_ERROR;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
224
server/util.c
224
server/util.c
@@ -766,30 +766,20 @@ AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp)
|
|||||||
return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
|
return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we can't use apr_file_* directly because of linking issues on Windows */
|
||||||
static apr_status_t cfg_close(void *param)
|
static apr_status_t cfg_close(void *param)
|
||||||
{
|
{
|
||||||
apr_file_t *cfp = (apr_file_t *) param;
|
return apr_file_close(param);
|
||||||
return (apr_file_close(cfp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfg_getch(void *param)
|
static apr_status_t cfg_getch(char *ch, void *param)
|
||||||
{
|
{
|
||||||
char ch;
|
return apr_file_getc(ch, param);
|
||||||
apr_file_t *cfp = (apr_file_t *) param;
|
|
||||||
if (apr_file_getc(&ch, cfp) == APR_SUCCESS)
|
|
||||||
return ch;
|
|
||||||
return (int)EOF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *cfg_getstr(void *buf, size_t bufsiz, void *param)
|
static apr_status_t cfg_getstr(void *buf, size_t bufsiz, void *param)
|
||||||
{
|
{
|
||||||
apr_file_t *cfp = (apr_file_t *) param;
|
return apr_file_gets(buf, bufsiz, param);
|
||||||
apr_status_t rv;
|
|
||||||
rv = apr_file_gets(buf, bufsiz, cfp);
|
|
||||||
if (rv == APR_SUCCESS) {
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a ap_configfile_t as FILE, return open ap_configfile_t struct pointer */
|
/* Open a ap_configfile_t as FILE, return open ap_configfile_t struct pointer */
|
||||||
@@ -864,9 +854,9 @@ AP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg,
|
|||||||
new_cfg = apr_palloc(p, sizeof(*new_cfg));
|
new_cfg = apr_palloc(p, sizeof(*new_cfg));
|
||||||
new_cfg->param = file;
|
new_cfg->param = file;
|
||||||
new_cfg->name = apr_pstrdup(p, name);
|
new_cfg->name = apr_pstrdup(p, name);
|
||||||
new_cfg->getch = (int (*)(void *)) cfg_getch;
|
new_cfg->getch = cfg_getch;
|
||||||
new_cfg->getstr = (void *(*)(void *, size_t, void *)) cfg_getstr;
|
new_cfg->getstr = cfg_getstr;
|
||||||
new_cfg->close = (int (*)(void *)) cfg_close;
|
new_cfg->close = cfg_close;
|
||||||
new_cfg->line_number = 0;
|
new_cfg->line_number = 0;
|
||||||
*ret_cfg = new_cfg;
|
*ret_cfg = new_cfg;
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
@@ -874,170 +864,156 @@ AP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg,
|
|||||||
|
|
||||||
|
|
||||||
/* Allocate a ap_configfile_t handle with user defined functions and params */
|
/* Allocate a ap_configfile_t handle with user defined functions and params */
|
||||||
AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(apr_pool_t *p,
|
AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(
|
||||||
const char *descr,
|
apr_pool_t *p, const char *descr, void *param,
|
||||||
void *param,
|
apr_status_t (*getc_func) (char *ch, void *param),
|
||||||
int(*getch)(void *param),
|
apr_status_t (*gets_func) (void *buf, size_t bufsize, void *param),
|
||||||
void *(*getstr) (void *buf, size_t bufsiz, void *param),
|
apr_status_t (*close_func) (void *param))
|
||||||
int(*close_func)(void *param))
|
|
||||||
{
|
{
|
||||||
ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg));
|
ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg));
|
||||||
#ifdef DEBUG
|
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
|
|
||||||
"Opening config handler %s", descr);
|
|
||||||
#endif
|
|
||||||
new_cfg->param = param;
|
new_cfg->param = param;
|
||||||
new_cfg->name = descr;
|
new_cfg->name = descr;
|
||||||
new_cfg->getch = getch;
|
new_cfg->getch = getc_func;
|
||||||
new_cfg->getstr = getstr;
|
new_cfg->getstr = gets_func;
|
||||||
new_cfg->close = close_func;
|
new_cfg->close = close_func;
|
||||||
new_cfg->line_number = 0;
|
new_cfg->line_number = 0;
|
||||||
return new_cfg;
|
return new_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read one character from a configfile_t */
|
/* Read one character from a configfile_t */
|
||||||
AP_DECLARE(int) ap_cfg_getc(ap_configfile_t *cfp)
|
AP_DECLARE(apr_status_t) ap_cfg_getc(char *ch, ap_configfile_t *cfp)
|
||||||
{
|
{
|
||||||
register int ch = cfp->getch(cfp->param);
|
apr_status_t rc = cfp->getch(ch, cfp->param);
|
||||||
if (ch == LF)
|
if (rc == APR_SUCCESS && *ch == LF)
|
||||||
++cfp->line_number;
|
++cfp->line_number;
|
||||||
return ch;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
AP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp,
|
||||||
|
apr_status_t rc)
|
||||||
|
{
|
||||||
|
char buf[MAX_STRING_LEN];
|
||||||
|
if (rc == APR_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
return apr_psprintf(p, "Error reading %s at line %d: %s",
|
||||||
|
cfp->name, cfp->line_number,
|
||||||
|
rc == APR_ENOSPC ? "Line too long"
|
||||||
|
: apr_strerror(rc, buf, sizeof(buf)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read one line from open ap_configfile_t, strip LF, increase line number */
|
/* Read one line from open ap_configfile_t, strip LF, increase line number */
|
||||||
/* If custom handler does not define a getstr() function, read char by char */
|
/* If custom handler does not define a getstr() function, read char by char */
|
||||||
AP_DECLARE(int) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t *cfp)
|
AP_DECLARE(apr_status_t) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t *cfp)
|
||||||
{
|
{
|
||||||
|
apr_status_t rc;
|
||||||
|
char *src, *dst;
|
||||||
/* If a "get string" function is defined, use it */
|
/* If a "get string" function is defined, use it */
|
||||||
if (cfp->getstr != NULL) {
|
if (cfp->getstr != NULL) {
|
||||||
char *src, *dst;
|
|
||||||
char *cp;
|
char *cp;
|
||||||
char *cbuf = buf;
|
char *cbuf = buf;
|
||||||
size_t cbufsize = bufsize;
|
size_t cbufsize = bufsize;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
++cfp->line_number;
|
++cfp->line_number;
|
||||||
if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL)
|
rc = cfp->getstr(cbuf, cbufsize, cfp->param);
|
||||||
return 1;
|
if (rc == APR_EOF) {
|
||||||
|
if (cbuf != buf) {
|
||||||
|
*cbuf = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return APR_EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rc != APR_SUCCESS) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check for line continuation,
|
* check for line continuation,
|
||||||
* i.e. match [^\\]\\[\r]\n only
|
* i.e. match [^\\]\\[\r]\n only
|
||||||
*/
|
*/
|
||||||
cp = cbuf;
|
cp = cbuf;
|
||||||
while (cp < cbuf+cbufsize && *cp != '\0')
|
cp += strlen(cp);
|
||||||
cp++;
|
|
||||||
if (cp > cbuf && cp[-1] == LF) {
|
if (cp > cbuf && cp[-1] == LF) {
|
||||||
cp--;
|
cp--;
|
||||||
if (cp > cbuf && cp[-1] == CR)
|
if (cp > cbuf && cp[-1] == CR)
|
||||||
cp--;
|
cp--;
|
||||||
if (cp > cbuf && cp[-1] == '\\') {
|
if (cp > cbuf && cp[-1] == '\\') {
|
||||||
cp--;
|
cp--;
|
||||||
if (!(cp > cbuf && cp[-1] == '\\')) {
|
/*
|
||||||
/*
|
* line continuation requested -
|
||||||
* line continuation requested -
|
* then remove backslash and continue
|
||||||
* then remove backslash and continue
|
*/
|
||||||
*/
|
cbufsize -= (cp-cbuf);
|
||||||
cbufsize -= (cp-cbuf);
|
cbuf = cp;
|
||||||
cbuf = cp;
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* no real continuation because escaped -
|
|
||||||
* then just remove escape character
|
|
||||||
*/
|
|
||||||
for ( ; cp < cbuf+cbufsize && *cp != '\0'; cp++)
|
|
||||||
cp[0] = cp[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (cp - buf >= bufsize - 1) {
|
||||||
|
return APR_ENOSPC;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Leading and trailing white space is eliminated completely
|
|
||||||
*/
|
|
||||||
src = buf;
|
|
||||||
while (apr_isspace(*src))
|
|
||||||
++src;
|
|
||||||
/* blast trailing whitespace */
|
|
||||||
dst = &src[strlen(src)];
|
|
||||||
while (--dst >= src && apr_isspace(*dst))
|
|
||||||
*dst = '\0';
|
|
||||||
/* Zap leading whitespace by shifting */
|
|
||||||
if (src != buf)
|
|
||||||
for (dst = buf; (*dst++ = *src++) != '\0'; )
|
|
||||||
;
|
|
||||||
|
|
||||||
#ifdef DEBUG_CFG_LINES
|
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "Read config: %s", buf);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* No "get string" function defined; read character by character */
|
/* No "get string" function defined; read character by character */
|
||||||
register int c;
|
size_t i = 0;
|
||||||
register size_t i = 0;
|
|
||||||
|
|
||||||
buf[0] = '\0';
|
if (bufsize < 2) {
|
||||||
/* skip leading whitespace */
|
|
||||||
do {
|
|
||||||
c = cfp->getch(cfp->param);
|
|
||||||
} while (c == '\t' || c == ' ');
|
|
||||||
|
|
||||||
if (c == EOF)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if(bufsize < 2) {
|
|
||||||
/* too small, assume caller is crazy */
|
/* too small, assume caller is crazy */
|
||||||
return 1;
|
return APR_EINVAL;
|
||||||
}
|
}
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if ((c == '\t') || (c == ' ')) {
|
char c;
|
||||||
buf[i++] = ' ';
|
rc = cfp->getch(&c, cfp->param);
|
||||||
while ((c == '\t') || (c == ' '))
|
if (rc == APR_EOF) {
|
||||||
c = cfp->getch(cfp->param);
|
if (i > 0)
|
||||||
}
|
break;
|
||||||
if (c == CR) {
|
else
|
||||||
/* silently ignore CR (_assume_ that a LF follows) */
|
return APR_EOF;
|
||||||
c = cfp->getch(cfp->param);
|
|
||||||
}
|
}
|
||||||
|
if (rc != APR_SUCCESS)
|
||||||
|
return rc;
|
||||||
if (c == LF) {
|
if (c == LF) {
|
||||||
/* increase line number and return on LF */
|
|
||||||
++cfp->line_number;
|
++cfp->line_number;
|
||||||
}
|
/* check for line continuation */
|
||||||
if (c == EOF || c == 0x4 || c == LF || i >= (bufsize - 2)) {
|
|
||||||
/*
|
|
||||||
* check for line continuation
|
|
||||||
*/
|
|
||||||
if (i > 0 && buf[i-1] == '\\') {
|
if (i > 0 && buf[i-1] == '\\') {
|
||||||
i--;
|
i--;
|
||||||
if (!(i > 0 && buf[i-1] == '\\')) {
|
continue;
|
||||||
/* line is continued */
|
|
||||||
c = cfp->getch(cfp->param);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* else nothing needs be done because
|
|
||||||
* then the backslash is escaped and
|
|
||||||
* we just strip to a single one
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
/* blast trailing whitespace */
|
else {
|
||||||
while (i > 0 && apr_isspace(buf[i - 1]))
|
break;
|
||||||
--i;
|
}
|
||||||
buf[i] = '\0';
|
}
|
||||||
#ifdef DEBUG_CFG_LINES
|
else if (i >= bufsize - 2) {
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
|
return APR_ENOSPC;
|
||||||
"Read config: %s", buf);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
buf[i] = c;
|
buf[i] = c;
|
||||||
++i;
|
++i;
|
||||||
c = cfp->getch(cfp->param);
|
|
||||||
}
|
}
|
||||||
|
buf[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Leading and trailing white space is eliminated completely
|
||||||
|
*/
|
||||||
|
src = buf;
|
||||||
|
while (apr_isspace(*src))
|
||||||
|
++src;
|
||||||
|
/* blast trailing whitespace */
|
||||||
|
dst = &src[strlen(src)];
|
||||||
|
while (--dst >= src && apr_isspace(*dst))
|
||||||
|
*dst = '\0';
|
||||||
|
/* Zap leading whitespace by shifting */
|
||||||
|
if (src != buf)
|
||||||
|
memmove(buf, src, dst - src + 2);
|
||||||
|
|
||||||
|
#ifdef DEBUG_CFG_LINES
|
||||||
|
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "Read config: '%s'", buf);
|
||||||
|
#endif
|
||||||
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Size an HTTP header field list item, as separated by a comma.
|
/* Size an HTTP header field list item, as separated by a comma.
|
||||||
|
Reference in New Issue
Block a user