sms: handle text mode SMS listing
Undoubtedly we'll need to adjust the regex but this works for now.
This commit is contained in:
@@ -1489,9 +1489,8 @@ sms_cache_lookup_full (MMModem *modem,
|
|||||||
mpm = g_hash_table_lookup (priv->sms_parts,
|
mpm = g_hash_table_lookup (priv->sms_parts,
|
||||||
GUINT_TO_POINTER (refnum));
|
GUINT_TO_POINTER (refnum));
|
||||||
if (mpm == NULL) {
|
if (mpm == NULL) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"Internal error - no multipart structure for multipart SMS");
|
||||||
"Internal error - no multipart structure for multipart SMS");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1508,19 +1507,17 @@ sms_cache_lookup_full (MMModem *modem,
|
|||||||
part = g_hash_table_lookup (priv->sms_contents,
|
part = g_hash_table_lookup (priv->sms_contents,
|
||||||
GUINT_TO_POINTER (mpm->parts[i]));
|
GUINT_TO_POINTER (mpm->parts[i]));
|
||||||
if (part == NULL) {
|
if (part == NULL) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"Internal error - part %d (index %d) is missing",
|
||||||
"Internal error - part %d (index %d) is missing",
|
i, mpm->parts[i]);
|
||||||
i, mpm->parts[i]);
|
|
||||||
g_free (textparts);
|
g_free (textparts);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
text = g_hash_table_lookup (part, "text");
|
text = g_hash_table_lookup (part, "text");
|
||||||
if (text == NULL) {
|
if (text == NULL) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"Internal error - part %d (index %d) has no text element",
|
||||||
"Internal error - part %d (index %d) has no text element",
|
i, mpm->parts[i]);
|
||||||
i, mpm->parts[i]);
|
|
||||||
g_free (textparts);
|
g_free (textparts);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -4882,8 +4879,7 @@ sms_get_done (MMAtSerialPort *port,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_insert (properties, "index",
|
g_hash_table_insert (properties, "index", simple_uint_value (idx));
|
||||||
simple_uint_value (idx));
|
|
||||||
sms_cache_insert (info->modem, properties, idx);
|
sms_cache_insert (info->modem, properties, idx);
|
||||||
|
|
||||||
look_for_complete = GPOINTER_TO_UINT (mm_callback_info_get_data(info,
|
look_for_complete = GPOINTER_TO_UINT (mm_callback_info_get_data(info,
|
||||||
@@ -5125,6 +5121,168 @@ sms_delete (MMModemGsmSms *modem,
|
|||||||
user_data);
|
user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
pdu_parse_cmgl (MMGenericGsm *self, const char *response, GError **error)
|
||||||
|
{
|
||||||
|
int rv, status, tpdu_len, offset;
|
||||||
|
GHashTable *properties;
|
||||||
|
|
||||||
|
while (*response) {
|
||||||
|
int idx;
|
||||||
|
char pdu[SMS_MAX_PDU_LEN + 1];
|
||||||
|
|
||||||
|
rv = sscanf (response, "+CMGL: %d,%d,,%d %344s %n",
|
||||||
|
&idx, &status, &tpdu_len, pdu, &offset);
|
||||||
|
if (4 != rv) {
|
||||||
|
g_set_error (error,
|
||||||
|
MM_MODEM_ERROR,
|
||||||
|
MM_MODEM_ERROR_GENERAL,
|
||||||
|
"Failed to parse CMGL response: expected 4 results got %d", rv);
|
||||||
|
mm_err("Couldn't parse response to SMS LIST (%d)", rv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
response += offset;
|
||||||
|
|
||||||
|
properties = sms_parse_pdu (pdu, NULL);
|
||||||
|
if (properties) {
|
||||||
|
g_hash_table_insert (properties, "index", simple_uint_value (idx));
|
||||||
|
sms_cache_insert (MM_MODEM (self), properties, idx);
|
||||||
|
/* The cache holds a reference, so we don't need it anymore */
|
||||||
|
g_hash_table_unref (properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_match_uint (GMatchInfo *m, guint match_index, guint *out_val)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
unsigned long num;
|
||||||
|
|
||||||
|
g_return_val_if_fail (out_val != NULL, FALSE);
|
||||||
|
|
||||||
|
s = g_match_info_fetch (m, match_index);
|
||||||
|
g_return_val_if_fail (s != NULL, FALSE);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
num = strtoul (s, NULL, 10);
|
||||||
|
g_free (s);
|
||||||
|
|
||||||
|
if (num <= 1000 && errno == 0) {
|
||||||
|
*out_val = (guint) num;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_match_string_unquoted (GMatchInfo *m, guint match_index)
|
||||||
|
{
|
||||||
|
char *s, *p, *q, *ret = NULL;
|
||||||
|
|
||||||
|
q = s = g_match_info_fetch (m, match_index);
|
||||||
|
g_return_val_if_fail (s != NULL, FALSE);
|
||||||
|
|
||||||
|
/* remove quotes */
|
||||||
|
if (*q == '"')
|
||||||
|
q++;
|
||||||
|
p = strchr (q, '"');
|
||||||
|
if (p)
|
||||||
|
*p = '\0';
|
||||||
|
if (*q)
|
||||||
|
ret = g_strdup (q);
|
||||||
|
g_free (s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
text_parse_cmgl (MMGenericGsm *self, const char *response, GError **error)
|
||||||
|
{
|
||||||
|
GRegex *r;
|
||||||
|
GMatchInfo *match_info = NULL;
|
||||||
|
|
||||||
|
/* +CMGL: <index>,<stat>,<oa/da>,[alpha],<scts><CR><LF><data><CR><LF> */
|
||||||
|
r = g_regex_new ("\\+CMGL:\\s*(\\d+)\\s*,\\s*([^,]*),\\s*([^,]*),\\s*([^,]*),\\s*([^\\r\\n]*)\\r\\n(.*)\\r\\n", 0, 0, NULL);
|
||||||
|
g_assert (r);
|
||||||
|
|
||||||
|
if (!g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) {
|
||||||
|
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
|
"Failed to parse CMGL response");
|
||||||
|
mm_err("Couldn't parse response to SMS LIST");
|
||||||
|
g_regex_unref (r);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g_match_info_matches (match_info)) {
|
||||||
|
GHashTable *properties;
|
||||||
|
guint matches, idx;
|
||||||
|
char *number = NULL, *timestamp, *text, *ucs2_text;
|
||||||
|
gsize ucs2_len = 0;
|
||||||
|
GByteArray *data;
|
||||||
|
|
||||||
|
matches = g_match_info_get_match_count (match_info);
|
||||||
|
if (matches != 7) {
|
||||||
|
mm_dbg ("Failed to match entire CMGL response (count %d)", matches);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!get_match_uint (match_info, 1, &idx)) {
|
||||||
|
mm_dbg ("Failed to convert message index");
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* <stat is ignored for now> */
|
||||||
|
|
||||||
|
number = get_match_string_unquoted (match_info, 3);
|
||||||
|
if (!number) {
|
||||||
|
mm_dbg ("Failed to get message sender number");
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp = get_match_string_unquoted (match_info, 5);
|
||||||
|
|
||||||
|
text = g_match_info_fetch (match_info, 6);
|
||||||
|
/* FIXME: Text is going to be in the character set we've set with +CSCS */
|
||||||
|
|
||||||
|
/* The raw SMS data can only be GSM, UCS2, or unknown (8-bit), so we
|
||||||
|
* need to convert to UCS2 here.
|
||||||
|
*/
|
||||||
|
ucs2_text = g_convert (text, -1, "UCS-2BE//TRANSLIT", "UTF-8", NULL, &ucs2_len, NULL);
|
||||||
|
g_assert (ucs2_text);
|
||||||
|
data = g_byte_array_sized_new (ucs2_len);
|
||||||
|
g_byte_array_append (data, (const guint8 *) ucs2_text, ucs2_len);
|
||||||
|
g_free (ucs2_text);
|
||||||
|
|
||||||
|
properties = sms_properties_hash_new (NULL,
|
||||||
|
number,
|
||||||
|
timestamp,
|
||||||
|
text,
|
||||||
|
data,
|
||||||
|
2, /* DCS = UCS2 */
|
||||||
|
0); /* class */
|
||||||
|
g_assert (properties);
|
||||||
|
|
||||||
|
g_free (number);
|
||||||
|
g_free (timestamp);
|
||||||
|
g_free (text);
|
||||||
|
g_byte_array_free (data, TRUE);
|
||||||
|
|
||||||
|
g_hash_table_insert (properties, "index", simple_uint_value (idx));
|
||||||
|
sms_cache_insert (MM_MODEM (self), properties, idx);
|
||||||
|
/* The cache holds a reference, so we don't need it anymore */
|
||||||
|
g_hash_table_unref (properties);
|
||||||
|
|
||||||
|
next:
|
||||||
|
g_match_info_next (match_info, NULL);
|
||||||
|
}
|
||||||
|
g_match_info_free (match_info);
|
||||||
|
|
||||||
|
g_regex_unref (r);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_list_results (gpointer data)
|
free_list_results (gpointer data)
|
||||||
{
|
{
|
||||||
@@ -5141,12 +5299,12 @@ sms_list_done (MMAtSerialPort *port,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
|
MMGenericGsm *self = MM_GENERIC_GSM (info->modem);
|
||||||
GPtrArray *results = NULL;
|
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
|
||||||
int rv, status, tpdu_len, offset;
|
|
||||||
char *rstr;
|
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
GHashTable *properties = NULL;
|
GHashTable *properties = NULL;
|
||||||
|
GPtrArray *results = NULL;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
/* If the modem has already been removed, return without
|
/* If the modem has already been removed, return without
|
||||||
* scheduling callback */
|
* scheduling callback */
|
||||||
@@ -5159,47 +5317,28 @@ sms_list_done (MMAtSerialPort *port,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
results = g_ptr_array_new ();
|
if (priv->sms_pdu_mode)
|
||||||
rstr = response->str;
|
success = pdu_parse_cmgl (self, response->str, &info->error);
|
||||||
while (*rstr) {
|
else
|
||||||
GError *local;
|
success = text_parse_cmgl (self, response->str, &info->error);
|
||||||
int idx;
|
|
||||||
char pdu[SMS_MAX_PDU_LEN + 1];
|
|
||||||
|
|
||||||
rv = sscanf (rstr, "+CMGL: %d,%d,,%d %344s %n",
|
if (success) {
|
||||||
&idx, &status, &tpdu_len, pdu, &offset);
|
results = g_ptr_array_new ();
|
||||||
if (4 != rv) {
|
|
||||||
mm_err("Couldn't parse response to SMS LIST (%d)", rv);
|
/* Add all the complete messages to the results */
|
||||||
break;
|
g_hash_table_iter_init (&iter, priv->sms_contents);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &properties)) {
|
||||||
|
g_hash_table_ref (properties);
|
||||||
|
g_clear_error (&info->error);
|
||||||
|
properties = sms_cache_lookup_full (info->modem, properties, NULL);
|
||||||
|
if (properties)
|
||||||
|
g_ptr_array_add (results, properties);
|
||||||
}
|
}
|
||||||
rstr += offset;
|
|
||||||
|
|
||||||
properties = sms_parse_pdu (pdu, &local);
|
if (results)
|
||||||
if (properties) {
|
mm_callback_info_set_data (info, "list-sms", results, free_list_results);
|
||||||
g_hash_table_insert (properties, "index",
|
|
||||||
simple_uint_value (idx));
|
|
||||||
sms_cache_insert (info->modem, properties, idx);
|
|
||||||
/* The cache holds a reference, so we don't need it anymore */
|
|
||||||
g_hash_table_unref (properties);
|
|
||||||
} else {
|
|
||||||
/* Ignore the error */
|
|
||||||
g_clear_error(&local);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add all the complete messages to the results */
|
|
||||||
properties = NULL;
|
|
||||||
g_hash_table_iter_init (&iter, priv->sms_contents);
|
|
||||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &properties)) {
|
|
||||||
g_hash_table_ref (properties);
|
|
||||||
g_clear_error (&info->error);
|
|
||||||
properties = sms_cache_lookup_full (info->modem, properties, &info->error);
|
|
||||||
if (properties)
|
|
||||||
g_ptr_array_add (results, properties);
|
|
||||||
}
|
|
||||||
if (results)
|
|
||||||
mm_callback_info_set_data (info, "list-sms", results, free_list_results);
|
|
||||||
|
|
||||||
mm_callback_info_schedule (info);
|
mm_callback_info_schedule (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -345,6 +345,39 @@ byte_array_value (const GByteArray *array)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHashTable *
|
||||||
|
sms_properties_hash_new (const char *smsc,
|
||||||
|
const char *number,
|
||||||
|
const char *timestamp,
|
||||||
|
const char *text,
|
||||||
|
const GByteArray *data,
|
||||||
|
guint data_coding_scheme,
|
||||||
|
guint *class)
|
||||||
|
{
|
||||||
|
GHashTable *properties;
|
||||||
|
|
||||||
|
g_return_val_if_fail (number != NULL, NULL);
|
||||||
|
g_return_val_if_fail (text != NULL, NULL);
|
||||||
|
g_return_val_if_fail (data != NULL, NULL);
|
||||||
|
|
||||||
|
properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue);
|
||||||
|
g_hash_table_insert (properties, "number", simple_string_value (number));
|
||||||
|
g_hash_table_insert (properties, "data", byte_array_value (data));
|
||||||
|
g_hash_table_insert (properties, "data-coding-scheme", simple_uint_value (data_coding_scheme));
|
||||||
|
g_hash_table_insert (properties, "text", simple_string_value (text));
|
||||||
|
|
||||||
|
if (smsc)
|
||||||
|
g_hash_table_insert (properties, "smsc", simple_string_value (smsc));
|
||||||
|
|
||||||
|
if (timestamp)
|
||||||
|
g_hash_table_insert (properties, "timestamp", simple_string_value (timestamp));
|
||||||
|
|
||||||
|
if (class)
|
||||||
|
g_hash_table_insert (properties, "class", simple_uint_value (*class));
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
GHashTable *
|
GHashTable *
|
||||||
sms_parse_pdu (const char *hexpdu, GError **error)
|
sms_parse_pdu (const char *hexpdu, GError **error)
|
||||||
{
|
{
|
||||||
@@ -358,13 +391,14 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
char *smsc_addr, *sender_addr, *sc_timestamp, *msg_text;
|
char *smsc_addr, *sender_addr, *sc_timestamp, *msg_text;
|
||||||
SmsEncoding user_data_encoding;
|
SmsEncoding user_data_encoding;
|
||||||
GByteArray *pdu_data;
|
GByteArray *pdu_data;
|
||||||
|
guint concat_ref = 0, concat_max = 0, concat_seq = 0, msg_class = 0;
|
||||||
|
gboolean multipart = FALSE, class_valid = FALSE;
|
||||||
|
|
||||||
/* Convert PDU from hex to binary */
|
/* Convert PDU from hex to binary */
|
||||||
pdu = (guint8 *) utils_hexstr2bin (hexpdu, &pdu_len);
|
pdu = (guint8 *) utils_hexstr2bin (hexpdu, &pdu_len);
|
||||||
if (!pdu) {
|
if (!pdu) {
|
||||||
*error = g_error_new_literal (MM_MODEM_ERROR,
|
g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"Couldn't parse PDU of SMS GET response from hex");
|
||||||
"Couldn't parse PDU of SMS GET response from hex");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,10 +406,10 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
smsc_addr_num_octets = pdu[0];
|
smsc_addr_num_octets = pdu[0];
|
||||||
variable_length_items = smsc_addr_num_octets;
|
variable_length_items = smsc_addr_num_octets;
|
||||||
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
|
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"PDU too short (1): %zd vs %d",
|
||||||
"PDU too short (1): %zd vs %d", pdu_len,
|
pdu_len,
|
||||||
variable_length_items + SMS_MIN_PDU_LEN);
|
variable_length_items + SMS_MIN_PDU_LEN);
|
||||||
g_free (pdu);
|
g_free (pdu);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -390,10 +424,10 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
sender_addr_num_octets = (sender_addr_num_digits + 1) >> 1;
|
sender_addr_num_octets = (sender_addr_num_digits + 1) >> 1;
|
||||||
variable_length_items += sender_addr_num_octets;
|
variable_length_items += sender_addr_num_octets;
|
||||||
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
|
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"PDU too short (2): %zd vs %d",
|
||||||
"PDU too short (2): %zd vs %d", pdu_len,
|
pdu_len,
|
||||||
variable_length_items + SMS_MIN_PDU_LEN);
|
variable_length_items + SMS_MIN_PDU_LEN);
|
||||||
g_free (pdu);
|
g_free (pdu);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -410,43 +444,23 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
else
|
else
|
||||||
variable_length_items += user_data_len;
|
variable_length_items += user_data_len;
|
||||||
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
|
if (pdu_len < variable_length_items + SMS_MIN_PDU_LEN) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"PDU too short (3): %zd vs %d",
|
||||||
"PDU too short (3): %zd vs %d", pdu_len,
|
pdu_len,
|
||||||
variable_length_items + SMS_MIN_PDU_LEN);
|
variable_length_items + SMS_MIN_PDU_LEN);
|
||||||
g_free (pdu);
|
g_free (pdu);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only handle SMS-DELIVER */
|
/* Only handle SMS-DELIVER */
|
||||||
if ((pdu[msg_start_offset] & SMS_TP_MTI_MASK) != SMS_TP_MTI_SMS_DELIVER) {
|
if ((pdu[msg_start_offset] & SMS_TP_MTI_MASK) != SMS_TP_MTI_SMS_DELIVER) {
|
||||||
*error = g_error_new (MM_MODEM_ERROR,
|
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
"Unhandled message type: 0x%02x",
|
||||||
"Unhandled message type: 0x%02x",
|
pdu[msg_start_offset]);
|
||||||
pdu[msg_start_offset]);
|
|
||||||
g_free (pdu);
|
g_free (pdu);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
|
|
||||||
simple_free_gvalue);
|
|
||||||
|
|
||||||
smsc_addr = sms_decode_address (&pdu[1], 2 * (pdu[0] - 1));
|
|
||||||
g_hash_table_insert (properties, "smsc",
|
|
||||||
simple_string_value (smsc_addr));
|
|
||||||
g_free (smsc_addr);
|
|
||||||
|
|
||||||
sender_addr = sms_decode_address (&pdu[msg_start_offset + 2],
|
|
||||||
pdu[msg_start_offset + 1]);
|
|
||||||
g_hash_table_insert (properties, "number",
|
|
||||||
simple_string_value (sender_addr));
|
|
||||||
g_free (sender_addr);
|
|
||||||
|
|
||||||
sc_timestamp = sms_decode_timestamp (&pdu[tp_dcs_offset + 1]);
|
|
||||||
g_hash_table_insert (properties, "timestamp",
|
|
||||||
simple_string_value (sc_timestamp));
|
|
||||||
g_free (sc_timestamp);
|
|
||||||
|
|
||||||
bit_offset = 0;
|
bit_offset = 0;
|
||||||
if (pdu[msg_start_offset] & SMS_TP_UDHI) {
|
if (pdu[msg_start_offset] & SMS_TP_UDHI) {
|
||||||
int udhl, end, offset;
|
int udhl, end, offset;
|
||||||
@@ -470,12 +484,10 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
pdu[offset + 2] > pdu[offset + 1])
|
pdu[offset + 2] > pdu[offset + 1])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
g_hash_table_insert (properties, "concat-reference",
|
concat_ref = pdu[offset];
|
||||||
simple_uint_value (pdu[offset]));
|
concat_max = pdu[offset + 1];
|
||||||
g_hash_table_insert (properties, "concat-max",
|
concat_seq = pdu[offset + 2];
|
||||||
simple_uint_value (pdu[offset + 1]));
|
multipart = TRUE;
|
||||||
g_hash_table_insert (properties, "concat-sequence",
|
|
||||||
simple_uint_value (pdu[offset + 2]));
|
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
/* Concatenated short message, 16-bit reference */
|
/* Concatenated short message, 16-bit reference */
|
||||||
@@ -483,14 +495,10 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
pdu[offset + 3] > pdu[offset + 2])
|
pdu[offset + 3] > pdu[offset + 2])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
g_hash_table_insert (properties, "concat-reference",
|
concat_ref = (pdu[offset] << 8) | pdu[offset + 1];
|
||||||
simple_uint_value (
|
concat_max = pdu[offset + 2];
|
||||||
(pdu[offset] << 8)
|
concat_seq = pdu[offset + 3];
|
||||||
| pdu[offset + 1]));
|
multipart = TRUE;
|
||||||
g_hash_table_insert (properties, "concat-max",
|
|
||||||
simple_uint_value (pdu[offset + 2]));
|
|
||||||
g_hash_table_insert (properties, "concat-sequence",
|
|
||||||
simple_uint_value (pdu[offset + 3]));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,21 +533,39 @@ sms_parse_pdu (const char *hexpdu, GError **error)
|
|||||||
user_data_encoding, bit_offset);
|
user_data_encoding, bit_offset);
|
||||||
g_warn_if_fail (msg_text != NULL);
|
g_warn_if_fail (msg_text != NULL);
|
||||||
}
|
}
|
||||||
g_hash_table_insert (properties, "text", simple_string_value (msg_text));
|
|
||||||
g_free (msg_text);
|
|
||||||
|
|
||||||
/* Add the raw PDU data */
|
/* Raw PDU data */
|
||||||
pdu_data = g_byte_array_sized_new (user_data_len);
|
pdu_data = g_byte_array_sized_new (user_data_len);
|
||||||
g_byte_array_append (pdu_data, &pdu[user_data_offset], user_data_len);
|
g_byte_array_append (pdu_data, &pdu[user_data_offset], user_data_len);
|
||||||
g_hash_table_insert (properties, "data", byte_array_value (pdu_data));
|
|
||||||
g_byte_array_free (pdu_data, TRUE);
|
|
||||||
g_hash_table_insert (properties, "data-coding-scheme",
|
|
||||||
simple_uint_value (pdu[tp_dcs_offset] & 0xFF));
|
|
||||||
|
|
||||||
if (pdu[tp_dcs_offset] & SMS_DCS_CLASS_VALID)
|
if (pdu[tp_dcs_offset] & SMS_DCS_CLASS_VALID) {
|
||||||
g_hash_table_insert (properties, "class",
|
msg_class = pdu[tp_dcs_offset] & SMS_DCS_CLASS_MASK;
|
||||||
simple_uint_value (pdu[tp_dcs_offset] &
|
class_valid = TRUE;
|
||||||
SMS_DCS_CLASS_MASK));
|
}
|
||||||
|
|
||||||
|
smsc_addr = sms_decode_address (&pdu[1], 2 * (pdu[0] - 1));
|
||||||
|
sender_addr = sms_decode_address (&pdu[msg_start_offset + 2], pdu[msg_start_offset + 1]);
|
||||||
|
sc_timestamp = sms_decode_timestamp (&pdu[tp_dcs_offset + 1]);
|
||||||
|
|
||||||
|
properties = sms_properties_hash_new (smsc_addr,
|
||||||
|
sender_addr,
|
||||||
|
sc_timestamp,
|
||||||
|
msg_text,
|
||||||
|
pdu_data,
|
||||||
|
pdu[tp_dcs_offset] & 0xFF,
|
||||||
|
class_valid ? &msg_class : NULL);
|
||||||
|
g_assert (properties);
|
||||||
|
if (multipart) {
|
||||||
|
g_hash_table_insert (properties, "concat-reference", simple_uint_value (concat_ref));
|
||||||
|
g_hash_table_insert (properties, "concat-max", simple_uint_value (concat_max));
|
||||||
|
g_hash_table_insert (properties, "concat-sequence", simple_uint_value (concat_seq));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (smsc_addr);
|
||||||
|
g_free (sender_addr);
|
||||||
|
g_free (sc_timestamp);
|
||||||
|
g_free (msg_text);
|
||||||
|
g_byte_array_free (pdu_data, TRUE);
|
||||||
g_free (pdu);
|
g_free (pdu);
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
|
@@ -31,6 +31,14 @@ guint8 *sms_create_submit_pdu (const char *number,
|
|||||||
guint *out_msgstart,
|
guint *out_msgstart,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GHashTable *sms_properties_hash_new (const char *smsc,
|
||||||
|
const char *number,
|
||||||
|
const char *timestamp,
|
||||||
|
const char *text,
|
||||||
|
const GByteArray *data,
|
||||||
|
guint data_coding_scheme,
|
||||||
|
guint *class);
|
||||||
|
|
||||||
/* For testcases only */
|
/* For testcases only */
|
||||||
guint sms_encode_address (const char *address,
|
guint sms_encode_address (const char *address,
|
||||||
guint8 *buf,
|
guint8 *buf,
|
||||||
|
Reference in New Issue
Block a user