Hi list,

attached is a patch that adds regular expressions to the kannel configuration. With this feature, POSIX-style regular expressions can be used to specify white-lists etc. The implementation is rather straightforward, so I guess lengthy explanations are not necessary. All expressions are compiled once and then reused when needed, thus the performance tradeoff should be acceptable.

The new configuration parameteres can be used parallel to the other params (e.g. white-list and white-list-regex can both be used at the same time).
The new parameters are as follows
core: white-list-regex, black-list-regex
wap-push-user: allowed-prefix-regex,denied-prefix-regex,white-list-regex,black-list-regex
smsbox: white-list-regex,black-list-regex
smsc: allowed-smsc-id-regex, denied-smsc-id-regex,preferred-smsc-id-regex,allowed-prefix-regex,denied-prefix-regex,preferred-prefix-regex
sms-service: accepted-smsc-regex,allowed-prefix-regex,denied-prefix-regex,allowed-receiver-prefix-regex,denied-receiver-prefix-regex,white-list-regex,black-list-regex
sendsms-user: accepted-smsc-regex,allowed-prefix-regex,denied-prefix-regex,allowed-receiver-prefix-regex,denied-receiver-prefix-regex,white-list-regex,black-list-regex


Please try out the patch and drop me a line with your comments :)

--

Mit freundlichen Gruessen/Best regards

David Schmitz
Softwareentwicklung

-----------------------------------------------------------------
Wapme Systems AG
Vogelsanger Weg 80
40470 D�sseldorf

Tel.:  + 49 -211-7 48 45 - 2708
Fax:  + 49 -211-80-6-06-2801

E-Mail:   [EMAIL PROTECTED]
Internet: http://www.wapme-systems.de

Index: gwlib/regex.h
===================================================================
RCS file: /home/cvs/gateway/gwlib/regex.h,v
retrieving revision 1.4
diff -u -b -r1.4 regex.h
--- gwlib/regex.h       15 Nov 2003 13:14:23 -0000      1.4
+++ gwlib/regex.h       17 Dec 2003 08:45:21 -0000
@@ -85,6 +85,11 @@
  */
 #define REGEX_MAX_SUB_MATCH 10
 
+enum {
+    MATCH = 1,
+    NO_MATCH = -1
+};
+
 
 /*
  * Destroy a previously compiled regular expression.
@@ -187,6 +192,12 @@
 #define gw_regex_subst_pre(preg, os, rule) \
     gw_regex_subst_pre_real(preg, os, rule, __FILE__, __LINE__, __func__)
 
+
+/*
+ * checks whether or not a given Oct-string matches the regular expression.
+ * returns MATCH on match otherwise NO_MATCH
+ */
+int gw_regex_matches(const regex_t *preg, const Octstr *os);
 
 #endif
 #endif  /* REGEX_H */
Index: gwlib/regex.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/regex.c,v
retrieving revision 1.5
diff -u -b -r1.5 regex.c
--- gwlib/regex.c       15 Nov 2003 13:14:23 -0000      1.5
+++ gwlib/regex.c       17 Dec 2003 08:45:21 -0000
@@ -119,7 +119,6 @@
     int rc;
 
     gw_assert(preg != NULL);
-
     rc = regexec(preg, string ? octstr_get_cstr(string) : NULL,  nmatch, pmatch, 
eflags);
     if (rc != REG_NOMATCH && rc != 0) {
         char buffer[512];
@@ -128,7 +127,6 @@
               __FILE__, (long) __LINE__, __func__, octstr_get_cstr(string), buffer,
               (file), (long) (line), (func));
     }
-
     return rc;
 }
 
@@ -342,6 +340,17 @@
     
     return result;
 }
+
+int gw_regex_matches(const regex_t *preg, const Octstr *os) {
+    size_t n = 1;
+    regmatch_t p[10];
+
+    gw_assert(os != NULL && preg != NULL);
+    
+    debug("", 0, "exec regex on string: %s", octstr_get_cstr(os));
+    return
+        (gw_regex_exec(preg, os, n, p, 0) == 0) ? MATCH : NO_MATCH;
+};
 
 #endif  /* HAVE_REGEX || HAVE_PCRE */
 
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.98
diff -u -b -r1.98 cfg.def
--- gwlib/cfg.def       25 Nov 2003 23:45:13 -0000      1.98
+++ gwlib/cfg.def       17 Dec 2003 08:45:21 -0000
@@ -100,7 +100,9 @@
     OCTSTR(store-file)
     OCTSTR(unified-prefix)
     OCTSTR(white-list)
+    OCTSTR(white-list-regex)
     OCTSTR(black-list)
+    OCTSTR(black-list-regex)
     OCTSTR(http-proxy-host)
     OCTSTR(http-proxy-port)
     OCTSTR(http-proxy-exceptions)
@@ -198,8 +200,12 @@
     OCTSTR(ppg-password)
     OCTSTR(country-prefix)
     OCTSTR(allowed-prefix)
+    OCTSTR(allowed-prefix-regex)
     OCTSTR(denied-prefix)
+    OCTSTR(denied-prefix-regex)
     OCTSTR(white-list)
+    OCTSTR(white-list-regex)
+    OCTSTR(black-list-regex)
     OCTSTR(black-list)
     OCTSTR(deny-ip)
     OCTSTR(allow-ip)
@@ -256,6 +262,8 @@
     OCTSTR(xmlrpc-url)
     OCTSTR(http-request-retry)
     OCTSTR(http-queue-delay)
+    OCTSTR(white-list-regex)
+    OCTSTR(black-list-regex)
 )
 
 
@@ -342,6 +350,12 @@
     OCTSTR(msg-id-type)
     OCTSTR(no-dlr)
     OCTSTR(connection-timeout)
+    OCTSTR(allowed-smsc-id-regex)
+    OCTSTR(denied-smsc-id-regex)
+    OCTSTR(preferred-smsc-id-regex)
+    OCTSTR(allowed-prefix-regex)
+    OCTSTR(denied-prefix-regex)
+    OCTSTR(preferred-prefix-regex)
 )
 
 
@@ -357,6 +371,7 @@
     OCTSTR(text)
     OCTSTR(exec)
     OCTSTR(accepted-smsc)
+    OCTSTR(accepted-smsc-regex)
     OCTSTR(forced-smsc)
     OCTSTR(default-smsc)
     OCTSTR(faked-sender)
@@ -375,11 +390,17 @@
     OCTSTR(send-sender)
     OCTSTR(catch-all)
     OCTSTR(allowed-prefix)
+    OCTSTR(allowed-prefix-regex)
     OCTSTR(denied-prefix)
+    OCTSTR(denied-prefix-regex)
     OCTSTR(allowed-receiver-prefix)
+    OCTSTR(allowed-receiver-prefix-regex)
     OCTSTR(denied-receiver-prefix)
+    OCTSTR(denied-receiver-prefix-regex)
     OCTSTR(white-list)
+    OCTSTR(white-list-regex)
     OCTSTR(black-list)
+    OCTSTR(black-list-regex)
     OCTSTR(dlr-url)
 )
 
@@ -406,6 +427,13 @@
     OCTSTR(white-list)
     OCTSTR(black-list)
     OCTSTR(dlr-url)
+    OCTSTR(accepted-smsc-regex)
+    OCTSTR(allowed-prefix-regex)
+    OCTSTR(denied-prefix-regex)
+    OCTSTR(allowed-receiver-prefix-regex)
+    OCTSTR(denied-receiver-prefix-regex)
+    OCTSTR(white-list-regex)
+    OCTSTR(black-list-regex)
 )
 
 
Index: gw/bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.69
diff -u -b -r1.69 bb_smscconn.c
--- gw/bb_smscconn.c    8 Dec 2003 11:25:44 -0000       1.69
+++ gw/bb_smscconn.c    17 Dec 2003 08:45:21 -0000
@@ -113,6 +113,9 @@
 static Numhash *black_list;
 static Numhash *white_list;
 
+static regex_t *white_list_regex = NULL;
+static regex_t *black_list_regex = NULL;
+
 static long router_thread = -1;
 
 int route_incoming_to_boxc(Msg *sms);
@@ -261,6 +264,15 @@
        msg_destroy(sms);
         return SMSCCONN_FAILED_REJECTED;
     }
+
+    if (white_list_regex && (gw_regex_matches(white_list_regex, sms->sms.sender) == 
NO_MATCH)) {
+        info(0, "Number <%s> is not in white-list, message discarded",
+             octstr_get_cstr(sms->sms.sender));
+        bb_alog_sms(conn, sms, "REJECTED - not white-regex-listed SMS");
+        msg_destroy(sms);
+        return SMSCCONN_FAILED_REJECTED;
+    };
+    
     if (black_list &&
        numhash_find_number(black_list, sms->sms.sender) == 1) {
        info(0, "Number <%s> is in black-list, message discarded",
@@ -270,6 +282,14 @@
        return SMSCCONN_FAILED_REJECTED;
     }
 
+    if (black_list_regex && (gw_regex_matches(black_list_regex, sms->sms.sender) == 
NO_MATCH)) {
+        info(0, "Number <%s> is not in black-list, message discarded",
+             octstr_get_cstr(sms->sms.sender));
+        bb_alog_sms(conn, sms, "REJECTED - black-regex-listed SMS");
+        msg_destroy(sms);
+        return SMSCCONN_FAILED_REJECTED;
+    };
+
     if (sms->sms.sms_type != report)
        sms->sms.sms_type = mo;
 
@@ -415,11 +435,22 @@
         white_list = numhash_create(octstr_get_cstr(os));
        octstr_destroy(os);
     }
+    if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {
+        if ((white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
+        octstr_destroy(os);
+    }
+    
     os = cfg_get(grp, octstr_imm("black-list"));
     if (os != NULL) {
         black_list = numhash_create(octstr_get_cstr(os));
        octstr_destroy(os);
     }
+    if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {
+        if ((black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
+        octstr_destroy(os);
+    }
 
     smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
     /*
@@ -623,6 +654,8 @@
     octstr_destroy(unified_prefix);    
     numhash_destroy(white_list);
     numhash_destroy(black_list);
+    if (white_list_regex != NULL) gw_regex_destroy(white_list_regex);
+    if (black_list_regex != NULL) gw_regex_destroy(black_list_regex);
 }
 
 
Index: gw/smsbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsbox.c,v
retrieving revision 1.240
diff -u -b -r1.240 smsbox.c
--- gw/smsbox.c 8 Dec 2003 11:25:44 -0000       1.240
+++ gw/smsbox.c 17 Dec 2003 08:45:22 -0000
@@ -64,6 +64,7 @@
 #include <string.h>
 
 #include "gwlib/gwlib.h"
+#include "gwlib/regex.h"
 
 #include "msg.h"
 #include "sms.h"
@@ -125,6 +126,8 @@
 static int mo_recode = 0;
 static Numhash *white_list;
 static Numhash *black_list;
+static regex_t *white_list_regex = NULL;
+static regex_t *black_list_regex = NULL;
 static unsigned long max_http_retries = HTTP_MAX_RETRIES;
 static unsigned long http_queue_delay = HTTP_RETRY_DELAY;
 static Octstr *ppg_service_name = NULL;
@@ -1907,6 +1910,16 @@
         } else {
             list_append_unique(allowed, receiv, octstr_item_match);
         }
+
+        if (urltrans_white_list_regex(t) &&
+                gw_regex_matches(urltrans_white_list_regex(t), receiv) == NO_MATCH) {
+            info(0, "Number <%s> is not in white-list-regex, message discarded",
+                 octstr_get_cstr(receiv));
+            list_append_unique(denied, receiv, octstr_item_match);
+        } else {
+            list_append_unique(allowed, receiv, octstr_item_match);
+        }
+        
         if (urltrans_black_list(t) &&
             numhash_find_number(urltrans_black_list(t), receiv) == 1) {
             info(0, "Number <%s> is in black-list, message discarded",
@@ -1915,6 +1928,17 @@
         } else {
             list_append_unique(allowed, receiv, octstr_item_match);
         }
+
+        if (urltrans_black_list_regex(t) &&
+                gw_regex_matches(urltrans_black_list_regex(t), receiv) == MATCH) {
+            info(0, "Number <%s> is in black-list-regex, message discarded",
+                 octstr_get_cstr(receiv));
+            list_append_unique(denied, receiv, octstr_item_match);
+        } else {
+            list_append_unique(allowed, receiv, octstr_item_match);
+        }
+        
+
         if (white_list &&
             numhash_find_number(white_list, receiv) < 1) {
             info(0, "Number <%s> is not in global white-list, message discarded",
@@ -1923,6 +1947,16 @@
         } else {
             list_append_unique(allowed, receiv, octstr_item_match);
         }
+
+        if (white_list_regex &&
+            gw_regex_matches(white_list_regex, receiv) == NO_MATCH) {
+            info(0, "Number <%s> is not in global white-list-regex, message 
discarded",
+                 octstr_get_cstr(receiv));
+            list_append_unique(denied, receiv, octstr_item_match);
+        } else {
+            list_append_unique(allowed, receiv, octstr_item_match);
+        }
+
         if (black_list &&
             numhash_find_number(black_list, receiv) == 1) {
             info(0, "Number <%s> is in global black-list, message discarded",
@@ -1931,6 +1965,15 @@
         } else {
             list_append_unique(allowed, receiv, octstr_item_match);
         }
+
+        if (black_list_regex &&
+            gw_regex_matches(black_list_regex, receiv) == MATCH) {
+            info(0, "Number <%s> is in global black-list-regex, message discarded",
+                 octstr_get_cstr(receiv));
+            list_append_unique(denied, receiv, octstr_item_match);
+        } else {
+            list_append_unique(allowed, receiv, octstr_item_match);
+        }
     }
     
     /*
@@ -3155,11 +3198,25 @@
            white_list = numhash_create(octstr_get_cstr(os));
            octstr_destroy(os);
        }
+
+       os = cfg_get(grp, octstr_imm("white-list-regex"));
+       if (os != NULL) {
+        if ((white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+                        panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(os));
+        octstr_destroy(os);
+       }
+
        os = cfg_get(grp, octstr_imm("black-list"));
        if (os != NULL) {
            black_list = numhash_create(octstr_get_cstr(os));
            octstr_destroy(os);
        }
+       os = cfg_get(grp, octstr_imm("black-list-regex"));
+       if (os != NULL) {
+        if ((black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+                        panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(os));
+        octstr_destroy(os);
+       }
     }
 
     cfg_get_integer(&sendsms_port, grp, octstr_imm("sendsms-port"));
@@ -3220,7 +3277,6 @@
     /* HTTP queueing values */
     cfg_get_integer(&max_http_retries, grp, octstr_imm("http-request-retry"));
     cfg_get_integer(&http_queue_delay, grp, octstr_imm("http-queue-delay"));
-
     if (sendsms_port > 0) {
         if (http_open_port_if(sendsms_port, ssl, sendsms_interface) == -1) {   
             if (only_try_http)
@@ -3367,6 +3423,8 @@
     octstr_destroy(ppg_service_name);    
     numhash_destroy(black_list);
     numhash_destroy(white_list);
+    if (white_list_regex != NULL) gw_regex_destroy(white_list_regex);
+    if (black_list_regex != NULL) gw_regex_destroy(black_list_regex);
     cfg_destroy(cfg);
 
     /* 
Index: gw/smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/smscconn.c,v
retrieving revision 1.42
diff -u -b -r1.42 smscconn.c
--- gw/smscconn.c       15 Nov 2003 13:14:23 -0000      1.42
+++ gw/smscconn.c       17 Dec 2003 08:45:22 -0000
@@ -66,6 +66,7 @@
 #include <time.h>
 
 #include "gwlib/gwlib.h"
+#include "gwlib/regex.h"
 #include "smscconn.h"
 #include "smscconn_p.h"
 #include "bb_smscconn_cb.h"
@@ -149,6 +150,11 @@
     Octstr *smsc_type;
     int ret;
     long throughput;
+    Octstr *allowed_smsc_id_regex;
+    Octstr *denied_smsc_id_regex;
+    Octstr *allowed_prefix_regex;
+    Octstr *denied_prefix_regex;
+    Octstr *preferred_prefix_regex;
 
     if (grp == NULL)
        return NULL;
@@ -189,6 +195,27 @@
     GET_OPTIONAL_VAL(conn->log_file, "log-file");
     cfg_get_bool(&conn->alt_dcs, grp, octstr_imm("alt-dcs"));
              
+    GET_OPTIONAL_VAL(allowed_smsc_id_regex, "allowed-smsc-id-regex");
+    if (allowed_smsc_id_regex != NULL) 
+        if ((conn->allowed_smsc_id_regex = gw_regex_comp(allowed_smsc_id_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(allowed_smsc_id_regex));
+    GET_OPTIONAL_VAL(denied_smsc_id_regex, "denied-smsc-id-regex");
+    if (denied_smsc_id_regex != NULL) 
+        if ((conn->denied_smsc_id_regex = gw_regex_comp(denied_smsc_id_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(denied_smsc_id_regex));
+    GET_OPTIONAL_VAL(allowed_prefix_regex, "allowed-prefix-regex");
+    if (allowed_prefix_regex != NULL) 
+        if ((conn->allowed_prefix_regex = gw_regex_comp(allowed_prefix_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(allowed_prefix_regex));
+    GET_OPTIONAL_VAL(denied_prefix_regex, "denied-prefix-regex");
+    if (denied_prefix_regex != NULL) 
+        if ((conn->denied_prefix_regex = gw_regex_comp(denied_prefix_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(denied_prefix_regex));
+    GET_OPTIONAL_VAL(preferred_prefix_regex, "preferred-prefix-regex");
+    if (preferred_prefix_regex != NULL) 
+        if ((conn->preferred_prefix_regex = gw_regex_comp(preferred_prefix_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(preferred_prefix_regex));
+             
     if (cfg_get_integer(&throughput, grp, octstr_imm("throughput")) == -1)
         conn->throughput = 0;   /* defaults to no throughtput limitation */
     else 
@@ -208,6 +235,9 @@
     if (conn->allowed_smsc_id && conn->denied_smsc_id)
        warning(0, "Both 'allowed-smsc-id' and 'denied-smsc-id' set, deny-list "
                "automatically ignored");
+    if (conn->allowed_smsc_id_regex && conn->denied_smsc_id_regex)
+        warning(0, "Both 'allowed-smsc-id_regex' and 'denied-smsc-id_regex' set, 
deny-regex "
+                "automatically ignored");
 
     if (cfg_get_integer(&conn->reconnect_delay, grp, 
                         octstr_imm("reconnect-delay")) == -1)
@@ -304,6 +334,12 @@
     octstr_destroy(conn->our_host);
     octstr_destroy(conn->log_file);
 
+    if (conn->denied_smsc_id_regex != NULL) 
gw_regex_destroy(conn->denied_smsc_id_regex);
+    if (conn->allowed_smsc_id_regex != NULL) 
gw_regex_destroy(conn->allowed_smsc_id_regex);
+    if (conn->preferred_prefix_regex != NULL) 
gw_regex_destroy(conn->preferred_prefix_regex);
+    if (conn->denied_prefix_regex != NULL) 
gw_regex_destroy(conn->denied_prefix_regex);
+    if (conn->allowed_prefix_regex != NULL) 
gw_regex_destroy(conn->allowed_prefix_regex);
+
     octstr_destroy(conn->reroute_to_smsc);
     dict_destroy(conn->reroute_by_receiver);
     
@@ -396,22 +432,50 @@
        list_destroy(list, octstr_destroy_item);
     }
 
+    if (conn->allowed_smsc_id_regex) {
+        if (msg->sms.smsc_id == NULL)
+            return -1;
+        
+        if (gw_regex_matches(conn->allowed_smsc_id_regex, msg->sms.smsc_id) == 
NO_MATCH) 
+            return -1;
+    }
+    else if (conn->denied_smsc_id_regex && msg->sms.smsc_id != NULL) {
+        if (gw_regex_matches(conn->denied_smsc_id_regex, msg->sms.smsc_id) == MATCH) 
+            return -1;
+    };
+
     /* Have allowed */
     if (conn->allowed_prefix && ! conn->denied_prefix && 
        (does_prefix_match(conn->allowed_prefix, msg->sms.receiver) != 1))
        return -1;
 
+    if (conn->allowed_prefix_regex && ! conn->denied_prefix_regex) {
+        if (gw_regex_matches(conn->allowed_prefix_regex, msg->sms.receiver) == 
NO_MATCH)
+            return -1;
+    }
+
     /* Have denied */
     if (conn->denied_prefix && ! conn->allowed_prefix &&
        (does_prefix_match(conn->denied_prefix, msg->sms.receiver) == 1))
        return -1;
 
+    if (conn->denied_prefix_regex && ! conn->allowed_prefix_regex) {
+        if (gw_regex_matches(conn->denied_prefix_regex, msg->sms.receiver) == MATCH)
+            return -1;
+    }
+
     /* Have allowed and denied */
     if (conn->denied_prefix && conn->allowed_prefix &&
        (does_prefix_match(conn->allowed_prefix, msg->sms.receiver) != 1) &&
        (does_prefix_match(conn->denied_prefix, msg->sms.receiver) == 1) )
        return -1;
 
+    if (conn->allowed_prefix_regex && conn->denied_prefix_regex) {
+        if ((gw_regex_matches(conn->allowed_prefix_regex, msg->sms.receiver) == 
NO_MATCH)
+            && (gw_regex_matches(conn->denied_prefix_regex, msg->sms.receiver) == 
MATCH))
+            return -1;
+    };
+    
     /* then see if it is preferred one */
 
     if (conn->preferred_smsc_id && msg->sms.smsc_id != NULL) {
@@ -426,6 +490,11 @@
        if (does_prefix_match(conn->preferred_prefix, msg->sms.receiver) == 1)
            return 1;
 
+    if (conn->preferred_prefix_regex) {
+        if (gw_regex_matches(conn->preferred_prefix_regex, msg->sms.receiver) == 
MATCH)
+            return 1;
+    };
+        
     return 0;
 }
 
Index: gw/smscconn_p.h
===================================================================
RCS file: /home/cvs/gateway/gw/smscconn_p.h,v
retrieving revision 1.41
diff -u -b -r1.41 smscconn_p.h
--- gw/smscconn_p.h     15 Nov 2003 13:14:23 -0000      1.41
+++ gw/smscconn_p.h     17 Dec 2003 08:45:22 -0000
@@ -142,6 +142,7 @@
 
 #include <signal.h>
 #include "gwlib/gwlib.h"
+#include "gwlib/regex.h"
 #include "smscconn.h"
 
 struct smscconn {
@@ -168,12 +169,18 @@
     Octstr *id;                        /* Abstract name specified in configuration and
                                   used for logging and routing */
     Octstr *allowed_smsc_id;
+    regex_t *allowed_smsc_id_regex;
     Octstr *denied_smsc_id;
+    regex_t *denied_smsc_id_regex;
     Octstr *preferred_smsc_id;
+    regex_t *preferred_smsc_id_regex;
 
     Octstr *allowed_prefix;
+    regex_t *allowed_prefix_regex;
     Octstr *denied_prefix;
+    regex_t *denied_prefix_regex;
     Octstr *preferred_prefix;
+    regex_t *preferred_prefix_regex;
     Octstr *unified_prefix;
     
     Octstr *our_host;   /* local device IP to bind for TCP communication */
Index: gw/urltrans.c
===================================================================
RCS file: /home/cvs/gateway/gw/urltrans.c,v
retrieving revision 1.89
diff -u -b -r1.89 urltrans.c
--- gw/urltrans.c       8 Dec 2003 11:25:44 -0000       1.89
+++ gw/urltrans.c       17 Dec 2003 08:45:22 -0000
@@ -71,6 +71,7 @@
 #include "urltrans.h"
 #include "gwlib/gwlib.h"
 #include "gw/sms.h"
+#include "gwlib/regex.h"
 
 
 /***********************************************************************
@@ -126,6 +127,15 @@
     int has_catchall_arg;
     int catch_all;
     Octstr *dlr_url;   /* Url to call for delivery reports */
+
+    regex_t* regex;       /* the compiled regular expression for the keyword*/
+    regex_t *accepted_smsc_regex;
+    regex_t *allowed_prefix_regex;
+    regex_t *denied_prefix_regex;
+    regex_t *allowed_receiver_prefix_regex;
+    regex_t *denied_receiver_prefix_regex;
+    regex_t *white_list_regex;
+    regex_t *black_list_regex;
 };
 
 
@@ -312,6 +322,7 @@
 
     gw_assert(name != NULL);
     for (i = 0; i < list_len(trans->list); ++i) {
+
        t = list_get(trans->list, i);
        if (t->type == TRANSTYPE_SENDSMS) {
            if (octstr_compare(name, t->username) == 0)
@@ -781,11 +792,21 @@
     return t->white_list;
 }
 
+regex_t *urltrans_white_list_regex(URLTranslation *t)
+{
+    return t->white_list_regex;
+}
+
 Numhash *urltrans_black_list(URLTranslation *t)
 {
     return t->black_list;
 }
 
+regex_t *urltrans_black_list_regex(URLTranslation *t)
+{
+    return t->black_list_regex;
+}
+
 int urltrans_assume_plain_text(URLTranslation *t) 
 {
     return t->assume_plain_text;
@@ -823,6 +844,15 @@
     Octstr *accepted_smsc, *forced_smsc, *default_smsc;
     Octstr *grpname, *sendsms_user, *sms_service;
     int is_sms_service;
+    regex_t *expr = NULL;
+    Octstr *accepted_smsc_regex;
+    Octstr *allowed_prefix_regex;
+    Octstr *denied_prefix_regex;
+    Octstr *allowed_receiver_prefix_regex;
+    Octstr *denied_receiver_prefix_regex;
+    Octstr *white_list_regex;
+    Octstr *black_list_regex;
+    Octstr *os;
     
     grpname = cfg_get_group_name(grp);
     if (grpname == NULL)
@@ -868,6 +898,14 @@
     ot->denied_recv_prefix = NULL;
     ot->white_list = NULL;
     ot->black_list = NULL;
+    ot->regex = NULL;
+    ot->accepted_smsc_regex = NULL;
+    ot->allowed_prefix_regex = NULL;
+    ot->denied_prefix_regex = NULL;
+    ot->allowed_receiver_prefix_regex = NULL;
+    ot->denied_receiver_prefix_regex = NULL;
+    ot->white_list_regex = NULL;
+    ot->black_list_regex = NULL;
     
     if (is_sms_service) {
        cfg_get_bool(&ot->catch_all, grp, octstr_imm("catch-all"));
@@ -914,6 +952,9 @@
            error(0, "Group 'sms-service' must include 'keyword'.");
            goto error;
        }
+        if ((expr = gw_regex_comp(ot->keyword, REG_EXTENDED)) == NULL)
+              panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(ot->keyword));
+        ot->regex = expr;
        octstr_convert_range(ot->keyword, 0, octstr_len(ot->keyword), 
                             tolower);
 
@@ -941,6 +982,12 @@
            ot->accepted_smsc = octstr_split(accepted_smsc, octstr_imm(";"));
            octstr_destroy(accepted_smsc);
        }
+        accepted_smsc_regex = cfg_get(grp, octstr_imm("accepted-smsc-regex"));
+        if (accepted_smsc_regex != NULL) { 
+            if ( (ot->accepted_smsc_regex = gw_regex_comp(accepted_smsc_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(accepted_smsc_regex));
+            octstr_destroy(accepted_smsc_regex);
+        }
 
        cfg_get_bool(&ot->assume_plain_text, grp, 
                     octstr_imm("assume-plain-text"));
@@ -951,9 +998,22 @@
        
        ot->prefix = cfg_get(grp, octstr_imm("prefix"));
        ot->suffix = cfg_get(grp, octstr_imm("suffix"));
+        ot->allowed_recv_prefix = cfg_get(grp, octstr_imm("allowed-receiver-prefix"));
+        allowed_receiver_prefix_regex = cfg_get(grp, 
octstr_imm("allowed-receiver-prefix-regex"));
+        if (allowed_receiver_prefix_regex != NULL) {
+            if ((ot->allowed_receiver_prefix_regex = 
gw_regex_comp(allowed_receiver_prefix_regex, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(allowed_receiver_prefix_regex));
+            octstr_destroy(allowed_receiver_prefix_regex);
+        }
 
        ot->allowed_recv_prefix = cfg_get(grp, octstr_imm("allowed-receiver-prefix"));
     ot->denied_recv_prefix = cfg_get(grp, octstr_imm("denied-receiver-prefix"));
+        denied_receiver_prefix_regex = cfg_get(grp, 
octstr_imm("denied-receiver-prefix-regex"));
+        if (denied_receiver_prefix_regex != NULL) {
+            if ((ot->denied_receiver_prefix_regex = 
gw_regex_comp(denied_receiver_prefix_regex, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern 
'%s'",octstr_get_cstr(denied_receiver_prefix_regex));
+            octstr_destroy(denied_receiver_prefix_regex);
+        }
 
        ot->args = count_occurences(ot->pattern, octstr_imm("%s"));
        ot->args += count_occurences(ot->pattern, octstr_imm("%S"));
@@ -993,22 +1053,45 @@
        ot->deny_ip = cfg_get(grp, octstr_imm("user-deny-ip"));
        ot->allow_ip = cfg_get(grp, octstr_imm("user-allow-ip"));
        ot->default_sender = cfg_get(grp, octstr_imm("default-sender"));
-
     }
+    
     ot->allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
+    allowed_prefix_regex = cfg_get(grp, octstr_imm("allowed-prefix-regex"));
+    if (allowed_prefix_regex != NULL) {
+        if ((ot->allowed_prefix_regex = gw_regex_comp(allowed_prefix_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(allowed_prefix_regex));
+        octstr_destroy(allowed_prefix_regex);
+    }
     ot->denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
-    {
-       Octstr *os;
+    denied_prefix_regex = cfg_get(grp, octstr_imm("denied-prefix-regex"));
+    if (denied_prefix_regex != NULL) {
+        if ((ot->denied_prefix_regex = gw_regex_comp(denied_prefix_regex, 
REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(denied_prefix_regex));
+        octstr_destroy(denied_prefix_regex);
+    }
+    
        os = cfg_get(grp, octstr_imm("white-list"));
        if (os != NULL) {
            ot->white_list = numhash_create(octstr_get_cstr(os));
            octstr_destroy(os);
        }
+    white_list_regex = cfg_get(grp, octstr_imm("white-list-regex"));
+    if (white_list_regex != NULL) {
+        if ((ot->white_list_regex = gw_regex_comp(white_list_regex, REG_EXTENDED)) == 
NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(white_list_regex));
+        octstr_destroy(white_list_regex);
+    }
+
        os = cfg_get(grp, octstr_imm("black-list"));
        if (os != NULL) {
            ot->black_list = numhash_create(octstr_get_cstr(os));
            octstr_destroy(os);
        }
+    black_list_regex = cfg_get(grp, octstr_imm("black-list-regex"));
+    if (black_list_regex != NULL) {
+        if ((ot->black_list_regex = gw_regex_comp(black_list_regex, REG_EXTENDED)) == 
NULL)
+            panic(0, "Could not compile pattern '%s'", 
octstr_get_cstr(black_list_regex));
+        octstr_destroy(black_list_regex);
     }
 
     if (cfg_get_integer(&ot->max_messages, grp, 
@@ -1054,7 +1137,7 @@
     
     ot = p;
     if (ot != NULL) {
-       octstr_destroy(ot->keyword);
+    if (ot->keyword != NULL) octstr_destroy(ot->keyword);
        list_destroy(ot->aliases, octstr_destroy_item);
        octstr_destroy(ot->dlr_url);
        octstr_destroy(ot->pattern);
@@ -1080,98 +1163,207 @@
        octstr_destroy(ot->denied_recv_prefix);
        numhash_destroy(ot->white_list);
        numhash_destroy(ot->black_list);
+    if (ot->regex != NULL) gw_regex_destroy(ot->regex);
+    if (ot->accepted_smsc_regex != NULL) gw_regex_destroy(ot->accepted_smsc_regex);
+    if (ot->allowed_prefix_regex != NULL) gw_regex_destroy(ot->allowed_prefix_regex);
+    if (ot->denied_prefix_regex != NULL) gw_regex_destroy(ot->denied_prefix_regex);
+    if (ot->allowed_receiver_prefix_regex != NULL) 
gw_regex_destroy(ot->allowed_receiver_prefix_regex);
+    if (ot->denied_receiver_prefix_regex != NULL) 
gw_regex_destroy(ot->denied_receiver_prefix_regex);
+    if (ot->white_list_regex != NULL) gw_regex_destroy(ot->white_list_regex);
+    if (ot->black_list_regex != NULL) gw_regex_destroy(ot->black_list_regex);
        gw_free(ot);
     }
 }
 
 
 /*
- * Find the appropriate translation 
+ * checks if the number of passed words matches the service-pattern defined in the
+ * translation. returns 0 if arguments are okay, -1 otherwise.
  */
-static URLTranslation *find_translation(URLTranslationList *trans, 
-       List *words, Octstr *smsc, Octstr *sender, Octstr *receiver, int *reject)
+int check_num_args(URLTranslation *t, List *words)
 {
-    Octstr *keyword;
-    int i, n;
-    URLTranslation *t;
-    List *list;
+    const int IS_OKAY = 0;
+    const int NOT_OKAY = -1;
+    int n;
+
     
     n = list_len(words);
-    if (n == 0)
-       return NULL;
-    keyword = list_get(words, 0);
-    keyword = octstr_duplicate(keyword);
-    octstr_convert_range(keyword, 0, octstr_len(keyword), tolower);
+    /* check number of arguments */
+    if (t->catch_all)
+    return IS_OKAY;
     
-    list = dict_get(trans->dict, keyword);
-    t = NULL;
-    for (i = 0; i < list_len(list); ++i) {
-       t = list_get(list, i);
+    if (n - 1 == t->args)
+    return IS_OKAY;
+
+    if (t->has_catchall_arg && n - 1 >= t->args)
+    return IS_OKAY;
+
+    return NOT_OKAY;
+    };
+
+/*
+ * checks if a request matches the parameters of a URL-Translation, e.g. whether or 
not 
+ * a user is allowed to use certain services. returns 0 if allowed, -1 if not.
+ * reject will be set to 1 is a number is rejected due to white/black-lists.
+ */
+int check_allowed_translation(URLTranslation *t, 
+                  Octstr *smsc, Octstr *sender, Octstr *receiver, int *reject)
+{
+    const int IS_ALLOWED = 0;
+    const int NOT_ALLOWED = -1;
 
        /* if smsc_id set and accepted_smsc exist, accept
         * translation only if smsc id is in accept string
         */
        if (smsc && t->accepted_smsc) {
-           if (!list_search(t->accepted_smsc, smsc, octstr_item_match)) {
-               t = NULL;
-               continue;
-           }
-       }
+        if (!list_search(t->accepted_smsc, smsc, octstr_item_match))              
+            return NOT_ALLOWED;
+    };
+    if (smsc && t->accepted_smsc_regex)
+        if (gw_regex_matches( t->accepted_smsc_regex, smsc) == NO_MATCH)
+            return NOT_ALLOWED;
 
        /* Have allowed for sender */
        if (t->allowed_prefix && ! t->denied_prefix &&
-          (does_prefix_match(t->allowed_prefix, sender) != 1)) {
-           t = NULL;
-           continue;
-       }
+        (does_prefix_match(t->allowed_prefix, sender) != 1))
+            return NOT_ALLOWED;
+
+    if (t->allowed_prefix_regex && ! t->denied_prefix_regex) 
+        if (gw_regex_matches( t->allowed_prefix_regex, sender) == NO_MATCH)
+            return NOT_ALLOWED;
 
        /* Have denied for sender */
        if (t->denied_prefix && ! t->allowed_prefix &&
-          (does_prefix_match(t->denied_prefix, sender) == 1)) {
-           t = NULL;
-           continue;
-       }
+    (does_prefix_match(t->denied_prefix, sender) == 1))
+    return NOT_ALLOWED;
+
+    if (t->denied_prefix_regex && ! t->allowed_prefix_regex)
+        if (gw_regex_matches( t->denied_prefix_regex, sender) == NO_MATCH)
+            return NOT_ALLOWED;
 
        /* Have allowed for receiver */
        if (t->allowed_recv_prefix && ! t->denied_recv_prefix &&
-          (does_prefix_match(t->allowed_recv_prefix, receiver) != 1)) {
-           t = NULL;
-           continue;
-       }
+    (does_prefix_match(t->allowed_recv_prefix, receiver) != 1))
+    return NOT_ALLOWED;
+
+    if (t->allowed_receiver_prefix_regex && ! t->denied_receiver_prefix_regex)
+    if (gw_regex_matches( t->allowed_receiver_prefix_regex, receiver) == NO_MATCH)
+        return NOT_ALLOWED;
 
        /* Have denied for receiver */
        if (t->denied_recv_prefix && ! t->allowed_recv_prefix &&
-          (does_prefix_match(t->denied_recv_prefix, receiver) == 1)) {
-           t = NULL;
-           continue;
-       }
+    (does_prefix_match(t->denied_recv_prefix, receiver) == 1))
+    return NOT_ALLOWED;
+
+    if (t->denied_receiver_prefix_regex && ! t->allowed_receiver_prefix_regex)
+    if (gw_regex_matches( t->denied_receiver_prefix_regex, receiver) == NO_MATCH)
+        return NOT_ALLOWED;
 
        if (t->white_list &&
            numhash_find_number(t->white_list, sender) < 1) {
-           t = NULL; *reject = 1;
-           continue;
+    *reject = 1;
+    return NOT_ALLOWED;
+    }
+
+    if (t->white_list_regex) 
+    if (gw_regex_matches( t->white_list_regex, sender) == NO_MATCH) {
+        *reject = 1;
+        return NOT_ALLOWED;
        }   
+
        if (t->black_list &&
            numhash_find_number(t->black_list, sender) == 1) {
-           t = NULL; *reject = 1;
-           continue;
+    *reject = 1;
+    return NOT_ALLOWED;
+    }
+
+    if (t->black_list_regex) 
+    if (gw_regex_matches(t->black_list_regex, sender) == MATCH) {
+        *reject = 1;
+        return NOT_ALLOWED;
        }   
 
        /* Have allowed and denied */
        if (t->denied_prefix && t->allowed_prefix &&
           (does_prefix_match(t->allowed_prefix, sender) != 1) &&
-          (does_prefix_match(t->denied_prefix, sender) == 1) ) {
-           t = NULL;
+    (does_prefix_match(t->denied_prefix, sender) == 1) )
+    return NOT_ALLOWED;
+
+    if (t->denied_prefix_regex && t->allowed_prefix_regex
+    && (gw_regex_matches(t->allowed_prefix_regex, sender) == NO_MATCH)
+    && (gw_regex_matches(t->denied_prefix_regex, sender) == MATCH))
+    return NOT_ALLOWED;
+
+    return IS_ALLOWED;
+};
+
+    
+/* get_matching_translations - iterate over all translations in trans. 
+ * for each translation check whether 
+ * the translation's keyword has already been interpreted as a regexp. 
+ * if not, compile it now,
+ * otherwise retrieve compilation result from dictionary.
+ *
+ * the translations where the word matches the translation's pattern 
+ * are returned in a list
+ * 
+ */
+List* get_matching_translations(URLTranslationList *trans, Octstr *word) 
+{
+    List *list;
+    /*char *tmp_word;*/
+    int i;
+    size_t n_match = 1;
+    regmatch_t p_match[10];
+    URLTranslation *t;
+
+    gw_assert(trans != NULL && word != NULL);
+
+    list = list_create();
+    for (i = 0; i < list_len(trans->list); ++i) {
+        t = list_get(trans->list, i);
+        if (t->keyword == NULL || t->regex == NULL)
            continue;
+        if (gw_regex_exec(t->regex, word, n_match, p_match, 0) == 0)
+            /*a match was found, remember translation */    
+            list_append(list, t);
        }
+    return list;
+}
 
-       if (t->catch_all)
-           break;
+/*
+ * Find the appropriate translation 
+ */
+static URLTranslation *find_translation(URLTranslationList *trans, 
+                    List *words, Octstr *smsc, Octstr *sender, Octstr *receiver, int 
*reject)
+{
+    Octstr *keyword;
+    int i, n;
+    URLTranslation *t;
+    List *list;
 
-       if (n - 1 == t->args)
-           break;
-       if (t->has_catchall_arg && n - 1 >= t->args)
+    n = list_len(words);
+    if (n == 0)
+        return NULL;
+    n = 1;
+
+    keyword = list_get(words, 0);
+    keyword = octstr_duplicate(keyword);
+    octstr_convert_range(keyword, 0, octstr_len(keyword), tolower);
+
+    list = get_matching_translations(trans, keyword);
+    /*
+      list now contains all translations where the keyword of the sms matches the
+      pattern defined by the tranlsation's keyword
+    */
+    t = NULL;
+    for (i = 0; i < list_len(list); ++i) {
+        t = list_get(list, i);
+
+        if (check_allowed_translation(t, smsc, sender, receiver, reject) == 0
+            && check_num_args(t, words) == 0)
            break;
+
        t = NULL;
     }
 
@@ -1180,6 +1372,7 @@
        *reject = 0;
 
     octstr_destroy(keyword);    
+    list_destroy(list, NULL);
     return t;
 }
 
@@ -1198,58 +1391,11 @@
     t = NULL;
     for (i = 0; i < list_len(list); ++i) {
        t = list_get(list, i);
-       if (smsc && t->accepted_smsc) {
-           if (!list_search(t->accepted_smsc, smsc, octstr_item_match)) {
-               t = NULL;
-               continue;
-           }
-       }
-
-       /* Have allowed sender */
-       if (t->allowed_prefix && ! t->denied_prefix &&
-                       (does_prefix_match(t->allowed_prefix, sender) != 1)) {
-           t = NULL;
-           continue;
-       }
-
-       /* Have denied sender */
-       if (t->denied_prefix && ! t->allowed_prefix &&
-                       (does_prefix_match(t->denied_prefix, sender) == 1)) {
-           t = NULL;
-           continue;
-       }
 
-       /* Have allowed receiver */
-       if (t->allowed_recv_prefix && ! t->denied_recv_prefix &&
-                       (does_prefix_match(t->allowed_recv_prefix, receiver) != 1)) {
-           t = NULL;
-           continue;
-       }
-
-       /* Have denied receiver */
-       if (t->denied_recv_prefix && ! t->allowed_recv_prefix &&
-                       (does_prefix_match(t->denied_recv_prefix, receiver) == 1)) {
-           t = NULL;
-           continue;
-       }
-
-       if (t->white_list && numhash_find_number(t->white_list, sender) < 1) {
-           t = NULL; *reject = 1;
-           continue;
-       }
-       if (t->black_list && numhash_find_number(t->black_list, sender) == 1) {
-           t = NULL; *reject = 1;
-           continue;
-                                                                                      
 }
+    if (check_allowed_translation(t, smsc, sender, receiver, reject) == 0)
+        break;
 
-       /* Have allowed and denied */
-       if (t->denied_prefix && t->allowed_prefix &&
-                       (does_prefix_match(t->allowed_prefix, sender) != 1) &&
-                       (does_prefix_match(t->denied_prefix, sender) == 1) ) {
            t = NULL;
-           continue;
-       }
-       break;
     }
 
     /* Only return reject if there's only blacklisted smsc's */
Index: gw/urltrans.h
===================================================================
RCS file: /home/cvs/gateway/gw/urltrans.h,v
retrieving revision 1.29
diff -u -b -r1.29 urltrans.h
--- gw/urltrans.h       15 Nov 2003 13:14:23 -0000      1.29
+++ gw/urltrans.h       17 Dec 2003 08:45:22 -0000
@@ -84,6 +84,7 @@
 #include "gwlib/gwlib.h"
 #include "msg.h"
 #include "numhash.h"
+#include "gwlib/regex.h"
 
 /*
  * This is the data structure that holds the list of translations. It is
@@ -303,6 +304,8 @@
 /* Return white and black to number list */
 Numhash *urltrans_white_list(URLTranslation *t);
 Numhash *urltrans_black_list(URLTranslation *t);
+regex_t *urltrans_white_list_regex(URLTranslation *t);
+regex_t *urltrans_black_list_regex(URLTranslation *t);
 
 /* Return value of true (!0) or false (0) variables */
 int urltrans_assume_plain_text(URLTranslation *t);
Index: gw/wap_push_ppg_pushuser.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_ppg_pushuser.c,v
retrieving revision 1.16
diff -u -b -r1.16 wap_push_ppg_pushuser.c
--- gw/wap_push_ppg_pushuser.c  15 Nov 2003 13:14:23 -0000      1.16
+++ gw/wap_push_ppg_pushuser.c  17 Dec 2003 08:45:23 -0000
@@ -62,6 +62,7 @@
 
 #include "wap_push_ppg_pushuser.h"
 #include "numhash.h"
+#include "gwlib/regex.h"
 
 /***************************************************************************
  *
@@ -77,10 +78,17 @@
     Octstr *country_prefix;
     Octstr *allowed_prefix;            /* phone number prefixes allowed by 
                                           this user when pushing*/
+    regex_t *allowed_prefix_regex;
+    
     Octstr *denied_prefix;             /* and denied ones */
+    regex_t *denied_prefix_regex;
+
     Numhash *white_list;               /* phone numbers of this user, used for 
                                           push*/
+    regex_t *white_list_regex;
     Numhash *black_list;               /* numbers should not be used for push*/
+    regex_t *black_list_regex;
+
     Octstr *user_deny_ip;              /* this user allows pushes from these 
                                           IPs*/
     Octstr *user_allow_ip;             /* and denies them from these*/
@@ -456,9 +464,13 @@
     u->name = NULL;
     u->username = NULL;                  
     u->allowed_prefix = NULL;           
+    u->allowed_prefix_regex = NULL;           
     u->denied_prefix = NULL;             
+    u->denied_prefix_regex = NULL;             
     u->white_list = NULL;               
+    u->white_list_regex = NULL;               
     u->black_list = NULL;              
+    u->black_list_regex = NULL;              
     u->user_deny_ip = NULL;              
     u->user_allow_ip = NULL;
     u->smsc_id = NULL;
@@ -510,6 +522,27 @@
            octstr_destroy(os);
     }
 
+    if ((os = cfg_get(grp, octstr_imm("allowed-prefix-regex"))) != NULL) {
+        if ((u->allowed_prefix_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
+        octstr_destroy(os);
+    };
+    if ((os = cfg_get(grp, octstr_imm("denied-prefix-regex"))) != NULL) {
+        if ((u->denied_prefix_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
+        octstr_destroy(os);
+    };
+    if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {
+        if ((u->white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
+        octstr_destroy(os);
+    };
+    if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {
+        if ((u->black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
+            panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
+        octstr_destroy(os);
+    };
+
     octstr_destroy(grpname);
     return u;
 
@@ -543,6 +576,11 @@
      octstr_destroy(u->user_allow_ip);
      octstr_destroy(u->smsc_id);
      octstr_destroy(u->default_smsc_id);
+
+     if (u->black_list_regex != NULL) gw_regex_destroy(u->black_list_regex);
+     if (u->white_list_regex != NULL) gw_regex_destroy(u->white_list_regex);
+     if (u->denied_prefix_regex != NULL) gw_regex_destroy(u->denied_prefix_regex);
+     if (u->allowed_prefix_regex != NULL) gw_regex_destroy(u->allowed_prefix_regex);
      gw_free(u);             
 }
 
@@ -854,7 +892,8 @@
     if (u == NULL)
         goto no_user;
 
-    if (u->allowed_prefix == NULL && u->denied_prefix == NULL)
+    if (        u->allowed_prefix == NULL && u->denied_prefix == NULL 
+        && u->allowed_prefix_regex == NULL && u->denied_prefix_regex == NULL)
         goto no_configuration;
 
     if (u->denied_prefix != NULL) {
@@ -870,10 +909,15 @@
         }
     }
 
-    if (u->allowed_prefix == NULL) {
+    /* note: country-prefix _must_be included in the pattern */
+    if (u->denied_prefix_regex != NULL) 
+        if (gw_regex_matches(u->denied_prefix_regex, number) == MATCH)
+            goto denied;
+
+    if (u->allowed_prefix_regex == NULL && u->allowed_prefix == NULL) 
         goto no_allowed_config;
-    }
 
+    if (u->allowed_prefix != NULL) {
     allowed = octstr_split(u->allowed_prefix, octstr_imm(";"));
     for (i = 0; i < list_len(allowed); ++i) {
          listed_prefix = list_get(allowed, i);
@@ -884,6 +928,12 @@
                 goto allowed;
          }
     }
+    }
+
+    /* note: country-prefix _must_ be included in the pattern */
+    if (u->allowed_prefix_regex != NULL) 
+        if (gw_regex_matches(u->allowed_prefix_regex, number) == MATCH)
+            goto allowed;
 
 /*
  * Here we have an intentional fall-through. It will removed when memory cleaning
@@ -912,18 +962,28 @@
 
 static int whitelisted(WAPPushUser *u, Octstr *number)
 {
-    if (u->white_list == NULL)
-        return 1;
+    int result = 1;
 
-    return numhash_find_number(u->white_list, number);
+    if (u->white_list != NULL)
+        result = numhash_find_number(u->white_list, number);
+
+    if ((result == 0) && (u->white_list_regex != NULL))
+        result = (gw_regex_matches(u->white_list_regex, number) == MATCH) ? 1 : 0;
+
+    return result;
 }
 
 static int blacklisted(WAPPushUser *u, Octstr *number)
 {
+    int result = 0;
+    
     if (u->black_list == NULL)
-        return 0;
+        result = numhash_find_number(u->black_list, number);
+
+    if ((result == 0) && (u->black_list_regex != NULL))
+        result = (gw_regex_matches(u->black_list_regex, number) == MATCH) ? 1 : 0;
 
-    return numhash_find_number(u->black_list, number);
+    return result;
 }
 
 /* 

Reply via email to