Revision: 1698
          http://gtkpod.svn.sourceforge.net/gtkpod/?rev=1698&view=rev
Author:   jcsjcs
Date:     2007-09-24 07:59:33 -0700 (Mon, 24 Sep 2007)

Log Message:
-----------
        ** code courtesy of Christophe Fergeau **

        * src/itdb_itunesdb.c (mk_mhbd): write extended header needed
          for new iPod Nanos (3G Video) and iPod Classics.

          src/itdb_device.c
          src/itdb_device.h: Code to parse SysInfoExtended and SysInfo
          for the FireWireGUID. You must either copy the iPod
          description XML file to Device/SysInfoExtended or add a line
          'FirewireGuid: 000A27....' to Device/SysInfo. You can get
          your FirewireGuid by using the tests/test-fw-id test program.

        * src/sha1.c
          src/sha1.h
          src/itdb_sha1.c
          src/itdb_sha1.h
          New files for obscure hash generation code.

        * src/Makefile.am: added new files.

        * tests/test-checksum.c
          tests/test-fw-id.c
          tests/Makefile.am: test programs to retrieve the
          FirewireGuid and calculate/write the obscure hash.

Modified Paths:
--------------
    libgpod/trunk/ChangeLog
    libgpod/trunk/docs/reference/tmpl/device.sgml
    libgpod/trunk/src/Makefile.am
    libgpod/trunk/src/itdb_device.c
    libgpod/trunk/src/itdb_device.h
    libgpod/trunk/src/itdb_itunesdb.c
    libgpod/trunk/tests/Makefile.am

Added Paths:
-----------
    libgpod/trunk/src/itdb_sha1.c
    libgpod/trunk/src/itdb_sha1.h
    libgpod/trunk/src/sha1.c
    libgpod/trunk/src/sha1.h
    libgpod/trunk/tests/test-checksum.c
    libgpod/trunk/tests/test-fw-id.c

Modified: libgpod/trunk/ChangeLog
===================================================================
--- libgpod/trunk/ChangeLog     2007-09-16 18:55:11 UTC (rev 1697)
+++ libgpod/trunk/ChangeLog     2007-09-24 14:59:33 UTC (rev 1698)
@@ -1,3 +1,30 @@
+2007-09-24 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
+       ** code courtesy of Christophe Fergeau **
+
+       * src/itdb_itunesdb.c (mk_mhbd): write extended header needed
+          for new iPod Nanos (3G Video) and iPod Classics.
+
+         src/itdb_device.c
+         src/itdb_device.h: Code to parse SysInfoExtended and SysInfo
+         for the FireWireGUID. You must either copy the iPod
+         description XML file to Device/SysInfoExtended or add a line
+         'FirewireGuid: 000A27....' to Device/SysInfo. You can get
+         your FirewireGuid by using the tests/test-fw-id test program.
+
+       * src/sha1.c
+         src/sha1.h
+         src/itdb_sha1.c
+         src/itdb_sha1.h
+         New files for obscure hash generation code.
+
+       * src/Makefile.am: added new files.
+
+        * tests/test-checksum.c
+         tests/test-fw-id.c
+         tests/Makefile.am: test programs to retrieve the
+         FirewireGuid and calculate/write the obscure hash.
+
 2007-09-15 Jorg Schuler <jcsjcs at users.sourceforge.net>
 
        * src/itdb_device.c:

Modified: libgpod/trunk/docs/reference/tmpl/device.sgml
===================================================================
--- libgpod/trunk/docs/reference/tmpl/device.sgml       2007-09-16 18:55:11 UTC 
(rev 1697)
+++ libgpod/trunk/docs/reference/tmpl/device.sgml       2007-09-24 14:59:33 UTC 
(rev 1698)
@@ -227,6 +227,7 @@
 @ITDB_IPOD_MODEL_NANO_BLUE: 
 @ITDB_IPOD_MODEL_NANO_GREEN: 
 @ITDB_IPOD_MODEL_NANO_PINK: 
[EMAIL PROTECTED]: 
 @ITDB_IPOD_MODEL_IPHONE_1: 
 @ITDB_IPOD_MODEL_SHUFFLE_SILVER: 
 @ITDB_IPOD_MODEL_SHUFFLE_PINK: 

Modified: libgpod/trunk/src/Makefile.am
===================================================================
--- libgpod/trunk/src/Makefile.am       2007-09-16 18:55:11 UTC (rev 1697)
+++ libgpod/trunk/src/Makefile.am       2007-09-24 14:59:33 UTC (rev 1698)
@@ -1,34 +1,38 @@
 lib_LTLIBRARIES = libgpod.la
 
 libgpod_la_SOURCES = \
+       db-artwork-debug.c  \
+       db-artwork-debug.h  \
+       db-artwork-parser.c \
+       db-artwork-parser.h \
+       db-artwork-writer.c \
+       db-image-parser.c   \
+       db-image-parser.h   \
+       db-itunes-parser.h  \
+       db-parse-context.c  \
+       db-parse-context.h  \
+       glib-compat.h \
        itdb.h           \
        itdb_artwork.c   \
+       itdb_device.c  \
+       itdb_device.h  \
+       itdb_endianness.h \
        itdb_itunesdb.c  \
+       itdb_photoalbum.c \
        itdb_playlist.c  \
        itdb_private.h   \
-       itdb_photoalbum.c \
+       itdb_sha1.c \
+       itdb_sha1.h \
+       itdb_sysinfo.c \
        itdb_track.c     \
-       db-artwork-parser.c \
-       db-artwork-parser.h \
-       db-parse-context.c  \
-       db-parse-context.h  \
-       db-artwork-debug.c  \
-       db-artwork-debug.h  \
-       db-image-parser.c   \
-       db-image-parser.h   \
-       db-itunes-parser.h  \
-       db-artwork-writer.c \
        ithumb-writer.c \
-       itdb_device.c \
-       itdb_device.h \
-       itdb_endianness.h \
        pixmaps.c \
        pixmaps.h \
-       glib-compat.h
+       sha1.c
 
 
 libgpod_la_headers = itdb.h
-libgpod_la_noinst_headers = itdb_private.h hal-common.h
+libgpod_la_noinst_headers = itdb_private.h hal-common.h sha1.h itdb-sha1.h
 libgpod_la_LDFLAGS = -version-info $(LIBGPOD_SO_VERSION) -no-undefined
 
 libgpodincludedir = $(includedir)/gpod-1.0/gpod

Modified: libgpod/trunk/src/itdb_device.c
===================================================================
--- libgpod/trunk/src/itdb_device.c     2007-09-16 18:55:11 UTC (rev 1697)
+++ libgpod/trunk/src/itdb_device.c     2007-09-24 14:59:33 UTC (rev 1698)
@@ -223,6 +223,7 @@
        N_("Nano (Blue)"),
        N_("Nano (Green)"),
        N_("Nano (Pink)"),
+       N_("Nano (Red)"),
        N_("iPhone (1)"),
        N_("Shuffle (Silver)"),
        N_("Shuffle (Pink)"),
@@ -471,13 +472,14 @@
        g_free (sysinfo_path);
     }
     g_free (dev_path);
+
+    itdb_device_read_sysinfo_xml (device, NULL);
+
     /* indicate that sysinfo is identical to what is on the iPod */
     device->sysinfo_changed = FALSE;
     return result;
 }
 
-
-
 /* used by itdb_device_write_sysinfo() */
 static void write_sysinfo_entry (const gchar *key,
                                 const gchar *value,
@@ -925,7 +927,6 @@
  *
  * Return value: true if @device can display artwork.
  */
-
 gboolean itdb_device_supports_artwork (Itdb_Device *device)
 {
     if (device == NULL) {
@@ -1035,3 +1036,26 @@
         device->timezone_shift += 3600;
     }
 }
+
+/**
+ * itdb_device_get_firewire_id
+ * @device: an #Itdb_Device
+ *
+ * Returns the Firewire ID for @device, this is useful to calculate the 
+ * iTunesDB checksum which is expected by newer iPod models
+ * (iPod classic/fat nanos)
+ *
+ * Return value: the guint64 firewire id, or 0 if we don't know it
+ **/
+guint64 itdb_device_get_firewire_id (Itdb_Device *device)
+{
+    gchar *fwid;
+
+    g_assert (device->sysinfo != NULL);
+
+    fwid = g_hash_table_lookup (device->sysinfo, "FirewireGuid");
+    if (fwid == NULL) {
+       return 0;
+    }
+    return g_ascii_strtoull (fwid, NULL, 16);
+}

Modified: libgpod/trunk/src/itdb_device.h
===================================================================
--- libgpod/trunk/src/itdb_device.h     2007-09-16 18:55:11 UTC (rev 1697)
+++ libgpod/trunk/src/itdb_device.h     2007-09-24 14:59:33 UTC (rev 1698)
@@ -100,6 +100,10 @@
 G_GNUC_INTERNAL const Itdb_ArtworkFormat *itdb_device_get_artwork_formats 
(Itdb_Device *device);
 G_GNUC_INTERNAL gint itdb_device_musicdirs_number (Itdb_Device *device);
 G_GNUC_INTERNAL void itdb_device_autodetect_endianess (Itdb_Device *device);
+G_GNUC_INTERNAL gboolean itdb_device_read_sysinfo_xml (Itdb_Device *device, 
+                                                      GError **error);
+G_GNUC_INTERNAL guint64 itdb_device_get_firewire_id (Itdb_Device *device);
+
 G_END_DECLS
 
 #endif

Modified: libgpod/trunk/src/itdb_itunesdb.c
===================================================================
--- libgpod/trunk/src/itdb_itunesdb.c   2007-09-16 18:55:11 UTC (rev 1697)
+++ libgpod/trunk/src/itdb_itunesdb.c   2007-09-24 14:59:33 UTC (rev 1698)
@@ -110,12 +110,15 @@
 #include "db-artwork-parser.h"
 #include "itdb_device.h"
 #include "itdb_private.h"
+#include "itdb_sha1.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <glib-object.h>
 #include <glib/gi18n-lib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/statvfs.h>
 #include <sys/types.h>
@@ -3401,7 +3404,7 @@
   cts = fexp->wcontents;
 
   put_header (cts, "mhbd");
-  put32lint (cts, 104); /* header size */
+  put32lint (cts, 188); /* header size */
   put32lint (cts, -1);  /* size of whole mhdb -- fill in later */
   put32lint (cts, 1);   /* ? */
   /* Version number: 0x01: iTunes 2
@@ -3416,13 +3419,33 @@
                     0x10: iTunes 6.0.1(?)
                     0x11: iTunes 6.0.2
                      0x12 = iTunes 6.0.5.
-                    0x13 = iTunes 7 */
-  fexp->itdb->version = 0x13;
+                    0x13 = iTunes 7 
+                     0x14 = iTunes 7.1
+                     0x15 = iTunes 7.2
+                     0x19 = iTunes 7.4
+    Be aware that newer ipods won't work if the library version number is too 
+    old
+  */
+  fexp->itdb->version = 0x19;
   put32lint (cts, fexp->itdb->version);
   put32lint (cts, children);
   put64lint (cts, fexp->itdb->id);
-  put32lint (cts, 2);   /* ? */
-  put32_n0 (cts, 17);   /* dummy space */
+  /* 0x20 */
+  put16lint (cts, 2);   /* always seems to be 2 */
+  put16_n0  (cts, 7);  /* unknown */
+  /* 0x30 */
+  put16lint (cts, 1);   /* ? but iPod Classic/fat Nanos won't display any song
+                        * if it's not 1 */
+  put16_n0  (cts, 10);  /* unknown */
+  /* 0x46 */
+  put16lint (cts, 0);   /* langauge */
+  put64lint (cts, 0);   /* library persistent ID */
+  /* 0x50 */
+  put32lint (cts, 0);   /* unknown: seen: 0x05 for nano 3G */
+  put32lint (cts, 0);   /* unknown: seen: 0x4d for nano 3G */
+  put32_n0 (cts, 5);    /* 20 bytes hash */
+  put32lint (cts, 0);   /* timezone offset in seconds */
+  put32_n0 (cts, 19);   /* dummy space */
 }
 
 /* Fill in the length of a standard header */
@@ -4920,6 +4943,122 @@
     return result;
 }
 
+static unsigned char *
+calculate_db_checksum (const char *itdb_path, guint64 fwid)
+{
+    int fd;
+    struct stat stat_buf;
+    int result;
+    unsigned char *itdb_data;
+    unsigned char *checksum;
+
+    fd = open (itdb_path, O_RDONLY);
+    if (fd < 0) {
+       g_warning ("Couldn't open %s", itdb_path);
+       return NULL;
+    }
+
+    result = fstat (fd, &stat_buf);
+    if (result != 0) {
+       g_warning ("Couldn't stat %s", itdb_path);
+       close (fd);
+       return NULL;
+    }
+
+    if (stat_buf.st_size < 0x80) {
+       g_warning ("%s is too small", itdb_path);
+       close (fd);
+       return NULL;
+    }
+
+    itdb_data = mmap (NULL, stat_buf.st_size, 
+                     PROT_READ | PROT_WRITE, 
+                     MAP_PRIVATE, fd, 0);
+    if (itdb_data == MAP_FAILED) {
+       g_warning ("Couldn't mmap %s", itdb_path);
+       close (fd);
+       return NULL;
+    }
+
+    /* Those fields must be zero'ed out for the sha1 calculation */
+    memset(itdb_data+0x18, 0, 8);
+    memset(itdb_data+0x32, 0, 20);
+    memset(itdb_data+0x58, 0, 20);
+
+    checksum = itdb_compute_hash (fwid, itdb_data, stat_buf.st_size);
+
+    munmap (itdb_data, stat_buf.st_size);
+    close (fd);
+
+    return checksum;
+}
+
+static gboolean itdb_write_checksum_to_file (const char *path, 
+                                            const unsigned char *checksum,
+                                            size_t size)
+{
+    FILE *f;
+    int result;
+    size_t count;
+
+    f = fopen (path, "rb+");
+    if (f == NULL) {
+       return FALSE;
+    }
+    
+    result = fseek (f, 0x58, SEEK_SET);
+    if (result != 0) {
+       fclose (f);
+       return FALSE;
+    }
+    
+    count = fwrite (checksum, size, 1, f);
+    fclose (f);
+   
+    return (count == 1);
+}
+
+static gboolean itdb_write_checksum (Itdb_iTunesDB *db)
+{
+    guint64 fwid;
+    char *itdb_path;
+    unsigned char *checksum;
+    gboolean result;
+
+    if (db->device == NULL) {
+       return FALSE;
+    }
+
+    fwid = itdb_device_get_firewire_id (db->device);
+    if (fwid == 0) {
+       return FALSE;
+    }
+
+    itdb_path = itdb_get_itunesdb_path (itdb_get_mountpoint (db));
+    checksum = calculate_db_checksum (itdb_path, fwid);
+
+    if (checksum == NULL) {
+       g_free (itdb_path);
+       return FALSE;
+    }
+
+    result = itdb_write_checksum_to_file (itdb_path, checksum, 
+                                         strlen ((char *)checksum));
+    g_free (itdb_path);
+
+    {
+       unsigned int i;
+       g_print ("Checksum: ");
+       for (i = 0; i < strlen ((char *)checksum); i++) {
+           g_print ("%02x ", checksum[i]);
+       }
+    }
+    g_print ("\n");
+    g_free (checksum);
+    
+    return result;
+}
+
 /**
  * itdb_write:
  * @itdb: the #Itdb_iTunesDB to write to disk
@@ -4965,8 +5104,16 @@
     g_free (itunes_filename);
     g_free (itunes_path);
 
-    if (result == TRUE)
+    if (result != FALSE)
     {
+       /* Set checksum (ipods require it starting from iPod Classic 
+        * and fat Nanos)
+        */
+       result = itdb_write_checksum (itdb);
+       if (!result) {
+           g_warning ("Couldn't set checksum");
+       }
+
        /* Write SysInfo file if it has changed */
        if (itdb->device->sysinfo_changed)
        {

Added: libgpod/trunk/src/itdb_sha1.c
===================================================================
--- libgpod/trunk/src/itdb_sha1.c                               (rev 0)
+++ libgpod/trunk/src/itdb_sha1.c       2007-09-24 14:59:33 UTC (rev 1698)
@@ -0,0 +1,247 @@
+/*
+|  Copyright (C) 2007 Christophe Fergeau <[EMAIL PROTECTED]>
+|
+|  The code in this file is heavily based on the proof-of-concept code
+|  written by wtbw
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|
+|   1. Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+|   2. Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+|   3. The name of the author may not be used to endorse or promote
+| products derived from this software without specific prior written
+| permission.
+|
+| THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+| IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+| IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+| BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+| OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+| OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+| OF SUCH DAMAGE.
+|
+|
+|  iTunes and iPod are trademarks of Apple
+|
+|  This product is not supported/written/published by Apple!
+*/
+
+#include <glib.h>
+#include "itdb_sha1.h"
+#include "sha1.h"
+
+static const unsigned char invTable[256] = {
+    0x74, 0x85, 0x96, 0xA7, 0xB8, 0xC9, 0xDA, 0xEB,
+    0xFC, 0x0D, 0x1E, 0x2F, 0x40, 0x51, 0x62, 0x73,
+    0x84, 0x95, 0xA6, 0xB7, 0xC8, 0xD9, 0xEA, 0xFB,
+    0x0C, 0x1D, 0x2E, 0x3F, 0x50, 0x61, 0x72, 0x83,
+    0x94, 0xA5, 0xB6, 0xC7, 0xD8, 0xE9, 0xFA, 0x0B,
+    0x1C, 0x2D, 0x3E, 0x4F, 0x60, 0x71, 0x82, 0x93,
+    0xA4, 0xB5, 0xC6, 0xD7, 0xE8, 0xF9, 0x0A, 0x1B,
+    0x2C, 0x3D, 0x4E, 0x5F, 0x70, 0x81, 0x92, 0xA3,
+    0xB4, 0xC5, 0xD6, 0xE7, 0xF8, 0x09, 0x1A, 0x2B,
+    0x3C, 0x4D, 0x5E, 0x6F, 0x80, 0x91, 0xA2, 0xB3,
+    0xC4, 0xD5, 0xE6, 0xF7, 0x08, 0x19, 0x2A, 0x3B,
+    0x4C, 0x5D, 0x6E, 0x7F, 0x90, 0xA1, 0xB2, 0xC3,
+    0xD4, 0xE5, 0xF6, 0x07, 0x18, 0x29, 0x3A, 0x4B,
+    0x5C, 0x6D, 0x7E, 0x8F, 0xA0, 0xB1, 0xC2, 0xD3,
+    0xE4, 0xF5, 0x06, 0x17, 0x28, 0x39, 0x4A, 0x5B,
+    0x6C, 0x7D, 0x8E, 0x9F, 0xB0, 0xC1, 0xD2, 0xE3,
+    0xF4, 0x05, 0x16, 0x27, 0x38, 0x49, 0x5A, 0x6B,
+    0x7C, 0x8D, 0x9E, 0xAF, 0xC0, 0xD1, 0xE2, 0xF3,
+    0x04, 0x15, 0x26, 0x37, 0x48, 0x59, 0x6A, 0x7B,
+    0x8C, 0x9D, 0xAE, 0xBF, 0xD0, 0xE1, 0xF2, 0x03,
+    0x14, 0x25, 0x36, 0x47, 0x58, 0x69, 0x7A, 0x8B,
+    0x9C, 0xAD, 0xBE, 0xCF, 0xE0, 0xF1, 0x02, 0x13,
+    0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8A, 0x9B,
+    0xAC, 0xBD, 0xCE, 0xDF, 0xF0, 0x01, 0x12, 0x23,
+    0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9A, 0xAB,
+    0xBC, 0xCD, 0xDE, 0xEF, 0x00, 0x11, 0x22, 0x33,
+    0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,
+    0xCC, 0xDD, 0xEE, 0xFF, 0x10, 0x21, 0x32, 0x43,
+    0x54, 0x65, 0x76, 0x87, 0x98, 0xA9, 0xBA, 0xCB,
+    0xDC, 0xED, 0xFE, 0x0F, 0x20, 0x31, 0x42, 0x53,
+    0x64, 0x75, 0x86, 0x97, 0xA8, 0xB9, 0xCA, 0xDB,
+    0xEC, 0xFD, 0x0E, 0x1F, 0x30, 0x41, 0x52, 0x63
+};
+
+static const unsigned char table1[256] = {
+    0x3A, 0x3F, 0x3E, 0x72, 0xBD, 0xA2, 0xD6, 0xB4,
+    0x63, 0xC0, 0x6E, 0x62, 0x59, 0x1E, 0xE2, 0x71,
+    0xB5, 0x0D, 0xE8, 0x0C, 0x25, 0x38, 0xCE, 0x23,
+    0x7C, 0xB7, 0xAD, 0x16, 0xDF, 0x47, 0x3D, 0xB3,
+    0x7E, 0x8C, 0xAA, 0x61, 0x31, 0x66, 0xBE, 0x4F,
+    0x97, 0x14, 0x54, 0xF0, 0x70, 0xEB, 0x30, 0xC4,
+    0x27, 0x4E, 0xFA, 0x1A, 0x2B, 0x11, 0xF4, 0x45,
+    0x8E, 0x5D, 0x73, 0xED, 0x22, 0x2E, 0x7D, 0xA4,
+    0x28, 0xDA, 0x2F, 0xC5, 0x92, 0x09, 0x05, 0x13,
+    0x9D, 0x32, 0x51, 0x4A, 0xC8, 0xBA, 0x96, 0xA7,
+    0x6A, 0x50, 0xF3, 0xBC, 0x93, 0xBF, 0xB0, 0xD2,
+    0xD5, 0x82, 0x19, 0x98, 0x35, 0xCF, 0x6B, 0xB6,
+    0x83, 0x56, 0x15, 0xF2, 0x9A, 0x9C, 0xCA, 0x74,
+    0x34, 0x58, 0x8D, 0xA6, 0x03, 0xFF, 0x46, 0x7B,
+    0xD0, 0x7A, 0x33, 0x76, 0xDD, 0xAC, 0xCB, 0x24,
+    0x7F, 0xB1, 0x85, 0x60, 0xC3, 0x26, 0x8A, 0x1D,
+    0x1C, 0x8F, 0x2A, 0xEF, 0x06, 0xDE, 0x67, 0x5E,
+    0xE7, 0xAE, 0xD9, 0xCC, 0x07, 0x6C, 0xF8, 0x0A,
+    0xD3, 0x40, 0x36, 0x1F, 0x2D, 0x95, 0x43, 0xDB,
+    0x01, 0x89, 0x4B, 0xF7, 0xB9, 0x39, 0xC2, 0x52,
+    0x53, 0xFD, 0x65, 0xF5, 0x68, 0xC1, 0xC7, 0x9F,
+    0x4D, 0xEA, 0xAF, 0x6D, 0x10, 0x44, 0x87, 0xD8,
+    0xEE, 0x1B, 0xFE, 0x3C, 0xDC, 0x84, 0x69, 0x48,
+    0x6F, 0xD1, 0x57, 0x55, 0xD4, 0xA5, 0x49, 0x5B,
+    0xE5, 0x0B, 0x94, 0xC9, 0x5F, 0xE1, 0x17, 0x81,
+    0xBB, 0xEC, 0xD7, 0xC6, 0x02, 0x4C, 0x42, 0x75,
+    0xA3, 0x99, 0xE4, 0xA1, 0x9B, 0x5A, 0xF1, 0x29,
+    0xA0, 0x64, 0x9E, 0x18, 0x41, 0x80, 0x2C, 0x79,
+    0x20, 0x8B, 0xAB, 0x90, 0x08, 0xB8, 0xA9, 0x77,
+    0x12, 0xF9, 0x0E, 0x88, 0xE9, 0x04, 0xFB, 0x86,
+    0x0F, 0xE0, 0xA8, 0x5C, 0xE6, 0x21, 0xCD, 0x3B,
+    0x00, 0x78, 0xFC, 0xF6, 0xE3, 0x37, 0xB2, 0x91
+};
+
+static const unsigned char table2[256] = {
+    0xF3, 0xE4, 0x1B, 0x38, 0xE5, 0x6F, 0xE8, 0x9D,
+    0x3E, 0x55, 0xBA, 0xC7, 0xAC, 0xEA, 0x66, 0xA2,
+    0xB9, 0x7A, 0x34, 0x43, 0x02, 0x4E, 0xFE, 0x36,
+    0x41, 0x57, 0x1A, 0xB1, 0x31, 0x87, 0x04, 0x52,
+    0x21, 0x22, 0xE1, 0x13, 0x7F, 0x03, 0x3A, 0x90,
+    0xF7, 0x69, 0x78, 0x12, 0x83, 0x0B, 0x9A, 0x97,
+    0x4D, 0xB7, 0x8C, 0xBF, 0x2D, 0x94, 0xD1, 0x93,
+    0x2F, 0x42, 0x23, 0xA4, 0xE0, 0x92, 0xDC, 0x68,
+    0xD3, 0xDD, 0xAF, 0x91, 0x9F, 0xED, 0x3D, 0x8F,
+    0xA1, 0x51, 0xD9, 0xE9, 0x70, 0x28, 0xEF, 0xB3,
+    0x49, 0xA5, 0x0D, 0xC5, 0xD0, 0x60, 0xB4, 0x2B,
+    0x07, 0xF8, 0xDF, 0xE6, 0x16, 0xC0, 0x30, 0x71,
+    0x85, 0xFD, 0x72, 0x95, 0x29, 0x79, 0x0A, 0x7B,
+    0x46, 0x11, 0x7D, 0x88, 0x1D, 0x2A, 0x48, 0x1F,
+    0x45, 0x89, 0x47, 0xEE, 0xBB, 0xBE, 0x6E, 0xC3,
+    0x6C, 0xCE, 0x10, 0x5A, 0x2C, 0xCA, 0xFB, 0xB2,
+    0xCB, 0x1C, 0x9C, 0xEC, 0x2E, 0x56, 0x59, 0x9B,
+    0xA6, 0x53, 0xAE, 0x17, 0x25, 0xC1, 0x3F, 0x6A,
+    0x0F, 0x09, 0x01, 0xA3, 0xD6, 0xA0, 0xD8, 0x08,
+    0xE3, 0x74, 0x06, 0x6D, 0x19, 0x98, 0x1E, 0x77,
+    0x76, 0xBC, 0xEB, 0x3C, 0xB0, 0xC4, 0xC8, 0x64,
+    0x0E, 0x86, 0x63, 0xD7, 0xDB, 0xBD, 0xA7, 0x82,
+    0x39, 0x4F, 0x27, 0xD2, 0x5F, 0x73, 0xF4, 0x75,
+    0x6B, 0xC2, 0xD5, 0x67, 0x5D, 0x80, 0xAB, 0x81,
+    0xDE, 0xF0, 0xAD, 0xAA, 0xCD, 0xB6, 0xF6, 0x7C,
+    0xFC, 0x33, 0x05, 0x14, 0x96, 0x15, 0xC9, 0x9E,
+    0x35, 0x5C, 0x7E, 0x44, 0x54, 0x58, 0x3B, 0x40,
+    0x20, 0xA8, 0x8B, 0x5E, 0x4A, 0x24, 0x99, 0x8E,
+    0xF5, 0xB5, 0x62, 0x00, 0x37, 0x5B, 0x18, 0x65,
+    0x8D, 0x32, 0xE2, 0xF9, 0xDA, 0x8A, 0xD4, 0xCC,
+    0x26, 0xF2, 0xF1, 0xE7, 0x4B, 0xC6, 0xCF, 0xFF,
+    0x4C, 0x84, 0x61, 0xFA, 0xB8, 0x0C, 0xA9, 0x50
+};
+
+static const unsigned char fixed[18] = {
+    0x67, 0x23, 0xFE, 0x30, 0x45, 0x33, 0xF8, 0x90, 0x99,
+    0x21, 0x07, 0xC1, 0xD0, 0x12, 0xB2, 0xA1, 0x07, 0x81
+};
+
+
+static int gcd(int a, int b){
+    while (TRUE)
+    {
+        a = a % b;
+        if( a == 0 )
+            return b;
+        b = b % a;
+        if( b == 0 )
+            return a;
+    }
+}
+
+static int lcm(int a, int b)
+{
+    if(a==0 || b==0)
+        return 1;
+
+    return (a*b)/gcd(a,b);
+}
+
+static unsigned char *generate_key (guint64 fwid)
+{
+    unsigned char *key;
+    unsigned char y[16];
+    SHA_INFO context;
+    int i;
+    guint64 fwid_be = GUINT64_TO_BE (fwid);
+    const unsigned char *firewire_id = (const unsigned char *)&fwid_be;
+
+    /* take LCM of each two bytes in the FWID in turn */
+    for (i=0; i<4; i++){
+        int a = firewire_id[i*2];
+        int b = firewire_id[i*2+1];
+        int cur_lcm = lcm(a,b);
+
+        unsigned char hi = (cur_lcm & 0xFF00) >> 8;
+        unsigned char lo = cur_lcm & 0xFF;
+
+        y[i*4] = ((table1[hi] * 0xB5) - 3);
+        y[i*4 + 1] = ((table2[hi] * 0xB7) + 0x49);
+        y[i*4 + 2] = ((table1[lo] * 0xB5) - 3);
+        y[i*4 + 3] = ((table2[lo] * 0xB7) + 0x49);
+    }
+
+    /* convert y */
+    for(i=0;i<16;i++){
+        y[i] = invTable[y[i]];
+    }
+
+    /* hash */
+    sha_init(&context);
+    sha_update(&context, fixed, 18);
+    sha_update(&context, y, 16);
+
+    key = g_new0 (unsigned char, 64);
+    sha_final(key, &context);
+
+    return key;
+}
+
+unsigned char *itdb_compute_hash (guint64 firewire_id,
+                                  const unsigned char *itdb,
+                                  unsigned long size)
+{
+    unsigned char *key;
+    unsigned char *hash;
+    SHA_INFO context;
+    int i;
+
+    key = generate_key(firewire_id);
+
+    /* hmac sha1 */
+    for (i=0; i < 64; i++)
+    {
+        key[i] ^= 0x36;
+    }
+
+    /* 20 bytes for the checksum, and 1 trailing \0 */
+    hash = g_new0 (unsigned char, 21);
+    sha_init(&context);
+    sha_update(&context, key, 64);
+    sha_update(&context, itdb, size);
+    sha_final(hash, &context);
+
+    for (i=0; i < 64; i++)
+        key[i] ^= 0x36 ^ 0x5c;
+
+    sha_init(&context);
+    sha_update(&context, key, 64);
+    sha_update(&context, hash, 20);
+    sha_final(hash, &context);
+
+    g_free (key);
+
+    return hash;
+}

Added: libgpod/trunk/src/itdb_sha1.h
===================================================================
--- libgpod/trunk/src/itdb_sha1.h                               (rev 0)
+++ libgpod/trunk/src/itdb_sha1.h       2007-09-24 14:59:33 UTC (rev 1698)
@@ -0,0 +1,37 @@
+/*
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
+|  Part of the gtkpod project.
+| 
+|  URL: http://www.gtkpod.org/
+|  URL: http://gtkpod.sourceforge.net/
+|
+|  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!
+|
+|  $Id$
+*/
+
+#ifndef __ITDB_SHA1_H__
+#define __ITDB_SHA1_H__
+
+#include <glib.h>
+
+unsigned char *itdb_compute_hash (guint64 firewire_id,
+                                  const unsigned char *itdb,
+                                  unsigned long size);
+#endif

Added: libgpod/trunk/src/sha1.c
===================================================================
--- libgpod/trunk/src/sha1.c                            (rev 0)
+++ libgpod/trunk/src/sha1.c    2007-09-24 14:59:33 UTC (rev 1698)
@@ -0,0 +1,450 @@
+/* (PD) 2001 The Bitzi Corporation
+ * Please see file COPYING or http://bitzi.com/publicdomain 
+ * for more info.
+ *
+ * NIST Secure Hash Algorithm 
+ * heavily modified by Uwe Hollerbach <[EMAIL PROTECTED] edu> 
+ * from Peter C. Gutmann's implementation as found in 
+ * Applied Cryptography by Bruce Schneier 
+ * Further modifications to include the "UNRAVEL" stuff, below 
+ *
+ * This code is in the public domain 
+ *
+ * $Id: sha1.c,v 1.1 2005-12-28 18:06:50 tpm Exp $
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <glib.h>
+#define SHA_BYTE_ORDER G_BYTE_ORDER
+
+#include <string.h>
+#include "sha1.h"
+
+/* UNRAVEL should be fastest & biggest */
+/* UNROLL_LOOPS should be just as big, but slightly slower */
+/* both undefined should be smallest and slowest */
+
+#define UNRAVEL
+/* #define UNROLL_LOOPS */
+
+/* SHA f()-functions */
+
+#define f1(x,y,z)      ((x & y) | (~x & z))
+#define f2(x,y,z)      (x ^ y ^ z)
+#define f3(x,y,z)      ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z)      (x ^ y ^ z)
+
+/* SHA constants */
+
+#define CONST1         0x5a827999L
+#define CONST2         0x6ed9eba1L
+#define CONST3         0x8f1bbcdcL
+#define CONST4         0xca62c1d6L
+
+/* truncate to 32 bits -- should be a null op on 32-bit machines */
+
+#define T32(x) ((x) & 0xffffffffL)
+
+/* 32-bit rotate */
+
+#define R32(x,n)       T32(((x << n) | (x >> (32 - n))))
+
+/* the generic case, for when the overall rotation is not unraveled */
+
+#define FG(n)  \
+    T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n);    \
+    E = D; D = C; C = R32(B,30); B = A; A = T
+
+/* specific cases, for when the overall rotation is unraveled */
+
+#define FA(n)  \
+    T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
+
+#define FB(n)  \
+    E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
+
+#define FC(n)  \
+    D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
+
+#define FD(n)  \
+    C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
+
+#define FE(n)  \
+    B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
+
+#define FT(n)  \
+    A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
+
+/* do SHA transformation */
+
+static void
+sha_transform (SHA_INFO * sha_info)
+{
+  int i;
+  SHA_BYTE *dp;
+  SHA_LONG T, A, B, C, D, E, W[80], *WP;
+
+  dp = sha_info->data;
+
+/*
+the following makes sure that at least one code block below is
+traversed or an error is reported, without the necessity for nested
+preprocessor if/else/endif blocks, which are a great pain in the
+nether regions of the anatomy...
+*/
+#undef SWAP_DONE
+
+#if (SHA_BYTE_ORDER == 1234)
+#define SWAP_DONE
+  for (i = 0; i < 16; ++i) {
+    T = *((SHA_LONG *) dp);
+    dp += 4;
+    W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
+        ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
+  }
+#endif /* SHA_BYTE_ORDER == 1234 */
+
+#if (SHA_BYTE_ORDER == 4321)
+#define SWAP_DONE
+  for (i = 0; i < 16; ++i) {
+    T = *((SHA_LONG *) dp);
+    dp += 4;
+    W[i] = T32 (T);
+  }
+#endif /* SHA_BYTE_ORDER == 4321 */
+
+#if (SHA_BYTE_ORDER == 12345678)
+#define SWAP_DONE
+  for (i = 0; i < 16; i += 2) {
+    T = *((SHA_LONG *) dp);
+    dp += 8;
+    W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
+        ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
+    T >>= 32;
+    W[i + 1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
+        ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
+  }
+#endif /* SHA_BYTE_ORDER == 12345678 */
+
+#if (SHA_BYTE_ORDER == 87654321)
+#define SWAP_DONE
+  for (i = 0; i < 16; i += 2) {
+    T = *((SHA_LONG *) dp);
+    dp += 8;
+    W[i] = T32 (T >> 32);
+    W[i + 1] = T32 (T);
+  }
+#endif /* SHA_BYTE_ORDER == 87654321 */
+
+#ifndef SWAP_DONE
+#error Unknown byte order -- you need to add code here
+#endif /* SWAP_DONE */
+
+  for (i = 16; i < 80; ++i) {
+    W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
+#if (SHA_VERSION == 1)
+    W[i] = R32 (W[i], 1);
+#endif /* SHA_VERSION */
+  }
+  A = sha_info->digest[0];
+  B = sha_info->digest[1];
+  C = sha_info->digest[2];
+  D = sha_info->digest[3];
+  E = sha_info->digest[4];
+  WP = W;
+#ifdef UNRAVEL
+  FA (1);
+  FB (1);
+  FC (1);
+  FD (1);
+  FE (1);
+  FT (1);
+  FA (1);
+  FB (1);
+  FC (1);
+  FD (1);
+  FE (1);
+  FT (1);
+  FA (1);
+  FB (1);
+  FC (1);
+  FD (1);
+  FE (1);
+  FT (1);
+  FA (1);
+  FB (1);
+  FC (2);
+  FD (2);
+  FE (2);
+  FT (2);
+  FA (2);
+  FB (2);
+  FC (2);
+  FD (2);
+  FE (2);
+  FT (2);
+  FA (2);
+  FB (2);
+  FC (2);
+  FD (2);
+  FE (2);
+  FT (2);
+  FA (2);
+  FB (2);
+  FC (2);
+  FD (2);
+  FE (3);
+  FT (3);
+  FA (3);
+  FB (3);
+  FC (3);
+  FD (3);
+  FE (3);
+  FT (3);
+  FA (3);
+  FB (3);
+  FC (3);
+  FD (3);
+  FE (3);
+  FT (3);
+  FA (3);
+  FB (3);
+  FC (3);
+  FD (3);
+  FE (3);
+  FT (3);
+  FA (4);
+  FB (4);
+  FC (4);
+  FD (4);
+  FE (4);
+  FT (4);
+  FA (4);
+  FB (4);
+  FC (4);
+  FD (4);
+  FE (4);
+  FT (4);
+  FA (4);
+  FB (4);
+  FC (4);
+  FD (4);
+  FE (4);
+  FT (4);
+  FA (4);
+  FB (4);
+  sha_info->digest[0] = T32 (sha_info->digest[0] + E);
+  sha_info->digest[1] = T32 (sha_info->digest[1] + T);
+  sha_info->digest[2] = T32 (sha_info->digest[2] + A);
+  sha_info->digest[3] = T32 (sha_info->digest[3] + B);
+  sha_info->digest[4] = T32 (sha_info->digest[4] + C);
+#else /* !UNRAVEL */
+#ifdef UNROLL_LOOPS
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (1);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (2);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (3);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+  FG (4);
+#else /* !UNROLL_LOOPS */
+  for (i = 0; i < 20; ++i) {
+    FG (1);
+  }
+  for (i = 20; i < 40; ++i) {
+    FG (2);
+  }
+  for (i = 40; i < 60; ++i) {
+    FG (3);
+  }
+  for (i = 60; i < 80; ++i) {
+    FG (4);
+  }
+#endif /* !UNROLL_LOOPS */
+  sha_info->digest[0] = T32 (sha_info->digest[0] + A);
+  sha_info->digest[1] = T32 (sha_info->digest[1] + B);
+  sha_info->digest[2] = T32 (sha_info->digest[2] + C);
+  sha_info->digest[3] = T32 (sha_info->digest[3] + D);
+  sha_info->digest[4] = T32 (sha_info->digest[4] + E);
+#endif /* !UNRAVEL */
+}
+
+/* initialize the SHA digest */
+
+void
+sha_init (SHA_INFO * sha_info)
+{
+  sha_info->digest[0] = 0x67452301L;
+  sha_info->digest[1] = 0xefcdab89L;
+  sha_info->digest[2] = 0x98badcfeL;
+  sha_info->digest[3] = 0x10325476L;
+  sha_info->digest[4] = 0xc3d2e1f0L;
+  sha_info->count_lo = 0L;
+  sha_info->count_hi = 0L;
+  sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+void
+sha_update (SHA_INFO * sha_info, const SHA_BYTE * buffer, int count)
+{
+  int i;
+  SHA_LONG clo;
+
+  clo = T32 (sha_info->count_lo + ((SHA_LONG) count << 3));
+  if (clo < sha_info->count_lo) {
+    ++sha_info->count_hi;
+  }
+  sha_info->count_lo = clo;
+  sha_info->count_hi += (SHA_LONG) count >> 29;
+  if (sha_info->local) {
+    i = SHA_BLOCKSIZE - sha_info->local;
+    if (i > count) {
+      i = count;
+    }
+    memcpy (((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
+    count -= i;
+    buffer += i;
+    sha_info->local += i;
+    if (sha_info->local == SHA_BLOCKSIZE) {
+      sha_transform (sha_info);
+    } else {
+      return;
+    }
+  }
+  while (count >= SHA_BLOCKSIZE) {
+    memcpy (sha_info->data, buffer, SHA_BLOCKSIZE);
+    buffer += SHA_BLOCKSIZE;
+    count -= SHA_BLOCKSIZE;
+    sha_transform (sha_info);
+  }
+  memcpy (sha_info->data, buffer, count);
+  sha_info->local = count;
+}
+
+/* finish computing the SHA digest */
+
+void
+sha_final (unsigned char digest[20], SHA_INFO * sha_info)
+{
+  int count;
+  SHA_LONG lo_bit_count, hi_bit_count;
+
+  lo_bit_count = sha_info->count_lo;
+  hi_bit_count = sha_info->count_hi;
+  count = (int) ((lo_bit_count >> 3) & 0x3f);
+  ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
+  if (count > SHA_BLOCKSIZE - 8) {
+    memset (((SHA_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+    sha_transform (sha_info);
+    memset ((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+  } else {
+    memset (((SHA_BYTE *) sha_info->data) + count, 0,
+        SHA_BLOCKSIZE - 8 - count);
+  }
+  sha_info->data[56] = (unsigned char) ((hi_bit_count >> 24) & 0xff);
+  sha_info->data[57] = (unsigned char) ((hi_bit_count >> 16) & 0xff);
+  sha_info->data[58] = (unsigned char) ((hi_bit_count >> 8) & 0xff);
+  sha_info->data[59] = (unsigned char) ((hi_bit_count >> 0) & 0xff);
+  sha_info->data[60] = (unsigned char) ((lo_bit_count >> 24) & 0xff);
+  sha_info->data[61] = (unsigned char) ((lo_bit_count >> 16) & 0xff);
+  sha_info->data[62] = (unsigned char) ((lo_bit_count >> 8) & 0xff);
+  sha_info->data[63] = (unsigned char) ((lo_bit_count >> 0) & 0xff);
+  sha_transform (sha_info);
+  digest[0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
+  digest[1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
+  digest[2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
+  digest[3] = (unsigned char) ((sha_info->digest[0]) & 0xff);
+  digest[4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
+  digest[5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
+  digest[6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
+  digest[7] = (unsigned char) ((sha_info->digest[1]) & 0xff);
+  digest[8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
+  digest[9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
+  digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
+  digest[11] = (unsigned char) ((sha_info->digest[2]) & 0xff);
+  digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
+  digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
+  digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
+  digest[15] = (unsigned char) ((sha_info->digest[3]) & 0xff);
+  digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
+  digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
+  digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
+  digest[19] = (unsigned char) ((sha_info->digest[4]) & 0xff);
+}

Added: libgpod/trunk/src/sha1.h
===================================================================
--- libgpod/trunk/src/sha1.h                            (rev 0)
+++ libgpod/trunk/src/sha1.h    2007-09-24 14:59:33 UTC (rev 1698)
@@ -0,0 +1,62 @@
+/* NIST Secure Hash Algorithm */
+/* heavily modified by Uwe Hollerbach <[EMAIL PROTECTED] edu> */
+/* from Peter C. Gutmann's implementation as found in */
+/* Applied Cryptography by Bruce Schneier */
+/* This code is in the public domain */
+/* $Id: sha1.h,v 1.1 2005-12-28 18:06:50 tpm Exp $ */
+
+#ifndef __GST_CDDA_SHA_H__
+#define __GST_CDDA_SHA_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Useful defines & typedefs */
+typedef unsigned char SHA_BYTE;        /* 8-bit quantity */
+typedef unsigned long SHA_LONG;        /* 32-or-more-bit quantity */
+
+#define SHA_BLOCKSIZE          64
+#define SHA_DIGESTSIZE         20
+
+typedef struct {
+    SHA_LONG digest[5];                /* message digest */
+    SHA_LONG count_lo, count_hi;       /* 64-bit bit count */
+    SHA_BYTE data[SHA_BLOCKSIZE];      /* SHA data buffer */
+    int local;                 /* unprocessed amount in data */
+} SHA_INFO;
+
+#define sha_init   itdb_sha_init
+#define sha_update itdb_sha_update
+#define sha_final  itdb_sha_final
+
+G_GNUC_INTERNAL void sha_init(SHA_INFO *);
+G_GNUC_INTERNAL void sha_update(SHA_INFO *, const SHA_BYTE *, int);
+G_GNUC_INTERNAL void sha_final(unsigned char [20], SHA_INFO *);
+
+#define SHA_VERSION 1
+
+#ifdef HAVE_CONFIG_H 
+#include "config.h"
+
+
+#ifdef WORDS_BIGENDIAN
+#  if SIZEOF_LONG == 4
+#    define SHA_BYTE_ORDER  4321
+#  elif SIZEOF_LONG == 8
+#    define SHA_BYTE_ORDER  87654321
+#  endif
+#else
+#  if SIZEOF_LONG == 4
+#    define SHA_BYTE_ORDER  1234
+#  elif SIZEOF_LONG == 8
+#    define SHA_BYTE_ORDER  12345678
+#  endif
+#endif
+
+#else
+
+#define SHA_BYTE_ORDER 1234
+
+#endif
+
+#endif /* __GST_CDDA_SHA_H__ */

Modified: libgpod/trunk/tests/Makefile.am
===================================================================
--- libgpod/trunk/tests/Makefile.am     2007-09-16 18:55:11 UTC (rev 1697)
+++ libgpod/trunk/tests/Makefile.am     2007-09-24 14:59:33 UTC (rev 1698)
@@ -1,5 +1,5 @@
 if HAVE_GDKPIXBUF
-TESTTHUMBS=test-thumbnails test-write-thumbnails test-photos get-timezone
+TESTTHUMBS=test-thumbnails test-write-thumbnails test-photos get-timezone 
 
 test_thumbnails_SOURCES = test-covers.c
 test_thumbnails_CFLAGS = $(AM_CFLAGS)
@@ -33,9 +33,14 @@
 test_init_ipod_SOURCES = test-init-ipod.c
 test_init_ipod_LDADD = 
 
+test_checksum_SOURCES = test-checksum.c
+
+test_firewire_id_SOURCES = test-fw-id.c
+
 get_timezone_SOURCES = get-timezone.c
 
-noinst_PROGRAMS=test-itdb test-ls $(TESTTHUMBS) $(TESTTAGLIB) $(TESTMISC)
+noinst_PROGRAMS=test-itdb test-ls test-checksum test-firewire-id \
+               $(TESTTHUMBS) $(TESTTAGLIB) $(TESTMISC)
 
 INCLUDES=$(LIBGPOD_CFLAGS) -I$(top_srcdir)/src 
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\"
 LIBS=$(LIBGPOD_LIBS) $(top_builddir)/src/libgpod.la

Added: libgpod/trunk/tests/test-checksum.c
===================================================================
--- libgpod/trunk/tests/test-checksum.c                         (rev 0)
+++ libgpod/trunk/tests/test-checksum.c 2007-09-24 14:59:33 UTC (rev 1698)
@@ -0,0 +1,181 @@
+/*
+|  Copyright (C) 2007 Christophe Fergeau <[EMAIL PROTECTED]>
+|
+|  The code in this file is heavily based on the proof-of-concept code
+|  written by wtbw
+|
+| Redistribution and use in source and binary forms, with or without
+| modification, are permitted provided that the following conditions are met:
+|
+|   1. Redistributions of source code must retain the above copyright
+| notice, this list of conditions and the following disclaimer.
+|   2. Redistributions in binary form must reproduce the above copyright
+| notice, this list of conditions and the following disclaimer in the
+| documentation and/or other materials provided with the distribution.
+|   3. The name of the author may not be used to endorse or promote
+| products derived from this software without specific prior written
+| permission.
+|
+| THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+| IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+| IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+| BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+| OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+| OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+| OF SUCH DAMAGE.
+|
+|
+|  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 <glib.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "itdb.h"
+#include "itdb_sha1.h"
+
+static unsigned char *
+calculate_db_checksum (const char *itdb_path, guint64 fwid)
+{
+    int fd;
+    struct stat stat_buf;
+    int result;
+    unsigned char *itdb_data;
+    unsigned char *checksum;
+
+    fd = open (itdb_path, O_RDONLY);
+    if (fd < 0) {
+       g_warning ("Couldn't open %s", itdb_path);
+       return NULL;
+    }
+
+    result = fstat (fd, &stat_buf);
+    if (result != 0) {
+       g_warning ("Couldn't stat %s", itdb_path);
+       close (fd);
+       return NULL;
+    }
+
+    if (stat_buf.st_size < 0x80) {
+       g_warning ("%s is too small", itdb_path);
+       close (fd);
+       return NULL;
+    }
+
+    itdb_data = mmap (NULL, stat_buf.st_size, 
+                     PROT_READ | PROT_WRITE, 
+                     MAP_PRIVATE, fd, 0);
+    if (itdb_data == MAP_FAILED) {
+       g_warning ("Couldn't mmap %s", itdb_path);
+       close (fd);
+       return NULL;
+    }
+
+    /* Those fields must be zero'ed out for the sha1 calculation */
+    memset(itdb_data+0x18, 0, 8);
+    memset(itdb_data+0x32, 0, 20);
+    memset(itdb_data+0x58, 0, 20);
+
+    checksum = itdb_compute_hash (fwid, itdb_data, stat_buf.st_size);
+
+    munmap (itdb_data, stat_buf.st_size);
+    close (fd);
+
+    return checksum;
+}
+
+static gboolean write_checksum_to_file (const char *path, 
+                                       const unsigned char *checksum,
+                                       size_t size)
+{
+    FILE *f;
+    int result;
+    size_t count;
+
+    f = fopen (path, "rb+");
+    if (f == NULL) {
+       return FALSE;
+    }
+    
+    result = fseek (f, 0x58, SEEK_SET);
+    if (result != 0) {
+       fclose (f);
+       return FALSE;
+    }
+    
+    count = fwrite (checksum, size, 1, f);
+    fclose (f);
+   
+    return (count == 1);
+}
+
+int
+main (int argc, char *argv[])
+{
+    char *itdb_path;
+    guint64 firewire_id;
+    unsigned char *checksum;
+    int i;
+
+    if (argc < 3) {
+       g_print ("Usage: %s <mountpoint> <firewire_id> [write]\n"
+                "       firewire_id in hexadecimal, e.g. 00A745....\n"
+                "       If any third argument is given, the checksum is 
written back to the iTunesDB.\n",
+                g_basename(argv[0]));
+       exit (0);
+    }
+    
+    errno = 0;
+    firewire_id = strtoull (argv[2], NULL, 16);
+    if (errno != 0) {
+       g_warning ("Couldn't parse %s as a firewire ID\n", argv[2]);
+       exit (0);       
+    }
+
+    itdb_path = itdb_get_itunesdb_path (argv[1]);
+    checksum = calculate_db_checksum (itdb_path, firewire_id);
+
+    if (argc >= 4)
+    {
+       gboolean success;
+
+       success = write_checksum_to_file (itdb_path, checksum, 20);
+       if (!success)
+       {
+           g_warning ("Couldn't write checksum back to file '%s'\n",
+                      argv[1]);
+       }
+    }
+
+    g_free (itdb_path);
+    
+    if (checksum == NULL) {
+       g_warning ("Couldn't compute checksum");
+       exit (0);
+    }
+
+    for (i = 0; i < strlen ((char *)checksum); i++) {
+       g_print ("%02x ", checksum[i]);
+    }
+    g_print ("\n");
+    g_free (checksum);
+
+    return 0;
+}

Added: libgpod/trunk/tests/test-fw-id.c
===================================================================
--- libgpod/trunk/tests/test-fw-id.c                            (rev 0)
+++ libgpod/trunk/tests/test-fw-id.c    2007-09-24 14:59:33 UTC (rev 1698)
@@ -0,0 +1,65 @@
+/*
+|   Copyright (C) 2007 Christophe Fergeau  <[EMAIL PROTECTED]>
+|
+|   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"
+#include "itdb_device.h"
+
+int
+main (int argc, char *argv[])
+{
+    Itdb_Device *device;
+    char *fwid;
+
+    if (argc < 2) {
+        g_print ("Usage: %s <mountpoint>\n", g_basename (argv[0]));
+        return 1;
+
+    }
+
+    device = itdb_device_new ();
+    if (device == NULL) {
+        return 1;
+    }
+
+    itdb_device_set_mountpoint (device, argv[1]);
+
+    fwid = itdb_device_get_sysinfo (device, "FirewireGuid");
+    if (fwid == NULL) {
+        g_print ("Couldn't find firewire ID\n");
+        return 1;
+    } else {
+       g_print ("FireWire ID: %s\n", fwid);
+    }
+
+    return 0;
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to