sms: 'Text' and 'Data' will never be given at the same time
When receiving an SMS, if the encoding is either GSM7 or UCS2, we will treat the contents of the SMS as text; and if the encoding is either 8BIT or unknown, we will just dump the contents of the SMS as data. When creating an SMS, the user is not allowed to give both text and data, only one can be given. We will use by default 8BIT when data is given, and guess the best encoding if text is given. Note that it's still possible to have SMS with neither text nor data, as in delivery status reports. This commit also handles the split of the input data in order to make it fit into singlepart or multipart messages.
This commit is contained in:
@@ -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" />
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
/* Add the raw PDU data */
|
||||
default:
|
||||
{
|
||||
GByteArray *raw;
|
||||
|
||||
mm_dbg ("Skipping SMS text: Unknown encoding");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
107
src/mm-sms.c
107
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]) {
|
||||
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 (split_text[i]));
|
||||
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));
|
||||
|
||||
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);
|
||||
} else {
|
||||
mm_sms_part_take_data (part, mm_sms_properties_get_data_bytearray (properties));
|
||||
}
|
||||
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));
|
||||
|
Reference in New Issue
Block a user