summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bplist.c160
1 files changed, 72 insertions, 88 deletions
diff --git a/src/bplist.c b/src/bplist.c
index 1ecbd66..c4fe3df 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -315,7 +315,7 @@ static plist_t parse_string_node(const char **bnode, uint64_t size)
315 return node_create(NULL, data); 315 return node_create(NULL, data);
316} 316}
317 317
318static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written) 318static char *plist_utf16be_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written)
319{ 319{
320 if (!unistr || (len <= 0)) return NULL; 320 if (!unistr || (len <= 0)) return NULL;
321 char *outbuf; 321 char *outbuf;
@@ -333,7 +333,8 @@ static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, l
333 } 333 }
334 334
335 while (i < len) { 335 while (i < len) {
336 wc = unistr[i++]; 336 wc = be16toh(get_unaligned(unistr + i));
337 i++;
337 if (wc >= 0xD800 && wc <= 0xDBFF) { 338 if (wc >= 0xD800 && wc <= 0xDBFF) {
338 if (!read_lead_surrogate) { 339 if (!read_lead_surrogate) {
339 read_lead_surrogate = 1; 340 read_lead_surrogate = 1;
@@ -380,24 +381,13 @@ static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, l
380static plist_t parse_unicode_node(const char **bnode, uint64_t size) 381static plist_t parse_unicode_node(const char **bnode, uint64_t size)
381{ 382{
382 plist_data_t data = plist_new_plist_data(); 383 plist_data_t data = plist_new_plist_data();
383 uint64_t i = 0;
384 uint16_t *unicodestr = NULL;
385 char *tmpstr = NULL; 384 char *tmpstr = NULL;
386 long items_read = 0; 385 long items_read = 0;
387 long items_written = 0; 386 long items_written = 0;
388 387
389 data->type = PLIST_STRING; 388 data->type = PLIST_STRING;
390 unicodestr = (uint16_t*) malloc(sizeof(uint16_t) * size);
391 if (!unicodestr) {
392 plist_free_data(data);
393 PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, sizeof(uint16_t) * size);
394 return NULL;
395 }
396 for (i = 0; i < size; i++)
397 unicodestr[i] = be16toh(get_unaligned((uint16_t*)(*bnode+(i<<1))));
398 389
399 tmpstr = plist_utf16_to_utf8(unicodestr, size, &items_read, &items_written); 390 tmpstr = plist_utf16be_to_utf8((uint16_t*)(*bnode), size, &items_read, &items_written);
400 free(unicodestr);
401 if (!tmpstr) { 391 if (!tmpstr) {
402 plist_free_data(data); 392 plist_free_data(data);
403 return NULL; 393 return NULL;
@@ -1028,14 +1018,74 @@ static void write_string(bytearray_t * bplist, char *val, uint64_t size)
1028 write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); 1018 write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size);
1029} 1019}
1030 1020
1031static void write_unicode(bytearray_t * bplist, uint16_t * val, uint64_t size) 1021static uint16_t *plist_utf8_to_utf16be(char *unistr, long size, long *items_read, long *items_written)
1032{ 1022{
1033 uint64_t i = 0; 1023 uint16_t *outbuf;
1034 uint16_t *buff = (uint16_t*)malloc(size << 1); 1024 int p = 0;
1035 for (i = 0; i < size; i++) 1025 long i = 0;
1036 buff[i] = be16toh(val[i]); 1026
1037 write_raw_data(bplist, BPLIST_UNICODE, (uint8_t*)buff, size); 1027 unsigned char c0;
1038 free(buff); 1028 unsigned char c1;
1029 unsigned char c2;
1030 unsigned char c3;
1031
1032 uint32_t w;
1033
1034 outbuf = (uint16_t*)malloc(((size*2)+1)*sizeof(uint16_t));
1035 if (!outbuf) {
1036 PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, (uint64_t)((size*2)+1)*sizeof(uint16_t));
1037 return NULL;
1038 }
1039
1040 while (i < size) {
1041 c0 = unistr[i];
1042 c1 = (i < size-1) ? unistr[i+1] : 0;
1043 c2 = (i < size-2) ? unistr[i+2] : 0;
1044 c3 = (i < size-3) ? unistr[i+3] : 0;
1045 if ((c0 >= 0xF0) && (i < size-3) && (c1 >= 0x80) && (c2 >= 0x80) && (c3 >= 0x80)) {
1046 // 4 byte sequence. Need to generate UTF-16 surrogate pair
1047 w = ((((c0 & 7) << 18) + ((c1 & 0x3F) << 12) + ((c2 & 0x3F) << 6) + (c3 & 0x3F)) & 0x1FFFFF) - 0x010000;
1048 outbuf[p++] = be16toh(0xD800 + (w >> 10));
1049 outbuf[p++] = be16toh(0xDC00 + (w & 0x3FF));
1050 i+=4;
1051 } else if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) {
1052 // 3 byte sequence
1053 outbuf[p++] = be16toh(((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12));
1054 i+=3;
1055 } else if ((c0 >= 0xC0) && (i < size-1) && (c1 >= 0x80)) {
1056 // 2 byte sequence
1057 outbuf[p++] = be16toh(((c1 & 0x3F) + ((c0 & 3) << 6)) + (((c0 >> 2) & 7) << 8));
1058 i+=2;
1059 } else if (c0 < 0x80) {
1060 // 1 byte sequence
1061 outbuf[p++] = be16toh(c0);
1062 i+=1;
1063 } else {
1064 // invalid character
1065 PLIST_BIN_ERR("%s: invalid utf8 sequence in string at index %lu\n", __func__, i);
1066 break;
1067 }
1068 }
1069 if (items_read) {
1070 *items_read = i;
1071 }
1072 if (items_written) {
1073 *items_written = p;
1074 }
1075 outbuf[p] = 0;
1076
1077 return outbuf;
1078}
1079
1080static void write_unicode(bytearray_t * bplist, char *val, uint64_t size)
1081{
1082 long items_read = 0;
1083 long items_written = 0;
1084 uint16_t *unicodestr = NULL;
1085
1086 unicodestr = plist_utf8_to_utf16be(val, size, &items_read, &items_written);
1087 write_raw_data(bplist, BPLIST_UNICODE, (uint8_t*)unicodestr, items_written);
1088 free(unicodestr);
1039} 1089}
1040 1090
1041static void write_array(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t ref_size) 1091static void write_array(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t ref_size)
@@ -1111,66 +1161,6 @@ static int is_ascii_string(char* s, int len)
1111 return ret; 1161 return ret;
1112} 1162}
1113 1163
1114static uint16_t *plist_utf8_to_utf16(char *unistr, long size, long *items_read, long *items_written)
1115{
1116 uint16_t *outbuf;
1117 int p = 0;
1118 long i = 0;
1119
1120 unsigned char c0;
1121 unsigned char c1;
1122 unsigned char c2;
1123 unsigned char c3;
1124
1125 uint32_t w;
1126
1127 outbuf = (uint16_t*)malloc(((size*2)+1)*sizeof(uint16_t));
1128 if (!outbuf) {
1129 PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, (uint64_t)((size*2)+1)*sizeof(uint16_t));
1130 return NULL;
1131 }
1132
1133 while (i < size) {
1134 c0 = unistr[i];
1135 c1 = (i < size-1) ? unistr[i+1] : 0;
1136 c2 = (i < size-2) ? unistr[i+2] : 0;
1137 c3 = (i < size-3) ? unistr[i+3] : 0;
1138 if ((c0 >= 0xF0) && (i < size-3) && (c1 >= 0x80) && (c2 >= 0x80) && (c3 >= 0x80)) {
1139 // 4 byte sequence. Need to generate UTF-16 surrogate pair
1140 w = ((((c0 & 7) << 18) + ((c1 & 0x3F) << 12) + ((c2 & 0x3F) << 6) + (c3 & 0x3F)) & 0x1FFFFF) - 0x010000;
1141 outbuf[p++] = 0xD800 + (w >> 10);
1142 outbuf[p++] = 0xDC00 + (w & 0x3FF);
1143 i+=4;
1144 } else if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) {
1145 // 3 byte sequence
1146 outbuf[p++] = ((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12);
1147 i+=3;
1148 } else if ((c0 >= 0xC0) && (i < size-1) && (c1 >= 0x80)) {
1149 // 2 byte sequence
1150 outbuf[p++] = ((c1 & 0x3F) + ((c0 & 3) << 6)) + (((c0 >> 2) & 7) << 8);
1151 i+=2;
1152 } else if (c0 < 0x80) {
1153 // 1 byte sequence
1154 outbuf[p++] = c0;
1155 i+=1;
1156 } else {
1157 // invalid character
1158 PLIST_BIN_ERR("%s: invalid utf8 sequence in string at index %lu\n", __func__, i);
1159 break;
1160 }
1161 }
1162 if (items_read) {
1163 *items_read = i;
1164 }
1165 if (items_written) {
1166 *items_written = p;
1167 }
1168 outbuf[p] = 0;
1169
1170 return outbuf;
1171
1172}
1173
1174PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) 1164PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1175{ 1165{
1176 ptrarray_t* objects = NULL; 1166 ptrarray_t* objects = NULL;
@@ -1186,10 +1176,6 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1186 uint8_t *buff = NULL; 1176 uint8_t *buff = NULL;
1187 uint64_t *offsets = NULL; 1177 uint64_t *offsets = NULL;
1188 bplist_trailer_t trailer; 1178 bplist_trailer_t trailer;
1189 //for string
1190 long items_read = 0;
1191 long items_written = 0;
1192 uint16_t *unicodestr = NULL;
1193 uint64_t objects_len = 0; 1179 uint64_t objects_len = 0;
1194 uint64_t buff_len = 0; 1180 uint64_t buff_len = 0;
1195 1181
@@ -1260,9 +1246,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1260 } 1246 }
1261 else 1247 else
1262 { 1248 {
1263 unicodestr = plist_utf8_to_utf16(data->strval, data->length, &items_read, &items_written); 1249 write_unicode(bplist_buff, data->strval, data->length);
1264 write_unicode(bplist_buff, unicodestr, items_written);
1265 free(unicodestr);
1266 } 1250 }
1267 break; 1251 break;
1268 case PLIST_DATA: 1252 case PLIST_DATA: