Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

smsc_cimd.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*****************************************************************************
00058 * smsc_cimd.c - Nokia SMS Center (CIMD 1.3).
00059 * Mikael Gueck for WapIT Ltd.
00060 */
00061 
00062 #include <errno.h>
00063 #include <string.h>
00064 #include <stdio.h>
00065 #include <unistd.h>
00066 #include <stdlib.h>
00067 #include <time.h>
00068 
00069 #include <sys/time.h>
00070 #include <sys/types.h>
00071 #include <sys/socket.h>
00072 
00073 #include "smsc.h"
00074 #include "smsc_p.h"
00075 #include "gwlib/gwlib.h"
00076 #include "alt_charsets.h"
00077 
00078 /******************************************************************************
00079 * Static functions
00080 */
00081 
00082 /* do the handshake baby */
00083 static int cimd_open_connection(SMSCenter *smsc);
00084 
00085 /* waits for an ACK message, returns the ACK command number or -1 for error */
00086 static int expect_acknowledge(SMSCenter *smsc, int *cmd, int *err);
00087 
00088 /* sends a general ACK */
00089 static int send_acknowledge(SMSCenter *smsc);
00090 
00091 /* Reconnect to a CIMD server, use an existing structure */
00092 static int connect_tcpip(SMSCenter *smsc);
00093 
00094 static int parse_cimd_to_iso88591(char *from, char *to, int length);
00095 
00096 static int parse_iso88591_to_cimd(
00097     char *from, char *to, int length, int alt_charset);
00098 
00099 /******************************************************************************
00100 * Open the connection and log in
00101 *
00102 * return 0 if ok, -1 on failure
00103 */
00104 static int cimd_open_connection(SMSCenter *smsc)
00105 {
00106 
00107     char *tmpbuff = NULL;
00108     int ret = 0;
00109 
00110     int cmd = 0, err = 0;
00111 
00112     /* allocate some spare space */
00113     tmpbuff = gw_malloc(10 * 1024);
00114     memset(tmpbuff, 0, 10*1024);
00115 
00116     /* connect */
00117     smsc->socket = tcpip_connect_to_server(smsc->cimd_hostname, smsc->cimd_port,
00118     NULL);
00119     /* XXX add interface_name if required */
00120 
00121     if (smsc->socket == -1)
00122         goto error;
00123 
00124     /* receive protocol string "CIMD rel 1.37\n" */
00125     for (;;) {
00126         ret = smscenter_read_into_buffer(smsc);
00127         if (strstr(smsc->buffer, "CIMD rel 1.37\n") != NULL)
00128             break;
00129         if (ret < 0) goto logout;
00130     }
00131 
00132     debug("bb.sms.cimd", 0, "got the server identification tag");
00133 
00134     smscenter_remove_from_buffer(smsc, smsc->buflen);
00135 
00136     /* send login string */
00137     sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%c",
00138             0x02,
00139             "01", 0x09,
00140             smsc->cimd_username, 0x09,
00141             smsc->cimd_password, 0x09,
00142             "11",
00143             0x03, 0x0A);
00144 
00145     ret = write_to_socket(smsc->socket, tmpbuff);
00146     if (ret < 0) goto logout;
00147 
00148     /* get an acknowledge message */
00149 
00150     smsc->cimd_last_spoke = 0;
00151 
00152     if (expect_acknowledge(smsc, &cmd, &err) < 1)
00153         goto logout;
00154 
00155     debug("bb.sms.cimd", 0, "logged in");
00156 
00157     gw_free(tmpbuff);
00158     return 0;
00159 
00160 logout:
00161     cimd_close(smsc);
00162 
00163 error:
00164     error(0, "cimd_open: could not open/handshake");
00165     gw_free(tmpbuff);
00166     return -1;
00167 }
00168 
00169 
00170 
00171 /******************************************************************************
00172 * Open the smscenter
00173 */
00174 SMSCenter *cimd_open(char *hostname, int port, char *username, char *password)
00175 {
00176 
00177     SMSCenter *smsc = NULL;
00178     int ret = 0;
00179 
00180     /* create a SMSCenter structure */
00181     smsc = smscenter_construct();
00182     if (smsc == NULL) goto error;
00183     smsc->type = SMSC_TYPE_CIMD;
00184     smsc->cimd_hostname = gw_strdup(hostname);
00185     smsc->hostname = gw_strdup(hostname); /* Needed by read_into_buffer() */
00186     smsc->cimd_port = port;
00187     smsc->cimd_username = gw_strdup(username);
00188     smsc->cimd_password = gw_strdup(password);
00189 
00190     ret = cimd_open_connection(smsc);
00191     if (ret < 0)
00192         goto error;
00193 
00194     sprintf(smsc->name, "CIMD:%s:%d:%s", smsc->cimd_hostname,
00195             smsc->cimd_port, smsc->cimd_username);
00196     return smsc;
00197 
00198 error:
00199     error(0, "cimd_open: could not open!");
00200     smscenter_destruct(smsc);
00201     return NULL;
00202 }
00203 
00204 
00205 /******************************************************************************
00206 * Re-open the connection and log in
00207 *
00208 * return -1 if failed
00209 */
00210 int cimd_reopen(SMSCenter *smsc)
00211 {
00212 
00213     cimd_close(smsc);
00214 
00215     if (cimd_open_connection(smsc) < 0) {
00216         error(0, "Failed to re-open the connection!");
00217         return -1;
00218     }
00219     return 0;
00220 }
00221 
00222 
00223 
00224 /******************************************************************************
00225 * Log out and close the socket
00226 *
00227 */
00228 int cimd_close(SMSCenter *smsc)
00229 {
00230 
00231     char *cbuff = NULL;
00232     int sum;
00233     int ret;
00234 
00235     if (smsc->socket == -1) {
00236         debug("bb.sms.cimd", 0, "Trying to close cimd while already closed!");
00237         return 0;
00238     }
00239     cbuff = gw_malloc(2 * 1024);
00240 
00241     sprintf(cbuff, "%c%s%c%s%c%c", 0x02, "02", 0x09, "11", 0x03, 0x0A);
00242 
00243     sum = write_to_socket(smsc->socket, cbuff);
00244     if (sum < 0) goto error;
00245 
00246     /* this time we don't block waiting for acknowledge */
00247     recv(smsc->socket, cbuff, 2*1024, 0);
00248 
00249     gw_free(cbuff);
00250 
00251     ret = close(smsc->socket);
00252     smsc->socket = -1;
00253     return ret;
00254 
00255 error:
00256     gw_free(cbuff);
00257     return -1;
00258 }
00259 
00260 
00261 /******************************************************************************
00262 * Check for MO messages, returns as in smsc_submit_smsmessage in smsc.h
00263 */
00264 int cimd_pending_smsmessage(SMSCenter *smsc)
00265 {
00266 
00267     char *tmpbuff = NULL, *newline = NULL;
00268     int ret = 0;
00269     time_t thetime = 0;
00270 
00271     /* check for input sanity */
00272     if (smsc == NULL)
00273         goto error;
00274 
00275     /* we can only query every 5 seconds */
00276     thetime = time(NULL);
00277     if ((smsc->cimd_last_spoke + 5) > thetime) goto no_messages;
00278     smsc->cimd_last_spoke = thetime;
00279 
00280     /* allocate some spare space */
00281     tmpbuff = gw_malloc(10 * 1024);
00282     memset(tmpbuff, 0, 10*1024);
00283 
00284     sprintf(tmpbuff, "%c%s%c%s%c%c",
00285             0x02,         /* stx */
00286             "05", 0x09,   /* request for message, tab */
00287             "11",         /* dummy chksum */
00288             0x03, 0x0A);  /* etx, lf */
00289 
00290     /* send the poll message to determine if we have messages in queue */
00291     ret = write_to_socket(smsc->socket, tmpbuff);
00292     if (ret < 0) {
00293         debug("bb.sms.cimd", 0, "sending poll message failed");
00294         goto error;
00295     }
00296     /* block while waiting for answer that dataset ends to a 0x0A */
00297     for (;;) {
00298 
00299         newline = memchr(smsc->buffer, 0x0A, smsc->buflen);
00300         if (newline != NULL) break;
00301 
00302         newline = memchr(smsc->buffer, 0x03, smsc->buflen);
00303         if (newline != NULL) break;
00304 
00305         ret = smscenter_read_into_buffer(smsc);
00306         if (ret <= 0) {
00307             debug("bb.sms.cimd", 0, "read_into_buffer failed!, ret=%d", ret);
00308             goto error;
00309         }
00310 
00311         usleep(500);
00312 
00313         /* Reconnect if no results in 30 seconds */
00314         if (time(NULL) > (thetime + 30)) {
00315 
00316             error(0, "timeout occurred, maybe the connection was broken?");
00317 
00318             /* Reconnect if neccessary, this catches most of them */
00319             /* XXX this is an ugly kludge, but then again,
00320                CIMD 1.3 is an ugly kludge. */
00321             connect_tcpip(smsc);
00322             goto no_messages;
00323 
00324         }
00325 
00326     }
00327 
00328     /* if we got an nck, cut the message out and return 0 */
00329     newline = memchr(smsc->buffer, 0x15, smsc->buflen);
00330     if (newline != NULL) {
00331         newline = memchr(smsc->buffer, 0x0A, smsc->buflen);
00332         if (newline == NULL)
00333             newline = memchr(smsc->buffer, 0x03, smsc->buflen);
00334         smscenter_remove_from_buffer(smsc, newline - smsc->buffer + 1);
00335         goto no_messages;
00336     }
00337 
00338     /* miracle of miracles, we got a message */
00339     gw_free(tmpbuff);
00340     return 1;
00341 
00342 no_messages:
00343     gw_free(tmpbuff);
00344     return 0;
00345 
00346 error:
00347 
00348     debug("bb.sms.cimd", 0, "smscenter_pending_smsmessage: returning error");
00349     gw_free(tmpbuff);
00350     return -1;
00351 }
00352 
00353 
00354 
00355 /******************************************************************************
00356 * Send a MT message, returns as in smsc_submit_smsmessage in smsc.h
00357 */
00358 int cimd_submit_msg(SMSCenter *smsc, Msg *msg)
00359 {
00360 
00361     char *tmpbuff = NULL, *tmptext = NULL;
00362     char msgtext[1024];
00363     int ret;
00364     int cmd = 0, err = 0;
00365 
00366     /* Fix these by implementing a could-not-send-because-
00367        protocol-does-not-allow in smsc.c or smsgateway.c */
00368     if (octstr_len(msg->sms.msgdata) + octstr_len(msg->sms.udhdata) < 1) {
00369     if (msg->sms.msgdata == NULL)
00370         msg->sms.msgdata = octstr_create("");
00371     octstr_append_from_hex(msg->sms.msgdata, "20");
00372     }
00373     if (octstr_len(msg->sms.sender) < 1) {
00374         warning(0, "cimd_submit_smsmessage: ignoring message with 0-length field");
00375         goto okay;  /* THIS IS NOT OKAY!!!! XXX */
00376     }
00377     if (octstr_len(msg->sms.receiver) < 1) {
00378         warning(0, "cimd_submit_smsmessage: ignoring message with 0-length field");
00379         goto okay;  /* THIS IS NOT OKAY!!!! XXX */
00380     }
00381 
00382     tmpbuff = gw_malloc(10 * 1024);
00383     tmptext = gw_malloc(10 * 1024);
00384 
00385     memset(tmpbuff, 0, 10*1024);
00386     memset(tmptext, 0, 10*1024);
00387     memset(msgtext, 0, sizeof(msgtext));
00388 
00389     if (octstr_len(msg->sms.udhdata)) {
00390         octstr_get_many_chars(msgtext, msg->sms.udhdata, 0, octstr_len(msg->sms.udhdata));
00391         octstr_get_many_chars(msgtext + octstr_len(msg->sms.udhdata),
00392                               msg->sms.msgdata, 0,
00393                               140 - octstr_len(msg->sms.udhdata));
00394     } else {
00395         octstr_get_many_chars(msgtext, msg->sms.msgdata, 0,
00396                               octstr_len(msg->sms.msgdata));
00397     }
00398 
00399     /* XXX parse_iso88591_to_cimd should use Octstr
00400      * directly, or get a char* and a length, instead of using NUL
00401      * terminated strings.
00402      */
00403     parse_iso88591_to_cimd(msgtext, tmptext, 10*1024, smsc->alt_charset);
00404 
00405     /* If messages has UDHs, add the magic number 31 to the right spot */
00406     sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c%c",
00407             0x02,
00408             "03", 0x09,
00409             octstr_get_cstr(msg->sms.receiver), 0x09,
00410             tmptext, 0x09,
00411             "", 0x09,
00412             "", 0x09,
00413             (octstr_len(msg->sms.udhdata)) ? "31" : "", 0x09,
00414             "11", 0x03, 0x0A);
00415 
00416     ret = write_to_socket(smsc->socket, tmpbuff);
00417     if (ret < 0) {
00418         debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: socket write error");
00419         goto error;
00420     }
00421 
00422     /* The Nokia SMSC MAY be configured to send delivery
00423        information, which we then will HAVE to acknowledge.
00424        Naturally the CIMD 1.3 protocol does not include any
00425        kind of negotiation mechanism. */
00426     ret = expect_acknowledge(smsc, &cmd, &err);
00427 
00428     if (ret >= 1) {
00429 
00430         if (cmd == 4) {
00431             send_acknowledge(smsc);
00432             goto okay;
00433         } else if (cmd == 3) {
00434             goto okay;
00435         }
00436 
00437     } else if (ret == 0) {
00438 
00439         if (cmd == 4) {
00440             send_acknowledge(smsc);
00441             goto okay;  /* FIXME XXX THIS IS BOGUS, FIX SMSGATEWAY.C */
00442             goto error;
00443         } else if (cmd == 3) {
00444             goto okay;  /* FIXME XXX THIS IS BOGUS, FIX SMSGATEWAY.C */
00445             goto error;
00446         } else {
00447             error(0, "Unexpected behaviour from the CIMD server");
00448             debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: acknowledge was <%i>", ret);
00449             debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: buffer==<%s>", smsc->buffer);
00450             goto error;
00451         }
00452 
00453     }
00454 
00455 okay:
00456     gw_free(tmpbuff);
00457     gw_free(tmptext);
00458     return 0;
00459 
00460 error:
00461     debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: returning error");
00462     gw_free(tmpbuff);
00463     gw_free(tmptext);
00464     return -1;
00465 
00466 }
00467 
00468 
00469 
00470 int cimd_receive_msg(SMSCenter *smsc, Msg **msg)
00471 {
00472 
00473     char *tmpbuff = NULL, *sender = NULL;
00474     char *receiver = NULL, *text = NULL, *scts = NULL;
00475     char *tmpchar = NULL;
00476 
00477     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: starting");
00478 
00479     /* the PENDING function has previously requested for
00480        the message and checked that it safely found its 
00481        way into the memory buffer (smsc->buffer) */
00482 
00483     /* we want to temporarily store some data */
00484     tmpbuff = gw_malloc(10 * 1024);
00485     sender = gw_malloc(10 * 1024);
00486     receiver = gw_malloc(10 * 1024);
00487     text = gw_malloc(10 * 1024);
00488     scts = gw_malloc(10 * 1024);
00489 
00490     memset(tmpbuff, 0, 10 * 1024);
00491     memset(sender, 0, 10 * 1024);
00492     memset(receiver, 0, 10 * 1024);
00493     memset(text, 0, 10 * 1024);
00494     memset(scts, 0, 10 * 1024);
00495 
00496     /* cut the raw message out from the message buffer */
00497     tmpchar = memchr(smsc->buffer, 0x0A, smsc->buflen);
00498     if (tmpchar == NULL) {
00499         tmpchar = memchr(smsc->buffer, 0x03, smsc->buflen);
00500         if (tmpchar == NULL) goto error;
00501     }
00502 
00503     strncpy(tmpbuff, smsc->buffer, tmpchar - smsc->buffer);
00504     smscenter_remove_from_buffer(smsc, tmpchar - smsc->buffer + 1);
00505 
00506     /* Parse the raw message */
00507     sscanf(tmpbuff,
00508            "\x02\x06\tC:05\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t11\x03\x0A",
00509            receiver, sender, text, scts);
00510 
00511     sscanf(tmpbuff,
00512            "\x02\x06\tC:05\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t11\x03",
00513            receiver, sender, text, scts);
00514 
00515     /* Translate from the CIMD character set to iso8859-1 */
00516     parse_cimd_to_iso88591(text, tmpbuff, 10*1024);
00517     strncpy(text, tmpbuff, 480);
00518 
00519     /* create a smsmessage structure out of the components */
00520     *msg = msg_create(sms);
00521     if (*msg == NULL) return -1;
00522     (*msg)->sms.sender = octstr_create(sender);
00523     (*msg)->sms.receiver = octstr_create(receiver);
00524     (*msg)->sms.msgdata = octstr_create(text);
00525 
00526     /* Send acknowledge */
00527     send_acknowledge(smsc);
00528 
00529     /* We got a message so we can instantly check for a new one. */
00530     smsc->cimd_last_spoke -= 5;
00531 
00532     /* Free and Finish */
00533 
00534     gw_free(tmpbuff);
00535     gw_free(sender);
00536     gw_free(receiver);
00537     gw_free(text);
00538     gw_free(scts);
00539 
00540     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: return ok");
00541 
00542     return 1;
00543 
00544 error:
00545     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: failed");
00546     gw_free(tmpbuff);
00547     gw_free(sender);
00548     gw_free(receiver);
00549     gw_free(text);
00550     gw_free(scts);
00551 
00552     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: return failed");
00553 
00554     return -1;
00555 }
00556 
00557 /******************************************************************************
00558 * In(f)ternal Functions
00559 */
00560 
00561 static int connect_tcpip(SMSCenter *smsc)
00562 {
00563 
00564     char *tmpbuff = NULL;
00565     int ret = 0;
00566     int cmd = 0, err = 0;
00567 
00568     debug("bb.sms.cimd", 0, "reconnecting to <%s>", smsc->name);
00569 
00570     /* allocate some spare space */
00571     tmpbuff = gw_malloc(10 * 1024);
00572     memset(tmpbuff, 0, 10*1024);
00573 
00574     /* Close connection */
00575     close(smsc->socket);
00576 
00577     smsc->socket = -1;
00578 
00579     /* Be sure to open a socket. */
00580     for (;;) {
00581         smsc->socket = tcpip_connect_to_server(
00582                            smsc->cimd_hostname, smsc->cimd_port,
00583                NULL);
00584         /* XXX add interface_name if required */
00585 
00586         if (smsc->socket != -1) break;
00587 
00588         usleep(1000);
00589     }
00590 
00591     /* Empty the buffer, there might be an evil ghost inside... */
00592 
00593     memset(smsc->buffer, 0, smsc->bufsize);
00594     smsc->buflen = 0;
00595 
00596     /* Expect the protocol string "CIMD rel 1.37\n" */
00597     for (;;) {
00598         ret = smscenter_read_into_buffer(smsc);
00599         if (ret < 0) goto logout;
00600         if (strstr(smsc->buffer, "CIMD rel 1.37\n") != NULL)
00601             break;
00602         usleep(1000);
00603     }
00604     smscenter_remove_from_buffer(smsc, smsc->buflen);
00605 
00606     /* send login string */
00607     sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%c",
00608             0x02,
00609             "01", 0x09,
00610             smsc->cimd_username, 0x09,
00611             smsc->cimd_password, 0x09,
00612             "11",
00613             0x03, 0x0A);
00614 
00615     ret = write_to_socket(smsc->socket, tmpbuff);
00616     if (ret < 0) goto logout;
00617 
00618     /* get an acknowledge message */
00619 
00620     smsc->cimd_last_spoke = 0;
00621 
00622     if (expect_acknowledge(smsc, &cmd, &err) < 1)
00623         goto logout;
00624 
00625     debug("bb.sms.cimd", 0, "cimd_connect_tcpip: logged in");
00626 
00627     gw_free(tmpbuff);
00628 
00629     return 1;
00630 
00631 logout:
00632     close(smsc->socket);
00633     gw_free(tmpbuff);
00634     return 0;
00635 }
00636 
00637 /******************************************************************************
00638 * Yeah, we got the message!
00639 */
00640 static int send_acknowledge(SMSCenter *smsc)
00641 {
00642 
00643     char tmpbuff[100];
00644     int tmpint;
00645 
00646     if (tmpbuff == NULL) {
00647         error(0, "cimd_send_acknowledge: memory allocation failure");
00648         goto error;
00649     }
00650 
00651     memset(tmpbuff, 0, sizeof(tmpbuff));
00652 
00653     sprintf(tmpbuff, "\2\6\t11\3\n");
00654 
00655     tmpint = write_to_socket(smsc->socket, tmpbuff);
00656     if (tmpint == -1) {
00657         error(0, "cimd_send_acknowledge: connection failure");
00658         goto error;
00659     }
00660 
00661     return 0;
00662 
00663 error:
00664     debug("bb.sms.cimd", 0, "cimd_send_acknowledge: failed");
00665     return -1;
00666 }
00667 
00668 /******************************************************************************
00669 * Wait for the Nokia piece of *!%&%*^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H SMSC
00670 * to catch up with our swift operation, block until... (~1sec?)
00671 */
00672 static int expect_acknowledge(SMSCenter *smsc, int *cmd, int *err)
00673 {
00674 
00675     char *end_of_dataset = NULL;
00676     char *ack = NULL, *nck = NULL;
00677     char *cmdspecifier = NULL, *errorspecifier = NULL;
00678     int ret = 0;
00679 
00680 #if 0
00681     time_t thetime;
00682     time(&thetime);
00683 #endif
00684 
00685     if (smsc == NULL) goto error;
00686 
00687     /* Loop until we get an acknowledgement message. */
00688     for (;;) {
00689 
00690         /* If the server is configured in to end a dataset with a \n */
00691         end_of_dataset = memchr(smsc->buffer, '\n', smsc->buflen);
00692         if (end_of_dataset != NULL) break;
00693 
00694         /* If the server is configured in to end a dataset with a \3 */
00695         end_of_dataset = memchr(smsc->buffer, 0x03, smsc->buflen);
00696         if (end_of_dataset != NULL) break;
00697 
00698         ret = smscenter_read_into_buffer(smsc);
00699         if (ret <= 0) {
00700             if (errno == EAGAIN) continue;
00701             if (errno == EINTR) continue;
00702             return -1;
00703         }
00704 
00705         usleep(500);
00706 
00707 #if 0
00708         /* Abort if no results in 30 seconds */
00709 
00710         if (time(NULL) > (thetime + 30)) {
00711 
00712             error(0, "timeout occurred, maybe the connection was broken?");
00713             if (errno == EPIPE) {
00714                 error(0, "broken pipe");
00715             } /* if errno */
00716 
00717             goto error;
00718 
00719         } /* if time */
00720 #endif
00721     }
00722 
00723     /* Check if our request was answered or denied */
00724     ack = memchr(smsc->buffer, 0x06, end_of_dataset - smsc->buffer);
00725     nck = memchr(smsc->buffer, 0x15, end_of_dataset - smsc->buffer);
00726 
00727     /* Get the command code from the acknowledge message */
00728     cmdspecifier = strstr(smsc->buffer, "\tC:");
00729     if (cmdspecifier != NULL)
00730         *cmd = strtol(cmdspecifier + 3, NULL, 10);
00731     else
00732         *cmd = 0;
00733 
00734     errorspecifier = strstr(smsc->buffer, "\tE:");
00735     if (errorspecifier != NULL)
00736         *err = strtol(errorspecifier + 3, NULL, 10);
00737     else
00738         *err = 0;
00739 
00740     debug("bb.sms.cimd", 0, "cimd_pending_smsmessage: smsc->buffer == <%s>", smsc->buffer);
00741 
00742     /* Remove the acknowledge message from the incoming buffer. */
00743     smscenter_remove_from_buffer(smsc, end_of_dataset - smsc->buffer + 1);
00744 
00745     /* if we got an acknowledge */
00746     if (ack != NULL) {
00747         info(0, "cimd_pending_smsmessage: got ACK");
00748         return 1;
00749     }
00750 
00751     /* if we got an NOT acknowledge */
00752     if (nck != NULL) {
00753         info(0, "cimd_pending_smsmessage: got NCK");
00754         return 0;
00755     }
00756 
00757     /* if we got an ERROR */
00758 error:
00759     error(0, "cimd_expect_acknowledge failed");
00760     return -1;
00761 
00762 }
00763 
00764 /******************************************************************************
00765 * Convert a string from ISO-8859-1 to the CIMD character set
00766 */
00767 static int parse_iso88591_to_cimd(char* from, char* to,
00768         int length, int alt_charset)
00769 {
00770 
00771     char *temp = to;
00772 
00773     if (from == NULL || to == NULL || length == 0)
00774         return -1;
00775 
00776     *to = '\0';
00777 
00778     while ((*from != '\0') && ((int) strlen(temp) < (length - 2))) {
00779 
00780         switch (*from) {
00781 
00782         case '@': strcat(to, "_Oa"); to += 3; break;
00783         case '£': strcat(to, "_L-"); to += 3; break;
00784 
00785         case '$':
00786             if (alt_charset == CIMD_PLAIN_DOLLAR_SIGN) {
00787                 strcat(to, "$");
00788                 to++;
00789             } else {
00790                 strcat(to, "_$ ");
00791                 to += 3;
00792             }
00793             break;
00794 
00795         case 'Å': strcat(to, "_A*"); to += 3; break;
00796         case 'å': strcat(to, "_a*"); to += 3; break;
00797         case 'ä': strcat(to, "_a\""); to += 3; break;
00798         case 'ö': strcat(to, "_o\""); to += 3; break;
00799         case 'Ä': strcat(to, "_A\""); to += 3; break;
00800         case 'Ö': strcat(to, "_O\""); to += 3; break;
00801         case '¥': strcat(to, "_Y-"); to += 3; break;
00802         case 'è': strcat(to, "_e`"); to += 3; break;
00803         case 'é': strcat(to, "_e´"); to += 3; break;
00804         case 'ù': strcat(to, "_u`"); to += 3; break;
00805         case 'ì': strcat(to, "_i`"); to += 3; break;
00806         case 'ò': strcat(to, "_o`"); to += 3; break;
00807         case 'Ç': strcat(to, "_C,"); to += 3; break;
00808         case 'Ø': strcat(to, "_O/"); to += 3; break;
00809         case 'ø': strcat(to, "_o/"); to += 3; break;
00810         case 'Æ': strcat(to, "_AE"); to += 3; break;
00811         case 'æ': strcat(to, "_ae"); to += 3; break;
00812         case 'ß': strcat(to, "_ss"); to += 3; break;
00813         case 'É': strcat(to, "_E´"); to += 3; break;
00814         case '¿': strcat(to, "_??"); to += 3; break;
00815         case 'Ü': strcat(to, "_U\""); to += 3; break;
00816         case 'ñ': strcat(to, "_n~"); to += 3; break;
00817         case 'ü': strcat(to, "_u\""); to += 3; break;
00818         case 'à': strcat(to, "_a`"); to += 3; break;
00819         case '¡': strcat(to, "_!!"); to += 3; break;
00820         case '_': strcat(to, "_--"); to += 3; break;
00821         case 'Ñ': strcat(to, "_N~"); to += 3; break;
00822         case '!': strcat(to, "!"); to++; break;
00823         case '"': strcat(to, "\""); to++; break;
00824         case '#': strcat(to, "#"); to++; break;
00825         case '¤': strcat(to, "¤"); to++; break;
00826         case '%': strcat(to, "%"); to++; break;
00827         case '&': strcat(to, "&"); to++; break;
00828         case '\'': strcat(to, "'"); to++; break;
00829         case '(': strcat(to, "("); to++; break;
00830         case ')': strcat(to, ")"); to++; break;
00831         case '*': strcat(to, "*"); to++; break;
00832         case '+': strcat(to, "+"); to++; break;
00833         case ',': strcat(to, ","); to++; break;
00834         case '-': strcat(to, "-"); to++; break;
00835         case '.': strcat(to, "."); to++; break;
00836         case '/': strcat(to, "/"); to++; break;
00837         case '0': strcat(to, "0"); to++; break;
00838         case '1': strcat(to, "1"); to++; break;
00839         case '2': strcat(to, "2"); to++; break;
00840         case '3': strcat(to, "3"); to++; break;
00841         case '4': strcat(to, "4"); to++; break;
00842         case '5': strcat(to, "5"); to++; break;
00843         case '6': strcat(to, "6"); to++; break;
00844         case '7': strcat(to, "7"); to++; break;
00845         case '8': strcat(to, "8"); to++; break;
00846         case '9': strcat(to, "9"); to++; break;
00847         case ':': strcat(to, ":"); to++; break;
00848         case ';': strcat(to, ";"); to++; break;
00849         case '<': strcat(to, "<"); to++; break;
00850         case '=': strcat(to, "="); to++; break;
00851         case '>': strcat(to, ">"); to++; break;
00852         case '?': strcat(to, "?"); to++; break;
00853         case 'A': strcat(to, "A"); to++; break;
00854         case 'B': strcat(to, "B"); to++; break;
00855         case 'C': strcat(to, "C"); to++; break;
00856         case 'D': strcat(to, "D"); to++; break;
00857         case 'E': strcat(to, "E"); to++; break;
00858         case 'F': strcat(to, "F"); to++; break;
00859         case 'G': strcat(to, "G"); to++; break;
00860         case 'H': strcat(to, "H"); to++; break;
00861         case 'I': strcat(to, "I"); to++; break;
00862         case 'J': strcat(to, "J"); to++; break;
00863         case 'K': strcat(to, "K"); to++; break;
00864         case 'L': strcat(to, "L"); to++; break;
00865         case 'M': strcat(to, "M"); to++; break;
00866         case 'N': strcat(to, "N"); to++; break;
00867         case 'O': strcat(to, "O"); to++; break;
00868         case 'P': strcat(to, "P"); to++; break;
00869         case 'Q': strcat(to, "Q"); to++; break;
00870         case 'R': strcat(to, "R"); to++; break;
00871         case 'S': strcat(to, "S"); to++; break;
00872         case 'T': strcat(to, "T"); to++; break;
00873         case 'U': strcat(to, "U"); to++; break;
00874         case 'V': strcat(to, "V"); to++; break;
00875         case 'W': strcat(to, "W"); to++; break;
00876         case 'X': strcat(to, "X"); to++; break;
00877         case 'Y': strcat(to, "Y"); to++; break;
00878         case 'Z': strcat(to, "Z"); to++; break;
00879         case 'a': strcat(to, "a"); to++; break;
00880         case 'b': strcat(to, "b"); to++; break;
00881         case 'c': strcat(to, "c"); to++; break;
00882         case 'd': strcat(to, "d"); to++; break;
00883         case 'e': strcat(to, "e"); to++; break;
00884         case 'f': strcat(to, "f"); to++; break;
00885         case 'g': strcat(to, "g"); to++; break;
00886         case 'h': strcat(to, "h"); to++; break;
00887         case 'i': strcat(to, "i"); to++; break;
00888         case 'j': strcat(to, "j"); to++; break;
00889         case 'k': strcat(to, "k"); to++; break;
00890         case 'l': strcat(to, "l"); to++; break;
00891         case 'm': strcat(to, "m"); to++; break;
00892         case 'n': strcat(to, "n"); to++; break;
00893         case 'o': strcat(to, "o"); to++; break;
00894         case 'p': strcat(to, "p"); to++; break;
00895         case 'q': strcat(to, "q"); to++; break;
00896         case 'r': strcat(to, "r"); to++; break;
00897         case 's': strcat(to, "s"); to++; break;
00898         case 't': strcat(to, "t"); to++; break;
00899         case 'u': strcat(to, "u"); to++; break;
00900         case 'v': strcat(to, "v"); to++; break;
00901         case 'w': strcat(to, "w"); to++; break;
00902         case 'x': strcat(to, "x"); to++; break;
00903         case 'y': strcat(to, "y"); to++; break;
00904         case 'z': strcat(to, "z"); to++; break;
00905         case ' ': strcat(to, " "); to++; break;
00906         case '\r': strcat(to, "\r"); to++; break;
00907         case '\n': strcat(to, "\n"); to++; break;
00908 
00909         default: strcat(to, "_??"); to += 3; break;
00910         }
00911         from++;
00912     }
00913 
00914     *to = '\0';
00915 
00916     return strlen(temp);
00917 }
00918 
00919 
00920 /******************************************************************************
00921 * Convert a string from the CIMD character set to ISO-8859-1
00922 */
00923 static int parse_cimd_to_iso88591(char* from, char* to, int length)
00924 {
00925 
00926     int my_int, temp_int;
00927 
00928     *to = '\0';
00929 
00930     for (my_int = 0; my_int < (int)strlen(from) && (int)strlen(to) < length; ) {
00931 
00932         if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == '"') {
00933             strcat(to, "ä");
00934             my_int += 3;
00935         } else if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == '*') {
00936             strcat(to, "å");
00937             my_int += 3;
00938         }
00939 
00940         /* argh, this drives me nu---uuutts */
00941 
00942         else if (from[my_int] == '@') {
00943             strcat(to, "@");
00944             my_int ++;
00945         }
00946         else if (from[my_int] == '_' && from[my_int + 1] == 'O' && from[my_int + 2] == 'a') {
00947             strcat(to, "@");
00948             my_int += 3;
00949         } else if (from[my_int] == '_' && from[my_int + 1] == 'L' && from[my_int + 2] == '-') {
00950             strcat(to, "£");
00951             my_int += 3;
00952         }
00953 
00954         /* this following one is against specifications but what to do
00955          * when it works?!? (the other is NOT used) rpr 1.10. */
00956 
00957         else if (from[my_int] == '$') {
00958             strcat(to, "$");
00959             my_int ++;
00960         }
00961         else if (from[my_int] == '_' && from[my_int + 1] == '$' && from[my_int + 2] == ' ') {
00962             strcat(to, "$");
00963             my_int += 3;
00964         }
00965         else if (from[my_int] == '_' && from[my_int + 1] == 'A' && from[my_int + 2] == '*') {
00966             strcat(to, "Å");
00967             my_int += 3;
00968         } else if (from[my_int] == '_' && from[my_int + 1] == 'o' && from[my_int + 2] == '"') {
00969             strcat(to, "ö");
00970             my_int += 3;
00971         } else if (from[my_int] == '_' && from[my_int + 1] == 'A' && from[my_int + 2] == '"') {
00972             strcat(to, "Ä");
00973             my_int += 3;
00974         } else if (from[my_int] == '_' && from[my_int + 1] == 'O' && from[my_int + 2] == '"') {
00975             strcat(to, "Ö");
00976             my_int += 3;
00977         } else if (from[my_int] == '_' && from[my_int + 1] == 'Y' && from[my_int + 2] == '-') {
00978             strcat(to, "¥");
00979             my_int += 3;
00980         } else if (from[my_int] == '_' && from[my_int + 1] == 'e' && from[my_int + 2] == '`') {
00981             strcat(to, "è");
00982             my_int += 3;
00983         } else if (from[my_int] == '_' && from[my_int + 1] == 'e' && from[my_int + 2] == '´') {
00984             strcat(to, "é");
00985             my_int += 3;
00986         } else if (from[my_int] == '_' && from[my_int + 1] == 'u' && from[my_int + 2] == '`') {
00987             strcat(to, "ù");
00988             my_int += 3;
00989         } else if (from[my_int] == '_' && from[my_int + 1] == 'i' && from[my_int + 2] == '`') {
00990             strcat(to, "ì");
00991             my_int += 3;
00992         } else if (from[my_int] == '_' && from[my_int + 1] == 'o' && from[my_int + 2] == '`') {
00993             strcat(to, "ò");
00994             my_int += 3;
00995         } else if (from[my_int] == '_' && from[my_int + 1] == 'C' && from[my_int + 2] == ',') {
00996             strcat(to, "Ç");
00997             my_int += 3;
00998         } else if (from[my_int] == '_' && from[my_int + 1] == 'O' && from[my_int + 2] == '/') {
00999             strcat(to, "Ø");
01000             my_int += 3;
01001         } else if (from[my_int] == '_' && from[my_int + 1] == 'o' && from[my_int + 2] == '/') {
01002             strcat(to, "ø");
01003             my_int += 3;
01004         } else if (from[my_int] == '_' && from[my_int + 1] == 'A' && from[my_int + 2] == 'E') {
01005             strcat(to, "Æ");
01006             my_int += 3;
01007         } else if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == 'e') {
01008             strcat(to, "æ");
01009             my_int += 3;
01010         } else if (from[my_int] == '_' && from[my_int + 1] == 's' && from[my_int + 2] == 's') {
01011             strcat(to, "ß");
01012             my_int += 3;
01013         } else if (from[my_int] == '_' && from[my_int + 1] == 'E' && from[my_int + 2] == '´') {
01014             strcat(to, "É");
01015             my_int += 3;
01016         } else if (from[my_int] == '_' && from[my_int + 1] == '?' && from[my_int + 2] == '?') {
01017             strcat(to, "¿");
01018             my_int += 3;
01019         } else if (from[my_int] == '_' && from[my_int + 1] == 'U' && from[my_int + 2] == '"') {
01020             strcat(to, "Ü");
01021             my_int += 3;
01022         } else if (from[my_int] == '_' && from[my_int + 1] == 'n' && from[my_int + 2] == '~' ) {
01023             strcat(to, "ñ");
01024             my_int += 3;
01025         } else if (from[my_int] == '_' && from[my_int + 1] == 'u' && from[my_int + 2] == '"') {
01026             strcat(to, "ü");
01027             my_int += 3;
01028         } else if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == '`') {
01029             strcat(to, "à");
01030             my_int += 3;
01031         } else if (from[my_int] == '_' && from[my_int + 1] == '!' && from[my_int + 2] == '!') {
01032             strcat(to, "¡");
01033             my_int += 3;
01034         } else if (from[my_int] == '_' && from[my_int + 1] == '-' && from[my_int + 2] == '-') {
01035             strcat(to, "_");
01036             my_int += 3;
01037         } else if (from[my_int] == '_' && from[my_int + 1] == 'N' && from[my_int + 2] == '~') {
01038             strcat(to, "_");
01039             my_int += 3;
01040         }
01041 
01042         /* I just LOVE the designers of this protocol -mg */
01043         else if (from[my_int] == ']') {
01044             strcat(to, "Å");
01045             my_int++;
01046         } else if (from[my_int] == '}') {
01047             strcat(to, "å");
01048             my_int++;
01049         } else if (from[my_int] == '[') {
01050             strcat(to, "Ä");
01051             my_int++;
01052         } else if (from[my_int] == '{') {
01053             strcat(to, "ä");
01054             my_int++;
01055         } else if (from[my_int] == '\\') {
01056             strcat(to, "Ö");
01057             my_int++;
01058         } else if (from[my_int] == '|') {
01059             strcat(to, "ö");
01060             my_int++;
01061         }
01062         else if (from[my_int] == '!') {
01063             strcat(to, "!");
01064             my_int++;
01065         } else if (from[my_int] == '"') {
01066             strcat(to, "\"");
01067             my_int++;
01068         } else if (from[my_int] == '#') {
01069             strcat(to, "#");
01070             my_int++;
01071         } else if (from[my_int] == '¤') {
01072             strcat(to, "¤");
01073             my_int++;
01074         } else if (from[my_int] == '%') {
01075             strcat(to, "%");
01076             my_int++;
01077         } else if (from[my_int] == '&') {
01078             strcat(to, "&");
01079             my_int++;
01080         } else if (from[my_int] == '\'') {
01081             strcat(to, "'");
01082             my_int++;
01083         } else if (from[my_int] == '(') {
01084             strcat(to, "(");
01085             my_int++;
01086         } else if (from[my_int] == ')') {
01087             strcat(to, ")");
01088             my_int++;
01089         } else if (from[my_int] == '*') {
01090             strcat(to, "*");
01091             my_int++;
01092         } else if (from[my_int] == '+') {
01093             strcat(to, "+");
01094             my_int++;
01095         } else if (from[my_int] == ',') {
01096             strcat(to, ",");
01097             my_int++;
01098         } else if (from[my_int] == '-') {
01099             strcat(to, "-");
01100             my_int++;
01101         } else if (from[my_int] == '.') {
01102             strcat(to, ".");
01103             my_int++;
01104         } else if (from[my_int] == '/') {
01105             strcat(to, "/");
01106             my_int++;
01107         } else if (from[my_int] == '0') {
01108             strcat(to, "0");
01109             my_int++;
01110         } else if (from[my_int] == '1') {
01111             strcat(to, "1");
01112             my_int++;
01113         } else if (from[my_int] == '2') {
01114             strcat(to, "2");
01115             my_int++;
01116         } else if (from[my_int] == '3') {
01117             strcat(to, "3");
01118             my_int++;
01119         } else if (from[my_int] == '4') {
01120             strcat(to, "4");
01121             my_int++;
01122         } else if (from[my_int] == '5') {
01123             strcat(to, "5");
01124             my_int++;
01125         } else if (from[my_int] == '6') {
01126             strcat(to, "6");
01127             my_int++;
01128         } else if (from[my_int] == '7') {
01129             strcat(to, "7");
01130             my_int++;
01131         } else if (from[my_int] == '8') {
01132             strcat(to, "8");
01133             my_int++;
01134         } else if (from[my_int] == '9') {
01135             strcat(to, "9");
01136             my_int++;
01137         } else if (from[my_int] == ':') {
01138             strcat(to, ":");
01139             my_int++;
01140         } else if (from[my_int] == ';') {
01141             strcat(to, ";");
01142             my_int++;
01143         } else if (from[my_int] == '<') {
01144             strcat(to, "<");
01145             my_int++;
01146         } else if (from[my_int] == '=') {
01147             strcat(to, "=");
01148             my_int++;
01149         } else if (from[my_int] == '>') {
01150             strcat(to, ">");
01151             my_int++;
01152         } else if (from[my_int] == '?') {
01153             strcat(to, "?");
01154             my_int++;
01155         } else if (from[my_int] == 'A') {
01156             strcat(to, "A");
01157             my_int++;
01158         } else if (from[my_int] == 'B') {
01159             strcat(to, "B");
01160             my_int++;
01161         } else if (from[my_int] == 'C') {
01162             strcat(to, "C");
01163             my_int++;
01164         } else if (from[my_int] == 'D') {
01165             strcat(to, "D");
01166             my_int++;
01167         } else if (from[my_int] == 'E') {
01168             strcat(to, "E");
01169             my_int++;
01170         } else if (from[my_int] == 'F') {
01171             strcat(to, "F");
01172             my_int++;
01173         } else if (from[my_int] == 'G') {
01174             strcat(to, "G");
01175             my_int++;
01176         } else if (from[my_int] == 'H') {
01177             strcat(to, "H");
01178             my_int++;
01179         } else if (from[my_int] == 'I') {
01180             strcat(to, "I");
01181             my_int++;
01182         } else if (from[my_int] == 'J') {
01183             strcat(to, "J");
01184             my_int++;
01185         } else if (from[my_int] == 'K') {
01186             strcat(to, "K");
01187             my_int++;
01188         } else if (from[my_int] == 'L') {
01189             strcat(to, "L");
01190             my_int++;
01191         } else if (from[my_int] == 'M') {
01192             strcat(to, "M");
01193             my_int++;
01194         } else if (from[my_int] == 'N') {
01195             strcat(to, "N");
01196             my_int++;
01197         } else if (from[my_int] == 'O') {
01198             strcat(to, "O");
01199             my_int++;
01200         } else if (from[my_int] == 'P') {
01201             strcat(to, "P");
01202             my_int++;
01203         } else if (from[my_int] == 'Q') {
01204             strcat(to, "Q");
01205             my_int++;
01206         } else if (from[my_int] == 'R') {
01207             strcat(to, "R");
01208             my_int++;
01209         } else if (from[my_int] == 'S') {
01210             strcat(to, "S");
01211             my_int++;
01212         } else if (from[my_int] == 'T') {
01213             strcat(to, "T");
01214             my_int++;
01215         } else if (from[my_int] == 'U') {
01216             strcat(to, "U");
01217             my_int++;
01218         } else if (from[my_int] == 'V') {
01219             strcat(to, "V");
01220             my_int++;
01221         } else if (from[my_int] == 'W') {
01222             strcat(to, "W");
01223             my_int++;
01224         } else if (from[my_int] == 'X') {
01225             strcat(to, "X");
01226             my_int++;
01227         } else if (from[my_int] == 'Y') {
01228             strcat(to, "Y");
01229             my_int++;
01230         } else if (from[my_int] == 'Z') {
01231             strcat(to, "Z");
01232             my_int++;
01233         } else if (from[my_int] == 'a') {
01234             strcat(to, "a");
01235             my_int++;
01236         } else if (from[my_int] == 'b') {
01237             strcat(to, "b");
01238             my_int++;
01239         } else if (from[my_int] == 'c') {
01240             strcat(to, "c");
01241             my_int++;
01242         } else if (from[my_int] == 'd') {
01243             strcat(to, "d");
01244             my_int++;
01245         } else if (from[my_int] == 'e') {
01246             strcat(to, "e");
01247             my_int++;
01248         } else if (from[my_int] == 'f') {
01249             strcat(to, "f");
01250             my_int++;
01251         } else if (from[my_int] == 'g') {
01252             strcat(to, "g");
01253             my_int++;
01254         } else if (from[my_int] == 'h') {
01255             strcat(to, "h");
01256             my_int++;
01257         } else if (from[my_int] == 'i') {
01258             strcat(to, "i");
01259             my_int++;
01260         } else if (from[my_int] == 'j') {
01261             strcat(to, "j");
01262             my_int++;
01263         } else if (from[my_int] == 'k') {
01264             strcat(to, "k");
01265             my_int++;
01266         } else if (from[my_int] == 'l') {
01267             strcat(to, "l");
01268             my_int++;
01269         } else if (from[my_int] == 'm') {
01270             strcat(to, "m");
01271             my_int++;
01272         } else if (from[my_int] == 'n') {
01273             strcat(to, "n");
01274             my_int++;
01275         } else if (from[my_int] == 'o') {
01276             strcat(to, "o");
01277             my_int++;
01278         } else if (from[my_int] == 'p') {
01279             strcat(to, "p");
01280             my_int++;
01281         } else if (from[my_int] == 'q') {
01282             strcat(to, "q");
01283             my_int++;
01284         } else if (from[my_int] == 'r') {
01285             strcat(to, "r");
01286             my_int++;
01287         } else if (from[my_int] == 's') {
01288             strcat(to, "s");
01289             my_int++;
01290         } else if (from[my_int] == 't') {
01291             strcat(to, "t");
01292             my_int++;
01293         } else if (from[my_int] == 'u') {
01294             strcat(to, "u");
01295             my_int++;
01296         } else if (from[my_int] == 'v') {
01297             strcat(to, "v");
01298             my_int++;
01299         } else if (from[my_int] == 'w') {
01300             strcat(to, "w");
01301             my_int++;
01302         } else if (from[my_int] == 'x') {
01303             strcat(to, "x");
01304             my_int++;
01305         } else if (from[my_int] == 'y') {
01306             strcat(to, "y");
01307             my_int++;
01308         } else if (from[my_int] == 'z') {
01309             strcat(to, "z");
01310             my_int++;
01311         } else if (from[my_int] == ' ') {
01312             strcat(to, " ");
01313             my_int++;
01314         } else if (from[my_int] == '\r') {
01315             strcat(to, "\r");
01316             my_int++;
01317         } else if (from[my_int] == '\n') {
01318             strcat(to, "\n");
01319             my_int++;
01320         }
01321         else { /* of course it might be that nothing happened */
01322             debug("bb.sms.cimd", 0, "parse: [%c:%02X %c:%02X %c:%02X]", from[my_int],
01323                   from[my_int], from[my_int + 1], from[my_int + 1],
01324                   from[my_int + 2], from[my_int + 2]);
01325 
01326             temp_int = strlen(to);
01327             to[temp_int] = 0xBF;    /* '¿' */
01328             to[temp_int + 1] = '\0';
01329             my_int++;
01330         }
01331 
01332     } /* for */
01333 
01334     return strlen(to);
01335 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.