Module: sip-router Branch: master Commit: 0c830402b517f3e4194dd28b0383e57b8a803d21 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0c830402...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Mon Dec 19 22:08:57 2011 +0100
textopsx: added fnmatch(value, expr, flags) function
- shell-style pattern matching (via file selection wildcards), using C function fnmatch()
---
modules/textopsx/README | 20 +++++++++ modules/textopsx/doc/functions.xml | 29 ++++++++++++ modules/textopsx/textopsx.c | 84 +++++++++++++++++++++++++++++++++++- 3 files changed, 131 insertions(+), 2 deletions(-)
diff --git a/modules/textopsx/README b/modules/textopsx/README index d4e51e8..104638a 100644 --- a/modules/textopsx/README +++ b/modules/textopsx/README @@ -19,6 +19,7 @@ Daniel-Constantin Mierla 1.2.2. change_reply_status(code, reason) 1.2.3. remove_body() 1.2.4. keep_hf(regexp) + 1.2.5. fnmatch(value, expr [, flags])
1.1. Overview
@@ -95,3 +96,22 @@ remove_body(); ... keep_hf("User-Agent"); ... + +1.2.5. fnmatch(value, expr [, flags]) + + Match the value against the expr using the shell-style pattern for file + name matching (see man page for C function fnmatch()). It is known to + be faster and uses less-memory than regexp. + + Parameters flags is optional and can be 'i' to do case insensitive + matching. + + This function can be used from ANY_ROUTE. + + Example 5. fnmatch() usage +... +if(fnmatch("$rU", "123*")) +{ + ... +} +... diff --git a/modules/textopsx/doc/functions.xml b/modules/textopsx/doc/functions.xml index eec3144..ab4eb06 100644 --- a/modules/textopsx/doc/functions.xml +++ b/modules/textopsx/doc/functions.xml @@ -117,4 +117,33 @@ keep_hf("User-Agent"); </example> </section>
+ <section id="textopsx.fnmatch"> + <title> + <function moreinfo="none">fnmatch(value, expr [, flags])</function> + </title> + <para> + Match the value against the expr using the shell-style pattern + for file name matching (see man page for C function fnmatch()). + It is known to be faster and uses less-memory than regexp. + </para> + <para> + Parameters flags is optional and can be 'i' to do case insensitive + matching. + </para> + <para> + This function can be used from ANY_ROUTE. + </para> + <example> + <title><function>fnmatch()</function> usage</title> + <programlisting format="linespecific"> +... +if(fnmatch("$rU", "123*")) +{ + ... +} +... +</programlisting> + </example> + </section> + </section> diff --git a/modules/textopsx/textopsx.c b/modules/textopsx/textopsx.c index 687cce4..7dddf8b 100644 --- a/modules/textopsx/textopsx.c +++ b/modules/textopsx/textopsx.c @@ -27,6 +27,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <fnmatch.h>
#include "../../sr_module.h" #include "../../dprint.h" @@ -40,10 +41,14 @@ MODULE_VERSION
static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2);
-static int change_reply_status_f(struct sip_msg*, char*, char *); +static int change_reply_status_f(sip_msg_t*, char*, char*); static int change_reply_status_fixup(void** param, int param_no);
-static int w_keep_hf_f(struct sip_msg*, char*, char *); +static int w_keep_hf_f(sip_msg_t*, char*, char*); + +static int w_fnmatch2_f(sip_msg_t*, char*, char*); +static int w_fnmatch3_f(sip_msg_t*, char*, char*, char*); +static int fixup_fnmatch(void** param, int param_no);
static int w_remove_body_f(struct sip_msg*, char*, char *); static int bind_textopsx(textopsx_api_t *tob); @@ -58,6 +63,10 @@ static cmd_export_t cmds[] = { 0, ANY_ROUTE }, {"keep_hf", (cmd_function)w_keep_hf_f, 1, fixup_regexp_null, ANY_ROUTE }, + {"fnmatch", (cmd_function)w_fnmatch2_f, 2, + fixup_fnmatch, ANY_ROUTE }, + {"fnmatch", (cmd_function)w_fnmatch3_f, 3, + fixup_fnmatch, ANY_ROUTE }, {"bind_textopsx", (cmd_function)bind_textopsx, 1, 0, ANY_ROUTE },
@@ -323,6 +332,77 @@ static int w_keep_hf_f(struct sip_msg* msg, char* key, char* foo) return -1; }
+/** + * + */ +static int w_fnmatch(str *val, str *match, str *flags) +{ + int i; + i = 0; +#ifdef FNM_CASEFOLD + if(flags && (flags->s[0]=='i' || flags->s[0]=='I')) + i = FNM_CASEFOLD; +#endif + if(fnmatch(match->s, val->s, i)==0) + return 0; + return -1; +} + +/** + * + */ +static int w_fnmatch2_f(sip_msg_t *msg, char *val, char *match) +{ + str sval; + str smatch; + if(get_str_fparam(&sval, msg, (fparam_t*)val)<0 + || get_str_fparam(&smatch, msg, (fparam_t*)match)<0) + { + LM_ERR("invalid parameters"); + return -1; + } + if(w_fnmatch(&sval, &smatch, NULL)<0) + return -1; + return 1; +} + +/** + * + */ +static int w_fnmatch3_f(sip_msg_t *msg, char *val, char *match, char *flags) +{ + str sval; + str smatch; + str sflags; + if(get_str_fparam(&sval, msg, (fparam_t*)val)<0 + || get_str_fparam(&smatch, msg, (fparam_t*)match)<0 + || get_str_fparam(&sflags, msg, (fparam_t*)flags)<0) + { + LM_ERR("invalid parameters"); + return -1; + } + if(w_fnmatch(&sval, &smatch, &sflags)<0) + return -1; + return 1; +} + +/** + * + */ +static int fixup_fnmatch(void** param, int param_no) +{ + if (param_no == 1) { + return fixup_var_pve_12(param, param_no); + } else if (param_no == 2) { + return fixup_var_pve_12(param, param_no); + } else if (param_no == 3) { + return fixup_var_pve_12(param, param_no); + } else { + return 0; + } + +} + /* * Function to load the textops api. */
Daniel-Constantin Mierla writes:
+if(fnmatch("$rU", "123*"))
daniel,
would this be the same as starts_with("$rU", "123")? if so, i suspect that starts_with would be even faster.
if i write
if(fnmatch("$rU", "*123")) ...
would match require that $rU ends with 123?
-- juha
Hello,
On 12/20/11 12:15 PM, Juha Heinanen wrote:
Daniel-Constantin Mierla writes:
+if(fnmatch("$rU", "123*"))
daniel,
would this be the same as starts_with("$rU", "123")? if so, i suspect that starts_with would be even faster.
perhaps starts_with() is faster for this case.
if i write
if(fnmatch("$rU", "*123")) ...
would match require that $rU ends with 123?
yes. Practically fnmatch uses the shell-like pattern matching, which is used for example with 'ls' command. You can have wildcards like * or ? at any position in the value, not only start or end. fnmatch is present as operator for quite long time in avpops/avp_check() and might be handy when needing to do such simple matching instead of using full regexp.
Cheers, Daniel