diff --git a/src/smsutil.c b/src/smsutil.c index 6d4ac127..dd338053 100644 --- a/src/smsutil.c +++ b/src/smsutil.c @@ -2184,3 +2184,163 @@ void sms_assembly_expire(struct sms_assembly *assembly, time_t before) g_slist_free_1(tmp); } } + +static inline GSList *sms_list_append(GSList *l, const struct sms *in) +{ + struct sms *sms; + + sms = g_new(struct sms, 1); + memcpy(sms, in, sizeof(struct sms)); + l = g_slist_prepend(l, sms); + + return l; +} + +GSList *sms_text_prepare(const char *utf8, guint16 ref, gboolean use_16bit) +{ + struct sms template; + int offset = 0; + unsigned char *gsm_encoded = NULL; + char *ucs2_encoded = NULL; + long written; + long left; + guint8 seq; + guint8 max; + GSList *r = NULL; + + memset(&template, 0, sizeof(struct sms)); + template.type = SMS_TYPE_SUBMIT; + template.submit.rd = FALSE; + template.submit.vpf = SMS_VALIDITY_PERIOD_FORMAT_RELATIVE; + template.submit.rp = FALSE; + template.submit.srr = FALSE; + template.submit.mr = 0; + template.submit.vp.relative = 0xA7; /* 24 Hours */ + + /* UDHI, UDL, UD and DCS actually depend on what we have in the text */ + gsm_encoded = convert_utf8_to_gsm(utf8, -1, NULL, &written, 0); + + if (!gsm_encoded) + ucs2_encoded = g_convert(utf8, -1, "UCS-2BE//TRANSLIT", "UTF-8", + NULL, &written, NULL); + + if (!gsm_encoded && !ucs2_encoded) + return NULL; + + if (gsm_encoded) + template.submit.dcs = 0x00; /* Class Unspecified, 7 Bit */ + else + template.submit.dcs = 0x08; /* Class Unspecified, UCS2 */ + + if (offset != 0) + template.submit.udhi = FALSE; + + if (gsm_encoded && (written <= sms_text_capacity_gsm(160, offset))) { + template.submit.udl = written + (offset * 8 + 6) / 7; + pack_7bit_own_buf(gsm_encoded, written, offset, FALSE, NULL, + 0, template.submit.ud + offset); + + g_free(gsm_encoded); + return sms_list_append(NULL, &template); + } + + if (ucs2_encoded && (written <= (140 - offset))) { + template.submit.udl = written + offset; + memcpy(template.submit.ud + offset, ucs2_encoded, written); + + g_free(ucs2_encoded); + return sms_list_append(NULL, &template); + } + + template.submit.udhi = TRUE; + + if (!offset) + offset = 1; + + if (use_16bit) { + template.submit.ud[0] += 6; + template.submit.ud[offset] = SMS_IEI_CONCATENATED_16BIT; + template.submit.ud[offset + 1] = 4; + template.submit.ud[offset + 2] = (ref & 0xf0) >> 8; + template.submit.ud[offset + 3] = ref & 0xf; + + offset += 6; + } else { + template.submit.ud[0] += 5; + template.submit.ud[offset] = SMS_IEI_CONCATENATED_8BIT; + template.submit.ud[offset + 1] = 3; + template.submit.ud[offset + 2] = ref & 0xf; + + offset += 5; + } + + seq = 1; + left = written; + written = 0; + + while (left > 0) { + long chunk; + + if (gsm_encoded) { + chunk = sms_text_capacity_gsm(160, offset); + + if (gsm_encoded[written + chunk - 1] == 0x1b) + chunk -= 1; + + if (left < chunk) + chunk = left; + + template.submit.udl = chunk + (offset * 8 + 6) / 7; + pack_7bit_own_buf(gsm_encoded + written, chunk, + offset, FALSE, NULL, 0, + template.submit.ud + offset); + } else { + chunk = 140 - offset; + chunk &= ~0x1; + + if (left < chunk) + chunk = left; + + template.submit.udl = chunk + offset; + memcpy(template.submit.ud + offset, + ucs2_encoded + written, chunk); + } + + written += chunk; + left -= chunk; + + template.submit.ud[offset - 1] = seq; + + r = sms_list_append(r, &template); + + if (seq == 255) + break; + + seq += 1; + } + + if (gsm_encoded) + g_free(gsm_encoded); + + if (ucs2_encoded) + g_free(ucs2_encoded); + + if (left > 0) { + g_slist_foreach(r, (GFunc)g_free, NULL); + g_slist_free(r); + + return NULL; + } else { + GSList *l; + + for (l = r; l; l = l->next) { + struct sms *sms = l->data; + + sms->submit.ud[offset - 2] = seq; + } + } + + r = g_slist_reverse(r); + + return r; +} diff --git a/src/smsutil.h b/src/smsutil.h index 758eac75..36b467be 100644 --- a/src/smsutil.h +++ b/src/smsutil.h @@ -394,3 +394,5 @@ GSList *sms_assembly_add_fragment(struct sms_assembly *assembly, const struct sms_address *addr, guint16 ref, guint8 max, guint8 seq); void sms_assembly_expire(struct sms_assembly *assembly, time_t before); + +GSList *sms_text_prepare(const char *utf8, guint16 ref, gboolean use_16bit);