smsbox.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:94k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * smsbox.c - main program of the smsbox
  3.  */
  4. #include <errno.h>
  5. #include <unistd.h>
  6. #include <signal.h>
  7. #include <string.h>
  8. #include "gwlib/gwlib.h"
  9. #include "msg.h"
  10. #include "sms.h"
  11. #include "bb.h"
  12. #include "shared.h"
  13. #include "heartbeat.h"
  14. #include "html.h"
  15. #include "urltrans.h"
  16. #include "ota_prov_attr.h"
  17. #include "ota_prov.h"
  18. #include "ota_compiler.h"
  19. #ifdef HAVE_SECURITY_PAM_APPL_H
  20. #include <security/pam_appl.h>
  21. #endif
  22. /*
  23.  * Maximum number of octets in an SMS message. Note that this is 8 bit
  24.  * characters, not 7 bit characters.
  25.  */
  26. enum { MAX_SMS_OCTETS = 140 };
  27. #define SENDSMS_DEFAULT_CHARS "0123456789 +-"
  28. #define O_DESTROY(a) { if(a) octstr_destroy(a); a = NULL; }
  29. /* Defaults for the HTTP request queueing inside http_queue_thread */
  30. #define HTTP_MAX_RETRIES    0
  31. #define HTTP_RETRY_DELAY    10 /* in sec. */
  32. static Cfg *cfg;
  33. static long bb_port;
  34. static int bb_ssl = 0;
  35. static long sendsms_port = 0;
  36. static Octstr *sendsms_url = NULL;
  37. static Octstr *sendota_url = NULL;
  38. static Octstr *xmlrpc_url = NULL;
  39. static Octstr *bb_host;
  40. static char *pid_file;
  41. static Octstr *accepted_chars = NULL;
  42. static int only_try_http = 0;
  43. static URLTranslationList *translations = NULL;
  44. static long sms_max_length = MAX_SMS_OCTETS;
  45. static char *sendsms_number_chars;
  46. static Octstr *global_sender = NULL;
  47. static Octstr *reply_couldnotfetch = NULL;
  48. static Octstr *reply_couldnotrepresent = NULL;
  49. static Octstr *reply_requestfailed = NULL;
  50. static Octstr *reply_emptymessage = NULL;
  51. static int mo_recode = 0;
  52. static Numhash *white_list;
  53. static Numhash *black_list;
  54. static unsigned long max_http_retries = HTTP_MAX_RETRIES;
  55. static unsigned long http_queue_delay = HTTP_RETRY_DELAY;
  56. static List *smsbox_requests = NULL;      /* the inbound request queue */
  57. static List *smsbox_http_requests = NULL; /* the outbound HTTP request queue */
  58. int charset_processing (Octstr *charset, Octstr *text, int coding);
  59. long get_tag(Octstr *body, Octstr *tag, Octstr **value, long pos, int nostrip);
  60. /***********************************************************************
  61.  * Communication with the bearerbox.
  62.  */
  63. /*
  64.  * Read an Msg from the bearerbox and send it to the proper receiver
  65.  * via a List. At the moment all messages are sent to the smsbox_requests
  66.  * List.
  67.  */
  68. static void read_messages_from_bearerbox(void)
  69. {
  70.     time_t start, t;
  71.     int secs;
  72.     int total = 0;
  73.     Msg *msg;
  74.     start = t = time(NULL);
  75.     while (program_status != shutting_down) {
  76. msg = read_from_bearerbox();
  77. if (msg == NULL)
  78.     break;
  79. if (msg_type(msg) == admin) {
  80.     if (msg->admin.command == cmd_shutdown) {
  81. info(0, "Bearerbox told us to die");
  82. program_status = shutting_down;
  83.     }
  84.     /*
  85.      * XXXX here should be suspend/resume, add RSN
  86.      */
  87.     msg_destroy(msg);
  88. } else if (msg_type(msg) == sms) {
  89.     if (total == 0)
  90. start = time(NULL);
  91.     total++;
  92.     list_produce(smsbox_requests, msg);
  93. } else {
  94.     warning(0, "Received other message than sms/admin, ignoring!");
  95.     msg_destroy(msg);
  96. }
  97.     }
  98.     secs = difftime(time(NULL), start);
  99.     info(0, "Received (and handled?) %d requests in %d seconds "
  100.       "(%.2f per second)", total, secs, (float)total / secs);
  101. }
  102. /***********************************************************************
  103.  * Send Msg to bearerbox for delivery to phone, possibly split it first.
  104.  */
  105. /*
  106.  * Counter for catenated SMS messages. The counter that can be put into
  107.  * the catenated SMS message's UDH headers is actually the lowest 8 bits.
  108.  */
  109. static Counter *catenated_sms_counter;
  110.  
  111. /*
  112.  * Send a message to the bearerbox for delivery to a phone. Use
  113.  * configuration from `trans' to format the message before sending.
  114.  * Return >= 0 for success & count of splitted sms messages, 
  115.  * -1 for failure.  Does not destroy the msg.
  116.  */
  117. static int send_message(URLTranslation *trans, Msg *msg)
  118. {
  119.     int max_msgs;
  120.     Octstr *header, *footer, *suffix, *split_chars;
  121.     int catenate;
  122.     unsigned long msg_sequence, msg_count;
  123.     List *list;
  124.     Msg *part;
  125.     
  126.     gw_assert(msg != NULL);
  127.     gw_assert(msg_type(msg) == sms);
  128.     
  129.     if (trans != NULL)
  130. max_msgs = urltrans_max_messages(trans);
  131.     else
  132. max_msgs = 1;
  133.     
  134.     if (max_msgs == 0) {
  135. info(0, "No reply sent, denied.");
  136. return 0;
  137.     }
  138.     
  139.     /* Empty message?  Either ignore it or substitute the "empty"
  140.      * warning defined  */
  141.     if (octstr_len(msg->sms.msgdata) == 0) {
  142. if (trans != NULL && urltrans_omit_empty(trans))
  143.             return 0;
  144.         else
  145.     msg->sms.msgdata = octstr_duplicate(reply_emptymessage);
  146.     }
  147.     if (trans == NULL) {
  148. header = NULL;
  149. footer = NULL;
  150. suffix = NULL;
  151. split_chars = NULL;
  152. catenate = 0;
  153.     } else {
  154.      header = urltrans_header(trans);
  155. footer = urltrans_footer(trans);
  156. suffix = urltrans_split_suffix(trans);
  157. split_chars = urltrans_split_chars(trans);
  158. catenate = urltrans_concatenation(trans);
  159.     }
  160.     if (catenate)
  161.      msg_sequence = counter_increase(catenated_sms_counter) & 0xFF;
  162.     else
  163.      msg_sequence = 0;
  164.     list = sms_split(msg, header, footer, suffix, split_chars, catenate,
  165.                msg_sequence, max_msgs, sms_max_length);
  166.     msg_count = list_len(list);
  167.     debug("sms", 0, "message length %ld, sending %ld messages", 
  168.           octstr_len(msg->sms.msgdata), msg_count);
  169.     while ((part = list_extract_first(list)) != NULL)
  170. write_to_bearerbox(part);
  171.     list_destroy(list, NULL);
  172.     
  173.     return msg_count;
  174. }
  175. /***********************************************************************
  176.  * Stuff to remember which receiver belongs to which HTTP query.
  177.  * This also includes HTTP request data to queue a failed HTTP request
  178.  * into the smsbox_http_request queue which is then handled by the
  179.  * http_queue_thread thread on a re-scheduled time basis.
  180.  */
  181. static HTTPCaller *caller;
  182. static Counter *num_outstanding_requests;
  183.      
  184. struct receiver {
  185.     Msg *msg;
  186.     URLTranslation *trans;
  187.     int method;  /* the HTTP method to use */
  188.     Octstr *url; /* the after pattern URL */
  189.     List *http_headers; 
  190.     Octstr *body; /* body content of the request */
  191.     unsigned long retries; /* number of performed retries */
  192. };
  193. static void *remember_receiver(Msg *msg, URLTranslation *trans, int method, 
  194.                                Octstr *url, List *headers, Octstr *body, 
  195.                                unsigned int retries)
  196. {
  197.     struct receiver *receiver;
  198.     
  199.     counter_increase(num_outstanding_requests);
  200.     receiver = gw_malloc(sizeof(*receiver));
  201.     receiver->msg = msg_create(sms);
  202.     receiver->msg->sms.sender = octstr_duplicate(msg->sms.sender);
  203.     receiver->msg->sms.receiver = octstr_duplicate(msg->sms.receiver);
  204.     receiver->msg->sms.service = octstr_duplicate(urltrans_name(trans));
  205.     receiver->msg->sms.udhdata = NULL;
  206.     receiver->msg->sms.mclass = 0;
  207.     receiver->msg->sms.alt_dcs = 0;
  208.     receiver->msg->sms.pid = 0;
  209.     receiver->msg->sms.rpi = 0;
  210.     receiver->msg->sms.mwi = 0;
  211.     receiver->msg->sms.coding = 0;
  212.     receiver->msg->sms.compress = 0;
  213.     receiver->msg->sms.msgdata = NULL;
  214.     receiver->msg->sms.validity = 0;
  215.     receiver->msg->sms.deferred = 0;
  216.     receiver->msg->sms.time = (time_t) -1;
  217.     receiver->msg->sms.smsc_id = octstr_duplicate(msg->sms.smsc_id);
  218.     receiver->msg->sms.dlr_url = NULL;
  219.     receiver->msg->sms.dlr_mask = msg->sms.dlr_mask; 
  220.     /* to remember if it's a DLR http get */
  221.     
  222.     receiver->trans = trans;
  223.     /* remember the HTTP request if we need to queue this */
  224.     receiver->method = method;
  225.     receiver->url = octstr_duplicate(url);
  226.     receiver->http_headers = http_header_duplicate(headers);
  227.     receiver->body = octstr_duplicate(body);
  228.     receiver->retries = retries;
  229.     return receiver;
  230. }
  231. static void get_receiver(void *id, Msg **msg, URLTranslation **trans, int *method,
  232.                          Octstr **url, List **headers, Octstr **body, 
  233.                          unsigned long *retries)
  234. {
  235.     struct receiver *receiver;
  236.     
  237.     receiver = id;
  238.     *msg = receiver->msg;
  239.     *trans = receiver->trans;
  240.     *method = receiver->method;
  241.     *url = receiver->url;
  242.     *headers = receiver->http_headers;
  243.     *body = receiver->body;
  244.     *retries = receiver->retries;
  245.     gw_free(receiver);
  246.     counter_decrease(num_outstanding_requests);
  247. }
  248. static long outstanding_requests(void)
  249. {
  250.     return counter_value(num_outstanding_requests);
  251. }
  252. /***********************************************************************
  253.  * Thread for receiving reply from HTTP query and sending it to phone.
  254.  */
  255. static void strip_prefix_and_suffix(Octstr *html, Octstr *prefix, 
  256.                         Octstr *suffix)
  257. {
  258.     long prefix_end, suffix_start;
  259.     if (prefix == NULL || suffix == NULL)
  260.      return;
  261.     prefix_end = octstr_case_search(html, prefix, 0);
  262.     if (prefix_end == -1)
  263.         return;
  264.     prefix_end += octstr_len(prefix);
  265.     suffix_start = octstr_case_search(html, suffix, prefix_end);
  266.     if (suffix_start == -1)
  267.         return;
  268.     octstr_delete(html, 0, prefix_end);
  269.     octstr_truncate(html, suffix_start - prefix_end);
  270. }
  271. static void get_x_kannel_from_headers(List *headers, Octstr **from,
  272.       Octstr **to, Octstr **udh,
  273.       Octstr **user, Octstr **pass,
  274.       Octstr **smsc, int *mclass, int *mwi, 
  275.       int *coding, int *compress, 
  276.       int *validity, int *deferred, 
  277.       int *dlr_mask, Octstr **dlr_url, 
  278.       Octstr **account, int *pid, int *alt_dcs, int *rpi)
  279. {
  280.     Octstr *name, *val;
  281.     long l;
  282.     *dlr_mask = 0;
  283.     *dlr_url = NULL;
  284.     *mclass = *mwi = *coding = *compress = *validity = 
  285. *deferred = *pid = *alt_dcs = *rpi = 0;
  286.     for(l=0; l<list_len(headers); l++) {
  287. http_header_get(headers, l, &name, &val);
  288. if (octstr_case_compare(name, octstr_imm("X-Kannel-From")) == 0) {
  289.     *from = octstr_duplicate(val);
  290.     octstr_strip_blanks(*from);
  291. }
  292. else if (octstr_case_compare(name, octstr_imm("X-Kannel-To")) == 0) {
  293.     *to = octstr_duplicate(val);
  294.     octstr_strip_blanks(*to);
  295. }
  296. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Username")) == 0) {
  297.     if (user != NULL) {
  298. *user = octstr_duplicate(val);
  299. octstr_strip_blanks(*user);
  300.     }
  301. }
  302. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Password")) == 0) {
  303.     if (pass != NULL) {
  304. *pass = octstr_duplicate(val);
  305. octstr_strip_blanks(*pass);
  306.     }
  307. }
  308. else if (octstr_case_compare(name, octstr_imm("X-Kannel-SMSC")) == 0) {
  309.     if (smsc != NULL) {
  310. *smsc = octstr_duplicate(val);
  311. octstr_strip_blanks(*smsc);
  312.     }
  313. }
  314. else if (octstr_case_compare(name, octstr_imm("X-Kannel-UDH")) == 0) {
  315.     *udh = octstr_duplicate(val);
  316.     octstr_strip_blanks(*udh);
  317.     if (octstr_hex_to_binary(*udh) == -1) {
  318.         warning(0, "Invalid UDH received in X-Kannel-UDH");
  319. octstr_destroy(*udh);
  320. *udh = NULL;
  321.     }
  322. }
  323. else if (octstr_case_compare(name, octstr_imm("X-Kannel-DLR-URL")) == 0) {
  324.     *dlr_url = octstr_duplicate(val);
  325.     octstr_strip_blanks(*dlr_url);
  326. }
  327. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Account")) == 0) {
  328.     *account = octstr_duplicate(val);
  329. }
  330. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Flash")) == 0) {
  331.          sscanf(octstr_get_cstr(val),"%d", coding);
  332.     warning(0, "Flash field used and deprecated");
  333. }
  334. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Coding")) == 0) {
  335.          sscanf(octstr_get_cstr(val),"%d", coding);
  336. }
  337. else if (octstr_case_compare(name, octstr_imm("X-Kannel-PID")) == 0) {
  338.          sscanf(octstr_get_cstr(val),"%d", pid);
  339. }
  340. else if (octstr_case_compare(name, octstr_imm("X-Kannel-MWI")) == 0) {
  341.          sscanf(octstr_get_cstr(val),"%d", mwi);
  342.         }
  343. else if (octstr_case_compare(name, octstr_imm("X-Kannel-MClass")) == 0) {
  344.          sscanf(octstr_get_cstr(val),"%d", mclass);
  345.         }
  346. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Alt-DCS")) == 0) {
  347.          sscanf(octstr_get_cstr(val),"%d", alt_dcs);
  348.         }
  349. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Compress")) == 0) {
  350.          sscanf(octstr_get_cstr(val),"%d", compress);
  351.         }
  352. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Validity")) == 0) {
  353.          sscanf(octstr_get_cstr(val),"%d", validity);
  354. }
  355. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Deferred")) == 0) {
  356.          sscanf(octstr_get_cstr(val),"%d", deferred);
  357. }
  358. else if (octstr_case_compare(name, octstr_imm("X-Kannel-DLR-Mask")) == 0) {
  359.          sscanf(octstr_get_cstr(val),"%d", dlr_mask);
  360. }
  361. else if (octstr_case_compare(name, octstr_imm("X-Kannel-RPI")) == 0) {
  362.          sscanf(octstr_get_cstr(val),"%d", rpi);
  363. }
  364. octstr_destroy(name);
  365. octstr_destroy(val);
  366.     }
  367. }
  368. long get_tag(Octstr *body, Octstr *tag, Octstr **value, long pos, int nostrip) {
  369.     long start, end;
  370.     int taglen;
  371.     Octstr *tmp;
  372.     tmp = octstr_create("<");
  373.     octstr_append(tmp, tag);
  374.     octstr_append(tmp, octstr_imm(">"));
  375.     taglen = octstr_len(tmp);
  376.     start = octstr_search(body, tmp, pos);
  377.     octstr_destroy(tmp);
  378.     if(start != -1) {
  379. tmp = octstr_create("</");
  380. octstr_append(tmp, tag);
  381. octstr_append(tmp, octstr_imm(">"));
  382. end = octstr_search(body, tmp, start);
  383. octstr_destroy(tmp);
  384. if(end != -1) {
  385.     octstr_destroy(*value);
  386.     *value = octstr_copy(body, start + taglen, end - start - taglen);
  387.     if(nostrip == 0) {
  388. octstr_strip_blanks(*value);
  389. debug("sms", 0, "XMLParsing: tag <%s> value <%s>", octstr_get_cstr(tag), 
  390. octstr_get_cstr(*value));
  391.     }
  392.     return end + taglen + 1;
  393. } else {
  394.     debug("sms", 0, "XMLParsing: end tag </%s> not found", octstr_get_cstr(tag));
  395.     return -1;
  396. }
  397.     } else {
  398. // debug("sms", 0, "XMLParsing: tag <%s> not found", octstr_get_cstr(tag));
  399. return -1;
  400.     }
  401. }
  402. // requesttype = mt_reply or mt_push. for example, auth is only read on mt_push
  403. // parse body and populate fields, including replacing body for <ud> value and
  404. // type to text/plain
  405. static void get_x_kannel_from_xml(int requesttype , Octstr **type, Octstr **body, 
  406.                                   List *headers, Octstr **from,
  407.                                   Octstr **to, Octstr **udh,
  408.                                   Octstr **user, Octstr **pass,
  409.                                   Octstr **smsc, int *mclass, int *mwi,
  410.                                   int *coding, int *compress, 
  411.                                   int *validity, int *deferred,
  412.                                   int *dlr_mask, Octstr **dlr_url,
  413.                                   Octstr **account, int *pid, int *alt_dcs,
  414.                                   int *rpi, List **tolist)
  415. {                                    
  416. /*
  417.  * <?xml version="1.0" encoding="xxx"?>
  418.  * <!DOCTYPE ...
  419.  * <message>
  420.  *   <submit>
  421.  *     <da><number>...</number></da>
  422.  *     <da>...
  423.  *     <oa><number>...</number></oa>
  424.  *     <ud>...</ud>
  425.  *     <udh>0123</ud>
  426.  *     <dcs>
  427.  *       <mclass>.</mclass>
  428.  *       <coding>.</coding>
  429.  *       <mwi>.</mwi>
  430.  *       <compress>.</compress>
  431.  *       <alt-dcs>.</alt-dcs>
  432.  *     </dcs>
  433.  *     <pid>..</pid>
  434.  *     <statusrequest>
  435.  *       <dlr-mask>..</dlr-mask>
  436.  *       <dlr-url>...</dlr-url>
  437.  *     </statusrequest>
  438.  *     <from>
  439.  *       <user>...</user> ( or username)
  440.  *       <pass>...</pass> ( or password)
  441.  *       <account>...</account>
  442.  *     </from>
  443.  *     <to>smsc-id</to>
  444.  *   </submit>
  445.  * </message>
  446.  */
  447.     Octstr *text, *tmp, *tmp2;
  448.     long tmplong, where;
  449.     
  450.     tmp = tmp2 = text = NULL;
  451.     *dlr_mask = 0;
  452.     *dlr_url = NULL;
  453.     *mclass = *mwi = *coding = *compress = *validity = 
  454. *deferred = *pid = *alt_dcs = *rpi = 0;
  455.     debug("sms", 0, "XMLParsing: XML: <%s>", octstr_get_cstr(*body));
  456.     if(requesttype == mt_push) {
  457. /* auth */
  458. get_tag(*body, octstr_imm("from"), &tmp, 0, 0);
  459. if(tmp) {
  460.     /* user */
  461.     get_tag(tmp, octstr_imm("user"), user, 0, 0);
  462.     get_tag(tmp, octstr_imm("username"), user, 0, 0);
  463.     /* pass */
  464.     get_tag(tmp, octstr_imm("pass"), pass, 0, 0);
  465.     get_tag(tmp, octstr_imm("password"), pass, 0, 0);
  466.     /* account */
  467.     get_tag(tmp, octstr_imm("account"), account, 0, 0);
  468.     O_DESTROY(tmp);
  469. }
  470. /* to (da/number) Multiple tags */ 
  471. *tolist = list_create();
  472. where = get_tag(*body, octstr_imm("da"), &tmp, 0, 0);
  473. if(tmp) {
  474.     get_tag(tmp, octstr_imm("number"), to, 0, 0);
  475.     list_append(*tolist, octstr_duplicate(*to));
  476.     O_DESTROY(*to);
  477.     while(tmp && where != -1) {
  478. O_DESTROY(tmp);
  479. where = get_tag(*body, octstr_imm("da"), &tmp, where, 0);
  480. if(tmp) {
  481.     get_tag(tmp, octstr_imm("number"), &tmp2, 0, 0);
  482.     if(tmp2 != NULL) {
  483. list_append(*tolist, octstr_duplicate(tmp2));
  484. O_DESTROY(tmp2);
  485.     }
  486. }
  487.     }
  488. }
  489.     }
  490.     /* from (oa/number) */
  491.     get_tag(*body, octstr_imm("oa"), &tmp, 0, 0);
  492.     if(tmp) {
  493. get_tag(tmp, octstr_imm("number"), from, 0, 0);
  494. O_DESTROY(tmp);
  495.     }
  496.     
  497.     /* udh */
  498.     get_tag(*body, octstr_imm("udh"), &tmp, 0, 0);
  499.     if(tmp) {
  500. O_DESTROY(*udh);
  501. *udh = octstr_duplicate(tmp);
  502. octstr_hex_to_binary(*udh);
  503. O_DESTROY(tmp);
  504.     }
  505.     /* smsc */
  506.     get_tag(*body, octstr_imm("to"), smsc, 0, 0);
  507.     /* pid */
  508.     get_tag(*body, octstr_imm("pid"), &tmp, 0, 0);
  509.     if(tmp) {
  510. if(octstr_parse_long(&tmplong, tmp, 0, 10) != -1)
  511.     *pid = tmplong;
  512. O_DESTROY(tmp);
  513.     }
  514.     /* rpi */
  515.     get_tag(*body, octstr_imm("rpi"), &tmp, 0, 0);
  516.     if(tmp) {
  517. if(octstr_parse_long(&tmplong, tmp, 0, 10) != -1)
  518.     *rpi = tmplong;
  519. O_DESTROY(tmp);
  520.     }
  521.     /* dcs* (dcs/ *) */
  522.     get_tag(*body, octstr_imm("dcs"), &tmp, 0, 0);
  523.     if(tmp) {
  524. /* mclass (dcs/mclass) */
  525. get_tag(tmp, octstr_imm("mclass"), &tmp2, 0, 0);
  526. if(tmp2) {
  527.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  528. *mclass = tmplong;
  529.     O_DESTROY(tmp2);
  530. }
  531. /* mwi (dcs/mwi) */
  532. get_tag(tmp, octstr_imm("mwi"), &tmp2, 0, 0);
  533. if(tmp2) {
  534.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  535. *mwi = tmplong;
  536.     O_DESTROY(tmp2);
  537. }
  538. /* coding (dcs/coding) */
  539. get_tag(tmp, octstr_imm("coding"), &tmp2, 0, 0);
  540. if(tmp2) {
  541.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  542. *coding = tmplong;
  543.     O_DESTROY(tmp2);
  544. }
  545. /* compress (dcs/compress) */
  546. get_tag(tmp, octstr_imm("compress"), &tmp2, 0, 0);
  547. if(tmp2) {
  548.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  549. *compress = tmplong;
  550.     O_DESTROY(tmp2);
  551. }
  552. /* alt-dcs (dcs/alt-dcs) */
  553. get_tag(tmp, octstr_imm("alt-dcs"), &tmp2, 0, 0);
  554. if(tmp2) {
  555.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  556. *alt_dcs = tmplong;
  557.     O_DESTROY(tmp2);
  558. }
  559. O_DESTROY(tmp);
  560.     }
  561.     /* statusrequest* (statusrequest/ *) */
  562.     get_tag(*body, octstr_imm("statusrequest"), &tmp, 0, 0);
  563.     if(tmp) {
  564. /* dlr-mask (statusrequest/dlr-mask) */
  565. get_tag(tmp, octstr_imm("dlr-mask"), &tmp2, 0, 0);
  566. if(tmp2) {
  567.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  568. *dlr_mask = tmplong;
  569.     O_DESTROY(tmp2);
  570. }
  571. get_tag(tmp, octstr_imm("dlr-url"), dlr_url, 0, 0);
  572. O_DESTROY(tmp);
  573.     }
  574.     /* validity (vp/delay) */
  575.     get_tag(*body, octstr_imm("vp"), &tmp, 0, 0);
  576.     if(tmp) {
  577. get_tag(tmp, octstr_imm("delay"), &tmp2, 0, 0);
  578. if(tmp2) {
  579.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  580. *validity = tmplong;
  581.     O_DESTROY(tmp2);
  582. }
  583. O_DESTROY(tmp);
  584.     }
  585.     /* deferred (timing/delay) */
  586.     get_tag(*body, octstr_imm("timing"), &tmp, 0, 0);
  587.     if(tmp) {
  588. get_tag(tmp, octstr_imm("delay"), &tmp2, 0, 0);
  589. if(tmp2) {
  590.     if(octstr_parse_long(&tmplong, tmp2, 0, 10) != -1)
  591. *deferred = tmplong;
  592.     O_DESTROY(tmp2);
  593. }
  594. O_DESTROY(tmp);
  595.     }
  596.     /* text */
  597.     text = NULL;
  598.     get_tag(*body, octstr_imm("ud"), &text, 0, 0);
  599.     get_tag(*body, octstr_imm("ud-raw"), &text, 0, 1);
  600.     octstr_truncate(*body, 0);
  601.     if(text) {
  602. octstr_append(*body, text);
  603.     }
  604.     O_DESTROY(text);
  605.     
  606.     O_DESTROY(*type);
  607.     *type = octstr_create("text/plain");
  608. }
  609. static void fill_message(Msg *msg, URLTranslation *trans,
  610.  Octstr *replytext, int octet_stream,
  611.  Octstr *from, Octstr *to, Octstr *udh, 
  612.  int mclass, int mwi, int coding, int compress,
  613.  int validity, int deferred,
  614.  Octstr *dlr_url, int dlr_mask, int pid, int alt_dcs,
  615.              int rpi, Octstr *smsc)
  616. {    
  617.     msg->sms.msgdata = replytext;
  618.     msg->sms.time = time(NULL);
  619.     if (dlr_url != NULL) {
  620. if (urltrans_accept_x_kannel_headers(trans)) {
  621.     octstr_destroy(msg->sms.dlr_url);
  622.     msg->sms.dlr_url = dlr_url;
  623. } else {
  624.     warning(0, "Tried to change dlr_url to '%s', denied.",
  625.     octstr_get_cstr(dlr_url));
  626.     octstr_destroy(dlr_url);
  627. }
  628.     }
  629.     if (smsc != NULL) {
  630. if (urltrans_accept_x_kannel_headers(trans)) {
  631.     octstr_destroy(msg->sms.smsc_id);
  632.     msg->sms.smsc_id = smsc;
  633. } else {
  634.     warning(0, "Tried to change SMSC to '%s', denied.",
  635.     octstr_get_cstr(smsc));
  636.     octstr_destroy(smsc);
  637. }
  638.     }
  639.     if (from != NULL) {
  640. if (urltrans_accept_x_kannel_headers(trans)) {
  641.     octstr_destroy(msg->sms.sender);
  642.     msg->sms.sender = from;
  643. } else {
  644.     warning(0, "Tried to change sender to '%s', denied.",
  645.     octstr_get_cstr(from));
  646.     octstr_destroy(from);
  647. }
  648.     }
  649.     if (to != NULL) {
  650. if (urltrans_accept_x_kannel_headers(trans)) {
  651.     octstr_destroy(msg->sms.receiver);
  652.     msg->sms.receiver = to;
  653. } else {
  654.     warning(0, "Tried to change receiver to '%s', denied.",
  655.     octstr_get_cstr(to));
  656.     octstr_destroy(to);
  657. }
  658.     }
  659.     if (udh != NULL) {
  660. if (urltrans_accept_x_kannel_headers(trans)) {
  661.         octstr_destroy(msg->sms.udhdata);     
  662.         msg->sms.udhdata = udh;
  663. } else {
  664.     warning(0, "Tried to set UDH field, denied.");
  665.     O_DESTROY(udh);
  666. }
  667.     }
  668.     if (mclass) {
  669.         if (urltrans_accept_x_kannel_headers(trans))
  670.     msg->sms.mclass = mclass;   
  671. else 
  672.     warning(0, "Tried to set MClass field, denied.");
  673.     }
  674.     if (pid) {
  675.         if (urltrans_accept_x_kannel_headers(trans))
  676.     msg->sms.pid = pid;   
  677. else 
  678.     warning(0, "Tried to set PID field, denied.");
  679.     }
  680.     if (rpi) {
  681.         if (urltrans_accept_x_kannel_headers(trans))
  682.     msg->sms.rpi = rpi;   
  683. else 
  684.     warning(0, "Tried to set RPI field, denied.");
  685.     }
  686.     if (alt_dcs) {
  687.         if (urltrans_accept_x_kannel_headers(trans))
  688.     msg->sms.alt_dcs = alt_dcs;   
  689. else 
  690.     warning(0, "Tried to set Alt-DCS field, denied.");
  691.     }
  692.     if (mwi) {
  693.         if (urltrans_accept_x_kannel_headers(trans))
  694.     msg->sms.mwi = mwi;   
  695. else 
  696.     warning(0, "Tried to set MWI field, denied.");
  697.     }
  698.     if (coding) {
  699.         if (urltrans_accept_x_kannel_headers(trans))
  700.     msg->sms.coding = coding;   
  701. else
  702.     warning(0, "Tried to set Coding field, denied.");
  703.     }
  704.     if (compress) {
  705.         if (urltrans_accept_x_kannel_headers(trans))
  706.     msg->sms.compress = compress;   
  707. else
  708.     warning(0, "Tried to set Compress field, denied.");
  709.     }
  710.     /* Compatibility Mode */
  711.     if ( msg->sms.coding == DC_UNDEF) {
  712. if(octstr_len(udh))
  713.   msg->sms.coding = DC_8BIT;
  714. else
  715.   msg->sms.coding = DC_7BIT;
  716.     }
  717.     if (validity) {
  718. if (urltrans_accept_x_kannel_headers(trans))
  719.     msg->sms.validity = validity;
  720. else
  721.     warning(0, "Tried to change validity to '%d', denied.",
  722.     validity);
  723.     }
  724.     if (deferred) {
  725. if (urltrans_accept_x_kannel_headers(trans))
  726.     msg->sms.deferred = deferred;
  727. else
  728.     warning(0, "Tried to change deferred to '%d', denied.",
  729.     deferred);
  730.     }
  731.     if (dlr_mask) {
  732. if (urltrans_accept_x_kannel_headers(trans)) {
  733.     msg->sms.dlr_mask = dlr_mask;
  734. } else
  735.     warning(0, "Tried to change dlr_mask to '%d', denied.",
  736.     dlr_mask);
  737.     }
  738. }
  739. /***********************************************************************
  740.  * Thread to handle failed HTTP requests and retries to deliver the 
  741.  * information to the HTTP server. The thread uses the smsbox_http_requests
  742.  * queue that is spooled by url_result_thread in case the HTTP requests
  743.  * fails.
  744.  */
  745. static void http_queue_thread(void *arg)
  746. {
  747.     void *id;
  748.     Msg *msg;
  749.     URLTranslation *trans;
  750.     Octstr *req_url;
  751.     List *req_headers;
  752.     Octstr *req_body;
  753.     unsigned long retries;
  754.     int method;
  755.  
  756.     while ((id = list_consume(smsbox_http_requests)) != NULL) {
  757.         /* 
  758.          * Sleep for a while in order not to block other operting requests.
  759.          * Defaults to 10 sec. if not given via http-queue-delay directive in
  760.          * smsbox group.
  761.          */
  762.         if (http_queue_delay > 0) 
  763.             gwthread_sleep(http_queue_delay);
  764.         /* 
  765.          * Get all required HTTP request data from the queue and reconstruct 
  766.          * the id pointer for later lookup in url_result_thread.
  767.          */
  768.         get_receiver(id, &msg, &trans, &method, &req_url, &req_headers, &req_body, &retries);
  769.         
  770.         if (retries < max_http_retries) {
  771.             id = remember_receiver(msg, trans, method, req_url, req_headers, req_body, ++retries);
  772.         
  773.             debug("sms.http",0,"HTTP: Retrying request <%s> (%ld/%ld)",  
  774.                   octstr_get_cstr(req_url), retries, max_http_retries);
  775.             /* re-queue this request to the HTTPCaller list */
  776.             http_start_request(caller, method, req_url, req_headers, req_body, 
  777.                                1, id, NULL);
  778.         }
  779.     }
  780. }
  781. static void url_result_thread(void *arg)
  782. {
  783.     Octstr *final_url, *reply_body, *type, *charset, *replytext;
  784.     List *reply_headers;
  785.     int status, method;
  786.     void *id;
  787.     Msg *msg;
  788.     URLTranslation *trans;
  789.     Octstr *req_url;
  790.     List *req_headers;
  791.     Octstr *req_body;
  792.     Octstr *text_html;
  793.     Octstr *text_plain;
  794.     Octstr *text_wml;
  795.     Octstr *text_xml;
  796.     Octstr *octet_stream;
  797.     Octstr *udh, *from, *to;
  798.     Octstr *dlr_url;
  799.     Octstr *account;
  800.     Octstr *smsc;
  801.     int dlr_mask;
  802.     int octets;
  803.     int mclass, mwi, coding, compress, pid, alt_dcs, rpi;
  804.     int validity, deferred;
  805.     unsigned long retries;
  806.     unsigned int queued; /* indicate if processes reply is requeued */
  807.     dlr_mask = 0;
  808.     dlr_url = NULL;
  809.     text_html = octstr_imm("text/html");
  810.     text_wml = octstr_imm("text/vnd.wap.wml");
  811.     text_plain = octstr_imm("text/plain");
  812.     text_xml = octstr_imm("text/xml");
  813.     octet_stream = octstr_imm("application/octet-stream");
  814.     for (;;) {
  815.         queued = 0;
  816.         id = http_receive_result(caller, &status, &final_url, &reply_headers,
  817.                 &reply_body);
  818.         if (id == NULL)
  819.             break;
  820.     
  821.         get_receiver(id, &msg, &trans, &method, &req_url, &req_headers, &req_body, &retries);
  822.      
  823.         from = to = udh = smsc = NULL;
  824.         octets = mclass = mwi = coding = compress = pid = alt_dcs = rpi = 0;
  825.         validity = deferred = 0;
  826.         account = NULL;
  827.         if (status == HTTP_OK || status == HTTP_ACCEPTED) {
  828.             http_header_get_content_type(reply_headers, &type, &charset);
  829.             if (octstr_case_compare(type, text_html) == 0 ||
  830.                 octstr_case_compare(type, text_wml) == 0) {
  831.                 strip_prefix_and_suffix(reply_body, urltrans_prefix(trans), 
  832.                                         urltrans_suffix(trans));
  833.                 replytext = html_to_sms(reply_body);
  834.                 octstr_strip_blanks(replytext);
  835.                 get_x_kannel_from_headers(reply_headers, &from, &to, &udh,
  836.   NULL, NULL, &smsc, &mclass, &mwi, 
  837.   &coding, &compress, &validity, 
  838.   &deferred, &dlr_mask, &dlr_url, 
  839.   &account, &pid, &alt_dcs, &rpi);
  840.             } else if (octstr_case_compare(type, text_plain) == 0) {
  841.                 replytext = octstr_duplicate(reply_body);
  842.                 octstr_destroy(reply_body);
  843.                 reply_body = NULL;
  844.                 /* XXX full text octstr_strip_blanks(replytext); */
  845.                 get_x_kannel_from_headers(reply_headers, &from, &to, &udh,
  846.   NULL, NULL, &smsc, &mclass, &mwi, 
  847.   &coding, &compress, &validity, 
  848.   &deferred, &dlr_mask, &dlr_url, 
  849.   &account, &pid, &alt_dcs, &rpi);
  850.             } else if (octstr_case_compare(type, text_xml) == 0) {
  851.                 replytext = octstr_duplicate(reply_body);
  852.                 octstr_destroy(reply_body); 
  853.                 reply_body = NULL;
  854.                 get_x_kannel_from_xml(mt_reply, &type, &replytext, reply_headers, 
  855.                         &from, &to, &udh, NULL, NULL, &smsc, &mclass, &mwi, 
  856.                         &coding, &compress, &validity, &deferred, &dlr_mask, 
  857.                         &dlr_url, &account, &pid, &alt_dcs, &rpi, NULL);
  858.             } else if (octstr_case_compare(type, octet_stream) == 0) {
  859.                 replytext = octstr_duplicate(reply_body);
  860.                 octstr_destroy(reply_body);
  861.                 octets = 1;
  862.                 reply_body = NULL;
  863.                 get_x_kannel_from_headers(reply_headers, &from, &to, &udh,
  864.   NULL, NULL, &smsc, &mclass, &mwi, 
  865.   &coding, &compress, &validity, 
  866.   &deferred, &dlr_mask, &dlr_url, 
  867.   &account, &pid, &alt_dcs, &rpi);
  868.             } else {
  869.                 replytext = octstr_duplicate(reply_couldnotrepresent); 
  870.             }
  871.             if (charset_processing(charset, replytext, coding) == -1) {
  872.                 replytext = octstr_duplicate(reply_couldnotrepresent);
  873.             }
  874.             octstr_destroy(type);
  875.             octstr_destroy(charset);
  876.         } else if (max_http_retries > 0) {
  877.             id = remember_receiver(msg, trans, method, req_url, req_headers, req_body, retries);
  878.             list_produce(smsbox_http_requests, id);
  879.             queued++;
  880.             goto requeued;
  881.         } else
  882.             replytext = octstr_duplicate(reply_couldnotfetch);
  883.         fill_message(msg, trans, replytext, octets, from, to, udh, mclass,
  884.             mwi, coding, compress, validity, deferred, dlr_url, 
  885.            dlr_mask, pid, alt_dcs, rpi, smsc);
  886.         if (final_url == NULL)
  887.             final_url = octstr_imm("");
  888.         if (reply_body == NULL)
  889.             reply_body = octstr_imm("");
  890.         if (msg->sms.dlr_mask == 0) {
  891.             alog("SMS HTTP-request sender:%s request: '%s' "
  892.                  "url: '%s' reply: %d '%s'",
  893.                  octstr_get_cstr(msg->sms.receiver),
  894.                  (msg->sms.msgdata != NULL) ? octstr_get_cstr(msg->sms.msgdata) : "",
  895.                  octstr_get_cstr(final_url), status,
  896.                  (status == HTTP_OK) ? "<< successful >>" : octstr_get_cstr(reply_body));
  897.         }
  898. requeued:
  899.         octstr_destroy(final_url);
  900.         http_destroy_headers(reply_headers);
  901.         octstr_destroy(reply_body);
  902.         octstr_destroy(req_url);
  903.         http_destroy_headers(req_headers);
  904.         octstr_destroy(req_body);
  905.     
  906.         if (msg->sms.dlr_mask == 0 && !queued) {
  907.             if (send_message(trans, msg) < 0)
  908.                 error(0, "failed to send message to phone");
  909.         }
  910.         msg_destroy(msg);
  911.     }
  912. }
  913. /***********************************************************************
  914.  * Thread to receive SMS messages from bearerbox and obeying the requests
  915.  * in them. HTTP requests are started in the background (another thread
  916.  * will deal with the replies) and other requests are fulfilled directly.
  917.  */
  918. /*
  919.  * Perform the service requested by the user: translate the request into
  920.  * a pattern, if it is an URL, start its fetch and return 0, otherwise
  921.  * return the string in `*result' and return 1. Return -1 for errors,
  922.  */
  923. static int obey_request(Octstr **result, URLTranslation *trans, Msg *msg)
  924. {
  925.     Octstr *pattern, *xml, *tmp;
  926.     List *request_headers;
  927.     void *id;
  928.     struct tm tm;
  929.     char p[22];
  930.     int type;
  931.     FILE *f;
  932.     
  933.     gw_assert(msg != NULL);
  934.     gw_assert(msg_type(msg) == sms);
  935.     
  936.     if (msg->sms.sms_type == report)
  937. type = TRANSTYPE_GET_URL;
  938.     else
  939. type = urltrans_type(trans);
  940.     pattern = urltrans_get_pattern(trans, msg);
  941.     gw_assert(pattern != NULL);
  942.     
  943.     switch (type) {
  944.     case TRANSTYPE_TEXT:
  945. debug("sms", 0, "formatted text answer: <%s>", 
  946.       octstr_get_cstr(pattern));
  947. *result = pattern;
  948. alog("SMS request sender:%s request: '%s' fixed answer: '%s'",
  949.      octstr_get_cstr(msg->sms.receiver),
  950.      octstr_get_cstr(msg->sms.msgdata),
  951.      octstr_get_cstr(pattern)); 
  952. break;
  953.     
  954.     case TRANSTYPE_FILE:
  955. *result = octstr_read_file(octstr_get_cstr(pattern));
  956. octstr_destroy(pattern);
  957. alog("SMS request sender:%s request: '%s' file answer: '%s'",
  958.      octstr_get_cstr(msg->sms.receiver),
  959.      octstr_get_cstr(msg->sms.msgdata),
  960.      octstr_get_cstr(*result));
  961. break;
  962.     
  963.     case TRANSTYPE_EXECUTE:
  964.         debug("sms.exec", 0, "executing sms-service '%s'", 
  965.               octstr_get_cstr(pattern));
  966.         if ((f = popen(octstr_get_cstr(pattern), "r")) != NULL) {
  967.             octstr_destroy(pattern);
  968.             *result = octstr_read_pipe(f);
  969.             pclose(f);
  970.             alog("SMS request sender:%s request: '%s' file answer: '%s'",
  971.                 octstr_get_cstr(msg->sms.receiver),
  972.                 octstr_get_cstr(msg->sms.msgdata),
  973.                 octstr_get_cstr(*result));
  974.         } else {
  975.             error(0, "popen failed for '%s': %d: %s",
  976.                   octstr_get_cstr(pattern), errno, strerror(errno));
  977.             *result = NULL;
  978.             octstr_destroy(pattern);
  979.             goto error;
  980.         }
  981.         break;
  982.     case TRANSTYPE_GET_URL:
  983. request_headers = http_create_empty_headers();
  984.         http_header_add(request_headers, "User-Agent", GW_NAME "/" VERSION);
  985. if (urltrans_send_sender(trans)) {
  986.     http_header_add(request_headers, "X-Kannel-From",
  987.     octstr_get_cstr(msg->sms.receiver));
  988. }
  989. id = remember_receiver(msg, trans, HTTP_METHOD_GET, pattern, request_headers, NULL, 0);
  990. http_start_request(caller, HTTP_METHOD_GET, pattern, request_headers, 
  991.                        NULL, 1, id, NULL);
  992. octstr_destroy(pattern);
  993. http_destroy_headers(request_headers);
  994. *result = NULL;
  995. return 0;
  996.     case TRANSTYPE_POST_URL:
  997. request_headers = http_create_empty_headers();
  998. http_header_add(request_headers, "User-Agent", GW_NAME "/" VERSION);
  999. if (msg->sms.coding == DC_8BIT)
  1000.     http_header_add(request_headers, "Content-Type",
  1001.     "application/octet-stream");
  1002. else
  1003.     if(msg->sms.coding == DC_UCS2)
  1004. http_header_add(request_headers, "Content-Type", "text/plain; charset=UTF-16BE");
  1005.     else
  1006. http_header_add(request_headers, "Content-Type", "text/plain");
  1007. if (urltrans_send_sender(trans))
  1008.     http_header_add(request_headers, "X-Kannel-From",
  1009.     octstr_get_cstr(msg->sms.receiver));
  1010. http_header_add(request_headers, "X-Kannel-To",
  1011. octstr_get_cstr(msg->sms.sender));
  1012. /* should we use localtime? FIX ME */
  1013. tm = gw_gmtime(msg->sms.time);
  1014. sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d",
  1015. tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  1016. tm.tm_hour, tm.tm_min, tm.tm_sec);
  1017. http_header_add(request_headers, "X-Kannel-Time", p);
  1018. if (octstr_len(msg->sms.udhdata)) {
  1019.     Octstr *os;
  1020.     os = octstr_duplicate(msg->sms.udhdata);
  1021.     octstr_binary_to_hex(os, 1);
  1022.     http_header_add(request_headers, "X-Kannel-UDH",
  1023.     octstr_get_cstr(os));
  1024.     octstr_destroy(os);
  1025. }
  1026. if (octstr_len(msg->sms.smsc_id)) {
  1027.     Octstr *os;
  1028.     os = octstr_duplicate(msg->sms.smsc_id);
  1029.     http_header_add(request_headers, "X-Kannel-SMSC",
  1030.                     octstr_get_cstr(os));
  1031.     octstr_destroy(os);
  1032. }
  1033. if(msg->sms.mclass) {
  1034.     Octstr *os;
  1035.     os = octstr_format("%d",msg->sms.mclass);
  1036.     http_header_add(request_headers, "X-Kannel-MClass", 
  1037.      octstr_get_cstr(os));
  1038.     octstr_destroy(os);
  1039. }
  1040. if(msg->sms.pid) {
  1041.     Octstr *os;
  1042.     os = octstr_format("%d",msg->sms.pid);
  1043.     http_header_add(request_headers, "X-Kannel-PID", 
  1044.      octstr_get_cstr(os));
  1045.     octstr_destroy(os);
  1046. }
  1047. if(msg->sms.rpi) {
  1048.     Octstr *os;
  1049.     os = octstr_format("%d",msg->sms.rpi);
  1050.     http_header_add(request_headers, "X-Kannel-RPI", 
  1051.      octstr_get_cstr(os));
  1052.     octstr_destroy(os);
  1053. }
  1054. if(msg->sms.alt_dcs) {
  1055.     Octstr *os;
  1056.     os = octstr_format("%d",msg->sms.alt_dcs);
  1057.     http_header_add(request_headers, "X-Kannel-Alt-DCS", 
  1058.      octstr_get_cstr(os));
  1059.     octstr_destroy(os);
  1060. }
  1061. if(msg->sms.mwi) {
  1062.     Octstr *os;
  1063.     os = octstr_format("%d",msg->sms.mwi);
  1064.     http_header_add(request_headers, "X-Kannel-MWI", 
  1065.      octstr_get_cstr(os));
  1066.     octstr_destroy(os);
  1067. }
  1068. if(msg->sms.coding) {
  1069.     Octstr *os;
  1070.     os = octstr_format("%d",msg->sms.coding);
  1071.     http_header_add(request_headers, "X-Kannel-Coding", 
  1072.      octstr_get_cstr(os));
  1073.     octstr_destroy(os);
  1074. }
  1075. if(msg->sms.compress) {
  1076.     Octstr *os;
  1077.     os = octstr_format("%d",msg->sms.compress);
  1078.     http_header_add(request_headers, "X-Kannel-Compress", 
  1079.      octstr_get_cstr(os));
  1080.     octstr_destroy(os);
  1081. }
  1082. if (msg->sms.validity) {
  1083.     Octstr *os;
  1084.     os = octstr_format("%d",msg->sms.validity);
  1085.     http_header_add(request_headers, "X-Kannel-Validity", 
  1086.      octstr_get_cstr(os));
  1087.     octstr_destroy(os);
  1088. }
  1089. if (msg->sms.deferred) {
  1090.     Octstr *os;
  1091.     os = octstr_format("%d",msg->sms.deferred);
  1092.     http_header_add(request_headers, "X-Kannel-Deferred", 
  1093.      octstr_get_cstr(os));
  1094.     octstr_destroy(os);
  1095. }
  1096. if (msg->sms.service) {
  1097.     Octstr *os;
  1098.     os = octstr_duplicate(msg->sms.service);
  1099.     http_header_add(request_headers, "X-Kannel-Service", 
  1100.      octstr_get_cstr(os));
  1101.     octstr_destroy(os);
  1102. }
  1103. id = remember_receiver(msg, trans, HTTP_METHOD_POST, pattern, request_headers, msg->sms.msgdata, 0);
  1104. http_start_request(caller, HTTP_METHOD_POST, pattern, request_headers, 
  1105.              msg->sms.msgdata, 1, id, NULL);
  1106. octstr_destroy(pattern);
  1107. http_destroy_headers(request_headers);
  1108. *result = NULL;
  1109. return 0;
  1110.     case TRANSTYPE_POST_XML:
  1111. /* XXX The first two chars are beeing eaten somewhere and
  1112.  * only sometimes - something must be ungry */
  1113. #define OCTSTR_APPEND_XML(xml, tag, text)                  
  1114. octstr_append(xml, octstr_imm("  "));        
  1115. octstr_append(xml, octstr_imm("tt<"));        
  1116. octstr_append(xml, octstr_imm(tag));            
  1117. octstr_append(xml, octstr_imm(">"));            
  1118. octstr_append(xml, text);                       
  1119. octstr_append(xml, octstr_imm("</"));           
  1120. octstr_append(xml, octstr_imm(tag));            
  1121. octstr_append(xml, octstr_imm(">n"));
  1122. #define OCTSTR_APPEND_XML_NUMBER(xml, tag, value)          
  1123. octstr_append(xml, octstr_imm("  "));        
  1124. octstr_append(xml, octstr_imm("tt<"));        
  1125. octstr_append(xml, octstr_imm(tag));            
  1126. octstr_append(xml, octstr_imm(">"));            
  1127. octstr_append_decimal(xml, value);              
  1128. octstr_append(xml, octstr_imm("</"));           
  1129. octstr_append(xml, octstr_imm(tag));            
  1130. octstr_append(xml, octstr_imm(">n"));
  1131. request_headers = http_create_empty_headers();
  1132. http_header_add(request_headers, "User-Agent", GW_NAME "/" VERSION);
  1133. http_header_add(request_headers, "Content-Type", "text/xml");
  1134. xml = octstr_create("");
  1135. octstr_append(xml, octstr_imm("<?xml version="1.0" encoding="ISO-8859-1"?>n")); 
  1136.     /*
  1137.      * XXX  damn windows that breaks with this :
  1138.      * octstr_append(xml, octstr_imm("<!DOCTYPE message SYSTEM "SMSmessage.dtd">n"));
  1139.      */
  1140. octstr_append(xml, octstr_imm("<message cid="1">n"));
  1141. octstr_append(xml, octstr_imm("t<submit>n"));
  1142. /* oa */
  1143. if(urltrans_send_sender(trans)) {
  1144.     tmp = octstr_create("");
  1145.     OCTSTR_APPEND_XML(tmp, "number", msg->sms.receiver);
  1146.     OCTSTR_APPEND_XML(xml, "oa", tmp);
  1147.     octstr_destroy(tmp);
  1148. }
  1149. /* da */
  1150. {
  1151.     tmp = octstr_create("");
  1152.     OCTSTR_APPEND_XML(tmp, "number", msg->sms.sender);
  1153.     OCTSTR_APPEND_XML(xml, "da", tmp);
  1154.     octstr_destroy(tmp);
  1155. }
  1156. /* udh */
  1157. if(octstr_len(msg->sms.udhdata)) {
  1158.     Octstr *t;
  1159.     t = octstr_duplicate(msg->sms.udhdata);
  1160.     octstr_binary_to_hex(t, 1);
  1161.     OCTSTR_APPEND_XML(xml, "udh", t);
  1162.     octstr_destroy(t);
  1163. }
  1164. /* ud */
  1165. if(octstr_len(msg->sms.msgdata)) {
  1166.     OCTSTR_APPEND_XML(xml, "ud", msg->sms.msgdata);
  1167. }
  1168. /* pid */
  1169. if(msg->sms.pid != 0) {
  1170.     OCTSTR_APPEND_XML_NUMBER(xml, "pid", msg->sms.pid);
  1171. }
  1172. /* rpi */
  1173. if(msg->sms.rpi != 0) {
  1174.     OCTSTR_APPEND_XML_NUMBER(xml, "rpi", msg->sms.rpi);
  1175. }
  1176. /* dcs */
  1177. {
  1178.     tmp = octstr_create("");
  1179.     if(msg->sms.coding != 0) { 
  1180. OCTSTR_APPEND_XML_NUMBER(tmp, "coding", msg->sms.coding);
  1181.     }
  1182.     if(msg->sms.mclass != 0) {
  1183. OCTSTR_APPEND_XML_NUMBER(tmp, "mclass", msg->sms.mclass);
  1184.     }
  1185.     if(msg->sms.alt_dcs != 0) {
  1186. OCTSTR_APPEND_XML_NUMBER(tmp, "alt-dcs", msg->sms.alt_dcs);
  1187.     }
  1188.     if(msg->sms.mwi != 0) {
  1189. OCTSTR_APPEND_XML_NUMBER(tmp, "mwi", msg->sms.mwi);
  1190.     }
  1191.     if(msg->sms.compress != 0) {
  1192. OCTSTR_APPEND_XML_NUMBER(tmp, "compress", msg->sms.compress);
  1193.     }
  1194.     if(octstr_len(tmp)) {
  1195. OCTSTR_APPEND_XML(xml, "dcs", tmp)
  1196.     }
  1197.     octstr_destroy(tmp);
  1198. }
  1199. /* XXX timing = deferred */
  1200. /* XXX vp = validity */
  1201. /* at */
  1202. tm = gw_gmtime(msg->sms.time);
  1203. tmp = octstr_format("<year>%04d</year><month>%02d</month>"
  1204. "<day>%02d</day><hour>%02d</hour><minute>%02d</minute>"
  1205. "<second>%02d</second><timezone>0</timezone>",
  1206.         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  1207.         tm.tm_hour, tm.tm_min, tm.tm_sec);
  1208. OCTSTR_APPEND_XML(xml, "at", tmp);
  1209. octstr_destroy(tmp);
  1210. /* smsc = from */
  1211. if(octstr_len(msg->sms.smsc_id)) {
  1212.     OCTSTR_APPEND_XML(xml, "from", msg->sms.smsc_id);
  1213. }
  1214. /* service = to */
  1215. if(octstr_len(msg->sms.service)) {
  1216.     OCTSTR_APPEND_XML(xml, "to", msg->sms.service);
  1217. }
  1218. /* End XML */
  1219. octstr_append(xml, octstr_imm("t</submit>n"));
  1220. octstr_append(xml, octstr_imm("</message>n"));
  1221. if(msg->sms.msgdata != NULL)
  1222.     octstr_destroy(msg->sms.msgdata);
  1223. msg->sms.msgdata = xml;
  1224. debug("sms", 0, "XMLBuild: XML: <%s>", octstr_get_cstr(msg->sms.msgdata));
  1225. id = remember_receiver(msg, trans, HTTP_METHOD_POST, pattern, request_headers, msg->sms.msgdata, 0);
  1226. http_start_request(caller, HTTP_METHOD_POST, pattern, request_headers,
  1227.            msg->sms.msgdata, 1, id, NULL);
  1228. octstr_destroy(pattern);
  1229. http_destroy_headers(request_headers);
  1230. *result = NULL;
  1231. return 0;
  1232.     case TRANSTYPE_SENDSMS:
  1233. error(0, "Got URL translation type SENDSMS for incoming message.");
  1234. alog("SMS request sender:%s request: '%s' FAILED bad translation",
  1235.      octstr_get_cstr(msg->sms.receiver),
  1236.      octstr_get_cstr(msg->sms.msgdata));
  1237. octstr_destroy(pattern);
  1238. goto error;
  1239.     
  1240.     default:
  1241. error(0, "Unknown URL translation type %d", urltrans_type(trans));
  1242. alog("SMS request sender:%s request: '%s' FAILED unknown translation",
  1243.      octstr_get_cstr(msg->sms.receiver),
  1244.      octstr_get_cstr(msg->sms.msgdata));
  1245. octstr_destroy(pattern);
  1246. goto error;
  1247.     }
  1248.     
  1249.     return 1;
  1250.     
  1251. error:
  1252.     return -1;
  1253. }
  1254. static void obey_request_thread(void *arg) 
  1255. {
  1256.     Msg *msg, *reply_msg;
  1257.     Octstr *tmp, *reply;
  1258.     URLTranslation *trans;
  1259.     Octstr *p;
  1260.     int ret, dreport=0;
  1261.     
  1262.     while ((msg = list_consume(smsbox_requests)) != NULL) {
  1263. if (msg->sms.sms_type == report)
  1264.     dreport = 1;
  1265. else
  1266.     dreport = 0;
  1267. /* Recode to iso-8859-1 the MO message if possible */
  1268. if(mo_recode && msg->sms.coding == DC_UCS2) {
  1269.     Octstr *text;
  1270.     text = octstr_duplicate(msg->sms.msgdata);
  1271.     if(0 == octstr_recode (octstr_imm("iso-8859-1"), octstr_imm("UTF-16BE"), text)) {
  1272. if(octstr_search(text, octstr_imm("&#"), 0) == -1) {
  1273.     /* XXX I'm trying to search for &#xxxx; text, which indicates that the
  1274.      * text couldn't be recoded.
  1275.      * We should use other function to do the recode or detect it using
  1276.      * other method */
  1277.     info(0, "MO message converted from UCS2 to ISO-8859-1");
  1278.     octstr_destroy(msg->sms.msgdata);
  1279.     msg->sms.msgdata = octstr_duplicate(text);
  1280.     msg->sms.charset = octstr_create("ISO-8859-1");
  1281.     msg->sms.coding = DC_7BIT;
  1282. }
  1283.     }
  1284.     octstr_destroy(text);
  1285. }
  1286. if (octstr_len(msg->sms.sender) == 0 ||
  1287.     octstr_len(msg->sms.receiver) == 0) {
  1288.     error(0, "smsbox_req_thread: no sender/receiver, dump follows:");
  1289.     msg_dump(msg, 0);
  1290.     /* NACK should be returned here if we use such 
  1291.        things... future implementation! */
  1292.     msg_destroy(msg);
  1293.     continue;
  1294. }
  1295.     
  1296. if (octstr_compare(msg->sms.sender, msg->sms.receiver) == 0) {
  1297.     info(0, "NOTE: sender and receiver same number <%s>, ignoring!",
  1298.  octstr_get_cstr(msg->sms.sender));
  1299.     msg_destroy(msg);
  1300.     continue;
  1301. }
  1302. /* create reply message to be sent afterwards */
  1303. reply_msg = msg_create(ack);
  1304. reply_msg->ack.nack = 0;
  1305. reply_msg->ack.time = msg->sms.time;
  1306. reply_msg->ack.id = msg->sms.id;
  1307.     
  1308. if (dreport) {
  1309.     trans = urltrans_find_service(translations, msg);
  1310.     info(0, "Starting delivery report <%s> from <%s>",
  1311. octstr_get_cstr(msg->sms.service),
  1312. octstr_get_cstr(msg->sms.sender));
  1313. } else {
  1314.     trans = urltrans_find(translations, msg->sms.msgdata, 
  1315.                 msg->sms.smsc_id, msg->sms.sender, msg->sms.receiver);
  1316.     if (trans == NULL) {
  1317. Octstr *t;
  1318. warning(0, "No translation found for <%s> from <%s> to <%s>",
  1319.     msg->sms.msgdata != NULL ? octstr_get_cstr(msg->sms.msgdata) : "",
  1320.     octstr_get_cstr(msg->sms.sender),
  1321.     octstr_get_cstr(msg->sms.receiver));
  1322. t = msg->sms.sender;
  1323. msg->sms.sender = msg->sms.receiver;
  1324. msg->sms.receiver = t;
  1325. goto error;
  1326.     }
  1327.     
  1328.     info(0, "Starting to service <%s> from <%s> to <%s>",
  1329. octstr_get_cstr(msg->sms.msgdata),
  1330. octstr_get_cstr(msg->sms.sender),
  1331. octstr_get_cstr(msg->sms.receiver));
  1332.     /*
  1333.      * now, we change the sender (receiver now 'cause we swap them later)
  1334.      * if faked-sender or similar set. Note that we ignore if the 
  1335.      * replacement fails.
  1336.      */
  1337.     tmp = octstr_duplicate(msg->sms.sender);
  1338.     
  1339.     p = urltrans_faked_sender(trans);
  1340.     if (p != NULL) {
  1341. octstr_destroy(msg->sms.sender);
  1342. msg->sms.sender = octstr_duplicate(p);
  1343.     } else if (global_sender != NULL) {
  1344. octstr_destroy(msg->sms.sender);
  1345. msg->sms.sender = octstr_duplicate(global_sender);
  1346.     } else {
  1347. octstr_destroy(msg->sms.sender);
  1348. msg->sms.sender = octstr_duplicate(msg->sms.receiver);
  1349.     }
  1350.     octstr_destroy(msg->sms.receiver);
  1351.     msg->sms.receiver = tmp;
  1352.     msg->sms.sms_type = mt_reply;
  1353. }
  1354. /* TODO: check if the sender is approved to use this service */
  1355. if(msg->sms.service == NULL && trans != NULL)
  1356.     msg->sms.service = octstr_duplicate(urltrans_name(trans));
  1357. ret = obey_request(&reply, trans, msg);
  1358. if (ret != 0) {
  1359.     if (ret == -1) {
  1360.     error:
  1361.         error(0, "request failed");
  1362.         /* XXX this can be something different, according to 
  1363.            urltranslation */
  1364.         reply = octstr_duplicate(reply_requestfailed);
  1365.         trans = NULL; /* do not use any special translation */
  1366. O_DESTROY(msg->sms.service);
  1367.     }
  1368.     octstr_destroy(msg->sms.msgdata);
  1369.     msg->sms.msgdata = reply;
  1370.     msg->sms.coding = 0;
  1371.     msg->sms.time = time(NULL); /* set current time */
  1372.     if (!dreport) {
  1373.     if (send_message(trans, msg) < 0)
  1374. error(0, "request_thread: failed");
  1375.     }
  1376. }
  1377. write_to_bearerbox(reply_msg); /* implicit msg_destroy */
  1378. msg_destroy(msg);
  1379.     }
  1380. }
  1381. /***********************************************************************
  1382.  * HTTP sendsms interface.
  1383.  */
  1384. #ifdef HAVE_SECURITY_PAM_APPL_H /*Module for pam authentication */
  1385. /*
  1386.  * Use PAM (Pluggable Authentication Module) to check sendsms authentication.
  1387.  */
  1388. typedef const struct pam_message pam_message_type;
  1389. static const char *PAM_username;
  1390. static const char *PAM_password;
  1391. static int PAM_conv (int num_msg, pam_message_type **msg,
  1392.      struct pam_response **resp,
  1393.      void *appdata_ptr)
  1394. {
  1395.     int count = 0, replies = 0;
  1396.     struct pam_response *repl = NULL;
  1397.     int size = sizeof(struct pam_response);
  1398. #define GET_MEM 
  1399. repl = gw_realloc(repl, size); 
  1400. size += sizeof(struct pam_response)
  1401. #define COPY_STRING(s) (s) ? gw_strdup(s) : NULL
  1402.     for (count = 0; count < num_msg; count++) {
  1403. switch (msg[count]->msg_style) {
  1404. case PAM_PROMPT_ECHO_ON:
  1405.     GET_MEM;
  1406.     repl[replies].resp_retcode = PAM_SUCCESS;
  1407.     repl[replies++].resp = COPY_STRING(PAM_username);
  1408.     /* PAM frees resp */
  1409.     break;
  1410. case PAM_PROMPT_ECHO_OFF:
  1411.     GET_MEM;
  1412.     repl[replies].resp_retcode = PAM_SUCCESS;
  1413.     repl[replies++].resp = COPY_STRING(PAM_password);
  1414.     /* PAM frees resp */
  1415.     break;
  1416. case PAM_TEXT_INFO:
  1417.     warning(0, "unexpected message from PAM: %s", msg[count]->msg);
  1418.     break;
  1419. case PAM_ERROR_MSG:
  1420. default:
  1421.     /* Must be an error of some sort... */
  1422.     error(0, "unexpected error from PAM: %s", msg[count]->msg);
  1423.     gw_free(repl);
  1424.     return PAM_CONV_ERR;
  1425. }
  1426.     }
  1427.     if (repl)
  1428. *resp = repl;
  1429.     return PAM_SUCCESS;
  1430. }
  1431. static struct pam_conv PAM_conversation = {
  1432.     &PAM_conv,
  1433.     NULL
  1434. };
  1435. static int authenticate(const char *login, const char *passwd)
  1436. {
  1437.     pam_handle_t *pamh;
  1438.     int pam_error;
  1439.     
  1440.     PAM_username = login;
  1441.     PAM_password = passwd;
  1442.     
  1443.     pam_error = pam_start("kannel", login, &PAM_conversation, &pamh);
  1444.     if (pam_error != PAM_SUCCESS ||
  1445.         (pam_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
  1446. pam_end(pamh, pam_error);
  1447. return 0;
  1448.     }
  1449.     pam_end(pamh, PAM_SUCCESS);
  1450.     info(0, "sendsms used by <%s>", login);
  1451.     return 1;
  1452. }
  1453. /*
  1454.  * Check for matching username and password for requests.
  1455.  * Return an URLTranslation if successful NULL otherwise.
  1456.  */
  1457. static int pam_authorise_user(List *list) 
  1458. {
  1459.     Octstr *val, *user = NULL;
  1460.     char *pwd, *login;
  1461.     int result;
  1462.     if ((user = http_cgi_variable(list, "user")) == NULL &&
  1463.         (user = http_cgi_variable(list, "username"))==NULL)
  1464. return 0;
  1465.     login = octstr_get_cstr(user);
  1466.     
  1467.     if ((val = http_cgi_variable(list, "password")) == NULL &&
  1468.         (val = http_cgi_variable(list, "pass")) == NULL)
  1469. return 0;
  1470.     pwd = octstr_get_cstr(val);
  1471.     result = authenticate(login, pwd);
  1472.     
  1473.     return result;
  1474. }
  1475. #endif /* HAVE_SECURITY_PAM_APPL_H */
  1476. static Octstr *smsbox_req_handle(URLTranslation *t, Octstr *client_ip,
  1477.  Octstr *from, Octstr *to, Octstr *text, 
  1478.  Octstr *charset, Octstr *udh, Octstr *smsc,
  1479.  int mclass, int mwi, int coding, int compress, 
  1480.  int validity, int deferred, 
  1481.  int *status, int dlr_mask, Octstr *dlr_url, 
  1482.  Octstr *account, int pid, int alt_dcs, int rpi,
  1483.  List *receiver)
  1484. {      
  1485.     Msg *msg = NULL;
  1486.     Octstr *newfrom, *returnerror, *receiv;
  1487.     List *failed_id, *allowed, *denied;
  1488.     int no_recv, ret = 0, i;
  1489.     long del;
  1490.     /*
  1491.      * Multi-cast messages with several receivers in 'to' are handled
  1492.      * in a loop. We only change sms.time and sms.receiver within the
  1493.      * loop below, because everything else is identical for all receivers.
  1494.      * If receiver is not null, to list is already present on it
  1495.      */
  1496.     if(receiver == NULL) {
  1497. receiver = octstr_split_words(to);
  1498.     }
  1499.     no_recv = list_len(receiver);
  1500.     /*
  1501.      * check if UDH length is legal, or otherwise discard the
  1502.      * message, to prevent intentional buffer overflow schemes
  1503.      */
  1504.     if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
  1505. returnerror = octstr_create("UDH field misformed, rejected");
  1506. goto fielderror2;
  1507.     }
  1508.     /*
  1509.      * Check for white and black lists, first for the URLTranlation
  1510.      * lists and then for the global lists.
  1511.      *
  1512.      * Set the 'allowed' and 'denied' lists accordingly to process at
  1513.      * least all allowed receiver messages. This is a constrain
  1514.      * walk through all disallowing rules within the lists.
  1515.      */
  1516.     allowed = list_create();
  1517.     denied = list_create();
  1518.     for (i = 0; i < no_recv; i++) {
  1519.         receiv = list_get(receiver, i); 
  1520.             
  1521. /*
  1522.  * Check if there are any illegal characters in the 'to' scheme
  1523.  */
  1524. if (strspn(octstr_get_cstr(receiv), sendsms_number_chars) < octstr_len(receiv)) {
  1525.     info(0,"Illegal characters in 'to' string ('%s') vs '%s'",
  1526. octstr_get_cstr(receiv), sendsms_number_chars);
  1527.             list_append_unique(denied, receiv, octstr_item_match);
  1528. }
  1529.         /*
  1530.          * First of all fill the two lists systematicaly by the rules,
  1531.          * then we will revice the lists.
  1532.          */
  1533.         if (urltrans_white_list(t) &&
  1534.             numhash_find_number(urltrans_white_list(t), receiv) < 1) {
  1535.             info(0, "Number <%s> is not in white-list, message discarded",
  1536.                  octstr_get_cstr(receiv));
  1537.             list_append_unique(denied, receiv, octstr_item_match);
  1538.         } else {
  1539.             list_append_unique(allowed, receiv, octstr_item_match);
  1540.         }
  1541.         if (urltrans_black_list(t) &&
  1542.             numhash_find_number(urltrans_black_list(t), receiv) == 1) {
  1543.             info(0, "Number <%s> is in black-list, message discarded",
  1544.                  octstr_get_cstr(receiv));
  1545.             list_append_unique(denied, receiv, octstr_item_match);
  1546.         } else {
  1547.             list_append_unique(allowed, receiv, octstr_item_match);
  1548.         }
  1549.         if (white_list &&
  1550.             numhash_find_number(white_list, receiv) < 1) {
  1551.             info(0, "Number <%s> is not in global white-list, message discarded",
  1552.                  octstr_get_cstr(receiv));
  1553.             list_append_unique(denied, receiv, octstr_item_match);
  1554.         } else {
  1555.             list_append_unique(allowed, receiv, octstr_item_match);
  1556.         }
  1557.         if (black_list &&
  1558.             numhash_find_number(black_list, receiv) == 1) {
  1559.             info(0, "Number <%s> is in global black-list, message discarded",
  1560.                  octstr_get_cstr(receiv));
  1561.             list_append_unique(denied, receiv, octstr_item_match);
  1562.         } else {
  1563.             list_append_unique(allowed, receiv, octstr_item_match);
  1564.         }
  1565.     }
  1566.     
  1567.     /*
  1568.      * Now we have to revise the 'allowed' and 'denied' lists by walking
  1569.      * the 'denied' list and check if items are also present in 'allowed',
  1570.      * then we will discard them from 'allowed'.
  1571.      */
  1572.     for (i = 0; i < list_len(denied); i++) {
  1573.         receiv = list_get(denied, i);
  1574.         del = list_delete_matching(allowed, receiv, octstr_item_match);
  1575.     }
  1576.     
  1577.     if (urltrans_faked_sender(t) != NULL) {
  1578. /* discard previous from */
  1579. newfrom = octstr_duplicate(urltrans_faked_sender(t));
  1580.     } else if (octstr_len(from) > 0) {
  1581. newfrom = octstr_duplicate(from);
  1582.     } else if (urltrans_default_sender(t) != NULL) {
  1583. newfrom = octstr_duplicate(urltrans_default_sender(t));
  1584.     } else if (global_sender != NULL) {
  1585. newfrom = octstr_duplicate(global_sender);
  1586.     } else {
  1587. returnerror = octstr_create("Sender missing and no global set, rejected");
  1588. goto fielderror2;
  1589.     }
  1590.     info(0, "sendsms sender:<%s:%s> (%s) to:<%s> msg:<%s>",
  1591.          octstr_get_cstr(urltrans_username(t)),
  1592.          octstr_get_cstr(newfrom),
  1593.          octstr_get_cstr(client_ip),
  1594.          ( to == NULL ? "multi-cast" : octstr_get_cstr(to) ),
  1595.          ( text == NULL ? "" : octstr_get_cstr(text) ));
  1596.     
  1597.     /*
  1598.      * Create the msg structure and fill the types. Note that sms.receiver
  1599.      * and sms.time are set in the multi-cast support loop below.
  1600.      */
  1601.     msg = msg_create(sms);
  1602.     
  1603.     msg->sms.service = octstr_duplicate(urltrans_name(t));
  1604.     msg->sms.sms_type = mt_push;
  1605.     msg->sms.sender = octstr_duplicate(newfrom);
  1606.     msg->sms.account = account ? octstr_duplicate(account) : NULL;
  1607.     msg->sms.msgdata = text ? octstr_duplicate(text) : octstr_create("");
  1608.     msg->sms.udhdata = udh ? octstr_duplicate(udh) : octstr_create("");
  1609.     msg->sms.dlr_mask = dlr_mask;
  1610.     msg->sms.dlr_url = dlr_url ? octstr_duplicate(dlr_url) : octstr_create("");
  1611.     if ( mclass < 0 || mclass > 4 ) {
  1612. returnerror = octstr_create("MClass field misformed, rejected");
  1613. goto fielderror;
  1614.     }
  1615.     msg->sms.mclass = mclass;
  1616.     
  1617.     if ( pid < 0 || pid > 255 ) {
  1618. returnerror = octstr_create("PID field misformed, rejected");
  1619. goto fielderror;
  1620.     }
  1621.     msg->sms.pid = pid;
  1622.     if ( rpi < 0 || rpi > 1 ) {
  1623. returnerror = octstr_create("RPI field misformed, rejected");
  1624. goto fielderror;
  1625.     }
  1626.     msg->sms.rpi = rpi;
  1627.     
  1628.     if ( alt_dcs < 0 || alt_dcs > 2 ) {
  1629. returnerror = octstr_create("Alt-DCS field misformed, rejected");
  1630. goto fielderror;
  1631.     }
  1632.     msg->sms.alt_dcs = alt_dcs;
  1633.     
  1634.     if ( mwi < 0 || mwi > 8 ) {
  1635. returnerror = octstr_create("MWI field misformed, rejected");
  1636. goto fielderror;
  1637.     }
  1638.     msg->sms.mwi = mwi;
  1639.     if ( coding < 0 || coding > 4 ) {
  1640. returnerror = octstr_create("Coding field misformed, rejected");
  1641. goto fielderror;
  1642.     }
  1643.     msg->sms.coding = coding;
  1644.     if ( compress < 0 || compress > 1 ) {
  1645. returnerror = octstr_create("Compress field misformed, rejected");
  1646. goto fielderror;
  1647.     }
  1648.     msg->sms.compress = compress;
  1649.     /* Compatibility Mode */
  1650.     if ( msg->sms.coding == DC_UNDEF) {
  1651. if(octstr_len(udh))
  1652.   msg->sms.coding = DC_8BIT;
  1653. else
  1654.   msg->sms.coding = DC_7BIT;
  1655.     }
  1656.     if ( validity < 0 ) {
  1657. returnerror = octstr_create("Validity field misformed, rejected");
  1658. goto fielderror;
  1659.     }
  1660.     msg->sms.validity = validity;
  1661.     if ( deferred < 0 ) {
  1662. returnerror = octstr_create("Deferred field misformed, rejected");
  1663. goto fielderror;
  1664.     }
  1665.     msg->sms.deferred = deferred;
  1666.     /* new smsc-id argument - we should check this one, if able,
  1667.        but that's advanced logics -- Kalle */
  1668.     
  1669.     if (urltrans_forced_smsc(t)) {
  1670. msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
  1671. if (smsc)
  1672.     info(0, "send-sms request smsc id ignored, "
  1673.          "as smsc id forced to %s",
  1674.     octstr_get_cstr(urltrans_forced_smsc(t)));
  1675.     } else if (smsc) {
  1676. msg->sms.smsc_id = octstr_duplicate(smsc);
  1677.     } else if (urltrans_default_smsc(t)) {
  1678. msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
  1679.     } else
  1680. msg->sms.smsc_id = NULL;
  1681.     if (charset_processing(charset, msg->sms.msgdata, msg->sms.coding) == -1) {
  1682. returnerror = octstr_create("Charset or body misformed, rejected");
  1683. goto fielderror;
  1684.     }
  1685.     msg->sms.receiver = NULL;
  1686.     /* 
  1687.      * All checks are done, now add multi-cast request support by
  1688.      * looping through 'allowed'. This should work for any
  1689.      * number of receivers within 'to'. If the message fails append
  1690.      * it to 'failed_id'.
  1691.      */
  1692.     failed_id = list_create();
  1693.     while ((receiv = list_extract_first(allowed)) != NULL) {
  1694.         
  1695. O_DESTROY(msg->sms.receiver);
  1696.         msg->sms.receiver = octstr_duplicate(receiv);
  1697.         msg->sms.time = time(NULL);
  1698.         /* send the message and return number of splits */
  1699.         ret = send_message(t, msg);
  1700.         if (ret == -1) {
  1701.             /* add the receiver to the failed list */
  1702.             list_append(failed_id, receiv);
  1703.         } else {
  1704.             /* log the sending as successfull for this particular message */
  1705.             alog("send-SMS request added - sender:%s:%s %s target:%s request: '%s'",
  1706.              octstr_get_cstr(urltrans_username(t)),
  1707.                  octstr_get_cstr(newfrom), octstr_get_cstr(client_ip),
  1708.              octstr_get_cstr(receiv),
  1709.              udh == NULL ? ( text == NULL ? "" : octstr_get_cstr(text) ) : "<< UDH >>");
  1710.         }
  1711.     }
  1712.     msg_destroy(msg);
  1713.     list_destroy(receiver, octstr_destroy_item);
  1714.     list_destroy(allowed, octstr_destroy_item);
  1715.     /* have all receivers been denied by list rules?! */
  1716.     if (no_recv == list_len(denied)) {
  1717.         returnerror = octstr_create("Number(s) has/have been denied by white- and/or black-lists.");
  1718.         goto fielderror2;
  1719.     }
  1720.     if (list_len(failed_id) > 0)
  1721. goto error;
  1722.     
  1723.     list_destroy(failed_id, octstr_destroy_item);
  1724.     octstr_destroy(newfrom);
  1725.     *status = HTTP_ACCEPTED;
  1726.     returnerror = octstr_create("Sent.");
  1727.     /* 
  1728.      * Append all denied receivers to the returned body in case this is
  1729.      * a multi-cast send request
  1730.      */
  1731.     if (list_len(denied) > 0) {
  1732.         octstr_format_append(returnerror, " Denied receivers are:");
  1733.         while ((receiv = list_extract_first(denied)) != NULL) {
  1734.             octstr_format_append(returnerror, " %s", octstr_get_cstr(receiv));
  1735.         }
  1736.     }               
  1737.     list_destroy(denied, octstr_destroy_item);  
  1738.     /*
  1739.      * Append number of splits to returned body. 
  1740.      * This may be used by the calling client.
  1741.      */
  1742.     if (ret > 1) 
  1743.         octstr_format_append(returnerror, " Message splits: %d", ret);
  1744.     return returnerror;
  1745.     
  1746. fielderror:
  1747.     octstr_destroy(newfrom);
  1748.     msg_destroy(msg);
  1749. fielderror2:
  1750.     alog("send-SMS request failed - %s",
  1751.          octstr_get_cstr(returnerror));
  1752.     *status = HTTP_BAD_REQUEST;
  1753.     return returnerror;
  1754. error:
  1755.     error(0, "sendsms_request: failed");
  1756.     octstr_destroy(from);
  1757.     *status = HTTP_INTERNAL_SERVER_ERROR;
  1758.     returnerror = octstr_create("Sending failed.");
  1759.     /* 
  1760.      * Append all receivers to the returned body in case this is
  1761.      * a multi-cast send request
  1762.      */
  1763.     if (no_recv > 1) {
  1764.         octstr_format_append(returnerror, " Failed receivers are:");
  1765.         while ((receiv = list_extract_first(failed_id)) != NULL) {
  1766.             octstr_format_append(returnerror, " %s", octstr_get_cstr(receiv));
  1767.         }
  1768.     }
  1769.     octstr_destroy(receiv); 
  1770.     list_destroy(failed_id, octstr_destroy_item);
  1771.     list_destroy(denied, octstr_destroy_item);
  1772.     return returnerror;
  1773. }
  1774. /*
  1775.  * new authorisation, usable by POST and GET
  1776.  */
  1777. static URLTranslation *authorise_username(Octstr *username, Octstr *password,
  1778.   Octstr *client_ip) 
  1779. {
  1780.     URLTranslation *t = NULL;
  1781.     if (username == NULL || password == NULL)
  1782. return NULL;
  1783.     
  1784.     if ((t = urltrans_find_username(translations, username))==NULL)
  1785. return NULL;
  1786.     if (octstr_compare(password, urltrans_password(t))!=0)
  1787. return NULL;
  1788.     else {
  1789. Octstr *allow_ip = urltrans_allow_ip(t);
  1790. Octstr *deny_ip = urltrans_deny_ip(t);
  1791.         if (is_allowed_ip(allow_ip, deny_ip, client_ip) == 0) {
  1792.     warning(0, "Non-allowed connect tried by <%s> from <%s>, ignored",
  1793.     octstr_get_cstr(username), octstr_get_cstr(client_ip));
  1794.     return NULL;
  1795.         }
  1796.     }
  1797.     info(0, "sendsms used by <%s>", octstr_get_cstr(username));
  1798.     return t;
  1799. }
  1800. /*
  1801.  * Authentication whith the database of Kannel.
  1802.  * Check for matching username and password for requests.
  1803.  * Return an URLTranslation if successful NULL otherwise.
  1804.  */
  1805. static URLTranslation *default_authorise_user(List *list, Octstr *client_ip) 
  1806. {
  1807.     Octstr *pass, *user = NULL;
  1808.     if ((user = http_cgi_variable(list, "username")) == NULL)
  1809.         user = http_cgi_variable(list, "user");
  1810.     if ((pass = http_cgi_variable(list, "password")) == NULL)
  1811. pass = http_cgi_variable(list, "pass");
  1812.     return authorise_username(user, pass, client_ip);
  1813. }
  1814. static URLTranslation *authorise_user(List *list, Octstr *client_ip) 
  1815. {
  1816. #ifdef HAVE_SECURITY_PAM_APPL_H
  1817.     URLTranslation *t;
  1818.     
  1819.     t = urltrans_find_username(translations, octstr_imm("pam"));
  1820.     if (t != NULL) {
  1821. if (pam_authorise_user(list))
  1822.     return t;
  1823. else 
  1824.     return NULL;
  1825.     } else
  1826. return default_authorise_user(list, client_ip);
  1827. #else
  1828.     return default_authorise_user(list, client_ip);
  1829. #endif
  1830. }
  1831. /*
  1832.  * Create and send an SMS message from an HTTP request.
  1833.  * Args: args contains the CGI parameters
  1834.  */
  1835. static Octstr *smsbox_req_sendsms(List *args, Octstr *client_ip, int *status)
  1836. {
  1837.     URLTranslation *t = NULL;
  1838.     Octstr *from, *to, *charset;
  1839.     Octstr *text, *udh, *smsc, *tmp_string;
  1840.     Octstr *dlr_url = NULL;
  1841.     Octstr *account = NULL;
  1842.     int dlr_mask = 0;
  1843.     Octstr *dlr_mask_string;
  1844.     int mclass, mwi, coding, compress, validity, deferred, pid, alt_dcs, rpi;
  1845.    
  1846.     /* check the username and password */
  1847.     t = authorise_user(args, client_ip);
  1848.     if (t == NULL) {
  1849. *status = HTTP_FORBIDDEN;
  1850. return octstr_create("Authorization failed for sendsms");
  1851.     }
  1852.     
  1853.     udh = http_cgi_variable(args, "udh");
  1854.     text = http_cgi_variable(args, "text");
  1855.     charset = http_cgi_variable(args, "charset");
  1856.     smsc = http_cgi_variable(args, "smsc");
  1857.     from = http_cgi_variable(args, "from");
  1858.     to = http_cgi_variable(args, "to");
  1859.     account = http_cgi_variable(args,"account");
  1860.     dlr_url = http_cgi_variable(args, "dlrurl");
  1861.     dlr_mask_string = http_cgi_variable(args, "dlrmask");
  1862.     if(dlr_mask_string != NULL)
  1863.         sscanf(octstr_get_cstr(dlr_mask_string),"%d",&dlr_mask);
  1864.     else
  1865.      dlr_mask = 0;
  1866.     mclass = mwi = coding = compress = validity = 
  1867. deferred = pid = alt_dcs = rpi = 0;
  1868.     tmp_string = NULL;
  1869.     tmp_string = http_cgi_variable(args, "flash");
  1870.     if(tmp_string != NULL) {
  1871.         sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
  1872. warning(0, "Flash field used and deprecated");
  1873.     }
  1874.     tmp_string = NULL;
  1875.     tmp_string = http_cgi_variable(args, "mclass");
  1876.     if(tmp_string != NULL)
  1877.         sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
  1878.     tmp_string = NULL;
  1879.     tmp_string = http_cgi_variable(args, "pid");
  1880.     if(tmp_string != NULL)
  1881.         sscanf(octstr_get_cstr(tmp_string),"%d", &pid);
  1882.     tmp_string = NULL;
  1883.     tmp_string = http_cgi_variable(args, "rpi");
  1884.     if(tmp_string != NULL)
  1885.         sscanf(octstr_get_cstr(tmp_string),"%d", &rpi);
  1886.     tmp_string = NULL;
  1887.     tmp_string = http_cgi_variable(args, "alt-dcs");
  1888.     if(tmp_string != NULL)
  1889.         sscanf(octstr_get_cstr(tmp_string),"%d", &alt_dcs);
  1890.     tmp_string = NULL;
  1891.     tmp_string = http_cgi_variable(args, "mwi");
  1892.     if(tmp_string != NULL)
  1893.         sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
  1894.     tmp_string = NULL;
  1895.     tmp_string = http_cgi_variable(args, "coding");
  1896.     if(tmp_string != NULL)
  1897.         sscanf(octstr_get_cstr(tmp_string),"%d", &coding);
  1898.     tmp_string = NULL;
  1899.     tmp_string = http_cgi_variable(args, "compress");
  1900.     if(tmp_string != NULL)
  1901.         sscanf(octstr_get_cstr(tmp_string),"%d", &compress);
  1902.     tmp_string = NULL;
  1903.     tmp_string = http_cgi_variable(args, "validity");
  1904.     if(tmp_string != NULL)
  1905.         sscanf(octstr_get_cstr(tmp_string),"%d", &validity);
  1906.     tmp_string = NULL;
  1907.     tmp_string = http_cgi_variable(args, "deferred");
  1908.     if(tmp_string != NULL) {
  1909.         sscanf(octstr_get_cstr(tmp_string),"%d", &deferred);
  1910.     }
  1911.     /*
  1912.      * we expect cgi var text to be defined, even if it may be
  1913.      * empty to allow empty messages, st.
  1914.      */
  1915.     if (to == NULL) {
  1916. error(0, "%s got insufficient headers",octstr_get_cstr(sendsms_url));
  1917. *status = HTTP_BAD_REQUEST;
  1918. return octstr_create("Insufficient headers, rejected");
  1919.     } 
  1920.     else if (octstr_case_compare(to,
  1921. octstr_imm("")) == 0) {
  1922. error(0, "%s got empty to cgi variable", octstr_get_cstr(sendsms_url));
  1923. *status = HTTP_BAD_REQUEST;
  1924. return octstr_create("Empty receiver number not allowed, rejected");
  1925.     }
  1926.     return smsbox_req_handle(t, client_ip, from, to, text, charset, udh, 
  1927.      smsc, mclass, mwi, coding, compress, validity, 
  1928.      deferred, status, dlr_mask, dlr_url, account,
  1929.      pid, alt_dcs, rpi, NULL);
  1930.     
  1931. }
  1932. /*
  1933.  * Create and send an SMS message from an HTTP request.
  1934.  * Args: args contains the CGI parameters
  1935.  */
  1936. static Octstr *smsbox_sendsms_post(List *headers, Octstr *body,
  1937.    Octstr *client_ip, int *status)
  1938. {
  1939.     URLTranslation *t = NULL;
  1940.     Octstr *from, *to, *user, *pass, *udh, *smsc;
  1941.     Octstr *ret;
  1942.     Octstr *type, *charset;
  1943.     Octstr *dlr_url;
  1944.     Octstr *account;
  1945.     List *tolist;
  1946.     int dlr_mask = 0;
  1947.     int mclass, mwi, coding, compress, validity, deferred, pid, alt_dcs, rpi;
  1948.  
  1949.     from = to = user = pass = udh = smsc = dlr_url = account = NULL;
  1950.     tolist = NULL;
  1951.    
  1952.     ret = NULL;
  1953.     
  1954.     /* XXX here we should take into account content-type of body
  1955.     */
  1956.     http_header_get_content_type(headers, &type, &charset);
  1957.     if(octstr_case_compare(type, octstr_imm("text/xml")) == 0) {
  1958. get_x_kannel_from_xml(mt_push, &type, &body, headers, &from, &to, &udh,
  1959.         &user, &pass, &smsc, &mclass, &mwi, &coding,
  1960.         &compress, &validity, &deferred, &dlr_mask, &dlr_url, 
  1961. &account, &pid, &alt_dcs, &rpi, &tolist);
  1962.     } else {
  1963. get_x_kannel_from_headers(headers, &from, &to, &udh,
  1964.       &user, &pass, &smsc, &mclass, &mwi, &coding,
  1965.       &compress, &validity, &deferred, 
  1966.       &dlr_mask, &dlr_url, &account, &pid, &alt_dcs, &rpi);
  1967.     }
  1968.     /* check the username and password */
  1969.     t = authorise_username(user, pass, client_ip);
  1970.     if (t == NULL) {
  1971. *status = HTTP_FORBIDDEN;
  1972. ret = octstr_create("Authorization failed for sendsms");
  1973.     }
  1974.     else if (to == NULL && tolist == NULL) {
  1975. error(0, "%s got insufficient headers", octstr_get_cstr(sendsms_url));
  1976. *status = HTTP_BAD_REQUEST;
  1977. ret = octstr_create("Insufficient headers, rejected");
  1978.     } 
  1979.     else if (to != NULL && octstr_case_compare(to,
  1980. octstr_imm("")) == 0) {
  1981. error(0, "%s got empty to cgi variable", octstr_get_cstr(sendsms_url));
  1982. *status = HTTP_BAD_REQUEST;
  1983. return octstr_create("Empty receiver number not allowed, rejected");
  1984.     } 
  1985.     else {
  1986. if (octstr_case_compare(type,
  1987. octstr_imm("application/octet-stream")) == 0) {
  1988.     if (coding == DC_UNDEF)
  1989. coding = DC_8BIT; /* XXX Force UCS2 with DC Field */
  1990. } else if (octstr_case_compare(type,
  1991.        octstr_imm("text/plain")) == 0) {
  1992.     if (coding == DC_UNDEF)
  1993. coding = DC_7BIT;
  1994. } else {
  1995.     error(0, "%s got weird content type %s", octstr_get_cstr(sendsms_url),
  1996.   octstr_get_cstr(type));
  1997.     *status = HTTP_UNSUPPORTED_MEDIA_TYPE;
  1998.     ret = octstr_create("Unsupported content-type, rejected");
  1999. }
  2000. if (ret == NULL)
  2001.     ret = smsbox_req_handle(t, client_ip, from, to, body, charset,
  2002.     udh, smsc, mclass, mwi, coding, compress, 
  2003.     validity, deferred, status, dlr_mask, 
  2004.     dlr_url, account, pid, alt_dcs, rpi, tolist);
  2005. octstr_destroy(type);
  2006. octstr_destroy(charset);
  2007.     }
  2008.     octstr_destroy(from);
  2009.     octstr_destroy(to);
  2010.     octstr_destroy(user);
  2011.     octstr_destroy(pass);
  2012.     octstr_destroy(udh);
  2013.     octstr_destroy(smsc);
  2014.     octstr_destroy(dlr_url);
  2015.     octstr_destroy(account);
  2016.     return ret;
  2017. }
  2018. /*
  2019.  * Create and send an SMS message from an XML-RPC request.
  2020.  * Answer with a valid XML-RPC response for a successfull request.
  2021.  * 
  2022.  * function signature: boolean sms.send(struct)
  2023.  * 
  2024.  * The <struct> MUST contain at least <member>'s with name 'username',
  2025.  * 'password', 'to' and MAY contain additional <member>'s with name
  2026.  * 'from', 'account', 'smsc', 'udh', 'dlrmask', 'dlrurl'. All values
  2027.  * are of type string.
  2028.  */
  2029. static Octstr *smsbox_xmlrpc_post(List *headers, Octstr *body,
  2030.                                   Octstr *client_ip, int *status)
  2031. {
  2032.     Octstr *from, *to, *user, *pass, *udh, *smsc;
  2033.     Octstr *ret;
  2034.     Octstr *type, *charset;
  2035.     Octstr *dlr_url;
  2036.     Octstr *account;
  2037.     Octstr *output;
  2038.     Octstr *method_name;
  2039.     XMLRPCMethodCall *msg;
  2040.     from = to = user = pass = udh = smsc = dlr_url = account = NULL;
  2041.     ret = NULL;
  2042.     /*
  2043.      * check if the content type is valid for this request
  2044.      */
  2045.     http_header_get_content_type(headers, &type, &charset);
  2046.     if (octstr_case_compare(type, octstr_imm("text/xml")) != 0) {
  2047.         error(0, "Unsupported content-type '%s'", octstr_get_cstr(type));
  2048.         *status = HTTP_BAD_REQUEST;
  2049.         ret = octstr_format("Unsupported content-type '%s'", octstr_get_cstr(type));
  2050.     } else {
  2051.         /*
  2052.          * parse the body of the request and check if it is a valid XML-RPC
  2053.          * structure
  2054.          */
  2055.         msg = xmlrpc_call_parse(body);
  2056.         if ((xmlrpc_parse_status(msg) != XMLRPC_COMPILE_OK) && 
  2057.             ((output = xmlrpc_parse_error(msg)) != NULL)) {
  2058.             /* parse failure */
  2059.             error(0, "%s", octstr_get_cstr(output));
  2060.             *status = HTTP_BAD_REQUEST;
  2061.             ret = octstr_format("%s", octstr_get_cstr(output));
  2062.             octstr_destroy(output);
  2063.         } else {
  2064.             /*
  2065.              * at least the structure has been valid, now check for the
  2066.              * required methodName and the required variables
  2067.              */
  2068.             if (octstr_case_compare((method_name = xmlrpc_get_method_name(msg)), 
  2069.                                     octstr_imm("sms.send")) != 0) {
  2070.                 error(0, "Unknown method name '%s'", octstr_get_cstr(method_name));
  2071.                 *status = HTTP_BAD_REQUEST;
  2072.                 ret = octstr_format("Unkown method name '%s'", 
  2073.                                     octstr_get_cstr(method_name));
  2074.             } else {
  2075.                 /*
  2076.                  * check for the required struct members
  2077.                  */
  2078.             }
  2079.         }
  2080.         xmlrpc_call_destroy(msg);
  2081.     }
  2082.     
  2083.     return ret;
  2084. }
  2085. /*
  2086.  * Create and send an SMS OTA (auto configuration) message from an HTTP 
  2087.  * request. If cgivar "text" is present, use it as a xml configuration source,
  2088.  * otherwise read the configuration from the configuration file.
  2089.  * Args: list contains the CGI parameters
  2090.  */
  2091. static Octstr *smsbox_req_sendota(List *list, Octstr *client_ip, int *status)
  2092. {
  2093.     Octstr *id, *from, *phonenumber, *smsc, *ota_doc, *doc_type;
  2094.     CfgGroup *grp;
  2095.     List *grplist;
  2096.     Octstr *p;
  2097.     URLTranslation *t;
  2098.     Msg *msg;
  2099.     int ret, ota_type;
  2100.     
  2101.     id = phonenumber = smsc = NULL;
  2102.     /* check the username and password */
  2103.     t = authorise_user(list, client_ip);
  2104.     if (t == NULL) {
  2105. *status = HTTP_FORBIDDEN;
  2106. return octstr_create("Authorization failed for sendota");
  2107.     }
  2108.     
  2109.     if ((phonenumber = http_cgi_variable(list, "to")) == NULL) {
  2110.         if ((phonenumber = http_cgi_variable(list, "phonenumber")) == NULL) {
  2111.             error(0, "%s needs a valid phone number.", octstr_get_cstr(sendota_url));
  2112.             *status = HTTP_BAD_REQUEST;
  2113.             return octstr_create("Wrong sendota args.");
  2114.         }
  2115.     }
  2116.     if (urltrans_faked_sender(t) != NULL) {
  2117. from = octstr_duplicate(urltrans_faked_sender(t));
  2118.     } else if ((from = http_cgi_variable(list, "from")) != NULL &&
  2119.        octstr_len(from) > 0) {
  2120. from = octstr_duplicate(from);
  2121.     } else if (urltrans_default_sender(t) != NULL) {
  2122. from = octstr_duplicate(urltrans_default_sender(t));
  2123.     } else if (global_sender != NULL) {
  2124. from = octstr_duplicate(global_sender);
  2125.     } else {
  2126. *status = HTTP_BAD_REQUEST;
  2127. return octstr_create("Sender missing and no global set, rejected");
  2128.     }
  2129.         
  2130.     /* check does we have an external XML source for configuration */
  2131.     if ((ota_doc = http_cgi_variable(list, "text")) != NULL) {
  2132.         
  2133.         /*
  2134.          * We are doing the XML OTA compiler mode for this request
  2135.          */
  2136.         debug("sms", 0, "OTA service with XML document");
  2137.         ota_doc = octstr_duplicate(ota_doc);
  2138.         if ((doc_type = http_cgi_variable(list, "type")) == NULL) {
  2139.     doc_type = octstr_format("%s", "settings");
  2140.         } else {
  2141.     doc_type = octstr_duplicate(doc_type);
  2142.         }
  2143.         if ((ret = ota_pack_message(&msg, ota_doc, doc_type, from, 
  2144.                                 phonenumber)) < 0) {
  2145.             *status = HTTP_BAD_REQUEST;
  2146.             msg_destroy(msg);
  2147.             if (ret == -2)
  2148.                 return octstr_create("Erroneous document type, cannot"
  2149.                                      " compilen");
  2150.             else if (ret == -1)
  2151.         return octstr_create("Erroneous ota source, cannot compilen");
  2152.         }
  2153.         goto send;
  2154.     } else {
  2155.         /* 
  2156.          * We are doing the ota-settings or ota-bookmark group mode
  2157.          * for this request.
  2158.          *
  2159.          * Check if a ota-setting ID has been given and decide which OTA
  2160.          * properties to be send to the client otherwise try to find a
  2161.          * ota-bookmark ID. If none is found then send the default 
  2162.          * ota-setting group, which is the first within the config file.
  2163.          */
  2164.         id = http_cgi_variable(list, "otaid");
  2165.     
  2166.         grplist = cfg_get_multi_group(cfg, octstr_imm("ota-setting"));
  2167.         while (grplist && (grp = list_extract_first(grplist)) != NULL) {
  2168.             p = cfg_get(grp, octstr_imm("ota-id"));
  2169.             if (id == NULL || (p != NULL && octstr_compare(p, id) == 0)) {
  2170.                 ota_type = 1;
  2171.                 goto found;
  2172.             }
  2173.             octstr_destroy(p);
  2174.         }
  2175.         list_destroy(grplist, NULL);
  2176.         
  2177.         grplist = cfg_get_multi_group(cfg, octstr_imm("ota-bookmark"));
  2178.         while (grplist && (grp = list_extract_first(grplist)) != NULL) {
  2179.             p = cfg_get(grp, octstr_imm("ota-id"));
  2180.             if (id == NULL || (p != NULL && octstr_compare(p, id) == 0)) {
  2181.                 ota_type = 0;             
  2182.                 goto found;
  2183.             }
  2184.             octstr_destroy(p);
  2185.         }
  2186.         list_destroy(grplist, NULL);
  2187.         
  2188.         if (id != NULL)
  2189.             error(0, "%s can't find any ota-setting or ota-bookmark group with ota-id '%s'.", 
  2190.                  octstr_get_cstr(sendota_url), octstr_get_cstr(id));
  2191.         else
  2192.        error(0, "%s can't find any ota-setting group.", octstr_get_cstr(sendota_url));
  2193.         octstr_destroy(from);
  2194.         *status = HTTP_BAD_REQUEST;
  2195.         return octstr_create("Missing ota-setting or ota-bookmark group.");
  2196.     }
  2197.     
  2198. found:
  2199.     octstr_destroy(p);
  2200.     list_destroy(grplist, NULL);
  2201.     /* tokenize the OTA settings or bookmarks group and return the message */
  2202.     if (ota_type)
  2203.         msg = ota_tokenize_settings(grp, from, phonenumber);
  2204.     else
  2205.         msg = ota_tokenize_bookmarks(grp, from, phonenumber);
  2206. send: 
  2207.     /* we still need to check if smsc is forced for this */
  2208.     smsc = http_cgi_variable(list, "smsc");
  2209.     if (urltrans_forced_smsc(t)) {
  2210.         msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
  2211.         if (smsc)
  2212.             info(0, "send-sms request smsc id ignored, as smsc id forced to %s",
  2213.                  octstr_get_cstr(urltrans_forced_smsc(t)));
  2214.     } else if (smsc) {
  2215.         msg->sms.smsc_id = octstr_duplicate(smsc);
  2216.     } else if (urltrans_default_smsc(t)) {
  2217.         msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
  2218.     } else
  2219.         msg->sms.smsc_id = NULL;
  2220.     octstr_dump(msg->sms.msgdata, 0);
  2221.     info(0, "%s <%s> <%s>", octstr_get_cstr(sendota_url), 
  2222.       id ? octstr_get_cstr(id) : "<default>", octstr_get_cstr(phonenumber));
  2223.     
  2224.     ret = send_message(t, msg); 
  2225.     msg_destroy(msg);
  2226.     if (ret == -1) {
  2227.         error(0, "sendota_request: failed");
  2228.         *status = HTTP_INTERNAL_SERVER_ERROR;
  2229.         return octstr_create("Sending failed.");
  2230.     }
  2231.     *status = HTTP_ACCEPTED;
  2232.     return octstr_create("Sent.");
  2233. }
  2234. /*
  2235.  * Create and send an SMS OTA (auto configuration) message from an HTTP POST 
  2236.  * request. Take the X-Kannel-foobar HTTP headers as parameter information.
  2237.  * Args: list contains the CGI parameters
  2238.  *
  2239.  * We still care about passed GET variable, in case the X-Kannel-foobar
  2240.  * parameters are not used but the POST contains the XML body itself.
  2241.  */
  2242. static Octstr *smsbox_sendota_post(List *headers, Octstr *body,
  2243.                                    Octstr *client_ip, int *status)
  2244. {
  2245.     Octstr *name, *val, *ret;
  2246.     Octstr *from, *to, *id, *user, *pass, *smsc;
  2247.     Octstr *type, *charset, *doc_type, *ota_doc;
  2248.     URLTranslation *t;
  2249.     Msg *msg;
  2250.     long l;
  2251.     int r;
  2252.     id = from = to = user = pass = smsc = NULL;
  2253.     doc_type = ota_doc = NULL;
  2254.     /* 
  2255.      * process all special HTTP headers 
  2256.      */
  2257.     for (l = 0; l < list_len(headers); l++) {
  2258.     http_header_get(headers, l, &name, &val);
  2259. if (octstr_case_compare(name, octstr_imm("X-Kannel-OTA-ID")) == 0) {
  2260.     id = octstr_duplicate(val);
  2261.     octstr_strip_blanks(id);
  2262. }
  2263. else if (octstr_case_compare(name, octstr_imm("X-Kannel-From")) == 0) {
  2264.     from = octstr_duplicate(val);
  2265.     octstr_strip_blanks(from);
  2266. }
  2267. else if (octstr_case_compare(name, octstr_imm("X-Kannel-To")) == 0) {
  2268.     to = octstr_duplicate(val);
  2269.     octstr_strip_blanks(to);
  2270. }
  2271. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Username")) == 0) {
  2272. user = octstr_duplicate(val);
  2273. octstr_strip_blanks(user);
  2274. }
  2275. else if (octstr_case_compare(name, octstr_imm("X-Kannel-Password")) == 0) {
  2276. pass = octstr_duplicate(val);
  2277. octstr_strip_blanks(pass);
  2278. }
  2279. else if (octstr_case_compare(name, octstr_imm("X-Kannel-SMSC")) == 0) {
  2280. smsc = octstr_duplicate(val);
  2281. octstr_strip_blanks(smsc);
  2282. }
  2283.     }
  2284.     /* check the username and password */
  2285.     t = authorise_username(user, pass, client_ip);
  2286.     if (t == NULL) {
  2287.    *status = HTTP_FORBIDDEN;
  2288.    ret = octstr_create("Authorization failed for sendota");
  2289.     }
  2290.     /* let's see if we have at least a target msisdn */
  2291.     else if (to == NULL) {
  2292.    error(0, "%s needs a valid phone number.", octstr_get_cstr(sendota_url));
  2293.    *status = HTTP_BAD_REQUEST;
  2294.        ret = octstr_create("Wrong sendota args.");
  2295.     } else {
  2296.     if (urltrans_faked_sender(t) != NULL) {
  2297.         from = octstr_duplicate(urltrans_faked_sender(t));
  2298.     } else if (from != NULL && octstr_len(from) > 0) {
  2299.     } else if (urltrans_default_sender(t) != NULL) {
  2300.         from = octstr_duplicate(urltrans_default_sender(t));
  2301.     } else if (global_sender != NULL) {
  2302.         from = octstr_duplicate(global_sender);
  2303.     } else {
  2304.         *status = HTTP_BAD_REQUEST;
  2305.         ret = octstr_create("Sender missing and no global set, rejected");
  2306.         goto error;
  2307.     }
  2308.     /*
  2309.      * get the content-type of the body document 
  2310.      */
  2311.     http_header_get_content_type(headers, &type, &charset);
  2312. if (octstr_case_compare(type, 
  2313.         octstr_imm("application/x-wap-prov.browser-settings")) == 0) {
  2314.         doc_type = octstr_format("%s", "settings");
  2315.     } 
  2316.     else if (octstr_case_compare(type, 
  2317.              octstr_imm("application/x-wap-prov.browser-bookmarks")) == 0) {
  2318.     doc_type = octstr_format("%s", "bookmarks");
  2319.     }
  2320.     if (doc_type == NULL) {
  2321.     error(0, "%s got weird content type %s", octstr_get_cstr(sendota_url),
  2322.               octstr_get_cstr(type));
  2323.     *status = HTTP_UNSUPPORTED_MEDIA_TYPE;
  2324.     ret = octstr_create("Unsupported content-type, rejected");
  2325. } else {
  2326.         /* 
  2327.          * ok, this is want we expect
  2328.          * now lets compile the whole thing 
  2329.          */
  2330.         ota_doc = octstr_duplicate(body);
  2331.         if ((r = ota_pack_message(&msg, ota_doc, doc_type, from, to)) < 0) {
  2332.             *status = HTTP_BAD_REQUEST;
  2333.             msg_destroy(msg);
  2334.             if (r == -2) {
  2335.                 ret = octstr_create("Erroneous document type, cannot"
  2336.                                      " compilen");
  2337.                 goto error;
  2338.             }
  2339.             else if (r == -1) {
  2340.            ret = octstr_create("Erroneous ota source, cannot compilen");
  2341.                goto error;
  2342.             }
  2343.         }
  2344.         /* we still need to check if smsc is forced for this */
  2345.         if (urltrans_forced_smsc(t)) {
  2346.             msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
  2347.             if (smsc)
  2348.                 info(0, "send-sms request smsc id ignored, as smsc id forced to %s",
  2349.                      octstr_get_cstr(urltrans_forced_smsc(t)));
  2350.         } else if (smsc) {
  2351.             msg->sms.smsc_id = octstr_duplicate(smsc);
  2352.         } else if (urltrans_default_smsc(t)) {
  2353.             msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
  2354.         } else
  2355.             msg->sms.smsc_id = NULL;
  2356.         info(0, "%s <%s> <%s>", octstr_get_cstr(sendota_url), 
  2357.              id ? octstr_get_cstr(id) : "XML", octstr_get_cstr(to));
  2358.     
  2359.         r = send_message(t, msg); 
  2360.         msg_destroy(msg);
  2361.         if (r == -1) {
  2362.             error(0, "sendota_request: failed");
  2363.             *status = HTTP_INTERNAL_SERVER_ERROR;
  2364.             ret = octstr_create("Sending failed.");
  2365.         }
  2366.         *status = HTTP_ACCEPTED;
  2367.         ret = octstr_create("Sent.");
  2368.     }
  2369.     }    
  2370.     
  2371. error:
  2372.     octstr_destroy(user);
  2373.     octstr_destroy(pass);
  2374.     octstr_destroy(smsc);
  2375.     return ret;
  2376. }
  2377. static void sendsms_thread(void *arg)
  2378. {
  2379.     HTTPClient *client;
  2380.     Octstr *ip, *url, *body, *answer;
  2381.     List *hdrs, *args, *reply_hdrs;
  2382.     int status;
  2383.     reply_hdrs = http_create_empty_headers();
  2384.     http_header_add(reply_hdrs, "Content-type", "text/html");
  2385.     http_header_add(reply_hdrs, "Pragma", "no-cache");
  2386.     http_header_add(reply_hdrs, "Cache-Control", "no-cache");
  2387.     for (;;) {
  2388.      client = http_accept_request(sendsms_port, &ip, &url, &hdrs, &body, 
  2389.                     &args);
  2390. if (client == NULL)
  2391.     break;
  2392. info(0, "smsbox: Got HTTP request <%s> from <%s>",
  2393.     octstr_get_cstr(url), octstr_get_cstr(ip));
  2394.     /*
  2395.      * determine which kind of HTTP request this is any
  2396.      * call the necessary routine for it
  2397.      */
  2398.     /* sendsms */
  2399.     if (octstr_compare(url, sendsms_url) == 0)
  2400.     {
  2401. /* 
  2402.  * decide if this is a GET or POST request and let the 
  2403.  * related routine handle the checking
  2404.  */
  2405. if (body == NULL)
  2406.     answer = smsbox_req_sendsms(args, ip, &status);
  2407. else
  2408.     answer = smsbox_sendsms_post(hdrs, body, ip, &status);
  2409.     }
  2410.     /* XML-RPC */
  2411.     else if (octstr_compare(url, xmlrpc_url) == 0)
  2412.     {
  2413.         /*
  2414.          * XML-RPC request needs to have a POST body
  2415.          */
  2416.         if (body == NULL) {
  2417.             answer = octstr_create("Incomplete request.");
  2418.             status = HTTP_BAD_REQUEST;
  2419.         } else
  2420.             answer = smsbox_xmlrpc_post(hdrs, body, ip, &status);
  2421.     }
  2422.     /* sendota */
  2423.     else if (octstr_compare(url, sendota_url) == 0)
  2424.     {
  2425. if (body == NULL)
  2426.             answer = smsbox_req_sendota(args, ip, &status);
  2427.         else
  2428.             answer = smsbox_sendota_post(hdrs, body, ip, &status);
  2429.     }
  2430.     /* add aditional URI compares here */
  2431.     else {
  2432.         answer = octstr_create("Unknown request.");
  2433.         status = HTTP_NOT_FOUND;
  2434.     }
  2435. debug("sms.http", 0, "Status: %d Answer: <%s>", status,
  2436.           octstr_get_cstr(answer));
  2437.     octstr_destroy(ip);
  2438.     octstr_destroy(url);
  2439.     http_destroy_headers(hdrs);
  2440.     octstr_destroy(body);
  2441.     http_destroy_cgiargs(args);
  2442.     http_send_reply(client, status, reply_hdrs, answer);
  2443.     octstr_destroy(answer);
  2444.     }
  2445.     http_destroy_headers(reply_hdrs);
  2446. }
  2447. /***********************************************************************
  2448.  * Main program. Configuration, signal handling, etc.
  2449.  */
  2450. static void write_pid_file(void) {
  2451.     FILE *f;
  2452.         
  2453.     if (pid_file != NULL) {
  2454. f = fopen(pid_file, "w");
  2455. fprintf(f, "%dn", (int)getpid());
  2456. fclose(f);
  2457.     }
  2458. }
  2459. static void signal_handler(int signum) {
  2460.     /* On some implementations (i.e. linuxthreads), signals are delivered
  2461.      * to all threads.  We only want to handle each signal once for the
  2462.      * entire box, and we let the gwthread wrapper take care of choosing
  2463.      * one.
  2464.      */
  2465.     if (!gwthread_shouldhandlesignal(signum))
  2466.         return;
  2467.     switch (signum) {
  2468.         case SIGINT:
  2469.             if (program_status != shutting_down) {
  2470.                 error(0, "SIGINT received, aborting program...");
  2471.                 program_status = shutting_down;
  2472.             }
  2473.             break;
  2474.         case SIGHUP:
  2475.             warning(0, "SIGHUP received, catching and re-opening logs");
  2476.             log_reopen();
  2477.             alog_reopen();
  2478.             break;
  2479.         /* 
  2480.          * It would be more proper to use SIGUSR1 for this, but on some
  2481.          * platforms that's reserved by the pthread support. 
  2482.          */
  2483.         case SIGQUIT:
  2484.        warning(0, "SIGQUIT received, reporting memory usage.");
  2485.        gw_check_leaks();
  2486.        break;
  2487.     }
  2488. }
  2489. static void setup_signal_handlers(void) {
  2490.     struct sigaction act;
  2491.     act.sa_handler = signal_handler;
  2492.     sigemptyset(&act.sa_mask);
  2493.     act.sa_flags = 0;
  2494.     sigaction(SIGINT, &act, NULL);
  2495.     sigaction(SIGQUIT, &act, NULL);
  2496.     sigaction(SIGHUP, &act, NULL);
  2497.     sigaction(SIGPIPE, &act, NULL);
  2498. }
  2499. static Cfg *init_smsbox(Cfg *cfg)
  2500. {
  2501.     CfgGroup *grp;
  2502.     Octstr *logfile;
  2503.     Octstr *p;
  2504.     long lvl;
  2505.     Octstr *http_proxy_host = NULL;
  2506.     long http_proxy_port = -1;
  2507.     List *http_proxy_exceptions = NULL;
  2508.     Octstr *http_proxy_username = NULL;
  2509.     Octstr *http_proxy_password = NULL;
  2510.     int ssl = 0;
  2511.     bb_port = BB_DEFAULT_SMSBOX_PORT;
  2512.     bb_ssl = 0;
  2513.     bb_host = octstr_create(BB_DEFAULT_HOST);
  2514.     logfile = NULL;
  2515.     lvl = 0;
  2516.     /*
  2517.      * first we take the port number in bearerbox and other values from the
  2518.      * core group in configuration file
  2519.      */
  2520.     grp = cfg_get_single_group(cfg, octstr_imm("core"));
  2521.     
  2522.     if (cfg_get_integer(&bb_port, grp, octstr_imm("smsbox-port")) == -1)
  2523. panic(0, "Missing or bad 'smsbox-port' in core group");
  2524. #ifdef HAVE_LIBSSL
  2525.     cfg_get_bool(&bb_ssl, grp, octstr_imm("smsbox-port-ssl"));
  2526. #endif /* HAVE_LIBSSL */
  2527.     cfg_get_integer(&http_proxy_port, grp, octstr_imm("http-proxy-port"));
  2528.     http_proxy_host = cfg_get(grp, 
  2529.                octstr_imm("http-proxy-host"));
  2530.     http_proxy_username = cfg_get(grp, 
  2531.                    octstr_imm("http-proxy-username"));
  2532.     http_proxy_password = cfg_get(grp, 
  2533.                    octstr_imm("http-proxy-password"));
  2534.     http_proxy_exceptions = cfg_get_list(grp,
  2535.                    octstr_imm("http-proxy-exceptions"));
  2536. #ifdef HAVE_LIBSSL
  2537.     conn_config_ssl(grp);
  2538. #endif 
  2539.     
  2540.     /*
  2541.      * get the remaining values from the smsbox group
  2542.      */
  2543.     grp = cfg_get_single_group(cfg, octstr_imm("smsbox"));
  2544.     if (grp == NULL)
  2545. panic(0, "No 'smsbox' group in configuration");
  2546.     p = cfg_get(grp, octstr_imm("bearerbox-host"));
  2547.     if (p != NULL) {
  2548. octstr_destroy(bb_host);
  2549. bb_host = p;
  2550.     }
  2551.     cfg_get_bool(&mo_recode, grp, octstr_imm("mo-recode"));
  2552.     if(mo_recode < 0)
  2553. mo_recode = 0;
  2554.     reply_couldnotfetch= cfg_get(grp, octstr_imm("reply-couldnotfetch"));
  2555.     if (reply_couldnotfetch == NULL)
  2556. reply_couldnotfetch = octstr_create("Could not fetch content, sorry.");
  2557.     reply_couldnotrepresent= cfg_get(grp, octstr_imm("reply-couldnotfetch"));
  2558.     if (reply_couldnotrepresent == NULL)
  2559. reply_couldnotrepresent = octstr_create("Result could not be represented "
  2560.         "as an SMS message.");
  2561.     reply_requestfailed= cfg_get(grp, octstr_imm("reply-requestfailed"));
  2562.     if (reply_requestfailed == NULL)
  2563. reply_requestfailed = octstr_create("Request Failed");
  2564.     reply_emptymessage= cfg_get(grp, octstr_imm("reply-emptymessage"));
  2565.     if (reply_emptymessage == NULL)
  2566. reply_emptymessage = octstr_create("<Empty reply from service provider>");
  2567.     {   
  2568. Octstr *os;
  2569. os = cfg_get(grp, octstr_imm("white-list"));
  2570. if (os != NULL) {
  2571.     white_list = numhash_create(octstr_get_cstr(os));
  2572.     octstr_destroy(os);
  2573. }
  2574. os = cfg_get(grp, octstr_imm("black-list"));
  2575. if (os != NULL) {
  2576.     black_list = numhash_create(octstr_get_cstr(os));
  2577.     octstr_destroy(os);
  2578. }
  2579.     }
  2580.     cfg_get_integer(&sendsms_port, grp, octstr_imm("sendsms-port"));
  2581.     cfg_get_integer(&sms_max_length, grp, octstr_imm("sms-length"));
  2582. #ifdef HAVE_LIBSSL
  2583.     cfg_get_bool(&ssl, grp, octstr_imm("sendsms-port-ssl"));
  2584. #endif /* HAVE_LIBSSL */
  2585.     /*
  2586.      * load the configuration settings for the sendsms and sendota URIs
  2587.      * else assume the default URIs, st.
  2588.      */
  2589.     if ((sendsms_url = cfg_get(grp, octstr_imm("sendsms-url"))) == NULL)
  2590.         sendsms_url = octstr_imm("/cgi-bin/sendsms");
  2591.     if ((xmlrpc_url = cfg_get(grp, octstr_imm("xmlrpc-url"))) == NULL)
  2592.         xmlrpc_url = octstr_imm("/cgi-bin/xmlrpc");
  2593.     if ((sendota_url = cfg_get(grp, octstr_imm("sendota-url"))) == NULL)
  2594.         sendota_url = octstr_imm("/cgi-bin/sendota");
  2595.     global_sender = cfg_get(grp, octstr_imm("global-sender"));
  2596.     accepted_chars = cfg_get(grp, octstr_imm("sendsms-chars"));
  2597.     logfile = cfg_get(grp, octstr_imm("log-file"));
  2598.     cfg_get_integer(&lvl, grp, octstr_imm("log-level"));
  2599.     if (logfile != NULL) {
  2600. info(0, "Starting to log to file %s level %ld", 
  2601.      octstr_get_cstr(logfile), lvl);
  2602. log_open(octstr_get_cstr(logfile), lvl);
  2603. octstr_destroy(logfile);
  2604.     }
  2605.     if (global_sender != NULL) {
  2606. info(0, "Service global sender set as '%s'", 
  2607.      octstr_get_cstr(global_sender));
  2608.     }
  2609.     
  2610.     p = cfg_get(grp, octstr_imm("access-log"));
  2611.     if (p != NULL) {
  2612. info(0, "Logging accesses to '%s'.", octstr_get_cstr(p));
  2613. alog_open(octstr_get_cstr(p), 1);
  2614.     /* XXX should be able to use gmtime, too */
  2615. octstr_destroy(p);
  2616.     }
  2617.     /* HTTP queueing values */
  2618.     cfg_get_integer(&max_http_retries, grp, octstr_imm("http-request-retry"));
  2619.     cfg_get_integer(&http_queue_delay, grp, octstr_imm("http-queue-delay"));
  2620.     if (sendsms_port > 0) {
  2621. if (http_open_port(sendsms_port, ssl) == -1) {
  2622.     if (only_try_http)
  2623. error(0, "Failed to open HTTP socket, ignoring it");
  2624.     else
  2625. panic(0, "Failed to open HTTP socket");
  2626. }
  2627. else {
  2628.     info(0, "Set up send sms service at port %ld", sendsms_port);
  2629.     gwthread_create(sendsms_thread, NULL);
  2630. }
  2631.     }
  2632.     if (http_proxy_host != NULL && http_proxy_port > 0) {
  2633.      http_use_proxy(http_proxy_host, http_proxy_port,
  2634.        http_proxy_exceptions, http_proxy_username,
  2635.                        http_proxy_password);
  2636.     }
  2637.     octstr_destroy(http_proxy_host);
  2638.     octstr_destroy(http_proxy_username);
  2639.     octstr_destroy(http_proxy_password);
  2640.     list_destroy(http_proxy_exceptions, octstr_destroy_item);
  2641.     return cfg;
  2642. }
  2643. static int check_args(int i, int argc, char **argv) {
  2644.     if (strcmp(argv[i], "-H")==0 || strcmp(argv[i], "--tryhttp")==0) {
  2645. only_try_http = 1;
  2646.     } else
  2647. return -1;
  2648.     return 0;
  2649. int main(int argc, char **argv)
  2650. {
  2651.     int cf_index;
  2652.     Octstr *filename;
  2653.     double heartbeat_freq = DEFAULT_HEARTBEAT;
  2654.     gwlib_init();
  2655.     cf_index = get_and_set_debugs(argc, argv, check_args);
  2656.     
  2657.     setup_signal_handlers();
  2658.     
  2659.     if (argv[cf_index] == NULL)
  2660. filename = octstr_create("kannel.conf");
  2661.     else
  2662. filename = octstr_create(argv[cf_index]);
  2663.     cfg = cfg_create(filename);
  2664.     if (cfg_read(cfg) == -1)
  2665. panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(filename));
  2666.     octstr_destroy(filename);
  2667.     report_versions("smsbox");
  2668.     init_smsbox(cfg);
  2669.     if (max_http_retries > 0) {
  2670.         info(0, "Using HTTP request queueing with %ld retries, %lds delay.", 
  2671.                 max_http_retries, http_queue_delay);
  2672.     }
  2673.     debug("sms", 0, "----------------------------------------------");
  2674.     debug("sms", 0, GW_NAME " smsbox version %s starting", VERSION);
  2675.     write_pid_file();
  2676.     translations = urltrans_create();
  2677.     if (translations == NULL)
  2678. panic(0, "urltrans_create failed");
  2679.     if (urltrans_add_cfg(translations, cfg) == -1)
  2680. panic(0, "urltrans_add_cfg failed");
  2681.     sendsms_number_chars = SENDSMS_DEFAULT_CHARS;
  2682.     caller = http_caller_create();
  2683.     smsbox_requests = list_create();
  2684.     smsbox_http_requests = list_create();
  2685.     list_add_producer(smsbox_requests);
  2686.     list_add_producer(smsbox_http_requests);
  2687.     num_outstanding_requests = counter_create();
  2688.     catenated_sms_counter = counter_create();
  2689.     gwthread_create(obey_request_thread, NULL);
  2690.     gwthread_create(url_result_thread, NULL);
  2691.     gwthread_create(http_queue_thread, NULL);
  2692.     connect_to_bearerbox(bb_host, bb_port, bb_ssl, NULL /* bb_our_host */);
  2693. /* XXX add our_host if required */
  2694.     if (0 > heartbeat_start(write_to_bearerbox, heartbeat_freq,
  2695.        outstanding_requests)) {
  2696.         info(0, GW_NAME "Could not start heartbeat.");
  2697.     }
  2698.     read_messages_from_bearerbox();
  2699.     info(0, GW_NAME " smsbox terminating.");
  2700.     heartbeat_stop(ALL_HEARTBEATS);
  2701.     http_close_all_ports();
  2702.     gwthread_join_every(sendsms_thread);
  2703.     list_remove_producer(smsbox_requests);
  2704.     list_remove_producer(smsbox_http_requests);
  2705.     gwthread_join_every(obey_request_thread);
  2706.     http_caller_signal_shutdown(caller);
  2707.     gwthread_join_every(url_result_thread);
  2708.     gwthread_join_every(http_queue_thread);
  2709.     close_connection_to_bearerbox();
  2710.     alog_close();
  2711.     urltrans_destroy(translations);
  2712.     gw_assert(list_len(smsbox_requests) == 0);
  2713.     gw_assert(list_len(smsbox_http_requests) == 0);
  2714.     list_destroy(smsbox_requests, NULL);
  2715.     list_destroy(smsbox_http_requests, NULL);
  2716.     http_caller_destroy(caller);
  2717.     counter_destroy(num_outstanding_requests);
  2718.     counter_destroy(catenated_sms_counter);
  2719.     octstr_destroy(bb_host);
  2720.     octstr_destroy(global_sender);
  2721.     octstr_destroy(accepted_chars);
  2722.     octstr_destroy(sendsms_url);
  2723.     octstr_destroy(sendota_url);
  2724.     octstr_destroy(xmlrpc_url);
  2725.     octstr_destroy(reply_emptymessage);
  2726.     octstr_destroy(reply_requestfailed);
  2727.     octstr_destroy(reply_couldnotfetch);
  2728.     octstr_destroy(reply_couldnotrepresent);
  2729.     numhash_destroy(black_list);
  2730.     numhash_destroy(white_list);
  2731.     cfg_destroy(cfg);
  2732.     gwlib_shutdown();
  2733.     return 0;
  2734. }
  2735. int charset_processing (Octstr *charset, Octstr *body, int coding) {
  2736.     int resultcode = 0;
  2737.     
  2738.     if (octstr_len(charset)) {
  2739. // debug("sms.http", 0, "enter charset, coding=%d, msgdata is %s", coding, octstr_get_cstr(body));
  2740. // octstr_dump(body, 0);
  2741. if (coding == DC_7BIT) {
  2742.     /*
  2743.      * For 7 bit, convert to ISO-8859-1
  2744.      */
  2745.     if (octstr_recode (octstr_imm ("ISO-8859-1"), charset, body) < 0) {
  2746. resultcode = -1;
  2747.     }
  2748. } else if (coding == DC_UCS2) {
  2749.     /*
  2750.      * For UCS2, convert to UTF-16BE
  2751.      */
  2752.     if (octstr_recode (octstr_imm ("UTF-16BE"), charset, body) < 0) {
  2753. resultcode = -1;
  2754.     }
  2755. }
  2756. // debug("sms.http", 0, "exit charset, coding=%d, msgdata is %s", coding, octstr_get_cstr(body));
  2757. // octstr_dump(body, 0);
  2758.     }
  2759.     
  2760.     return resultcode;
  2761. }