Add encoding support to zip_{get,set}_{file,archive}_comment,
and handle interaction in zip_{get,set}_name.
Set general purpose bit flag 11 when writing out UTF-8 names.
Add new error type ZIP_ER_ENCMISMATCH for the case where the
encoding of file name and file comment don't match.

Document changes and workaround for ZIP_ER_ENCMISMATCH.

Update copyright years.

--HG--
branch : HEAD
diff --git a/lib/zip_get_file_comment.c b/lib/zip_get_file_comment.c
index aef0a7a..fc8c1ae 100644
--- a/lib/zip_get_file_comment.c
+++ b/lib/zip_get_file_comment.c
@@ -1,6 +1,6 @@
 /*
   zip_get_file_comment.c -- get file comment
-  Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2012 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>
@@ -33,6 +33,8 @@
 
 
 
+#include <string.h>
+
 #include "zipint.h"
 
 
@@ -40,12 +42,18 @@
 ZIP_EXTERN const char *
 zip_get_file_comment(struct zip *za, zip_uint64_t idx, int *lenp, int flags)
 {
+    const char *ret;
+
     if (idx >= za->nentry) {
 	_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
 	return NULL;
     }
 
     if ((flags & ZIP_FL_UNCHANGED) || (za->entry[idx].changes.valid & ZIP_DIRENT_COMMENT) == 0) {
+	if (za->cdir == NULL) {
+	    _zip_error_set(&za->error, ZIP_ER_NOENT, 0);
+	    return NULL;
+	}
 	if (idx >= za->cdir->nentry) {
 	    _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
 	    return NULL;
@@ -53,9 +61,32 @@
 	    
 	if (lenp != NULL)
 	    *lenp = za->cdir->entry[idx].settable.comment_len;
-	return za->cdir->entry[idx].settable.comment;
+	ret = za->cdir->entry[idx].settable.comment;
+
+	if (flags & ZIP_FL_NAME_RAW)
+	    return ret;
+
+	/* file comment already is UTF-8? */
+	if (za->cdir->entry[idx].bitflags & ZIP_GPBF_ENCODING_UTF_8)
+	    return ret;
+	
+	/* undeclared, start guessing */
+	if (za->cdir->entry[idx].fc_type == ZIP_ENCODING_UNKNOWN)
+	    za->cdir->entry[idx].fc_type = _zip_guess_encoding(ret, za->cdir->entry[idx].settable.comment_len);
+
+	if (((flags & ZIP_FL_NAME_STRICT) && (za->cdir->entry[idx].fc_type != ZIP_ENCODING_ASCII))
+	    || (za->cdir->entry[idx].fc_type == ZIP_ENCODING_CP437)) {
+	    if (za->cdir->entry[idx].comment_converted == NULL)
+		za->cdir->entry[idx].comment_converted = _zip_cp437_to_utf8(ret, za->cdir->entry[idx].settable.comment_len, &za->error);
+	    ret = za->cdir->entry[idx].comment_converted;
+	    if (lenp != NULL)
+		*lenp = strlen(ret);
+	}
+
+	return ret;
     }
 
+    /* already UTF-8, no conversion necessary */
     if (lenp != NULL)
 	*lenp = za->entry[idx].changes.comment_len;
     return za->entry[idx].changes.comment;