|
View:
New views
2 Messages
—
Rating Filter:
Alert me
|
|
|
Patch: support for deflated iTunesCDB from iPhone OS 3.0Hi,
please find attached a patch that - makes libgpod prefer iTunesCDB over iTunesDB - inflates everything after the 188 header on reading when the file is named iTunesCDB - deflates everything after the header in the same case together with another patch that - adds a simple test program that converts between iTunesCDB and iTunesDB. Please let me know if I should change anything. Regards, Martin [0001-uncompress-iTunesCDB-files-before-parsing-recompres.patch] From 83b6a8ebd0a91c99efe533299cfd4fc3f23c39be Mon Sep 17 00:00:00 2001 From: Martin Aumueller <aumuell@...> Date: Mon, 13 Jul 2009 07:19:21 +0200 Subject: [PATCH 1/2] uncompress iTunesCDB files before parsing, recompress before writing iPhoneOS 3.0 with iTunes 8.2 seems to prefer a 'deflate' compressed version of iTunesDB with the filename iTunesCDB over iTunesDB --- configure.ac | 18 +++++ src/Makefile.am | 2 +- src/itdb.h | 3 +- src/itdb_itunesdb.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 226 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index a8cfad0..2318c62 100644 --- a/configure.ac +++ b/configure.ac @@ -93,6 +93,24 @@ fi AC_SUBST(SGUTILS_LIBS) AM_CONDITIONAL(HAVE_SGUTILS, test x"$have_sgutils" = xyes) +dnl ************************************************** +dnl * zlib is neeeded for handling compressed iTunesCDB files +dnl ************************************************** +AC_CHECK_LIB(z, inflate, + [Z_LIBS="-lz"; have_zlib=yes], + have_zlib=no) +if test "x$have_zlib" != xyes; then + AC_CHECK_LIB(zlib, inflate, + [Z_LIBS="-lzlib"; have_zlib=yes], + have_zlib=no) +fi +if test x"$have_zlib" = xyes; then + AH_TEMPLATE([HAVE_ZLIB], [Whether zlib is installed, it's used for compressed iTunesCDB]) + AC_DEFINE_UNQUOTED(HAVE_ZLIB, 1) +fi +AC_SUBST(Z_LIBS) +AM_CONDITIONAL(HAVE_ZLIB, test x"$have_zlib" = xyes) + dnl *********************************************************************** dnl * HAL is optional, but is required if you want things to "just work" dnl * when a recent iPod is plugged in diff --git a/src/Makefile.am b/src/Makefile.am index 962c591..9cfdbd4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,7 +50,7 @@ noinst_HEADERS = \ sha1.h INCLUDES=$(LIBGPOD_CFLAGS) -LIBS=$(LIBGPOD_LIBS) -lm +LIBS=$(LIBGPOD_LIBS) $(Z_LIBS) -lm uninstall-hook: -rmdir --ignore-fail-on-non-empty $(DESTDIR)$(libgpodincludedir) diff --git a/src/itdb.h b/src/itdb.h index ddc0cde..8ecfe19 100644 --- a/src/itdb.h +++ b/src/itdb.h @@ -1674,7 +1674,8 @@ typedef enum ITDB_FILE_ERROR_CORRUPT, ITDB_FILE_ERROR_NOTFOUND, ITDB_FILE_ERROR_RENAME, - ITDB_FILE_ERROR_ITDB_CORRUPT + ITDB_FILE_ERROR_ITDB_CORRUPT, + ITDB_FILE_ERROR_NOTCOMPRESSED } ItdbFileError; diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c index ed66e98..a87cf5e 100644 --- a/src/itdb_itunesdb.c +++ b/src/itdb_itunesdb.c @@ -120,6 +120,9 @@ #include <string.h> #include <sys/types.h> #include <time.h> +#ifdef HAVE_ZLIB +#include <zlib.h> +#endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -2924,9 +2927,142 @@ static void error_no_control_dir (const gchar *mp, GError **error) } #endif +#ifdef HAVE_ZLIB +/** + * itdb_inflate: + * @source: data to be decompressed + * @sourcelen: length of input data + * @dest: output data, will be resized using g_realloc + * @destlen: output buffer size + * @destoff: offset in output buffer + * + * decompress using inflate algorithm as implemented in zlib, + * based on inf function in the zlib example zpipe.c + * + * Returns: TRUE if successful + */ +static gboolean +itdb_inflate(const gchar *source, gsize sourcelen, gchar **dest, gsize *destlen, gsize destoff) +{ + const int chunksize = 65536; + int ret; + z_stream strm; + + if (sourcelen <= 0) + return TRUE; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return FALSE; + + /* decompress until deflate stream ends or end of file */ + strm.avail_in = sourcelen; + + strm.next_in = (unsigned char *)source; + + *destlen += chunksize; + *dest = g_realloc(*dest, *destlen); + + /* run inflate() on input until output buffer not full */ + do { + strm.avail_out = *destlen-destoff; + strm.next_out = (unsigned char *)(*dest+destoff); + ret = inflate(&strm, Z_NO_FLUSH); + g_assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return FALSE; + } + destoff = *destlen - strm.avail_out; + if (strm.avail_out == 0) + { + *destlen += chunksize; + *dest = g_realloc(*dest, *destlen); + } + } while (strm.avail_out == 0); + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? TRUE : FALSE; +} +/** + * itdb_deflate: + * @source: data to be compressed + * @sourcelen: length of input data + * @dest: output data, will be resized using g_realloc + * @destlen: output buffer size + * @destoff: offset in output buffer + * + * compress using deflate algorithm as implemented in zlib with compression level 1, + * based on inf function in the zlib example zpipe.c + * + * Returns: TRUE if successful + */ static gboolean -itdb_parse_internal (Itdb_iTunesDB *itdb, GError **error) +itdb_deflate(const gchar *source, gsize sourcelen, gchar **dest, gsize *destlen, gsize destoff) +{ + const int level = 1; + const int chunksize = 65536; + int ret, flush; + z_stream strm; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, level); + if (ret != Z_OK) + return FALSE; + + strm.avail_in = sourcelen; + strm.next_in = (unsigned char *)source; + + *destlen += chunksize; + *dest = g_realloc(*dest, *destlen); + + flush = Z_FINISH; + + /* run deflate() on input until output buffer not full, finish + compression if all of source has been read in */ + do { + strm.avail_out = *destlen-destoff; + strm.next_out = (unsigned char *)(*dest+destoff); + ret = deflate(&strm, flush); /* no bad return value */ + g_assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + destoff = *destlen - strm.avail_out; + if (strm.avail_out == 0) + { + *destlen += chunksize; + *dest = g_realloc(*dest, *destlen); + } + else + { + *destlen -= strm.avail_out; + *dest = g_realloc(*dest, *destlen); + } + } while (strm.avail_out == 0); + g_assert(strm.avail_in == 0); /* all input will be used */ + g_assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return TRUE; +} +#endif + +static gboolean +itdb_parse_internal (Itdb_iTunesDB *itdb, gboolean compressed, GError **error) { FImport *fimp; gboolean success = FALSE; @@ -2936,7 +3072,42 @@ itdb_parse_internal (Itdb_iTunesDB *itdb, GError **error) fimp = g_new0 (FImport, 1); fimp->itdb = itdb; - fimp->fcontents = fcontents_read (itdb->filename, error); + if (compressed) + { +#ifdef HAVE_ZLIB + fimp->fcontents = fcontents_read (itdb->filename, error); + if (fimp->fcontents) + { + gchar *decompressed = NULL; + gsize length = 0; + FContents *cts = fimp->fcontents; + if (!itdb_inflate (cts->contents+188, cts->length-188, &decompressed, &length, 188)) + { + g_set_error (error, + ITDB_FILE_ERROR, + ITDB_FILE_ERROR_NOTCOMPRESSED, + _("File not in compressed format: '%s'."), + itdb->filename); + } + else + { + g_memmove (decompressed, cts->contents, 188); + g_free (cts->contents); + cts->contents = decompressed; + cts->length = length; + } + } +#else + g_set_error (error, + ITDB_FILE_ERROR, + ITDB_FILE_ERROR_NOTCOMPRESSED, + _("Decompression not available.")); +#endif + } + else + { + fimp->fcontents = fcontents_read (itdb->filename, error); + } if (fimp->fcontents) { @@ -2978,6 +3149,7 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error) gchar *itunes_dir; Itdb_iTunesDB *itdb = NULL; const gchar *db[] = {"iTunesDB", NULL}; + const gchar *cdb[] = {"iTunesCDB", NULL}; itunes_dir = itdb_get_itunes_dir (mp); @@ -2988,7 +3160,12 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error) return NULL; } - filename = itdb_resolve_path (itunes_dir, db); + filename = itdb_resolve_path (itunes_dir, cdb); + + if (!filename) + { + filename = itdb_resolve_path (itunes_dir, db); + } if (filename) { @@ -3000,7 +3177,7 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error) itdb_set_mountpoint (itdb, mp); itdb->filename = filename; - success = itdb_parse_internal (itdb, error); + success = itdb_parse_internal (itdb, g_str_has_suffix (itdb->filename, "/iTunesCDB"), error); if (success) { /* We don't test the return value of ipod_parse_artwork_db @@ -3069,7 +3246,7 @@ Itdb_iTunesDB *itdb_parse_file (const gchar *filename, GError **error) itdb = itdb_new (); itdb->filename = g_strdup (filename); - success = itdb_parse_internal (itdb, error); + success = itdb_parse_internal (itdb, g_str_has_suffix (itdb->filename, "/iTunesCDB"), error); if (!success) { itdb_free (itdb); @@ -5315,6 +5492,29 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename, } if (!fexp->error) { +#ifdef HAVE_ZLIB + if (g_str_has_suffix (itdb->filename, "/iTunesCDB")) + { + gchar *compressed = NULL; + gsize length = 0; + WContents *cts = fexp->wcontents; + if (!itdb_deflate (cts->contents+188, cts->total-188, &compressed, &length, 188)) + { + g_set_error (error, + ITDB_FILE_ERROR, + ITDB_FILE_ERROR_NOTCOMPRESSED, + _("Compression failure: '%s'."), + itdb->filename); + } + else + { + g_memmove (compressed, cts->contents, 188); + g_free (cts->contents); + cts->contents = compressed; + cts->total = length; + } + } +#endif if (!wcontents_write (cts)) g_propagate_error (&fexp->error, cts->error); } -- 1.6.2.5 [0002-simple-iTunesCDB-test-convert-between-iTunesDB-and.patch] From e55da9c80cc981609e34ed8fcd8bf4446aefd6ff Mon Sep 17 00:00:00 2001 From: Martin Aumueller <aumuell@...> Date: Thu, 16 Jul 2009 09:18:20 +0200 Subject: [PATCH 2/2] simple iTunesCDB test: convert between iTunesDB and iTunesCDB --- tests/Makefile.am | 12 +++++- tests/test-compress.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletions(-) create mode 100644 tests/test-compress.c diff --git a/tests/Makefile.am b/tests/Makefile.am index b4bbcc6..6ea0bd9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,6 +13,15 @@ else TESTTHUMBS= endif +if HAVE_ZLIB +TESTCOMPRESS=test-compress + +test_compress_SOURCES = test-compress.c +test_compress_LDADD = +else +TESTCOMPRESS= +endif + TESTMISC=test-init-ipod if HAVE_TAGLIB @@ -30,6 +39,7 @@ test_itdb_LDADD = test_ls_SOURCES = test-ls.c test_ls_LDADD = + test_init_ipod_SOURCES = test-init-ipod.c test_init_ipod_LDADD = @@ -48,7 +58,7 @@ get_timezone_SOURCES = get-timezone.c noinst_PROGRAMS=test-itdb test-ls test-checksum test-firewire-id \ test-sysinfo-extended-parsing \ - $(TESTTHUMBS) $(TESTTAGLIB) $(TESTMISC) + $(TESTTHUMBS) $(TESTTAGLIB) $(TESTMISC) $(TESTCOMPRESS) INCLUDES=$(LIBGPOD_CFLAGS) -I$(top_srcdir)/src -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" LIBS=$(LIBGPOD_LIBS) $(top_builddir)/src/libgpod.la diff --git a/tests/test-compress.c b/tests/test-compress.c new file mode 100644 index 0000000..e693ff7 --- /dev/null +++ b/tests/test-compress.c @@ -0,0 +1,115 @@ +/* +| Copyright (C) 2002-2003 Jorg Schuler <jcsjcs at users.sourceforge.net> +| Copyright (C) 2006 Christophe Fergeau <teuf@...> +| +| 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 +| +| iTunes and iPod are trademarks of Apple +| +| This product is not supported/written/published by Apple! +| +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <libintl.h> + +#include "itdb.h" + +#define LOCALDB "/.gtkpod/local_0.itdb" + +int +main (int argc, char *argv[]) +{ + GError *error=NULL; + const gchar *homeenv="HOME"; + Itdb_iTunesDB *itdb; + gchar *mountpoint = NULL, *playlistname = NULL; + + if (argc >= 2) + mountpoint = argv[1]; + + if (argc >= 3) + playlistname = argv[2]; + + if (mountpoint == NULL) + { + g_print ("Usage: %s <mountpoint>|-l\n\n", + g_basename(argv[0])); + exit (0); + } + + if (strcmp(mountpoint, "-l") == 0) { + mountpoint = g_build_filename(g_getenv(homeenv), LOCALDB, NULL); + itdb = itdb_parse_file (mountpoint, &error); + } + else + itdb = itdb_parse (mountpoint, &error); + + if (error) + { + if (error->message) { + g_print("%s\n", error->message); + } + g_error_free (error); + error = NULL; + } + + if (itdb) + { + gchar *filename = itdb->filename; + if (g_str_has_suffix (filename, "/iTunesDB") ) + { + gsize len = strlen (filename); + filename = g_strndup (filename, len+1); + ++len; + filename[len-3] = 'C'; + filename[len-2] = 'D'; + filename[len-1] = 'B'; + filename[len] = '\0'; + } + else if (g_str_has_suffix (filename, "/iTunesCDB") ) + { + gsize len = strlen (filename); + filename = g_strdup (filename); + --len; + filename[len-2] = 'D'; + filename[len-1] = 'B'; + filename[len] = '\0'; + } + + itdb_write_file (itdb, filename, &error); + + if (error) + { + if (error->message) { + g_print("%s\n", error->message); + } + g_error_free (error); + error = NULL; + } + + g_free (filename); + } + itdb_free (itdb); + + return 0; +} -- 1.6.2.5 ------------------------------------------------------------------------------ Enter the BlackBerry Developer Challenge This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge _______________________________________________ Gtkpod-devel mailing list Gtkpod-devel@... https://lists.sourceforge.net/lists/listinfo/gtkpod-devel |
|
|
Re: Patch: support for deflated iTunesCDB from iPhone OS 3.0One more thing that I forgot to say in my previous mail: thank you to
Christophe Fergeau for providing the information about iTunesCDB! On Friday 17 July 2009 00:09:27 Martin Aumueller wrote: > Hi, > > please find attached a patch that > - makes libgpod prefer iTunesCDB over iTunesDB > - inflates everything after the 188 header on reading when the file is > named iTunesCDB > - deflates everything after the header in the same case > together with another patch that > - adds a simple test program that converts between iTunesCDB and iTunesDB. > > Please let me know if I should change anything. > > Regards, > Martin ------------------------------------------------------------------------------ Enter the BlackBerry Developer Challenge This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge _______________________________________________ Gtkpod-devel mailing list Gtkpod-devel@... https://lists.sourceforge.net/lists/listinfo/gtkpod-devel |
| Free embeddable forum powered by Nabble | Forum Help |