diff options
-rw-r--r-- | introspection/org.freedesktop.ModemManager1.Sms.xml | 6 | ||||
-rw-r--r-- | src/mm-sms-part.c | 73 | ||||
-rw-r--r-- | src/mm-sms-part.h | 2 | ||||
-rw-r--r-- | src/mm-sms.c | 111 |
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)); |