mirror of git://git.sysmocom.de/ofono
Add utility to convert SIM FS strings to UTF8
This commit is contained in:
parent
36b52d4f87
commit
467db7dd7f
124
src/util.c
124
src/util.c
|
@ -692,3 +692,127 @@ unsigned char *pack_7bit(const unsigned char *in, long len, int byte_offset,
|
|||
return pack_7bit_own_buf(in, len, byte_offset, ussd, items_written,
|
||||
terminator, buf);
|
||||
}
|
||||
|
||||
char *sim_string_to_utf8(const unsigned char *buffer, int length)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int num_chars;
|
||||
unsigned short ucs2_offset;
|
||||
int res_len;
|
||||
int offset;
|
||||
char *utf8 = NULL;
|
||||
char *out;
|
||||
|
||||
if (length < 1)
|
||||
return NULL;
|
||||
|
||||
if (buffer[0] < 0x80) {
|
||||
/* We have to find the real length, since on SIM file system
|
||||
* alpha fields are 0xff padded
|
||||
*/
|
||||
for (i = 0; i < length; i++)
|
||||
if (buffer[i] == 0xff)
|
||||
break;
|
||||
|
||||
return convert_gsm_to_utf8(buffer, i, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
switch (buffer[0]) {
|
||||
case 0x80:
|
||||
for (i = 1; i < length; i += 2)
|
||||
if (buffer[i] == 0xff)
|
||||
break;
|
||||
|
||||
return g_convert(buffer + 1, i - 1,
|
||||
"UTF-8//TRANSLIT", "UCS-2BE",
|
||||
NULL, NULL, NULL);
|
||||
case 0x81:
|
||||
if (length < 3 || (buffer[1] > (length - 3)))
|
||||
return NULL;
|
||||
|
||||
num_chars = buffer[1];
|
||||
ucs2_offset = buffer[2] << 7;
|
||||
offset = 3;
|
||||
break;
|
||||
|
||||
case 0x82:
|
||||
if (length < 4 || buffer[1] > length - 4)
|
||||
return NULL;
|
||||
|
||||
num_chars = buffer[1];
|
||||
ucs2_offset = (buffer[2] << 8) | buffer[3];
|
||||
offset = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res_len = 0;
|
||||
i = offset;
|
||||
j = 0;
|
||||
|
||||
while ((i < length) && (j < num_chars)) {
|
||||
unsigned short c;
|
||||
|
||||
if (buffer[i] & 0x80) {
|
||||
c = (buffer[i++] & 0x7f) + ucs2_offset;
|
||||
res_len += UTF8_LENGTH(c);
|
||||
j += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buffer[i] == 0x1b) {
|
||||
++i;
|
||||
if (i >= length)
|
||||
return NULL;
|
||||
|
||||
c = gsm_extension_table_lookup(buffer[i++]);
|
||||
|
||||
if (c == 0)
|
||||
return NULL;
|
||||
|
||||
j += 2;
|
||||
} else {
|
||||
c = gsm_table[buffer[i++]];
|
||||
j += 1;
|
||||
}
|
||||
|
||||
res_len += UTF8_LENGTH(c);
|
||||
}
|
||||
|
||||
if (j != num_chars)
|
||||
return NULL;
|
||||
|
||||
/* Check that the string is padded out to the length by 0xff */
|
||||
for (; i < length; i++)
|
||||
if (buffer[i] != 0xff)
|
||||
return NULL;
|
||||
|
||||
utf8 = g_malloc(res_len + 1);
|
||||
|
||||
if (!utf8)
|
||||
return NULL;
|
||||
|
||||
i = offset;
|
||||
out = utf8;
|
||||
|
||||
while (out < utf8 + res_len) {
|
||||
unsigned short c;
|
||||
|
||||
if (buffer[i] & 0x80)
|
||||
c = (buffer[i++] & 0x7f) + ucs2_offset;
|
||||
else if (buffer[i] == 0x1b) {
|
||||
++i;
|
||||
c = gsm_extension_table_lookup(buffer[i++]);
|
||||
} else
|
||||
c = gsm_table[buffer[i++]];
|
||||
|
||||
out += g_unichar_to_utf8(c, out);
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
|
||||
return utf8;
|
||||
}
|
||||
|
|
|
@ -56,3 +56,5 @@ unsigned char *pack_7bit_own_buf(const unsigned char *in, long len,
|
|||
unsigned char *pack_7bit(const unsigned char *in, long len, int byte_offset,
|
||||
gboolean ussd,
|
||||
long *items_written, unsigned char terminator);
|
||||
|
||||
char *sim_string_to_utf8(const unsigned char *buffer, int length);
|
||||
|
|
Loading…
Reference in New Issue