typedef struct {
const char *default_error_msg;
const char *default_time_fmt;
+ const char *undefined_echo;
xbithack_t xbithack;
} include_dir_config;
typedef struct {
const char *default_start_tag;
const char *default_end_tag;
- const char *undefined_echo;
- apr_size_t undefined_echo_len;
} include_server_config;
/* main parser states */
backref_t *re; /* NULL if there wasn't a regex yet */
+ const char *undefined_echo;
+ apr_size_t undefined_echo_len;
+
#ifdef DEBUG_INCLUDE
struct {
ap_filter_t *f;
val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0);
}
else if (!strcasecmp(var, "USER_NAME")) {
- if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
+ if (apr_uid_name_get(&val, r->finfo.user, r->pool) != APR_SUCCESS) {
val = "<unknown>";
}
}
TYPE_TOKEN(token, TOKEN_RBRACE);
return 0;
case '=':
+ if (**parse == '=') ++*parse;
TYPE_TOKEN(token, TOKEN_EQ);
return 0;
case '!':
{
parse_node_t *new, *root = NULL, *current = NULL;
request_rec *r = ctx->intern->r;
- const char* buffer;
+ const char *error = "Invalid expression \"%s\" in file %s";
const char *parse = expr;
- int retval = 0, was_unmatched = 0;
+ int was_unmatched = 0;
unsigned regex = 0;
*was_error = 0;
continue;
default:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,
+ r->filename);
*was_error = 1;
- return retval;
+ return 0;
}
}
apr_pstrcat(ctx->dpool, current->token.value,
*current->token.value ? " " : "",
new->token.value, NULL);
- break;
+ continue;
case TOKEN_RE:
case TOKEN_RBRACE:
case TOKEN_GROUP:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
+ break;
default:
new->parent = current;
current = current->right = new;
- break;
+ continue;
}
break;
new->parent = current;
current = current->right = new;
++regex;
- break;
+ continue;
default:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
+ break;
}
break;
case TOKEN_AND:
case TOKEN_OR:
- /* Percolate upwards */
- while (current) {
- switch (current->token.type) {
- case TOKEN_LBRACE:
- break;
+ switch (current->token.type) {
+ case TOKEN_STRING:
+ case TOKEN_RE:
+ case TOKEN_GROUP:
+ current = current->parent;
- case TOKEN_RBRACE:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
+ while (current) {
+ switch (current->token.type) {
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_LBRACE:
+ break;
- default:
- current = current->parent;
- continue;
+ default:
+ current = current->parent;
+ continue;
+ }
+ break;
}
- break;
- }
- if (!current) {
- new->left = root;
- new->left->parent = new;
- new->parent = NULL;
- root = new;
- }
- else {
+ if (!current) {
+ new->left = root;
+ root->parent = new;
+ current = root = new;
+ continue;
+ }
+
new->left = current->right;
new->left->parent = new;
- current->right = new;
new->parent = current;
+ current = current->right = new;
+ continue;
+
+ default:
+ break;
}
- current = new;
break;
case TOKEN_EQ:
break;
}
}
-
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
+ break;
case TOKEN_RBRACE:
while (current && current->token.type != TOKEN_LBRACE) {
current = current->parent;
}
- if (!current) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Unmatched ')' in \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
+ if (current) {
+ TYPE_TOKEN(¤t->token, TOKEN_GROUP);
+ continue;
}
- TYPE_TOKEN(¤t->token, TOKEN_GROUP);
+ error = "Unmatched ')' in \"%s\" in file %s";
break;
case TOKEN_NOT:
case TOKEN_RE:
case TOKEN_RBRACE:
case TOKEN_GROUP:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
+ break;
default:
- break;
+ current->right = new;
+ new->parent = current;
+ current = new;
+ continue;
}
-
- current->right = new;
- new->parent = current;
- current = new;
break;
default:
break;
}
+
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr, r->filename);
+ *was_error = 1;
+ return 0;
}
DEBUG_DUMP_TREE(ctx, root);
/* Evaluate Parse Tree */
current = root;
+ error = NULL;
while (current) {
switch (current->token.type) {
case TOKEN_STRING:
- buffer = ap_ssi_parse_string(ctx, current->token.value, NULL, 0,
- SSI_EXPAND_DROP_NAME);
-
- current->token.value = buffer;
+ current->token.value =
+ ap_ssi_parse_string(ctx, current->token.value, NULL, 0,
+ SSI_EXPAND_DROP_NAME);
current->value = !!*current->token.value;
- DEBUG_DUMP_EVAL(ctx, current);
- current->done = 1;
- current = current->parent;
break;
- case TOKEN_RE:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "No operator before regex of expr \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
-
case TOKEN_AND:
case TOKEN_OR:
if (!current->left || !current->right) {
"Invalid expression \"%s\" in file %s",
expr, r->filename);
*was_error = 1;
- return retval;
+ return 0;
}
- if (!current->right->done) {
- switch (current->right->token.type) {
+ if (!current->left->done) {
+ switch (current->left->token.type) {
case TOKEN_STRING:
- buffer = ap_ssi_parse_string(ctx,
- current->right->token.value,
- NULL, 0, SSI_EXPAND_DROP_NAME);
-
- current->right->token.value = buffer;
- current->right->value = !!*current->right->token.value;
- DEBUG_DUMP_EVAL(ctx, current->right);
- current->right->done = 1;
+ current->left->token.value =
+ ap_ssi_parse_string(ctx, current->left->token.value,
+ NULL, 0, SSI_EXPAND_DROP_NAME);
+ current->left->value = !!*current->left->token.value;
+ DEBUG_DUMP_EVAL(ctx, current->left);
+ current->left->done = 1;
break;
default:
- current = current->right;
+ current = current->left;
continue;
}
}
/* short circuit evaluation */
- if (!current->left->done && !regex &&
- ((current->token.type == TOKEN_AND && !current->right->value) ||
- (current->token.type == TOKEN_OR && current->right->value))) {
- current->value = current->right->value;
+ if (!current->right->done && !regex &&
+ ((current->token.type == TOKEN_AND && !current->left->value) ||
+ (current->token.type == TOKEN_OR && current->left->value))) {
+ current->value = current->left->value;
}
else {
- if (!current->left->done) {
- switch (current->left->token.type) {
+ if (!current->right->done) {
+ switch (current->right->token.type) {
case TOKEN_STRING:
- buffer = ap_ssi_parse_string(ctx,
- current->left->token.value,
- NULL, 0,
- SSI_EXPAND_DROP_NAME);
-
- current->left->token.value = buffer;
- current->left->value = !!*current->left->token.value;
- DEBUG_DUMP_EVAL(ctx, current->left);
- current->left->done = 1;
+ current->right->token.value =
+ ap_ssi_parse_string(ctx,current->right->token.value,
+ NULL, 0, SSI_EXPAND_DROP_NAME);
+ current->right->value = !!*current->right->token.value;
+ DEBUG_DUMP_EVAL(ctx, current->right);
+ current->right->done = 1;
break;
default:
- current = current->left;
+ current = current->right;
continue;
}
}
current->right->value;
}
}
-
- DEBUG_DUMP_EVAL(ctx, current);
- current->done = 1;
- current = current->parent;
break;
case TOKEN_EQ:
"Invalid expression \"%s\" in file %s",
expr, r->filename);
*was_error = 1;
- return retval;
+ return 0;
}
- buffer = ap_ssi_parse_string(ctx, current->left->token.value,
- NULL, 0, SSI_EXPAND_DROP_NAME);
-
- current->left->token.value = buffer;
- buffer = ap_ssi_parse_string(ctx, current->right->token.value,
- NULL, 0, SSI_EXPAND_DROP_NAME);
-
- current->right->token.value = buffer;
+ current->left->token.value =
+ ap_ssi_parse_string(ctx, current->left->token.value, NULL, 0,
+ SSI_EXPAND_DROP_NAME);
+ current->right->token.value =
+ ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,
+ SSI_EXPAND_DROP_NAME);
if (current->right->token.type == TOKEN_RE) {
current->value = re_check(ctx, current->left->token.value,
if (current->token.type == TOKEN_NE) {
current->value = !current->value;
}
-
- DEBUG_DUMP_EVAL(ctx, current);
- current->done = 1;
- current = current->parent;
break;
case TOKEN_GE:
"Invalid expression \"%s\" in file %s",
expr, r->filename);
*was_error = 1;
- return retval;
+ return 0;
}
- buffer = ap_ssi_parse_string(ctx, current->left->token.value, NULL,
- 0, SSI_EXPAND_DROP_NAME);
- current->left->token.value = buffer;
- buffer = ap_ssi_parse_string(ctx, current->right->token.value, NULL,
- 0, SSI_EXPAND_DROP_NAME);
- current->right->token.value = buffer;
+ current->left->token.value =
+ ap_ssi_parse_string(ctx, current->left->token.value, NULL, 0,
+ SSI_EXPAND_DROP_NAME);
+ current->right->token.value =
+ ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0,
+ SSI_EXPAND_DROP_NAME);
current->value = strcmp(current->left->token.value,
current->right->token.value);
- if (current->token.type == TOKEN_GE) {
- current->value = current->value >= 0;
- }
- else if (current->token.type == TOKEN_GT) {
- current->value = current->value > 0;
- }
- else if (current->token.type == TOKEN_LE) {
- current->value = current->value <= 0;
- }
- else if (current->token.type == TOKEN_LT) {
- current->value = current->value < 0;
- }
- else {
- current->value = 0; /* Don't return -1 if unknown token */
+ switch (current->token.type) {
+ case TOKEN_GE: current->value = current->value >= 0; break;
+ case TOKEN_GT: current->value = current->value > 0; break;
+ case TOKEN_LE: current->value = current->value <= 0; break;
+ case TOKEN_LT: current->value = current->value < 0; break;
+ default: current->value = 0; break; /* should not happen */
}
-
- DEBUG_DUMP_EVAL(ctx, current);
- current->done = 1;
- current = current->parent;
break;
case TOKEN_NOT:
- if (current->right) {
- if (!current->right->done) {
- current = current->right;
- continue;
- }
- current->value = !current->right->value;
- }
- else {
- current->value = 0;
- }
-
- DEBUG_DUMP_EVAL(ctx, current);
- current->done = 1;
- current = current->parent;
- break;
-
case TOKEN_GROUP:
if (current->right) {
if (!current->right->done) {
current->value = 1;
}
- DEBUG_DUMP_EVAL(ctx, current);
- current->done = 1;
- current = current->parent;
+ if (current->token.type == TOKEN_NOT) {
+ current->value = !current->value;
+ }
break;
+ case TOKEN_RE:
+ if (!error) {
+ error = "No operator before regex in expr \"%s\" in file %s";
+ }
case TOKEN_LBRACE:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Unmatched '(' in \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- return retval;
-
+ if (!error) {
+ error = "Unmatched '(' in \"%s\" in file %s";
+ }
default:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "bad token type (internal parser error)");
+ if (!error) {
+ error = "internal parser error in \"%s\" in file %s";
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr,r->filename);
*was_error = 1;
- return retval;
+ return 0;
}
+
+ DEBUG_DUMP_EVAL(ctx, current);
+ current->done = 1;
+ current = current->parent;
}
return (root ? root->value : 0);
e_len = strlen(echo_text);
}
else {
- include_server_config *sconf;
-
- sconf = ap_get_module_config(r->server->module_config,
- &include_module);
- echo_text = sconf->undefined_echo;
- e_len = sconf->undefined_echo_len;
+ echo_text = ctx->intern->undefined_echo;
+ e_len = ctx->intern->undefined_echo_len;
}
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(
- apr_pstrmemdup(ctx->pool, echo_text, e_len),
+ apr_pmemdup(ctx->pool, echo_text, e_len),
e_len, ctx->pool, f->c->bucket_alloc));
}
else if (!strcmp(tag, "encoding")) {
}
/*
- * <!--#config [timefmt="..."] [sizefmt="..."] [errmsg="..."] -->
+ * <!--#config [timefmt="..."] [sizefmt="..."] [errmsg="..."]
+ * [echomsg="..."] -->
*/
static apr_status_t handle_config(include_ctx_t *ctx, ap_filter_t *f,
apr_bucket_brigade *bb)
while (1) {
char *tag = NULL;
char *tag_val = NULL;
- char *parsed_string;
ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, SSI_VALUE_RAW);
if (!tag || !tag_val) {
ctx->error_str = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
SSI_EXPAND_DROP_NAME);
}
+ else if (!strcmp(tag, "echomsg")) {
+ ctx->intern->undefined_echo =
+ ap_ssi_parse_string(ctx, tag_val, NULL, 0,SSI_EXPAND_DROP_NAME);
+ ctx->intern->undefined_echo_len=strlen(ctx->intern->undefined_echo);
+ }
else if (!strcmp(tag, "timefmt")) {
apr_time_t date = r->request_time;
ctx->time_str, 0));
}
else if (!strcmp(tag, "sizefmt")) {
+ char *parsed_string;
+
parsed_string = ap_ssi_parse_string(ctx, tag_val, NULL, 0,
SSI_EXPAND_DROP_NAME);
if (!strcmp(parsed_string, "bytes")) {
strlen(intern->start_seq));
intern->end_seq = sconf->default_end_tag;
intern->end_seq_len = strlen(intern->end_seq);
+ intern->undefined_echo = conf->undefined_echo;
+ intern->undefined_echo_len = strlen(conf->undefined_echo);
}
if ((parent = ap_get_module_config(r->request_config, &include_module))) {
result->default_error_msg = DEFAULT_ERROR_MSG;
result->default_time_fmt = DEFAULT_TIME_FORMAT;
+ result->undefined_echo = DEFAULT_UNDEFINED_ECHO;
result->xbithack = DEFAULT_XBITHACK;
return result;
result = apr_palloc(p, sizeof(include_server_config));
result->default_end_tag = DEFAULT_END_SEQUENCE;
result->default_start_tag = DEFAULT_START_SEQUENCE;
- result->undefined_echo = DEFAULT_UNDEFINED_ECHO;
- result->undefined_echo_len = sizeof(DEFAULT_UNDEFINED_ECHO) - 1;
return result;
}
static const char *set_undefined_echo(cmd_parms *cmd, void *mconfig,
const char *msg)
{
- include_server_config *conf;
-
- conf = ap_get_module_config(cmd->server->module_config, &include_module);
+ include_dir_config *conf = mconfig;
conf->undefined_echo = msg;
- conf->undefined_echo_len = strlen(msg);
return NULL;
}
"SSI Start String Tag"),
AP_INIT_TAKE1("SSIEndTag", set_default_end_tag, NULL, RSRC_CONF,
"SSI End String Tag"),
- AP_INIT_TAKE1("SSIUndefinedEcho", set_undefined_echo, NULL, RSRC_CONF,
+ AP_INIT_TAKE1("SSIUndefinedEcho", set_undefined_echo, NULL, OR_ALL,
"String to be displayed if an echoed variable is undefined"),
{NULL}
};