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