📄 mod_include.c
字号:
else if (leave_name) { val = p; len = ep - p; } if (val && len) { if (out) { memcpy(out, val, (out+len <= eout) ? len : (eout-out)); out += len; } else { current->len = len; current->string = val; outlen += len; } } p = newp; } } if ((out && out >= eout) || (length && outlen >= length)) { break; } /* check the remainder */ if (*p && (span = strcspn(p, "\\$")) > 0) { if (!out && current->len) { current->next = apr_palloc(ctx->dpool, sizeof(*current->next)); current = current->next; current->next = NULL; } if (out) { memcpy(out, p, (out+span <= eout) ? span : (eout-out)); out += span; } else { current->len = span; current->string = p; outlen += span; } p += span; } } while (p < in+inlen); /* assemble result */ if (out) { if (out > eout) { *eout = '\0'; } else { *out = '\0'; } } else { const char *ep; if (length && outlen > length) { outlen = length - 1; } ret = out = apr_palloc(ctx->pool, outlen + 1); ep = ret + outlen; do { if (result->len) { memcpy(out, result->string, (out+result->len <= ep) ? result->len : (ep-out)); out += result->len; } result = result->next; } while (result && out < ep); ret[outlen] = '\0'; } return ret;}/* * +-------------------------------------------------------+ * | | * | Conditional Expression Parser * | | * +-------------------------------------------------------+ */static APR_INLINE int re_check(include_ctx_t *ctx, const char *string, const char *rexp){ ap_regex_t *compiled; backref_t *re = ctx->intern->re; int rc; compiled = ap_pregcomp(ctx->dpool, rexp, AP_REG_EXTENDED); if (!compiled) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->intern->r, "unable to " "compile pattern \"%s\"", rexp); return -1; } if (!re) { re = ctx->intern->re = apr_palloc(ctx->pool, sizeof(*re)); } re->source = apr_pstrdup(ctx->pool, string); re->rexp = apr_pstrdup(ctx->pool, rexp); re->nsub = compiled->re_nsub; rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0); ap_pregfree(ctx->dpool, compiled); return rc;}static int get_ptoken(include_ctx_t *ctx, const char **parse, token_t *token, token_t *previous){ const char *p; apr_size_t shift; int unmatched; token->value = NULL; if (!*parse) { return 0; } /* Skip leading white space */ while (apr_isspace(**parse)) { ++*parse; } if (!**parse) { *parse = NULL; return 0; } TYPE_TOKEN(token, TOKEN_STRING); /* the default type */ p = *parse; unmatched = 0; switch (*(*parse)++) { case '(': TYPE_TOKEN(token, TOKEN_LBRACE); return 0; case ')': TYPE_TOKEN(token, TOKEN_RBRACE); return 0; case '=': if (**parse == '=') ++*parse; TYPE_TOKEN(token, TOKEN_EQ); return 0; case '!': if (**parse == '=') { TYPE_TOKEN(token, TOKEN_NE); ++*parse; return 0; } TYPE_TOKEN(token, TOKEN_NOT); return 0; case '\'': unmatched = '\''; break; case '/': /* if last token was ACCESS, this token is STRING */ if (previous != NULL && TOKEN_ACCESS == previous->type) { break; } TYPE_TOKEN(token, TOKEN_RE); unmatched = '/'; break; case '|': if (**parse == '|') { TYPE_TOKEN(token, TOKEN_OR); ++*parse; return 0; } break; case '&': if (**parse == '&') { TYPE_TOKEN(token, TOKEN_AND); ++*parse; return 0; } break; case '>': if (**parse == '=') { TYPE_TOKEN(token, TOKEN_GE); ++*parse; return 0; } TYPE_TOKEN(token, TOKEN_GT); return 0; case '<': if (**parse == '=') { TYPE_TOKEN(token, TOKEN_LE); ++*parse; return 0; } TYPE_TOKEN(token, TOKEN_LT); return 0; case '-': if (**parse == 'A' && (ctx->intern->accessenable)) { TYPE_TOKEN(token, TOKEN_ACCESS); ++*parse; return 0; } break; } /* It's a string or regex token * Now search for the next token, which finishes this string */ shift = 0; p = *parse = token->value = unmatched ? *parse : p; for (; **parse; p = ++*parse) { if (**parse == '\\') { if (!*(++*parse)) { p = *parse; break; } ++shift; } else { if (unmatched) { if (**parse == unmatched) { unmatched = 0; ++*parse; break; } } else if (apr_isspace(**parse)) { break; } else { int found = 0; switch (**parse) { case '(': case ')': case '=': case '!': case '<': case '>': ++found; break; case '|': case '&': if ((*parse)[1] == **parse) { ++found; } break; } if (found) { break; } } } } if (unmatched) { token->value = apr_pstrdup(ctx->dpool, ""); } else { apr_size_t len = p - token->value - shift; char *c = apr_palloc(ctx->dpool, len + 1); p = token->value; token->value = c; while (shift--) { const char *e = ap_strchr_c(p, '\\'); memcpy(c, p, e-p); c += e-p; *c++ = *++e; len -= e-p; p = e+1; } if (len) { memcpy(c, p, len); } c[len] = '\0'; } return unmatched;}static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error){ parse_node_t *new, *root = NULL, *current = NULL; request_rec *r = ctx->intern->r; request_rec *rr = NULL; const char *error = "Invalid expression \"%s\" in file %s"; const char *parse = expr; int was_unmatched = 0; unsigned regex = 0; *was_error = 0; if (!parse) { return 0; } /* Create Parse Tree */ while (1) { /* uncomment this to see how the tree a built: * * DEBUG_DUMP_TREE(ctx, root); */ CREATE_NODE(ctx, new); was_unmatched = get_ptoken(ctx, &parse, &new->token, (current != NULL ? ¤t->token : NULL)); if (!parse) { break; } DEBUG_DUMP_UNMATCHED(ctx, was_unmatched); DEBUG_DUMP_TOKEN(ctx, &new->token); if (!current) { switch (new->token.type) { case TOKEN_STRING: case TOKEN_NOT: case TOKEN_ACCESS: case TOKEN_LBRACE: root = current = new; continue; default: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, expr, r->filename); *was_error = 1; return 0; } } switch (new->token.type) { case TOKEN_STRING: switch (current->token.type) { case TOKEN_STRING: current->token.value = apr_pstrcat(ctx->dpool, current->token.value, *current->token.value ? " " : "", new->token.value, NULL); continue; case TOKEN_RE: case TOKEN_RBRACE: case TOKEN_GROUP: break; default: new->parent = current; current = current->right = new; continue; } break; case TOKEN_RE: switch (current->token.type) { case TOKEN_EQ: case TOKEN_NE: new->parent = current; current = current->right = new; ++regex; continue; default: break; } break; case TOKEN_AND: case TOKEN_OR: switch (current->token.type) { case TOKEN_STRING: case TOKEN_RE: case TOKEN_GROUP: current = current->parent; while (current) { switch (current->token.type) { case TOKEN_AND: case TOKEN_OR: case TOKEN_LBRACE: break; default: current = current->parent; continue; } break; } if (!current) { new->left = root; root->parent = new; current = root = new; continue; } new->left = current->right; new->left->parent = new; new->parent = current; current = current->right = new; continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -