aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2012-08-27 17:36:49 -0500
committerDan Williams <dcbw@redhat.com>2012-08-27 17:36:49 -0500
commitf3a33ecc452d47647ed19a763ba4915f1e356d3c (patch)
treec8a925cbca952a393aca3551d5be64911d4d9bb9
parentcf172a90fa9e1008d3d4c03d30ab72f7993055e1 (diff)
sms: fix handling of 'data' property for multipart messages
Text was getting concatenated when reconstructing the full message, but the data wasn't. That meant that non-text multipart messages, like the binary APN/MMS settings messages that operators often send, were broken.
-rw-r--r--src/mm-generic-gsm.c89
1 files changed, 51 insertions, 38 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 6651b2d7..a1a4af35 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -196,6 +196,7 @@ static void clck_cb (MMAtSerialPort *port,
#define GS_HASH_TAG "get-sms"
static GValue *simple_string_value (const char *str);
static GValue *simple_uint_value (guint32 i);
+static GValue *simple_byte_array_value (const GByteArray *array);
static void simple_free_gvalue (gpointer data);
MMModem *
@@ -1470,10 +1471,10 @@ sms_cache_lookup_full (MMModem *modem,
SMSMultiPartMessage *mpm;
GHashTable *full, *part, *first;
GHashTableIter iter;
- gpointer key, value;
- char *fulltext;
- char **textparts;
- GValue *ref, *idx, *text;
+ GByteArray *fulldata, *partdata;
+ GValue *ref, *idx, *text, *data, *value;
+ GString *fulltext;
+ const char *key;
ref = g_hash_table_lookup (properties, "concat-reference");
if (ref == NULL)
@@ -1505,7 +1506,8 @@ sms_cache_lookup_full (MMModem *modem,
return NULL;
/* Complete multipart message is present. Assemble it */
- textparts = g_malloc0((1 + mpm->numparts) * sizeof (*textparts));
+ fulltext = g_string_new ("");
+ fulldata = g_byte_array_sized_new (160 * mpm->numparts);
for (i = 0 ; i < mpm->numparts ; i++) {
part = g_hash_table_lookup (priv->sms_contents,
GUINT_TO_POINTER (mpm->parts[i]));
@@ -1513,54 +1515,53 @@ sms_cache_lookup_full (MMModem *modem,
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Internal error - part %d (index %d) is missing",
i, mpm->parts[i]);
- g_free (textparts);
+ g_string_free (fulltext, TRUE);
+ g_byte_array_free (fulldata, TRUE);
return NULL;
}
text = g_hash_table_lookup (part, "text");
- if (text == NULL) {
+ data = g_hash_table_lookup (part, "data");
+ if (!text || !data) {
g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Internal error - part %d (index %d) has no text element",
+ "Internal error - part %d (index %d) has no text or data element",
i, mpm->parts[i]);
- g_free (textparts);
+ g_string_free (fulltext, TRUE);
+ g_byte_array_free (fulldata, TRUE);
return NULL;
}
- textparts[i] = g_value_dup_string (text);
+
+ g_string_append (fulltext, g_value_get_string (text));
+ partdata = g_value_get_boxed (data);
+ g_byte_array_append (fulldata, partdata->data, partdata->len);
}
- textparts[i] = NULL;
- fulltext = g_strjoinv (NULL, textparts);
- g_strfreev (textparts);
- first = g_hash_table_lookup (priv->sms_contents,
- GUINT_TO_POINTER (mpm->parts[0]));
- full = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- simple_free_gvalue);
+ first = g_hash_table_lookup (priv->sms_contents, GUINT_TO_POINTER (mpm->parts[0]));
+ full = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, simple_free_gvalue);
+
g_hash_table_iter_init (&iter, first);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- const char *keystr = key;
- if (strncmp (keystr, "concat-", 7) == 0)
- continue;
- if (strcmp (keystr, "text") == 0 ||
- strcmp (keystr, "index") == 0)
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
+ GValue *newval;
+
+ /* Ignore hidden keys or ones we need to construct */
+ if (strncmp (key, "concat-", 7) == 0 ||
+ strcmp (key, "text") == 0 ||
+ strcmp (key, "data") == 0 ||
+ strcmp (key, "index") == 0)
continue;
- if (strcmp (keystr, "class") == 0) {
- GValue *val;
- val = g_slice_new0 (GValue);
- g_value_init (val, G_TYPE_UINT);
- g_value_copy (value, val);
- g_hash_table_insert (full, key, val);
- } else {
- GValue *val;
- val = g_slice_new0 (GValue);
- g_value_init (val, G_VALUE_TYPE (value));
- g_value_copy (value, val);
- g_hash_table_insert (full, key, val);
- }
+
+ /* Copy value to complete message hash */
+ newval = g_slice_new0 (GValue);
+ g_value_init (newval, G_VALUE_TYPE (value));
+ g_value_copy (value, newval);
+ g_hash_table_insert (full, (gpointer) key, newval);
}
g_hash_table_insert (full, "index", simple_uint_value (mpm->index));
- g_hash_table_insert (full, "text", simple_string_value (fulltext));
- g_free (fulltext);
+ g_hash_table_insert (full, "text", simple_string_value (fulltext->str));
+ g_hash_table_insert (full, "data", simple_byte_array_value (fulldata));
+ g_string_free (fulltext, TRUE);
+ g_byte_array_free (fulldata, TRUE);
return full;
}
@@ -6341,6 +6342,18 @@ simple_string_value (const char *str)
return val;
}
+static GValue *
+simple_byte_array_value (const GByteArray *array)
+{
+ GValue *val;
+
+ val = g_slice_new0 (GValue);
+ g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY);
+ g_value_set_boxed (val, array);
+
+ return val;
+}
+
#define SS_HASH_TAG "simple-get-status"
static void