18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sms.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "gsm.h"
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <memory.h>
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
167891dd35fa2439a70f43ab8572778a398365bf24David 'Digit' Turner#include <string.h>
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <assert.h>
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  DEBUG  1
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 1
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include "android/utils/debug.h"
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE  VERBOSE_CHECK(modem)
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE  DEBUG
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(...)  VERBOSE_PRINT(modem,__VA_ARGS__)
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(...)  ((void)0)
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* maximum number of data bytes in a SMS data message */
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_USER_DATA_BYTES   140
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* maximum number of 7-bit septets in a SMS text message */
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_USER_DATA_SEPTETS  160
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* size of the user data header in bytes */
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  USER_DATA_HEADER_SIZE   6
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** MESSAGE TEXT
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_utf8_from_message_str( const char*  str, int  strlen, unsigned char*  utf8, int  utf8len )
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  p       = (cbytes_t)str;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = p + strlen;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       count   = 0;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       escaped = 0;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (p < end)
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = p[0];
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* read the value from the string */
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p += 1;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 128) {
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((c & 0xe0) == 0xc0)
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x1f;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if ((c & 0xf0) == 0xe0)
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x0f;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x07;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p++;
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80) {
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = (c << 6) | (p[0] & 0x3f);
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p++;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (escaped) {
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (c) {
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case '\\':
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 'n':  /* \n is line feed */
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    c = 10;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 'x':  /* \xNN, where NN is a 2-digit hexadecimal value */
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (p+2 > end)
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return -1;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    c = gsm_hex2_to_byte( (const char*)p );
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (c < 0)
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return -1;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    p += 2;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 'u':  /* \uNNNN where NNNN is a 4-digiti hexadecimal value */
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (p + 4 > end)
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return -1;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    c = gsm_hex4_to_short( (const char*)p );
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (c < 0)
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return -1;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    p += 4;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:  /* invalid escape, return -1 */
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return -1;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escaped = 0;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == '\\')
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escaped = 1;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* now, try to write it to the destination */
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < 128) {
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (count < utf8len)
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8[count] = (byte_t) c;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            count += 1;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c < 0x800) {
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (count < utf8len)
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8[count]   = (byte_t)(0xc0 | ((c >> 6) & 0x1f));
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (count+1 < utf8len)
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8[count+1] = (byte_t)(0x80 | (c & 0x3f));
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            count += 2;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (count < utf8len)
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8[count]   = (byte_t)(0xc0 | ((c >> 12) & 0xf));
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (count+1 < utf8len)
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8[count+1] = (byte_t)(0x80 | ((c >> 6) & 0x3f));
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (count+2 < utf8len)
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8[count+2] = (byte_t)(0x80 | (c & 0x3f));
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            count += 3;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (escaped)   /* bad final escape */
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count;
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* to convert utf-8 to a message string, we only need to deal with control characters
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and that's it */
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  sms_utf8_to_message_str( const unsigned char*  utf8, int  utf8len, char*  str, int  strlen )
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  p = utf8;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end = p + utf8len;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       count   = 0;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (p < end)
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c      = p[0];
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  escape = 0;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* read the value from the string */
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p += 1;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 128) {
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((c & 0xe0) == 0xc0)
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x1f;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if ((c & 0xf0) == 0xe0)
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x0f;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x07;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p++;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80) {
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = (c << 6) | (p[0] & 0x3f);
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p++;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c < ' ') {
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escape = 1;
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (c == '\n') {
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c      = 'n';
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                escape = 2;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == '\\')
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            escape = 2;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (escape) {
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (c < 128) {
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (count < strlen)
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        str[count] = (char) c;
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count += 1;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else if (c < 0x800) {
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (count < strlen)
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        str[count]   = (byte_t)(0xc0 | ((c >> 6) & 0x1f));
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (count+1 < strlen)
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        str[count+1] = (byte_t)(0x80 | (c & 0x3f));
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count += 2;
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else {
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (count < strlen)
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        str[count]   = (byte_t)(0xc0 | ((c >> 12) & 0xf));
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (count+1 < strlen)
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        str[count+1] = (byte_t)(0x80 | ((c >> 6) & 0x3f));
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (count+2 < strlen)
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        str[count+2] = (byte_t)(0x80 | (c & 0x3f));
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count += 3;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (count+3 < strlen) {
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    str[count+0] = '\\';
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    str[count+1] = 'x';
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gsm_hex_from_byte(str + count + 2, c);
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                count += 4;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (count+2 < strlen) {
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    str[count+0] = '\\';
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    str[count+1] = (char) c;
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                count += 2;
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** TIMESTAMPS
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_timestamp_now( SmsTimeStamp  stamp )
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    time_t     now_time = time(NULL);
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm  gm       = *(gmtime(&now_time));
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm  local    = *(localtime(&now_time));
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int        tzdiff   = 0;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[0] = gsm_int_to_bcdi( local.tm_year % 100 );
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[1] = gsm_int_to_bcdi( local.tm_mon+1 );
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[2] = gsm_int_to_bcdi( local.tm_mday );
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[3] = gsm_int_to_bcdi( local.tm_hour );
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[4] = gsm_int_to_bcdi( local.tm_min );
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[5] = gsm_int_to_bcdi( local.tm_sec );
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tzdiff = (local.tm_hour*4 + local.tm_min/15) - (gm.tm_hour*4 + gm.tm_min/15);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (local.tm_yday > gm.tm_yday)
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tzdiff += 24*4;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (local.tm_yday < gm.tm_yday)
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tzdiff -= 24*4;
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stamp->data[6] = gsm_int_to_bcdi( tzdiff >= 0 ? tzdiff : -tzdiff );
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tzdiff < 0)
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stamp->data[6] |= 0x08;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_timestamp_to_tm( SmsTimeStamp  stamp, struct tm*  tm )
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  tzdiff;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_year = gsm_int_from_bcdi( stamp->data[0] );
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tm->tm_year < 50)
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tm->tm_year += 100;
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_mon  = gsm_int_from_bcdi( stamp->data[1] ) -1;
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_mday = gsm_int_from_bcdi( stamp->data[2] );
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_hour = gsm_int_from_bcdi( stamp->data[3] );
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_min  = gsm_int_from_bcdi( stamp->data[4] );
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_sec  = gsm_int_from_bcdi( stamp->data[5] );
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tm->tm_isdst = -1;
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tzdiff = gsm_int_from_bcdi( stamp->data[6] & 0xf7 );
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (stamp->data[6] & 0x8)
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tzdiff = -tzdiff;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tzdiff;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_add_timestamp( GsmRope  rope, const SmsTimeStampRec*  ts )
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add( rope, ts->data, 7 );
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** SMS ADDRESSES
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_from_str( SmsAddress  address, const char*  src, int  srclen )
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  end   = src + srclen;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          shift = 0, len = 0;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t      data = address->data;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->len = 0;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->toa = 0x81;
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (src >= end)
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( src[0] == '+' ) {
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address->toa = 0x91;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (++src == end)
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Fail;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset( address->data, 0, sizeof(address->data) );
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shift = 0;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (src < end) {
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = *src++ - '0';
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( (unsigned)c >= 10 ||
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              data >= address->data + sizeof(address->data) )
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Fail;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        data[0] |= c << shift;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   += 1;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift += 4;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 8) {
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 0;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            data += 1;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift != 0)
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        data[0] |= 0xf0;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->len = len;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_to_str( SmsAddress address, char*  str, int  strlen )
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char  dialdigits[16] = "0123456789*#,N%";
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                n, count = 0;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (address->toa == 0x91) {
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count < strlen)
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            str[count] = '+';
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count++;
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (n = 0; n < address->len; n += 2)
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   c = address->data[n/2];
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count < strlen)
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            str[count] = dialdigits[c & 0xf];
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count += 1;
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n+1 > address->len)
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count < strlen)
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            str[count] = dialdigits[(c >> 4) & 0xf];
357a1b379c65f787fc85bd9c6f4a6d14d8a2bebc9d5Marc Petit-Huguenin        if (str[count])
358a1b379c65f787fc85bd9c6f4a6d14d8a2bebc9d5Marc Petit-Huguenin            count += 1;
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count;
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_from_bytes( SmsAddress  address, const unsigned char*  buf, int  buflen )
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   len = sizeof(address->data), num_digits;
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (buflen < 2)
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->len = num_digits = buf[0];
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->toa = buf[1];
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = (num_digits+1)/2;
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( len > sizeof(address->data) )
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( address->data, buf+2, len );
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_to_bytes( SmsAddress  address, unsigned char*  buf, int  bufsize )
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len = (address->len + 1)/2 + 2;
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (buf == NULL)
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bufsize = 0;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bufsize < 1) goto Exit;
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf[0] = address->len;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bufsize < 2) goto Exit;
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf[1] = address->toa;
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf     += 2;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bufsize -= 2;
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bufsize > len-2)
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bufsize = len - 2;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( buf, address->data, bufsize );
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return len;
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_from_hex  ( SmsAddress  address, const char*  hex, int  hexlen )
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  hexend = hex + hexlen;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          nn, len, num_digits;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hexlen < 4)
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->len = num_digits = gsm_hex2_to_byte( hex );
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->toa = gsm_hex2_to_byte( hex+2 );
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hex += 4;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = (num_digits + 1)/2;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hex + len*2 > hexend)
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; nn < len; nn++ )
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address->data[nn] = gsm_hex2_to_byte( hex + nn*2 );
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_to_hex    ( SmsAddress  address, char*   hex, int  hexlen )
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len = (address->len + 1)/2 + 2;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hex == NULL)
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hexlen = 0;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hexlen < 2) goto Exit;
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_hex_from_byte( hex, address->len );
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hexlen < 4) goto Exit;
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_hex_from_byte( hex+2, address->toa );
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hex    += 4;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hexlen -= 4;
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( hexlen > 2*(len - 2) )
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hexlen = (len - 2)/2;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; nn < hexlen; nn += 2 )
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gsm_hex_from_byte( hex+nn, address->data[nn/2] );
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return len*2;
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_add_address( GsmRope  rope, const SmsAddressRec*  addr )
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, addr->len );
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, addr->toa );
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add( rope, addr->data, (addr->len+1)/2 );
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (addr->len & 1) {
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!rope->error && rope->data != NULL)
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rope->data[ rope->pos-1 ] |= 0xf0;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_address_eq( const SmsAddressRec*  addr1, const SmsAddressRec*  addr2 )
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( addr1->toa != addr2->toa ||
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         addr1->len != addr2->len )
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ( !memcmp( addr1->data, addr2->data, addr1->len ) );
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** SMS PARSER
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_get_byte( cbytes_t  *pcur, cbytes_t  end )
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur    = *pcur;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur < end) {
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = cur[0];
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pcur  = cur + 1;
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a service center address, returns -1 in case of error */
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_get_sc_address( cbytes_t   *pcur,
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    cbytes_t    end,
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    SmsAddress  address )
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur    = *pcur;
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur < end) {
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  len = cur[0];
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  dlen, adjust = 0;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cur += 1;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len == 0) {   /* empty address */
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            address->len = 0;
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            address->toa = 0x00;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result       = 0;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Exit;
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cur + len > end) {
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Exit;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address->toa = *cur++;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len         -= 1;
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result       = 0;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (dlen = 0; dlen < len; dlen+=1)
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  c = cur[dlen];
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  v;
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            adjust = 0;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dlen >= sizeof(address->data)) {
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                result = -1;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            v = (c & 0xf);
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (v >= 0xe)
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            adjust              = 1;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            address->data[dlen] = (byte_t) c;
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            v = (c >> 4) & 0xf;
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (v >= 0xe) {
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address->len = 2*dlen + adjust;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!result)
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pcur = cur;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_skip_sc_address( cbytes_t   *pcur,
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     cbytes_t    end )
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur    = *pcur;
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len;
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur >= end)
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len  = cur[0];
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cur += 1 + len;
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur > end)
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcur  = cur;
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = 0;
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a sender/receiver address, returns -1 in case of error */
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_get_address( cbytes_t   *pcur,
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 cbytes_t    end,
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 SmsAddress  address )
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur    = *pcur;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len, dlen;
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur >= end)
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dlen = *cur++;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dlen == 0) {
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address->len = 0;
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address->toa = 0;
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result       = 0;
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur + 1 + (dlen+1)/2 > end)
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->len = dlen;
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    address->toa = *cur++;
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = (dlen + 1)/2;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > sizeof(address->data))
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( address->data, cur, len );
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cur   += len;
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = 0;
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!result)
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pcur = cur;
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_skip_address( cbytes_t   *pcur,
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  cbytes_t    end  )
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur    = *pcur;
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       dlen;
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur + 2 > end)
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dlen = cur[0];
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cur += 2 + (dlen + 1)/2;
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur > end)
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = 0;
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a service center timestamp */
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_get_timestamp( cbytes_t     *pcur,
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   cbytes_t      end,
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   SmsTimeStamp  ts )
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur = *pcur;
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur + 7 > end)
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( ts->data, cur, 7 );
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcur = cur + 7;
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_skip_timestamp( cbytes_t  *pcur,
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    cbytes_t   end )
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur = *pcur;
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur + 7 > end)
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcur = cur + 7;
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_skip_validity_period( cbytes_t  *pcur,
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          cbytes_t   end,
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int        mtiByte )
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur = *pcur;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((mtiByte >> 3) & 3) {
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:  /* relative format */
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cur += 1;
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:  /* enhanced format */
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:  /* absolute format */
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cur += 7;
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur > end)
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcur = cur;
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** SMS PDU
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct SmsPDURec {
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t  base;
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t  end;
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t  tpdu;
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} SmsPDURec;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_free( SmsPDU  pdu )
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdu) {
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        free( pdu->base );
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pdu->base = NULL;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pdu->end  = NULL;
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pdu->tpdu = NULL;
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSmsPduType
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_type( SmsPDU  pdu )
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data    = pdu->tpdu;
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = pdu->end;
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       mtiByte = sms_get_byte(&data, end);
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mtiByte & 3) {
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:  return SMS_PDU_DELIVER;
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:  return SMS_PDU_SUBMIT;
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:  return SMS_PDU_STATUS_REPORT;
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return SMS_PDU_INVALID;
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_sender_address( SmsPDU  pdu, SmsAddress  address )
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data    = pdu->tpdu;
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = pdu->end;
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       mtiByte = sms_get_byte(&data, end);
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mtiByte & 3) {
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* SMS_PDU_DELIVER; */
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return sms_get_sc_address( &data, end, address );
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return -1;
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_sc_timestamp( SmsPDU  pdu, SmsTimeStamp  ts )
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data    = pdu->tpdu;
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = pdu->end;
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       mtiByte = sms_get_byte( &data, end );
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mtiByte & 3) {
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:  /* SMS_PDU_DELIVER */
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SmsAddressRec  address;
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ( sms_get_sc_address( &data, end, &address ) < 0 )
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return -1;
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                data += 2;  /* skip protocol identifer + coding scheme */
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return sms_get_timestamp( &data, end, ts );
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return -1;
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_receiver_address( SmsPDU  pdu, SmsAddress  address )
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data    = pdu->tpdu;
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = pdu->end;
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       mtiByte = sms_get_byte( &data, end );
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mtiByte & 3) {
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:  /* SMS_PDU_SUBMIT */
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                data += 1;  /* skip message reference */
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return sms_get_address( &data, end, address );
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return -1;
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef enum {
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SMS_CODING_SCHEME_UNKNOWN = 0,
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SMS_CODING_SCHEME_GSM7,
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SMS_CODING_SCHEME_UCS2
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} SmsCodingScheme;
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* see TS 23.038 Section 5 for details */
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SmsCodingScheme
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_get_coding_scheme( cbytes_t  *pcur,
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       cbytes_t   end )
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur = *pcur;
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       dataCoding;
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur >= end)
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return SMS_CODING_SCHEME_UNKNOWN;
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dataCoding = *cur++;
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcur      = cur;
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (dataCoding >> 4) {
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x00:
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x02:
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x03:
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return SMS_CODING_SCHEME_GSM7;
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x01:
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dataCoding == 0x10) return SMS_CODING_SCHEME_GSM7;
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dataCoding == 0x11) return SMS_CODING_SCHEME_UCS2;
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x04: case 0x05: case 0x06: case 0x07:
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dataCoding & 0x20)           return SMS_CODING_SCHEME_UNKNOWN; /* compressed 7-bits */
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((dataCoding >> 2) & 3) == 0) return SMS_CODING_SCHEME_GSM7;
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((dataCoding >> 2) & 3) == 2) return SMS_CODING_SCHEME_UCS2;
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xF:
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(dataCoding & 4)) return SMS_CODING_SCHEME_GSM7;
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return SMS_CODING_SCHEME_UNKNOWN;
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* see TS 23.040 section 9.2.3.24 for details */
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_get_text_utf8( cbytes_t        *pcur,
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   cbytes_t         end,
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   int              hasUDH,
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   SmsCodingScheme  coding,
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   GsmRope          rope )
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  cur    = *pcur;
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       result = -1;
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len;
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur >= end)
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = *cur++;
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* skip user data header if any */
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( hasUDH )
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  hlen;
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cur >= end)
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Exit;
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hlen = *cur++;
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cur + hlen > end)
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Exit;
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cur += hlen;
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (coding == SMS_CODING_SCHEME_GSM7)
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len -= 2*(hlen+1);
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len -= hlen+1;
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len < 0)
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Exit;
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* switch the user data header if any */
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (coding == SMS_CODING_SCHEME_GSM7)
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  count = utf8_from_gsm7( cur, 0, len, NULL );
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rope != NULL)
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bytes_t  dst = gsm_rope_reserve( rope, count );
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst != NULL)
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                utf8_from_gsm7( cur, 0, len, dst );
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cur += (len+1)/2;
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (coding == SMS_CODING_SCHEME_UCS2)
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  count = ucs2_to_utf8( cur, len/2, NULL );
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rope != NULL)
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bytes_t  dst = gsm_rope_reserve( rope, count );
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dst != NULL)
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ucs2_to_utf8( cur, len/2, dst );
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cur += len;
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = 0;
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!result)
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pcur = cur;
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* get the message embedded in a SMS PDU as a utf8 byte array, returns the length of the message in bytes */
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* or -1 in case of error */
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_text_message( SmsPDU  pdu, unsigned char*  utf8, int  utf8len )
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data    = pdu->tpdu;
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = pdu->end;
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       mtiByte = sms_get_byte( &data, end );
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mtiByte & 3) {
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:  /* SMS_PDU_DELIVER */
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SmsAddressRec    address;
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SmsTimeStampRec  timestamp;
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SmsCodingScheme  coding;
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                GsmRopeRec       rope[1];
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int              result;
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ( sms_get_sc_address( &data, end, &address ) < 0 )
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                data  += 1;  /* skip protocol identifier */
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                coding = sms_get_coding_scheme( &data, end );
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (coding == SMS_CODING_SCHEME_UNKNOWN)
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ( sms_get_timestamp( &data, end, &timestamp ) < 0 )
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ( sms_get_text_utf8( &data, end, (mtiByte & 0x40), coding, rope ) < 0 )
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                result = rope->pos;
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (utf8len > result)
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    utf8len = result;
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (utf8len > 0)
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    memcpy( utf8, rope->data, utf8len );
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gsm_rope_done( rope );
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return result;
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:  /* SMS_PDU_SUBMIT */
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SmsAddressRec    address;
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                SmsCodingScheme  coding;
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                GsmRopeRec       rope[1];
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int              result;
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                data += 1;  /* message reference */
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ( sms_get_address( &data, end, &address ) < 0 )
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                data  += 1;  /* skip protocol identifier */
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                coding = sms_get_coding_scheme( &data, end );
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (coding == SMS_CODING_SCHEME_UNKNOWN)
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gsm_rope_init_alloc( rope, 0 );
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ( sms_get_text_utf8( &data, end, (mtiByte & 0x40), coding, rope ) < 0 ) {
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gsm_rope_done( rope );
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto Fail;
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                result = rope->pos;
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (utf8len > result)
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    utf8len = result;
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (utf8len > 0)
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    memcpy( utf8, rope->data, utf8len );
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gsm_rope_done( rope );
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return result;
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic cbytes_t
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_user_data_ref( SmsPDU  pdu )
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data    = pdu->tpdu;
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  end     = pdu->end;
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       mtiByte = sms_get_byte( &data, end );
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len;
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* if there is no user-data-header, there is no message reference here */
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((mtiByte & 0x40) == 0)
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mtiByte & 3) {
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:  /* SMS_PDU_DELIVER */
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( sms_skip_address( &data, end ) < 0 )
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto Fail;
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            data  += 2;  /* skip protocol identifier + coding scheme */
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( sms_skip_timestamp( &data, end ) < 0 )
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto Fail;
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:  /* SMS_PDU_SUBMIT */
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            data += 1;  /* skip message reference */
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( sms_skip_address( &data, end ) < 0 )
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto Fail;
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            data += 2;  /* protocol identifier + oding schene */
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( sms_skip_validity_period( &data, end, mtiByte ) < 0 )
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto Fail;
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Fail;
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* skip user-data length */
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (data+1 >= end)
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len   = data[1];
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    data += 2;
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len >= 2 && data + 2 <= end) {
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  htype = data[0];
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  hlen = data[1];
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (htype == 00 && hlen == 3 && data + 5 <= end) {
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return data + 2;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        data += hlen;
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len  -= hlen - 2;
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_ref( SmsPDU  pdu )
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  user_ref = smspdu_get_user_data_ref( pdu );
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (user_ref != NULL)
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return user_ref[0];
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cbytes_t  data    = pdu->tpdu;
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cbytes_t  end     = pdu->end;
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int       mtiByte = sms_get_byte( &data, end );
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((mtiByte & 3) == 1) {
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* try to extract directly the reference for a SMS-SUBMIT */
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (data < end)
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return data[0];
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_max_index( SmsPDU  pdu )
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  user_ref = smspdu_get_user_data_ref( pdu );
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (user_ref != NULL) {
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return user_ref[1];
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_get_cur_index( SmsPDU  pdu )
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  user_ref = smspdu_get_user_data_ref( pdu );
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (user_ref != NULL) {
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return user_ref[2] - 1;
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_add_sms_user_header( GsmRope  rope,
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int      ref_number,
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int      pdu_count,
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int      pdu_index )
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, 0x05 );     /* total header length == 5 bytes */
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, 0x00 );     /* element id: concatenated message reference number */
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, 0x03 );     /* element len: 3 bytes */
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, (byte_t)ref_number );  /* reference number */
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, (byte_t)pdu_count );     /* max pdu index */
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, (byte_t)pdu_index+1 );   /* current pdu index */
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write a SMS-DELIVER PDU into a rope */
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_rope_add_sms_deliver_pdu( GsmRope                 rope,
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              cbytes_t                utf8,
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int                     utf8len,
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int                     use_gsm7,
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              const SmsAddressRec*    sender_address,
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              const SmsTimeStampRec*  timestamp,
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int                     ref_num,
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int                     pdu_count,
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int                     pdu_index)
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  coding;
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  mtiByte  = 0x20;  /* message type - SMS DELIVER */
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdu_count > 1)
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mtiByte |= 0x40;  /* user data header indicator */
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, 0 );        /* no SC Address */
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, mtiByte );     /* message type - SMS-DELIVER */
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_address( rope, sender_address );
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, 0 );        /* protocol identifier */
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* data coding scheme - GSM 7 bits / no class - or - 16-bit UCS2 / class 1 */
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    coding = (use_gsm7 ? 0x00 : 0x09);
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_c( rope, coding );               /* data coding scheme       */
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_timestamp( rope, timestamp );    /* service center timestamp */
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (use_gsm7) {
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bytes_t  dst;
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int    count = utf8_to_gsm7( utf8, utf8len, NULL, 0 );
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int    pad   = 0;
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        assert( count <= MAX_USER_DATA_SEPTETS - USER_DATA_HEADER_SIZE );
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pdu_count > 1)
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  headerBits    = 6*8;  /* 6 is size of header in bytes */
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  headerSeptets = headerBits / 7;
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (headerBits % 7 > 0)
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                headerSeptets += 1;
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pad = headerSeptets*7 - headerBits;
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gsm_rope_add_c( rope, count + headerSeptets );
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gsm_rope_add_sms_user_header(rope, ref_num, pdu_count, pdu_index);
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gsm_rope_add_c( rope, count );
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count = (count*7+pad+7)/8;  /* convert to byte count */
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst = gsm_rope_reserve( rope, count );
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst != NULL) {
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8_to_gsm7( utf8, utf8len, dst, pad );
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bytes_t  dst;
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      count = utf8_to_ucs2( utf8, utf8len, NULL );
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        assert( count*2 <= MAX_USER_DATA_BYTES - USER_DATA_HEADER_SIZE );
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pdu_count > 1)
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gsm_rope_add_c( rope, count*2 + 6 );
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gsm_rope_add_sms_user_header( rope, ref_num, pdu_count, pdu_index );
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gsm_rope_add_c( rope, count*2 );
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gsm_rope_add_c( rope, count*2 );
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst = gsm_rope_reserve( rope, count*2 );
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dst != NULL) {
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8_to_ucs2( utf8, utf8len, dst );
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SmsPDU
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_create_deliver( cbytes_t               utf8,
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int                    utf8len,
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int                    use_gsm7,
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       const SmsAddressRec*   sender_address,
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       const SmsTimeStampRec* timestamp,
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int                    ref_num,
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int                    pdu_count,
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int                    pdu_index )
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU      p;
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GsmRopeRec  rope[1];
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         size;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = calloc( sizeof(*p), 1 );
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) goto Exit;
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_init( rope );
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_sms_deliver_pdu( rope, utf8, utf8len, use_gsm7,
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 sender_address, timestamp,
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 ref_num, pdu_count, pdu_index);
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rope->error)
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_init_alloc( rope, rope->pos );
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gsm_rope_add_sms_deliver_pdu( rope, utf8, utf8len, use_gsm7,
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 sender_address, timestamp,
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 ref_num, pdu_count, pdu_index );
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p->base = gsm_rope_done_acquire( rope, &size );
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p->base == NULL)
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p->end  = p->base + size;
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p->tpdu = p->base + 1;
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return p;
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free(p);
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_free_list( SmsPDU*  pdus )
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdus) {
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; pdus[nn] != NULL; nn++)
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            smspdu_free( pdus[nn] );
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        free( pdus );
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSmsPDU*
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_create_deliver_utf8( const unsigned char*   utf8,
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int                    utf8len,
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            const SmsAddressRec*   sender_address,
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            const SmsTimeStampRec* timestamp )
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsTimeStampRec  ts0;
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int              use_gsm7;
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int              count, block;
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int              num_pdus = 0;
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int              leftover = 0;
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*          list = NULL;
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static unsigned char  ref_num = 0;
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (timestamp == NULL) {
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sms_timestamp_now( &ts0 );
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        timestamp = &ts0;
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* can we encode the message with the GSM 7-bit alphabet ? */
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    use_gsm7 = utf8_check_gsm7( utf8, utf8len );
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* count the number of SMS PDUs we'll need */
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    block = MAX_USER_DATA_SEPTETS - USER_DATA_HEADER_SIZE;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (use_gsm7) {
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count = utf8_to_gsm7( utf8, utf8len, NULL, 0 );
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count = utf8_to_ucs2( utf8, utf8len, NULL );
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        block = MAX_USER_DATA_BYTES - USER_DATA_HEADER_SIZE;
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    num_pdus = count / block;
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    leftover = count - num_pdus*block;
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (leftover > 0)
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        num_pdus += 1;
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    list = calloc( sizeof(SmsPDU*), num_pdus + 1 );
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (list == NULL)
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* now create each SMS PDU */
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cbytes_t   src     = utf8;
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cbytes_t   src_end = utf8 + utf8len;
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int        nn;
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < num_pdus; nn++)
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int       skip = block;
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cbytes_t  src_next;
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (leftover > 0 && nn == num_pdus-1)
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                skip = leftover;
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            src_next = utf8_skip_gsm7( src, src_end, skip );
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            list[nn] = smspdu_create_deliver( src, src_next - src, use_gsm7, sender_address, timestamp,
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                              ref_num, num_pdus, nn );
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (list[nn] == NULL)
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto Fail;
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            src = src_next;
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ref_num++;
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return list;
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free_list(list);
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSmsPDU
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_create_from_hex( const char*  hex, int  hexlen )
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU    p;
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cbytes_t  data;
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = calloc( sizeof(*p), 1 );
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) goto Exit;
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p->base = malloc( (hexlen+1)/2 );
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p->base == NULL) {
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        free(p);
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = NULL;
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( gsm_hex_to_bytes( (cbytes_t)hex, hexlen, p->base ) < 0 )
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p->end = p->base + (hexlen+1)/2;
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    data = p->base;
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( sms_skip_sc_address( &data, p->end ) < 0 )
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p->tpdu = (bytes_t) data;
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return p;
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free(p->base);
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free(p);
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsmspdu_to_hex( SmsPDU  pdu, char*  hex, int  hexlen )
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = (pdu->end - pdu->base)*2;
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hexlen > result)
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hexlen = result;
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn*2 < hexlen; nn++) {
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gsm_hex_from_byte( &hex[nn*2], pdu->base[nn] );
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** SMS SUBMIT RECEIVER
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ** collects one or more SMS-SUBMIT PDUs to generate a single message to deliver
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct SmsFragmentRec {
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct SmsFragmentRec*  next;
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsAddressRec           from[1];
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    byte_t                  ref;
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    byte_t                  max;
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    byte_t                  count;
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                     index;
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*                 pdus;
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} SmsFragmentRec, *SmsFragment;
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct SmsReceiverRec {
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           last;
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment   fragments;
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} SmsReceiverRec;
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_fragment_free( SmsFragment  frag )
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < frag->max; nn++) {
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (frag->pdus[nn] != NULL) {
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            smspdu_free( frag->pdus[nn] );
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            frag->pdus[nn] = NULL;
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag->pdus  = NULL;
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag->count = 0;
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag->max   = 0;
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag->index = 0;
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free( frag );
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SmsFragment
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_fragment_alloc( SmsReceiver  rec, const SmsAddressRec*  from, int   ref, int  max )
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment  frag = calloc(sizeof(*frag) + max*sizeof(SmsPDU), 1 );
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag != NULL) {
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag->from[0] = from[0];
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag->ref     = ref;
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag->max     = max;
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag->pdus    = (SmsPDU*)(frag + 1);
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag->index   = ++rec->last;
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  frag;
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSmsReceiver   sms_receiver_create( void )
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsReceiver  rec = calloc(sizeof(*rec),1);
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return rec;
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_destroy( SmsReceiver  rec )
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (rec->fragments) {
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        SmsFragment  frag = rec->fragments;
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rec->fragments = frag->next;
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sms_fragment_free(frag);
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SmsFragment*
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_find_p( SmsReceiver  rec, const SmsAddressRec*  from, int  ref )
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment*  pnode = &rec->fragments;
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment   node;
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        node = *pnode;
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (node == NULL)
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (node->ref == ref && sms_address_eq( node->from, from ))
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pnode = &node->next;
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  pnode;
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SmsFragment*
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_find_index_p( SmsReceiver  rec, int  index )
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment*  pnode = &rec->fragments;
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment   node;
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        node = *pnode;
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (node == NULL)
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (node->index == index)
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pnode = &node->next;
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  pnode;
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_add_submit_pdu( SmsReceiver  rec, SmsPDU       submit_pdu )
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsAddressRec  from[1];
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            ref, max, cur;
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment*   pnode;
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment    frag;
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( smspdu_get_receiver_address( submit_pdu, from ) < 0 ) {
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: could not extract receiver address\n", __FUNCTION__ );
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ref = smspdu_get_ref( submit_pdu );
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ref < 0) {
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: could not extract message reference from pdu\n", __FUNCTION__ );
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    max = smspdu_get_max_index( submit_pdu );
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (max < 0) {
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: invalid max fragment value: %d should be >= 1\n",
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           __FUNCTION__, max );
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pnode = sms_receiver_find_p( rec, from, ref );
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag  = *pnode;
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag == NULL) {
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag = sms_fragment_alloc( rec, from, ref, max );
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (frag == NULL) {
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D("%s: not enough memory to allocate new fragment\n", __FUNCTION__ );
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (D_ACTIVE) {
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            char  tmp[32];
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int   len;
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = sms_address_to_str( from, tmp, sizeof(tmp) );
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (len < 0) {
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                strcpy( tmp, "<unknown>" );
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = strlen(tmp);
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D("%s: created SMS index %d, from %.*s, ref %d, max %d\n", __FUNCTION__,
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               frag->index, len, tmp, frag->ref, frag->max);
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pnode = frag;
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cur = smspdu_get_cur_index( submit_pdu );
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur < 0) {
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D("%s: SMS fragment index is too small: %d should be >= 1\n", __FUNCTION__, cur+1 );
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cur >= max) {
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D("%s: SMS fragment index is too large (%d >= %d)\n", __FUNCTION__, cur, max);
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( frag->pdus[cur] != NULL ) {
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D("%s: receiving duplicate SMS fragment for %d/%d, ref=%d, discarding old one\n",
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          __FUNCTION__, cur+1, max, ref);
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        smspdu_free( frag->pdus[cur] );
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        frag->count -= 1;
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag->pdus[cur] = submit_pdu;
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    frag->count    += 1;
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag->count >= frag->max) {
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* yes, we received all fragments for this SMS */
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: SMS index %d, received all %d fragments\n", __FUNCTION__, frag->index, frag->count );
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return frag->index;
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* still waiting for more */
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: SMS index %d, received %d/%d, waiting for %d more\n", __FUNCTION__,
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            frag->index, cur+1, max, frag->max - frag->count );
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_get_text_message( SmsReceiver  rec, int  index, bytes_t  utf8, int  utf8len )
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment*  pnode = sms_receiver_find_index_p( rec, index );
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment   frag  = *pnode;
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           nn, total;
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag == NULL) {
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: invalid SMS index %d\n", __FUNCTION__, index );
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag->count != frag->max) {
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: SMS index %d still needs %d fragments\n", __FUNCTION__,
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           frag->index, frag->max - frag->count );
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* get the size of all combined text */
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    total = 0;
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; nn < frag->count; nn++ ) {
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  partial;
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (utf8 && utf8len > 0) {
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            partial  = smspdu_get_text_message( frag->pdus[nn], utf8, utf8len );
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8    += partial;
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            utf8len -= partial;
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            partial  = smspdu_get_text_message( frag->pdus[nn], NULL, 0 );
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        total += partial;
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return total;
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_remove( SmsReceiver  rec, int  index )
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment*  pnode = sms_receiver_find_index_p( rec, index );
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment   frag  = *pnode;
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag != NULL) {
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pnode = frag->next;
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sms_fragment_free(frag);
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSmsPDU*
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsms_receiver_create_deliver( SmsReceiver  rec, int  index, const SmsAddressRec*  from )
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*          result = NULL;
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment*     pnode = sms_receiver_find_index_p( rec, index );
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsFragment      frag  = *pnode;
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsTimeStampRec  now[1];
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int              nn, total;
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bytes_t          utf8;
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int              utf8len;
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag == NULL) {
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: invalid SMS index %d\n", __FUNCTION__, index );
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (frag->count != frag->max) {
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: SMS index %d still needs %d fragments\n", __FUNCTION__,
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           frag->index, frag->max - frag->count );
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* get the combined text message */
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    utf8len = sms_receiver_get_text_message( rec, index, NULL, 0 );
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (utf8len < 0)
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    utf8 = malloc( utf8len + 1 );
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (utf8 == NULL) {
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D( "%s: not enough memory to allocate %d bytes\n",
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           __FUNCTION__, utf8len+1 );
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    total = 0;
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; nn < frag->count; nn++ ) {
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        total += smspdu_get_text_message( frag->pdus[nn], utf8 + total, utf8len - total );
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sms_timestamp_now( now );
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = smspdu_create_deliver_utf8( utf8, utf8len, from, now );
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free(utf8);
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sms_receiver_remove( rec, index );
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1658