commit b9b83dc8b6c3d1f0c53ed32f05279ca838d54e02
Author: Nikias Bassen <nik...@gmx.li>
Date:   Mon Oct 4 01:15:39 2010 +0200

    add hashAB support via external module

 configure.ac           |   10 +++
 src/Makefile.am        |    2 +
 src/db-itunes-parser.h |    2 +
 src/itdb_device.c      |    1 +
 src/itdb_hashAB.c      |  145 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/itdb_itunesdb.c    |   30 +++++++---
 src/itdb_private.h     |   24 +++++---
 src/itdb_sqlite.c      |   54 +++++++++++++-----
 8 files changed, 237 insertions(+), 31 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 8704506..296f56e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -192,6 +192,16 @@ AC_SUBST(TMPMOUNTDIR)
 AH_TEMPLATE([TMPMOUNTDIR], [Directory where HAL/udev will create a 
sub-directory to mount iPods])
 AC_DEFINE_UNQUOTED(TMPMOUNTDIR, "$with_temp_mount_dir", [Directory where 
HAL/udev will create a sub-directory to mount iPods])
 
+dnl ***********************************************************************
+dnl * provide a $l{ibdir}/libgpod directory for external modules
+dnl ***********************************************************************
+AC_ARG_WITH(libgpod-blob-dir, [AC_HELP_STRING([--with-libgpod-blob-dir=PATH],
+                                              [Load libgpod binary blobs from 
this directory [LIBDIR/libgpod]])],
+            [],
+            [with_libgpod_blob_dir='${libdir}/libgpod'])
+LIBGPOD_BLOB_DIR=$with_libgpod_blob_dir
+AC_SUBST(LIBGPOD_BLOB_DIR)
+
 dnl **************************************************
 dnl * TagLib is only used by test-rebuild-db 
 dnl **************************************************
diff --git a/src/Makefile.am b/src/Makefile.am
index ce02831..90148f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@ libgpod_la_SOURCES =          \
        itdb_device.c           \
        itdb_hash58.c           \
        itdb_hash72.c           \
+       itdb_hashAB.c           \
        itdb_iphone.c           \
        itdb_itunesdb.c         \
        itdb_photoalbum.c       \
@@ -32,6 +33,7 @@ libgpod_la_CFLAGS = -DWITH_INTERNAL_GCHECKSUM
 endif
 
 libgpod_la_LDFLAGS = -version-info $(LIBGPOD_SO_VERSION) -no-undefined
+libgpod_la_CPPFLAGS = -DLIBGPOD_BLOB_DIR=\"$(LIBGPOD_BLOB_DIR)\"
 
 libgpodincludebase = $(includedir)/gpod-1.0
 libgpodincludedir = $(libgpodincludebase)/gpod
diff --git a/src/db-itunes-parser.h b/src/db-itunes-parser.h
index cc71bcc..80d5213 100644
--- a/src/db-itunes-parser.h
+++ b/src/db-itunes-parser.h
@@ -102,6 +102,8 @@ struct _MhbdHeader {
        guint16 unk_0xa4;
        guint16 unk_0xa6;
        guint16 unk_0xa8;
+       guchar align_0xa9;
+       guchar hashAB[57];
        guchar  padding[];
 } __attribute__((__packed__));
 
diff --git a/src/itdb_device.c b/src/itdb_device.c
index 42c4b23..f1aabad 100644
--- a/src/itdb_device.c
+++ b/src/itdb_device.c
@@ -1938,6 +1938,7 @@ G_GNUC_INTERNAL gboolean itdb_device_write_checksum 
(Itdb_Device *device,
        case ITDB_CHECKSUM_HASH72:
            return itdb_hash72_write_hash (device, itdb_data, itdb_len, error);
         case ITDB_CHECKSUM_HASHAB:
+           return itdb_hashAB_write_hash (device, itdb_data, itdb_len, error);
        case ITDB_CHECKSUM_UNKNOWN:
             g_set_error (error, 0, -1, "Unsupported checksum type");
            return FALSE;
diff --git a/src/itdb_hashAB.c b/src/itdb_hashAB.c
new file mode 100644
index 0000000..ce0f794
--- /dev/null
+++ b/src/itdb_hashAB.c
@@ -0,0 +1,145 @@
+/*
+|  Copyright (c) 2010 Nikias Bassen <nik...@gmx.li>
+| 
+|  The code contained in this file is free software; you can redistribute
+|  it and/or modify it under the terms of the GNU Lesser General Public
+|  License as published by the Free Software Foundation; either version
+|  2.1 of the License, or (at your option) any later version.
+|
+|  This file 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
+|  Lesser General Public License for more details.
+|
+|  You should have received a copy of the GNU Lesser General Public
+|  License along with this code; 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!
+*/
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include "rijndael.h"
+
+#include <glib/gstdio.h>
+
+#include <gmodule.h>
+
+#include "itdb_device.h"
+#include "db-itunes-parser.h"
+#include "itdb_private.h"
+
+typedef void (*calcHashAB_t)(unsigned char target[57], const unsigned char 
sha1[20], const unsigned char uuid[20], const unsigned char rnd_bytes[23]);
+static calcHashAB_t calc_hashAB = NULL;
+
+static gboolean load_libhashab()
+{
+       gchar *path;
+       GModule *handle;
+
+       if (!g_module_supported()) {
+               return FALSE;
+       }
+       path = g_module_build_path(LIBGPOD_BLOB_DIR, "hashab");
+       handle = g_module_open(path, G_MODULE_BIND_LAZY);
+       g_free(path);
+       if (!handle) {
+               return FALSE;
+       }
+
+       if (!g_module_symbol(handle, "calcHashAB", (void**)&calc_hashAB)) {
+               g_module_close(handle);
+               g_warning("symbol 'calcHashAB' not found");
+               return FALSE;
+       }
+       g_module_make_resident(handle);
+
+       printf("***** hashAB support successfully loaded *****\n");
+
+       return TRUE;
+}
+
+static void itdb_hashAB_compute_itunesdb_sha1 (unsigned char *itdb_data, 
+                                              gsize itdb_len,
+                                              unsigned char sha1[20])
+{
+    guchar backup18[8];
+    guchar backup32[20];
+    guchar hashAB[57];
+    gsize sha1_len;
+    GChecksum *checksum;
+    MhbdHeader *header;
+
+    g_assert (itdb_len >= 0x6c);
+
+    header = (MhbdHeader *)itdb_data;
+    g_assert (strncmp (header->header_id, "mhbd", strlen ("mhbd")) == 0);
+    memcpy (backup18, &header->db_id, sizeof (backup18));
+    memcpy (backup32, &header->unk_0x32, sizeof (backup32));
+    memcpy (hashAB, &header->hashAB, sizeof (hashAB));
+
+    /* Those fields must be zero'ed out for the sha1 calculation */
+    memset(&header->db_id, 0, sizeof (header->db_id));
+
+    memset(&header->hash58, 0, sizeof (header->hash58));
+    memset(&header->hash72, 0, sizeof (header->hash72));
+    memset(&header->hashAB, 0, sizeof (header->hashAB));
+
+    sha1_len = g_checksum_type_get_length (G_CHECKSUM_SHA1);
+    checksum = g_checksum_new (G_CHECKSUM_SHA1);
+    g_checksum_update (checksum, itdb_data, itdb_len);
+    g_checksum_get_digest (checksum, sha1, &sha1_len);
+    g_checksum_free (checksum);
+
+    memcpy (&header->db_id, backup18, sizeof (backup18));
+    memcpy (&header->unk_0x32, backup32, sizeof (backup32));
+}
+
+gboolean itdb_hashAB_compute_hash_for_sha1 (const Itdb_Device *device,
+                                           const guchar sha1[20],
+                                           guchar signature[57],
+                                           GError **error)
+{
+    unsigned char uuid[20];
+    unsigned char rndpart[23] = "ABCDEFGHIJKLMNOPQRSTUVW";
+
+    if (calc_hashAB == NULL) {
+       if (!load_libhashab()) {
+           g_set_error (error, 0, -1, "Unsupported checksum type");
+           return FALSE;
+       }
+    }
+
+    if (!get_uuid(device, uuid)) return FALSE;
+
+    calc_hashAB(signature, sha1, uuid, rndpart);
+
+    return TRUE;
+}
+
+gboolean itdb_hashAB_write_hash (const Itdb_Device *device,
+                                unsigned char *itdb_data,
+                                gsize itdb_len,
+                                GError **error)
+{
+    guchar sha1[20];
+    MhbdHeader *header;
+
+    if (itdb_len < 0xF4) {
+       g_set_error (error, 0, -1, "iTunesDB file too small to write checksum");
+       return FALSE;
+    }
+
+    header = (MhbdHeader *)itdb_data;
+    header->hashing_scheme = GUINT16_FROM_LE (ITDB_CHECKSUM_HASHAB);
+    itdb_hashAB_compute_itunesdb_sha1 (itdb_data, itdb_len, sha1);
+    return itdb_hashAB_compute_hash_for_sha1 (device, sha1, header->hashAB, 
error);
+}
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index 7f587bf..9ccf61a 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -3801,7 +3801,7 @@ static void mk_mhbd (FExport *fexp, guint32 children)
   cts = fexp->wcontents;
 
   put_header (cts, "mhbd");
-  put32lint (cts, 188); /* header size */
+  put32lint (cts, 244); /* header size */
   put32lint (cts, -1);  /* size of whole mhdb -- fill in later */
   if (itdb_device_supports_compressed_itunesdb (fexp->itdb->device)) {
       /* 2 on iPhone 3.0 and Nano 5G, 1 on iPod Color and iPod Classic
@@ -3830,10 +3830,12 @@ static void mk_mhbd (FExport *fexp, guint32 children)
                      0x19 = iTunes 7.4
                      0x28 = iTunes 8.2.1
                     0x2a = iTunes 9.0.1
+                    0x2e = iTunes 9.1
+                    0x30 = iTunes 9.2
     Be aware that newer ipods won't work if the library version number is too 
     old
   */
-  fexp->itdb->version = 0x2a;
+  fexp->itdb->version = 0x30;
   put32lint (cts, fexp->itdb->version);
   put32lint (cts, children);
   put64lint (cts, fexp->itdb->id);
@@ -3857,20 +3859,32 @@ static void mk_mhbd (FExport *fexp, guint32 children)
                                                 /* seen: 0x01 for iPod Color   
    */
   put32lint (cts, fexp->itdb->priv->unk_0x54);  /* unknown: seen: 0x4d for 
nano 3G */
                                                /* seen: 0x0f for iPod Color    
   */
-  put32_n0 (cts, 5);    /* 20 bytes hash */
+  put32_n0 (cts, 5);    /* 20 bytes hash58 */
   put32lint (cts, fexp->itdb->tzoffset);   /* timezone offset in seconds */
   /* 0x70 */
-  put16lint (cts, 2);   /* without it, iTunes thinks iPhone databases
-                          are corrupted, 0 on iPod Color */
-  put16lint (cts, 0);
-  put32_n0 (cts, 11);   /* new hash */
+  switch (itdb_device_get_checksum_type(fexp->itdb->device)) {
+    case ITDB_CHECKSUM_HASHAB:
+      put16lint (cts, 4);   /* new on 4th gen iOS devices */
+      break;
+    case ITDB_CHECKSUM_HASH72:
+      put16lint (cts, 2);
+      break;
+    default:
+      put16lint (cts, 0);
+      break;
+  }
+  put16lint (cts, 0);   /* hash72 */
+  put32_n0 (cts, 11);   /* hash72 */
   /* 0xa0 */
   put16lint (cts, fexp->itdb->priv->audio_language); /* audio_language */
   put16lint (cts, fexp->itdb->priv->subtitle_language); /* subtitle_language */
   put16lint (cts, fexp->itdb->priv->unk_0xa4); /* unknown */
   put16lint (cts, fexp->itdb->priv->unk_0xa6); /* unknown */
   put16lint (cts, fexp->itdb->priv->unk_0xa8); /* unknown */
-  put16lint (cts, 0);
+  put8int (cts, 0);
+  /* 0xab */
+  put8int (cts, 0);   /* hashAB */
+  put32_n0 (cts, 14); /* hashAB */
   put32_n0 (cts, 4); /* dummy space */
 }
 
diff --git a/src/itdb_private.h b/src/itdb_private.h
index afc694e..56dd5d7 100644
--- a/src/itdb_private.h
+++ b/src/itdb_private.h
@@ -224,24 +224,32 @@ G_GNUC_INTERNAL gint itdb_get_max_photo_id ( Itdb_PhotoDB 
*db );
 G_GNUC_INTERNAL Itdb_iTunesDB *db_get_itunesdb (Itdb_DB *db);
 G_GNUC_INTERNAL Itdb_PhotoDB *db_get_photodb (Itdb_DB *db);
 G_GNUC_INTERNAL gint itdb_thumb_get_byteorder (ItdbThumbFormat format);
-G_GNUC_INTERNAL time_t device_time_mac_to_time_t (Itdb_Device *device, 
+G_GNUC_INTERNAL time_t device_time_mac_to_time_t (Itdb_Device *device,
                                                guint64 mactime);
 G_GNUC_INTERNAL guint64 device_time_time_t_to_mac (Itdb_Device *device,
                                                 time_t timet);
 G_GNUC_INTERNAL gint itdb_musicdirs_number_by_mountpoint (const gchar 
*mountpoint);
 G_GNUC_INTERNAL int itdb_sqlite_generate_itdbs(FExport *fexp);
-G_GNUC_INTERNAL gboolean itdb_hash72_extract_hash_info(const Itdb_Device 
*device, 
-                                                      unsigned char 
*itdb_data, 
+G_GNUC_INTERNAL gboolean itdb_hashAB_write_hash (const Itdb_Device *device,
+                                                unsigned char *itdb_data,
+                                                gsize itdb_len,
+                                                GError **error);
+G_GNUC_INTERNAL gboolean itdb_hash72_extract_hash_info(const Itdb_Device 
*device,
+                                                      unsigned char *itdb_data,
                                                       gsize itdb_len);
-G_GNUC_INTERNAL gboolean itdb_hash72_write_hash (const Itdb_Device *device, 
-                                                unsigned char *itdb_data, 
+G_GNUC_INTERNAL gboolean itdb_hash72_write_hash (const Itdb_Device *device,
+                                                unsigned char *itdb_data,
                                                 gsize itdb_len,
                                                 GError **error);
-G_GNUC_INTERNAL gboolean itdb_hash58_write_hash (Itdb_Device *device, 
-                                                unsigned char *itdb_data, 
+G_GNUC_INTERNAL gboolean itdb_hash58_write_hash (Itdb_Device *device,
+                                                unsigned char *itdb_data,
                                                 gsize itdb_len,
                                                 GError **error);
-G_GNUC_INTERNAL gboolean itdb_hash72_compute_hash_for_sha1 (const Itdb_Device 
*device, 
+G_GNUC_INTERNAL gboolean itdb_hashAB_compute_hash_for_sha1 (const Itdb_Device 
*device,
+                                                           const guchar 
sha1[20],
+                                                           guchar 
signature[57],
+                                                           GError **error);
+G_GNUC_INTERNAL gboolean itdb_hash72_compute_hash_for_sha1 (const Itdb_Device 
*device,
                                                            const guchar 
sha1[20],
                                                            guchar 
signature[46],
                                                            GError **error);
diff --git a/src/itdb_sqlite.c b/src/itdb_sqlite.c
index a5a0738..4e0197a 100644
--- a/src/itdb_sqlite.c
+++ b/src/itdb_sqlite.c
@@ -2041,24 +2041,22 @@ error:
     return FALSE;
 }
 
-static const guint CBK_HEADER_SIZE = 46;
-
-static void cbk_calc_sha1_of_sha1s(GArray *cbk)
+static void cbk_calc_sha1_of_sha1s(GArray *cbk, guint cbk_header_size)
 {
     GChecksum *checksum;
     unsigned char* final_sha1;
     unsigned char* sha1s;
     gsize final_sha1_len;
 
-    g_assert (cbk->len > CBK_HEADER_SIZE + 20);
+    g_assert (cbk->len > cbk_header_size + 20);
 
-    final_sha1 = &g_array_index(cbk, guchar, CBK_HEADER_SIZE);
-    sha1s = &g_array_index(cbk, guchar, CBK_HEADER_SIZE + 20);
+    final_sha1 = &g_array_index(cbk, guchar, cbk_header_size);
+    sha1s = &g_array_index(cbk, guchar, cbk_header_size + 20);
     final_sha1_len = g_checksum_type_get_length(G_CHECKSUM_SHA1);
     g_assert (final_sha1_len == 20);
 
     checksum = g_checksum_new(G_CHECKSUM_SHA1);
-    g_checksum_update(checksum, sha1s, cbk->len - (CBK_HEADER_SIZE + 20));
+    g_checksum_update(checksum, sha1s, cbk->len - (cbk_header_size + 20));
     g_checksum_get_digest(checksum, final_sha1, &final_sha1_len);
     g_checksum_free(checksum);
 }
@@ -2069,12 +2067,30 @@ static gboolean mk_Locations_cbk(Itdb_iTunesDB *itdb, 
const char *dirname)
     char *cbk_filename;
     GArray *cbk;
     gboolean success;
-    guchar *cbk_hash72;
+    guchar *cbk_hash;
     guchar *final_sha1;
+    guint cbk_header_size = 0;
+    guint checksum_type;
+
+    checksum_type = itdb_device_get_checksum_type(itdb->device);
+    switch (checksum_type) {
+       case ITDB_CHECKSUM_HASHAB:
+           cbk_header_size = 57;
+           break;
+       case ITDB_CHECKSUM_HASH72:
+           cbk_header_size = 46;
+           break;
+       default:
+           break;
+    }
+    if (cbk_header_size == 0) {
+       fprintf(stderr, "ERROR: Unsupported checksum type '%d' in cbk file 
generation!\n", checksum_type);
+       return FALSE;
+    }
 
     cbk = g_array_sized_new(FALSE, TRUE, 1,
-                           CBK_HEADER_SIZE + 20);
-    g_array_set_size(cbk, CBK_HEADER_SIZE + 20);
+                           cbk_header_size + 20);
+    g_array_set_size(cbk, cbk_header_size + 20);
 
     locations_filename = g_build_filename(dirname, "Locations.itdb", NULL);
     success = cbk_calc_sha1s(locations_filename, cbk);
@@ -2083,11 +2099,19 @@ static gboolean mk_Locations_cbk(Itdb_iTunesDB *itdb, 
const char *dirname)
        g_array_free(cbk, TRUE);
        return FALSE;
     }
-    cbk_calc_sha1_of_sha1s(cbk);
-    final_sha1 = &g_array_index(cbk, guchar, CBK_HEADER_SIZE);
-    cbk_hash72 = &g_array_index(cbk, guchar, 0);
-    success = itdb_hash72_compute_hash_for_sha1 (itdb->device, final_sha1,
-                                                cbk_hash72, NULL);
+    cbk_calc_sha1_of_sha1s(cbk, cbk_header_size);
+    final_sha1 = &g_array_index(cbk, guchar, cbk_header_size);
+    cbk_hash = &g_array_index(cbk, guchar, 0);
+    switch (checksum_type) {
+       case ITDB_CHECKSUM_HASHAB:
+           success = itdb_hashAB_compute_hash_for_sha1 (itdb->device, 
final_sha1, cbk_hash, NULL);
+           break;
+       case ITDB_CHECKSUM_HASH72:
+           success = itdb_hash72_compute_hash_for_sha1 (itdb->device, 
final_sha1, cbk_hash, NULL);
+           break;
+       default:
+           break;
+    }
     if (!success) {
        g_array_free(cbk, TRUE);
        return FALSE;

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
gtkpod-cvs2 mailing list
gtkpod-cvs2@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to