summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--introspection/org.freedesktop.ModemManager1.Sms.xml6
-rw-r--r--src/mm-sms-part.c73
-rw-r--r--src/mm-sms-part.h2
-rw-r--r--src/mm-sms.c111
4 files changed, 157 insertions, 35 deletions
diff --git a/introspection/org.freedesktop.ModemManager1.Sms.xml b/introspection/org.freedesktop.ModemManager1.Sms.xml
index 534be3be4..858c98901 100644
--- a/introspection/org.freedesktop.ModemManager1.Sms.xml
+++ b/introspection/org.freedesktop.ModemManager1.Sms.xml
@@ -66,10 +66,12 @@
<!--
Text:
- Message text.
+ Message text, in UTF-8.
When sending, if the text is larger than the limit of the technology or
modem, the message will be broken into multiple parts or messages.
+
+ Note that Text and Data are never given at the same time.
-->
<property name="Text" type="s" access="read" />
@@ -80,6 +82,8 @@
When sending, if the data is larger than the limit of the technology or
modem, the message will be broken into multiple parts or messages.
+
+ Note that Text and Data are never given at the same time.
-->
<property name="Data" type="ay" access="read" />
diff --git a/src/mm-sms-part.c b/src/mm-sms-part.c
index b78e9056b..cb1ee5fa7 100644
--- a/src/mm-sms-part.c
+++ b/src/mm-sms-part.c
@@ -499,7 +499,6 @@ mm_sms_part_new_from_binary_pdu (guint index,
GError **error)
{
MMSmsPart *sms_part;
- GByteArray *raw;
guint8 pdu_type;
guint offset;
guint smsc_addr_size_bytes;
@@ -835,28 +834,34 @@ mm_sms_part_new_from_binary_pdu (guint index,
tp_user_data_size_elements -= udhl;
}
- if ( user_data_encoding == MM_SMS_ENCODING_8BIT
- || user_data_encoding == MM_SMS_ENCODING_UNKNOWN) {
- /* 8-bit encoding is usually binary data, and we have no idea what
- * actual encoding the data is in so we can't convert it.
- */
- mm_dbg ("Skipping SMS part text: 8-bit or Unknown encoding");
- mm_sms_part_set_text (sms_part, "");
- } else {
+ switch (user_data_encoding) {
+ case MM_SMS_ENCODING_GSM7:
+ case MM_SMS_ENCODING_UCS2:
/* Otherwise if it's 7-bit or UCS2 we can decode it */
- mm_dbg ("Decoding text with '%u' elements", tp_user_data_size_elements);
+ mm_dbg ("Decoding SMS text with '%u' elements", tp_user_data_size_elements);
mm_sms_part_take_text (sms_part,
sms_decode_text (&pdu[tp_user_data_offset],
tp_user_data_size_elements,
user_data_encoding,
bit_offset));
g_warn_if_fail (sms_part->text != NULL);
- }
+ break;
+
+ default:
+ {
+ GByteArray *raw;
+
+ mm_dbg ("Skipping SMS text: Unknown encoding");
- /* Add the raw PDU data */
- raw = g_byte_array_sized_new (tp_user_data_size_bytes);
- g_byte_array_append (raw, &pdu[tp_user_data_offset], tp_user_data_size_bytes);
- mm_sms_part_take_data (sms_part, raw);
+ /* 8-bit encoding is usually binary data, and we have no idea what
+ * actual encoding the data is in so we can't convert it.
+ */
+ raw = g_byte_array_sized_new (tp_user_data_size_bytes);
+ g_byte_array_append (raw, &pdu[tp_user_data_offset], tp_user_data_size_bytes);
+ mm_sms_part_take_data (sms_part, raw);
+ break;
+ }
+ }
}
return sms_part;
@@ -1238,3 +1243,41 @@ mm_sms_part_util_split_text (const gchar *text,
return out;
}
+
+GByteArray **
+mm_sms_part_util_split_data (const GByteArray *data)
+{
+ GByteArray **out;
+
+ /* Some info about the rules for splitting.
+ *
+ * The User Data can be up to 140 bytes in the SMS part:
+ * 0) If we only need one chunk, it can be of up to 140 bytes.
+ * If we need more than one chunk, these have to be of 140 - 6 = 134
+ * bytes each, as we need place for the UDH header.
+ */
+
+ if (data->len <= 140) {
+ out = g_new0 (GByteArray *, 2);
+ out[0] = g_byte_array_append (g_byte_array_sized_new (data->len),
+ data->data,
+ data->len);
+ } else {
+ guint n_chunks;
+ guint i;
+ guint j;
+
+ n_chunks = data->len / 134;
+ if (data->len % 134 != 0)
+ n_chunks ++;
+
+ out = g_new0 (GByteArray *, n_chunks + 1);
+ for (i = 0, j = 0; i < n_chunks; i++, j+= 134) {
+ out[i] = g_byte_array_append (g_byte_array_sized_new (134),
+ &data->data[j],
+ MIN (data->len - j, 134));
+ }
+ }
+
+ return out;
+}
diff --git a/src/mm-sms-part.h b/src/mm-sms-part.h
index 60e9b71e6..9b75ef14b 100644
--- a/src/mm-sms-part.h
+++ b/src/mm-sms-part.h
@@ -138,4 +138,6 @@ guint mm_sms_part_encode_address (const gchar *address,
gchar **mm_sms_part_util_split_text (const gchar *text,
MMSmsEncoding *encoding);
+GByteArray **mm_sms_part_util_split_data (const GByteArray *data);
+
#endif /* MM_SMS_PART_H */
diff --git a/src/mm-sms.c b/src/mm-sms.c
index 1bedfde81..27d8ca26b 100644
--- a/src/mm-sms.c
+++ b/src/mm-sms.c
@@ -1434,14 +1434,19 @@ mm_sms_new_from_properties (MMBaseModem *modem,
GError **error)
{
MMSmsPart *part;
- gchar **split_text;
guint n_parts;
+ const gchar *text;
MMSmsEncoding encoding;
+ gchar **split_text = NULL;
+ GByteArray *data;
+ GByteArray **split_data = NULL;
+
+ text = mm_sms_properties_get_text (properties);
+ data = mm_sms_properties_peek_data_bytearray (properties);
/* Don't create SMS from properties if either (text|data) or number is missing */
if (!mm_sms_properties_get_number (properties) ||
- (!mm_sms_properties_get_text (properties) &&
- !mm_sms_properties_get_data (properties, NULL))) {
+ (!text && !data)) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_INVALID_ARGS,
@@ -1451,9 +1456,33 @@ mm_sms_new_from_properties (MMBaseModem *modem,
return NULL;
}
- split_text = mm_sms_part_util_split_text (mm_sms_properties_get_text (properties),
- &encoding);
- n_parts = (split_text ? g_strv_length (split_text) : 0);
+ /* Don't create SMS from properties if both text and data are given */
+ if (text && data) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Cannot create SMS: both 'text' and 'data' given");
+ return NULL;
+ }
+
+ if (text) {
+ split_text = mm_sms_part_util_split_text (text, &encoding);
+ if (!split_text) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Cannot create SMS: cannot process input text");
+ return NULL;
+ }
+ n_parts = g_strv_length (split_text);
+ } else if (data) {
+ encoding = MM_SMS_ENCODING_8BIT;
+ split_data = mm_sms_part_util_split_data (data);
+ g_assert (split_data != NULL);
+ /* noop within the for */
+ for (n_parts = 0; split_data[n_parts]; n_parts++);
+ } else
+ g_assert_not_reached ();
if (n_parts > 1) {
MMSms *sms = NULL;
@@ -1461,15 +1490,37 @@ mm_sms_new_from_properties (MMBaseModem *modem,
/* wtf... is this really the way to go? */
guint reference = g_random_int_range (1,255);
- /* Loop text chunks */
- while (split_text[i]) {
- mm_dbg (" Processing chunk '%u' of text with '%u' bytes",
- i, (guint)strlen (split_text[i]));
+ g_assert (split_text != NULL || split_data != NULL);
+ g_assert (!(split_text != NULL && split_data != NULL));
+
+ /* Loop text/data chunks */
+ while (1) {
+ gchar *part_text = NULL;
+ GByteArray *part_data = NULL;
+
+ if (split_text) {
+ if (!split_text[i])
+ break;
+ part_text = split_text[i];
+ split_text[i] = NULL;
+ mm_dbg (" Processing chunk '%u' of text with '%u' bytes",
+ i, (guint) strlen (part_text));
+ } else if (split_data) {
+ if (!split_data[i])
+ break;
+ part_data = split_data[i];
+ split_data[i] = NULL;
+ mm_dbg (" Processing chunk '%u' of data with '%u' bytes",
+ i, part_data->len);
+
+ } else
+ g_assert_not_reached ();
/* Create new part */
part = mm_sms_part_new (SMS_PART_INVALID_INDEX,
MM_SMS_PDU_TYPE_SUBMIT);
- mm_sms_part_set_text (part, split_text[i]);
+ mm_sms_part_take_text (part, part_text);
+ mm_sms_part_take_data (part, part_data);
mm_sms_part_set_encoding (part, encoding);
mm_sms_part_set_number (part, mm_sms_properties_get_number (properties));
mm_sms_part_set_smsc (part, mm_sms_properties_get_smsc (properties));
@@ -1481,13 +1532,13 @@ mm_sms_new_from_properties (MMBaseModem *modem,
mm_sms_part_set_concat_max (part, n_parts);
if (!sms) {
- mm_dbg ("Building user-created multipart SMS...");
+ mm_dbg ("Building user-created multipart SMS... (%u parts expected)", n_parts);
sms = mm_sms_multipart_new (
modem,
MM_SMS_STATE_UNKNOWN,
MM_SMS_STORAGE_UNKNOWN, /* not stored anywhere yet */
reference,
- g_strv_length (split_text),
+ n_parts,
part,
error);
if (!sms)
@@ -1501,18 +1552,40 @@ mm_sms_new_from_properties (MMBaseModem *modem,
i++;
}
+ /* Rewalk the arrays and remove any remaining text/data not set after an error */
+ if (split_text) {
+ for (i = 0; i < n_parts; i++) {
+ if (split_text[i])
+ g_free (split_text[i]);
+ }
+
+ g_free (split_text);
+ }
+ else if (split_data) {
+ for (i = 0; i < n_parts; i++) {
+ if (split_data[i])
+ g_byte_array_unref (split_data[i]);
+ }
+ g_free (split_data);
+ }
+
return sms;
}
/* Single part it will be */
part = mm_sms_part_new (SMS_PART_INVALID_INDEX,
MM_SMS_PDU_TYPE_SUBMIT);
- if (n_parts == 1) {
- mm_sms_part_set_text (part, mm_sms_properties_get_text (properties));
- mm_sms_part_set_encoding (part, encoding);
- } else {
- mm_sms_part_take_data (part, mm_sms_properties_get_data_bytearray (properties));
- }
+
+ if (split_text) {
+ mm_sms_part_take_text (part, split_text[0]);
+ g_free (split_text);
+ } else if (split_data) {
+ mm_sms_part_take_data (part, split_data[0]);
+ g_free (split_data);
+ } else
+ g_assert_not_reached ();
+
+ mm_sms_part_set_encoding (part, encoding);
mm_sms_part_set_number (part, mm_sms_properties_get_number (properties));
mm_sms_part_set_smsc (part, mm_sms_properties_get_smsc (properties));
mm_sms_part_set_validity (part, mm_sms_properties_get_validity (properties));