1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2014 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  *    if any, must include the following acknowledgment:
22  *       "This product includes software developed by the
23  *        Kannel Group (http://www.kannel.org/)."
24  *    Alternately, this acknowledgment may appear in the software itself,
25  *    if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  *    endorse or promote products derived from this software without
29  *    prior written permission. For written permission, please
30  *    contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  *    nor may "Kannel" appear in their name, without prior written
34  *    permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group.  For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * urltrans.c - URL translations
59  *
60  * Lars Wirzenius
61  */
62 
63 
64 #include <ctype.h>
65 #include <errno.h>
66 #include <limits.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <time.h>
70 
71 #include "urltrans.h"
72 #include "gwlib/gwlib.h"
73 #include "gw/sms.h"
74 #include "gw/dlr.h"
75 #include "gw/meta_data.h"
76 
77 
78 /***********************************************************************
79  * Definitions of data structures. These are not visible to the external
80  * world -- they may be accessed only via the functions declared in
81  * urltrans.h.
82  */
83 
84 
85 /*
86  * Hold one keyword/options entity
87  */
88 struct URLTranslation {
89     int type;		/* see enumeration in header file */
90     Octstr *pattern;	/* url, text or file-name pattern */
91     Octstr *prefix;	/* for prefix-cut */
92     Octstr *suffix;	/* for suffix-cut */
93     Octstr *faked_sender;/* works only with certain services */
94     Octstr *default_sender;/* Default sender to sendsms-user */
95     long max_messages;	/* absolute limit of reply messages */
96     int concatenation;	/* send long messages as concatenated SMS's if true */
97     Octstr *split_chars;/* allowed chars to be used to split message */
98     Octstr *split_suffix;/* chars added to end after each split (not last) */
99     int omit_empty;	/* if the reply is empty, is notification send */
100     Octstr *header;	/* string to be inserted to each SMS */
101     Octstr *footer;	/* string to be appended to each SMS */
102     Octstr *alt_charset; /* alternative charset to use towards service */
103     List *accepted_smsc; /* smsc id's allowed to use this service. If not set,
104 			    all messages can use this service */
105     List *accepted_account; /* account id's allowed to use this service. If not set,
106 			    all messages can use this service */
107 
108     Octstr *name;	/* Translation name */
109     Octstr *username;	/* send sms username */
110     Octstr *password;	/* password associated */
111     Octstr *forced_smsc;/* if smsc id is forcet to certain for this user */
112     Octstr *default_smsc; /* smsc id if none given in http send-sms request */
113     Octstr *allow_ip;	/* allowed IPs to request send-sms with this
114     	    	    	   account */
115     Octstr *deny_ip;	/* denied IPs to request send-sms with this account */
116     Octstr *allowed_prefix;	/* Prefixes (of sender) allowed in this translation, or... */
117     Octstr *denied_prefix;	/* ...denied prefixes */
118     Octstr *allowed_recv_prefix; /* Prefixes (of receiver) allowed in this translation, or... */
119     Octstr *denied_recv_prefix;	/* ...denied prefixes */
120     Numhash *white_list;	/* To numbers allowed, or ... */
121     Numhash *black_list; /* ...denied numbers */
122 
123     int assume_plain_text; /* for type: octet-stream */
124     int accept_x_kannel_headers; /* do we accept special headers in reply */
125     int strip_keyword;	/* POST body */
126     int send_sender;	/* POST headers */
127 
128     int args;
129     int has_catchall_arg;
130     int catch_all;
131     Octstr *dlr_url;    /* URL to call for delivery reports */
132     long dlr_mask;       /* DLR event mask */
133 
134     regex_t *keyword_regex;       /* the compiled regular expression for the keyword*/
135     regex_t *accepted_smsc_regex;
136     regex_t *accepted_account_regex;
137     regex_t *allowed_prefix_regex;
138     regex_t *denied_prefix_regex;
139     regex_t *allowed_receiver_prefix_regex;
140     regex_t *denied_receiver_prefix_regex;
141     regex_t *white_list_regex;
142     regex_t *black_list_regex;
143 };
144 
145 
146 /*
147  * Hold the list of all translations.
148  */
149 struct URLTranslationList {
150     List *list;
151     List *defaults; /* List of default sms-services */
152     Dict *names;	/* Dict of lowercase Octstr names */
153 };
154 
155 
156 /***********************************************************************
157  * Declarations of internal functions. These are defined at the end of
158  * the file.
159  */
160 
161 static long count_occurences(Octstr *str, Octstr *pat);
162 static URLTranslation *create_onetrans(CfgGroup *grp);
163 static void destroy_onetrans(void *ot);
164 static URLTranslation *find_translation(URLTranslationList *trans, Msg *msg);
165 static URLTranslation *find_default_translation(URLTranslationList *trans,
166 						Octstr *smsc, Octstr *sender, Octstr *receiver,
167 						Octstr *account);
168 
169 
170 /***********************************************************************
171  * Implementations of the functions declared in urltrans.h. See the
172  * header for explanations of what they should do.
173  */
174 
175 
destroy_keyword_list(void * list)176 static void destroy_keyword_list(void *list)
177 {
178     gwlist_destroy(list, NULL);
179 }
180 
181 
urltrans_create(void)182 URLTranslationList *urltrans_create(void)
183 {
184     URLTranslationList *trans;
185 
186     trans = gw_malloc(sizeof(URLTranslationList));
187     trans->list = gwlist_create();
188     trans->defaults = gwlist_create();
189     trans->names = dict_create(1024, destroy_keyword_list);
190     return trans;
191 }
192 
193 
urltrans_destroy(URLTranslationList * trans)194 void urltrans_destroy(URLTranslationList *trans)
195 {
196     gwlist_destroy(trans->list, destroy_onetrans);
197     gwlist_destroy(trans->defaults, destroy_onetrans);
198     dict_destroy(trans->names);
199     gw_free(trans);
200 }
201 
202 
urltrans_add_one(URLTranslationList * trans,CfgGroup * grp)203 int urltrans_add_one(URLTranslationList *trans, CfgGroup *grp)
204 {
205     URLTranslation *ot;
206     List *list2;
207 
208     ot = create_onetrans(grp);
209     if (ot == NULL)
210 	return -1;
211 
212     if (ot->type != TRANSTYPE_SENDSMS && ot->keyword_regex == NULL)
213         gwlist_append(trans->defaults, ot);
214     else
215         gwlist_append(trans->list, ot);
216 
217     list2 = dict_get(trans->names, ot->name);
218     if (list2 == NULL) {
219     	list2 = gwlist_create();
220 	dict_put(trans->names, ot->name, list2);
221     }
222     gwlist_append(list2, ot);
223 
224     return 0;
225 }
226 
227 
urltrans_add_cfg(URLTranslationList * trans,Cfg * cfg)228 int urltrans_add_cfg(URLTranslationList *trans, Cfg *cfg)
229 {
230     CfgGroup *grp;
231     List *list;
232 
233     list = cfg_get_multi_group(cfg, octstr_imm("sms-service"));
234     while (list && (grp = gwlist_extract_first(list)) != NULL) {
235 	if (urltrans_add_one(trans, grp) == -1) {
236 	    gwlist_destroy(list, NULL);
237 	    return -1;
238 	}
239     }
240     gwlist_destroy(list, NULL);
241 
242     list = cfg_get_multi_group(cfg, octstr_imm("sendsms-user"));
243     while (list && (grp = gwlist_extract_first(list)) != NULL) {
244 	if (urltrans_add_one(trans, grp) == -1) {
245 	    gwlist_destroy(list, NULL);
246 	    return -1;
247 	}
248     }
249     gwlist_destroy(list, NULL);
250 
251     return 0;
252 }
253 
254 
urltrans_find(URLTranslationList * trans,Msg * msg)255 URLTranslation *urltrans_find(URLTranslationList *trans, Msg *msg)
256 {
257     URLTranslation *t = NULL;
258 
259     t = find_translation(trans, msg);
260     if (t == NULL) {
261         t = find_default_translation(trans, msg->sms.smsc_id, msg->sms.sender, msg->sms.receiver, msg->sms.account);
262     }
263 
264     return t;
265 }
266 
267 
urltrans_find_service(URLTranslationList * trans,Msg * msg)268 URLTranslation *urltrans_find_service(URLTranslationList *trans, Msg *msg)
269 {
270     URLTranslation *t;
271     List *list;
272 
273     list = dict_get(trans->names, msg->sms.service);
274     if (list != NULL) {
275        t = gwlist_get(list, 0);
276     } else  {
277        t = NULL;
278     }
279     return t;
280 }
281 
282 
283 
urltrans_find_username(URLTranslationList * trans,Octstr * name)284 URLTranslation *urltrans_find_username(URLTranslationList *trans, Octstr *name)
285 {
286     URLTranslation *t;
287     int i;
288 
289     gw_assert(name != NULL);
290     for (i = 0; i < gwlist_len(trans->list); ++i) {
291 	t = gwlist_get(trans->list, i);
292 	if (t->type == TRANSTYPE_SENDSMS) {
293 	    if (octstr_compare(name, t->username) == 0)
294 		return t;
295 	}
296     }
297     return NULL;
298 }
299 
300 /*
301  * Remove the first word and the whitespace that follows it from
302  * the start of the message data.
303  */
strip_keyword(Msg * request)304 static void strip_keyword(Msg *request)
305 {
306     int ch;
307     long pos;
308 
309     pos = 0;
310 
311     for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++)
312         if (isspace(ch))
313             break;
314 
315     for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++)
316         if (!isspace(ch))
317             break;
318 
319     octstr_delete(request->sms.msgdata, 0, pos);
320 }
321 
322 
urltrans_fill_escape_codes(Octstr * pattern,Msg * request)323 Octstr *urltrans_fill_escape_codes(Octstr *pattern, Msg *request)
324 {
325     Octstr *enc;
326     Octstr *meta_group, *meta_param;
327     int nextarg, j;
328     struct tm tm;
329     int num_words;
330     List *word_list;
331     Octstr *result;
332     long pattern_len;
333     long pos;
334     int c;
335     long i, k;
336     Octstr *temp;
337 
338     result = octstr_create("");
339 
340     if (request->sms.msgdata) {
341         word_list = octstr_split_words(request->sms.msgdata);
342         num_words = gwlist_len(word_list);
343     } else {
344         word_list = gwlist_create();
345         num_words = 0;
346     }
347 
348     pattern_len = octstr_len(pattern);
349     nextarg = 1;
350     pos = 0;
351     for (;;) {
352         while (pos < pattern_len) {
353             c = octstr_get_char(pattern, pos);
354             if (c == '%' && pos + 1 < pattern_len)
355                 break;
356             octstr_append_char(result, c);
357             ++pos;
358         }
359 
360         if (pos == pattern_len)
361             break;
362 
363     switch (octstr_get_char(pattern, pos + 1)) {
364     case 'a':
365         for (j = 0; j < num_words; ++j) {
366         enc = octstr_duplicate(gwlist_get(word_list, j));
367         octstr_url_encode(enc);
368         if (j > 0)
369             octstr_append_char(result, '+');
370         octstr_append(result, enc);
371         octstr_destroy(enc);
372         }
373         break;
374 
375     case 'A':
376         if (request->sms.msgdata) {
377         enc = octstr_duplicate(request->sms.msgdata);
378         octstr_url_encode(enc);
379         octstr_append(result, enc);
380         octstr_destroy(enc);
381         }
382         break;
383 
384     case 'b':
385         enc = octstr_duplicate(request->sms.msgdata);
386         octstr_url_encode(enc);
387         octstr_append(result, enc);
388         octstr_destroy(enc);
389         break;
390 
391     case 'B':  /* billing identifier/information */
392         if (octstr_len(request->sms.binfo)) {
393             enc = octstr_duplicate(request->sms.binfo);
394             octstr_url_encode(enc);
395             octstr_append(result, enc);
396             octstr_destroy(enc);
397         }
398         break;
399 
400     case 'c':
401         octstr_append_decimal(result, request->sms.coding);
402         break;
403 
404     case 'C':
405         if (octstr_len(request->sms.charset)) {
406             octstr_append(result, request->sms.charset);
407         } else {
408             switch (request->sms.coding) {
409             case DC_UNDEF:
410             case DC_7BIT:
411                 octstr_append(result, octstr_imm("UTF-8"));
412                 break;
413             case DC_8BIT:
414                 octstr_append(result, octstr_imm("8-BIT"));
415                 break;
416             case DC_UCS2:
417                 octstr_append(result, octstr_imm("UTF-16BE"));
418                 break;
419             }
420         }
421         break;
422 
423     case 'd':
424         enc = octstr_create("");
425         octstr_append_decimal(enc, request->sms.dlr_mask);
426         octstr_url_encode(enc);
427         octstr_append(result, enc);
428         octstr_destroy(enc);
429         break;
430 
431     case 'D': /* meta_data */
432         if (octstr_len(request->sms.meta_data)) {
433             enc = octstr_duplicate(request->sms.meta_data);
434             octstr_url_encode(enc);
435             octstr_append(result, enc);
436             octstr_destroy(enc);
437         }
438         break;
439 
440     case 'f':  /* smsc number*/
441         if (octstr_len(request->sms.smsc_number)) {
442             enc = octstr_duplicate(request->sms.smsc_number);
443             octstr_url_encode(enc);
444             octstr_append(result, enc);
445             octstr_destroy(enc);
446         }
447         break;
448 
449     case 'F':
450         if (request->sms.foreign_id == NULL)
451             break;
452         enc = octstr_duplicate(request->sms.foreign_id);
453         octstr_url_encode(enc);
454         octstr_append(result, enc);
455         octstr_destroy(enc);
456         break;
457 
458     case 'i':
459         if (request->sms.smsc_id == NULL)
460         break;
461         enc = octstr_duplicate(request->sms.smsc_id);
462         octstr_url_encode(enc);
463         octstr_append(result, enc);
464         octstr_destroy(enc);
465         break;
466 
467     case 'I':
468         if (!uuid_is_null(request->sms.id)) {
469                 char id[UUID_STR_LEN + 1];
470                 uuid_unparse(request->sms.id, id);
471             octstr_append_cstr(result, id);
472             }
473         break;
474 
475     case 'k':
476         if (num_words <= 0)
477         break;
478         enc = octstr_duplicate(gwlist_get(word_list, 0));
479         octstr_url_encode(enc);
480         octstr_append(result, enc);
481         octstr_destroy(enc);
482         break;
483 
484     case 'm':  /* mclass - message class */
485         enc = octstr_create("");
486         octstr_append_decimal(enc, request->sms.mclass);
487         octstr_url_encode(enc);
488         octstr_append(result, enc);
489         octstr_destroy(enc);
490         break;
491 
492     case 'M':  /* mwi - message waiting indicator */
493         enc = octstr_create("");
494         octstr_append_decimal(enc, request->sms.mwi);
495         octstr_url_encode(enc);
496         octstr_append(result, enc);
497         octstr_destroy(enc);
498         break;
499 
500     case 'n':
501         if (request->sms.service == NULL)
502         break;
503         enc = octstr_duplicate(request->sms.service);
504         octstr_url_encode(enc);
505         octstr_append(result, enc);
506         octstr_destroy(enc);
507         break;
508 
509     case 'o':  /* account information (may be operator id for aggregators */
510         if (octstr_len(request->sms.account)) {
511             enc = octstr_duplicate(request->sms.account);
512             octstr_url_encode(enc);
513             octstr_append(result, enc);
514             octstr_destroy(enc);
515         }
516         break;
517 
518     case 'O':  /* DCS */
519     {
520         int dcs;
521         dcs = fields_to_dcs(request, request->sms.alt_dcs);
522         octstr_format_append(result, "%02d", dcs);
523         break;
524     }
525 
526     /* NOTE: the sender and receiver is already switched in
527      *    message, so that's why we must use 'sender' when
528      *    we want original receiver and vice versa
529      */
530     case 'P':
531         enc = octstr_duplicate(request->sms.sender);
532         octstr_url_encode(enc);
533         octstr_append(result, enc);
534         octstr_destroy(enc);
535         break;
536 
537     case 'p':
538         enc = octstr_duplicate(request->sms.receiver);
539         octstr_url_encode(enc);
540         octstr_append(result, enc);
541         octstr_destroy(enc);
542         break;
543 
544     case 'q':
545         if (strncmp(octstr_get_cstr(request->sms.receiver),"00",2)==0) {
546         enc = octstr_copy(request->sms.receiver, 2,
547                           octstr_len(request->sms.receiver));
548         octstr_url_encode(enc);
549         octstr_format_append(result, "%%2B%S", enc);
550         octstr_destroy(enc);
551         } else {
552         enc = octstr_duplicate(request->sms.receiver);
553         octstr_url_encode(enc);
554         octstr_append(result, enc);
555         octstr_destroy(enc);
556         }
557         break;
558 
559     case 'Q':
560         if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) {
561         enc = octstr_copy(request->sms.sender, 2,
562                           octstr_len(request->sms.sender));
563         octstr_url_encode(enc);
564         octstr_format_append(result, "%%2B%S", enc);
565         octstr_destroy(enc);
566         } else {
567         enc = octstr_duplicate(request->sms.sender);
568                 octstr_url_encode(enc);
569         octstr_append(result, enc);
570         octstr_destroy(enc);
571         }
572         break;
573 
574     case 'r':
575         for (j = nextarg; j < num_words; ++j) {
576         enc = octstr_duplicate(gwlist_get(word_list, j));
577         octstr_url_encode(enc);
578         if (j != nextarg)
579             octstr_append_char(result, '+');
580         octstr_append(result, enc);
581         octstr_destroy(enc);
582         }
583         break;
584 
585     case 'R': /* dlr_url */
586         if (octstr_len(request->sms.dlr_url)) {
587             enc = octstr_duplicate(request->sms.dlr_url);
588             octstr_url_encode(enc);
589             octstr_append(result, enc);
590             octstr_destroy(enc);
591         }
592         break;
593 
594     case 's':
595         if (nextarg >= num_words)
596         	break;
597         enc = octstr_duplicate(gwlist_get(word_list, nextarg));
598         octstr_url_encode(enc);
599         octstr_append(result, enc);
600         octstr_destroy(enc);
601         ++nextarg;
602         break;
603 
604     case 'S':
605         if (nextarg >= num_words)
606         	break;
607         temp = gwlist_get(word_list, nextarg);
608         for (i = 0; i < octstr_len(temp); ++i) {
609         	if (octstr_get_char(temp, i) == '*')
610         		octstr_append_char(result, '~');
611         	else
612         		octstr_append_char(result, octstr_get_char(temp, i));
613         }
614         ++nextarg;
615         break;
616 
617     case 't':
618         tm = gw_gmtime(request->sms.time);
619         octstr_format_append(result, "%04d-%02d-%02d+%02d:%02d:%02d",
620                  tm.tm_year + 1900,
621                  tm.tm_mon + 1,
622                  tm.tm_mday,
623                  tm.tm_hour,
624                  tm.tm_min,
625                  tm.tm_sec);
626         break;
627 
628     case 'T':
629         if (request->sms.time == MSG_PARAM_UNDEFINED)
630         break;
631         octstr_format_append(result, "%ld", request->sms.time);
632         break;
633 
634     case 'u':
635         if(octstr_len(request->sms.udhdata)) {
636         enc = octstr_duplicate(request->sms.udhdata);
637         octstr_url_encode(enc);
638         octstr_append(result, enc);
639         octstr_destroy(enc);
640         }
641         break;
642 
643     case 'v':
644         if (request->sms.validity != MSG_PARAM_UNDEFINED) {
645             octstr_format_append(result, "%ld", (request->sms.validity - time(NULL)) / 60);
646         }
647         break;
648 
649     case 'V':
650         if (request->sms.deferred != MSG_PARAM_UNDEFINED) {
651             octstr_format_append(result, "%ld", (request->sms.deferred - time(NULL)) / 60);
652         }
653         break;
654 
655     /*
656      * This allows to pass meta-data individual parameters into urls.
657      * The syntax is as follows: %#group#parameter#
658      * For example: %#smpp#my_param# would be replaced with the value
659      * 'my_param' from the group 'smpp' coming inside the meta_data field.
660      */
661     case '#':
662         /* ASCII 0x23 == '#' */
663         k = octstr_search_char(pattern, 0x23, pos + 2);
664         if (k >= 0) {
665             pos += 2;
666             meta_group = octstr_copy(pattern, pos, (k-pos));
667             pos = k + 1;
668             k = octstr_search_char(pattern, 0x23, pos);
669             if (k >= 0) {
670                 meta_param = octstr_copy(pattern, pos, (k-pos));
671                 pos = k - 1;
672                 if (request->sms.meta_data != NULL) {
673                     enc = meta_data_get_value(request->sms.meta_data,
674                             octstr_get_cstr(meta_group), meta_param);
675                     octstr_url_encode(enc);
676                     octstr_append(result, enc);
677                     octstr_destroy(enc);
678                 }
679                 octstr_destroy(meta_param);
680             } else {
681                 pos++;
682             }
683             octstr_destroy(meta_group);
684         }
685         break;
686 
687     /* XXX sms.parameters not present in here:
688      *   * pid - will we receive this ?
689      *   * alt-dcs - shouldn't be required unless we want to inform
690      *               which alt-dcs external server should use back
691      *   * compress - if we use compression, probably kannel would
692      *                decompress and reset this to 0. not required
693      *   * rpi - we don't receive these from smsc
694      *   * username, password, dlr-url, account - nonsense to send
695      */
696     case '%':
697         octstr_format_append(result, "%%");
698         break;
699 
700     default:
701         octstr_format_append(result, "%%%c",
702                              octstr_get_char(pattern, pos + 1));
703         break;
704     }
705 
706     pos += 2;
707     }
708 
709     gwlist_destroy(word_list, octstr_destroy_item);
710 
711     return result;
712 }
713 
714 
715 /*
716  * Trans being NULL means that we are servicing ppg (doing dlr, but this does not
717  * concern us here).
718  */
urltrans_get_pattern(URLTranslation * t,Msg * request)719 Octstr *urltrans_get_pattern(URLTranslation *t, Msg *request)
720 {
721     Octstr *result, *pattern;
722 
723     if (request->sms.sms_type != report_mo && t->type == TRANSTYPE_SENDSMS)
724         return octstr_create("");
725 
726     /* check if this is a delivery report message or not */
727     if (request->sms.sms_type != report_mo) {
728         pattern = t->pattern;
729     } else {
730         /* this is a DLR message */
731         pattern = request->sms.dlr_url;
732         if (octstr_len(pattern) == 0) {
733             if (t && octstr_len(t->dlr_url)) {
734                 pattern = t->dlr_url;
735             } else {
736                 return octstr_create("");
737             }
738         }
739     }
740 
741     /* We have pulled this out into an own exported function. This
742      * gives other modules the chance to use the same escape code
743      * semantics for Msgs. */
744     result = urltrans_fill_escape_codes(pattern, request);
745 
746     /*
747      * this SHOULD be done in smsbox, not here, but well,
748      * much easier to do here
749      */
750     if (t && (t->type == TRANSTYPE_POST_URL || t->type == TRANSTYPE_POST_XML)
751 		    && t->strip_keyword)
752 	strip_keyword(request);
753 
754     return result;
755 }
756 
757 
urltrans_type(URLTranslation * t)758 int urltrans_type(URLTranslation *t)
759 {
760     return t->type;
761 }
762 
urltrans_prefix(URLTranslation * t)763 Octstr *urltrans_prefix(URLTranslation *t)
764 {
765     return t->prefix;
766 }
767 
urltrans_suffix(URLTranslation * t)768 Octstr *urltrans_suffix(URLTranslation *t)
769 {
770     return t->suffix;
771 }
772 
urltrans_default_sender(URLTranslation * t)773 Octstr *urltrans_default_sender(URLTranslation *t)
774 {
775     return t->default_sender;
776 }
777 
urltrans_faked_sender(URLTranslation * t)778 Octstr *urltrans_faked_sender(URLTranslation *t)
779 {
780     return t->faked_sender;
781 }
782 
urltrans_max_messages(URLTranslation * t)783 int urltrans_max_messages(URLTranslation *t)
784 {
785     return t->max_messages;
786 }
787 
urltrans_concatenation(URLTranslation * t)788 int urltrans_concatenation(URLTranslation *t)
789 {
790     return t->concatenation;
791 }
792 
urltrans_split_chars(URLTranslation * t)793 Octstr *urltrans_split_chars(URLTranslation *t)
794 {
795     return t->split_chars;
796 }
797 
urltrans_split_suffix(URLTranslation * t)798 Octstr *urltrans_split_suffix(URLTranslation *t)
799 {
800     return t->split_suffix;
801 }
802 
urltrans_omit_empty(URLTranslation * t)803 int urltrans_omit_empty(URLTranslation *t)
804 {
805     return t->omit_empty;
806 }
807 
urltrans_header(URLTranslation * t)808 Octstr *urltrans_header(URLTranslation *t)
809 {
810     return t->header;
811 }
812 
urltrans_footer(URLTranslation * t)813 Octstr *urltrans_footer(URLTranslation *t)
814 {
815     return t->footer;
816 }
817 
urltrans_alt_charset(URLTranslation * t)818 Octstr *urltrans_alt_charset(URLTranslation *t)
819 {
820     return t->alt_charset;
821 }
822 
urltrans_name(URLTranslation * t)823 Octstr *urltrans_name(URLTranslation *t)
824 {
825     return t->name;
826 }
827 
urltrans_username(URLTranslation * t)828 Octstr *urltrans_username(URLTranslation *t)
829 {
830     return t->username;
831 }
832 
urltrans_password(URLTranslation * t)833 Octstr *urltrans_password(URLTranslation *t)
834 {
835     return t->password;
836 }
837 
urltrans_forced_smsc(URLTranslation * t)838 Octstr *urltrans_forced_smsc(URLTranslation *t)
839 {
840     return t->forced_smsc;
841 }
842 
urltrans_default_smsc(URLTranslation * t)843 Octstr *urltrans_default_smsc(URLTranslation *t)
844 {
845     return t->default_smsc;
846 }
847 
urltrans_allow_ip(URLTranslation * t)848 Octstr *urltrans_allow_ip(URLTranslation *t)
849 {
850     return t->allow_ip;
851 }
852 
urltrans_deny_ip(URLTranslation * t)853 Octstr *urltrans_deny_ip(URLTranslation *t)
854 {
855     return t->deny_ip;
856 }
857 
urltrans_allowed_prefix(URLTranslation * t)858 Octstr *urltrans_allowed_prefix(URLTranslation *t)
859 {
860     return t->allowed_prefix;
861 }
862 
urltrans_denied_prefix(URLTranslation * t)863 Octstr *urltrans_denied_prefix(URLTranslation *t)
864 {
865     return t->denied_prefix;
866 }
867 
urltrans_allowed_recv_prefix(URLTranslation * t)868 Octstr *urltrans_allowed_recv_prefix(URLTranslation *t)
869 {
870     return t->allowed_recv_prefix;
871 }
872 
urltrans_denied_recv_prefix(URLTranslation * t)873 Octstr *urltrans_denied_recv_prefix(URLTranslation *t)
874 {
875     return t->denied_recv_prefix;
876 }
877 
urltrans_white_list(URLTranslation * t)878 Numhash *urltrans_white_list(URLTranslation *t)
879 {
880     return t->white_list;
881 }
882 
urltrans_white_list_regex(URLTranslation * t)883 regex_t *urltrans_white_list_regex(URLTranslation *t)
884 {
885     return t->white_list_regex;
886 }
887 
urltrans_black_list(URLTranslation * t)888 Numhash *urltrans_black_list(URLTranslation *t)
889 {
890     return t->black_list;
891 }
892 
urltrans_black_list_regex(URLTranslation * t)893 regex_t *urltrans_black_list_regex(URLTranslation *t)
894 {
895     return t->black_list_regex;
896 }
897 
urltrans_assume_plain_text(URLTranslation * t)898 int urltrans_assume_plain_text(URLTranslation *t)
899 {
900     return t->assume_plain_text;
901 }
902 
urltrans_accept_x_kannel_headers(URLTranslation * t)903 int urltrans_accept_x_kannel_headers(URLTranslation *t)
904 {
905     return t->accept_x_kannel_headers;
906 }
907 
urltrans_strip_keyword(URLTranslation * t)908 int urltrans_strip_keyword(URLTranslation *t)
909 {
910     return t->strip_keyword;
911 }
912 
urltrans_send_sender(URLTranslation * t)913 int urltrans_send_sender(URLTranslation *t)
914 {
915     return t->send_sender;
916 }
917 
urltrans_dlr_url(URLTranslation * t)918 Octstr *urltrans_dlr_url(URLTranslation *t)
919 {
920     return t->dlr_url;
921 }
922 
urltrans_dlr_mask(URLTranslation * t)923 int urltrans_dlr_mask(URLTranslation *t)
924 {
925     return t->dlr_mask;
926 }
927 
928 
929 /***********************************************************************
930  * Internal functions.
931  */
932 
933 
934 /*
935  * Create one URLTranslation. Return NULL for failure, pointer to it for OK.
936  */
create_onetrans(CfgGroup * grp)937 static URLTranslation *create_onetrans(CfgGroup *grp)
938 {
939     URLTranslation *ot;
940     Octstr *url, *post_url, *post_xml, *text, *file, *exec;
941     Octstr *accepted_smsc, *accepted_account, *forced_smsc, *default_smsc;
942     Octstr *grpname;
943     int is_sms_service, regex_flag = REG_EXTENDED;
944     Octstr *accepted_smsc_regex;
945     Octstr *accepted_account_regex;
946     Octstr *allowed_prefix_regex;
947     Octstr *denied_prefix_regex;
948     Octstr *allowed_receiver_prefix_regex;
949     Octstr *denied_receiver_prefix_regex;
950     Octstr *white_list_regex;
951     Octstr *black_list_regex;
952     Octstr *keyword_regex;
953     Octstr *os, *tmp;
954 
955     grpname = cfg_get_group_name(grp);
956     if (grpname == NULL)
957     	return NULL;
958 
959     if (octstr_str_compare(grpname, "sms-service") == 0)
960         is_sms_service = 1;
961     else if (octstr_str_compare(grpname, "sendsms-user") == 0)
962         is_sms_service = 0;
963     else {
964         octstr_destroy(grpname);
965         return NULL;
966     }
967     octstr_destroy(grpname);
968 
969     ot = gw_malloc(sizeof(URLTranslation));
970     memset(ot, 0, sizeof(*ot));
971 
972     if (is_sms_service) {
973         cfg_get_bool(&ot->catch_all, grp, octstr_imm("catch-all"));
974 
975         ot->dlr_url = cfg_get(grp, octstr_imm("dlr-url"));
976         if (cfg_get_integer(&ot->dlr_mask, grp, octstr_imm("dlr-mask")) == -1)
977             ot->dlr_mask = DLR_UNDEFINED;
978         ot->alt_charset = cfg_get(grp, octstr_imm("alt-charset"));
979 
980         url = cfg_get(grp, octstr_imm("get-url"));
981         if (url == NULL)
982             url = cfg_get(grp, octstr_imm("url"));
983 
984 	post_url = cfg_get(grp, octstr_imm("post-url"));
985 	post_xml = cfg_get(grp, octstr_imm("post-xml"));
986 	file = cfg_get(grp, octstr_imm("file"));
987 	text = cfg_get(grp, octstr_imm("text"));
988 	exec = cfg_get(grp, octstr_imm("exec"));
989 	if (url != NULL) {
990 	    ot->type = TRANSTYPE_GET_URL;
991 	    ot->pattern = octstr_duplicate(url);
992 	} else if (post_url != NULL) {
993 	    ot->type = TRANSTYPE_POST_URL;
994 	    ot->pattern = octstr_duplicate(post_url);
995 	    ot->catch_all = 1;
996 	} else if (post_xml != NULL) {
997 	    ot->type = TRANSTYPE_POST_XML;
998 	    ot->pattern = octstr_duplicate(post_xml);
999 	    ot->catch_all = 1;
1000 	} else if (file != NULL) {
1001 	    ot->type = TRANSTYPE_FILE;
1002 	    ot->pattern = octstr_duplicate(file);
1003 	} else if (text != NULL) {
1004 	    ot->type = TRANSTYPE_TEXT;
1005 	    ot->pattern = octstr_duplicate(text);
1006 	} else if (exec != NULL) {
1007 	    ot->type = TRANSTYPE_EXECUTE;
1008 	    ot->pattern = octstr_duplicate(exec);
1009 	} else {
1010 	    octstr_destroy(url);
1011 	    octstr_destroy(post_url);
1012 	    octstr_destroy(post_xml);
1013 	    octstr_destroy(file);
1014 	    octstr_destroy(text);
1015 	    octstr_destroy(exec);
1016 	    error(0, "Configuration group `sms-service' "
1017 	    	     "did not specify get-url, post-url, post-xml, file or text.");
1018     	    goto error;
1019 	}
1020 	octstr_destroy(url);
1021 	octstr_destroy(post_url);
1022 	octstr_destroy(post_xml);
1023 	octstr_destroy(file);
1024 	octstr_destroy(text);
1025 	octstr_destroy(exec);
1026 
1027 	tmp = cfg_get(grp, octstr_imm("keyword"));
1028         keyword_regex = cfg_get(grp, octstr_imm("keyword-regex"));
1029 	if (tmp == NULL && keyword_regex == NULL) {
1030 	    error(0, "Group 'sms-service' must include either 'keyword' or 'keyword-regex'.");
1031 	    goto error;
1032 	}
1033 	if (tmp != NULL && keyword_regex != NULL) {
1034 	    error(0, "Group 'sms-service' may inlcude either 'keyword' or 'keyword-regex'.");
1035 	    octstr_destroy(tmp);
1036 	    octstr_destroy(keyword_regex);
1037 	    goto error;
1038 	}
1039 
1040 	if (tmp != NULL && octstr_str_compare(tmp, "default") == 0) {
1041 	    /* default sms-service */
1042 	    ot->keyword_regex = NULL;
1043 	    octstr_destroy(tmp);
1044 	} else if (tmp != NULL) {
1045 	    Octstr *aliases;
1046 
1047 	    /* convert to regex */
1048 	    regex_flag |= REG_ICASE;
1049 	    keyword_regex = octstr_format("^[ ]*(%S", tmp);
1050 	    octstr_destroy(tmp);
1051 
1052 	    aliases = cfg_get(grp, octstr_imm("aliases"));
1053 	    if (aliases != NULL) {
1054 	        long i;
1055 	        List *l;
1056 
1057 	        l = octstr_split(aliases, octstr_imm(";"));
1058 	        octstr_destroy(aliases);
1059 
1060 	        for (i = 0; i < gwlist_len(l); ++i) {
1061 	            os = gwlist_get(l, i);
1062 	            octstr_format_append(keyword_regex, "|%S", os);
1063 	        }
1064 	        gwlist_destroy(l, octstr_destroy_item);
1065 	    }
1066 
1067 	    octstr_append_cstr(keyword_regex, ")[ ]*");
1068 	}
1069 
1070         if (keyword_regex != NULL && (ot->keyword_regex = gw_regex_comp(keyword_regex, regex_flag)) == NULL) {
1071             error(0, "Could not compile pattern '%s'", octstr_get_cstr(keyword_regex));
1072             octstr_destroy(keyword_regex);
1073             goto error;
1074         }
1075 
1076 	ot->name = cfg_get(grp, octstr_imm("name"));
1077 	if (ot->name == NULL)
1078 	    ot->name = keyword_regex ? octstr_duplicate(keyword_regex) : octstr_create("default");
1079 	octstr_destroy(keyword_regex);
1080 
1081 	accepted_smsc = cfg_get(grp, octstr_imm("accepted-smsc"));
1082 	if (accepted_smsc != NULL) {
1083 	    ot->accepted_smsc = octstr_split(accepted_smsc, octstr_imm(";"));
1084 	    octstr_destroy(accepted_smsc);
1085 	}
1086 	accepted_account = cfg_get(grp, octstr_imm("accepted-account"));
1087 	if (accepted_account != NULL) {
1088 	    ot->accepted_account = octstr_split(accepted_account, octstr_imm(";"));
1089 	    octstr_destroy(accepted_account);
1090 	}
1091         accepted_smsc_regex = cfg_get(grp, octstr_imm("accepted-smsc-regex"));
1092         if (accepted_smsc_regex != NULL) {
1093             if ( (ot->accepted_smsc_regex = gw_regex_comp(accepted_smsc_regex, REG_EXTENDED)) == NULL)
1094             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(accepted_smsc_regex));
1095             octstr_destroy(accepted_smsc_regex);
1096         }
1097         accepted_account_regex = cfg_get(grp, octstr_imm("accepted-account-regex"));
1098         if (accepted_account_regex != NULL) {
1099             if ( (ot->accepted_account_regex = gw_regex_comp(accepted_account_regex, REG_EXTENDED)) == NULL)
1100             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(accepted_account_regex));
1101             octstr_destroy(accepted_account_regex);
1102         }
1103 
1104 	cfg_get_bool(&ot->assume_plain_text, grp,
1105 		     octstr_imm("assume-plain-text"));
1106 	cfg_get_bool(&ot->accept_x_kannel_headers, grp,
1107 		     octstr_imm("accept-x-kannel-headers"));
1108 	cfg_get_bool(&ot->strip_keyword, grp, octstr_imm("strip-keyword"));
1109 	cfg_get_bool(&ot->send_sender, grp, octstr_imm("send-sender"));
1110 
1111 	ot->prefix = cfg_get(grp, octstr_imm("prefix"));
1112 	ot->suffix = cfg_get(grp, octstr_imm("suffix"));
1113         ot->allowed_recv_prefix = cfg_get(grp, octstr_imm("allowed-receiver-prefix"));
1114         allowed_receiver_prefix_regex = cfg_get(grp, octstr_imm("allowed-receiver-prefix-regex"));
1115         if (allowed_receiver_prefix_regex != NULL) {
1116             if ((ot->allowed_receiver_prefix_regex = gw_regex_comp(allowed_receiver_prefix_regex, REG_EXTENDED)) == NULL)
1117             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_receiver_prefix_regex));
1118             octstr_destroy(allowed_receiver_prefix_regex);
1119         }
1120 
1121 	ot->allowed_recv_prefix = cfg_get(grp, octstr_imm("allowed-receiver-prefix"));
1122 	ot->denied_recv_prefix = cfg_get(grp, octstr_imm("denied-receiver-prefix"));
1123         denied_receiver_prefix_regex = cfg_get(grp, octstr_imm("denied-receiver-prefix-regex"));
1124         if (denied_receiver_prefix_regex != NULL) {
1125             if ((ot->denied_receiver_prefix_regex = gw_regex_comp(denied_receiver_prefix_regex, REG_EXTENDED)) == NULL)
1126             panic(0, "Could not compile pattern '%s'",octstr_get_cstr(denied_receiver_prefix_regex));
1127             octstr_destroy(denied_receiver_prefix_regex);
1128         }
1129 
1130 	ot->args = count_occurences(ot->pattern, octstr_imm("%s"));
1131 	ot->args += count_occurences(ot->pattern, octstr_imm("%S"));
1132 	ot->has_catchall_arg =
1133 	    (count_occurences(ot->pattern, octstr_imm("%r")) > 0) ||
1134 	    (count_occurences(ot->pattern, octstr_imm("%a")) > 0);
1135 
1136     } else {
1137 	ot->type = TRANSTYPE_SENDSMS;
1138 	ot->pattern = octstr_create("");
1139 	ot->args = 0;
1140 	ot->has_catchall_arg = 0;
1141 	ot->catch_all = 1;
1142 	ot->username = cfg_get(grp, octstr_imm("username"));
1143 	ot->password = cfg_get(grp, octstr_imm("password"));
1144 	ot->dlr_url = cfg_get(grp, octstr_imm("dlr-url"));
1145 	grp_dump(grp);
1146 	if (ot->password == NULL) {
1147 	    error(0, "Password required for send-sms user");
1148 	    goto error;
1149 	}
1150 	ot->name = cfg_get(grp, octstr_imm("name"));
1151 	if (ot->name == NULL)
1152 	    ot->name = octstr_duplicate(ot->username);
1153 
1154 	forced_smsc = cfg_get(grp, octstr_imm("forced-smsc"));
1155 	default_smsc = cfg_get(grp, octstr_imm("default-smsc"));
1156 	if (forced_smsc != NULL) {
1157 	    if (default_smsc != NULL) {
1158 		info(0, "Redundant default-smsc for send-sms user %s",
1159 		     octstr_get_cstr(ot->username));
1160 	    }
1161 	    ot->forced_smsc = forced_smsc;
1162 	    octstr_destroy(default_smsc);
1163 	} else  if (default_smsc != NULL)
1164 	    ot->default_smsc = default_smsc;
1165 
1166 	ot->deny_ip = cfg_get(grp, octstr_imm("user-deny-ip"));
1167 	ot->allow_ip = cfg_get(grp, octstr_imm("user-allow-ip"));
1168 	ot->default_sender = cfg_get(grp, octstr_imm("default-sender"));
1169     }
1170 
1171     ot->allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
1172     allowed_prefix_regex = cfg_get(grp, octstr_imm("allowed-prefix-regex"));
1173     if (allowed_prefix_regex != NULL) {
1174         if ((ot->allowed_prefix_regex = gw_regex_comp(allowed_prefix_regex, REG_EXTENDED)) == NULL)
1175             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_prefix_regex));
1176         octstr_destroy(allowed_prefix_regex);
1177     }
1178     ot->denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
1179     denied_prefix_regex = cfg_get(grp, octstr_imm("denied-prefix-regex"));
1180     if (denied_prefix_regex != NULL) {
1181         if ((ot->denied_prefix_regex = gw_regex_comp(denied_prefix_regex, REG_EXTENDED)) == NULL)
1182             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(denied_prefix_regex));
1183         octstr_destroy(denied_prefix_regex);
1184     }
1185 
1186     os = cfg_get(grp, octstr_imm("white-list"));
1187     if (os != NULL) {
1188         ot->white_list = numhash_create(octstr_get_cstr(os));
1189         octstr_destroy(os);
1190     }
1191     white_list_regex = cfg_get(grp, octstr_imm("white-list-regex"));
1192     if (white_list_regex != NULL) {
1193         if ((ot->white_list_regex = gw_regex_comp(white_list_regex, REG_EXTENDED)) == NULL)
1194             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(white_list_regex));
1195         octstr_destroy(white_list_regex);
1196     }
1197 
1198     os = cfg_get(grp, octstr_imm("black-list"));
1199     if (os != NULL) {
1200         ot->black_list = numhash_create(octstr_get_cstr(os));
1201         octstr_destroy(os);
1202     }
1203     black_list_regex = cfg_get(grp, octstr_imm("black-list-regex"));
1204     if (black_list_regex != NULL) {
1205         if ((ot->black_list_regex = gw_regex_comp(black_list_regex, REG_EXTENDED)) == NULL)
1206             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(black_list_regex));
1207         octstr_destroy(black_list_regex);
1208     }
1209 
1210     if (cfg_get_integer(&ot->max_messages, grp, octstr_imm("max-messages")) == -1)
1211 	ot->max_messages = 1;
1212     cfg_get_bool(&ot->concatenation, grp, octstr_imm("concatenation"));
1213     cfg_get_bool(&ot->omit_empty, grp, octstr_imm("omit-empty"));
1214 
1215     ot->header = cfg_get(grp, octstr_imm("header"));
1216     ot->footer = cfg_get(grp, octstr_imm("footer"));
1217     ot->faked_sender = cfg_get(grp, octstr_imm("faked-sender"));
1218     ot->split_chars = cfg_get(grp, octstr_imm("split-chars"));
1219     ot->split_suffix = cfg_get(grp, octstr_imm("split-suffix"));
1220 
1221     if ( (ot->prefix == NULL && ot->suffix != NULL) ||
1222 	 (ot->prefix != NULL && ot->suffix == NULL) ) {
1223 	warning(0, "Service : suffix and prefix are only used"
1224 		   " if both are set.");
1225     }
1226     if ((ot->prefix != NULL || ot->suffix != NULL) &&
1227         ot->type != TRANSTYPE_GET_URL) {
1228 	warning(0, "Service : suffix and prefix are only used"
1229                    " if type is 'get-url'.");
1230     }
1231 
1232     return ot;
1233 
1234 error:
1235     error(0, "Couldn't create a URLTranslation.");
1236     destroy_onetrans(ot);
1237     return NULL;
1238 }
1239 
1240 
1241 /*
1242  * Free one URLTranslation.
1243  */
destroy_onetrans(void * p)1244 static void destroy_onetrans(void *p)
1245 {
1246     URLTranslation *ot;
1247 
1248     ot = p;
1249     if (ot != NULL) {
1250 	octstr_destroy(ot->dlr_url);
1251 	octstr_destroy(ot->pattern);
1252 	octstr_destroy(ot->prefix);
1253 	octstr_destroy(ot->suffix);
1254 	octstr_destroy(ot->default_sender);
1255 	octstr_destroy(ot->faked_sender);
1256 	octstr_destroy(ot->split_chars);
1257 	octstr_destroy(ot->split_suffix);
1258 	octstr_destroy(ot->header);
1259 	octstr_destroy(ot->footer);
1260 	octstr_destroy(ot->alt_charset);
1261 	gwlist_destroy(ot->accepted_smsc, octstr_destroy_item);
1262 	gwlist_destroy(ot->accepted_account, octstr_destroy_item);
1263 	octstr_destroy(ot->name);
1264 	octstr_destroy(ot->username);
1265 	octstr_destroy(ot->password);
1266 	octstr_destroy(ot->forced_smsc);
1267 	octstr_destroy(ot->default_smsc);
1268 	octstr_destroy(ot->allow_ip);
1269 	octstr_destroy(ot->deny_ip);
1270 	octstr_destroy(ot->allowed_prefix);
1271 	octstr_destroy(ot->denied_prefix);
1272 	octstr_destroy(ot->allowed_recv_prefix);
1273 	octstr_destroy(ot->denied_recv_prefix);
1274 	numhash_destroy(ot->white_list);
1275 	numhash_destroy(ot->black_list);
1276         if (ot->keyword_regex != NULL) gw_regex_destroy(ot->keyword_regex);
1277         if (ot->accepted_smsc_regex != NULL) gw_regex_destroy(ot->accepted_smsc_regex);
1278         if (ot->accepted_account_regex != NULL) gw_regex_destroy(ot->accepted_account_regex);
1279         if (ot->allowed_prefix_regex != NULL) gw_regex_destroy(ot->allowed_prefix_regex);
1280         if (ot->denied_prefix_regex != NULL) gw_regex_destroy(ot->denied_prefix_regex);
1281         if (ot->allowed_receiver_prefix_regex != NULL) gw_regex_destroy(ot->allowed_receiver_prefix_regex);
1282         if (ot->denied_receiver_prefix_regex != NULL) gw_regex_destroy(ot->denied_receiver_prefix_regex);
1283         if (ot->white_list_regex != NULL) gw_regex_destroy(ot->white_list_regex);
1284         if (ot->black_list_regex != NULL) gw_regex_destroy(ot->black_list_regex);
1285 	gw_free(ot);
1286     }
1287 }
1288 
1289 
1290 /*
1291  * checks if the number of passed words matches the service-pattern defined in the
1292  * translation. returns 0 if arguments are okay, -1 otherwise.
1293  */
check_num_args(URLTranslation * t,List * words)1294 static int check_num_args(URLTranslation *t, List *words)
1295 {
1296     const int IS_OKAY = 0;
1297     const int NOT_OKAY = -1;
1298     int n;
1299 
1300 
1301     n = gwlist_len(words);
1302     /* check number of arguments */
1303     if (t->catch_all)
1304         return IS_OKAY;
1305 
1306     if (n - 1 == t->args)
1307         return IS_OKAY;
1308 
1309     if (t->has_catchall_arg && n - 1 >= t->args)
1310         return IS_OKAY;
1311 
1312     return NOT_OKAY;
1313 }
1314 
1315 /*
1316  * checks if a request matches the parameters of a URL-Translation, e.g. whether or not
1317  * a user is allowed to use certain services. returns 0 if allowed, -1 if not.
1318  */
check_allowed_translation(URLTranslation * t,Octstr * smsc,Octstr * sender,Octstr * receiver,Octstr * account)1319 static int check_allowed_translation(URLTranslation *t,
1320                   Octstr *smsc, Octstr *sender, Octstr *receiver, Octstr *account)
1321 {
1322     const int IS_ALLOWED = 0;
1323     const int NOT_ALLOWED = -1;
1324 
1325     /* if smsc_id set and accepted_smsc exist, accept
1326      * translation only if smsc id is in accept string
1327      */
1328     if (smsc && t->accepted_smsc && !gwlist_search(t->accepted_smsc, smsc, octstr_item_match))
1329         return NOT_ALLOWED;
1330 
1331     if (smsc && t->accepted_smsc_regex && gw_regex_match_pre( t->accepted_smsc_regex, smsc) == 0)
1332         return NOT_ALLOWED;
1333 
1334     /* if account_id set and accepted_account exist, accept
1335      * translation only if smsc id is in accept string
1336      */
1337     if (account && t->accepted_account && !gwlist_search(t->accepted_account, account, octstr_item_match))
1338         return NOT_ALLOWED;
1339 
1340     if (account && t->accepted_account_regex && gw_regex_match_pre( t->accepted_account_regex, account) == 0)
1341         return NOT_ALLOWED;
1342 
1343     /* Have allowed for sender */
1344     if (t->allowed_prefix && !t->denied_prefix && does_prefix_match(t->allowed_prefix, sender) != 1)
1345         return NOT_ALLOWED;
1346 
1347     if (t->allowed_prefix_regex && !t->denied_prefix_regex && gw_regex_match_pre(t->allowed_prefix_regex, sender) == 0)
1348         return NOT_ALLOWED;
1349 
1350     /* Have denied for sender */
1351     if (t->denied_prefix && !t->allowed_prefix && does_prefix_match(t->denied_prefix, sender) == 1)
1352         return NOT_ALLOWED;
1353 
1354     if (t->denied_prefix_regex && !t->allowed_prefix_regex && gw_regex_match_pre(t->denied_prefix_regex, sender) == 1)
1355         return NOT_ALLOWED;
1356 
1357     /* Have allowed for receiver */
1358     if (t->allowed_recv_prefix && !t->denied_recv_prefix && does_prefix_match(t->allowed_recv_prefix, receiver) != 1)
1359         return NOT_ALLOWED;
1360 
1361     if (t->allowed_receiver_prefix_regex && !t->denied_receiver_prefix_regex &&
1362         gw_regex_match_pre(t->allowed_receiver_prefix_regex, receiver) == 0)
1363         return NOT_ALLOWED;
1364 
1365     /* Have denied for receiver */
1366     if (t->denied_recv_prefix && !t->allowed_recv_prefix && does_prefix_match(t->denied_recv_prefix, receiver) == 1)
1367         return NOT_ALLOWED;
1368 
1369     if (t->denied_receiver_prefix_regex && !t->allowed_receiver_prefix_regex &&
1370         gw_regex_match_pre(t->denied_receiver_prefix_regex, receiver) == 0)
1371         return NOT_ALLOWED;
1372 
1373     if (t->white_list && numhash_find_number(t->white_list, sender) < 1) {
1374         return NOT_ALLOWED;
1375     }
1376 
1377     if (t->white_list_regex && gw_regex_match_pre(t->white_list_regex, sender) == 0) {
1378         return NOT_ALLOWED;
1379     }
1380 
1381     if (t->black_list && numhash_find_number(t->black_list, sender) == 1) {
1382         return NOT_ALLOWED;
1383     }
1384 
1385     if (t->black_list_regex && gw_regex_match_pre(t->black_list_regex, sender) == 1) {
1386         return NOT_ALLOWED;
1387     }
1388 
1389     /* Have allowed and denied */
1390     if (t->denied_prefix && t->allowed_prefix && does_prefix_match(t->allowed_prefix, sender) != 1 &&
1391         does_prefix_match(t->denied_prefix, sender) == 1)
1392         return NOT_ALLOWED;
1393 
1394     if (t->denied_prefix_regex && t->allowed_prefix_regex &&
1395         gw_regex_match_pre(t->allowed_prefix_regex, sender) == 0 &&
1396         gw_regex_match_pre(t->denied_prefix_regex, sender) == 1)
1397         return NOT_ALLOWED;
1398 
1399     return IS_ALLOWED;
1400 };
1401 
1402 
1403 /* get_matching_translations - iterate over all translations in trans.
1404  * for each translation check whether
1405  * the translation's keyword has already been interpreted as a regexp.
1406  * if not, compile it now,
1407  * otherwise retrieve compilation result from dictionary.
1408  *
1409  * the translations where the word matches the translation's pattern
1410  * are returned in a list
1411  *
1412  */
get_matching_translations(URLTranslationList * trans,Octstr * msg)1413 static List *get_matching_translations(URLTranslationList *trans, Octstr *msg)
1414 {
1415     List *list;
1416     long i;
1417     URLTranslation *t;
1418 
1419     gw_assert(trans != NULL && msg != NULL);
1420 
1421     list = gwlist_create();
1422     for (i = 0; i < gwlist_len(trans->list); ++i) {
1423         t = gwlist_get(trans->list, i);
1424 
1425         if (t->keyword_regex == NULL)
1426             continue;
1427 
1428         if (gw_regex_match_pre(t->keyword_regex, msg) == 1) {
1429             debug("", 0, "match found: %s", octstr_get_cstr(t->name));
1430             gwlist_append(list, t);
1431         } else {
1432             debug("", 0, "no match found: %s", octstr_get_cstr(t->name));
1433         }
1434     }
1435 
1436     return list;
1437 }
1438 
1439 /*
1440  * Find the appropriate translation
1441  */
find_translation(URLTranslationList * trans,Msg * msg)1442 static URLTranslation *find_translation(URLTranslationList *trans, Msg *msg)
1443 {
1444     Octstr *data;
1445     int i;
1446     URLTranslation *t = NULL;
1447     List *list, *words;
1448 
1449     /* convert tolower and try to match */
1450     data = octstr_duplicate(msg->sms.msgdata);
1451     i = 0;
1452     while((i = octstr_search_char(data, 0, i)) != -1 && i < octstr_len(data) - 1) {
1453         octstr_delete(data, i, 1);
1454     }
1455 
1456     list = get_matching_translations(trans, data);
1457     words = octstr_split_words(data);
1458 
1459     /**
1460      * List now contains all translations where the keyword of the sms
1461      * matches the pattern defined by the tranlsation's keyword.
1462      */
1463     for (i = 0; i < gwlist_len(list); ++i) {
1464         t = gwlist_get(list, i);
1465 
1466         /* TODO check_num_args, do we really need this??? */
1467         if (check_allowed_translation(t, msg->sms.smsc_id, msg->sms.sender, msg->sms.receiver, msg->sms.account) == 0
1468             && check_num_args(t, words) == 0)
1469             break;
1470 
1471         t = NULL;
1472     }
1473 
1474     octstr_destroy(data);
1475     gwlist_destroy(words, octstr_destroy_item);
1476     gwlist_destroy(list, NULL);
1477 
1478     return t;
1479 }
1480 
1481 
find_default_translation(URLTranslationList * trans,Octstr * smsc,Octstr * sender,Octstr * receiver,Octstr * account)1482 static URLTranslation *find_default_translation(URLTranslationList *trans,
1483 						Octstr *smsc, Octstr *sender, Octstr *receiver,
1484 						Octstr *account)
1485 {
1486     URLTranslation *t;
1487     int i;
1488     List *list;
1489 
1490     list = trans->defaults;
1491     t = NULL;
1492     for (i = 0; i < gwlist_len(list); ++i) {
1493 	t = gwlist_get(list, i);
1494 
1495         if (check_allowed_translation(t, smsc, sender, receiver, account) == 0)
1496             break;
1497 
1498 	t = NULL;
1499     }
1500 
1501     return t;
1502 }
1503 
1504 /*
1505  * Count the number of times `pat' occurs in `str'.
1506  */
count_occurences(Octstr * str,Octstr * pat)1507 static long count_occurences(Octstr *str, Octstr *pat)
1508 {
1509     long count;
1510     long pos;
1511     long len;
1512 
1513     count = 0;
1514     pos = 0;
1515     len = octstr_len(pat);
1516     while ((pos = octstr_search(str, pat, pos)) != -1) {
1517     	++count;
1518 	pos += len;
1519     }
1520     return count;
1521 }
1522 
1523