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