Contents of /trunk/beep-media-player/patches/beep-media-player-0.9.7-unicode.patch
Parent Directory | Revision Log
Revision 144 -
(show annotations)
(download)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 16841 byte(s)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 16841 byte(s)
-import
1 | diff -r -U3 bmp-0.9.7.orig/Input/mpg123/id3_frame_content.c bmp-0.9.7/Input/mpg123/id3_frame_content.c |
2 | --- bmp-0.9.7.orig/Input/mpg123/id3_frame_content.c 2005-02-25 21:45:03.000000000 -0500 |
3 | +++ bmp-0.9.7/Input/mpg123/id3_frame_content.c 2005-02-25 21:56:14.000000000 -0500 |
4 | @@ -44,9 +44,7 @@ |
5 | char * |
6 | id3_get_content(struct id3_frame *frame) |
7 | { |
8 | - char *text, *text_beg, *ptr; |
9 | - char buffer[256]; |
10 | - int spc = sizeof(buffer) - 1; |
11 | + gchar *text, *text_it; |
12 | |
13 | /* Type check */ |
14 | if (frame->fr_desc->fd_id != ID3_TCON) |
15 | @@ -56,83 +54,82 @@ |
16 | if (id3_decompress_frame(frame) == -1) |
17 | return NULL; |
18 | |
19 | - if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1) |
20 | - text_beg = text = g_strdup((char *) frame->fr_data + 1); |
21 | - else |
22 | - text_beg = text = id3_utf16_to_ascii((char *) frame->fr_data + 1); |
23 | - |
24 | - /* |
25 | - * If content is just plain text, return it. |
26 | - */ |
27 | - if (text[0] != '(') { |
28 | - return text; |
29 | - } |
30 | - |
31 | + ID3_FRAME_DEFINE_CURSOR(frame); |
32 | + |
33 | + guint8 encoding; |
34 | + ID3_FRAME_READ_OR_RETVAL(encoding, NULL); |
35 | + |
36 | + text = text_it = id3_string_decode(encoding, cursor, length); |
37 | + |
38 | + if (text == NULL) |
39 | + return NULL; |
40 | + |
41 | /* |
42 | * Expand ID3v1 genre numbers. |
43 | */ |
44 | - ptr = buffer; |
45 | - while (text[0] == '(' && text[1] != '(' && spc > 0) { |
46 | - const char *genre; |
47 | - int num = 0; |
48 | - |
49 | - if (text[1] == 'R' && text[2] == 'X') { |
50 | - text += 4; |
51 | - genre = _(" (Remix)"); |
52 | - if (ptr == buffer) |
53 | - genre++; |
54 | - |
55 | + while ((text_it = strstr(text_it, "(")) != NULL) |
56 | + { |
57 | + gchar* replace = NULL; |
58 | + gchar* ref_start = text_it + 1; |
59 | + |
60 | + if (*ref_start == ')') |
61 | + { |
62 | + /* False alarm */ |
63 | + ++text_it; |
64 | + continue; |
65 | } |
66 | - else if (text[1] == 'C' && text[2] == 'R') { |
67 | - text += 4; |
68 | - genre = _(" (Cover)"); |
69 | - if (ptr == buffer) |
70 | - genre++; |
71 | - |
72 | + |
73 | + gsize ref_size = strstr(ref_start, ")") - ref_start; |
74 | + |
75 | + if (strncmp(ref_start, "RX", ref_size) == 0) |
76 | + { |
77 | + replace = _("Remix"); |
78 | } |
79 | - else { |
80 | - /* Get ID3v1 genre number */ |
81 | - text++; |
82 | - while (*text != ')') { |
83 | - num *= 10; |
84 | - num += *text++ - '0'; |
85 | + else if (strncmp(ref_start, "CR", ref_size) == 0) |
86 | + { |
87 | + replace = _("Cover"); |
88 | + } |
89 | + else |
90 | + { |
91 | + /* Maybe an ID3v1 genre? */ |
92 | + int genre_number; |
93 | + gchar* genre_number_str = g_strndup(ref_start, ref_size); |
94 | + if (sscanf(genre_number_str, "%d", &genre_number) > 0) |
95 | + { |
96 | + /* Boundary check */ |
97 | + if (genre_number >= sizeof(mpg123_id3_genres) / sizeof(char *)) |
98 | + continue; |
99 | + replace = gettext(mpg123_id3_genres[genre_number]); |
100 | } |
101 | - text++; |
102 | - |
103 | - /* Boundary check */ |
104 | - if (num >= sizeof(mpg123_id3_genres) / sizeof(char *)) |
105 | - continue; |
106 | - |
107 | - genre = gettext(mpg123_id3_genres[num]); |
108 | - |
109 | - if (ptr != buffer && spc-- > 0) |
110 | - *ptr++ = '/'; |
111 | } |
112 | |
113 | - /* Expand string into buffer */ |
114 | - while (*genre != '\0' && spc > 0) { |
115 | - *ptr++ = *genre++; |
116 | - spc--; |
117 | + if (replace != NULL) |
118 | + { |
119 | + /* Amazingly hairy code to replace a part of the original genre string |
120 | + with 'replace'. */ |
121 | + gchar* copy = g_malloc(strlen(text) - ref_size + strlen(replace) + 1); |
122 | + gsize pos = 0; |
123 | + gsize copy_size; |
124 | + |
125 | + /* Copy the part before the replaced part */ |
126 | + copy_size = ref_start - text; |
127 | + memcpy(copy + pos, text, copy_size); |
128 | + pos += copy_size; |
129 | + /* Copy the replacement instead of the original reference */ |
130 | + copy_size = strlen(replace); |
131 | + memcpy(copy + pos, replace, copy_size); |
132 | + pos += copy_size; |
133 | + /* Copy the rest, including the null */ |
134 | + memcpy(copy + pos, ref_start + ref_size, strlen(ref_start + ref_size)+1); |
135 | + |
136 | + /* Put into original variables */ |
137 | + gsize offset = text_it - text; |
138 | + g_free(text); |
139 | + text = copy; |
140 | + text_it = text + offset; |
141 | } |
142 | + |
143 | + ++text_it; |
144 | } |
145 | - |
146 | - /* |
147 | - * Add plaintext refinement. |
148 | - */ |
149 | - if (*text == '(') |
150 | - text++; |
151 | - if (*text != '\0' && ptr != buffer && spc-- > 0) |
152 | - *ptr++ = ' '; |
153 | - while (*text != '\0' && spc > 0) { |
154 | - *ptr++ = *text++; |
155 | - spc--; |
156 | - } |
157 | - *ptr = '\0'; |
158 | - |
159 | - g_free(text_beg); |
160 | - |
161 | - /* |
162 | - * Return the expanded content string. |
163 | - */ |
164 | - return g_strdup(buffer); |
165 | + return text; |
166 | } |
167 | diff -r -U3 bmp-0.9.7.orig/Input/mpg123/id3_frame_text.c bmp-0.9.7/Input/mpg123/id3_frame_text.c |
168 | --- bmp-0.9.7.orig/Input/mpg123/id3_frame_text.c 2005-02-25 21:45:03.000000000 -0500 |
169 | +++ bmp-0.9.7/Input/mpg123/id3_frame_text.c 2005-02-26 01:25:45.613011872 -0500 |
170 | @@ -35,21 +35,6 @@ |
171 | #include "id3_header.h" |
172 | |
173 | |
174 | -char * |
175 | -id3_utf16_to_ascii(void *utf16) |
176 | -{ |
177 | - char ascii[256]; |
178 | - char *uc = (char *) utf16 + 2; |
179 | - int i; |
180 | - |
181 | - for (i = 0; *uc != 0 && i < sizeof(ascii); i++, uc += 2) |
182 | - ascii[i] = *uc; |
183 | - |
184 | - ascii[i] = 0; |
185 | - return g_strdup(ascii); |
186 | -} |
187 | - |
188 | - |
189 | /* |
190 | * Function id3_get_encoding (frame) |
191 | * |
192 | @@ -78,7 +63,12 @@ |
193 | if (id3_decompress_frame(frame) == -1) |
194 | return -1; |
195 | |
196 | - return *(gint8 *) frame->fr_data; |
197 | + ID3_FRAME_DEFINE_CURSOR(frame); |
198 | + |
199 | + guint8 encoding; |
200 | + ID3_FRAME_READ_OR_RETVAL(encoding, -1); |
201 | + |
202 | + return encoding; |
203 | } |
204 | |
205 | |
206 | @@ -119,6 +109,108 @@ |
207 | return 0; |
208 | } |
209 | |
210 | +/* Get size of string in bytes including null. */ |
211 | +gsize id3_string_size(guint8 encoding, const void* text, gsize max_size) |
212 | +{ |
213 | + switch ( encoding ) { |
214 | + case ID3_ENCODING_ISO_8859_1: |
215 | + case ID3_ENCODING_UTF8: |
216 | + { |
217 | + const guint8* text8 = text; |
218 | + while ( (max_size >= sizeof(*text8)) && (*text8 != 0) ) |
219 | + { |
220 | + ++text8; |
221 | + max_size -= sizeof(*text8); |
222 | + } |
223 | + |
224 | + if (max_size >= sizeof(*text8)) |
225 | + { |
226 | + ++text8; |
227 | + max_size -= sizeof(*text8); |
228 | + } |
229 | + |
230 | + return text8 - (guint8*)text; |
231 | + } |
232 | + case ID3_ENCODING_UTF16: |
233 | + case ID3_ENCODING_UTF16BE: |
234 | + { |
235 | + const guint16* text16 = (guint16*)text; |
236 | + while ( (max_size > 0) && (*text16 != 0) ) |
237 | + { |
238 | + ++text16; |
239 | + max_size -= sizeof(*text16); |
240 | + } |
241 | + |
242 | + if (max_size > 0) |
243 | + { |
244 | + ++text16; |
245 | + max_size -= sizeof(*text16); |
246 | + } |
247 | + |
248 | + return (guint8*)text16 - (guint8*)text; |
249 | + } |
250 | + default: |
251 | + return 0; |
252 | + } |
253 | +} |
254 | + |
255 | +/* |
256 | + * Returns a newly-allocated UTF-8 string in the locale's encoding. |
257 | + * max_size specifies the maximum size of 'text', including terminating nulls. |
258 | + */ |
259 | +gchar* id3_string_decode(guint8 encoding, const void* text, gsize max_size) |
260 | +{ |
261 | + /* Otherwise, we'll end up passing -1 to functions, eliminating safety benefits. */ |
262 | + if (max_size <= 0) |
263 | + return NULL; |
264 | + |
265 | + switch( encoding ) |
266 | + { |
267 | + case ID3_ENCODING_ISO_8859_1: |
268 | + { |
269 | + return g_locale_to_utf8((const gchar*)text, max_size, NULL, NULL, NULL); |
270 | + } |
271 | + case ID3_ENCODING_UTF8: |
272 | + { |
273 | + gchar* end_text = (gchar*)text; |
274 | + if (g_utf8_validate((const gchar*)text, max_size, &end_text)) |
275 | + return g_strndup((const gchar*)text, max_size); |
276 | + else |
277 | + { |
278 | + /* g_utf8_validate() with second argument positive |
279 | + will return 0 if the string contains nulls. Frequently |
280 | + someone will pass us a valid null-terminated utf8 |
281 | + string, with max_size overestimated a bit; so we need |
282 | + to run another test to truly check validity */ |
283 | + if((end_text != text) && (*end_text == NULL) && |
284 | + g_utf8_validate((const gchar*)text, NULL, NULL)) |
285 | + return g_strndup((const gchar*)text, max_size); |
286 | + |
287 | + return NULL; |
288 | + } |
289 | + } |
290 | + case ID3_ENCODING_UTF16: |
291 | + { |
292 | + gsize size_bytes = id3_string_size(encoding, text, max_size); |
293 | + gchar* utf8 = g_convert((const gchar*)text, size_bytes, "UTF-8", "UTF-16", NULL, NULL, NULL); |
294 | + /* If conversion passes on the BOM as-is, we strip it. */ |
295 | + if (g_utf8_get_char(utf8) == 0xfeff) |
296 | + { |
297 | + gchar* new_utf8 = g_strdup(utf8+3); |
298 | + g_free(utf8); |
299 | + utf8 = new_utf8; |
300 | + } |
301 | + return utf8; |
302 | + } |
303 | + case ID3_ENCODING_UTF16BE: |
304 | + { |
305 | + gsize size_bytes = id3_string_size(encoding, text, max_size); |
306 | + return g_convert((const gchar*)text, size_bytes, "UTF-8", "UTF-16BE", NULL, NULL, NULL); |
307 | + } |
308 | + default: |
309 | + return NULL; |
310 | + } |
311 | +} |
312 | |
313 | /* |
314 | * Function id3_get_text (frame) |
315 | @@ -137,38 +229,21 @@ |
316 | if (id3_decompress_frame(frame) == -1) |
317 | return NULL; |
318 | |
319 | + ID3_FRAME_DEFINE_CURSOR(frame); |
320 | + |
321 | + guint8 encoding; |
322 | + ID3_FRAME_READ_OR_RETVAL(encoding, NULL); |
323 | + |
324 | if (frame->fr_desc->fd_id == ID3_TXXX || frame->fr_desc->fd_id == ID3_COMM) { |
325 | /* |
326 | * This is a user defined text frame. Skip the description. |
327 | */ |
328 | - switch (*(guint8 *) frame->fr_data) { |
329 | - case ID3_ENCODING_ISO_8859_1: |
330 | - { |
331 | - char *text = (char *) frame->fr_data + 1; |
332 | - |
333 | - while (*text != 0) |
334 | - text++; |
335 | - |
336 | - return g_strdup(++text); |
337 | - } |
338 | - case ID3_ENCODING_UTF16: |
339 | - { |
340 | - char *text16 = (char *) frame->fr_data + 1; |
341 | - |
342 | - while (*text16 != 0 || *(text16 + 1) != 0) |
343 | - text16 += 2; |
344 | - |
345 | - return id3_utf16_to_ascii(text16 + 2); |
346 | - } |
347 | - default: |
348 | - return NULL; |
349 | - } |
350 | + gsize bytes = id3_string_size(encoding, cursor, length); |
351 | + cursor += bytes; |
352 | + length -= bytes; |
353 | } |
354 | |
355 | - if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1) |
356 | - return g_strdup((char *) frame->fr_data + 1); |
357 | - else |
358 | - return id3_utf16_to_ascii(((char *) frame->fr_data + 1)); |
359 | + return id3_string_decode(encoding, cursor, length); |
360 | } |
361 | |
362 | |
363 | @@ -193,10 +268,12 @@ |
364 | if (id3_decompress_frame(frame) == -1) |
365 | return NULL; |
366 | |
367 | - if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1) |
368 | - return g_strdup((char *) frame->fr_data + 1); |
369 | - else |
370 | - return id3_utf16_to_ascii((char *) frame->fr_data + 1); |
371 | + ID3_FRAME_DEFINE_CURSOR(frame); |
372 | + |
373 | + guint8 encoding; |
374 | + ID3_FRAME_READ_OR_RETVAL(encoding, NULL); |
375 | + |
376 | + return id3_string_decode(encoding, cursor, length); |
377 | } |
378 | |
379 | |
380 | @@ -216,41 +293,19 @@ |
381 | if (id3_decompress_frame(frame) == -1) |
382 | return -1; |
383 | |
384 | - /* |
385 | - * Generate integer according to encoding. |
386 | - */ |
387 | - switch (*(guint8 *) frame->fr_data) { |
388 | - case ID3_ENCODING_ISO_8859_1: |
389 | - { |
390 | - char *text = ((char *) frame->fr_data) + 1; |
391 | - |
392 | - while (*text >= '0' && *text <= '9') { |
393 | - number *= 10; |
394 | - number += *text - '0'; |
395 | - text++; |
396 | - } |
397 | - |
398 | - return number; |
399 | - } |
400 | - case ID3_ENCODING_UTF16: |
401 | - { |
402 | - char *text = ((char *) frame->fr_data) + 3; |
403 | - |
404 | -/* if (*(gint16 *) frame->fr_data == 0xfeff) */ |
405 | -/* text++; */ |
406 | - |
407 | - while (*text >= '0' && *text <= '9') { |
408 | - number *= 10; |
409 | - number += *text - '0'; |
410 | - text++; |
411 | - } |
412 | - |
413 | - return number; |
414 | - } |
415 | - |
416 | - default: |
417 | - return -1; |
418 | - } |
419 | + ID3_FRAME_DEFINE_CURSOR(frame); |
420 | + |
421 | + guint8 encoding; |
422 | + ID3_FRAME_READ_OR_RETVAL(encoding, number); |
423 | + |
424 | + gchar* number_str = id3_string_decode(encoding, cursor, length); |
425 | + if (number_str != NULL) |
426 | + { |
427 | + sscanf(number_str, "%d", &number); |
428 | + g_free(number_str); |
429 | + } |
430 | + |
431 | + return number; |
432 | } |
433 | |
434 | |
435 | @@ -306,7 +361,6 @@ |
436 | id3_set_text_number(struct id3_frame *frame, int number) |
437 | { |
438 | char buf[64]; |
439 | - int pos; |
440 | char *text; |
441 | |
442 | /* Type check */ |
443 | @@ -321,20 +375,12 @@ |
444 | /* |
445 | * Create a string with a reversed number. |
446 | */ |
447 | - pos = 0; |
448 | - while (number > 0 && pos < 64) { |
449 | - buf[pos++] = (number % 10) + '0'; |
450 | - number /= 10; |
451 | - } |
452 | - if (pos == 64) |
453 | - return -1; |
454 | - if (pos == 0) |
455 | - buf[pos++] = '0'; |
456 | + snprintf(buf, sizeof(buf), "%d", number); |
457 | |
458 | /* |
459 | * Allocate memory for new data. |
460 | */ |
461 | - frame->fr_raw_size = pos + 1; |
462 | + frame->fr_raw_size = strlen(buf) + 1; |
463 | frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1); |
464 | |
465 | /* |
466 | @@ -342,9 +388,7 @@ |
467 | */ |
468 | *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1; |
469 | text = (char *) frame->fr_raw_data + 1; |
470 | - while (--pos >= 0) |
471 | - *text++ = buf[pos]; |
472 | - *text = '\0'; |
473 | + strcpy(text, buf); |
474 | |
475 | frame->fr_altered = 1; |
476 | frame->fr_owner->id3_altered = 1; |
477 | diff -r -U3 bmp-0.9.7.orig/Input/mpg123/id3_frame_url.c bmp-0.9.7/Input/mpg123/id3_frame_url.c |
478 | --- bmp-0.9.7.orig/Input/mpg123/id3_frame_url.c 2005-02-25 21:45:03.000000000 -0500 |
479 | +++ bmp-0.9.7/Input/mpg123/id3_frame_url.c 2005-02-25 22:15:28.000000000 -0500 |
480 | @@ -48,36 +48,26 @@ |
481 | /* Check if frame is compressed */ |
482 | if (id3_decompress_frame(frame) == -1) |
483 | return NULL; |
484 | - |
485 | - if (frame->fr_desc->fd_id == ID3_WXXX) { |
486 | + |
487 | + ID3_FRAME_DEFINE_CURSOR(frame); |
488 | + |
489 | + if ( frame->fr_desc->fd_id == ID3_WXXX ) { |
490 | /* |
491 | * This is a user defined link frame. Skip the description. |
492 | */ |
493 | - switch (*(guint8 *) frame->fr_data) { |
494 | - case ID3_ENCODING_ISO_8859_1: |
495 | - { |
496 | - char *text = (char *) frame->fr_data + 1; |
497 | - |
498 | - while (*text != 0) |
499 | - text++; |
500 | - |
501 | - return g_strdup(++text); |
502 | - } |
503 | - case ID3_ENCODING_UTF16: |
504 | - { |
505 | - gint16 *text16 = (gint16 *) ((glong) frame->fr_data + 1); |
506 | - |
507 | - while (*text16 != 0) |
508 | - text16++; |
509 | - |
510 | - return g_strdup((char *) (++text16)); |
511 | - } |
512 | - default: |
513 | + guint8 encoding; |
514 | + gsize description_size; |
515 | + |
516 | + ID3_FRAME_READ_OR_RETVAL(encoding, NULL); |
517 | + |
518 | + description_size = id3_string_size(encoding, cursor, length); |
519 | + if (description_size == 0) |
520 | return NULL; |
521 | - } |
522 | + cursor += description_size; |
523 | + length -= description_size; |
524 | } |
525 | |
526 | - return g_strdup((char *) frame->fr_data); |
527 | + return id3_string_decode(ID3_ENCODING_ISO_8859_1, cursor, length); |
528 | } |
529 | |
530 | |
531 | @@ -102,8 +92,10 @@ |
532 | if (id3_decompress_frame(frame) == -1) |
533 | return NULL; |
534 | |
535 | - if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1) |
536 | - return g_strdup((char *) frame->fr_data + 1); |
537 | - else |
538 | - return id3_utf16_to_ascii((gint16 *) ((glong) frame->fr_data + 1)); |
539 | + ID3_FRAME_DEFINE_CURSOR(frame); |
540 | + |
541 | + guint8 encoding; |
542 | + ID3_FRAME_READ_OR_RETVAL(encoding, NULL); |
543 | + |
544 | + return id3_string_decode(encoding, cursor, length); |
545 | } |
546 | diff -r -U3 bmp-0.9.7.orig/Input/mpg123/xmms-id3.h bmp-0.9.7/Input/mpg123/xmms-id3.h |
547 | --- bmp-0.9.7.orig/Input/mpg123/xmms-id3.h 2005-02-25 21:45:03.000000000 -0500 |
548 | +++ bmp-0.9.7/Input/mpg123/xmms-id3.h 2005-02-25 21:49:22.000000000 -0500 |
549 | @@ -29,6 +29,7 @@ |
550 | #define ID3_H |
551 | |
552 | #include <glib.h> |
553 | +#include <string.h> |
554 | #include <libbeep/vfs.h> |
555 | |
556 | /* |
557 | @@ -318,6 +319,21 @@ |
558 | #define ID3_WPB ID3_FRAME_ID_22('W', 'P', 'B') |
559 | #define ID3_WXX ID3_FRAME_ID_22('W', 'X', 'X') |
560 | |
561 | +/* |
562 | + * Handy macros which help us writing more secure length-aware code |
563 | + * which involves reading the frame's data buffer. |
564 | + */ |
565 | + |
566 | +#define ID3_FRAME_DEFINE_CURSOR(frame) \ |
567 | + gsize length = frame->fr_size; \ |
568 | + guint8* cursor = frame->fr_data; |
569 | + |
570 | +#define ID3_FRAME_READ_OR_RETVAL(variable, retval) \ |
571 | + if (length < sizeof(variable)) \ |
572 | + return retval; \ |
573 | + memcpy((void*)&variable, (void*)cursor, sizeof(variable)); \ |
574 | + cursor += sizeof(variable); \ |
575 | + length -= sizeof(variable); |
576 | |
577 | /* |
578 | * Prototypes. |
579 | @@ -343,7 +359,8 @@ |
580 | void id3_frame_clear_data(struct id3_frame *frame); |
581 | |
582 | /* From id3_frame_text.c */ |
583 | -char *id3_utf16_to_ascii(void *); |
584 | +gsize id3_string_size(guint8 encoding, const void* text, gsize max_size); |
585 | +gchar* id3_string_decode(guint8 encoding, const void* text, gsize max_size); |
586 | gint8 id3_get_encoding(struct id3_frame *); |
587 | int id3_set_encoding(struct id3_frame *, gint8); |
588 | char *id3_get_text(struct id3_frame *); |