Index: gw/smsc/smsc_http.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_http.c,v
retrieving revision 1.61
diff -u -b -w -r1.61 smsc_http.c
--- gw/smsc/smsc_http.c	14 Jan 2009 11:11:46 -0000	1.61
+++ gw/smsc/smsc_http.c	28 May 2009 17:22:01 -0000
@@ -129,8 +129,33 @@
 
 #define DEFAULT_CHARSET "UTF-8"
 
+/*
+ * This maps fields to values for MO parameters
+ */
+typedef struct fieldmap {
+    Octstr *username;
+    Octstr *password;
+    Octstr *from;
+    Octstr *to;
+    Octstr *text;
+    Octstr *udh;
+    Octstr *account;
+    Octstr *binfo;
+    Octstr *dlr_mask;
+    Octstr *dlr_url;
+    Octstr *dlr_mid;
+    Octstr *flash;
+    Octstr *mclass;
+    Octstr *mwi;
+    Octstr *coding;
+    Octstr *validity;
+    Octstr *deferred;
+    Octstr *foreign_id;
+} FieldMap;
+
 typedef struct conndata {
     HTTPCaller *http_ref;
+    FieldMap *fieldmap;
     long receive_thread;
     long send_cb_thread;
     int shutdown;
@@ -165,6 +190,35 @@
 } ConnData;
 
 
+/*
+ * Destroys the FieldMap structure
+ */
+static void fieldmap_destroy(FieldMap *fieldmap)
+{
+    if (fieldmap == NULL)
+        return;
+    octstr_destroy(fieldmap->username);
+    octstr_destroy(fieldmap->password);
+    octstr_destroy(fieldmap->from);
+    octstr_destroy(fieldmap->to);
+    octstr_destroy(fieldmap->text);
+    octstr_destroy(fieldmap->udh);
+    octstr_destroy(fieldmap->account);
+    octstr_destroy(fieldmap->binfo);
+    octstr_destroy(fieldmap->dlr_mask);
+    octstr_destroy(fieldmap->dlr_url);
+    octstr_destroy(fieldmap->dlr_mid);
+    octstr_destroy(fieldmap->flash);
+    octstr_destroy(fieldmap->mclass);
+    octstr_destroy(fieldmap->mwi);
+    octstr_destroy(fieldmap->coding);
+    octstr_destroy(fieldmap->validity);
+    octstr_destroy(fieldmap->deferred);
+    octstr_destroy(fieldmap->foreign_id);
+    gw_free(fieldmap);
+}
+
+
 static void conndata_destroy(ConnData *conndata)
 {
     if (conndata == NULL)
@@ -177,6 +231,7 @@
         gw_regex_destroy(conndata->permfail_regex);
     if (conndata->tempfail_regex)
         gw_regex_destroy(conndata->tempfail_regex);
+    fieldmap_destroy(conndata->fieldmap);
     octstr_destroy(conndata->allow_ip);
     octstr_destroy(conndata->send_url);
     octstr_destroy(conndata->dlr_url);
@@ -1454,7 +1509,7 @@
 
 
 /*----------------------------------------------------------------
- * (Semi-)generic HTTP interface
+ * Generic HTTP interface
  *
  * This 'generic' type will handle the 'send-url' directive in the 
  * group the same way the 'sms-service' for smsbox does, via 
@@ -1462,12 +1517,6 @@
  * regex value that match against the reponse body. The HTTP reponse
  * code is not obeyed.
  * 
- * It handles mainly MT messages, due to the fact that MO traffic
- * can't be abstracted in a universal way. Therefor we use the
- * Kannel sendsms interface layout as generic fallback. So if your
- * SMSC provider needs to send MO messages, he needs to implement
- * the Kannel sendsms HTTP interface variables.
- * 
  * Example config group:
  * 
  *  group = smsc
@@ -1477,6 +1526,9 @@
  *  status-success-regex = "ok"
  *  status-permfail-regex = "failure"
  *  status-tempfail-regex = "retry later"
+ *  generic-param-from = "phoneNumber"
+ *  generic-param-to = "shortCode"
+ *  generic-param-text = "message"
  * 
  * Note that neither 'smsc-username' nor 'smsc-password' is required,
  * since they are coded into the the 'send-url' value directly. 
@@ -1484,6 +1536,221 @@
  * Stipe Tolj <st@tolj.org>
  */
 
+/*
+ * Get the FieldMap struct to map MO parameters
+ */
+static FieldMap *generic_get_field_map(CfgGroup *grp)
+{
+    FieldMap *fm = NULL;
+    fm = gw_malloc(sizeof(FieldMap));
+    gw_assert(fm != NULL);
+    fm->username = cfg_get(grp, octstr_imm("generic-param-username"));
+    if (fm->username == NULL)
+        fm->username = octstr_create("username");
+    fm->password = cfg_get(grp, octstr_imm("generic-param-password"));
+    if (fm->password == NULL)
+        fm->password = octstr_create("password");
+    fm->from = cfg_get(grp, octstr_imm("generic-param-from"));
+    if (fm->from == NULL)
+        fm->from = octstr_create("from");
+    fm->to = cfg_get(grp, octstr_imm("generic-param-to"));
+    if (fm->to == NULL)
+        fm->to = octstr_create("to");
+    fm->text = cfg_get(grp, octstr_imm("generic-param-text"));
+    if (fm->text == NULL)
+        fm->text = octstr_create("text");
+    fm->udh = cfg_get(grp, octstr_imm("generic-param-udh"));
+    if (fm->udh == NULL)
+        fm->udh = octstr_create("udh");
+    fm->account = cfg_get(grp, octstr_imm("generic-param-account"));
+    if (fm->account == NULL)
+        fm->account = octstr_create("account");
+    fm->binfo = cfg_get(grp, octstr_imm("generic-param-binfo"));
+    if (fm->binfo == NULL)
+        fm->binfo = octstr_create("binfo");
+    fm->dlr_mask = cfg_get(grp, octstr_imm("generic-param-dlr-mask"));
+    if (fm->dlr_mask == NULL)
+        fm->dlr_mask = octstr_create("dlr-mask");
+    fm->dlr_url = cfg_get(grp, octstr_imm("generic-param-dlr-url"));
+    if (fm->dlr_url == NULL)
+        fm->dlr_url = octstr_create("dlr-url");
+    fm->dlr_mid = cfg_get(grp, octstr_imm("generic-param-dlr-mid"));
+    if (fm->dlr_mid == NULL)
+        fm->dlr_mid = octstr_create("dlr-mid");
+    fm->flash = cfg_get(grp, octstr_imm("generic-param-flash"));
+    if (fm->flash == NULL)
+        fm->flash = octstr_create("flash");
+    fm->mclass = cfg_get(grp, octstr_imm("generic-param-mclass"));
+    if (fm->mclass == NULL)
+        fm->mclass = octstr_create("mclass");
+    fm->mwi = cfg_get(grp, octstr_imm("generic-param-mwi"));
+    if (fm->mwi == NULL)
+        fm->mwi = octstr_create("mwi");
+    fm->coding = cfg_get(grp, octstr_imm("generic-param-coding"));
+    if (fm->coding == NULL)
+        fm->coding = octstr_create("coding");
+    fm->validity = cfg_get(grp, octstr_imm("generic-param-validity"));
+    if (fm->validity == NULL)
+        fm->validity = octstr_create("validity");
+    fm->deferred = cfg_get(grp, octstr_imm("generic-param-deferred"));
+    if (fm->deferred == NULL)
+        fm->deferred = octstr_create("deferred");
+    fm->foreign_id = cfg_get(grp, octstr_imm("generic-param-foreign-id"));
+    if (fm->foreign_id == NULL)
+        fm->foreign_id = octstr_create("foreign-id");
+
+    return fm;
+}
+
+static void generic_receive_sms(SMSCConn *conn, HTTPClient *client,
+                               List *headers, Octstr *body, List *cgivars)
+{
+    ConnData *conndata = conn->data;
+    FieldMap *fm = conndata->fieldmap;
+    Octstr *user, *pass, *from, *to, *text, *udh, *account, *binfo;
+    Octstr *dlrurl, *dlrmid;
+    Octstr *tmp_string, *retmsg;
+    int	mclass, mwi, coding, validity, deferred, dlrmask;
+    List *reply_headers;
+    int ret;
+
+    mclass = mwi = coding = validity =
+        deferred = dlrmask = SMS_PARAM_UNDEFINED;
+
+    user = http_cgi_variable(cgivars, octstr_get_cstr(fm->username));
+    pass = http_cgi_variable(cgivars, octstr_get_cstr(fm->password));
+    from = http_cgi_variable(cgivars, octstr_get_cstr(fm->from));
+    to = http_cgi_variable(cgivars, octstr_get_cstr(fm->to));
+    text = http_cgi_variable(cgivars, octstr_get_cstr(fm->text));
+    udh = http_cgi_variable(cgivars, octstr_get_cstr(fm->udh));
+    account = http_cgi_variable(cgivars, octstr_get_cstr(fm->account));
+    binfo = http_cgi_variable(cgivars, octstr_get_cstr(fm->binfo));
+    dlrurl = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_url));
+    dlrmid = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mid));
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->flash));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
+    }
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mclass));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
+    }
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mwi));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
+    }
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->coding));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &coding);
+    }
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->validity));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &validity);
+    }
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->deferred));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &deferred);
+    }
+    tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mask));
+    if (tmp_string) {
+        sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
+    }
+    debug("smsc.http.kannel", 0, "HTTP[%s]: Received an HTTP request",
+          octstr_get_cstr(conn->id));
+
+    if ((conndata->username != NULL && conndata->password != NULL) &&
+        (user == NULL || pass == NULL ||
+        octstr_compare(user, conndata->username) != 0 ||
+        octstr_compare(pass, conndata->password) != 0)) {
+        error(0, "HTTP[%s]: Authorization failure",
+              octstr_get_cstr(conn->id));
+        retmsg = octstr_create("Authorization failed for sendsms");
+    }
+    else if (dlrurl != NULL && dlrmask != 0 && dlrmid != NULL) {
+        /* we got a DLR, and we don't require additional values */
+        Msg *dlrmsg;
+
+        dlrmsg = dlr_find(conn->id,
+            dlrmid, /* message id */
+            to, /* destination */
+            dlrmask);
+
+        if (dlrmsg != NULL) {
+            dlrmsg->sms.sms_type = report_mo;
+
+            debug("smsc.http.kannel", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
+                  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));
+
+            ret = bb_smscconn_receive(conn, dlrmsg);
+            if (ret == -1)
+                retmsg = octstr_create("Not accepted");
+            else
+                retmsg = octstr_create("Sent.");
+        } else {
+            error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
+                  "in it id<%s> dst<%s>, type<%d>",
+                  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
+                  octstr_get_cstr(to), dlrmask);
+            retmsg = octstr_create("Unknown DLR, not accepted");
+        }
+    }
+    else if (from == NULL || to == NULL || text == NULL) {
+
+        error(0, "HTTP[%s]: Insufficient args",
+              octstr_get_cstr(conn->id));
+        retmsg = octstr_create("Insufficient args, rejected");
+    }
+    else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
+        error(0, "HTTP[%s]: UDH field misformed, rejected",
+              octstr_get_cstr(conn->id));
+        retmsg = octstr_create("UDH field misformed, rejected");
+    }
+    else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
+        error(0, "HTTP[%s]: UDH field is too long, rejected",
+              octstr_get_cstr(conn->id));
+        retmsg = octstr_create("UDH field is too long, rejected");
+    }
+    else {
+        /* we got a normal MO SMS */
+        Msg *msg;
+        msg = msg_create(sms);
+
+        debug("smsc.http.kannel", 0, "HTTP[%s]: Constructing new SMS",
+              octstr_get_cstr(conn->id));
+
+        msg->sms.service = octstr_duplicate(user);
+        msg->sms.sender = octstr_duplicate(from);
+        msg->sms.receiver = octstr_duplicate(to);
+        msg->sms.msgdata = octstr_duplicate(text);
+        msg->sms.udhdata = octstr_duplicate(udh);
+
+        msg->sms.smsc_id = octstr_duplicate(conn->id);
+        msg->sms.time = time(NULL);
+        msg->sms.mclass = mclass;
+        msg->sms.mwi = mwi;
+        msg->sms.coding = coding;
+        msg->sms.validity = validity;
+        msg->sms.deferred = deferred;
+        msg->sms.account = octstr_duplicate(account);
+        msg->sms.binfo = octstr_duplicate(binfo);
+        ret = bb_smscconn_receive(conn, msg);
+        if (ret == -1)
+            retmsg = octstr_create("Not accepted");
+        else
+            retmsg = octstr_create("Sent.");
+    }
+
+    reply_headers = gwlist_create();
+    http_header_add(reply_headers, "Content-Type", "text/plain");
+    debug("smsc.http.kannel", 0, "HTTP[%s]: Sending reply",
+          octstr_get_cstr(conn->id));
+    http_send_reply(client, HTTP_ACCEPTED, reply_headers, retmsg);
+
+    octstr_destroy(retmsg);
+    http_destroy_headers(reply_headers);
+}
+
+
 static void generic_send_sms(SMSCConn *conn, Msg *sms)
 {
     ConnData *conndata = conn->data;
@@ -1635,6 +1902,7 @@
     cfg_get_bool(&conndata->no_sep, cfg, octstr_imm("no-sep"));
     conndata->proxy = cfg_get(cfg, octstr_imm("system-id"));
     conndata->alt_charset = cfg_get(cfg, octstr_imm("alt-charset"));
+    conndata->fieldmap = generic_get_field_map(cfg);
 
     if (conndata->send_url == NULL)
         panic(0, "HTTP[%s]: Sending not allowed. No 'send-url' specified.",
@@ -1693,7 +1961,7 @@
                   octstr_get_cstr(conn->id));
             goto error;
         }
-        conndata->receive_sms = kannel_receive_sms; /* emulate sendsms interface */
+        conndata->receive_sms = generic_receive_sms; /* emulate sendsms interface */
         conndata->send_sms = generic_send_sms;
         conndata->parse_reply = generic_parse_reply;
 
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.139
diff -u -b -w -r1.139 cfg.def
--- gwlib/cfg.def	6 May 2009 18:47:34 -0000	1.139
+++ gwlib/cfg.def	28 May 2009 17:22:01 -0000
@@ -386,6 +386,24 @@
     OCTSTR(max-sms-octets)
     OCTSTR(login-prompt)
     OCTSTR(password-prompt)
+    OCTSTR(generic-param-username)
+    OCTSTR(generic-param-password)
+    OCTSTR(generic-param-from)
+    OCTSTR(generic-param-to)
+    OCTSTR(generic-param-text)
+    OCTSTR(generic-param-udh)
+    OCTSTR(generic-param-account)
+    OCTSTR(generic-param-binfo)
+    OCTSTR(generic-param-dlr-mask)
+    OCTSTR(generic-param-dlr-url)
+    OCTSTR(generic-param-dlr-mid)
+    OCTSTR(generic-param-flash)
+    OCTSTR(generic-param-mclass)
+    OCTSTR(generic-param-mwi)
+    OCTSTR(generic-param-coding)
+    OCTSTR(generic-param-validity)
+    OCTSTR(generic-param-deferred)
+    OCTSTR(generic-param-foreign-id)
 )
 
 
