aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-02-01 22:30:20 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:15:00 +0100
commit1eb7f60e4cee9295980d14de7d586a0bca24e869 (patch)
tree6ff11326efea8c966da0f97ad4b181ceb46c567d /src
parent6f103c136660eee618d6b38c69d3ba91e3b41921 (diff)
sms: assemble and export the SMS when its completed
Diffstat (limited to 'src')
-rw-r--r--src/mm-sms-list.c35
-rw-r--r--src/mm-sms.c114
-rw-r--r--src/mm-sms.h9
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,