Beginnings of torrentzip support:
- add archive global flags, with support for getting and setting them.
- detect wether archive is torrentzipped

--HG--
branch : HEAD
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ec794e4..a55920c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -30,6 +30,7 @@
 	zip_fread.c \
 	zip_free.c \
 	zip_get_archive_comment.c \
+	zip_get_archive_flag.c \
 	zip_get_file_comment.c \
 	zip_get_num_files.c \
 	zip_get_name.c \
@@ -40,6 +41,7 @@
 	zip_rename.c \
 	zip_replace.c \
 	zip_set_archive_comment.c \
+	zip_set_archive_flag.c \
 	zip_set_file_comment.c \
 	zip_source_buffer.c \
 	zip_source_file.c \
diff --git a/lib/zip.h b/lib/zip.h
index 3342b10..014df7a 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -3,7 +3,7 @@
 
 /*
   zip.h -- exported declarations.
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -66,6 +66,10 @@
 #define ZIP_FL_COMPRESSED	4 /* read compressed data */
 #define ZIP_FL_UNCHANGED	8 /* use original data, ignoring changes */
 
+/* archive global flags flags */
+
+#define ZIP_AFL_TORRENT		1 /* torrent zipped */
+
 /* libzip error codes */
 
 #define ZIP_ER_OK             0  /* N No error */
@@ -188,6 +192,7 @@
 ZIP_EXTERN struct zip_file *zip_fopen_index(struct zip *, int, int);
 ZIP_EXTERN ssize_t zip_fread(struct zip_file *, void *, size_t);
 ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, int);
+ZIP_EXTERN int zip_get_archive_flag(struct zip *, int, int);
 ZIP_EXTERN const char *zip_get_file_comment(struct zip *, int, int *, int);
 ZIP_EXTERN const char *zip_get_name(struct zip *, int, int);
 ZIP_EXTERN int zip_get_num_files(struct zip *);
@@ -196,6 +201,7 @@
 ZIP_EXTERN int zip_rename(struct zip *, int, const char *);
 ZIP_EXTERN int zip_replace(struct zip *, int, struct zip_source *);
 ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, int);
+ZIP_EXTERN int zip_set_archive_flag(struct zip *, int, int);
 ZIP_EXTERN int zip_set_file_comment(struct zip *, int, const char *, int);
 ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *,
 						off_t, int);
diff --git a/lib/zip_new.c b/lib/zip_new.c
index c72a604..3e8ccee 100644
--- a/lib/zip_new.c
+++ b/lib/zip_new.c
@@ -64,6 +64,7 @@
     za->entry = NULL;
     za->nfile = za->nfile_alloc = 0;
     za->file = NULL;
+    za->flags = za->ch_flags = 0;
     
     return za;
 }
diff --git a/lib/zip_open.c b/lib/zip_open.c
index 2d6590f..d3306c8 100644
--- a/lib/zip_open.c
+++ b/lib/zip_open.c
@@ -1,6 +1,6 @@
 /*
   zip_open.c -- open zip archive
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -35,6 +35,7 @@
 
 #include <sys/stat.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -44,6 +45,7 @@
 static void set_error(int *, struct zip_error *, int);
 static struct zip *_zip_allocate_new(const char *, int *);
 static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
+static void _zip_check_torrentzip(struct zip *);
 static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t);
 static int _zip_file_exists(const char *, int, int *);
 static int _zip_headercomp(struct zip_dirent *, int,
@@ -114,6 +116,9 @@
     for (i=0; i<cdir->nentry; i++)
 	_zip_entry_new(za);
 
+    _zip_check_torrentzip(za);
+    za->ch_flags = za->flags;
+
     return za;
 }
 
@@ -193,13 +198,14 @@
 	return NULL;
     }
 
-    if (cd->comment_len)
+    if (cd->comment_len) {
 	if ((cd->comment=(char *)_zip_memdup(eocd+EOCDLEN,
 					     cd->comment_len, error))
 	    == NULL) {
 	    free(cd);
 	    return NULL;
 	}
+    }
 
     cdp = eocd;
     if (cd->size < (unsigned int)(eocd-buf)) {
@@ -297,6 +303,52 @@
 
 
 
+/* _zip_check_torrentzip:
+   check wether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
+
+static void
+_zip_check_torrentzip(struct zip *za)
+{
+    uLong crc_got, crc_should;
+    char *end;
+    Bytef buf[BUFSIZE];
+    unsigned int n, remain;
+
+    if (za->zp == NULL || za->cdir == NULL)
+	return;
+
+    if (za->cdir->comment_len != TORRENT_SIG_LEN+8
+	|| strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0)
+	return;
+    
+    errno = 0;
+    crc_should = strtoul(za->cdir->comment+TORRENT_SIG_LEN, &end, 16);
+    if ((crc_should == UINT_MAX && errno != 0) || (end && *end))
+	return;
+    
+    crc_got = crc32(0L, Z_NULL, 0);
+
+    if (fseek(za->zp, za->cdir->offset, SEEK_SET) != 0)
+	return;
+    remain = za->cdir->size;
+
+    while (remain > 0) {
+	n = remain > BUFSIZE ? BUFSIZE : remain;
+	if ((n=fread(buf, 1, n, za->zp)) <= 0)
+	    return;
+
+	crc_got = crc32(crc_got, buf, n);
+
+	remain -= n;
+    }
+
+    if (crc_got == crc_should)
+	za->flags |= ZIP_AFL_TORRENT;
+}
+
+
+
+
 /* _zip_headercomp:
    compares two headers h1 and h2; if they are local headers, set
    local1p or local2p respectively to 1, else 0. Return 0 if they
diff --git a/lib/zipint.h b/lib/zipint.h
index 775a036..7107585 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -70,6 +70,8 @@
 #define LOCAL_MAGIC   "PK\3\4"
 #define EOCD_MAGIC    "PK\5\6"
 #define DATADES_MAGIC "PK\7\8"
+#define TORRENT_SIG	"TORRENTZIPPED-"
+#define TORRENT_SIG_LEN	14
 #define CDENTRYSIZE         46u
 #define LENTRYSIZE          30
 #define MAXCOMLEN        65536
@@ -111,6 +113,9 @@
     FILE *zp;			/* file */
     struct zip_error error;	/* error information */
 
+    unsigned int flags;		/* archive global flags */
+    unsigned int ch_flags;	/* changed archive global flags */
+
     struct zip_cdir *cdir;	/* central directory */
     char *ch_comment;		/* changed archive comment */
     int ch_comment_len;		/* length of changed zip archive