1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2014 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  *    if any, must include the following acknowledgment:
22  *       "This product includes software developed by the
23  *        Kannel Group (http://www.kannel.org/)."
24  *    Alternately, this acknowledgment may appear in the software itself,
25  *    if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  *    endorse or promote products derived from this software without
29  *    prior written permission. For written permission, please
30  *    contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  *    nor may "Kannel" appear in their name, without prior written
34  *    permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group.  For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*****************************************************************************
58 * smsc_cimd.c - Nokia SMS Center (CIMD 1.3).
59 * Mikael Gueck for WapIT Ltd.
60 */
61 
62 #include <errno.h>
63 #include <string.h>
64 #include <stdio.h>
65 #include <unistd.h>
66 #include <stdlib.h>
67 #include <time.h>
68 
69 #include <sys/time.h>
70 #include <sys/types.h>
71 #include <sys/socket.h>
72 
73 #include "smsc.h"
74 #include "smsc_p.h"
75 #include "gwlib/gwlib.h"
76 #include "alt_charsets.h"
77 
78 /******************************************************************************
79 * Static functions
80 */
81 
82 /* do the handshake baby */
83 static int cimd_open_connection(SMSCenter *smsc);
84 
85 /* waits for an ACK message, returns the ACK command number or -1 for error */
86 static int expect_acknowledge(SMSCenter *smsc, int *cmd, int *err);
87 
88 /* sends a general ACK */
89 static int send_acknowledge(SMSCenter *smsc);
90 
91 /* Reconnect to a CIMD server, use an existing structure */
92 static int connect_tcpip(SMSCenter *smsc);
93 
94 static int parse_cimd_to_iso88591(char *from, char *to, int length);
95 
96 static int parse_iso88591_to_cimd(
97     char *from, char *to, int length, int alt_charset);
98 
99 /******************************************************************************
100 * Open the connection and log in
101 *
102 * return 0 if ok, -1 on failure
103 */
cimd_open_connection(SMSCenter * smsc)104 static int cimd_open_connection(SMSCenter *smsc)
105 {
106 
107     char *tmpbuff = NULL;
108     int ret = 0;
109 
110     int cmd = 0, err = 0;
111 
112     /* allocate some spare space */
113     tmpbuff = gw_malloc(10 * 1024);
114     memset(tmpbuff, 0, 10*1024);
115 
116     /* connect */
117     smsc->socket = tcpip_connect_to_server(smsc->cimd_hostname, smsc->cimd_port,
118 	NULL);
119 	/* XXX add interface_name if required */
120 
121     if (smsc->socket == -1)
122         goto error;
123 
124     /* receive protocol string "CIMD rel 1.37\n" */
125     for (;;) {
126         ret = smscenter_read_into_buffer(smsc);
127         if (strstr(smsc->buffer, "CIMD rel 1.37\n") != NULL)
128             break;
129         if (ret < 0) goto logout;
130     }
131 
132     debug("bb.sms.cimd", 0, "got the server identification tag");
133 
134     smscenter_remove_from_buffer(smsc, smsc->buflen);
135 
136     /* send login string */
137     sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%c",
138             0x02,
139             "01", 0x09,
140             smsc->cimd_username, 0x09,
141             smsc->cimd_password, 0x09,
142             "11",
143             0x03, 0x0A);
144 
145     ret = write_to_socket(smsc->socket, tmpbuff);
146     if (ret < 0) goto logout;
147 
148     /* get an acknowledge message */
149 
150     smsc->cimd_last_spoke = 0;
151 
152     if (expect_acknowledge(smsc, &cmd, &err) < 1)
153         goto logout;
154 
155     debug("bb.sms.cimd", 0, "logged in");
156 
157     gw_free(tmpbuff);
158     return 0;
159 
160 logout:
161     cimd_close(smsc);
162 
163 error:
164     error(0, "cimd_open: could not open/handshake");
165     gw_free(tmpbuff);
166     return -1;
167 }
168 
169 
170 
171 /******************************************************************************
172 * Open the smscenter
173 */
cimd_open(char * hostname,int port,char * username,char * password)174 SMSCenter *cimd_open(char *hostname, int port, char *username, char *password)
175 {
176 
177     SMSCenter *smsc = NULL;
178     int ret = 0;
179 
180     /* create a SMSCenter structure */
181     smsc = smscenter_construct();
182     if (smsc == NULL) goto error;
183     smsc->type = SMSC_TYPE_CIMD;
184     smsc->cimd_hostname = gw_strdup(hostname);
185     smsc->hostname = gw_strdup(hostname); /* Needed by read_into_buffer() */
186     smsc->cimd_port = port;
187     smsc->cimd_username = gw_strdup(username);
188     smsc->cimd_password = gw_strdup(password);
189 
190     ret = cimd_open_connection(smsc);
191     if (ret < 0)
192         goto error;
193 
194     sprintf(smsc->name, "CIMD:%s:%d:%s", smsc->cimd_hostname,
195             smsc->cimd_port, smsc->cimd_username);
196     return smsc;
197 
198 error:
199     error(0, "cimd_open: could not open!");
200     smscenter_destruct(smsc);
201     return NULL;
202 }
203 
204 
205 /******************************************************************************
206 * Re-open the connection and log in
207 *
208 * return -1 if failed
209 */
cimd_reopen(SMSCenter * smsc)210 int cimd_reopen(SMSCenter *smsc)
211 {
212 
213     cimd_close(smsc);
214 
215     if (cimd_open_connection(smsc) < 0) {
216         error(0, "Failed to re-open the connection!");
217         return -1;
218     }
219     return 0;
220 }
221 
222 
223 
224 /******************************************************************************
225 * Log out and close the socket
226 *
227 */
cimd_close(SMSCenter * smsc)228 int cimd_close(SMSCenter *smsc)
229 {
230 
231     char *cbuff = NULL;
232     int sum;
233     int ret;
234 
235     if (smsc->socket == -1) {
236         debug("bb.sms.cimd", 0, "Trying to close cimd while already closed!");
237         return 0;
238     }
239     cbuff = gw_malloc(2 * 1024);
240 
241     sprintf(cbuff, "%c%s%c%s%c%c", 0x02, "02", 0x09, "11", 0x03, 0x0A);
242 
243     sum = write_to_socket(smsc->socket, cbuff);
244     if (sum < 0) goto error;
245 
246     /* this time we don't block waiting for acknowledge */
247     recv(smsc->socket, cbuff, 2*1024, 0);
248 
249     gw_free(cbuff);
250 
251     ret = close(smsc->socket);
252     smsc->socket = -1;
253     return ret;
254 
255 error:
256     gw_free(cbuff);
257     return -1;
258 }
259 
260 
261 /******************************************************************************
262 * Check for MO messages, returns as in smsc_submit_smsmessage in smsc.h
263 */
cimd_pending_smsmessage(SMSCenter * smsc)264 int cimd_pending_smsmessage(SMSCenter *smsc)
265 {
266 
267     char *tmpbuff = NULL, *newline = NULL;
268     int ret = 0;
269     time_t thetime = 0;
270 
271     /* check for input sanity */
272     if (smsc == NULL)
273         goto error;
274 
275     /* we can only query every 5 seconds */
276     thetime = time(NULL);
277     if ((smsc->cimd_last_spoke + 5) > thetime) goto no_messages;
278     smsc->cimd_last_spoke = thetime;
279 
280     /* allocate some spare space */
281     tmpbuff = gw_malloc(10 * 1024);
282     memset(tmpbuff, 0, 10*1024);
283 
284     sprintf(tmpbuff, "%c%s%c%s%c%c",
285             0x02,         /* stx */
286             "05", 0x09,   /* request for message, tab */
287             "11",         /* dummy chksum */
288             0x03, 0x0A);  /* etx, lf */
289 
290     /* send the poll message to determine if we have messages in queue */
291     ret = write_to_socket(smsc->socket, tmpbuff);
292     if (ret < 0) {
293         debug("bb.sms.cimd", 0, "sending poll message failed");
294         goto error;
295     }
296     /* block while waiting for answer that dataset ends to a 0x0A */
297     for (;;) {
298 
299         newline = memchr(smsc->buffer, 0x0A, smsc->buflen);
300         if (newline != NULL) break;
301 
302         newline = memchr(smsc->buffer, 0x03, smsc->buflen);
303         if (newline != NULL) break;
304 
305         ret = smscenter_read_into_buffer(smsc);
306         if (ret <= 0) {
307             debug("bb.sms.cimd", 0, "read_into_buffer failed!, ret=%d", ret);
308             goto error;
309         }
310 
311         usleep(500);
312 
313         /* Reconnect if no results in 30 seconds */
314         if (time(NULL) > (thetime + 30)) {
315 
316             error(0, "timeout occurred, maybe the connection was broken?");
317 
318             /* Reconnect if neccessary, this catches most of them */
319             /* XXX this is an ugly kludge, but then again,
320                CIMD 1.3 is an ugly kludge. */
321             connect_tcpip(smsc);
322             goto no_messages;
323 
324         }
325 
326     }
327 
328     /* if we got an nck, cut the message out and return 0 */
329     newline = memchr(smsc->buffer, 0x15, smsc->buflen);
330     if (newline != NULL) {
331         newline = memchr(smsc->buffer, 0x0A, smsc->buflen);
332         if (newline == NULL)
333             newline = memchr(smsc->buffer, 0x03, smsc->buflen);
334         smscenter_remove_from_buffer(smsc, newline - smsc->buffer + 1);
335         goto no_messages;
336     }
337 
338     /* miracle of miracles, we got a message */
339     gw_free(tmpbuff);
340     return 1;
341 
342 no_messages:
343     gw_free(tmpbuff);
344     return 0;
345 
346 error:
347 
348     debug("bb.sms.cimd", 0, "smscenter_pending_smsmessage: returning error");
349     gw_free(tmpbuff);
350     return -1;
351 }
352 
353 
354 
355 /******************************************************************************
356 * Send a MT message, returns as in smsc_submit_smsmessage in smsc.h
357 */
cimd_submit_msg(SMSCenter * smsc,Msg * msg)358 int cimd_submit_msg(SMSCenter *smsc, Msg *msg)
359 {
360 
361     char *tmpbuff = NULL, *tmptext = NULL;
362     char msgtext[1024];
363     int ret;
364     int cmd = 0, err = 0;
365 
366     /* Fix these by implementing a could-not-send-because-
367        protocol-does-not-allow in smsc.c or smsgateway.c */
368     if (octstr_len(msg->sms.msgdata) + octstr_len(msg->sms.udhdata) < 1) {
369 	if (msg->sms.msgdata == NULL)
370 	    msg->sms.msgdata = octstr_create("");
371 	octstr_append_from_hex(msg->sms.msgdata, "20");
372     }
373     if (octstr_len(msg->sms.sender) < 1) {
374         warning(0, "cimd_submit_smsmessage: ignoring message with 0-length field");
375         goto okay;  /* THIS IS NOT OKAY!!!! XXX */
376     }
377     if (octstr_len(msg->sms.receiver) < 1) {
378         warning(0, "cimd_submit_smsmessage: ignoring message with 0-length field");
379         goto okay;  /* THIS IS NOT OKAY!!!! XXX */
380     }
381 
382     tmpbuff = gw_malloc(10 * 1024);
383     tmptext = gw_malloc(10 * 1024);
384 
385     memset(tmpbuff, 0, 10*1024);
386     memset(tmptext, 0, 10*1024);
387     memset(msgtext, 0, sizeof(msgtext));
388 
389     if (octstr_len(msg->sms.udhdata)) {
390         octstr_get_many_chars(msgtext, msg->sms.udhdata, 0, octstr_len(msg->sms.udhdata));
391         octstr_get_many_chars(msgtext + octstr_len(msg->sms.udhdata),
392                               msg->sms.msgdata, 0,
393                               140 - octstr_len(msg->sms.udhdata));
394     } else {
395         octstr_get_many_chars(msgtext, msg->sms.msgdata, 0,
396                               octstr_len(msg->sms.msgdata));
397     }
398 
399     /* XXX parse_iso88591_to_cimd should use Octstr
400      * directly, or get a char* and a length, instead of using NUL
401      * terminated strings.
402      */
403     parse_iso88591_to_cimd(msgtext, tmptext, 10*1024, smsc->alt_charset);
404 
405     /* If messages has UDHs, add the magic number 31 to the right spot */
406     sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c%c",
407             0x02,
408             "03", 0x09,
409             octstr_get_cstr(msg->sms.receiver), 0x09,
410             tmptext, 0x09,
411             "", 0x09,
412             "", 0x09,
413             (octstr_len(msg->sms.udhdata)) ? "31" : "", 0x09,
414             "11", 0x03, 0x0A);
415 
416     ret = write_to_socket(smsc->socket, tmpbuff);
417     if (ret < 0) {
418         debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: socket write error");
419         goto error;
420     }
421 
422     /* The Nokia SMSC MAY be configured to send delivery
423        information, which we then will HAVE to acknowledge.
424        Naturally the CIMD 1.3 protocol does not include any
425        kind of negotiation mechanism. */
426     ret = expect_acknowledge(smsc, &cmd, &err);
427 
428     if (ret >= 1) {
429 
430         if (cmd == 4) {
431             send_acknowledge(smsc);
432             goto okay;
433         } else if (cmd == 3) {
434             goto okay;
435         }
436 
437     } else if (ret == 0) {
438 
439         if (cmd == 4) {
440             send_acknowledge(smsc);
441             goto okay;  /* FIXME XXX THIS IS BOGUS, FIX SMSGATEWAY.C */
442             goto error;
443         } else if (cmd == 3) {
444             goto okay;  /* FIXME XXX THIS IS BOGUS, FIX SMSGATEWAY.C */
445             goto error;
446         } else {
447             error(0, "Unexpected behaviour from the CIMD server");
448             debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: acknowledge was <%i>", ret);
449             debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: buffer==<%s>", smsc->buffer);
450             goto error;
451         }
452 
453     }
454 
455 okay:
456     gw_free(tmpbuff);
457     gw_free(tmptext);
458     return 0;
459 
460 error:
461     debug("bb.sms.cimd", 0, "cimd_submit_smsmessage: returning error");
462     gw_free(tmpbuff);
463     gw_free(tmptext);
464     return -1;
465 
466 }
467 
468 
469 
cimd_receive_msg(SMSCenter * smsc,Msg ** msg)470 int cimd_receive_msg(SMSCenter *smsc, Msg **msg)
471 {
472 
473     char *tmpbuff = NULL, *sender = NULL;
474     char *receiver = NULL, *text = NULL, *scts = NULL;
475     char *tmpchar = NULL;
476 
477     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: starting");
478 
479     /* the PENDING function has previously requested for
480        the message and checked that it safely found its
481        way into the memory buffer (smsc->buffer) */
482 
483     /* we want to temporarily store some data */
484     tmpbuff = gw_malloc(10 * 1024);
485     sender = gw_malloc(10 * 1024);
486     receiver = gw_malloc(10 * 1024);
487     text = gw_malloc(10 * 1024);
488     scts = gw_malloc(10 * 1024);
489 
490     memset(tmpbuff, 0, 10 * 1024);
491     memset(sender, 0, 10 * 1024);
492     memset(receiver, 0, 10 * 1024);
493     memset(text, 0, 10 * 1024);
494     memset(scts, 0, 10 * 1024);
495 
496     /* cut the raw message out from the message buffer */
497     tmpchar = memchr(smsc->buffer, 0x0A, smsc->buflen);
498     if (tmpchar == NULL) {
499         tmpchar = memchr(smsc->buffer, 0x03, smsc->buflen);
500         if (tmpchar == NULL) goto error;
501     }
502 
503     strncpy(tmpbuff, smsc->buffer, tmpchar - smsc->buffer);
504     smscenter_remove_from_buffer(smsc, tmpchar - smsc->buffer + 1);
505 
506     /* Parse the raw message */
507     sscanf(tmpbuff,
508            "\x02\x06\tC:05\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t11\x03\x0A",
509            receiver, sender, text, scts);
510 
511     sscanf(tmpbuff,
512            "\x02\x06\tC:05\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t11\x03",
513            receiver, sender, text, scts);
514 
515     /* Translate from the CIMD character set to iso8859-1 */
516     parse_cimd_to_iso88591(text, tmpbuff, 10*1024);
517     strncpy(text, tmpbuff, 480);
518 
519     /* create a smsmessage structure out of the components */
520     *msg = msg_create(sms);
521     if (*msg == NULL) return -1;
522     (*msg)->sms.sender = octstr_create(sender);
523     (*msg)->sms.receiver = octstr_create(receiver);
524     (*msg)->sms.msgdata = octstr_create(text);
525 
526     /* Send acknowledge */
527     send_acknowledge(smsc);
528 
529     /* We got a message so we can instantly check for a new one. */
530     smsc->cimd_last_spoke -= 5;
531 
532     /* Free and Finish */
533 
534     gw_free(tmpbuff);
535     gw_free(sender);
536     gw_free(receiver);
537     gw_free(text);
538     gw_free(scts);
539 
540     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: return ok");
541 
542     return 1;
543 
544 error:
545     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: failed");
546     gw_free(tmpbuff);
547     gw_free(sender);
548     gw_free(receiver);
549     gw_free(text);
550     gw_free(scts);
551 
552     debug("bb.sms.cimd", 0, "cimd_receive_smsmessage: return failed");
553 
554     return -1;
555 }
556 
557 /******************************************************************************
558 * In(f)ternal Functions
559 */
560 
connect_tcpip(SMSCenter * smsc)561 static int connect_tcpip(SMSCenter *smsc)
562 {
563 
564     char *tmpbuff = NULL;
565     int ret = 0;
566     int cmd = 0, err = 0;
567 
568     debug("bb.sms.cimd", 0, "reconnecting to <%s>", smsc->name);
569 
570     /* allocate some spare space */
571     tmpbuff = gw_malloc(10 * 1024);
572     memset(tmpbuff, 0, 10*1024);
573 
574     /* Close connection */
575     close(smsc->socket);
576 
577     smsc->socket = -1;
578 
579     /* Be sure to open a socket. */
580     for (;;) {
581         smsc->socket = tcpip_connect_to_server(
582                            smsc->cimd_hostname, smsc->cimd_port,
583 			   NULL);
584 	    /* XXX add interface_name if required */
585 
586         if (smsc->socket != -1) break;
587 
588         usleep(1000);
589     }
590 
591     /* Empty the buffer, there might be an evil ghost inside... */
592 
593     memset(smsc->buffer, 0, smsc->bufsize);
594     smsc->buflen = 0;
595 
596     /* Expect the protocol string "CIMD rel 1.37\n" */
597     for (;;) {
598         ret = smscenter_read_into_buffer(smsc);
599         if (ret < 0) goto logout;
600         if (strstr(smsc->buffer, "CIMD rel 1.37\n") != NULL)
601             break;
602         usleep(1000);
603     }
604     smscenter_remove_from_buffer(smsc, smsc->buflen);
605 
606     /* send login string */
607     sprintf(tmpbuff, "%c%s%c%s%c%s%c%s%c%c",
608             0x02,
609             "01", 0x09,
610             smsc->cimd_username, 0x09,
611             smsc->cimd_password, 0x09,
612             "11",
613             0x03, 0x0A);
614 
615     ret = write_to_socket(smsc->socket, tmpbuff);
616     if (ret < 0) goto logout;
617 
618     /* get an acknowledge message */
619 
620     smsc->cimd_last_spoke = 0;
621 
622     if (expect_acknowledge(smsc, &cmd, &err) < 1)
623         goto logout;
624 
625     debug("bb.sms.cimd", 0, "cimd_connect_tcpip: logged in");
626 
627     gw_free(tmpbuff);
628 
629     return 1;
630 
631 logout:
632     close(smsc->socket);
633     gw_free(tmpbuff);
634     return 0;
635 }
636 
637 /******************************************************************************
638 * Yeah, we got the message!
639 */
send_acknowledge(SMSCenter * smsc)640 static int send_acknowledge(SMSCenter *smsc)
641 {
642 
643     char tmpbuff[100];
644     int tmpint;
645 
646     if (tmpbuff == NULL) {
647         error(0, "cimd_send_acknowledge: memory allocation failure");
648         goto error;
649     }
650 
651     memset(tmpbuff, 0, sizeof(tmpbuff));
652 
653     sprintf(tmpbuff, "\2\6\t11\3\n");
654 
655     tmpint = write_to_socket(smsc->socket, tmpbuff);
656     if (tmpint == -1) {
657         error(0, "cimd_send_acknowledge: connection failure");
658         goto error;
659     }
660 
661     return 0;
662 
663 error:
664     debug("bb.sms.cimd", 0, "cimd_send_acknowledge: failed");
665     return -1;
666 }
667 
668 /******************************************************************************
669 * Wait for the Nokia piece of *!%&%*^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H SMSC
670 * to catch up with our swift operation, block until... (~1sec?)
671 */
expect_acknowledge(SMSCenter * smsc,int * cmd,int * err)672 static int expect_acknowledge(SMSCenter *smsc, int *cmd, int *err)
673 {
674 
675     char *end_of_dataset = NULL;
676     char *ack = NULL, *nck = NULL;
677     char *cmdspecifier = NULL, *errorspecifier = NULL;
678     int ret = 0;
679 
680 #if 0
681     time_t thetime;
682     time(&thetime);
683 #endif
684 
685     if (smsc == NULL) goto error;
686 
687     /* Loop until we get an acknowledgement message. */
688     for (;;) {
689 
690         /* If the server is configured in to end a dataset with a \n */
691         end_of_dataset = memchr(smsc->buffer, '\n', smsc->buflen);
692         if (end_of_dataset != NULL) break;
693 
694         /* If the server is configured in to end a dataset with a \3 */
695         end_of_dataset = memchr(smsc->buffer, 0x03, smsc->buflen);
696         if (end_of_dataset != NULL) break;
697 
698         ret = smscenter_read_into_buffer(smsc);
699         if (ret <= 0) {
700             if (errno == EAGAIN) continue;
701             if (errno == EINTR) continue;
702             return -1;
703         }
704 
705         usleep(500);
706 
707 #if 0
708         /* Abort if no results in 30 seconds */
709 
710         if (time(NULL) > (thetime + 30)) {
711 
712             error(0, "timeout occurred, maybe the connection was broken?");
713             if (errno == EPIPE) {
714                 error(0, "broken pipe");
715             } /* if errno */
716 
717             goto error;
718 
719         } /* if time */
720 #endif
721     }
722 
723     /* Check if our request was answered or denied */
724     ack = memchr(smsc->buffer, 0x06, end_of_dataset - smsc->buffer);
725     nck = memchr(smsc->buffer, 0x15, end_of_dataset - smsc->buffer);
726 
727     /* Get the command code from the acknowledge message */
728     cmdspecifier = strstr(smsc->buffer, "\tC:");
729     if (cmdspecifier != NULL)
730         *cmd = strtol(cmdspecifier + 3, NULL, 10);
731     else
732         *cmd = 0;
733 
734     errorspecifier = strstr(smsc->buffer, "\tE:");
735     if (errorspecifier != NULL)
736         *err = strtol(errorspecifier + 3, NULL, 10);
737     else
738         *err = 0;
739 
740     debug("bb.sms.cimd", 0, "cimd_pending_smsmessage: smsc->buffer == <%s>", smsc->buffer);
741 
742     /* Remove the acknowledge message from the incoming buffer. */
743     smscenter_remove_from_buffer(smsc, end_of_dataset - smsc->buffer + 1);
744 
745     /* if we got an acknowledge */
746     if (ack != NULL) {
747         info(0, "cimd_pending_smsmessage: got ACK");
748         return 1;
749     }
750 
751     /* if we got an NOT acknowledge */
752     if (nck != NULL) {
753         info(0, "cimd_pending_smsmessage: got NCK");
754         return 0;
755     }
756 
757     /* if we got an ERROR */
758 error:
759     error(0, "cimd_expect_acknowledge failed");
760     return -1;
761 
762 }
763 
764 /******************************************************************************
765 * Convert a string from ISO-8859-1 to the CIMD character set
766 */
parse_iso88591_to_cimd(char * from,char * to,int length,int alt_charset)767 static int parse_iso88591_to_cimd(char* from, char* to,
768         int length, int alt_charset)
769 {
770 
771     char *temp = to;
772 
773     if (from == NULL || to == NULL || length == 0)
774         return -1;
775 
776     *to = '\0';
777 
778     while ((*from != '\0') && ((int) strlen(temp) < (length - 2))) {
779 
780         switch (*from) {
781 
782         case '@': strcat(to, "_Oa"); to += 3; break;
783         case '�': strcat(to, "_L-"); to += 3; break;
784 
785         case '$':
786             if (alt_charset == CIMD_PLAIN_DOLLAR_SIGN) {
787                 strcat(to, "$");
788                 to++;
789             } else {
790                 strcat(to, "_$ ");
791                 to += 3;
792             }
793             break;
794 
795         case '�': strcat(to, "_A*"); to += 3; break;
796         case '�': strcat(to, "_a*"); to += 3; break;
797         case '�': strcat(to, "_a\""); to += 3; break;
798         case '�': strcat(to, "_o\""); to += 3; break;
799         case '�': strcat(to, "_A\""); to += 3; break;
800         case '�': strcat(to, "_O\""); to += 3; break;
801         case '�': strcat(to, "_Y-"); to += 3; break;
802         case '�': strcat(to, "_e`"); to += 3; break;
803         case '�': strcat(to, "_e�"); to += 3; break;
804         case '�': strcat(to, "_u`"); to += 3; break;
805         case '�': strcat(to, "_i`"); to += 3; break;
806         case '�': strcat(to, "_o`"); to += 3; break;
807         case '�': strcat(to, "_C,"); to += 3; break;
808         case '�': strcat(to, "_O/"); to += 3; break;
809         case '�': strcat(to, "_o/"); to += 3; break;
810         case '�': strcat(to, "_AE"); to += 3; break;
811         case '�': strcat(to, "_ae"); to += 3; break;
812         case '�': strcat(to, "_ss"); to += 3; break;
813         case '�': strcat(to, "_E�"); to += 3; break;
814         case '�': strcat(to, "_??"); to += 3; break;
815         case '�': strcat(to, "_U\""); to += 3; break;
816         case '�': strcat(to, "_n~"); to += 3; break;
817         case '�': strcat(to, "_u\""); to += 3; break;
818         case '�': strcat(to, "_a`"); to += 3; break;
819         case '�': strcat(to, "_!!"); to += 3; break;
820         case '_': strcat(to, "_--"); to += 3; break;
821         case '�': strcat(to, "_N~"); to += 3; break;
822         case '!': strcat(to, "!"); to++; break;
823         case '"': strcat(to, "\""); to++; break;
824         case '#': strcat(to, "#"); to++; break;
825         case '�': strcat(to, "�"); to++; break;
826         case '%': strcat(to, "%"); to++; break;
827         case '&': strcat(to, "&"); to++; break;
828         case '\'': strcat(to, "'"); to++; break;
829         case '(': strcat(to, "("); to++; break;
830         case ')': strcat(to, ")"); to++; break;
831         case '*': strcat(to, "*"); to++; break;
832         case '+': strcat(to, "+"); to++; break;
833         case ',': strcat(to, ","); to++; break;
834         case '-': strcat(to, "-"); to++; break;
835         case '.': strcat(to, "."); to++; break;
836         case '/': strcat(to, "/"); to++; break;
837         case '0': strcat(to, "0"); to++; break;
838         case '1': strcat(to, "1"); to++; break;
839         case '2': strcat(to, "2"); to++; break;
840         case '3': strcat(to, "3"); to++; break;
841         case '4': strcat(to, "4"); to++; break;
842         case '5': strcat(to, "5"); to++; break;
843         case '6': strcat(to, "6"); to++; break;
844         case '7': strcat(to, "7"); to++; break;
845         case '8': strcat(to, "8"); to++; break;
846         case '9': strcat(to, "9"); to++; break;
847         case ':': strcat(to, ":"); to++; break;
848         case ';': strcat(to, ";"); to++; break;
849         case '<': strcat(to, "<"); to++; break;
850         case '=': strcat(to, "="); to++; break;
851         case '>': strcat(to, ">"); to++; break;
852         case '?': strcat(to, "?"); to++; break;
853         case 'A': strcat(to, "A"); to++; break;
854         case 'B': strcat(to, "B"); to++; break;
855         case 'C': strcat(to, "C"); to++; break;
856         case 'D': strcat(to, "D"); to++; break;
857         case 'E': strcat(to, "E"); to++; break;
858         case 'F': strcat(to, "F"); to++; break;
859         case 'G': strcat(to, "G"); to++; break;
860         case 'H': strcat(to, "H"); to++; break;
861         case 'I': strcat(to, "I"); to++; break;
862         case 'J': strcat(to, "J"); to++; break;
863         case 'K': strcat(to, "K"); to++; break;
864         case 'L': strcat(to, "L"); to++; break;
865         case 'M': strcat(to, "M"); to++; break;
866         case 'N': strcat(to, "N"); to++; break;
867         case 'O': strcat(to, "O"); to++; break;
868         case 'P': strcat(to, "P"); to++; break;
869         case 'Q': strcat(to, "Q"); to++; break;
870         case 'R': strcat(to, "R"); to++; break;
871         case 'S': strcat(to, "S"); to++; break;
872         case 'T': strcat(to, "T"); to++; break;
873         case 'U': strcat(to, "U"); to++; break;
874         case 'V': strcat(to, "V"); to++; break;
875         case 'W': strcat(to, "W"); to++; break;
876         case 'X': strcat(to, "X"); to++; break;
877         case 'Y': strcat(to, "Y"); to++; break;
878         case 'Z': strcat(to, "Z"); to++; break;
879         case 'a': strcat(to, "a"); to++; break;
880         case 'b': strcat(to, "b"); to++; break;
881         case 'c': strcat(to, "c"); to++; break;
882         case 'd': strcat(to, "d"); to++; break;
883         case 'e': strcat(to, "e"); to++; break;
884         case 'f': strcat(to, "f"); to++; break;
885         case 'g': strcat(to, "g"); to++; break;
886         case 'h': strcat(to, "h"); to++; break;
887         case 'i': strcat(to, "i"); to++; break;
888         case 'j': strcat(to, "j"); to++; break;
889         case 'k': strcat(to, "k"); to++; break;
890         case 'l': strcat(to, "l"); to++; break;
891         case 'm': strcat(to, "m"); to++; break;
892         case 'n': strcat(to, "n"); to++; break;
893         case 'o': strcat(to, "o"); to++; break;
894         case 'p': strcat(to, "p"); to++; break;
895         case 'q': strcat(to, "q"); to++; break;
896         case 'r': strcat(to, "r"); to++; break;
897         case 's': strcat(to, "s"); to++; break;
898         case 't': strcat(to, "t"); to++; break;
899         case 'u': strcat(to, "u"); to++; break;
900         case 'v': strcat(to, "v"); to++; break;
901         case 'w': strcat(to, "w"); to++; break;
902         case 'x': strcat(to, "x"); to++; break;
903         case 'y': strcat(to, "y"); to++; break;
904         case 'z': strcat(to, "z"); to++; break;
905         case ' ': strcat(to, " "); to++; break;
906         case '\r': strcat(to, "\r"); to++; break;
907         case '\n': strcat(to, "\n"); to++; break;
908 
909         default: strcat(to, "_??"); to += 3; break;
910         }
911         from++;
912     }
913 
914     *to = '\0';
915 
916     return strlen(temp);
917 }
918 
919 
920 /******************************************************************************
921 * Convert a string from the CIMD character set to ISO-8859-1
922 */
parse_cimd_to_iso88591(char * from,char * to,int length)923 static int parse_cimd_to_iso88591(char* from, char* to, int length)
924 {
925 
926     int my_int, temp_int;
927 
928     *to = '\0';
929 
930     for (my_int = 0; my_int < (int)strlen(from) && (int)strlen(to) < length; ) {
931 
932         if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == '"') {
933             strcat(to, "�");
934             my_int += 3;
935         } else if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == '*') {
936             strcat(to, "�");
937             my_int += 3;
938         }
939 
940         /* argh, this drives me nu---uuutts */
941 
942         else if (from[my_int] == '@') {
943             strcat(to, "@");
944             my_int ++;
945         }
946         else if (from[my_int] == '_' && from[my_int + 1] == 'O' && from[my_int + 2] == 'a') {
947             strcat(to, "@");
948             my_int += 3;
949         } else if (from[my_int] == '_' && from[my_int + 1] == 'L' && from[my_int + 2] == '-') {
950             strcat(to, "�");
951             my_int += 3;
952         }
953 
954         /* this following one is against specifications but what to do
955          * when it works?!? (the other is NOT used) rpr 1.10. */
956 
957         else if (from[my_int] == '$') {
958             strcat(to, "$");
959             my_int ++;
960         }
961         else if (from[my_int] == '_' && from[my_int + 1] == '$' && from[my_int + 2] == ' ') {
962             strcat(to, "$");
963             my_int += 3;
964         }
965         else if (from[my_int] == '_' && from[my_int + 1] == 'A' && from[my_int + 2] == '*') {
966             strcat(to, "�");
967             my_int += 3;
968         } else if (from[my_int] == '_' && from[my_int + 1] == 'o' && from[my_int + 2] == '"') {
969             strcat(to, "�");
970             my_int += 3;
971         } else if (from[my_int] == '_' && from[my_int + 1] == 'A' && from[my_int + 2] == '"') {
972             strcat(to, "�");
973             my_int += 3;
974         } else if (from[my_int] == '_' && from[my_int + 1] == 'O' && from[my_int + 2] == '"') {
975             strcat(to, "�");
976             my_int += 3;
977         } else if (from[my_int] == '_' && from[my_int + 1] == 'Y' && from[my_int + 2] == '-') {
978             strcat(to, "�");
979             my_int += 3;
980         } else if (from[my_int] == '_' && from[my_int + 1] == 'e' && from[my_int + 2] == '`') {
981             strcat(to, "�");
982             my_int += 3;
983         } else if (from[my_int] == '_' && from[my_int + 1] == 'e' && from[my_int + 2] == '�') {
984             strcat(to, "�");
985             my_int += 3;
986         } else if (from[my_int] == '_' && from[my_int + 1] == 'u' && from[my_int + 2] == '`') {
987             strcat(to, "�");
988             my_int += 3;
989         } else if (from[my_int] == '_' && from[my_int + 1] == 'i' && from[my_int + 2] == '`') {
990             strcat(to, "�");
991             my_int += 3;
992         } else if (from[my_int] == '_' && from[my_int + 1] == 'o' && from[my_int + 2] == '`') {
993             strcat(to, "�");
994             my_int += 3;
995         } else if (from[my_int] == '_' && from[my_int + 1] == 'C' && from[my_int + 2] == ',') {
996             strcat(to, "�");
997             my_int += 3;
998         } else if (from[my_int] == '_' && from[my_int + 1] == 'O' && from[my_int + 2] == '/') {
999             strcat(to, "�");
1000             my_int += 3;
1001         } else if (from[my_int] == '_' && from[my_int + 1] == 'o' && from[my_int + 2] == '/') {
1002             strcat(to, "�");
1003             my_int += 3;
1004         } else if (from[my_int] == '_' && from[my_int + 1] == 'A' && from[my_int + 2] == 'E') {
1005             strcat(to, "�");
1006             my_int += 3;
1007         } else if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == 'e') {
1008             strcat(to, "�");
1009             my_int += 3;
1010         } else if (from[my_int] == '_' && from[my_int + 1] == 's' && from[my_int + 2] == 's') {
1011             strcat(to, "�");
1012             my_int += 3;
1013         } else if (from[my_int] == '_' && from[my_int + 1] == 'E' && from[my_int + 2] == '�') {
1014             strcat(to, "�");
1015             my_int += 3;
1016         } else if (from[my_int] == '_' && from[my_int + 1] == '?' && from[my_int + 2] == '?') {
1017             strcat(to, "�");
1018             my_int += 3;
1019         } else if (from[my_int] == '_' && from[my_int + 1] == 'U' && from[my_int + 2] == '"') {
1020             strcat(to, "�");
1021             my_int += 3;
1022         } else if (from[my_int] == '_' && from[my_int + 1] == 'n' && from[my_int + 2] == '~' ) {
1023             strcat(to, "�");
1024             my_int += 3;
1025         } else if (from[my_int] == '_' && from[my_int + 1] == 'u' && from[my_int + 2] == '"') {
1026             strcat(to, "�");
1027             my_int += 3;
1028         } else if (from[my_int] == '_' && from[my_int + 1] == 'a' && from[my_int + 2] == '`') {
1029             strcat(to, "�");
1030             my_int += 3;
1031         } else if (from[my_int] == '_' && from[my_int + 1] == '!' && from[my_int + 2] == '!') {
1032             strcat(to, "�");
1033             my_int += 3;
1034         } else if (from[my_int] == '_' && from[my_int + 1] == '-' && from[my_int + 2] == '-') {
1035             strcat(to, "_");
1036             my_int += 3;
1037         } else if (from[my_int] == '_' && from[my_int + 1] == 'N' && from[my_int + 2] == '~') {
1038             strcat(to, "_");
1039             my_int += 3;
1040         }
1041 
1042         /* I just LOVE the designers of this protocol -mg */
1043         else if (from[my_int] == ']') {
1044             strcat(to, "�");
1045             my_int++;
1046         } else if (from[my_int] == '}') {
1047             strcat(to, "�");
1048             my_int++;
1049         } else if (from[my_int] == '[') {
1050             strcat(to, "�");
1051             my_int++;
1052         } else if (from[my_int] == '{') {
1053             strcat(to, "�");
1054             my_int++;
1055         } else if (from[my_int] == '\\') {
1056             strcat(to, "�");
1057             my_int++;
1058         } else if (from[my_int] == '|') {
1059             strcat(to, "�");
1060             my_int++;
1061         }
1062         else if (from[my_int] == '!') {
1063             strcat(to, "!");
1064             my_int++;
1065         } else if (from[my_int] == '"') {
1066             strcat(to, "\"");
1067             my_int++;
1068         } else if (from[my_int] == '#') {
1069             strcat(to, "#");
1070             my_int++;
1071         } else if (from[my_int] == '�') {
1072             strcat(to, "�");
1073             my_int++;
1074         } else if (from[my_int] == '%') {
1075             strcat(to, "%");
1076             my_int++;
1077         } else if (from[my_int] == '&') {
1078             strcat(to, "&");
1079             my_int++;
1080         } else if (from[my_int] == '\'') {
1081             strcat(to, "'");
1082             my_int++;
1083         } else if (from[my_int] == '(') {
1084             strcat(to, "(");
1085             my_int++;
1086         } else if (from[my_int] == ')') {
1087             strcat(to, ")");
1088             my_int++;
1089         } else if (from[my_int] == '*') {
1090             strcat(to, "*");
1091             my_int++;
1092         } else if (from[my_int] == '+') {
1093             strcat(to, "+");
1094             my_int++;
1095         } else if (from[my_int] == ',') {
1096             strcat(to, ",");
1097             my_int++;
1098         } else if (from[my_int] == '-') {
1099             strcat(to, "-");
1100             my_int++;
1101         } else if (from[my_int] == '.') {
1102             strcat(to, ".");
1103             my_int++;
1104         } else if (from[my_int] == '/') {
1105             strcat(to, "/");
1106             my_int++;
1107         } else if (from[my_int] == '0') {
1108             strcat(to, "0");
1109             my_int++;
1110         } else if (from[my_int] == '1') {
1111             strcat(to, "1");
1112             my_int++;
1113         } else if (from[my_int] == '2') {
1114             strcat(to, "2");
1115             my_int++;
1116         } else if (from[my_int] == '3') {
1117             strcat(to, "3");
1118             my_int++;
1119         } else if (from[my_int] == '4') {
1120             strcat(to, "4");
1121             my_int++;
1122         } else if (from[my_int] == '5') {
1123             strcat(to, "5");
1124             my_int++;
1125         } else if (from[my_int] == '6') {
1126             strcat(to, "6");
1127             my_int++;
1128         } else if (from[my_int] == '7') {
1129             strcat(to, "7");
1130             my_int++;
1131         } else if (from[my_int] == '8') {
1132             strcat(to, "8");
1133             my_int++;
1134         } else if (from[my_int] == '9') {
1135             strcat(to, "9");
1136             my_int++;
1137         } else if (from[my_int] == ':') {
1138             strcat(to, ":");
1139             my_int++;
1140         } else if (from[my_int] == ';') {
1141             strcat(to, ";");
1142             my_int++;
1143         } else if (from[my_int] == '<') {
1144             strcat(to, "<");
1145             my_int++;
1146         } else if (from[my_int] == '=') {
1147             strcat(to, "=");
1148             my_int++;
1149         } else if (from[my_int] == '>') {
1150             strcat(to, ">");
1151             my_int++;
1152         } else if (from[my_int] == '?') {
1153             strcat(to, "?");
1154             my_int++;
1155         } else if (from[my_int] == 'A') {
1156             strcat(to, "A");
1157             my_int++;
1158         } else if (from[my_int] == 'B') {
1159             strcat(to, "B");
1160             my_int++;
1161         } else if (from[my_int] == 'C') {
1162             strcat(to, "C");
1163             my_int++;
1164         } else if (from[my_int] == 'D') {
1165             strcat(to, "D");
1166             my_int++;
1167         } else if (from[my_int] == 'E') {
1168             strcat(to, "E");
1169             my_int++;
1170         } else if (from[my_int] == 'F') {
1171             strcat(to, "F");
1172             my_int++;
1173         } else if (from[my_int] == 'G') {
1174             strcat(to, "G");
1175             my_int++;
1176         } else if (from[my_int] == 'H') {
1177             strcat(to, "H");
1178             my_int++;
1179         } else if (from[my_int] == 'I') {
1180             strcat(to, "I");
1181             my_int++;
1182         } else if (from[my_int] == 'J') {
1183             strcat(to, "J");
1184             my_int++;
1185         } else if (from[my_int] == 'K') {
1186             strcat(to, "K");
1187             my_int++;
1188         } else if (from[my_int] == 'L') {
1189             strcat(to, "L");
1190             my_int++;
1191         } else if (from[my_int] == 'M') {
1192             strcat(to, "M");
1193             my_int++;
1194         } else if (from[my_int] == 'N') {
1195             strcat(to, "N");
1196             my_int++;
1197         } else if (from[my_int] == 'O') {
1198             strcat(to, "O");
1199             my_int++;
1200         } else if (from[my_int] == 'P') {
1201             strcat(to, "P");
1202             my_int++;
1203         } else if (from[my_int] == 'Q') {
1204             strcat(to, "Q");
1205             my_int++;
1206         } else if (from[my_int] == 'R') {
1207             strcat(to, "R");
1208             my_int++;
1209         } else if (from[my_int] == 'S') {
1210             strcat(to, "S");
1211             my_int++;
1212         } else if (from[my_int] == 'T') {
1213             strcat(to, "T");
1214             my_int++;
1215         } else if (from[my_int] == 'U') {
1216             strcat(to, "U");
1217             my_int++;
1218         } else if (from[my_int] == 'V') {
1219             strcat(to, "V");
1220             my_int++;
1221         } else if (from[my_int] == 'W') {
1222             strcat(to, "W");
1223             my_int++;
1224         } else if (from[my_int] == 'X') {
1225             strcat(to, "X");
1226             my_int++;
1227         } else if (from[my_int] == 'Y') {
1228             strcat(to, "Y");
1229             my_int++;
1230         } else if (from[my_int] == 'Z') {
1231             strcat(to, "Z");
1232             my_int++;
1233         } else if (from[my_int] == 'a') {
1234             strcat(to, "a");
1235             my_int++;
1236         } else if (from[my_int] == 'b') {
1237             strcat(to, "b");
1238             my_int++;
1239         } else if (from[my_int] == 'c') {
1240             strcat(to, "c");
1241             my_int++;
1242         } else if (from[my_int] == 'd') {
1243             strcat(to, "d");
1244             my_int++;
1245         } else if (from[my_int] == 'e') {
1246             strcat(to, "e");
1247             my_int++;
1248         } else if (from[my_int] == 'f') {
1249             strcat(to, "f");
1250             my_int++;
1251         } else if (from[my_int] == 'g') {
1252             strcat(to, "g");
1253             my_int++;
1254         } else if (from[my_int] == 'h') {
1255             strcat(to, "h");
1256             my_int++;
1257         } else if (from[my_int] == 'i') {
1258             strcat(to, "i");
1259             my_int++;
1260         } else if (from[my_int] == 'j') {
1261             strcat(to, "j");
1262             my_int++;
1263         } else if (from[my_int] == 'k') {
1264             strcat(to, "k");
1265             my_int++;
1266         } else if (from[my_int] == 'l') {
1267             strcat(to, "l");
1268             my_int++;
1269         } else if (from[my_int] == 'm') {
1270             strcat(to, "m");
1271             my_int++;
1272         } else if (from[my_int] == 'n') {
1273             strcat(to, "n");
1274             my_int++;
1275         } else if (from[my_int] == 'o') {
1276             strcat(to, "o");
1277             my_int++;
1278         } else if (from[my_int] == 'p') {
1279             strcat(to, "p");
1280             my_int++;
1281         } else if (from[my_int] == 'q') {
1282             strcat(to, "q");
1283             my_int++;
1284         } else if (from[my_int] == 'r') {
1285             strcat(to, "r");
1286             my_int++;
1287         } else if (from[my_int] == 's') {
1288             strcat(to, "s");
1289             my_int++;
1290         } else if (from[my_int] == 't') {
1291             strcat(to, "t");
1292             my_int++;
1293         } else if (from[my_int] == 'u') {
1294             strcat(to, "u");
1295             my_int++;
1296         } else if (from[my_int] == 'v') {
1297             strcat(to, "v");
1298             my_int++;
1299         } else if (from[my_int] == 'w') {
1300             strcat(to, "w");
1301             my_int++;
1302         } else if (from[my_int] == 'x') {
1303             strcat(to, "x");
1304             my_int++;
1305         } else if (from[my_int] == 'y') {
1306             strcat(to, "y");
1307             my_int++;
1308         } else if (from[my_int] == 'z') {
1309             strcat(to, "z");
1310             my_int++;
1311         } else if (from[my_int] == ' ') {
1312             strcat(to, " ");
1313             my_int++;
1314         } else if (from[my_int] == '\r') {
1315             strcat(to, "\r");
1316             my_int++;
1317         } else if (from[my_int] == '\n') {
1318             strcat(to, "\n");
1319             my_int++;
1320         }
1321         else { /* of course it might be that nothing happened */
1322             debug("bb.sms.cimd", 0, "parse: [%c:%02X %c:%02X %c:%02X]", from[my_int],
1323                   from[my_int], from[my_int + 1], from[my_int + 1],
1324                   from[my_int + 2], from[my_int + 2]);
1325 
1326             temp_int = strlen(to);
1327             to[temp_int] = 0xBF; 	/* '�' */
1328             to[temp_int + 1] = '\0';
1329             my_int++;
1330         }
1331 
1332     } /* for */
1333 
1334     return strlen(to);
1335 }
1336