Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

urltrans.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * urltrans.c - URL translations
00059  *
00060  * Lars Wirzenius
00061  */
00062 
00063 
00064 #include <ctype.h>
00065 #include <errno.h>
00066 #include <limits.h>
00067 #include <stdlib.h>
00068 #include <string.h>
00069 #include <time.h>
00070 
00071 #include "urltrans.h"
00072 #include "gwlib/gwlib.h"
00073 #include "gw/sms.h"
00074 
00075 
00076 /***********************************************************************
00077  * Definitions of data structures. These are not visible to the external
00078  * world -- they may be accessed only via the functions declared in
00079  * urltrans.h.
00080  */
00081 
00082 
00083 /*
00084  * Hold one keyword/options entity
00085  */
00086 struct URLTranslation {
00087     int type;       /* see enumeration in header file */
00088     Octstr *pattern;    /* url, text or file-name pattern */
00089     Octstr *prefix; /* for prefix-cut */
00090     Octstr *suffix; /* for suffix-cut */
00091     Octstr *faked_sender;/* works only with certain services */
00092     Octstr *default_sender;/* Default sender to sendsms-user */
00093     long max_messages;  /* absolute limit of reply messages */
00094     int concatenation;  /* send long messages as concatenated SMS's if true */
00095     Octstr *split_chars;/* allowed chars to be used to split message */
00096     Octstr *split_suffix;/* chars added to end after each split (not last) */
00097     int omit_empty; /* if the reply is empty, is notification send */
00098     Octstr *header; /* string to be inserted to each SMS */
00099     Octstr *footer; /* string to be appended to each SMS */
00100     List *accepted_smsc; /* smsc id's allowed to use this service. If not set,
00101                 all messages can use this service */
00102     List *accepted_account; /* account id's allowed to use this service. If not set,
00103                 all messages can use this service */
00104     
00105     Octstr *name;   /* Translation name */
00106     Octstr *username;   /* send sms username */
00107     Octstr *password;   /* password associated */
00108     Octstr *forced_smsc;/* if smsc id is forcet to certain for this user */
00109     Octstr *default_smsc; /* smsc id if none given in http send-sms request */
00110     Octstr *allow_ip;   /* allowed IPs to request send-sms with this 
00111                            account */
00112     Octstr *deny_ip;    /* denied IPs to request send-sms with this account */
00113     Octstr *allowed_prefix; /* Prefixes (of sender) allowed in this translation, or... */
00114     Octstr *denied_prefix;  /* ...denied prefixes */
00115     Octstr *allowed_recv_prefix; /* Prefixes (of receiver) allowed in this translation, or... */
00116     Octstr *denied_recv_prefix; /* ...denied prefixes */
00117     Numhash *white_list;    /* To numbers allowed, or ... */
00118     Numhash *black_list; /* ...denied numbers */
00119 
00120     int assume_plain_text; /* for type: octet-stream */
00121     int accept_x_kannel_headers; /* do we accept special headers in reply */
00122     int strip_keyword;  /* POST body */
00123     int send_sender;    /* POST headers */
00124     
00125     int args;
00126     int has_catchall_arg;
00127     int catch_all;
00128     Octstr *dlr_url;    /* Url to call for delivery reports */
00129 
00130     regex_t *keyword_regex;       /* the compiled regular expression for the keyword*/
00131     regex_t *accepted_smsc_regex;
00132     regex_t *accepted_account_regex;
00133     regex_t *allowed_prefix_regex;
00134     regex_t *denied_prefix_regex;
00135     regex_t *allowed_receiver_prefix_regex;
00136     regex_t *denied_receiver_prefix_regex;
00137     regex_t *white_list_regex;
00138     regex_t *black_list_regex;
00139 };
00140 
00141 
00142 /*
00143  * Hold the list of all translations.
00144  */
00145 struct URLTranslationList {
00146     List *list;
00147     List *defaults; /* List of default sms-services */
00148     Dict *names;    /* Dict of lowercase Octstr names */
00149 };
00150 
00151 
00152 /***********************************************************************
00153  * Declarations of internal functions. These are defined at the end of
00154  * the file.
00155  */
00156 
00157 static long count_occurences(Octstr *str, Octstr *pat);
00158 static URLTranslation *create_onetrans(CfgGroup *grp);
00159 static void destroy_onetrans(void *ot);
00160 static URLTranslation *find_translation(URLTranslationList *trans, Msg *msg);
00161 static URLTranslation *find_default_translation(URLTranslationList *trans,
00162                         Octstr *smsc, Octstr *sender, Octstr *receiver,
00163                         Octstr *account);
00164 
00165 
00166 /***********************************************************************
00167  * Implementations of the functions declared in urltrans.h. See the
00168  * header for explanations of what they should do.
00169  */
00170 
00171 
00172 static void destroy_keyword_list(void *list)
00173 {
00174     gwlist_destroy(list, NULL);
00175 }
00176 
00177 
00178 URLTranslationList *urltrans_create(void) 
00179 {
00180     URLTranslationList *trans;
00181     
00182     trans = gw_malloc(sizeof(URLTranslationList));
00183     trans->list = gwlist_create();
00184     trans->defaults = gwlist_create();
00185     trans->names = dict_create(1024, destroy_keyword_list);
00186     return trans;
00187 }
00188 
00189 
00190 void urltrans_destroy(URLTranslationList *trans) 
00191 {
00192     gwlist_destroy(trans->list, destroy_onetrans);
00193     gwlist_destroy(trans->defaults, destroy_onetrans);
00194     dict_destroy(trans->names);
00195     gw_free(trans);
00196 }
00197 
00198 
00199 int urltrans_add_one(URLTranslationList *trans, CfgGroup *grp)
00200 {
00201     URLTranslation *ot;
00202     List *list2;
00203     
00204     ot = create_onetrans(grp);
00205     if (ot == NULL)
00206     return -1;
00207 
00208     if (ot->type != TRANSTYPE_SENDSMS && ot->keyword_regex == NULL)
00209         gwlist_append(trans->defaults, ot);
00210     else 
00211         gwlist_append(trans->list, ot);
00212     
00213     list2 = dict_get(trans->names, ot->name);
00214     if (list2 == NULL) {
00215         list2 = gwlist_create();
00216     dict_put(trans->names, ot->name, list2);
00217     }
00218     gwlist_append(list2, ot);
00219 
00220     return 0;
00221 }
00222 
00223 
00224 int urltrans_add_cfg(URLTranslationList *trans, Cfg *cfg) 
00225 {
00226     CfgGroup *grp;
00227     List *list;
00228     
00229     list = cfg_get_multi_group(cfg, octstr_imm("sms-service"));
00230     while (list && (grp = gwlist_extract_first(list)) != NULL) {
00231     if (urltrans_add_one(trans, grp) == -1) {
00232         gwlist_destroy(list, NULL);
00233         return -1;
00234     }
00235     }
00236     gwlist_destroy(list, NULL);
00237     
00238     list = cfg_get_multi_group(cfg, octstr_imm("sendsms-user"));
00239     while (list && (grp = gwlist_extract_first(list)) != NULL) {
00240     if (urltrans_add_one(trans, grp) == -1) {
00241         gwlist_destroy(list, NULL);
00242         return -1;
00243     }
00244     }
00245     gwlist_destroy(list, NULL);
00246 
00247     return 0;
00248 }
00249 
00250 
00251 URLTranslation *urltrans_find(URLTranslationList *trans, Msg *msg) 
00252 {
00253     URLTranslation *t = NULL;
00254     
00255     t = find_translation(trans, msg);
00256     if (t == NULL) {
00257         t = find_default_translation(trans, msg->sms.smsc_id, msg->sms.sender, msg->sms.receiver, msg->sms.account);
00258     }
00259 
00260     return t;
00261 }
00262 
00263 
00264 URLTranslation *urltrans_find_service(URLTranslationList *trans, Msg *msg)
00265 {
00266     URLTranslation *t;
00267     List *list;
00268     
00269     list = dict_get(trans->names, msg->sms.service);
00270     if (list != NULL) {
00271        t = gwlist_get(list, 0);
00272     } else  {
00273        t = NULL;
00274     }
00275     return t;
00276 }
00277 
00278 
00279 
00280 URLTranslation *urltrans_find_username(URLTranslationList *trans, Octstr *name)
00281 {
00282     URLTranslation *t;
00283     int i;
00284 
00285     gw_assert(name != NULL);
00286     for (i = 0; i < gwlist_len(trans->list); ++i) {
00287     t = gwlist_get(trans->list, i);
00288     if (t->type == TRANSTYPE_SENDSMS) {
00289         if (octstr_compare(name, t->username) == 0)
00290         return t;
00291     }
00292     }
00293     return NULL;
00294 }
00295 
00296 /*
00297  * Remove the first word and the whitespace that follows it from
00298  * the start of the message data.
00299  */
00300 static void strip_keyword(Msg *request)
00301 {          
00302     int ch;
00303     long pos;
00304 
00305     pos = 0;
00306 
00307     for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++)
00308         if (isspace(ch))
00309             break;
00310 
00311     for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++)
00312         if (!isspace(ch))
00313             break;
00314 
00315     octstr_delete(request->sms.msgdata, 0, pos);
00316 }
00317 
00318 
00319 Octstr *urltrans_fill_escape_codes(Octstr *pattern, Msg *request)
00320 {
00321     Octstr *enc;
00322     int nextarg, j;
00323     struct tm tm;
00324     int num_words;
00325     List *word_list;
00326     Octstr *result;
00327     long pattern_len;
00328     long pos;
00329     int c;
00330     long i;
00331     Octstr *temp;
00332 
00333     result = octstr_create("");
00334 
00335     if (request->sms.msgdata) {
00336         word_list = octstr_split_words(request->sms.msgdata);
00337         num_words = gwlist_len(word_list);
00338     } else {
00339         word_list = gwlist_create();
00340         num_words = 0;
00341     }
00342     
00343     pattern_len = octstr_len(pattern);
00344     nextarg = 1;
00345     pos = 0;
00346     for (;;) {
00347         while (pos < pattern_len) {
00348             c = octstr_get_char(pattern, pos);
00349             if (c == '%' && pos + 1 < pattern_len)
00350                 break;
00351             octstr_append_char(result, c);
00352             ++pos;
00353         }
00354 
00355         if (pos == pattern_len)
00356             break;
00357 
00358     switch (octstr_get_char(pattern, pos + 1)) {
00359     case 'a':
00360         for (j = 0; j < num_words; ++j) {
00361         enc = octstr_duplicate(gwlist_get(word_list, j));
00362         octstr_url_encode(enc);
00363         if (j > 0)
00364             octstr_append_char(result, '+');
00365         octstr_append(result, enc);
00366         octstr_destroy(enc);
00367         }
00368         break;
00369 
00370     case 'A':
00371         if (request->sms.msgdata) {
00372         enc = octstr_duplicate(request->sms.msgdata);
00373         octstr_url_encode(enc);
00374         octstr_append(result, enc);
00375         octstr_destroy(enc);
00376         }
00377         break;
00378 
00379     case 'b':
00380         enc = octstr_duplicate(request->sms.msgdata);
00381         octstr_url_encode(enc);
00382         octstr_append(result, enc);
00383         octstr_destroy(enc);
00384         break;
00385 
00386     case 'B':  /* billing identifier/information */
00387         if (octstr_len(request->sms.binfo)) {
00388             enc = octstr_duplicate(request->sms.binfo);
00389             octstr_url_encode(enc);
00390             octstr_append(result, enc);
00391             octstr_destroy(enc);
00392         }
00393         break;
00394 
00395     case 'c':
00396         octstr_append_decimal(result, request->sms.coding);
00397         break;
00398 
00399     case 'C':
00400         if(octstr_len(request->sms.charset)) {
00401             octstr_append(result, request->sms.charset);
00402         } else {
00403             switch (request->sms.coding) {
00404             case DC_UNDEF:
00405             case DC_7BIT:
00406                 octstr_append(result, octstr_imm("UTF-8"));
00407                 break;
00408             case DC_8BIT:
00409                 octstr_append(result, octstr_imm("8-BIT"));
00410                 break;
00411             case DC_UCS2:
00412                 octstr_append(result, octstr_imm("UTF-16BE"));
00413                 break;
00414             }
00415         }
00416         break;
00417 
00418     case 'd':
00419         enc = octstr_create("");
00420         octstr_append_decimal(enc, request->sms.dlr_mask);
00421         octstr_url_encode(enc);
00422         octstr_append(result, enc);
00423         octstr_destroy(enc);
00424         break;
00425 
00426     case 'f':  /* smsc number*/
00427         if (octstr_len(request->sms.smsc_number)) {
00428             enc = octstr_duplicate(request->sms.smsc_number);
00429             octstr_url_encode(enc);
00430             octstr_append(result, enc);
00431             octstr_destroy(enc);
00432         }
00433         break;
00434 
00435     case 'i':
00436         if (request->sms.smsc_id == NULL)
00437         break;
00438         enc = octstr_duplicate(request->sms.smsc_id);
00439         octstr_url_encode(enc);
00440         octstr_append(result, enc);
00441         octstr_destroy(enc);
00442         break;
00443 
00444     case 'I':
00445         if (!uuid_is_null(request->sms.id)) {
00446                 char id[UUID_STR_LEN + 1];
00447                 uuid_unparse(request->sms.id, id);
00448             octstr_append_cstr(result, id);
00449             }
00450         break;
00451 
00452     case 'k':
00453         if (num_words <= 0)
00454         break;
00455         enc = octstr_duplicate(gwlist_get(word_list, 0));
00456         octstr_url_encode(enc);
00457         octstr_append(result, enc);
00458         octstr_destroy(enc);
00459         break;
00460 
00461     case 'm':  /* mclass - message class */
00462         enc = octstr_create("");
00463         octstr_append_decimal(enc, request->sms.mclass);
00464         octstr_url_encode(enc);
00465         octstr_append(result, enc);
00466         octstr_destroy(enc);
00467         break;
00468 
00469     case 'M':  /* mwi - message waiting indicator */
00470         enc = octstr_create("");
00471         octstr_append_decimal(enc, request->sms.mwi);
00472         octstr_url_encode(enc);
00473         octstr_append(result, enc);
00474         octstr_destroy(enc);
00475         break;
00476 
00477     case 'n':
00478         if (request->sms.service == NULL)
00479         break;
00480         enc = octstr_duplicate(request->sms.service);
00481         octstr_url_encode(enc);
00482         octstr_append(result, enc);
00483         octstr_destroy(enc);
00484         break;
00485 
00486     case 'o':  /* account information (may be operator id for aggregators */
00487         if (octstr_len(request->sms.account)) {
00488             enc = octstr_duplicate(request->sms.account);
00489             octstr_url_encode(enc);
00490             octstr_append(result, enc);
00491             octstr_destroy(enc);
00492         }
00493         break;
00494 
00495     case 'O':  /* DCS */
00496     {
00497         int dcs;
00498         dcs = fields_to_dcs(request, request->sms.alt_dcs);
00499         octstr_format_append(result, "%02d", dcs);
00500         break;
00501     }
00502 
00503     /* NOTE: the sender and receiver is already switched in
00504      *    message, so that's why we must use 'sender' when
00505      *    we want original receiver and vice versa
00506      */
00507     case 'P':
00508         enc = octstr_duplicate(request->sms.sender);
00509         octstr_url_encode(enc);
00510         octstr_append(result, enc);
00511         octstr_destroy(enc);
00512         break;
00513 
00514     case 'p':
00515         enc = octstr_duplicate(request->sms.receiver);
00516         octstr_url_encode(enc);
00517         octstr_append(result, enc);
00518         octstr_destroy(enc);
00519         break;
00520 
00521     case 'q':
00522         if (strncmp(octstr_get_cstr(request->sms.receiver),"00",2)==0) {
00523         enc = octstr_copy(request->sms.receiver, 2, 
00524                           octstr_len(request->sms.receiver));
00525         octstr_url_encode(enc);
00526         octstr_format_append(result, "%%2B%S", enc);
00527         octstr_destroy(enc);
00528         } else {
00529         enc = octstr_duplicate(request->sms.receiver);
00530         octstr_url_encode(enc);
00531         octstr_append(result, enc);
00532         octstr_destroy(enc);
00533         }
00534         break;
00535 
00536     case 'Q':
00537         if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) {
00538         enc = octstr_copy(request->sms.sender, 2, 
00539                           octstr_len(request->sms.sender));
00540         octstr_url_encode(enc);
00541         octstr_format_append(result, "%%2B%S", enc);
00542         octstr_destroy(enc);
00543         } else {
00544         enc = octstr_duplicate(request->sms.sender);
00545                 octstr_url_encode(enc);
00546         octstr_append(result, enc);
00547         octstr_destroy(enc);
00548         }
00549         break;
00550 
00551     case 'r':
00552         for (j = nextarg; j < num_words; ++j) {
00553         enc = octstr_duplicate(gwlist_get(word_list, j));
00554         octstr_url_encode(enc);
00555         if (j != nextarg)
00556             octstr_append_char(result, '+');
00557         octstr_append(result, enc);
00558         octstr_destroy(enc);
00559         }
00560         break;
00561 
00562     case 's':
00563         if (nextarg >= num_words)
00564         break;
00565         enc = octstr_duplicate(gwlist_get(word_list, nextarg));
00566         octstr_url_encode(enc);
00567         octstr_append(result, enc);
00568         octstr_destroy(enc);
00569         ++nextarg;
00570         break;
00571 
00572     case 'S':
00573         if (nextarg >= num_words)
00574         break;
00575         temp = gwlist_get(word_list, nextarg);
00576         for (i = 0; i < octstr_len(temp); ++i) {
00577         if (octstr_get_char(temp, i) == '*')
00578             octstr_append_char(result, '~');
00579         else
00580             octstr_append_char(result, octstr_get_char(temp, i));
00581         }
00582         ++nextarg;
00583         break;
00584 
00585     case 't':
00586         tm = gw_gmtime(request->sms.time);
00587         octstr_format_append(result, "%04d-%02d-%02d+%02d:%02d:%02d",
00588                  tm.tm_year + 1900,
00589                  tm.tm_mon + 1,
00590                  tm.tm_mday,
00591                  tm.tm_hour,
00592                  tm.tm_min,
00593                  tm.tm_sec);
00594         break;
00595 
00596     case 'T':
00597         if (request->sms.time == MSG_PARAM_UNDEFINED)
00598         break;
00599         octstr_format_append(result, "%ld", request->sms.time);
00600         break;
00601 
00602     case 'u':
00603         if(octstr_len(request->sms.udhdata)) {
00604         enc = octstr_duplicate(request->sms.udhdata);
00605         octstr_url_encode(enc);
00606         octstr_append(result, enc);
00607         octstr_destroy(enc);
00608         }
00609         break;
00610     
00611     /* XXX sms.parameters not present in here:
00612      *   * pid - will we receive this ? 
00613      *   * alt-dcs - shouldn't be required unless we want to inform 
00614      *               which alt-dcs external server should use back
00615      *   * compress - if we use compression, probably kannel would 
00616      *                decompress and reset this to 0. not required
00617      *   * validity, deferred, rpi - we don't receive these from smsc
00618      *   * username, password, dlr-url, account - nonsense to send
00619      */
00620 
00621     case '%':
00622         octstr_format_append(result, "%%");
00623         break;
00624 
00625     default:
00626         octstr_format_append(result, "%%%c",
00627                              octstr_get_char(pattern, pos + 1));
00628         break;
00629     }
00630 
00631     pos += 2;
00632     }
00633     
00634     gwlist_destroy(word_list, octstr_destroy_item);    
00635 
00636     return result;    
00637 }
00638 
00639 
00640 /*
00641  * Trans being NULL means that we are servicing ppg (doing dlr, but this does not
00642  * concern us here).
00643  */
00644 Octstr *urltrans_get_pattern(URLTranslation *t, Msg *request)
00645 {
00646     Octstr *result, *pattern;
00647     
00648     if (request->sms.sms_type != report_mo && t->type == TRANSTYPE_SENDSMS)
00649         return octstr_create("");
00650 
00651     /* check if this is a delivery report message or not */
00652     if (request->sms.sms_type != report_mo) {
00653         pattern = t->pattern;
00654     } else {
00655         /* this is a DLR message */
00656         pattern = request->sms.dlr_url;
00657         if (octstr_len(pattern) == 0) {
00658             if (t && octstr_len(t->dlr_url)) {
00659                 pattern = t->dlr_url;
00660             } else {
00661                 return octstr_create("");
00662             }
00663         }
00664     }
00665 
00666     /* We have pulled this out into an own exported function. This 
00667      * gives other modules the chance to use the same escape code
00668      * semantics for Msgs. */
00669     result = urltrans_fill_escape_codes(pattern, request);
00670 
00671     /*
00672      * this SHOULD be done in smsbox, not here, but well,
00673      * much easier to do here
00674      */
00675     if (t && (t->type == TRANSTYPE_POST_URL || t->type == TRANSTYPE_POST_XML)
00676             && t->strip_keyword)
00677     strip_keyword(request);
00678 
00679     return result;
00680 }
00681 
00682 
00683 int urltrans_type(URLTranslation *t) 
00684 {
00685     return t->type;
00686 }
00687 
00688 Octstr *urltrans_prefix(URLTranslation *t) 
00689 {
00690     return t->prefix;
00691 }
00692 
00693 Octstr *urltrans_suffix(URLTranslation *t) 
00694 {
00695     return t->suffix;
00696 }
00697 
00698 Octstr *urltrans_default_sender(URLTranslation *t) 
00699 {
00700     return t->default_sender;
00701 }
00702 
00703 Octstr *urltrans_faked_sender(URLTranslation *t) 
00704 {
00705     return t->faked_sender;
00706 }
00707 
00708 int urltrans_max_messages(URLTranslation *t) 
00709 {
00710     return t->max_messages;
00711 }
00712 
00713 int urltrans_concatenation(URLTranslation *t) 
00714 {
00715     return t->concatenation;
00716 }
00717 
00718 Octstr *urltrans_split_chars(URLTranslation *t) 
00719 {
00720     return t->split_chars;
00721 }
00722 
00723 Octstr *urltrans_split_suffix(URLTranslation *t) 
00724 {
00725     return t->split_suffix;
00726 }
00727 
00728 int urltrans_omit_empty(URLTranslation *t) 
00729 {
00730     return t->omit_empty;
00731 }
00732 
00733 Octstr *urltrans_header(URLTranslation *t) 
00734 {
00735     return t->header;
00736 }
00737 
00738 Octstr *urltrans_footer(URLTranslation *t) 
00739 {
00740     return t->footer;
00741 }
00742 
00743 Octstr *urltrans_name(URLTranslation *t) 
00744 {
00745     return t->name;
00746 }
00747 
00748 Octstr *urltrans_username(URLTranslation *t) 
00749 {
00750     return t->username;
00751 }
00752 
00753 Octstr *urltrans_password(URLTranslation *t) 
00754 {
00755     return t->password;
00756 }
00757 
00758 Octstr *urltrans_forced_smsc(URLTranslation *t) 
00759 {
00760     return t->forced_smsc;
00761 }
00762 
00763 Octstr *urltrans_default_smsc(URLTranslation *t) 
00764 {
00765     return t->default_smsc;
00766 }
00767 
00768 Octstr *urltrans_allow_ip(URLTranslation *t) 
00769 {
00770     return t->allow_ip;
00771 }
00772 
00773 Octstr *urltrans_deny_ip(URLTranslation *t) 
00774 {
00775     return t->deny_ip;
00776 }
00777 
00778 Octstr *urltrans_allowed_prefix(URLTranslation *t) 
00779 {
00780     return t->allowed_prefix;
00781 }
00782 
00783 Octstr *urltrans_denied_prefix(URLTranslation *t) 
00784 {
00785     return t->denied_prefix;
00786 }
00787 
00788 Octstr *urltrans_allowed_recv_prefix(URLTranslation *t) 
00789 {
00790     return t->allowed_recv_prefix;
00791 }
00792 
00793 Octstr *urltrans_denied_recv_prefix(URLTranslation *t) 
00794 {
00795     return t->denied_recv_prefix;
00796 }
00797 
00798 Numhash *urltrans_white_list(URLTranslation *t)
00799 {
00800     return t->white_list;
00801 }
00802 
00803 regex_t *urltrans_white_list_regex(URLTranslation *t)
00804 {
00805     return t->white_list_regex;
00806 }
00807 
00808 Numhash *urltrans_black_list(URLTranslation *t)
00809 {
00810     return t->black_list;
00811 }
00812 
00813 regex_t *urltrans_black_list_regex(URLTranslation *t)
00814 {
00815     return t->black_list_regex;
00816 }
00817 
00818 int urltrans_assume_plain_text(URLTranslation *t) 
00819 {
00820     return t->assume_plain_text;
00821 }
00822 
00823 int urltrans_accept_x_kannel_headers(URLTranslation *t) 
00824 {
00825     return t->accept_x_kannel_headers;
00826 }
00827 
00828 int urltrans_strip_keyword(URLTranslation *t) 
00829 {
00830     return t->strip_keyword;
00831 }
00832 
00833 int urltrans_send_sender(URLTranslation *t) 
00834 {
00835     return t->send_sender;
00836 }
00837 
00838 
00839 
00840 /***********************************************************************
00841  * Internal functions.
00842  */
00843 
00844 
00845 /*
00846  * Create one URLTranslation. Return NULL for failure, pointer to it for OK.
00847  */
00848 static URLTranslation *create_onetrans(CfgGroup *grp)
00849 {
00850     URLTranslation *ot;
00851     Octstr *url, *post_url, *post_xml, *text, *file, *exec;
00852     Octstr *accepted_smsc, *accepted_account, *forced_smsc, *default_smsc;
00853     Octstr *grpname;
00854     int is_sms_service;
00855     Octstr *accepted_smsc_regex;
00856     Octstr *accepted_account_regex;
00857     Octstr *allowed_prefix_regex;
00858     Octstr *denied_prefix_regex;
00859     Octstr *allowed_receiver_prefix_regex;
00860     Octstr *denied_receiver_prefix_regex;
00861     Octstr *white_list_regex;
00862     Octstr *black_list_regex;
00863     Octstr *keyword_regex;
00864     Octstr *os, *tmp;
00865     
00866     grpname = cfg_get_group_name(grp);
00867     if (grpname == NULL)
00868         return NULL;
00869 
00870     if (octstr_str_compare(grpname, "sms-service") == 0)
00871         is_sms_service = 1;
00872     else if (octstr_str_compare(grpname, "sendsms-user") == 0)
00873         is_sms_service = 0;
00874     else {
00875         octstr_destroy(grpname);
00876         return NULL;
00877     }
00878     octstr_destroy(grpname);
00879 
00880     ot = gw_malloc(sizeof(URLTranslation));
00881     memset(ot, 0, sizeof(*ot));
00882     
00883     if (is_sms_service) {
00884         cfg_get_bool(&ot->catch_all, grp, octstr_imm("catch-all"));
00885 
00886         ot->dlr_url = cfg_get(grp, octstr_imm("dlr-url"));
00887         
00888         url = cfg_get(grp, octstr_imm("get-url"));
00889         if (url == NULL)
00890             url = cfg_get(grp, octstr_imm("url"));
00891         
00892     post_url = cfg_get(grp, octstr_imm("post-url"));
00893     post_xml = cfg_get(grp, octstr_imm("post-xml"));
00894     file = cfg_get(grp, octstr_imm("file"));
00895     text = cfg_get(grp, octstr_imm("text"));
00896     exec = cfg_get(grp, octstr_imm("exec"));
00897     if (url != NULL) {
00898         ot->type = TRANSTYPE_GET_URL;
00899         ot->pattern = octstr_duplicate(url);
00900     } else if (post_url != NULL) {
00901         ot->type = TRANSTYPE_POST_URL;
00902         ot->pattern = octstr_duplicate(post_url);
00903         ot->catch_all = 1;
00904     } else if (post_xml != NULL) {
00905         ot->type = TRANSTYPE_POST_XML;
00906         ot->pattern = octstr_duplicate(post_xml);
00907         ot->catch_all = 1;
00908     } else if (file != NULL) {
00909         ot->type = TRANSTYPE_FILE;
00910         ot->pattern = octstr_duplicate(file);
00911     } else if (text != NULL) {
00912         ot->type = TRANSTYPE_TEXT;
00913         ot->pattern = octstr_duplicate(text);
00914     } else if (exec != NULL) {
00915         ot->type = TRANSTYPE_EXECUTE;
00916         ot->pattern = octstr_duplicate(exec);
00917     } else {
00918         octstr_destroy(url);
00919         octstr_destroy(post_url);
00920         octstr_destroy(post_xml);
00921         octstr_destroy(file);
00922         octstr_destroy(text);
00923         octstr_destroy(exec);
00924         error(0, "Configuration group `sms-service' "
00925                  "did not specify get-url, post-url, post-xml, file or text.");
00926             goto error;
00927     }
00928     octstr_destroy(url);
00929     octstr_destroy(post_url);
00930     octstr_destroy(post_xml);
00931     octstr_destroy(file);
00932     octstr_destroy(text);
00933     octstr_destroy(exec);
00934 
00935     tmp = cfg_get(grp, octstr_imm("keyword"));
00936         keyword_regex = cfg_get(grp, octstr_imm("keyword-regex"));
00937     if (tmp == NULL && keyword_regex == NULL) {
00938         error(0, "Group 'sms-service' must include either 'keyword' or 'keyword-regex'.");
00939         goto error;
00940     }
00941     if (tmp != NULL && keyword_regex != NULL) {
00942         error(0, "Group 'sms-service' may inlcude either 'keyword' or 'keyword-regex'.");
00943         octstr_destroy(tmp);
00944         octstr_destroy(keyword_regex);
00945         goto error;
00946     }
00947     
00948     if (tmp != NULL && octstr_str_compare(tmp, "default") == 0) {
00949         /* default sms-service */
00950         ot->keyword_regex = NULL;
00951         octstr_destroy(tmp);
00952     } else if (tmp != NULL) {
00953         Octstr *aliases;
00954         
00955         /* convert to regex */
00956             octstr_convert_range(tmp, 0, octstr_len(tmp), tolower);
00957         keyword_regex = octstr_format("^[ ]*(%S", tmp);
00958         octstr_destroy(tmp);
00959 
00960         aliases = cfg_get(grp, octstr_imm("aliases"));
00961         if (aliases != NULL) {
00962             long i;
00963             List *l;
00964 
00965             l = octstr_split(aliases, octstr_imm(";"));
00966             octstr_destroy(aliases);
00967             
00968             for (i = 0; i < gwlist_len(l); ++i) {
00969                 os = gwlist_get(l, i);
00970                 octstr_convert_range(os, 0, octstr_len(os), tolower);
00971                 octstr_format_append(keyword_regex, "|%S", os);
00972             }
00973             gwlist_destroy(l, octstr_destroy_item);
00974         }
00975         
00976         octstr_append_cstr(keyword_regex, ")[ ]*");
00977     }
00978 
00979         if (keyword_regex != NULL && (ot->keyword_regex = gw_regex_comp(keyword_regex, REG_EXTENDED)) == NULL) {
00980             error(0, "Could not compile pattern '%s'", octstr_get_cstr(keyword_regex));
00981             octstr_destroy(keyword_regex);
00982             goto error;
00983         }
00984 
00985     ot->name = cfg_get(grp, octstr_imm("name"));
00986     if (ot->name == NULL)
00987         ot->name = keyword_regex ? octstr_duplicate(keyword_regex) : octstr_create("default");
00988     octstr_destroy(keyword_regex);
00989 
00990     accepted_smsc = cfg_get(grp, octstr_imm("accepted-smsc"));
00991     if (accepted_smsc != NULL) {
00992         ot->accepted_smsc = octstr_split(accepted_smsc, octstr_imm(";"));
00993         octstr_destroy(accepted_smsc);
00994     }
00995     accepted_account = cfg_get(grp, octstr_imm("accepted-account"));
00996     if (accepted_account != NULL) {
00997         ot->accepted_account = octstr_split(accepted_account, octstr_imm(";"));
00998         octstr_destroy(accepted_account);
00999     }
01000         accepted_smsc_regex = cfg_get(grp, octstr_imm("accepted-smsc-regex"));
01001         if (accepted_smsc_regex != NULL) { 
01002             if ( (ot->accepted_smsc_regex = gw_regex_comp(accepted_smsc_regex, REG_EXTENDED)) == NULL)
01003             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(accepted_smsc_regex));
01004             octstr_destroy(accepted_smsc_regex);
01005         }
01006         accepted_account_regex = cfg_get(grp, octstr_imm("accepted-account-regex"));
01007         if (accepted_account_regex != NULL) { 
01008             if ( (ot->accepted_account_regex = gw_regex_comp(accepted_account_regex, REG_EXTENDED)) == NULL)
01009             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(accepted_account_regex));
01010             octstr_destroy(accepted_account_regex);
01011         }
01012 
01013     cfg_get_bool(&ot->assume_plain_text, grp, 
01014              octstr_imm("assume-plain-text"));
01015     cfg_get_bool(&ot->accept_x_kannel_headers, grp, 
01016              octstr_imm("accept-x-kannel-headers"));
01017     cfg_get_bool(&ot->strip_keyword, grp, octstr_imm("strip-keyword"));
01018     cfg_get_bool(&ot->send_sender, grp, octstr_imm("send-sender"));
01019     
01020     ot->prefix = cfg_get(grp, octstr_imm("prefix"));
01021     ot->suffix = cfg_get(grp, octstr_imm("suffix"));
01022         ot->allowed_recv_prefix = cfg_get(grp, octstr_imm("allowed-receiver-prefix"));
01023         allowed_receiver_prefix_regex = cfg_get(grp, octstr_imm("allowed-receiver-prefix-regex"));
01024         if (allowed_receiver_prefix_regex != NULL) {
01025             if ((ot->allowed_receiver_prefix_regex = gw_regex_comp(allowed_receiver_prefix_regex, REG_EXTENDED)) == NULL)
01026             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_receiver_prefix_regex));
01027             octstr_destroy(allowed_receiver_prefix_regex);
01028         }
01029 
01030     ot->allowed_recv_prefix = cfg_get(grp, octstr_imm("allowed-receiver-prefix"));
01031     ot->denied_recv_prefix = cfg_get(grp, octstr_imm("denied-receiver-prefix"));
01032         denied_receiver_prefix_regex = cfg_get(grp, octstr_imm("denied-receiver-prefix-regex"));
01033         if (denied_receiver_prefix_regex != NULL) {
01034             if ((ot->denied_receiver_prefix_regex = gw_regex_comp(denied_receiver_prefix_regex, REG_EXTENDED)) == NULL)
01035             panic(0, "Could not compile pattern '%s'",octstr_get_cstr(denied_receiver_prefix_regex));
01036             octstr_destroy(denied_receiver_prefix_regex);
01037         }
01038 
01039     ot->args = count_occurences(ot->pattern, octstr_imm("%s"));
01040     ot->args += count_occurences(ot->pattern, octstr_imm("%S"));
01041     ot->has_catchall_arg = 
01042         (count_occurences(ot->pattern, octstr_imm("%r")) > 0) ||
01043         (count_occurences(ot->pattern, octstr_imm("%a")) > 0);
01044 
01045     } else {
01046     ot->type = TRANSTYPE_SENDSMS;
01047     ot->pattern = octstr_create("");
01048     ot->args = 0;
01049     ot->has_catchall_arg = 0;
01050     ot->catch_all = 1;
01051     ot->username = cfg_get(grp, octstr_imm("username"));
01052     ot->password = cfg_get(grp, octstr_imm("password"));
01053     ot->dlr_url = cfg_get(grp, octstr_imm("dlr-url"));
01054     grp_dump(grp);
01055     if (ot->password == NULL) {
01056         error(0, "Password required for send-sms user");
01057         goto error;
01058     }
01059     ot->name = cfg_get(grp, octstr_imm("name"));
01060     if (ot->name == NULL)
01061         ot->name = octstr_duplicate(ot->username);
01062 
01063     forced_smsc = cfg_get(grp, octstr_imm("forced-smsc"));
01064     default_smsc = cfg_get(grp, octstr_imm("default-smsc"));
01065     if (forced_smsc != NULL) {
01066         if (default_smsc != NULL) {
01067         info(0, "Redundant default-smsc for send-sms user %s", 
01068              octstr_get_cstr(ot->username));
01069         }
01070         ot->forced_smsc = forced_smsc;
01071         octstr_destroy(default_smsc);
01072     } else  if (default_smsc != NULL)
01073         ot->default_smsc = default_smsc;
01074 
01075     ot->deny_ip = cfg_get(grp, octstr_imm("user-deny-ip"));
01076     ot->allow_ip = cfg_get(grp, octstr_imm("user-allow-ip"));
01077     ot->default_sender = cfg_get(grp, octstr_imm("default-sender"));
01078     }
01079     
01080     ot->allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
01081     allowed_prefix_regex = cfg_get(grp, octstr_imm("allowed-prefix-regex"));
01082     if (allowed_prefix_regex != NULL) {
01083         if ((ot->allowed_prefix_regex = gw_regex_comp(allowed_prefix_regex, REG_EXTENDED)) == NULL)
01084             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_prefix_regex));
01085         octstr_destroy(allowed_prefix_regex);
01086     }
01087     ot->denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
01088     denied_prefix_regex = cfg_get(grp, octstr_imm("denied-prefix-regex"));
01089     if (denied_prefix_regex != NULL) {
01090         if ((ot->denied_prefix_regex = gw_regex_comp(denied_prefix_regex, REG_EXTENDED)) == NULL)
01091             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(denied_prefix_regex));
01092         octstr_destroy(denied_prefix_regex);
01093     }
01094     
01095     os = cfg_get(grp, octstr_imm("white-list"));
01096     if (os != NULL) {
01097         ot->white_list = numhash_create(octstr_get_cstr(os));
01098         octstr_destroy(os);
01099     }
01100     white_list_regex = cfg_get(grp, octstr_imm("white-list-regex"));
01101     if (white_list_regex != NULL) {
01102         if ((ot->white_list_regex = gw_regex_comp(white_list_regex, REG_EXTENDED)) == NULL)
01103             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(white_list_regex));
01104         octstr_destroy(white_list_regex);
01105     }
01106 
01107     os = cfg_get(grp, octstr_imm("black-list"));
01108     if (os != NULL) {
01109         ot->black_list = numhash_create(octstr_get_cstr(os));
01110         octstr_destroy(os);
01111     }
01112     black_list_regex = cfg_get(grp, octstr_imm("black-list-regex"));
01113     if (black_list_regex != NULL) {
01114         if ((ot->black_list_regex = gw_regex_comp(black_list_regex, REG_EXTENDED)) == NULL)
01115             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(black_list_regex));
01116         octstr_destroy(black_list_regex);
01117     }
01118 
01119     if (cfg_get_integer(&ot->max_messages, grp, octstr_imm("max-messages")) == -1)
01120     ot->max_messages = 1;
01121     cfg_get_bool(&ot->concatenation, grp, octstr_imm("concatenation"));
01122     cfg_get_bool(&ot->omit_empty, grp, octstr_imm("omit-empty"));
01123     
01124     ot->header = cfg_get(grp, octstr_imm("header"));
01125     ot->footer = cfg_get(grp, octstr_imm("footer"));
01126     ot->faked_sender = cfg_get(grp, octstr_imm("faked-sender"));
01127     ot->split_chars = cfg_get(grp, octstr_imm("split-chars"));
01128     ot->split_suffix = cfg_get(grp, octstr_imm("split-suffix"));
01129 
01130     if ( (ot->prefix == NULL && ot->suffix != NULL) ||
01131      (ot->prefix != NULL && ot->suffix == NULL) ) {
01132     warning(0, "Service : suffix and prefix are only used"
01133            " if both are set.");
01134     }
01135     if ((ot->prefix != NULL || ot->suffix != NULL) &&
01136         ot->type != TRANSTYPE_GET_URL) {
01137     warning(0, "Service : suffix and prefix are only used"
01138                    " if type is 'get-url'.");
01139     }
01140     
01141     return ot;
01142 
01143 error:
01144     error(0, "Couldn't create a URLTranslation.");
01145     destroy_onetrans(ot);
01146     return NULL;
01147 }
01148 
01149 
01150 /*
01151  * Free one URLTranslation.
01152  */
01153 static void destroy_onetrans(void *p) 
01154 {
01155     URLTranslation *ot;
01156     
01157     ot = p;
01158     if (ot != NULL) {
01159     octstr_destroy(ot->dlr_url);
01160     octstr_destroy(ot->pattern);
01161     octstr_destroy(ot->prefix);
01162     octstr_destroy(ot->suffix);
01163     octstr_destroy(ot->default_sender);
01164     octstr_destroy(ot->faked_sender);
01165     octstr_destroy(ot->split_chars);
01166     octstr_destroy(ot->split_suffix);
01167     octstr_destroy(ot->header);
01168     octstr_destroy(ot->footer);
01169     gwlist_destroy(ot->accepted_smsc, octstr_destroy_item);
01170     gwlist_destroy(ot->accepted_account, octstr_destroy_item);
01171     octstr_destroy(ot->name);
01172     octstr_destroy(ot->username);
01173     octstr_destroy(ot->password);
01174     octstr_destroy(ot->forced_smsc);
01175     octstr_destroy(ot->default_smsc);
01176     octstr_destroy(ot->allow_ip);
01177     octstr_destroy(ot->deny_ip);
01178     octstr_destroy(ot->allowed_prefix);
01179     octstr_destroy(ot->denied_prefix);
01180     octstr_destroy(ot->allowed_recv_prefix);
01181     octstr_destroy(ot->denied_recv_prefix);
01182     numhash_destroy(ot->white_list);
01183     numhash_destroy(ot->black_list);
01184         if (ot->keyword_regex != NULL) gw_regex_destroy(ot->keyword_regex);
01185         if (ot->accepted_smsc_regex != NULL) gw_regex_destroy(ot->accepted_smsc_regex);
01186         if (ot->accepted_account_regex != NULL) gw_regex_destroy(ot->accepted_account_regex);
01187         if (ot->allowed_prefix_regex != NULL) gw_regex_destroy(ot->allowed_prefix_regex);
01188         if (ot->denied_prefix_regex != NULL) gw_regex_destroy(ot->denied_prefix_regex);
01189         if (ot->allowed_receiver_prefix_regex != NULL) gw_regex_destroy(ot->allowed_receiver_prefix_regex);
01190         if (ot->denied_receiver_prefix_regex != NULL) gw_regex_destroy(ot->denied_receiver_prefix_regex);
01191         if (ot->white_list_regex != NULL) gw_regex_destroy(ot->white_list_regex);
01192         if (ot->black_list_regex != NULL) gw_regex_destroy(ot->black_list_regex);
01193     gw_free(ot);
01194     }
01195 }
01196 
01197 
01198 /*
01199  * checks if the number of passed words matches the service-pattern defined in the
01200  * translation. returns 0 if arguments are okay, -1 otherwise.
01201  */
01202 static int check_num_args(URLTranslation *t, List *words)
01203 {
01204     const int IS_OKAY = 0;
01205     const int NOT_OKAY = -1;
01206     int n;
01207 
01208     
01209     n = gwlist_len(words);
01210     /* check number of arguments */
01211     if (t->catch_all)
01212         return IS_OKAY;
01213     
01214     if (n - 1 == t->args)
01215         return IS_OKAY;
01216 
01217     if (t->has_catchall_arg && n - 1 >= t->args)
01218         return IS_OKAY;
01219 
01220     return NOT_OKAY;
01221 }
01222 
01223 /*
01224  * checks if a request matches the parameters of a URL-Translation, e.g. whether or not 
01225  * a user is allowed to use certain services. returns 0 if allowed, -1 if not.
01226  */
01227 static int check_allowed_translation(URLTranslation *t,
01228                   Octstr *smsc, Octstr *sender, Octstr *receiver, Octstr *account)
01229 {
01230     const int IS_ALLOWED = 0;
01231     const int NOT_ALLOWED = -1;
01232 
01233     /* if smsc_id set and accepted_smsc exist, accept
01234      * translation only if smsc id is in accept string
01235      */
01236     if (smsc && t->accepted_smsc && !gwlist_search(t->accepted_smsc, smsc, octstr_item_match))
01237         return NOT_ALLOWED;
01238 
01239     if (smsc && t->accepted_smsc_regex && gw_regex_match_pre( t->accepted_smsc_regex, smsc) == 0)
01240         return NOT_ALLOWED;
01241 
01242     /* if account_id set and accepted_account exist, accept
01243      * translation only if smsc id is in accept string
01244      */
01245     if (account && t->accepted_account && !gwlist_search(t->accepted_account, account, octstr_item_match))
01246         return NOT_ALLOWED;
01247 
01248     if (account && t->accepted_account_regex && gw_regex_match_pre( t->accepted_account_regex, account) == 0)
01249         return NOT_ALLOWED;
01250 
01251     /* Have allowed for sender */
01252     if (t->allowed_prefix && !t->denied_prefix && does_prefix_match(t->allowed_prefix, sender) != 1)
01253         return NOT_ALLOWED;
01254 
01255     if (t->allowed_prefix_regex && !t->denied_prefix_regex && gw_regex_match_pre(t->allowed_prefix_regex, sender) == 0)
01256         return NOT_ALLOWED;
01257 
01258     /* Have denied for sender */
01259     if (t->denied_prefix && !t->allowed_prefix && does_prefix_match(t->denied_prefix, sender) == 1)
01260         return NOT_ALLOWED;
01261 
01262     if (t->denied_prefix_regex && !t->allowed_prefix_regex && gw_regex_match_pre(t->denied_prefix_regex, sender) == 1)
01263         return NOT_ALLOWED;
01264 
01265     /* Have allowed for receiver */
01266     if (t->allowed_recv_prefix && !t->denied_recv_prefix && does_prefix_match(t->allowed_recv_prefix, receiver) != 1)
01267         return NOT_ALLOWED;
01268 
01269     if (t->allowed_receiver_prefix_regex && !t->denied_receiver_prefix_regex &&
01270         gw_regex_match_pre(t->allowed_receiver_prefix_regex, receiver) == 0)
01271         return NOT_ALLOWED;
01272 
01273     /* Have denied for receiver */
01274     if (t->denied_recv_prefix && !t->allowed_recv_prefix && does_prefix_match(t->denied_recv_prefix, receiver) == 1)
01275         return NOT_ALLOWED;
01276 
01277     if (t->denied_receiver_prefix_regex && !t->allowed_receiver_prefix_regex &&
01278         gw_regex_match_pre(t->denied_receiver_prefix_regex, receiver) == 0)
01279         return NOT_ALLOWED;
01280 
01281     if (t->white_list && numhash_find_number(t->white_list, sender) < 1) {
01282         return NOT_ALLOWED;
01283     }
01284 
01285     if (t->white_list_regex && gw_regex_match_pre(t->white_list_regex, sender) == 0) {
01286         return NOT_ALLOWED;
01287     }   
01288 
01289     if (t->black_list && numhash_find_number(t->black_list, sender) == 1) {
01290         return NOT_ALLOWED;
01291     }
01292 
01293     if (t->black_list_regex && gw_regex_match_pre(t->black_list_regex, sender) == 1) {
01294         return NOT_ALLOWED;
01295     }   
01296 
01297     /* Have allowed and denied */
01298     if (t->denied_prefix && t->allowed_prefix && does_prefix_match(t->allowed_prefix, sender) != 1 &&
01299         does_prefix_match(t->denied_prefix, sender) == 1)
01300         return NOT_ALLOWED;
01301 
01302     if (t->denied_prefix_regex && t->allowed_prefix_regex &&
01303         gw_regex_match_pre(t->allowed_prefix_regex, sender) == 0 &&
01304         gw_regex_match_pre(t->denied_prefix_regex, sender) == 1)
01305         return NOT_ALLOWED;
01306 
01307     return IS_ALLOWED;
01308 };
01309 
01310     
01311 /* get_matching_translations - iterate over all translations in trans. 
01312  * for each translation check whether 
01313  * the translation's keyword has already been interpreted as a regexp. 
01314  * if not, compile it now,
01315  * otherwise retrieve compilation result from dictionary.
01316  *
01317  * the translations where the word matches the translation's pattern 
01318  * are returned in a list
01319  * 
01320  */
01321 static List *get_matching_translations(URLTranslationList *trans, Octstr *msg) 
01322 {
01323     List *list;
01324     long i;
01325     URLTranslation *t;
01326 
01327     gw_assert(trans != NULL && msg != NULL);
01328 
01329     list = gwlist_create();
01330     for (i = 0; i < gwlist_len(trans->list); ++i) {
01331         t = gwlist_get(trans->list, i);
01332         
01333         if (t->keyword_regex == NULL)
01334             continue;
01335 
01336         if (gw_regex_match_pre(t->keyword_regex, msg) == 1) {
01337             debug("", 0, "match found: %s", octstr_get_cstr(t->name));
01338             gwlist_append(list, t);
01339         } else {
01340             debug("", 0, "no match found: %s", octstr_get_cstr(t->name));
01341         }
01342     }
01343     
01344     return list;
01345 }
01346 
01347 /*
01348  * Find the appropriate translation 
01349  */
01350 static URLTranslation *find_translation(URLTranslationList *trans, Msg *msg)
01351 {
01352     Octstr *data;
01353     int i;
01354     URLTranslation *t = NULL;
01355     List *list, *words;
01356 
01357     /* convert tolower and try to match */
01358     data = octstr_duplicate(msg->sms.msgdata);
01359     octstr_convert_range(data, 0, octstr_len(data), tolower);
01360     i = 0;
01361     while((i = octstr_search_char(data, 0, i)) != -1 && i < octstr_len(data) - 1) {
01362         octstr_delete(data, i, 1);
01363     }
01364     
01365     list = get_matching_translations(trans, data);
01366     words = octstr_split_words(data);
01367 
01372     for (i = 0; i < gwlist_len(list); ++i) {
01373         t = gwlist_get(list, i);
01374 
01375         /* TODO check_num_args, do we really need this??? */
01376         if (check_allowed_translation(t, msg->sms.smsc_id, msg->sms.sender, msg->sms.receiver, msg->sms.account) == 0
01377             && check_num_args(t, words) == 0)
01378             break;
01379 
01380         t = NULL;
01381     }
01382 
01383     octstr_destroy(data);
01384     gwlist_destroy(words, octstr_destroy_item);
01385     gwlist_destroy(list, NULL);
01386     
01387     return t;
01388 }
01389 
01390 
01391 static URLTranslation *find_default_translation(URLTranslationList *trans,
01392                         Octstr *smsc, Octstr *sender, Octstr *receiver,
01393                         Octstr *account)
01394 {
01395     URLTranslation *t;
01396     int i;
01397     List *list;
01398 
01399     list = trans->defaults;
01400     t = NULL;
01401     for (i = 0; i < gwlist_len(list); ++i) {
01402     t = gwlist_get(list, i);
01403 
01404         if (check_allowed_translation(t, smsc, sender, receiver, account) == 0)
01405             break;
01406 
01407     t = NULL;
01408     }
01409 
01410     return t;
01411 }
01412 
01413 /*
01414  * Count the number of times `pat' occurs in `str'.
01415  */
01416 static long count_occurences(Octstr *str, Octstr *pat)
01417 {
01418     long count;
01419     long pos;
01420     long len;
01421     
01422     count = 0;
01423     pos = 0;
01424     len = octstr_len(pat);
01425     while ((pos = octstr_search(str, pat, pos)) != -1) {
01426         ++count;
01427     pos += len;
01428     }
01429     return count;
01430 }
01431 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.