コード例 #1
0
ファイル: smsc_wrapper.c プロジェクト: Jayriq/kannel-gateway
static void wrapper_sender(void *arg)
{
    Msg 	*msg;
    SMSCConn 	*conn = arg;
    SmscWrapper *wrap = conn->data;

    /* Make sure we log into our own log-file if defined */
    log_thread_to(conn->log_idx);

    /* send messages to SMSC until our outgoing_list is empty and
     * no producer anymore (we are set to shutdown) */
    while(conn->status != SMSCCONN_DEAD) {

	if ((msg = gwlist_consume(wrap->outgoing_queue)) == NULL)
            break;

        if (octstr_search_char(msg->sms.receiver, ' ', 0) != -1) {
            /*
             * multi-send: this should be implemented in corresponding
             *  SMSC protocol, but while we are waiting for that...
             */
            int i;
	    Msg *newmsg;
            /* split from spaces: in future, split with something more sensible,
             * this is dangerous... (as space is url-encoded as '+')
             */
            List *nlist = octstr_split_words(msg->sms.receiver);

	    debug("bb.sms", 0, "Handling multi-receiver message");

            for(i=0; i < gwlist_len(nlist); i++) {

		newmsg = msg_duplicate(msg);
                octstr_destroy(newmsg->sms.receiver);

                newmsg->sms.receiver = gwlist_get(nlist, i);
                sms_send(conn, newmsg);
            }
            gwlist_destroy(nlist, NULL);
            msg_destroy(msg);
        }
        else
	    sms_send(conn,msg);

    }
    /* cleanup, we are now dying */

    debug("bb.sms", 0, "SMSCConn %s sender died, waiting for receiver",
	  octstr_get_cstr(conn->name));
    
    conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;

    if (conn->is_stopped) {
	gwlist_remove_producer(wrap->stopped);
	conn->is_stopped = 0;
    }

    gwthread_wakeup(wrap->receiver_thread);
    gwthread_join(wrap->receiver_thread);

    /* call 'failed' to all messages still in queue */
    
    mutex_lock(conn->flow_mutex);

    conn->status = SMSCCONN_DEAD;

    while((msg = gwlist_extract_first(wrap->outgoing_queue))!=NULL) {
	bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
    }
    smscwrapper_destroy(wrap);
    conn->data = NULL;
    
    mutex_unlock(conn->flow_mutex);

    bb_smscconn_killed();
}
コード例 #2
0
ファイル: urltrans.c プロジェクト: gburiticato/kannel
Octstr *urltrans_fill_escape_codes(Octstr *pattern, Msg *request)
{
    Octstr *enc;
    Octstr *meta_group, *meta_param;
    int nextarg, j;
    struct tm tm;
    int num_words;
    List *word_list;
    Octstr *result;
    long pattern_len;
    long pos;
    int c;
    long i, k;
    Octstr *temp;

    result = octstr_create("");

    if (request->sms.msgdata) {
        word_list = octstr_split_words(request->sms.msgdata);
        num_words = gwlist_len(word_list);
    } else {
        word_list = gwlist_create();
        num_words = 0;
    }
    
    pattern_len = octstr_len(pattern);
    nextarg = 1;
    pos = 0;
    for (;;) {
        while (pos < pattern_len) {
            c = octstr_get_char(pattern, pos);
            if (c == '%' && pos + 1 < pattern_len)
                break;
            octstr_append_char(result, c);
            ++pos;
        }

        if (pos == pattern_len)
            break;

    switch (octstr_get_char(pattern, pos + 1)) {
    case 'a':
        for (j = 0; j < num_words; ++j) {
        enc = octstr_duplicate(gwlist_get(word_list, j));
        octstr_url_encode(enc);
        if (j > 0)
            octstr_append_char(result, '+');
        octstr_append(result, enc);
        octstr_destroy(enc);
        }
        break;

    case 'A':
        if (request->sms.msgdata) {
        enc = octstr_duplicate(request->sms.msgdata);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        }
        break;

    case 'b':
        enc = octstr_duplicate(request->sms.msgdata);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'B':  /* billing identifier/information */
        if (octstr_len(request->sms.binfo)) {
            enc = octstr_duplicate(request->sms.binfo);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;

    case 'c':
        octstr_append_decimal(result, request->sms.coding);
        break;

    case 'C':
        if (octstr_len(request->sms.charset)) {
            octstr_append(result, request->sms.charset);
        } else {
            switch (request->sms.coding) {
            case DC_UNDEF:
            case DC_7BIT:
                octstr_append(result, octstr_imm("UTF-8"));
                break;
            case DC_8BIT:
                octstr_append(result, octstr_imm("8-BIT"));
                break;
            case DC_UCS2:
                octstr_append(result, octstr_imm("UTF-16BE"));
                break;
            }
        }
        break;

    case 'd':
        enc = octstr_create("");
        octstr_append_decimal(enc, request->sms.dlr_mask);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'D': /* meta_data */
        if (octstr_len(request->sms.meta_data)) {
            enc = octstr_duplicate(request->sms.meta_data);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;

    case 'f':  /* smsc number*/
        if (octstr_len(request->sms.smsc_number)) {
            enc = octstr_duplicate(request->sms.smsc_number);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;

    case 'F':
        if (request->sms.foreign_id == NULL)
            break;
        enc = octstr_duplicate(request->sms.foreign_id);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'i':
        if (request->sms.smsc_id == NULL)
        break;
        enc = octstr_duplicate(request->sms.smsc_id);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'I':
        if (!uuid_is_null(request->sms.id)) {
                char id[UUID_STR_LEN + 1];
                uuid_unparse(request->sms.id, id);
            octstr_append_cstr(result, id);
            }
        break;

    case 'k':
        if (num_words <= 0)
        break;
        enc = octstr_duplicate(gwlist_get(word_list, 0));
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'm':  /* mclass - message class */
        enc = octstr_create("");
        octstr_append_decimal(enc, request->sms.mclass);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'M':  /* mwi - message waiting indicator */
        enc = octstr_create("");
        octstr_append_decimal(enc, request->sms.mwi);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'n':
        if (request->sms.service == NULL)
        break;
        enc = octstr_duplicate(request->sms.service);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'o':  /* account information (may be operator id for aggregators */
        if (octstr_len(request->sms.account)) {
            enc = octstr_duplicate(request->sms.account);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;

    case 'O':  /* DCS */
    {
        int dcs;
        dcs = fields_to_dcs(request, request->sms.alt_dcs);
        octstr_format_append(result, "%02d", dcs);
        break;
    }

    /* NOTE: the sender and receiver is already switched in
     *    message, so that's why we must use 'sender' when
     *    we want original receiver and vice versa
     */
    case 'P':
        enc = octstr_duplicate(request->sms.sender);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'p':
        enc = octstr_duplicate(request->sms.receiver);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        break;

    case 'q':
        if (strncmp(octstr_get_cstr(request->sms.receiver),"00",2)==0) {
        enc = octstr_copy(request->sms.receiver, 2, 
                          octstr_len(request->sms.receiver));
        octstr_url_encode(enc);
        octstr_format_append(result, "%%2B%S", enc);
        octstr_destroy(enc);
        } else {
        enc = octstr_duplicate(request->sms.receiver);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        }
        break;

    case 'Q':
        if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) {
        enc = octstr_copy(request->sms.sender, 2, 
                          octstr_len(request->sms.sender));
        octstr_url_encode(enc);
        octstr_format_append(result, "%%2B%S", enc);
        octstr_destroy(enc);
        } else {
        enc = octstr_duplicate(request->sms.sender);
                octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        }
        break;

    case 'r':
        for (j = nextarg; j < num_words; ++j) {
        enc = octstr_duplicate(gwlist_get(word_list, j));
        octstr_url_encode(enc);
        if (j != nextarg)
            octstr_append_char(result, '+');
        octstr_append(result, enc);
        octstr_destroy(enc);
        }
        break;

    case 'R': /* dlr_url */
        if (octstr_len(request->sms.dlr_url)) {
            enc = octstr_duplicate(request->sms.dlr_url);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;

    case 's':
        if (nextarg >= num_words)
        	break;
        enc = octstr_duplicate(gwlist_get(word_list, nextarg));
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        ++nextarg;
        break;

    case 'S':
        if (nextarg >= num_words)
        	break;
        temp = gwlist_get(word_list, nextarg);
        for (i = 0; i < octstr_len(temp); ++i) {
        	if (octstr_get_char(temp, i) == '*')
        		octstr_append_char(result, '~');
        	else
        		octstr_append_char(result, octstr_get_char(temp, i));
        }
        ++nextarg;
        break;

    case 't':
        tm = gw_gmtime(request->sms.time);
        octstr_format_append(result, "%04d-%02d-%02d+%02d:%02d:%02d",
                 tm.tm_year + 1900,
                 tm.tm_mon + 1,
                 tm.tm_mday,
                 tm.tm_hour,
                 tm.tm_min,
                 tm.tm_sec);
        break;

    case 'T':
        if (request->sms.time == MSG_PARAM_UNDEFINED)
        break;
        octstr_format_append(result, "%ld", request->sms.time);
        break;

    case 'u':
        if(octstr_len(request->sms.udhdata)) {
        enc = octstr_duplicate(request->sms.udhdata);
        octstr_url_encode(enc);
        octstr_append(result, enc);
        octstr_destroy(enc);
        }
        break;

    case 'v':
        if (request->sms.validity != MSG_PARAM_UNDEFINED) {
            octstr_format_append(result, "%ld", (request->sms.validity - time(NULL)) / 60);
        }
        break;

    case 'V':
        if (request->sms.deferred != MSG_PARAM_UNDEFINED) {
            octstr_format_append(result, "%ld", (request->sms.deferred - time(NULL)) / 60);
        }
        break;
    
    /*
     * This allows to pass meta-data individual parameters into urls.
     * The syntax is as follows: %#group#parameter#
     * For example: %#smpp#my_param# would be replaced with the value
     * 'my_param' from the group 'smpp' coming inside the meta_data field.
     */
    case '#':
        /* ASCII 0x23 == '#' */
        k = octstr_search_char(pattern, 0x23, pos + 2);
        if (k >= 0) {
            pos += 2;
            meta_group = octstr_copy(pattern, pos, (k-pos));
            pos = k + 1;
            k = octstr_search_char(pattern, 0x23, pos);
            if (k >= 0) {
                meta_param = octstr_copy(pattern, pos, (k-pos));
                pos = k - 1;
                if (request->sms.meta_data != NULL) {
                    enc = meta_data_get_value(request->sms.meta_data,
                            octstr_get_cstr(meta_group), meta_param);
                    octstr_url_encode(enc);
                    octstr_append(result, enc);
                    octstr_destroy(enc);
                }
                octstr_destroy(meta_param);
            } else {
                pos++;
            }
            octstr_destroy(meta_group);
        }
        break;

    /* XXX sms.parameters not present in here:
     *   * pid - will we receive this ? 
     *   * alt-dcs - shouldn't be required unless we want to inform 
     *               which alt-dcs external server should use back
     *   * compress - if we use compression, probably kannel would 
     *                decompress and reset this to 0. not required
     *   * rpi - we don't receive these from smsc
     *   * username, password, dlr-url, account - nonsense to send
     */
    case '%':
        octstr_format_append(result, "%%");
        break;

    default:
        octstr_format_append(result, "%%%c",
                             octstr_get_char(pattern, pos + 1));
        break;
    }

    pos += 2;
    }
    
    gwlist_destroy(word_list, octstr_destroy_item);    

    return result;    
}
コード例 #3
0
ファイル: bearerbox.c プロジェクト: markjeee/mbuni
static int mm7http_receive(MmsBoxHTTPClientInfo *h)
{
     MmsMsg *m = NULL;
     List *mh = NULL;
     int hstatus = HTTP_OK;
     List *rh = http_create_empty_headers();
     Octstr *reply_body = NULL;
     
     List *to = NULL;
     Octstr *hto = NULL, *subject = NULL,  *msgid = NULL;
     Octstr *hfrom = NULL, *body, *rr_uri = NULL, *dlr_uri = NULL;
     time_t expiryt = -1, deliveryt = -1;
     Octstr *qf = NULL, *mmc_id = NULL, *qdir = NULL, *s;
     int msize;
     int dlr, rr;
     int mtype;
     List *cgivars_ctypes = NULL, *rqh = http_create_empty_headers();

     parse_cgivars(h->headers, h->body, &h->cgivars, &cgivars_ctypes);
     
     hfrom = http_cgi_variable(h->cgivars, "from");     
     hto =  http_cgi_variable(h->cgivars, "to");     
     body = http_cgi_variable(h->cgivars, "mms");

     msize = octstr_len(body);

     debug("mmsbox.mm7http.sendinterface", 0, 
	   " --> Enterred http-mmsc send interface, blen=[%d] <--- ", 
	   msize);
     
     if (hto == NULL) {
	  http_header_add(rh, "Content-Type", "text/plain"); 
	  hstatus = HTTP_BAD_REQUEST;
	  reply_body = octstr_format("Missing 'to' argument");
	  
	  goto done;

     } else if (hfrom == NULL) {
	  http_header_add(rh, "Content-Type", "text/plain"); 
	  hstatus = HTTP_BAD_REQUEST;
	  reply_body = octstr_format("Missing 'from' argument");
	  
	  goto done;
	  
     } else if (body == NULL ||  /* A message is required, and must parse */
		(m = mms_frombinary(body, hfrom ? hfrom : octstr_imm("anon@anon"))) == NULL) {
	  http_header_add(rh, "Content-Type", "text/plain"); 
	  hstatus = HTTP_BAD_REQUEST;
	  reply_body = octstr_format("Unexpected MMS message, no content?");
	  
	  goto done;
     }      


     to = octstr_split_words(hto);

     mtype = mms_messagetype(m);
     mh = mms_message_headers(m);

     /* find interesting headers. */
     subject = http_header_value(mh, octstr_imm("Subject"));

     /* Find expiry and delivery times */
     
     if ((s = http_header_value(mh, octstr_imm("X-Mms-Expiry"))) != NULL) {
	  expiryt = date_parse_http(s);
	  octstr_destroy(s);
     } else 
	  expiryt = time(NULL) +  DEFAULT_EXPIRE;
          
     if ((s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time"))) != NULL) {
	  deliveryt = date_parse_http(s);
	  octstr_destroy(s);
     } else 
	  deliveryt = 0;
     
     qdir = get_mmsbox_queue_dir(hfrom, to, h->m, &mmc_id); /* get routing info. */
     
     switch(mtype) {
	  Octstr *value, *value2;
     case MMS_MSGTYPE_SEND_REQ:
     case MMS_MSGTYPE_RETRIEVE_CONF:
       
	  /* Get/make a Message ID */
	  if ((msgid = mms_get_header_value(m, octstr_imm("Message-ID"))) == NULL) { /* Make a message id for it directly. We need it below. */
	       msgid = mms_make_msgid(NULL, NULL);
	       mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid));	       
	  }
	  
	  if ((value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"))) != NULL && 
	      octstr_case_compare(value, octstr_imm("Yes")) == 0) 
	       dlr = 1;
	  else 
	       dlr = 0;
	  octstr_destroy(value);

	  if ((value = http_header_value(mh, octstr_imm("X-Mms-Read-Report"))) != NULL && 
	      octstr_case_compare(value, octstr_imm("Yes")) == 0) 
	       rr = 1;
	  else 
	       rr = 0;
	  octstr_destroy(value);
	  
	  if (deliveryt < 0)
	       deliveryt = time(NULL);
	  
	  if (expiryt < 0)
	       expiryt = time(NULL) + DEFAULT_EXPIRE;
	  
	  mms_remove_headers(m, "Bcc");
	  mms_remove_headers(m, "X-Mms-Delivery-Time");
	  mms_remove_headers(m, "X-Mms-Expiry");
	  mms_remove_headers(m, "X-Mms-Sender-Visibility");
	  
	  MOD_SUBJECT(m, h->m, hfrom);
	  

	  if (qdir == outgoing_qdir) { /* We need to remember the old message ID so we can re-write it 
				   * if a DLR is relayed backwards. 			
				   */
	       Octstr *t = mms_maketransid(NULL, octstr_imm(MM_NAME)); /* make a fake transaction id  so dlr works*/

	       http_header_add(rqh, "X-Mbuni-TransactionID", octstr_get_cstr(t));
	       if (dlr)
		    dlr_uri = octstr_format("msgid:%S", msgid);
	       if (rr)
		    rr_uri  =  octstr_format("msgid:%S", msgid); 	       	 

	       octstr_destroy(t);
	  }

	  /* Save it,  put message id in header, return. */     
	  qf = qfs->mms_queue_add(hfrom, to, subject, 
				  h->m->id, mmc_id,
				  deliveryt, expiryt, m, NULL, 
				  NULL, NULL,
				  dlr_uri, rr_uri,
				  rqh,
				  dlr,
				  octstr_get_cstr(qdir),
				  "MM7/HTTP-IN",
				  NULL);
	  
	  if (qf) {
	       /* Log to access log */
	       mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL);
	       
	       hstatus = HTTP_OK;
	  } else 
	       hstatus = HTTP_INTERNAL_SERVER_ERROR;
	  break;
     case MMS_MSGTYPE_DELIVERY_IND:
	  msgid = mms_get_header_value(m, octstr_imm("Message-ID")); 
	  value = mms_get_header_value(m, octstr_imm("X-Mms-Status"));
	  value2 = mms_get_header_value(m, octstr_imm("X-Mbuni-Orig-Message-ID")); 
	  
	  rr_uri = mmsbox_get_report_info(m, h->m, mmc_id, "delivery-report", 
					  value, rqh, NULL, 0, msgid);
	  if (mmc_id == NULL && value2)
	       http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2));		    

	  qf = qfs->mms_queue_add(hfrom, to, NULL, 
				  h->m->id, mmc_id,
				  0, time(NULL) + default_msgexpiry, m, NULL, 
				  NULL, NULL,
				  rr_uri, NULL,
				  rqh,
				  0,
				  octstr_get_cstr(qdir), 				  
				  "MM7/HTTP-IN",
				  NULL);
	  if (qf)  {
	       /* Log to access log */
	       mms_log("DeliveryReport", hfrom, to, -1, msgid,value, h->m->id, "MMSBox", h->ua, NULL);
	       
	       hstatus = HTTP_OK;
	  }  else 
	       hstatus = HTTP_INTERNAL_SERVER_ERROR;
	  octstr_destroy(value);
	  octstr_destroy(value2);
	  break;
	  
     case MMS_MSGTYPE_READ_ORIG_IND:
	  msgid = mms_get_header_value(m, octstr_imm("Message-ID")); 
	  value = mms_get_header_value(m, octstr_imm("X-Mms-Read-Status"));
	  value2 = mms_get_header_value(m, octstr_imm("X-Mbuni-Orig-Message-ID")); 

	  rr_uri = mmsbox_get_report_info(m, h->m, mmc_id, "read-report", 
					  value, rqh, NULL, 0, msgid);
	  if (mmc_id == NULL && value2)
	       http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2));		    

	  qf = qfs->mms_queue_add(hfrom, to, NULL, 
				  h->m->id, mmc_id,
				  0, time(NULL) + default_msgexpiry, m, NULL, 
				  NULL, NULL,
				  rr_uri, NULL,
				  rqh,
				  0,
				  octstr_get_cstr(qdir), 				  
				  "MM7/HTTP-IN",
				  NULL);
	  if (qf)  {
	       /* Log to access log */
	       mms_log("Received RR", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL);		    
	       hstatus = HTTP_NO_CONTENT;
	  }  else 
	       hstatus = HTTP_INTERNAL_SERVER_ERROR;
	  octstr_destroy(value);
	  octstr_destroy(value2);
	  break;
     }
     
 done:
     
     http_header_add(rh, "X-Mbuni-Version", VERSION);
     
     http_send_reply(h->client, hstatus, rh, msgid ? msgid : (qf ? qf : octstr_imm("")));

     gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);

     octstr_destroy(subject);

     octstr_destroy(qf);
     octstr_destroy(mmc_id);
     octstr_destroy(msgid);
     
     http_destroy_headers(mh);
     http_destroy_headers(rh);
     http_destroy_headers(rqh);

     if (m) 
	  mms_destroy(m);      
     
     http_destroy_cgiargs(cgivars_ctypes);
     
     return http_status_class(hstatus) == HTTP_STATUS_SUCCESSFUL ? 0 : -1;
}
コード例 #4
0
ファイル: urltrans.c プロジェクト: armic/erpts
/*
 * Trans being NULL means that we are servicing ppg (doing dlr, but this does not
 * concern us here).
 */
Octstr *urltrans_get_pattern(URLTranslation *t, Msg *request)
{
    Octstr *enc;
    int nextarg, j;
    struct tm tm;
    int num_words;
    List *word_list;
    Octstr *result, *pattern;
    long pattern_len;
    long pos;
    int c;
    long i;
    Octstr *temp;
    Octstr *url, *reply; /* For and If delivery report */

    url = reply = NULL;
    
    if (request->sms.sms_type != report_mo && t->type == TRANSTYPE_SENDSMS)
        return octstr_create("");

    if (request->sms.msgdata) {
        word_list = octstr_split_words(request->sms.msgdata);
        num_words = list_len(word_list);
    } else {
    	word_list = list_create();
        num_words = 0;
    }

    result = octstr_create("");

    /* check if this is a delivery report message or not */
    if (request->sms.sms_type != report_mo) {
        pattern = t->pattern;
    } else {

        /* this is a DLR message */
        reply = octstr_duplicate(request->sms.msgdata);
        url = octstr_duplicate(request->sms.dlr_url);

        pattern = url;
        if (octstr_len(pattern) == 0) {
            if (t && octstr_len(t->dlr_url)) {
                pattern = t->dlr_url;
            } else {
                list_destroy(word_list, octstr_destroy_item);
                return octstr_create("");
            }
        }
    }

    pattern_len = octstr_len(pattern);
    nextarg = 1;
    pos = 0;
    for (;;) {
        while (pos < pattern_len) {
            c = octstr_get_char(pattern, pos);
            if (c == '%' && pos + 1 < pattern_len)
                break;
            octstr_append_char(result, c);
            ++pos;
        }

        if (pos == pattern_len)
            break;

    switch (octstr_get_char(pattern, pos + 1)) {
	case 'k':
	    if (num_words <= 0)
		break;
	    enc = octstr_duplicate(list_get(word_list, 0));
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 's':
	    if (nextarg >= num_words)
		break;
	    enc = octstr_duplicate(list_get(word_list, nextarg));
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    ++nextarg;
	    break;

	case 'S':
	    if (nextarg >= num_words)
		break;
	    temp = list_get(word_list, nextarg);
	    for (i = 0; i < octstr_len(temp); ++i) {
		if (octstr_get_char(temp, i) == '*')
		    octstr_append_char(result, '~');
		else
		    octstr_append_char(result, octstr_get_char(temp, i));
	    }
	    ++nextarg;
	    break;

	case 'r':
	    for (j = nextarg; j < num_words; ++j) {
		enc = octstr_duplicate(list_get(word_list, j));
		octstr_url_encode(enc);
		if (j != nextarg)
		    octstr_append_char(result, '+');
		octstr_append(result, enc);
		octstr_destroy(enc);
	    }
	    break;
    
	/* NOTE: the sender and receiver is already switched in
	 *    message, so that's why we must use 'sender' when
	 *    we want original receiver and vice versa
	 */
	case 'P':
	    enc = octstr_duplicate(request->sms.sender);
    	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 'p':
	    enc = octstr_duplicate(request->sms.receiver);
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 'Q':
	    if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) {
		enc = octstr_copy(request->sms.sender, 2, 
		    	    	  octstr_len(request->sms.sender));
		octstr_url_encode(enc);
		octstr_format_append(result, "%%2B%S", enc);
		octstr_destroy(enc);
	    } else {
		enc = octstr_duplicate(request->sms.sender);
    	    	octstr_url_encode(enc);
		octstr_append(result, enc);
		octstr_destroy(enc);
	    }
	    break;

	case 'q':
	    if (strncmp(octstr_get_cstr(request->sms.receiver),"00",2)==0) {
		enc = octstr_copy(request->sms.receiver, 2, 
		    	    	  octstr_len(request->sms.receiver));
		octstr_url_encode(enc);
		octstr_format_append(result, "%%2B%S", enc);
		octstr_destroy(enc);
	    } else {
		enc = octstr_duplicate(request->sms.receiver);
		octstr_url_encode(enc);
		octstr_append(result, enc);
		octstr_destroy(enc);
	    }
	    break;

	case 'a':
	    for (j = 0; j < num_words; ++j) {
		enc = octstr_duplicate(list_get(word_list, j));
		octstr_url_encode(enc);
		if (j > 0)
		    octstr_append_char(result, '+');
		octstr_append(result, enc);
		octstr_destroy(enc);
	    }
	    break;

	case 'b':
	    enc = octstr_duplicate(request->sms.msgdata);
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 't':
	    tm = gw_gmtime(request->sms.time);
	    octstr_format_append(result, "%04d-%02d-%02d+%02d:%02d:%02d",
				 tm.tm_year + 1900,
				 tm.tm_mon + 1,
				 tm.tm_mday,
				 tm.tm_hour,
				 tm.tm_min,
				 tm.tm_sec);
	    break;

	case 'T':
	    if (request->sms.time == MSG_PARAM_UNDEFINED)
		break;
	    octstr_format_append(result, "%ld", request->sms.time);
	    break;

	case 'i':
	    if (request->sms.smsc_id == NULL)
		break;
	    enc = octstr_duplicate(request->sms.smsc_id);
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 'I':
	    if (!uuid_is_null(request->sms.id)) {
                char id[UUID_STR_LEN + 1];
                uuid_unparse(request->sms.id, id);
	        octstr_append_cstr(result, id);
            }
	    break;

	case 'n':
	    if (request->sms.service == NULL)
		break;
	    enc = octstr_duplicate(request->sms.service);
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 'd':
	    enc = octstr_create("");
	    octstr_append_decimal(enc, request->sms.dlr_mask);
	    octstr_url_encode(enc);
	    octstr_append(result, enc);
	    octstr_destroy(enc);
	    break;

	case 'A':
	    if (reply) {
		enc = octstr_duplicate(reply);
		octstr_url_encode(enc);
		octstr_append(result, enc);
		octstr_destroy(enc);
	    }
	    break;

	case 'c':
	    octstr_append_decimal(result, request->sms.coding);
	    break;

	case 'C':
	    if(octstr_len(request->sms.charset)) {
		octstr_append(result, request->sms.charset);
	    } else {
		switch (request->sms.coding) {
		    case DC_UNDEF:
		    case DC_7BIT:
			octstr_append(result, octstr_imm("ISO-8859-1"));
			break;
		    case DC_8BIT:
			octstr_append(result, octstr_imm("8-BIT"));
			break;
		    case DC_UCS2:
			octstr_append(result, octstr_imm("UTF16-BE"));
			break;
		}
	    }
	    break;

	case 'u':
	    if(octstr_len(request->sms.udhdata)) {
		enc = octstr_duplicate(request->sms.udhdata);
		octstr_url_encode(enc);
		octstr_append(result, enc);
		octstr_destroy(enc);
	    }
	    break;

	case 'B':  /* billing identifier/information */
	    if (octstr_len(request->sms.binfo)) {
            enc = octstr_duplicate(request->sms.binfo);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;
	
    case 'o':  /* account information (may be operator id for aggregators */
	    if (octstr_len(request->sms.account)) {
            enc = octstr_duplicate(request->sms.account);
            octstr_url_encode(enc);
            octstr_append(result, enc);
            octstr_destroy(enc);
        }
        break;

	/* XXX sms.parameters not present in here:
	 *   * pid - will we receive this ? 
	 *   * mwi,mclass - will we receive these bits from smsc ?
	 *   * alt-dcs - shouldn't be required unless we want to inform 
	 *               which alt-dcs external server should use back
	 *   * compress - if we use compression, probably kannel would 
	 *                decompress and reset this to 0. not required
	 *   * validity, deferred, rpi - we don't receive these from smsc
	 *   * username, password, dlr-url, account - nonsense to send
	 */

	case '%':
	    octstr_format_append(result, "%%");
	    break;

	default:
	    octstr_format_append(result, "%%%c",
	    	    	    	 octstr_get_char(pattern, pos + 1));
	    break;
	}

	pos += 2;
    }
    /*
     * this SHOULD be done in smsbox, not here, but well,
     * much easier to do here
     */
    if (t && (t->type == TRANSTYPE_POST_URL || t->type == TRANSTYPE_POST_XML)
		    && t->strip_keyword)
	strip_keyword(request);

    octstr_destroy(url);
    octstr_destroy(reply);

    list_destroy(word_list, octstr_destroy_item);
    return result;
}