Modules may register additional unary operators.</p>
<table class="bordered"><tr class="header"><th>Name</th><th>Description</th></tr>
-<tr><td><code>-n</code></td>
+<tr><td><code>-d</code></td>
+ <td>True if file exists and is a directory</td></tr>
+<tr class="odd"><td><code>-e</code></td>
+ <td>True if file (or dir or special) exists</td></tr>
+<tr><td><code>-f</code></td>
+ <td>True if file exists and is regular file</td></tr>
+<tr class="odd"><td><code>-L</code></td>
+ <td>True if file exists and is symlink</td></tr>
+<tr><td><code>-h</code></td>
+ <td>True if file exists and is symlink (same as <code>-L</code>)</td></tr>
+<tr class="odd"><td><code>-n</code></td>
<td>True if string is not empty</td></tr>
-<tr class="odd"><td><code>-z</code></td>
+<tr><td><code>-z</code></td>
<td>True if string is empty</td></tr>
-<tr><td><code>-T</code></td>
+<tr class="odd"><td><code>-T</code></td>
<td>False if string is empty, "<code>0</code>", "<code>off</code>",
"<code>false</code>", or "<code>no</code>" (case insensitive).
True otherwise.</td></tr>
-<tr class="odd"><td><code>-R</code></td>
+<tr><td><code>-R</code></td>
<td>Same as "<code>%{REMOTE_ADDR} -ipmatch ...</code>", but more efficient
</td></tr>
</table>
<td>Unescape %hex encoded string, leaving URL-special characters encoded (XXX: describe better)</td></tr>
<tr><td><code>file</code></td>
<td>Read contents from a file</td></tr>
+<tr class="odd"><td><code>filesize</code></td>
+ <td>Return size of a file (or 0 if file does not exist or is not regular file)</td></tr>
</table>
<p>In addition to string-valued functions, there are also list-valued functions which
<columnspec><column width=".2"/><column width=".2"/><column width=".6"/></columnspec>
<tr><th>Name</th><th>Description</th></tr>
+ <tr><td><code>-d</code></td>
+ <td>True if file exists and is a directory</td></tr>
+ <tr><td><code>-e</code></td>
+ <td>True if file (or dir or special) exists</td></tr>
+ <tr><td><code>-f</code></td>
+ <td>True if file exists and is regular file</td></tr>
+ <tr><td><code>-L</code></td>
+ <td>True if file exists and is symlink</td></tr>
+ <tr><td><code>-h</code></td>
+ <td>True if file exists and is symlink (same as <code>-L</code>)</td></tr>
<tr><td><code>-n</code></td>
<td>True if string is not empty</td></tr>
<tr><td><code>-z</code></td>
<td>Unescape %hex encoded string, leaving URL-special characters encoded (XXX: describe better)</td></tr>
<tr><td><code>file</code></td>
<td>Read contents from a file</td></tr>
+ <tr><td><code>filesize</code></td>
+ <td>Return size of a file (or 0 if file does not exist or is not regular file)</td></tr>
+
</table>
<p>In addition to string-valued functions, there are also list-valued functions which
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)
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;
{ 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 }
};