junzip: style and migrate header into private-libwebsockets.h
authorAndy Green <andy@warmcat.com>
Fri, 3 Mar 2017 01:19:14 +0000 (09:19 +0800)
committerAndy Green <andy@warmcat.com>
Fri, 3 Mar 2017 01:19:14 +0000 (09:19 +0800)
Also introduce CMake LWS_WITH_ZIP_FOPS defaulting to ON that builds junzip.c and
make sure this is exported in lws_config.h (included by libwebsockets.h)

Improve lws handling of stdint.h import or simulate it.

CMakeLists.txt
lib/junzip.c
lib/junzip.h [deleted file]
lib/libwebsockets.h
lib/private-libwebsockets.h
lws_config.h.in

index 95f473e..6429374 100644 (file)
@@ -114,6 +114,7 @@ option(LWS_WITH_NO_LOGS "Disable all logging from being compiled in" OFF)
 option(LWS_STATIC_PIC "Build the static version of the library with position-independent code" OFF)
 option(LWS_WITH_RANGES "Support http ranges (RFC7233)" ON)
 option(LWS_FALLBACK_GETHOSTBYNAME "Also try to do dns resolution using gethostbyname if getaddrinfo fails" OFF)
+option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" ON)
 
 if (LWS_WITH_LWSWS)
  message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
@@ -652,6 +653,11 @@ if (LWS_WITH_RANGES)
                lib/ranges.c)
 endif()
 
+if (LWS_WITH_ZIP_FOPS)
+       list(APPEND SOURCES
+               lib/junzip.c)
+endif()
+
 # Add helper files for Windows.
 if (WIN32)
        set(WIN32_HELPERS_PATH win32port/win32helpers)
@@ -1670,6 +1676,7 @@ message(" LWS_STATIC_PIC = ${LWS_STATIC_PIC}")
 message(" LWS_WITH_RANGES = ${LWS_WITH_RANGES}")
 message(" LWS_PLAT_OPTEE = ${LWS_PLAT_OPTEE}")
 message(" LWS_WITH_ESP32 = ${LWS_WITH_ESP32}")
+message(" LWS_WITH_ZIP_FOPS = ${LWS_WITH_ZIP_FOPS}")
 
 message("---------------------------------------------------------------------")
 
index d50489f..b20d534 100644 (file)
 
 #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;
 }
diff --git a/lib/junzip.h b/lib/junzip.h
deleted file mode 100644 (file)
index 145a70d..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Unzip library by Per Bothner.
- * Loosely based on Joonas Pihlajamaa's JUnzip.
- * Released into public domain. https://github.com/jokkebk/JUnzip
- */
-
-#ifndef __JUNZIP_H
-#define __JUNZIP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include <stdint.h>
-
-// If you don't have stdint.h, the following two lines should work for most 32/64 bit systems
-// typedef unsigned int uint32_t;
-// typedef unsigned short uint16_t;
-
-typedef struct JZFile JZFile;
-
-struct JZFile {
-    unsigned char *start;
-    off_t length;
-    long position;
-    int numEntries;
-    uint32_t centralDirectoryOffset;
-};
-
-#define zf_tell(ZF) ((ZF)->position)
-#define zf_available(ZF) ((ZF)->length - (ZF)->position)
-#define zf_current(ZF) ((ZF)->start + (ZF)->position)
-
-#define ZIP_LOCAL_FILE_HEADER_LENGTH 30
-
-typedef struct {
-    uint16_t compressionMethod;
-    uint32_t crc32;
-    uint32_t compressedSize;
-    uint32_t uncompressedSize;
-    long fileNameStart;
-    uint16_t fileNameLength;
-    uint16_t extraFieldLength; // unsupported
-    uint32_t offset;
-} JZFileHeader;
-
-// Callback prototype for central and local file record reading functions
-typedef int (*JZRecordCallback)(JZFile *zip, int index, JZFileHeader *header);
-
-// Read ZIP file end record. Will move within file.
-int jzReadEndRecord(JZFile *zip);
-
-// Read ZIP file global directory. Will move within file.
-// Callback is called for each record, until callback returns zero
-int jzReadCentralDirectory(JZFile *zip, JZRecordCallback callback);
-
-  // See to the start of the actual data of the given entry.
-int jzSeekData(JZFile *zip, JZFileHeader *header);
-
-// Read data from file stream, described by header, to preallocated buffer
-// Return value is zlib coded, e.g. Z_OK, or error code
-int jzReadData(JZFile *zip, JZFileHeader *header, void *buffer);
-
-#ifdef __cplusplus
-};
-#endif /* __cplusplus */
-
-#endif
index c5244ad..bf7cc64 100644 (file)
@@ -4296,10 +4296,23 @@ struct lws_fop_fd {
 #if !defined(ssize_t)
 typedef SSIZE_T ssize_t;
 #endif
+#endif
+
+#if defined(LWS_HAVE_STDINT_H)
+#include <stdint.h>
+#else
+#if defined(WIN32) || defined(_WIN32)
 /* !!! >:-[  */
 typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
 typedef unsigned __int8 uint8_t;
+#else
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+#endif
 #endif
+
 typedef struct lws_fop_fd *lws_fop_fd_t;
 typedef size_t lws_filepos_t;
 typedef ssize_t lws_fileofs_t;
index e8fbd2f..3431c97 100644 (file)
@@ -439,6 +439,57 @@ extern "C" {
 #define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
 #endif
 
+/**
+ * Unzip library by Per Bothner.
+ * Loosely based on Joonas Pihlajamaa's JUnzip.
+ * Released into public domain. https://github.com/jokkebk/JUnzip
+ * ------->
+ */
+
+typedef struct jzfile {
+    unsigned char *start;
+    off_t length;
+    long position;
+    int numEntries;
+    uint32_t centralDirectoryOffset;
+} jzfile_t;
+
+#define zf_tell(ZF) ((ZF)->position)
+#define zf_available(ZF) ((ZF)->length - (ZF)->position)
+#define zf_current(ZF) ((ZF)->start + (ZF)->position)
+
+#define ZIP_LOCAL_FILE_HEADER_LENGTH 30
+
+typedef struct {
+    uint16_t compressionMethod;
+    uint32_t crc32;
+    uint32_t compressedSize;
+    uint32_t uncompressedSize;
+    long fileNameStart;
+    uint16_t fileNameLength;
+    uint16_t extraFieldLength; // unsupported
+    uint32_t offset;
+} jzfile_hdr_t;
+
+// Callback prototype for central and local file record reading functions
+typedef int (*jzcb_t)(jzfile_t *zip, int index, jzfile_hdr_t *header);
+
+// Read ZIP file end record. Will move within file.
+int jzReadEndRecord(jzfile_t *zip);
+
+// Read ZIP file global directory. Will move within file.
+// Callback is called for each record, until callback returns zero
+int jzReadCentralDirectory(jzfile_t *zip, jzcb_t callback);
+
+  // See to the start of the actual data of the given entry.
+int jzSeekData(jzfile_t *zip, jzfile_hdr_t *header);
+
+// Read data from file stream, described by header, to preallocated buffer
+// Return value is zlib coded, e.g. Z_OK, or error code
+int jzReadData(jzfile_t *zip, jzfile_hdr_t *header, void *buffer);
+
+/* <------ */
+
 enum lws_websocket_opcodes_07 {
        LWSWSOPC_CONTINUATION = 0,
        LWSWSOPC_TEXT_FRAME = 1,
index 2bb1a50..b51c21c 100644 (file)
 /* OPTEE */
 #cmakedefine LWS_PLAT_OPTEE
 
+/* ZIP FOPS */
+#cmakedefine LWS_WITH_ZIP_FOPS
+#cmakedefine LWS_HAVE_STDINT_H
+
 #cmakedefine LWS_FALLBACK_GETHOSTBYNAME
 ${LWS_SIZEOFPTR_CODE}