Magellan Linux

Contents of /trunk/beep-media-player/patches/beep-media-player-0.9.7-unicode.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 144 - (show annotations) (download)
Tue May 8 20:06:05 2007 UTC (16 years, 11 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 *);