# HG changeset patch # User yaz # Date 1161331185 25200 # Node ID b5a1b762f58661f4803abf5a4b93019780aede79 # Parent 230d8b49db8be5f7d268cc9d9cb06309634c2b9a [svn] - xspf now uses url encoding for location entry. diff -r 230d8b49db8b -r b5a1b762f586 ChangeLog --- a/ChangeLog Mon Oct 16 11:40:44 2006 -0700 +++ b/ChangeLog Fri Oct 20 00:59:45 2006 -0700 @@ -1,3 +1,11 @@ +2006-10-16 18:40:44 +0000 Giacomo Lozito + revision [188] + - do not use a different DATA_DIR for audacious-plugins + trunk/configure.ac | 2 +- + trunk/src/scrobbler/Makefile | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + + 2006-10-15 16:41:42 +0000 William Pitcock revision [186] - workaround for GNOME VFS crash diff -r 230d8b49db8b -r b5a1b762f586 src/xspf/Makefile --- a/src/xspf/Makefile Mon Oct 16 11:40:44 2006 -0700 +++ b/src/xspf/Makefile Fri Oct 20 00:59:45 2006 -0700 @@ -5,7 +5,7 @@ LIBDIR = $(plugindir)/$(CONTAINER_PLUGIN_DIR) -SOURCES = xspf.c base64.c +SOURCES = xspf.c base64.c urlencode.c OBJECTS = ${SOURCES:.c=.o} diff -r 230d8b49db8b -r b5a1b762f586 src/xspf/urlencode.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xspf/urlencode.c Fri Oct 20 00:59:45 2006 -0700 @@ -0,0 +1,158 @@ +/* the original code was taken from wget-1.10.2 */ + +#include +#include +#include +#include +#include "urlencode.h" + +enum { + /* rfc1738 reserved chars + "$" and ",". */ + urlchr_reserved = 1, + + /* rfc1738 unsafe chars, plus non-printables. */ + urlchr_unsafe = 2 +}; + +#define urlchr_test(c, mask) (urlchr_table[(unsigned char)(c)] & (mask)) +#define URL_RESERVED_CHAR(c) urlchr_test(c, urlchr_reserved) +#define URL_UNSAFE_CHAR(c) urlchr_test(c, urlchr_unsafe) +#define XNUM_TO_DIGIT(x) ("0123456789ABCDEF"[x] + 0) +#define ISXDIGIT(x) (isxdigit((unsigned char)(x))) +#define X2DIGITS_TO_NUM(h1, h2) ((XDIGIT_TO_NUM (h1) << 4) + XDIGIT_TO_NUM (h2)) +#define XDIGIT_TO_NUM(h) ((h) < 'A' ? (h) - '0' : toupper (h) - 'A' + 10) + +/* Shorthands for the table: */ +#define R urlchr_reserved +#define U urlchr_unsafe +#define RU R|U + +static const unsigned char urlchr_table[256] = +{ + U, U, U, U, U, U, U, U, /* NUL SOH STX ETX EOT ENQ ACK BEL */ + U, U, U, U, U, U, U, U, /* BS HT LF VT FF CR SO SI */ + U, U, U, U, U, U, U, U, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + U, U, U, U, U, U, U, U, /* CAN EM SUB ESC FS GS RS US */ + U, 0, U, RU, R, U, R, 0, /* SP ! " # $ % & ' */ + 0, 0, 0, R, R, 0, 0, R, /* ( ) * + , - . / */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */ + 0, 0, RU, R, U, R, U, R, /* 8 9 : ; < = > ? */ + RU, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */ + 0, 0, 0, RU, U, RU, U, 0, /* X Y Z [ \ ] ^ _ */ + U, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */ + 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */ + 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */ + 0, 0, 0, U, U, U, 0, U, /* x y z { | } ~ DEL */ + + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, +}; +#undef R +#undef U +#undef RU + +/* URL-unescape the string S. + + This is done by transforming the sequences "%HH" to the character + represented by the hexadecimal digits HH. If % is not followed by + two hexadecimal digits, it is inserted literally. + + The transformation is done in place. If you need the original + string intact, make a copy before calling this function. */ + +char * +xspf_url_decode (const char *s) +{ + char *copy = strdup(s); + char *t = copy; /* t - tortoise */ + char *h = copy; /* h - hare */ + + for (; *h; h++, t++) + { + if (*h != '%') + { + copychar: + *t = *h; + } + else + { + char c; + /* Do nothing if '%' is not followed by two hex digits. */ + if (!h[1] || !h[2] || !(ISXDIGIT (h[1]) && ISXDIGIT (h[2]))) + goto copychar; + c = X2DIGITS_TO_NUM (h[1], h[2]); + /* Don't unescape %00 because there is no way to insert it + into a C string without effectively truncating it. */ + if (c == '\0') + goto copychar; + *t = c; + h += 2; + } + } + *t = '\0'; + return copy; +} + +/* The core of url_escape_* functions. Escapes the characters that + match the provided mask in urlchr_table. + + If ALLOW_PASSTHROUGH is non-zero, a string with no unsafe chars + will be returned unchanged. If ALLOW_PASSTHROUGH is zero, a + freshly allocated string will be returned in all cases. */ + +static char * +url_escape_1 (const char *s, unsigned char mask, int allow_passthrough) +{ + const char *p1; + char *p2, *newstr; + int newlen; + int addition = 0; + + for (p1 = s; *p1; p1++) + if (urlchr_test (*p1, mask)) + addition += 2; /* Two more characters (hex digits) */ + + if (!addition) + return allow_passthrough ? (char *)s : strdup (s); + + newlen = (p1 - s) + addition; + newstr = (char *)malloc (newlen + 1); + + p1 = s; + p2 = newstr; + while (*p1) + { + /* Quote the characters that match the test mask. */ + if (urlchr_test (*p1, mask)) + { + unsigned char c = *p1++; + *p2++ = '%'; + *p2++ = XNUM_TO_DIGIT (c >> 4); + *p2++ = XNUM_TO_DIGIT (c & 0xf); + } + else + *p2++ = *p1++; + } + g_return_if_fail (p2 - newstr == newlen); + *p2 = '\0'; + + return newstr; +} + +/* URL-escape the unsafe characters (see urlchr_table) in a given + string, returning a freshly allocated string. */ + +char * +xspf_url_encode (const char *s) +{ + return url_escape_1 (s, urlchr_unsafe, 0); +} diff -r 230d8b49db8b -r b5a1b762f586 src/xspf/urlencode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xspf/urlencode.h Fri Oct 20 00:59:45 2006 -0700 @@ -0,0 +1,4 @@ +/* prototypes */ + +char *xspf_url_decode(const char *url); +char *xspf_url_encode(const char *path); diff -r 230d8b49db8b -r b5a1b762f586 src/xspf/xspf.c --- a/src/xspf/xspf.c Mon Oct 16 11:40:44 2006 -0700 +++ b/src/xspf/xspf.c Fri Oct 20 00:59:45 2006 -0700 @@ -45,6 +45,7 @@ #include #include +#include "urlencode.h" #include "base64.h" #define TMP_BUF_LEN 128 @@ -61,11 +62,17 @@ // creator, album, title, duration, trackNum, annotation, image, for(nptr = track->children; nptr != NULL; nptr = nptr->next){ if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "location")){ + GError *err = NULL; + gchar *tmp = NULL; xmlChar *str = xmlNodeGetContent(nptr); - location = g_locale_from_utf8(str,-1,NULL,NULL,NULL); - if(!location) - location = g_strdup(str); + tmp = g_locale_from_utf8(str, -1, NULL, NULL, &err); //for backward compatibility + if(err != NULL) + location = xspf_url_decode(str); + else + location = xspf_url_decode(tmp); + xmlFree(str); + g_free(tmp); g_free(err); } else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "creator")){ tuple->performer = (gchar *)xmlNodeGetContent(nptr); @@ -126,7 +133,7 @@ xmlFree(str); continue; } - else if(!xmlStrcmp(rel, "b64filename")){ + else if(!xmlStrcmp(rel, "b64filename")){ //for backward compatibility gchar *b64str = NULL; b64str = (gchar *)xmlNodeGetContent(nptr); b64filename = g_malloc0(strlen(b64str)*3/4+1); @@ -134,7 +141,6 @@ g_free(b64str); continue; } - xmlFree(rel); rel = NULL; } @@ -234,23 +240,17 @@ { PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); xmlNodePtr track, location; - gchar *utf_filename = NULL; - gboolean use_base64 = FALSE; + gchar *filename = NULL; track = xmlNewNode(NULL, "track"); location = xmlNewNode(NULL, "location"); - /* try locale encoding first */ - utf_filename = g_locale_to_utf8(entry->filename, -1, NULL, NULL, NULL); + /* url encode file name */ + filename = (gchar *)xspf_url_encode(entry->filename); + if(!g_utf8_validate(filename, -1, NULL)) + continue; - if (!utf_filename) { - use_base64 = TRUE; /* filename isn't straightforward. */ - /* if above fails, try to guess */ - utf_filename = str_to_utf8(entry->filename); - } - if(!g_utf8_validate(utf_filename, -1, NULL)) - continue; - xmlAddChild(location, xmlNewText(utf_filename)); + xmlAddChild(location, xmlNewText(filename)); xmlAddChild(track, location); xmlAddChild(tracklist, track); @@ -367,22 +367,8 @@ } } - - if (use_base64 && entry->filename) { - gchar *b64str = NULL; - b64str = g_malloc0(strlen(entry->filename)*2); - to64frombits(b64str, entry->filename, strlen(entry->filename)); - tmp = xmlNewNode(NULL, "meta"); - xmlSetProp(tmp, "rel", "b64filename"); - xmlAddChild(tmp, xmlNewText(b64str)); - xmlAddChild(track, tmp); - g_free(b64str); - use_base64 = FALSE; - } - - g_free(utf_filename); - utf_filename = NULL; - + g_free(filename); + filename = NULL; } PLAYLIST_UNLOCK();