From 4d322880f4d92b4754602f74ad9a38b9ffcf76d2 Mon Sep 17 00:00:00 2001 From: Michael Sweet Date: Tue, 4 Apr 2017 23:32:11 -0400 Subject: [PATCH] Update ZIP container code, now things are working... --- config.h.in | 4 +- configure.ac | 4 +- mxmldoc.c | 50 ++++----- xcode/mxml.xcodeproj/project.pbxproj | 4 +- zipc.c | 148 ++++++++++++++++++--------- zipc.h | 1 + 6 files changed, 131 insertions(+), 80 deletions(-) diff --git a/config.h.in b/config.h.in index ead41ea..8be60c0 100644 --- a/config.h.in +++ b/config.h.in @@ -45,10 +45,10 @@ /* - * Do we have libarchive's archive.h header? + * Do we have ? */ -#undef HAVE_ARCHIVE_H +#undef HAVE_ZLIB_H /* diff --git a/configure.ac b/configure.ac index 9834d39..4ae516c 100644 --- a/configure.ac +++ b/configure.ac @@ -117,7 +117,9 @@ if test $ac_cv_c_long_long = yes; then fi dnl EPUB support (via libz and zipc) -AC_SEARCH_LIBS(gzgets,z,[LIBS="-lz $LIBS"]) +AC_SEARCH_LIBS(gzgets,z,[ + AC_DEFINE(HAVE_ZLIB_H) + LIBS="-lz $LIBS"]) dnl Threading support AC_ARG_ENABLE(threads, [ --enable-threads enable multi-threading support]) diff --git a/mxmldoc.c b/mxmldoc.c index 0c12f66..6916dbd 100644 --- a/mxmldoc.c +++ b/mxmldoc.c @@ -622,7 +622,7 @@ main(int argc, /* I - Number of command-line args */ break; case OUTPUT_TOKENS : - fputs("\n" + fputs("\n" "\n", stdout); write_tokens(stdout, mxmldoc, path); @@ -3274,7 +3274,7 @@ write_description( else if (*ptr & 128) { /* - * Convert UTF-8 to Unicode constant... + * Convert utf-8 to Unicode constant... */ int ch; /* Unicode character */ @@ -3422,14 +3422,14 @@ write_epub(const char *section, /* I - Section */ zipc_file_t *epubf; /* File in EPUB ZIP container */ char xhtmlfile[1024], /* XHTML output filename */ *xhtmlptr; /* Pointer into output filename */ - mxml_node_t *content_opf, /* content.opf file */ + mxml_node_t *package_opf, /* package_opf file */ *package, /* package node */ *metadata, /* metadata node */ *manifest, /* manifest node */ *spine, /* spine node */ *temp; /* Other (leaf) node */ char identifier[256], /* dc:identifier string */ - *content_opf_string; /* content.opf file as a string */ + *package_opf_string; /* package_opf file as a string */ toc_t *toc; /* Table of contents */ toc_entry_t *tentry; /* Current table of contents */ mxml_node_t *toc_ncx, /* toc.ncx file */ @@ -3450,7 +3450,7 @@ write_epub(const char *section, /* I - Section */ "\n" "\n" " \n" - " \n" + " \n" " \n" "\n"; @@ -3762,7 +3762,7 @@ write_epub(const char *section, /* I - Section */ fclose(fp); /* - * Now make the content.opf file... + * Now make the package_opf file... */ if ((epubptr = strrchr(epubfile, '/')) != NULL) @@ -3773,9 +3773,9 @@ write_epub(const char *section, /* I - Section */ if ((epubptr = strstr(epubbase, ".epub")) != NULL) *epubptr = '\0'; - content_opf = mxmlNewXML("1.0"); + package_opf = mxmlNewXML("1.0"); - package = mxmlNewElement(content_opf, "package"); + package = mxmlNewElement(package_opf, "package"); mxmlElementSetAttr(package, "xmlns", "http://www.idpf.org/2007/opf"); mxmlElementSetAttr(package, "unique-identifier", epubbase); mxmlElementSetAttr(package, "version", "3.0"); @@ -3810,14 +3810,14 @@ write_epub(const char *section, /* I - Section */ manifest = mxmlNewElement(package, "manifest"); - temp = mxmlNewElement(manifest, "item"); - mxmlElementSetAttr(temp, "id", "ncx"); - mxmlElementSetAttr(temp, "href", "toc.ncx"); - mxmlElementSetAttr(temp, "media-type", "application/x-dtbncx+xml"); +// temp = mxmlNewElement(manifest, "item"); +// mxmlElementSetAttr(temp, "id", "ncx"); +// mxmlElementSetAttr(temp, "href", "toc.ncx"); +// mxmlElementSetAttr(temp, "media-type", "application/x-dtbncx+xml"); temp = mxmlNewElement(manifest, "item"); - mxmlElementSetAttr(temp, "id", "toc"); - mxmlElementSetAttr(temp, "href", "toc.xhtml"); + mxmlElementSetAttr(temp, "id", "nav"); + mxmlElementSetAttr(temp, "href", "nav.xhtml"); mxmlElementSetAttr(temp, "media-type", "application/xhtml+xml"); mxmlElementSetAttr(temp, "properties", "nav"); @@ -3829,12 +3829,12 @@ write_epub(const char *section, /* I - Section */ // spine = mxmlNewElement(package, "spine"); - mxmlElementSetAttr(spine, "toc", "ncx"); +// mxmlElementSetAttr(spine, "toc", "ncx"); temp = mxmlNewElement(spine, "itemref"); mxmlElementSetAttr(temp, "idref", "body"); - content_opf_string = mxmlSaveAllocString(content_opf, epub_ws_cb); + package_opf_string = mxmlSaveAllocString(package_opf, epub_ws_cb); /* * Make the toc.ncx file... @@ -3970,14 +3970,14 @@ write_epub(const char *section, /* I - Section */ } unlink(xhtmlfile); - /* OEBPS/content.opf file */ - zipcCreateFileWithString(epub, "OEBPS/content.opf", content_opf_string); + /* OEBPS/package.opf file */ + zipcCreateFileWithString(epub, "OEBPS/package.opf", package_opf_string); /* OEBPS/toc.ncx file */ - zipcCreateFileWithString(epub, "OEBPS/toc.ncx", toc_ncx_string); +// zipcCreateFileWithString(epub, "OEBPS/toc.ncx", toc_ncx_string); - /* OEBPS/toc.xhtml file */ - epubf = zipcCreateFile(epub, "OEBPS/toc.xhtml", 1); + /* OEBPS/nav.xhtml file */ + epubf = zipcCreateFile(epub, "OEBPS/nav.xhtml", 1); if ((fp = fopen(toc_xhtmlfile, "r")) != NULL) { char buffer[65536]; /* Copy buffer */ @@ -4370,7 +4370,7 @@ write_html(const char *section, /* I - Section */ return; } - fputs("\n" + fputs("\n" "\n" "\n" "\n" @@ -4425,7 +4425,7 @@ write_html(const char *section, /* I - Section */ return; } - fputs("\n" + fputs("\n" "\n" "\n" "\n" @@ -4457,7 +4457,7 @@ write_html(const char *section, /* I - Section */ return; } - fputs("\n" + fputs("\n" "\n", out); write_tokens(out, doc, "index.html"); @@ -5781,7 +5781,7 @@ write_string(FILE *out, /* I - Output file */ else if (*s & 128) { /* - * Convert UTF-8 to Unicode constant... + * Convert utf-8 to Unicode constant... */ int ch; /* Unicode character */ diff --git a/xcode/mxml.xcodeproj/project.pbxproj b/xcode/mxml.xcodeproj/project.pbxproj index f8e4694..805d776 100644 --- a/xcode/mxml.xcodeproj/project.pbxproj +++ b/xcode/mxml.xcodeproj/project.pbxproj @@ -440,7 +440,7 @@ "DEBUG=1", "$(inherited)", ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -488,7 +488,7 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; diff --git a/zipc.c b/zipc.c index b976e11..6756089 100644 --- a/zipc.c +++ b/zipc.c @@ -48,25 +48,24 @@ #define ZIPC_LOCAL_HEADER 0x04034b50 /* Start of a local file header */ #define ZIPC_DIR_HEADER 0x02014b50 /* File header in central directory */ -#define ZIPC_DIGITAL_SIG 0x05054b50 /* Digital signature at end */ #define ZIPC_END_RECORD 0x06054b50 /* End of central directory record */ -#define ZIPC_MADE_BY 0x0314 /* Version made by UNIX using zip 2.0 */ -#define ZIPC_VERSION 0x0014 /* Version needed: 2.0 */ +#define ZIPC_MADE_BY 0x031e /* Version made by UNIX using zip 2.0 */ +#define ZIPC_DIR_VERSION 0x000a /* Version needed: 1.0 */ +#define ZIPC_FILE_VERSION 0x0014 /* Version needed: 2.0 */ -#define ZIPC_FLAG_NONE 0 /* No flags */ - -#define ZIPC_FLAG_CMASK 0x0006 /* Compression fields */ -#define ZIPC_FLAG_CNORMAL 0x0000 /* Normal compression */ #define ZIPC_FLAG_CMAX 0x0002 /* Maximum compression */ -#define ZIPC_FLAG_CFAST 0x0004 /* Fast compression */ -#define ZIPC_FLAG_CSUPER 0x0006 /* Super fast compression */ - #define ZIPC_FLAG_DATA 0x0008 /* Length and CRC-32 fields follow data */ #define ZIPC_COMP_STORE 0 /* No compression */ #define ZIPC_COMP_DEFLATE 8 /* Deflate compression */ +#define ZIPC_INTERNAL_BIN 0x0000 /* Internal attributes = binary */ +#define ZIPC_INTERNAL_TEXT 0x0001 /* Internal attributes = text */ + +#define ZIPC_EXTERNAL_DIR 0x41ed0010 /* External attributes = directory */ +#define ZIPC_EXTERNAL_FILE 0x81a40000 /* External attributes = file */ + /* * Local types... @@ -76,11 +75,11 @@ struct _zipc_s { FILE *fp; /* ZIP file */ const char *error; /* Last error message */ - int alloc_files, /* Allocated file entries in ZIP */ + size_t alloc_files, /* Allocated file entries in ZIP */ num_files; /* Number of file entries in ZIP */ zipc_file_t *files; /* File entries in ZIP */ - unsigned int modtime; /* MS-DOS modification date/time */ z_stream stream; /* Deflate stream for current file */ + unsigned int modtime; /* MS-DOS modification date/time */ char buffer[16384]; /* Deflate output buffer */ }; @@ -94,6 +93,8 @@ struct _zipc_file_s size_t compressed_size; /* Size of file (compressed) */ size_t uncompressed_size; /* Size of file (uncompressed) */ size_t offset; /* Offset of this entry in file */ + unsigned short internal_attrs; /* Internal attributes */ + unsigned int external_attrs; /* External attributes */ }; @@ -141,9 +142,9 @@ zipcClose(zipc_t *zc) /* I - ZIP container */ status |= zipc_write_u32(zc, ZIPC_END_RECORD); status |= zipc_write_u16(zc, 0); /* Disk number */ status |= zipc_write_u16(zc, 0); /* Disk number containing directory */ - status |= zipc_write_u16(zc, zc->num_files); - status |= zipc_write_u16(zc, zc->num_files); - status |= zipc_write_u32(zc, end - start); + status |= zipc_write_u16(zc, (unsigned)zc->num_files); + status |= zipc_write_u16(zc, (unsigned)zc->num_files); + status |= zipc_write_u32(zc, (unsigned)(end - start)); status |= zipc_write_u32(zc, (unsigned)start); status |= zipc_write_u16(zc, 0); /* file comment length */ @@ -159,6 +160,42 @@ zipcClose(zipc_t *zc) /* I - ZIP container */ } +/* + * 'zipcCreateDirectory()' - Create a directory in a ZIP container. + * + * The "filename" value is the path within the ZIP container. Directories are + * separated by the forward slash ("/"). + */ + +int /* O - 0 on success, -1 on error */ +zipcCreateDirectory( + zipc_t *zc, /* I - ZIP container */ + const char *filename) /* I - Directory name */ +{ + zipc_file_t *zf = zipc_add_file(zc, filename, 0); + /* ZIP container file */ + int status = 0; /* Return status */ + + + if (zf) + { + char *end = zf->filename + strlen(zf->filename); + + if (end > zf->filename && end < (zf->filename + sizeof(zf->filename) - 1) && end[-1] != '/') + *end = '/'; + + zf->crc32 = 0; + zf->external_attrs = ZIPC_EXTERNAL_DIR; + + status |= zipc_write_local_header(zc, zf); + } + else + status = -1; + + return (status); +} + + /* * 'zipcCreateFile()' - Create a ZIP container file. * @@ -182,6 +219,7 @@ zipcCreateFile( zipc_file_t *zf = zipc_add_file(zc, filename, compressed); /* ZIP container file */ + zf->external_attrs = ZIPC_EXTERNAL_FILE; if (zipc_write_local_header(zc, zf)) return (NULL); @@ -215,7 +253,9 @@ zipcCreateFileWithString( { zf->uncompressed_size = len; zf->compressed_size = len; - zf->crc32 = crc32(zf->crc32, (const Bytef *)contents, len); + zf->crc32 = crc32(zf->crc32, (const Bytef *)contents, (unsigned)len); + zf->internal_attrs = ZIPC_INTERNAL_TEXT; + zf->external_attrs = ZIPC_EXTERNAL_FILE; status |= zipc_write_local_header(zc, zf); status |= zipc_write(zc, contents, len); @@ -262,8 +302,8 @@ zipcFileFinish(zipc_file_t *zf) /* I - ZIP container file */ break; } - status |= zipc_write(zf->zc, zc->buffer, (char *)zc->stream.next_out - zc->buffer); - zf->compressed_size += (char *)zc->stream.next_out - zc->buffer; + status |= zipc_write(zf->zc, zc->buffer, (size_t)((char *)zc->stream.next_out - zc->buffer)); + zf->compressed_size += (size_t)((char *)zc->stream.next_out - zc->buffer); zc->stream.next_out = (Bytef *)zc->buffer; zc->stream.avail_out = sizeof(zc->buffer); @@ -271,8 +311,8 @@ zipcFileFinish(zipc_file_t *zf) /* I - ZIP container file */ if ((char *)zc->stream.next_out > zc->buffer) { - status |= zipc_write(zf->zc, zc->buffer, (char *)zc->stream.next_out - zc->buffer); - zf->compressed_size += (char *)zc->stream.next_out - zc->buffer; + status |= zipc_write(zf->zc, zc->buffer, (size_t)((char *)zc->stream.next_out - zc->buffer)); + zf->compressed_size += (size_t)((char *)zc->stream.next_out - zc->buffer); } deflateEnd(&zc->stream); @@ -312,6 +352,8 @@ zipcFilePrintf(zipc_file_t *zf, /* I - ZIP container file */ } va_end(ap); + zf->internal_attrs = ZIPC_INTERNAL_TEXT; + return (zipcFileWrite(zf, buffer, strlen(buffer))); } @@ -330,6 +372,8 @@ int /* O - 0 on success, -1 on error */ zipcFilePuts(zipc_file_t *zf, /* I - ZIP container file */ const char *s) /* I - String to write */ { + zf->internal_attrs = ZIPC_INTERNAL_TEXT; + return (zipcFileWrite(zf, s, strlen(s))); } @@ -355,7 +399,7 @@ zipcFileWrite(zipc_file_t *zf, /* I - ZIP container file */ zf->uncompressed_size += bytes; - zf->crc32 = crc32(zf->crc32, (const Bytef *)data, bytes); + zf->crc32 = crc32(zf->crc32, (const Bytef *)data, (unsigned)bytes); if (zf->method == ZIPC_COMP_STORE) { @@ -381,8 +425,8 @@ zipcFileWrite(zipc_file_t *zf, /* I - ZIP container file */ { if (zc->stream.avail_out < (int)(sizeof(zc->buffer) / 8)) { - status |= zipc_write(zf->zc, zc->buffer, (char *)zc->stream.next_out - zc->buffer); - zf->compressed_size += (char *)zc->stream.next_out - zc->buffer; + status |= zipc_write(zf->zc, zc->buffer, (size_t)((char *)zc->stream.next_out - zc->buffer)); + zf->compressed_size += (size_t)((char *)zc->stream.next_out - zc->buffer); zc->stream.next_out = (Bytef *)zc->buffer; zc->stream.avail_out = sizeof(zc->buffer); @@ -525,7 +569,11 @@ zipcFileXMLPrintf( } if (bufptr > buffer) - status |= zipcFileWrite(zf, buffer, bufptr - buffer); + { + zf->internal_attrs = ZIPC_INTERNAL_TEXT; + + status |= zipcFileWrite(zf, buffer, (size_t)(bufptr - buffer)); + } return (status); } @@ -578,23 +626,23 @@ zipcOpen(const char *filename, /* I - Filename of container */ * * Bits Description * ------ ----------- - * 0-4 Second - * 5-10 Minute - * 11-15 Hour + * 0-4 Seconds / 2 (0-29) + * 5-10 Minute (0-59) + * 11-15 Hour (0-23) * 16-20 Day (1-31) * 21-24 Month (1-12) * 25-31 Years since 1980 */ curtime = time(NULL); - curdate = gmtime(&curtime); - - zc->modtime = curdate->tm_sec | - (curdate->tm_min << 5) | - (curdate->tm_hour << 11) | - (curdate->tm_mday << 16) | - ((curdate->tm_mon + 1) << 21) | - ((curdate->tm_year - 80) << 25); + curdate = localtime(&curtime); + + zc->modtime = (unsigned)(curdate->tm_sec / 2) | + ((unsigned)curdate->tm_min << 5) | + ((unsigned)curdate->tm_hour << 11) | + ((unsigned)curdate->tm_mday << 16) | + ((unsigned)(curdate->tm_mon + 1) << 21) | + ((unsigned)(curdate->tm_year - 80) << 25); } return (zc); @@ -644,7 +692,7 @@ zipc_add_file(zipc_t *zc, /* I - ZIP container */ temp->zc = zc; temp->crc32 = crc32(0, NULL, 0); - temp->offset = ftell(zc->fp); + temp->offset = (size_t)ftell(zc->fp); if (compression) { @@ -698,20 +746,20 @@ zipc_write_dir_header( status |= zipc_write_u32(zc, ZIPC_DIR_HEADER); status |= zipc_write_u16(zc, ZIPC_MADE_BY); - status |= zipc_write_u16(zc, ZIPC_VERSION); + status |= zipc_write_u16(zc, zf->external_attrs == ZIPC_EXTERNAL_DIR ? ZIPC_DIR_VERSION : ZIPC_FILE_VERSION); status |= zipc_write_u16(zc, zf->flags); status |= zipc_write_u16(zc, zf->method); status |= zipc_write_u32(zc, zc->modtime); status |= zipc_write_u32(zc, zf->crc32); - status |= zipc_write_u32(zc, zf->compressed_size); - status |= zipc_write_u32(zc, zf->uncompressed_size); - status |= zipc_write_u16(zc, filenamelen); + status |= zipc_write_u32(zc, (unsigned)zf->compressed_size); + status |= zipc_write_u32(zc, (unsigned)zf->uncompressed_size); + status |= zipc_write_u16(zc, (unsigned)filenamelen); status |= zipc_write_u16(zc, 0); /* extra field length */ status |= zipc_write_u16(zc, 0); /* comment length */ status |= zipc_write_u16(zc, 0); /* disk number start */ - status |= zipc_write_u16(zc, 0); /* internal file attributes */ - status |= zipc_write_u32(zc, 0); /* external file attributes */ - status |= zipc_write_u32(zc, zf->offset); + status |= zipc_write_u16(zc, zf->internal_attrs); + status |= zipc_write_u32(zc, zf->external_attrs); + status |= zipc_write_u32(zc, (unsigned)zf->offset); status |= zipc_write(zc, zf->filename, filenamelen); return (status); @@ -732,18 +780,18 @@ zipc_write_local_header( size_t filenamelen = strlen(zf->filename); /* Length of filename */ - if (zf->uncompressed_size == 0) + if (zf->uncompressed_size == 0 && zf->external_attrs != ZIPC_EXTERNAL_DIR) flags |= ZIPC_FLAG_DATA; status |= zipc_write_u32(zc, ZIPC_LOCAL_HEADER); - status |= zipc_write_u16(zc, ZIPC_VERSION); + status |= zipc_write_u16(zc, zf->external_attrs == ZIPC_EXTERNAL_DIR ? ZIPC_DIR_VERSION : ZIPC_FILE_VERSION); status |= zipc_write_u16(zc, flags); status |= zipc_write_u16(zc, zf->method); status |= zipc_write_u32(zc, zc->modtime); status |= zipc_write_u32(zc, zf->uncompressed_size == 0 ? 0 : zf->crc32); - status |= zipc_write_u32(zc, zf->compressed_size); - status |= zipc_write_u32(zc, zf->uncompressed_size); - status |= zipc_write_u16(zc, filenamelen); + status |= zipc_write_u32(zc, (unsigned)zf->compressed_size); + status |= zipc_write_u32(zc, (unsigned)zf->uncompressed_size); + status |= zipc_write_u16(zc, (unsigned)filenamelen); status |= zipc_write_u16(zc, 0); /* extra field length */ status |= zipc_write(zc, zf->filename, filenamelen); @@ -764,8 +812,8 @@ zipc_write_local_trailer( status |= zipc_write_u32(zc, zf->crc32); - status |= zipc_write_u32(zc, zf->compressed_size); - status |= zipc_write_u32(zc, zf->uncompressed_size); + status |= zipc_write_u32(zc, (unsigned)zf->compressed_size); + status |= zipc_write_u32(zc, (unsigned)zf->uncompressed_size); return (status); } diff --git a/zipc.h b/zipc.h index ab2ca56..20265c6 100644 --- a/zipc.h +++ b/zipc.h @@ -50,6 +50,7 @@ typedef struct _zipc_file_s zipc_file_t;/* File/directory in ZIP container */ */ extern int zipcClose(zipc_t *zc); +extern int zipcCreateDirectory(zipc_t *zc, const char *filename); extern zipc_file_t *zipcCreateFile(zipc_t *zc, const char *filename, int compressed); extern int zipcCreateFileWithString(zipc_t *zc, const char *filename, const char *contents); extern const char *zipcError(zipc_t *zc);