don't allow duplicate names in archive

--HG--
branch : HEAD
diff --git a/ChangeLog b/ChangeLog
index d9255b5..5896ccd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2004-11-30  Dieter Baron  <dillo@danbala.tuwien.ac.at>
+
+	* lib/zip_name_locate.c (_zip_name_locate): new function.
+	(zip_name_locate): move actual name lookup to _zip_name_locate.
+	* lib/zip_set_name.c (_zip_set_name): don't allow duplicate names
+	in archive; return error if name is NULL.
+	* lib/zip_replace.c (_zip_replace): don't call _zip_set_name when
+	name is NULL.
+	* lib/zip_get_name.c (zip_get_name): fix when called with
+	partially initialized entry.
+	
 2004-11-30  Thomas Klausner <wiz@danbala.tuwien.ac.at>
 
 	* zipint.h: Include zip.h; add zlib.h.
diff --git a/TODO b/TODO
index 6352a01..6bf93b3 100644
--- a/TODO
+++ b/TODO
@@ -11,18 +11,16 @@
 * zipcmp.c: In function `compare_zip':
 * zipcmp.c:189: warning: passing arg 3 of `compare_list' from incompatible pointer type
 * what is ZIP_CMD_CLOSE good for; check callers
-* man page cleanup: zf/za -> archive; "global variable zip_err"
-* zipint.h should include zip.h?
-* sort zipint.h contents
+* man page cleanup: "global variable zip_err"
 * documentation:
 	zip_error_sys_type zip_file_get_error zip_get_error
-* don't allow the same filename twice in a zip (when adding/replacing)
 * regression tests
 * code review
 * README
 * update code for new API
 * fix XXX in man/
 * fix XXX in lib?
+* fix XXX in ChangeLog!
 ------------------------------------------------ others
 * zip_commit
 * zip_replace_zip: allow rewinding
diff --git a/lib/zip_get_name.c b/lib/zip_get_name.c
index 34f5f3a..293eb3e 100644
--- a/lib/zip_get_name.c
+++ b/lib/zip_get_name.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_get_name.c,v 1.9 2004/11/17 21:55:11 wiz Exp $
+  $NiH: zip_get_name.c,v 1.10 2004/11/18 17:11:21 wiz Exp $
 
   zip_get_name.c -- get filename for a file in zip file
   Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
@@ -51,5 +51,9 @@
     if (za->entry[idx].ch_filename)
 	return za->entry[idx].ch_filename;
 
+    /* newly added (partially filled) entry */
+    if (za->cdir == NULL || idx >= za->cdir->nentry)
+	return NULL;
+    
     return za->cdir->entry[idx].filename;
 }
diff --git a/lib/zip_name_locate.c b/lib/zip_name_locate.c
index 7dc8318..cc8bbc3 100644
--- a/lib/zip_name_locate.c
+++ b/lib/zip_name_locate.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_name_locate.c,v 1.14 2004/11/17 21:55:12 wiz Exp $
+  $NiH: zip_name_locate.c,v 1.15 2004/11/18 15:04:05 wiz Exp $
 
   zip_name_locate.c -- get index by name
   Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
@@ -45,15 +45,30 @@
 int
 zip_name_locate(struct zip *za, const char *fname, int flags)
 {
-    int (*cmp)(const char *, const char *);
-    const char *fn, *p, *q;
-    int i, n;
-
+    int i;
+    
     if (fname == NULL) {
 	_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
 	return -1;
     }
     
+    i = _zip_name_locate(za, fname, flags);
+
+    if (i == -1)
+	_zip_error_set(&za->error, ZIP_ER_NOENT, 0);
+
+    return i;
+}
+
+
+
+int
+_zip_name_locate(struct zip *za, const char *fname, int flags)
+{
+    int (*cmp)(const char *, const char *);
+    const char *fn, *p, *q;
+    int i, n;
+
     cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
 
     n = (flags & ZIP_FL_UNCHANGED) ? za->cdir->nentry : za->nentry;
@@ -62,6 +77,10 @@
 	    fn = za->cdir->entry[i].filename;
 	else
 	    fn = zip_get_name(za, i);
+
+	/* newly added (partially filled) entry */
+	if (fn == NULL)
+	    continue;
 	
 	if (flags & ZIP_FL_NODIR) {
 	    /* XXX: is this correct? */
@@ -79,6 +98,5 @@
 	    return i;
     }
 
-    _zip_error_set(&za->error, ZIP_ER_NOENT, 0);
     return -1;
 }
diff --git a/lib/zip_rename.c b/lib/zip_rename.c
index ab6b669..7e75d2b 100644
--- a/lib/zip_rename.c
+++ b/lib/zip_rename.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_rename.c,v 1.13 2004/11/17 21:55:12 wiz Exp $
+  $NiH: zip_rename.c,v 1.14 2004/11/18 17:11:22 wiz Exp $
 
   zip_rename.c -- rename file in zip archive
   Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
@@ -48,11 +48,5 @@
 	return -1;
     }
 
-    /* XXX: move this to _zip_set_name */
-    if (za->entry[idx].state == ZIP_ST_UNCHANGED) 
-	za->entry[idx].state = ZIP_ST_RENAMED;
-    
-    _zip_set_name(za, idx, name);
-
-    return 0;
+    return _zip_set_name(za, idx, name);
 }
diff --git a/lib/zip_replace.c b/lib/zip_replace.c
index 595271d..92929aa 100644
--- a/lib/zip_replace.c
+++ b/lib/zip_replace.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_replace.c,v 1.17 2004/11/18 15:04:05 wiz Exp $
+  $NiH: zip_replace.c,v 1.18 2004/11/30 21:42:23 wiz Exp $
 
   zip_replace.c -- replace file via callback function
   Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
@@ -67,7 +67,7 @@
     
     _zip_unchange_data(za->entry+idx);
 
-    if (_zip_set_name(za, idx, name) != 0)
+    if (name && _zip_set_name(za, idx, name) != 0)
 	return -1;
     
     za->entry[idx].state = ((za->cdir == NULL || idx >= za->cdir->nentry)
diff --git a/lib/zip_set_name.c b/lib/zip_set_name.c
index ac5f930..d0bf1a5 100644
--- a/lib/zip_set_name.c
+++ b/lib/zip_set_name.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_set_name.c,v 1.13 2004/11/17 21:55:13 wiz Exp $
+  $NiH: zip_set_name.c,v 1.14 2004/11/18 17:11:22 wiz Exp $
 
   zip_set_name.c -- rename helper function
   Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
@@ -47,20 +47,26 @@
 {
     char *s;
     
-    if (idx < 0 || idx >= za->nentry) {
+    if (idx < 0 || idx >= za->nentry || name == NULL) {
 	_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
 	return -1;
     }
 
-    if (name != NULL) {
-	if ((s=strdup(name)) == NULL) {
-	    _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-	    return -1;
-	}
-	
-	free(za->entry[idx].ch_filename);
-	za->entry[idx].ch_filename = s;
+    if (_zip_name_locate(za, name, 0) != -1) {
+	_zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+	return -1;
     }
 
+    if ((s=strdup(name)) == NULL) {
+	_zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+	return -1;
+    }
+    
+    if (za->entry[idx].state == ZIP_ST_UNCHANGED) 
+	za->entry[idx].state = ZIP_ST_RENAMED;
+
+    free(za->entry[idx].ch_filename);
+    za->entry[idx].ch_filename = s;
+
     return 0;
 }
diff --git a/lib/zipint.h b/lib/zipint.h
index 0dcc044..79efc00 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -2,7 +2,7 @@
 #define _HAD_ZIPINT_H
 
 /*
-  $NiH: zipint.h,v 1.32 2004/11/30 21:42:24 wiz Exp $
+  $NiH: zipint.h,v 1.33 2004/11/30 21:51:30 wiz Exp $
 
   zipint.h -- internal declarations.
   Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
@@ -199,6 +199,7 @@
 void _zip_free(struct zip *);
 int _zip_local_header_read(struct zip *, int);
 void *_zip_memdup(const void *, int);
+int _zip_name_locate(struct zip *, const char *, int);
 struct zip *_zip_new(struct zip_error *);
 unsigned short _zip_read2(unsigned char **);
 unsigned int _zip_read4(unsigned char **);