Update ZIP container code, now things are working...

This commit is contained in:
Michael Sweet 2017-04-04 23:32:11 -04:00
parent 7c2551e996
commit 4d322880f4
6 changed files with 130 additions and 79 deletions

View File

@ -45,10 +45,10 @@
/*
* Do we have libarchive's archive.h header?
* Do we have <zlib.h>?
*/
#undef HAVE_ARCHIVE_H
#undef HAVE_ZLIB_H
/*

View File

@ -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])

View File

@ -622,7 +622,7 @@ main(int argc, /* I - Number of command-line args */
break;
case OUTPUT_TOKENS :
fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<Tokens version=\"1.0\">\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 */
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<container xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\" version=\"1.0\">\n"
" <rootfiles>\n"
" <rootfile full-path=\"OEBPS/content.opf\" media-type=\"application/oebps-package+xml\"/>\n"
" <rootfile full-path=\"OEBPS/package.opf\" media-type=\"application/oebps-package+xml\"/>\n"
" </rootfiles>\n"
"</container>\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 */
// <item id="imgl" href="images/sample.png" media-type="image/png" />
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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n"
@ -4425,7 +4425,7 @@ write_html(const char *section, /* I - Section */
return;
}
fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<DocSetNodes version=\"1.0\">\n"
"<TOC>\n"
"<Node id=\"0\">\n"
@ -4457,7 +4457,7 @@ write_html(const char *section, /* I - Section */
return;
}
fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<Tokens version=\"1.0\">\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 */

View File

@ -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;

146
zipc.c
View File

@ -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);
curdate = localtime(&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);
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);
}

1
zipc.h
View File

@ -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);