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 unsigned long crc;
83 int err = 0;
84 int zerr;
85
86 memset(&zstream, 0, sizeof(zstream));
87 zstream.zalloc = Z_NULL;
88 zstream.zfree = Z_NULL;
89 zstream.opaque = Z_NULL;
90 zstream.next_in = (void*)in;
91 zstream.avail_in = unlen;
92 zstream.next_out = (Bytef*) out;
93 zstream.avail_out = unlen;
94 zstream.data_type = Z_UNKNOWN;
95
96 // Use the undocumented "negative window bits" feature to tell zlib
97 // that there's no zlib header waiting for it.
98 zerr = inflateInit2(&zstream, -MAX_WBITS);
99 if (zerr != Z_OK) {
100 return -1;
101 }
102
103 // uncompress the data
104 zerr = inflate(&zstream, Z_FINISH);
105 if (zerr != Z_STREAM_END) {
106 fprintf(stderr, "zerr=%d Z_STREAM_END=%d total_out=%lu\n", zerr, Z_STREAM_END,
107 zstream.total_out);
108 err = -1;
109 }
110
111 inflateEnd(&zstream);
112 return err;
113 }
114
115 int
decompress_zipentry(zipentry_t e,void * buf,int bufsize)116 decompress_zipentry(zipentry_t e, void* buf, int bufsize)
117 {
118 Zipentry* entry = (Zipentry*)e;
119 switch (entry->compressionMethod)
120 {
121 case STORED:
122 memcpy(buf, entry->data, entry->uncompressedSize);
123 return 0;
124 case DEFLATED:
125 return uninflate(buf, bufsize, entry->data, entry->compressedSize);
126 default:
127 return -1;
128 }
129 }
130
131 void
dump_zipfile(FILE * to,zipfile_t file)132 dump_zipfile(FILE* to, zipfile_t file)
133 {
134 Zipfile* zip = (Zipfile*)file;
135 Zipentry* entry = zip->entries;
136 int i;
137
138 fprintf(to, "entryCount=%d\n", zip->entryCount);
139 for (i=0; i<zip->entryCount; i++) {
140 fprintf(to, " file \"");
141 fwrite(entry->fileName, entry->fileNameLength, 1, to);
142 fprintf(to, "\"\n");
143 entry = entry->next;
144 }
145 }
146
147 zipentry_t
iterate_zipfile(zipfile_t file,void ** cookie)148 iterate_zipfile(zipfile_t file, void** cookie)
149 {
150 Zipentry* entry = (Zipentry*)*cookie;
151 if (entry == NULL) {
152 Zipfile* zip = (Zipfile*)file;
153 *cookie = zip->entries;
154 return *cookie;
155 } else {
156 entry = entry->next;
157 *cookie = entry;
158 return entry;
159 }
160 }
161