#include <zlib.h>
-#include "junzip.h"
-
-#define ZIP_CENTRAL_SIGNATURE 0
-#define ZIP_CENTRAL_VERSION_MADE_BY 4
-#define ZIP_CENTRAL_VERSION_NEEDED_TO_EXTRACT 6
-#define ZIP_CENTRAL_GENERAL_PURPOSE_BIT_FLAG 8
-#define ZIP_CENTRAL_COMPRESSION_METHOD 10
-#define ZIP_CENTRAL_LAST_MOD_FILE_TIME 12
-#define ZIP_CENTRAL_LAST_MOD_FILE_DATE 14
-#define ZIP_CENTRAL_CRC32 16
-#define ZIP_CENTRAL_COMPRESSED_SIZE 20
-#define ZIP_CENTRAL_UNCOMPRESSED_SIZE 24
-#define ZIP_CENTRAL_FILE_NAME_LENGTH 28
-#define ZIP_CENTRAL_EXTRA_FIELD_LENGTH 30
-#define ZIP_CENTRAL_FILE_COMMENT_LENGTH 32
-#define ZIP_CENTRAL_DISK_NUMBER_START 34
-#define ZIP_CENTRAL_INTERNAL_FILE_ATTRIBUTES 36
-#define ZIP_CENTRAL_EXTERNAL_FILE_ATTRIBUTES 38
-#define ZIP_CENTRAL_RELATIVE_OFFSET_OF_LOCAL_HEADER 42
-#define ZIP_CENTRAL_DIRECTORY_LENGTH 46
-
-#define ZIP_END_SIGNATURE_OFFSET 0
-#define ZIP_END_DESK_NUMBER 4
-#define ZIP_END_CENTRAL_DIRECTORY_DISK_NUMBER 6
-#define ZIP_END_NUM_ENTRIES_THIS_DISK 8
-#define ZIP_END_NUM_ENTRIES 10
-#define ZIP_END_CENTRAL_DIRECTORY_SIZE 12
-#define ZIP_END_CENTRAL_DIRECTORY_OFFSET 16
-#define ZIP_END_ZIP_COMMENT_LENGTH 20
-#define ZIP_END_DIRECTORY_LENGTH 22
-
-#define get_u16(PTR) ((PTR)[0] | ((PTR)[1] << 8))
-#define get_u32(PTR) ((PTR)[0] | ((PTR)[1]<<8) | ((PTR)[2]<<16) | ((PTR)[3]<<24))
+#include "private-libwebsockets.h"
+
+enum {
+ ZC_SIGNATURE = 0,
+ ZC_VERSION_MADE_BY = 4,
+ ZC_VERSION_NEEDED_TO_EXTRACT = 6,
+ ZC_GENERAL_PURPOSE_BIT_FLAG = 8,
+ ZC_COMPRESSION_METHOD = 10,
+ ZC_LAST_MOD_FILE_TIME = 12,
+ ZC_LAST_MOD_FILE_DATE = 14,
+ ZC_CRC32 = 16,
+ ZC_COMPRESSED_SIZE = 20,
+ ZC_UNCOMPRESSED_SIZE = 24,
+ ZC_FILE_NAME_LENGTH = 28,
+ ZC_EXTRA_FIELD_LENGTH = 30,
+ ZC_FILE_COMMENT_LENGTH = 32,
+ ZC_DISK_NUMBER_START = 34,
+ ZC_INTERNAL_FILE_ATTRIBUTES = 36,
+ ZC_EXTERNAL_FILE_ATTRIBUTES = 38,
+ ZC_RELATIVE_OFFSET_OF_LOCAL_HEADER = 42,
+ ZC_DIRECTORY_LENGTH = 46,
+
+ ZE_SIGNATURE_OFFSET = 0,
+ ZE_DESK_NUMBER = 4,
+ ZE_CENTRAL_DIRECTORY_DISK_NUMBER = 6,
+ ZE_NUM_ENTRIES_THIS_DISK = 8,
+ ZE_NUM_ENTRIES = 10,
+ ZE_CENTRAL_DIRECTORY_SIZE = 12,
+ ZE_CENTRAL_DIRECTORY_OFFSET = 16,
+ ZE_ZIP_COMMENT_LENGTH = 20,
+ ZE_DIRECTORY_LENGTH = 22,
+};
+
+static uint16_t
+get_u16(void *p)
+{
+ const uint8_t *c = (const uint8_t *)p;
+
+ return (uint16_t)((c[0] | (c[1] << 8)));
+}
+
+static uint32_t
+get_u32(void *p)
+{
+ const uint8_t *c = (const uint8_t *)p;
+
+ return (uint32_t)((c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)));
+}
static int
-zf_seek_set(JZFile *zfile, size_t offset)
+zf_seek_set(jzfile_t *zfile, size_t offset)
{
- int new_position = offset;
- if (new_position < 0 || new_position > zfile->length)
- return -1;
- zfile->position = new_position;
- return 0;
+ int new_position = offset;
+
+ if (new_position < 0 || new_position > zfile->length)
+ return -1;
+ zfile->position = new_position;
+
+ return 0;
}
static int
-zf_seek_cur(JZFile *zfile, size_t offset)
+zf_seek_cur(jzfile_t *zfile, size_t offset)
{
- int new_position = zfile->position + offset;
- if (new_position < 0 || new_position > zfile->length)
- return -1;
- zfile->position = new_position;
- return 0;
+ int new_position = zfile->position + offset;
+
+ if (new_position < 0 || new_position > zfile->length)
+ return -1;
+ zfile->position = new_position;
+
+ return 0;
}
static int
-zf_seek_end(JZFile *zfile, size_t offset)
+zf_seek_end(jzfile_t *zfile, size_t offset)
{
- int new_position = zfile->length + offset;
- if (new_position < 0 || new_position > zfile->length)
- return -1;
- zfile->position = new_position;
- return 0;
+ int new_position = zfile->length + offset;
+
+ if (new_position < 0 || new_position > zfile->length)
+ return -1;
+ zfile->position = new_position;
+
+ return 0;
}
-size_t zf_read(JZFile *zfile, void *buf, size_t size)
+size_t
+zf_read(jzfile_t *zfile, void *buf, size_t size)
{
- size_t avail = zfile->length - zfile->position;
- if (size > avail)
- size = avail;
- memcpy(buf, zfile->start + zfile->position, size);
- zfile->position += size;
- return size;
+ size_t avail = zfile->length - zfile->position;
+
+ if (size > avail)
+ size = avail;
+ memcpy(buf, zfile->start + zfile->position, size);
+ zfile->position += size;
+
+ return size;
}
-// Read ZIP file end record. Will move within file.
-int jzReadEndRecord(JZFile *zip) {
- long fileSize, readBytes, i;
-
- if(zf_seek_end(zip, -ZIP_END_DIRECTORY_LENGTH)) {
- return Z_ERRNO;
- }
-
- unsigned char *ptr = zf_current(zip);
- while (ptr[0] != 0x50 || ptr[1] != 0x4B || ptr[2] != 0x05 || ptr[3] != 0x06) {
- if (ptr == zip->start) {
- return Z_ERRNO;
- }
- ptr--;
- }
- zip->numEntries = get_u16(ptr + ZIP_END_NUM_ENTRIES);
- zip->centralDirectoryOffset= get_u32(ptr + ZIP_END_CENTRAL_DIRECTORY_OFFSET);
- if (get_u16(ptr + ZIP_END_DESK_NUMBER)
- || get_u16(ptr + ZIP_END_CENTRAL_DIRECTORY_DISK_NUMBER)
- || zip->numEntries != get_u16(ptr + ZIP_END_NUM_ENTRIES_THIS_DISK)) {
- return Z_ERRNO;
- }
-
- return Z_OK;
+/* Read ZIP file end record. Will move within file. */
+int
+jzReadEndRecord(jzfile_t *zip)
+{
+ unsigned char *ptr = zf_current(zip);
+
+ if (zf_seek_end(zip, -ZE_DIRECTORY_LENGTH))
+ return Z_ERRNO;
+
+ while (ptr[0] != 0x50 || ptr[1] != 0x4B || ptr[2] != 5 || ptr[3] != 6)
+ if (ptr-- == zip->start)
+ return Z_ERRNO;
+
+ zip->numEntries = get_u16(ptr + ZE_NUM_ENTRIES);
+ zip->centralDirectoryOffset= get_u32(ptr + ZE_CENTRAL_DIRECTORY_OFFSET);
+
+ if (get_u16(ptr + ZE_DESK_NUMBER) ||
+ get_u16(ptr + ZE_CENTRAL_DIRECTORY_DISK_NUMBER) ||
+ zip->numEntries != get_u16(ptr + ZE_NUM_ENTRIES_THIS_DISK))
+ return Z_ERRNO;
+
+ return Z_OK;
}
-// Read ZIP file global directory. Will move within file.
-int jzReadCentralDirectory(JZFile *zip, JZRecordCallback callback) {
- JZFileHeader header;
- int i;
-
- if(zf_seek_set(zip, zip->centralDirectoryOffset)) {
- return Z_ERRNO;
- }
-
- for(i=0; i < zip->numEntries; i++) {
- unsigned char *ptr = zf_current(zip);
- if (zf_available(zip) < ZIP_CENTRAL_DIRECTORY_LENGTH) {
- return Z_ERRNO;
- }
- zf_seek_cur(zip, ZIP_CENTRAL_DIRECTORY_LENGTH);
- if (get_u32(ptr + ZIP_CENTRAL_SIGNATURE) != 0x02014B50) {
- return Z_ERRNO;
- }
- // Construct JZFileHeader from global file header
- header.compressionMethod = get_u16(ptr + ZIP_CENTRAL_COMPRESSION_METHOD);
- header.crc32 = get_u32(ptr + ZIP_CENTRAL_CRC32);
- header.compressedSize = get_u32(ptr + ZIP_CENTRAL_COMPRESSED_SIZE);
- header.uncompressedSize = get_u32(ptr + ZIP_CENTRAL_UNCOMPRESSED_SIZE);
- header.fileNameLength = get_u16(ptr + ZIP_CENTRAL_FILE_NAME_LENGTH);
- header.extraFieldLength = get_u16(ptr + ZIP_CENTRAL_EXTRA_FIELD_LENGTH);
- header.offset = get_u32(ptr + ZIP_CENTRAL_RELATIVE_OFFSET_OF_LOCAL_HEADER);
-
- header.fileNameStart = zf_tell(zip);
- if (zf_seek_cur(zip, header.fileNameLength + header.extraFieldLength + get_u16(ptr + ZIP_CENTRAL_FILE_COMMENT_LENGTH))) {
- return Z_ERRNO;
- }
-
- if(!callback(zip, i, &header))
- break; // end if callback returns zero
- }
-
- return Z_OK;
+/* Read ZIP file global directory. Will move within file. */
+int
+jzReadCentralDirectory(jzfile_t *zip, jzcb_t callback)
+{
+ jzfile_hdr_t h;
+ int i;
+
+ if (zf_seek_set(zip, zip->centralDirectoryOffset))
+ return Z_ERRNO;
+
+ for (i = 0; i < zip->numEntries; i++) {
+ unsigned char *ptr = zf_current(zip);
+
+ if (zf_available(zip) < ZC_DIRECTORY_LENGTH)
+ return Z_ERRNO;
+
+ zf_seek_cur(zip, ZC_DIRECTORY_LENGTH);
+ if (get_u32(ptr + ZC_SIGNATURE) != 0x02014B50)
+ return Z_ERRNO;
+
+ // Construct jzfile_hdr_t from global file h
+ h.compressionMethod = get_u16(ptr + ZC_COMPRESSION_METHOD);
+ h.crc32 = get_u32(ptr + ZC_CRC32);
+ h.compressedSize = get_u32(ptr + ZC_COMPRESSED_SIZE);
+ h.uncompressedSize = get_u32(ptr + ZC_UNCOMPRESSED_SIZE);
+ h.fileNameLength = get_u16(ptr + ZC_FILE_NAME_LENGTH);
+ h.extraFieldLength = get_u16(ptr + ZC_EXTRA_FIELD_LENGTH);
+ h.offset = get_u32(ptr + ZC_RELATIVE_OFFSET_OF_LOCAL_HEADER);
+
+ h.fileNameStart = zf_tell(zip);
+ if (zf_seek_cur(zip, h.fileNameLength + h.extraFieldLength +
+ get_u16(ptr + ZC_FILE_COMMENT_LENGTH)))
+ return Z_ERRNO;
+
+ if (!callback(zip, i, &h))
+ break; // end if callback returns zero
+ }
+
+ return Z_OK;
}
-int jzSeekData(JZFile *zip, JZFileHeader *entry) {
- size_t offset = entry->offset;
- offset += ZIP_LOCAL_FILE_HEADER_LENGTH;
- offset += entry->fileNameLength + entry->extraFieldLength;
- if (offset < 0 || offset > zip->length)
- return Z_STREAM_END;
- zip->position = offset;
- return Z_OK;
+int jzSeekData(jzfile_t *zip, jzfile_hdr_t *entry)
+{
+ size_t offset = entry->offset;
+
+ offset += ZIP_LOCAL_FILE_HEADER_LENGTH;
+ offset += entry->fileNameLength + entry->extraFieldLength;
+
+ if (offset < 0 || offset > zip->length)
+ return Z_STREAM_END;
+
+ zip->position = offset;
+
+ return Z_OK;
}
-// Read data from file stream, described by header, to preallocated buffer
-int jzReadData(JZFile *zip, JZFileHeader *header, void *buffer) {
- unsigned char *bytes = (unsigned char *)buffer; // cast
- long compressedLeft, uncompressedLeft;
- z_stream strm;
- int ret;
-
- if(header->compressionMethod == 0) { // Store - just read it
- if (zf_read(zip, buffer, header->uncompressedSize) <
- header->uncompressedSize)
- return Z_ERRNO;
- } else if (header->compressionMethod == 8) { // Deflate - using zlib
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
-
- strm.avail_in = 0;
- strm.next_in = Z_NULL;
-
- // Use inflateInit2 with negative window bits to indicate raw data
- if ((ret = inflateInit2(&strm, -MAX_WBITS)) != Z_OK)
- return ret; // Zlib errors are negative
-
- // Inflate compressed data
- for (compressedLeft = header->compressedSize,
- uncompressedLeft = header->uncompressedSize;
- compressedLeft && uncompressedLeft && ret != Z_STREAM_END;
- compressedLeft -= strm.avail_in) {
- // Read next chunk
- unsigned char *ptr = zf_current(zip);
- strm.avail_in = compressedLeft;
- zf_seek_cur(zip, compressedLeft);
- if(strm.avail_in == 0) {
- inflateEnd(&strm);
- return Z_ERRNO;
- }
-
- strm.next_in = ptr;
- strm.avail_out = uncompressedLeft;
- strm.next_out = bytes;
-
- compressedLeft -= strm.avail_in; // inflate will change avail_in
-
- ret = inflate(&strm, Z_NO_FLUSH);
-
- if(ret == Z_STREAM_ERROR) return ret; // shouldn't happen
-
- switch (ret) {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR; /* and fall through */
- case Z_DATA_ERROR: case Z_MEM_ERROR:
- (void)inflateEnd(&strm);
- return ret;
- }
-
- bytes += uncompressedLeft - strm.avail_out; // bytes uncompressed
- uncompressedLeft = strm.avail_out;
- }
-
- inflateEnd(&strm);
- } else {
- return Z_ERRNO;
- }
-
- return Z_OK;
+/* Read data from file stream, described by h, to preallocated buffer */
+int
+jzReadData(jzfile_t *zip, jzfile_hdr_t *h, void *buffer)
+{
+ unsigned char *bytes = (unsigned char *)buffer;
+ long compressedLeft, uncompressedLeft;
+ z_stream strm;
+ int ret;
+
+ switch (h->compressionMethod) {
+ case 0: /* Store - just read it */
+ if (zf_read(zip, buffer, h->uncompressedSize) <
+ h->uncompressedSize)
+ return Z_ERRNO;
+ break;
+ case 8: /* Deflate - using zlib */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+
+ /*
+ * Use inflateInit2 with negative window bits to
+ * indicate raw data
+ */
+ if ((ret = inflateInit2(&strm, -MAX_WBITS)) != Z_OK)
+ return ret; /* Zlib errors are negative */
+
+ /* Inflate compressed data */
+ for (compressedLeft = h->compressedSize,
+ uncompressedLeft = h->uncompressedSize;
+ compressedLeft && uncompressedLeft && ret != Z_STREAM_END;
+ compressedLeft -= strm.avail_in) {
+ /* Read next chunk */
+ unsigned char *ptr = zf_current(zip);
+
+ strm.avail_in = compressedLeft;
+ zf_seek_cur(zip, compressedLeft);
+ if (strm.avail_in == 0) {
+ inflateEnd(&strm);
+
+ return Z_ERRNO;
+ }
+
+ strm.next_in = ptr;
+ strm.avail_out = uncompressedLeft;
+ strm.next_out = bytes;
+
+ compressedLeft -= strm.avail_in;
+ /* inflate will change avail_in */
+
+ ret = inflate(&strm, Z_NO_FLUSH);
+
+ if (ret == Z_STREAM_ERROR)
+ return ret;
+
+ switch (ret) {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ /* and fall through */
+ case Z_DATA_ERROR: case Z_MEM_ERROR:
+ (void)inflateEnd(&strm);
+
+ return ret;
+ }
+
+ /* bytes uncompressed */
+ bytes += uncompressedLeft - strm.avail_out;
+ uncompressedLeft = strm.avail_out;
+ }
+
+ inflateEnd(&strm);
+ break;
+ default:
+ return Z_ERRNO;
+ }
+
+ return Z_OK;
}