From 17651e0c9af48c34f857ae7126d2cf348779d1f3 Mon Sep 17 00:00:00 2001 From: Stefan Fritsch Date: Sat, 14 May 2011 13:22:11 +0000 Subject: [PATCH] Add various file existance test operators to ap_expr git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1103097 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 ++ docs/manual/expr.html.en | 20 +++++++++--- docs/manual/expr.xml | 13 ++++++++ server/util_expr_eval.c | 70 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 2cd9baa971..e5bba159d7 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.3.13 + *) core: Add various file existance test operators to ap_expr. + [Stefan Fritsch] + *) mod_proxy_express: New mass reverse-proxy switch extension for mod_proxy. [Jim Jagielski] diff --git a/docs/manual/expr.html.en b/docs/manual/expr.html.en index 6fc51f6b30..f0e9c20775 100644 --- a/docs/manual/expr.html.en +++ b/docs/manual/expr.html.en @@ -324,15 +324,25 @@ listfunction ::= listfuncname "(" word ")" Modules may register additional unary operators.

- + + + + + + + + + + + - + - + - +
NameDescription
-n
-dTrue if file exists and is a directory
-eTrue if file (or dir or special) exists
-fTrue if file exists and is regular file
-LTrue if file exists and is symlink
-hTrue if file exists and is symlink (same as -L)
-n True if string is not empty
-z
-z True if string is empty
-T
-T False if string is empty, "0", "off", "false", or "no" (case insensitive). True otherwise.
-R
-R Same as "%{REMOTE_ADDR} -ipmatch ...", but more efficient
@@ -370,6 +380,8 @@ listfunction ::= listfuncname "(" word ")" Unescape %hex encoded string, leaving URL-special characters encoded (XXX: describe better) file Read contents from a file +filesize + Return size of a file (or 0 if file does not exist or is not regular file)

In addition to string-valued functions, there are also list-valued functions which diff --git a/docs/manual/expr.xml b/docs/manual/expr.xml index ea9a182929..bc2604e82c 100644 --- a/docs/manual/expr.xml +++ b/docs/manual/expr.xml @@ -347,6 +347,16 @@ listfunction ::= listfuncname "(" word ")" NameDescription + -d + True if file exists and is a directory + -e + True if file (or dir or special) exists + -f + True if file exists and is regular file + -L + True if file exists and is symlink + -h + True if file exists and is symlink (same as -L) -n True if string is not empty -z @@ -396,6 +406,9 @@ listfunction ::= listfuncname "(" word ")" Unescape %hex encoded string, leaving URL-special characters encoded (XXX: describe better) file Read contents from a file + filesize + Return size of a file (or 0 if file does not exist or is not regular file) +

In addition to string-valued functions, there are also list-valued functions which diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c index 9a1c80d13c..57a328b18f 100644 --- a/server/util_expr_eval.c +++ b/server/util_expr_eval.c @@ -872,6 +872,16 @@ static const char *file_func(ap_expr_eval_ctx_t *ctx, const void *data, return buf; } +static const char *filesize_func(ap_expr_eval_ctx_t *ctx, const void *data, + char *arg) +{ + apr_finfo_t sb; + if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) == APR_SUCCESS + && sb.filetype == APR_REG && sb.size > 0) + return apr_psprintf(ctx->p, "%" APR_OFF_T_FMT, sb.size); + else + return "0"; +} static const char *unescape_func(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg) @@ -893,6 +903,50 @@ static int op_nz(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg) return (arg[0] != '\0'); } +static int op_file_min(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg) +{ + apr_finfo_t sb; + const char *name = (const char *)data; + if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) != APR_SUCCESS) + return 0; + switch (name[0]) { + case 'd': + return (sb.filetype == APR_DIR); + case 'e': + return 1; + case 'f': + return (sb.filetype == APR_REG); + case 's': + return (sb.filetype == APR_REG && sb.size > 0); + default: + ap_assert(0); + } + return 0; +} + +static int op_file_link(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg) +{ + apr_finfo_t sb; +#if !defined(OS2) + if (apr_stat(&sb, arg, APR_FINFO_MIN | APR_FINFO_LINK, ctx->p) == APR_SUCCESS + && sb.filetype == APR_LNK) { + return 1; + } +#endif + return 0; +} + +static int op_file_xbit(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg) +{ + apr_finfo_t sb; + if (apr_stat(&sb, arg, APR_FINFO_PROT| APR_FINFO_LINK, ctx->p) == APR_SUCCESS + && (sb.protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE))) { + return 1; + } + return 0; +} + + APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *)); static APR_OPTIONAL_FN_TYPE(ssl_is_https) *is_https = NULL; @@ -1255,15 +1309,23 @@ static const struct expr_provider_single string_func_providers[] = { { escape_func, "escape", NULL }, { unescape_func, "unescape", NULL }, { file_func, "file", NULL }, + { filesize_func, "filesize", NULL }, { NULL, NULL, NULL} }; /* XXX: base64 encode/decode ? */ static const struct expr_provider_single unary_op_providers[] = { - { op_nz, "n", NULL }, - { op_nz, "z", NULL }, - { op_R, "R", subnet_parse_arg }, - { op_T, "T", NULL }, + { op_nz, "n", NULL }, + { op_nz, "z", NULL }, + { op_R, "R", subnet_parse_arg }, + { op_T, "T", NULL }, + { op_file_min, "d", NULL }, + { op_file_min, "e", NULL }, + { op_file_min, "f", NULL }, + { op_file_min, "s", NULL }, + { op_file_link, "L", NULL }, + { op_file_link, "h", NULL }, + { op_file_xbit, "x", NULL }, { NULL, NULL, NULL } }; -- 2.40.0