diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-02-01 22:30:20 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:15:00 +0100 |
commit | 1eb7f60e4cee9295980d14de7d586a0bca24e869 (patch) | |
tree | 6ff11326efea8c966da0f97ad4b181ceb46c567d /src | |
parent | 6f103c136660eee618d6b38c69d3ba91e3b41921 (diff) |
sms: assemble and export the SMS when its completed
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-sms-list.c | 35 | ||||
-rw-r--r-- | src/mm-sms.c | 114 | ||||
-rw-r--r-- | src/mm-sms.h | 9 |
3 files changed, 138 insertions, 20 deletions
diff --git a/src/mm-sms-list.c b/src/mm-sms-list.c index 6b1082d6..dd709b66 100644 --- a/src/mm-sms-list.c +++ b/src/mm-sms-list.c @@ -184,12 +184,21 @@ take_singlepart (MMSmsList *self, gboolean received) { MMSms *sms; + GError *error = NULL; - sms = mm_sms_new (self->priv->modem, part); - self->priv->list = g_list_prepend (self->priv->list, sms); - g_signal_emit (self, signals[SIGNAL_ADDED], 0, - mm_sms_get_path (sms), - received); + sms = mm_sms_new (self->priv->modem, + received, + part, + &error); + if (!sms) { + mm_warn ("Couldn't create single-part SMS: '%s'", error->message); + g_error_free (error); + } else { + self->priv->list = g_list_prepend (self->priv->list, sms); + g_signal_emit (self, signals[SIGNAL_ADDED], 0, + mm_sms_get_path (sms), + received); + } } static gboolean @@ -214,15 +223,23 @@ take_multipart (MMSmsList *self, } else { /* Create new Multipart */ sms = mm_sms_multipart_new (self->priv->modem, + received, concat_reference, mm_sms_part_get_concat_max (part), - part); + part, + error); + if (!sms) + return FALSE; + self->priv->list = g_list_prepend (self->priv->list, sms); - g_signal_emit (self, signals[SIGNAL_ADDED], 0, - mm_sms_get_path (sms), - received); } + /* Check if completed and assembled */ + if (mm_sms_multipart_is_complete (sms) && + mm_sms_multipart_is_assembled (sms)) + g_signal_emit (self, signals[SIGNAL_ADDED], 0, + mm_sms_get_path (sms)); + return TRUE; } diff --git a/src/mm-sms.c b/src/mm-sms.c index 241dd9ae..5c5b9e62 100644 --- a/src/mm-sms.c +++ b/src/mm-sms.c @@ -63,6 +63,10 @@ struct _MMSmsPrivate { /* List of SMS parts */ guint max_parts; GList *parts; + + /* Set to true when all needed parts were received, + * parsed and assembled */ + gboolean is_assembled; }; /*****************************************************************************/ @@ -136,6 +140,12 @@ mm_sms_multipart_is_complete (MMSms *self) return (g_list_length (self->priv->parts) == self->priv->max_parts); } +gboolean +mm_sms_multipart_is_assembled (MMSms *self) +{ + return self->priv->is_assembled; +} + /*****************************************************************************/ static guint @@ -268,6 +278,67 @@ mm_sms_delete_parts (MMSms *self, /*****************************************************************************/ +static gboolean +assemble_sms (MMSms *self, + GError **error) +{ + GList *l; + gchar **textparts; + guint idx; + gchar *fulltext; + MMSmsPart *first = NULL; + + /* Assemble text from all parts */ + textparts = g_malloc0 ((1 + self->priv->max_parts) * sizeof (* textparts)); + for (l = self->priv->parts; l; l = g_list_next (l)) { + idx = mm_sms_part_get_concat_sequence ((MMSmsPart *)l->data); + if (textparts[idx]) { + mm_warn ("Duplicate part index (%u) found, ignoring", idx); + continue; + } + /* NOTE! we don't strdup here */ + textparts[idx] = (gchar *)mm_sms_part_get_text ((MMSmsPart *)l->data); + + /* If first in multipart, keep it for later */ + if (idx == 0) + first = (MMSmsPart *)l->data; + } + + /* Check if we have all parts */ + for (idx = 0; idx < self->priv->max_parts; idx++) { + if (!textparts[idx]) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Cannot assemble SMS, missing part at index %u", + idx); + g_free (textparts); + return FALSE; + } + } + + /* If we got all parts, we also have the first one always */ + g_assert (first != NULL); + + /* If we got everything, assemble the text! */ + fulltext = g_strjoinv (NULL, textparts); + g_object_set (self, + "text", fulltext, + "smsc", mm_sms_part_get_smsc (first), + "class", mm_sms_part_get_class (first), + "to", mm_sms_part_get_number (first), + "timestamp", mm_sms_part_get_timestamp (first), + NULL); + g_free (fulltext); + g_free (textparts); + + self->priv->is_assembled = TRUE; + + return TRUE; +} + +/*****************************************************************************/ + static guint cmp_sms_part_sequence (MMSmsPart *a, MMSmsPart *b) @@ -323,33 +394,58 @@ mm_sms_multipart_take_part (MMSms *self, part, (GCompareFunc)cmp_sms_part_sequence); + /* We only populate contents when the multipart SMS is complete */ + if (mm_sms_multipart_is_complete (self)) { + GError *inner_error = NULL; + + if (!assemble_sms (self, &inner_error)) { + /* We DO NOT propagate the error. The part was properly taken + * so ownership passed to the MMSms object. */ + mm_warn ("Couldn't assemble SMS: '%s'", + inner_error->message); + g_error_free (inner_error); + } else + /* Only export once properly assembled */ + mm_sms_export (self); + } + return TRUE; } MMSms * mm_sms_new (MMBaseModem *modem, - MMSmsPart *part) + gboolean received, + MMSmsPart *part, + GError **error) { MMSms *self; self = g_object_new (MM_TYPE_SMS, MM_SMS_MODEM, modem, + "state", (received ? + MM_MODEM_SMS_STATE_RECEIVED : + MM_MODEM_SMS_STATE_STORED), NULL); /* Keep the single part in the list */ self->priv->parts = g_list_prepend (self->priv->parts, part); - /* Only export once properly created */ - mm_sms_export (self); + if (!assemble_sms (self, error)) + g_clear_object (&self); + else + /* Only export once properly created */ + mm_sms_export (self); return self; } MMSms * mm_sms_multipart_new (MMBaseModem *modem, + gboolean received, guint reference, guint max_parts, - MMSmsPart *first_part) + MMSmsPart *first_part, + GError **error) { MMSms *self; @@ -358,13 +454,13 @@ mm_sms_multipart_new (MMBaseModem *modem, MM_SMS_IS_MULTIPART, TRUE, MM_SMS_MAX_PARTS, max_parts, MM_SMS_MULTIPART_REFERENCE, reference, + "state", (received ? + MM_MODEM_SMS_STATE_RECEIVED : + MM_MODEM_SMS_STATE_STORED), NULL); - /* Add the first part to the list */ - self->priv->parts = g_list_prepend (self->priv->parts, first_part); - - /* Only export once properly created */ - mm_sms_export (self); + if (!mm_sms_multipart_take_part (self, first_part, error)) + g_clear_object (&self); return self; } diff --git a/src/mm-sms.h b/src/mm-sms.h index 9810f5bc..dddf0fe7 100644 --- a/src/mm-sms.h +++ b/src/mm-sms.h @@ -56,12 +56,16 @@ struct _MMSmsClass { GType mm_sms_get_type (void); MMSms *mm_sms_new (MMBaseModem *modem, - MMSmsPart *part); + gboolean received, + MMSmsPart *part, + GError **error); MMSms *mm_sms_multipart_new (MMBaseModem *modem, + gboolean received, guint reference, guint max_parts, - MMSmsPart *first_part); + MMSmsPart *first_part, + GError **error); gboolean mm_sms_multipart_take_part (MMSms *self, MMSmsPart *part, GError **error); @@ -75,6 +79,7 @@ gboolean mm_sms_has_part_index (MMSms *self, gboolean mm_sms_is_multipart (MMSms *self); guint mm_sms_get_multipart_reference (MMSms *self); gboolean mm_sms_multipart_is_complete (MMSms *self); +gboolean mm_sms_multipart_is_assembled (MMSms *self); void mm_sms_delete_parts (MMSms *self, GAsyncReadyCallback callback, |