• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <zipfile/zipfile.h>
2 
3 #include "private.h"
4 #include <stdlib.h>
5 #include <string.h>
6 #include <zlib.h>
7 #define DEF_MEM_LEVEL 8                // normally in zutil.h?
8 
9 zipfile_t
init_zipfile(const void * data,size_t size)10 init_zipfile(const void* data, size_t size)
11 {
12     int err;
13 
14     Zipfile *file = malloc(sizeof(Zipfile));
15     if (file == NULL) return NULL;
16     memset(file, 0, sizeof(Zipfile));
17     file->buf = data;
18     file->bufsize = size;
19 
20     err = read_central_dir(file);
21     if (err != 0) goto fail;
22 
23     return file;
24 fail:
25     free(file);
26     return NULL;
27 }
28 
29 void
release_zipfile(zipfile_t f)30 release_zipfile(zipfile_t f)
31 {
32     Zipfile* file = (Zipfile*)f;
33     Zipentry* entry = file->entries;
34     while (entry) {
35         Zipentry* next = entry->next;
36         free(entry);
37         entry = next;
38     }
39     free(file);
40 }
41 
42 zipentry_t
lookup_zipentry(zipfile_t f,const char * entryName)43 lookup_zipentry(zipfile_t f, const char* entryName)
44 {
45     Zipfile* file = (Zipfile*)f;
46     Zipentry* entry = file->entries;
47     while (entry) {
48         if (0 == memcmp(entryName, entry->fileName, entry->fileNameLength)) {
49             return entry;
50         }
51         entry = entry->next;
52     }
53     return NULL;
54 }
55 
56 size_t
get_zipentry_size(zipentry_t entry)57 get_zipentry_size(zipentry_t entry)
58 {
59     return ((Zipentry*)entry)->uncompressedSize;
60 }
61 
62 char*
get_zipentry_name(zipentry_t entry)63 get_zipentry_name(zipentry_t entry)
64 {
65     Zipentry* e = (Zipentry*)entry;
66     int l = e->fileNameLength;
67     char* s = malloc(l+1);
68     memcpy(s, e->fileName, l);
69     s[l] = '\0';
70     return s;
71 }
72 
73 enum {
74     STORED = 0,
75     DEFLATED = 8
76 };
77 
78 static int
uninflate(unsigned char * out,int unlen,const unsigned char * in,int clen)79 uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen)
80 {
81     z_stream zstream;
82     int err = 0;
83     int zerr;
84 
85     memset(&zstream, 0, sizeof(zstream));
86     zstream.zalloc = Z_NULL;
87     zstream.zfree = Z_NULL;
88     zstream.opaque = Z_NULL;
89     zstream.next_in = (void*)in;
90     zstream.avail_in = clen;
91     zstream.next_out = (Bytef*) out;
92     zstream.avail_out = unlen;
93     zstream.data_type = Z_UNKNOWN;
94 
95     // Use the undocumented "negative window bits" feature to tell zlib
96     // that there's no zlib header waiting for it.
97     zerr = inflateInit2(&zstream, -MAX_WBITS);
98     if (zerr != Z_OK) {
99         return -1;
100     }
101 
102     // uncompress the data
103     zerr = inflate(&zstream, Z_FINISH);
104     if (zerr != Z_STREAM_END) {
105         fprintf(stderr, "zerr=%d Z_STREAM_END=%d total_out=%lu\n", zerr, Z_STREAM_END,
106                     zstream.total_out);
107         err = -1;
108     }
109 
110      inflateEnd(&zstream);
111     return err;
112 }
113 
114 int
decompress_zipentry(zipentry_t e,void * buf,int bufsize)115 decompress_zipentry(zipentry_t e, void* buf, int bufsize)
116 {
117     Zipentry* entry = (Zipentry*)e;
118     switch (entry->compressionMethod)
119     {
120         case STORED:
121             memcpy(buf, entry->data, entry->uncompressedSize);
122             return 0;
123         case DEFLATED:
124             return uninflate(buf, bufsize, entry->data, entry->compressedSize);
125         default:
126             return -1;
127     }
128 }
129 
130 void
dump_zipfile(FILE * to,zipfile_t file)131 dump_zipfile(FILE* to, zipfile_t file)
132 {
133     Zipfile* zip = (Zipfile*)file;
134     Zipentry* entry = zip->entries;
135     int i;
136 
137     fprintf(to, "entryCount=%d\n", zip->entryCount);
138     for (i=0; i<zip->entryCount; i++) {
139         fprintf(to, "  file \"");
140         fwrite(entry->fileName, entry->fileNameLength, 1, to);
141         fprintf(to, "\"\n");
142         entry = entry->next;
143     }
144 }
145 
146 zipentry_t
iterate_zipfile(zipfile_t file,void ** cookie)147 iterate_zipfile(zipfile_t file, void** cookie)
148 {
149     Zipentry* entry = (Zipentry*)*cookie;
150     if (entry == NULL) {
151         Zipfile* zip = (Zipfile*)file;
152         *cookie = zip->entries;
153         return *cookie;
154     } else {
155         entry = entry->next;
156         *cookie = entry;
157         return entry;
158     }
159 }
160