# HG changeset patch # User yaz # Date 1158847735 25200 # Node ID 85d7e55b29d2ab2fd0d393263153828c22ebea25 # Parent 653288afa6e72fd2c3587981614890d3cb77444f [svn] - redundant metadata has been removed. - weird filename will be handled in base64 encoding. - "comment" is replaced with "annotation". diff -r 653288afa6e7 -r 85d7e55b29d2 ChangeLog --- a/ChangeLog Thu Sep 21 04:16:52 2006 -0700 +++ b/ChangeLog Thu Sep 21 07:08:55 2006 -0700 @@ -1,3 +1,12 @@ +2006-09-21 11:16:52 +0000 William Pitcock + revision [92] + - fix a $(BEEP_DEFINES) issue where -DDATA_DIR is wrong + + + Changes: Modified: + +1 -1 trunk/configure.ac + + 2006-09-21 11:03:13 +0000 William Pitcock revision [90] - drop libmusicbrainz requirement diff -r 653288afa6e7 -r 85d7e55b29d2 src/xspf/Makefile --- a/src/xspf/Makefile Thu Sep 21 04:16:52 2006 -0700 +++ b/src/xspf/Makefile Thu Sep 21 07:08:55 2006 -0700 @@ -5,7 +5,7 @@ LIBDIR = $(plugindir)/$(CONTAINER_PLUGIN_DIR) -SOURCES = xspf.c +SOURCES = xspf.c base64.c OBJECTS = ${SOURCES:.c=.o} diff -r 653288afa6e7 -r 85d7e55b29d2 src/xspf/base64.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xspf/base64.c Thu Sep 21 07:08:55 2006 -0700 @@ -0,0 +1,114 @@ +/** + * \file base64.c + * \brief base-64 conversion routines. + * + * \author Eric S. Raymond . + * + * For license terms, see the file COPYING. + * + * This base 64 encoding is defined in RFC2045 section 6.8, + * "Base64 Content-Transfer-Encoding", but lines must not be broken in the + * scheme used here. + */ +#include + + +static const char base64digits[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BAD -1 +static const char base64val[] = { + BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, + BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, + BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD, + BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD, + BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD +}; +#define DECODE64(c) (isascii(c) ? base64val[c] : BAD) + +/** + * \brief Raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) + * + * \param[out] out A pointer to a char to hold the converted string + * \param[in] in String to convert + * \param[in] inlen Length of the string to be converted + */ +void to64frombits(unsigned char *out, const unsigned char *in, int inlen) +{ + for (; inlen >= 3; inlen -= 3) + { + *out++ = base64digits[in[0] >> 2]; + *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *out++ = base64digits[in[2] & 0x3f]; + in += 3; + } + + if (inlen > 0) + { + unsigned char fragment; + + *out++ = base64digits[in[0] >> 2]; + fragment = (in[0] << 4) & 0x30; + + if (inlen > 1) + fragment |= in[1] >> 4; + + *out++ = base64digits[fragment]; + *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c]; + *out++ = '='; + } + + *out = '\0'; +} + +/** + * \brief base 64 to raw bytes in quasi-big-endian order, returning count of bytes + * + * \param[out] out Where to save the converted string + * \param[in] in String to convert + * \return Number of converted bytes. + */ +int from64tobits(char *out, const char *in) +{ + int len = 0; + register unsigned char digit1, digit2, digit3, digit4; + + if (in[0] == '+' && in[1] == ' ') + in += 2; + if (*in == '\r') + return(0); + + do { + digit1 = in[0]; + if (DECODE64(digit1) == BAD) + return(-1); + digit2 = in[1]; + if (DECODE64(digit2) == BAD) + return(-1); + digit3 = in[2]; + if (digit3 != '=' && DECODE64(digit3) == BAD) + return(-1); + digit4 = in[3]; + if (digit4 != '=' && DECODE64(digit4) == BAD) + return(-1); + in += 4; + *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4); + ++len; + if (digit3 != '=') + { + *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2); + ++len; + if (digit4 != '=') + { + *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4); + ++len; + } + } + } while (*in && *in != '\r' && digit4 != '='); + + return (len); +} diff -r 653288afa6e7 -r 85d7e55b29d2 src/xspf/base64.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xspf/base64.h Thu Sep 21 07:08:55 2006 -0700 @@ -0,0 +1,28 @@ +/** + * \file base64.h + * \brief This file has all base64.c declarations + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * See COPYING for details. + */ + +#ifndef BASE64_H_ +#define BASE64_H_ + +void to64frombits(unsigned char*,const unsigned char*,int); +int from64tobits(char*,const char*); + +#endif /* BASE64_H_ */ diff -r 653288afa6e7 -r 85d7e55b29d2 src/xspf/xspf.c --- a/src/xspf/xspf.c Thu Sep 21 04:16:52 2006 -0700 +++ b/src/xspf/xspf.c Thu Sep 21 07:08:55 2006 -0700 @@ -45,12 +45,16 @@ #include #include +#include "base64.h" + +#define TMP_BUF_LEN 128 + static void add_file(xmlNode *track, const gchar *filename, gint pos) { xmlNode *nptr; TitleInput *tuple; - gchar *locale_uri = NULL; + gchar *location = NULL, *b64filename = NULL, *locale_uri = NULL; tuple = bmp_title_input_new(); @@ -58,16 +62,10 @@ for(nptr = track->children; nptr != NULL; nptr = nptr->next){ if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "location")){ xmlChar *str = xmlNodeGetContent(nptr); - locale_uri = g_locale_from_utf8(str,-1,NULL,NULL,NULL); - if(!locale_uri){ - /* try ISO-8859-1 for last resort */ - locale_uri = g_convert(str, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL); - } + location = g_locale_from_utf8(str,-1,NULL,NULL,NULL); + if(!location) + location = g_strdup(str); xmlFree(str); - if(locale_uri){ - tuple->file_name = g_path_get_basename(locale_uri); - tuple->file_path = g_path_get_dirname(locale_uri); - } } else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "creator")){ tuple->performer = (gchar *)xmlNodeGetContent(nptr); @@ -88,11 +86,15 @@ tuple->track_number = atol(str); xmlFree(str); } + else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "annotation")){ + tuple->comment = (gchar *)xmlNodeGetContent(nptr); + continue; + } // // additional metadata // - // year, date, genre, comment, file_ext, file_path, formatter + // year, date, genre, formatter, mtime, b64filename // else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "meta")){ xmlChar *rel = NULL; @@ -113,30 +115,26 @@ tuple->genre = (gchar *)xmlNodeGetContent(nptr); continue; } - else if(!xmlStrcmp(rel, "comment")){ - tuple->comment = (gchar *)xmlNodeGetContent(nptr); - continue; - } - else if(!xmlStrcmp(rel, "file_ext")){ - tuple->file_ext = (gchar *)xmlNodeGetContent(nptr); - continue; - } - else if(!xmlStrcmp(rel, "file_path")){ - tuple->file_path = (gchar *)xmlNodeGetContent(nptr); - continue; - } else if(!xmlStrcmp(rel, "formatter")){ tuple->formatter = (gchar *)xmlNodeGetContent(nptr); continue; } else if(!xmlStrcmp(rel, "mtime")){ - xmlChar *str; + xmlChar *str = NULL; str = xmlNodeGetContent(nptr); tuple->mtime = (time_t)atoll(str); - if(str) - xmlFree(str); + xmlFree(str); continue; } + else if(!xmlStrcmp(rel, "b64filename")){ + gchar *b64str = NULL; + b64str = (gchar *)xmlNodeGetContent(nptr); + b64filename = g_malloc0(strlen(b64str)*3/4+1); + from64tobits(b64filename, b64str); + g_free(b64str); + continue; + } + xmlFree(rel); rel = NULL; } @@ -145,13 +143,20 @@ if (tuple->length == 0) { tuple->length = -1; } - // add file to playlist - playlist_load_ins_file_tuple(locale_uri, filename, pos, tuple); - pos++; - if(locale_uri) { - g_free(locale_uri); - locale_uri = NULL; + + locale_uri = b64filename ? b64filename : location; + + if(locale_uri){ + tuple->file_name = g_path_get_basename(locale_uri); + tuple->file_path = g_path_get_dirname(locale_uri); + tuple->file_ext = g_strdup(strrchr(locale_uri, '.')); + // add file to playlist + playlist_load_ins_file_tuple(locale_uri, filename, pos, tuple); + pos++; } + + g_free(location); g_free(b64filename); + locale_uri = NULL; location = NULL; b64filename = NULL; } static void @@ -223,6 +228,7 @@ PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); xmlNodePtr track, location; gchar *utf_filename = NULL; + gboolean use_base64 = FALSE; track = xmlNewNode(NULL, "track"); location = xmlNewNode(NULL, "location"); @@ -231,10 +237,10 @@ utf_filename = g_locale_to_utf8(entry->filename, -1, NULL, NULL, NULL); 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)); @@ -271,7 +277,7 @@ if (entry->tuple->length > 0) { gchar *str; - str = g_malloc(128); // XXX fix me. + str = g_malloc(TMP_BUF_LEN); tmp = xmlNewNode(NULL, "duration"); sprintf(str, "%d", entry->tuple->length); xmlAddChild(tmp, xmlNewText(str)); @@ -282,7 +288,7 @@ if (entry->tuple->track_number != 0) { gchar *str; - str = g_malloc(128); // XXX fix me. + str = g_malloc(TMP_BUF_LEN); tmp = xmlNewNode(NULL, "trackNum"); sprintf(str, "%d", entry->tuple->track_number); xmlAddChild(tmp, xmlNewText(str)); @@ -290,15 +296,23 @@ xmlAddChild(track, tmp); } + if (entry->tuple->comment != NULL && + g_utf8_validate(entry->tuple->comment, -1, NULL)) + { + tmp = xmlNewNode(NULL, "annotation"); + xmlAddChild(tmp, xmlNewText(entry->tuple->comment)); + xmlAddChild(track, tmp); + } + // // additional metadata // - // year, date, genre, comment, file_ext, file_path, formatter + // year, date, genre, formatter, mtime // if (entry->tuple->year != 0) { gchar *str; - str = g_malloc(128); // XXX fix me. + str = g_malloc(TMP_BUF_LEN); tmp = xmlNewNode(NULL, "meta"); xmlSetProp(tmp, "rel", "year"); sprintf(str, "%d", entry->tuple->year); @@ -325,33 +339,6 @@ xmlAddChild(track, tmp); } - if (entry->tuple->comment != NULL && - g_utf8_validate(entry->tuple->comment, -1, NULL)) - { - tmp = xmlNewNode(NULL, "meta"); - xmlSetProp(tmp, "rel", "comment"); - xmlAddChild(tmp, xmlNewText(entry->tuple->comment)); - xmlAddChild(track, tmp); - } - - if (entry->tuple->file_ext != NULL && - g_utf8_validate(entry->tuple->file_ext, -1, NULL)) - { - tmp = xmlNewNode(NULL, "meta"); - xmlSetProp(tmp, "rel", "file_ext"); - xmlAddChild(tmp, xmlNewText(entry->tuple->file_ext)); - xmlAddChild(track, tmp); - } - - if (entry->tuple->file_path != NULL && - g_utf8_validate(entry->tuple->file_path, -1, NULL)) - { - tmp = xmlNewNode(NULL, "meta"); - xmlSetProp(tmp, "rel", "file_path"); - xmlAddChild(tmp, xmlNewText(entry->tuple->file_path)); - xmlAddChild(track, tmp); - } - if (entry->tuple->formatter != NULL && g_utf8_validate(entry->tuple->formatter, -1, NULL)) { @@ -363,20 +350,32 @@ if (entry->tuple->mtime) { gchar *str; - str = g_malloc(128); // XXX fix me. + str = g_malloc(TMP_BUF_LEN); tmp = xmlNewNode(NULL, "meta"); xmlSetProp(tmp, "rel", "mtime"); sprintf(str, "%ld", (long) entry->tuple->mtime); xmlAddChild(tmp, xmlNewText(str)); xmlAddChild(track, tmp); g_free(str); - } + } } - if(utf_filename) { - g_free(utf_filename); - utf_filename = NULL; + + 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; + } xmlSaveFormatFile(filename, doc, 1);