📄 urltrans.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * urltrans.c - URL translations * * Lars Wirzenius */#include <ctype.h>#include <errno.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "urltrans.h"#include "gwlib/gwlib.h"#include "gw/sms.h"#include "gwlib/regex.h"/*********************************************************************** * Definitions of data structures. These are not visible to the external * world -- they may be accessed only via the functions declared in * urltrans.h. *//* * Hold one keyword/options entity */struct URLTranslation { Octstr *keyword; /* keyword in SMS (similar) query */ List *aliases; /* keyword aliases, List of Octstr */ int type; /* see enumeration in header file */ Octstr *pattern; /* url, text or file-name pattern */ Octstr *prefix; /* for prefix-cut */ Octstr *suffix; /* for suffix-cut */ Octstr *faked_sender;/* works only with certain services */ Octstr *default_sender;/* Default sender to sendsms-user */ long max_messages; /* absolute limit of reply messages */ int concatenation; /* send long messages as concatenated SMS's if true */ Octstr *split_chars;/* allowed chars to be used to split message */ Octstr *split_suffix;/* chars added to end after each split (not last) */ int omit_empty; /* if the reply is empty, is notification send */ Octstr *header; /* string to be inserted to each SMS */ Octstr *footer; /* string to be appended to each SMS */ List *accepted_smsc; /* smsc id's allowed to use this service. If not set, all messages can use this service */ Octstr *name; /* Translation name */ Octstr *username; /* send sms username */ Octstr *password; /* password associated */ Octstr *forced_smsc;/* if smsc id is forcet to certain for this user */ Octstr *default_smsc; /* smsc id if none given in http send-sms request */ Octstr *allow_ip; /* allowed IPs to request send-sms with this account */ Octstr *deny_ip; /* denied IPs to request send-sms with this account */ Octstr *allowed_prefix; /* Prefixes (of sender) allowed in this translation, or... */ Octstr *denied_prefix; /* ...denied prefixes */ Octstr *allowed_recv_prefix; /* Prefixes (of receiver) allowed in this translation, or... */ Octstr *denied_recv_prefix; /* ...denied prefixes */ Numhash *white_list; /* To numbers allowed, or ... */ Numhash *black_list; /* ...denied numbers */ int assume_plain_text; /* for type: octet-stream */ int accept_x_kannel_headers; /* do we accept special headers in reply */ int strip_keyword; /* POST body */ int send_sender; /* POST headers */ int args; int has_catchall_arg; int catch_all; Octstr *dlr_url; /* Url to call for delivery reports */ regex_t *keyword_regex; /* the compiled regular expression for the keyword*/ regex_t *accepted_smsc_regex; regex_t *allowed_prefix_regex; regex_t *denied_prefix_regex; regex_t *allowed_receiver_prefix_regex; regex_t *denied_receiver_prefix_regex; regex_t *white_list_regex; regex_t *black_list_regex;};/* * Hold the list of all translations. */struct URLTranslationList { List *list; Dict *dict; /* Dict of lowercase Octstr keywords*/ Dict *names; /* Dict of lowercase Octstr names */};/*********************************************************************** * Declarations of internal functions. These are defined at the end of * the file. */static long count_occurences(Octstr *str, Octstr *pat);static URLTranslation *create_onetrans(CfgGroup *grp);static void destroy_onetrans(void *ot);static URLTranslation *find_translation(URLTranslationList *trans, List *words, Octstr *smsc, Octstr *sender, Octstr *receiver, int *reject);static URLTranslation *find_default_translation(URLTranslationList *trans, Octstr *smsc, Octstr *sender, Octstr *receiver, int *reject);static URLTranslation *find_black_list_translation(URLTranslationList *trans, Octstr *smsc);/*********************************************************************** * Implementations of the functions declared in urltrans.h. See the * header for explanations of what they should do. */static void destroy_keyword_list(void *list){ list_destroy(list, NULL);}URLTranslationList *urltrans_create(void) { URLTranslationList *trans; trans = gw_malloc(sizeof(URLTranslationList)); trans->list = list_create(); trans->dict = dict_create(1024, destroy_keyword_list); trans->names = dict_create(1024, destroy_keyword_list); return trans;}void urltrans_destroy(URLTranslationList *trans) { list_destroy(trans->list, destroy_onetrans); dict_destroy(trans->names); dict_destroy(trans->dict); gw_free(trans);}int urltrans_add_one(URLTranslationList *trans, CfgGroup *grp){ URLTranslation *ot; long i; List *list, *list2; Octstr *alias; ot = create_onetrans(grp); if (ot == NULL) return -1; list_append(trans->list, ot); list2 = dict_get(trans->names, ot->name); if (list2 == NULL) { list2 = list_create(); dict_put(trans->names, ot->name, list2); } list_append(list2, ot); if (ot->keyword == NULL || ot->type == TRANSTYPE_SENDSMS) return 0; list = dict_get(trans->dict, ot->keyword); if (list == NULL) { list = list_create(); dict_put(trans->dict, ot->keyword, list); } list_append(list, ot); for (i = 0; i < list_len(ot->aliases); ++i) { alias = list_get(ot->aliases, i); list = dict_get(trans->dict, alias); if (list == NULL) { list = list_create(); dict_put(trans->dict, alias, list); } list_append(list, ot); } return 0;}int urltrans_add_cfg(URLTranslationList *trans, Cfg *cfg) { CfgGroup *grp; List *list; list = cfg_get_multi_group(cfg, octstr_imm("sms-service")); while (list && (grp = list_extract_first(list)) != NULL) { if (urltrans_add_one(trans, grp) == -1) { list_destroy(list, NULL); return -1; } } list_destroy(list, NULL); list = cfg_get_multi_group(cfg, octstr_imm("sendsms-user")); while (list && (grp = list_extract_first(list)) != NULL) { if (urltrans_add_one(trans, grp) == -1) { list_destroy(list, NULL); return -1; } } list_destroy(list, NULL); return 0;}URLTranslation *urltrans_find(URLTranslationList *trans, Octstr *text, Octstr *smsc, Octstr *sender, Octstr *receiver) { List *words; URLTranslation *t = NULL; int reject = 0; /* do not panic if text == NULL */ if (text != NULL) { words = octstr_split_words(text); t = find_translation(trans, words, smsc, sender, receiver, &reject); list_destroy(words, octstr_destroy_item); } if (reject) t = find_black_list_translation(trans, smsc); if (t == NULL) { t = find_default_translation(trans, smsc, sender, receiver, &reject); if (reject) t = find_black_list_translation(trans, smsc); } return t;}URLTranslation *urltrans_find_service(URLTranslationList *trans, Msg *msg){ URLTranslation *t; List *list; list = dict_get(trans->names, msg->sms.service); if (list != NULL) { t = list_get(list, 0); } else { t = NULL; } return t;}URLTranslation *urltrans_find_username(URLTranslationList *trans, Octstr *name){ URLTranslation *t; int i; gw_assert(name != NULL); for (i = 0; i < list_len(trans->list); ++i) { t = list_get(trans->list, i); if (t->type == TRANSTYPE_SENDSMS) { if (octstr_compare(name, t->username) == 0) return t; } } return NULL;}/* * Remove the first word and the whitespace that follows it from * the start of the message data. */static void strip_keyword(Msg *request){ int ch; long pos; pos = 0; for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++) if (isspace(ch)) break; for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++) if (!isspace(ch)) break; octstr_delete(request->sms.msgdata, 0, pos);}/* * Trans being NULL means that we are servicing ppg (doing dlr, but this does not * concern us here). */Octstr *urltrans_get_pattern(URLTranslation *t, Msg *request){ Octstr *enc; int nextarg, j; struct tm tm; int num_words; List *word_list; Octstr *result, *pattern; long pattern_len; long pos; int c; long i; Octstr *temp; Octstr *url, *reply; /* For and If delivery report */ url = reply = NULL; if (request->sms.sms_type != report_mo && t->type == TRANSTYPE_SENDSMS) return octstr_create(""); if (request->sms.msgdata) { word_list = octstr_split_words(request->sms.msgdata); num_words = list_len(word_list); } else { word_list = list_create(); num_words = 0; } result = octstr_create(""); /* check if this is a delivery report message or not */ if (request->sms.sms_type != report_mo) { pattern = t->pattern; } else { /* this is a DLR message */ reply = octstr_duplicate(request->sms.msgdata); url = octstr_duplicate(request->sms.dlr_url); pattern = url; if (octstr_len(pattern) == 0) { if (t && octstr_len(t->dlr_url)) { pattern = t->dlr_url; } else { list_destroy(word_list, octstr_destroy_item); return octstr_create(""); } } } pattern_len = octstr_len(pattern); nextarg = 1; pos = 0; for (;;) { while (pos < pattern_len) { c = octstr_get_char(pattern, pos); if (c == '%' && pos + 1 < pattern_len) break; octstr_append_char(result, c); ++pos; } if (pos == pattern_len) break; switch (octstr_get_char(pattern, pos + 1)) { case 'k': if (num_words <= 0) break; enc = octstr_duplicate(list_get(word_list, 0)); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 's': if (nextarg >= num_words) break; enc = octstr_duplicate(list_get(word_list, nextarg)); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); ++nextarg; break; case 'S': if (nextarg >= num_words) break; temp = list_get(word_list, nextarg); for (i = 0; i < octstr_len(temp); ++i) { if (octstr_get_char(temp, i) == '*') octstr_append_char(result, '~'); else octstr_append_char(result, octstr_get_char(temp, i)); } ++nextarg; break; case 'r': for (j = nextarg; j < num_words; ++j) { enc = octstr_duplicate(list_get(word_list, j)); octstr_url_encode(enc); if (j != nextarg) octstr_append_char(result, '+'); octstr_append(result, enc); octstr_destroy(enc); } break; /* NOTE: the sender and receiver is already switched in * message, so that's why we must use 'sender' when * we want original receiver and vice versa */ case 'P': enc = octstr_duplicate(request->sms.sender); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'p': enc = octstr_duplicate(request->sms.receiver); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'Q': if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) { enc = octstr_copy(request->sms.sender, 2,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -