"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "odt2txt-0.4/kunzip/zipfile.c" of archive odt2txt-0.4.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <utime.h>
7 #include <time.h>
8 #include <unistd.h>
9
10 #include "fileio.h"
11 #include "zipfile.h"
12 #include "kunzip.h"
13 #include "../strbuf.h"
14 #include "../mem.h"
15
16 /*
17
18 This code is Copyright 2005-2006 by Michael Kohn
19
20 This program is free software; you can redistribute it and/or
21 modify it under the terms of the GNU General Public License,
22 version 2 as published by the Free Software Foundation
23
24 */
25
26 #define BUFFER_SIZE 16738
27
28 /* #define _GNU_SOURCE */
29
30 unsigned int copy_file_tobuf(FILE *in, STRBUF *out, int len)
31 {
32 unsigned char buffer[BUFFER_SIZE];
33 uLong checksum;
34 int t, r;
35
36 checksum = crc32(0L, Z_NULL, 0);
37
38 t = 0;
39
40 while (t < len) {
41 if (t + BUFFER_SIZE < len) {
42 r = BUFFER_SIZE;
43 } else {
44 r = len - t;
45 }
46
47 read_buffer(in, buffer, r);
48 strbuf_append_n(out, (char *)buffer, r);
49 checksum = crc32(checksum, buffer, r);
50 t = t + r;
51 }
52
53 return checksum;
54 }
55
56 int read_zip_header(FILE *in,
57 struct zip_local_file_header_t *local_file_header)
58 {
59 local_file_header->signature = read_int(in);
60 if (local_file_header->signature != 0x04034b50)
61 return -1;
62
63 local_file_header->version = read_word(in);
64 local_file_header->general_purpose_bit_flag = read_word(in);
65 local_file_header->compression_method = read_word(in);
66 local_file_header->last_mod_file_time = read_word(in);
67 local_file_header->last_mod_file_date = read_word(in);
68 local_file_header->crc_32 = read_int(in);
69 local_file_header->compressed_size = read_int(in);
70 local_file_header->uncompressed_size = read_int(in);
71 local_file_header->file_name_length = read_word(in);
72 local_file_header->extra_field_length = read_word(in);
73 local_file_header->descriptor_length = 0;
74
75 /* if the 4th bit in the general_purpose_bit_flag is set,
76 crc32, compressed_size and uncompressed_size are written
77 into a data descriptor that follows the compressed
78 data */
79 if (local_file_header->general_purpose_bit_flag & 8) {
80 long data_start = ftell(in);
81 unsigned int signature;
82
83 while (1) {
84 signature = read_int(in);
85
86 if (feof(in)) {
87 fseek(in, data_start, SEEK_SET);
88 return -1;
89 }
90
91 if (signature == 0x08074b50) {
92 local_file_header->crc_32 = read_int(in);
93 local_file_header->compressed_size =
94 read_int(in);
95 local_file_header->uncompressed_size =
96 read_int(in);
97 local_file_header->descriptor_length = 16;
98 fseek(in, data_start, SEEK_SET);
99 return 0;
100 }
101
102 fseek(in, -3, SEEK_CUR);
103 }
104
105 }
106 return 0;
107 }
108
109 #ifdef DEBUG
110 int print_zip_header(struct zip_local_file_header_t *local_file_header)
111 {
112 printf("ZIP LOCAL FILE HEADER\n");
113 printf("----------------------------------\n");
114 printf("Signature: %02x%02x%02x%02x\n",
115 ((local_file_header->signature >> 24) & 255),
116 ((local_file_header->signature >> 16) & 255),
117 ((local_file_header->signature >> 8) & 255),
118 (local_file_header->signature & 255));
119 printf("Version: %d\n", local_file_header->version);
120 printf("General Purpose Bit Flag: %d\n",
121 local_file_header->general_purpose_bit_flag);
122 printf("Compression Method: %d\n",
123 local_file_header->compression_method);
124 printf("Last Mod File Time: %d\n",
125 local_file_header->last_mod_file_time);
126 printf("Last Mod File Date: %d\n",
127 local_file_header->last_mod_file_date);
128 printf("CRC-32: %d\n", local_file_header->crc_32);
129 printf("Compressed Size: %d\n", local_file_header->compressed_size);
130 printf("Uncompressed Size: %d\n", local_file_header->uncompressed_size);
131 printf("File Name Length: %d\n", local_file_header->file_name_length);
132 printf("Extra Field Length: %d\n",
133 local_file_header->extra_field_length);
134 printf("File Name: %s\n", local_file_header->file_name);
135
136 return 0;
137 }
138 #endif
139
140 STRBUF *kunzip_file_tobuf(FILE *in)
141 {
142 STRBUF *out;
143 struct zip_local_file_header_t local_file_header;
144 int ret_code;
145 int checksum;
146 long marker;
147
148 ret_code = 0;
149
150 if (read_zip_header(in, &local_file_header) == -1)
151 return NULL;
152
153 local_file_header.file_name =
154 (char *)ymalloc(local_file_header.file_name_length + 1);
155 local_file_header.extra_field =
156 (unsigned char *)ymalloc(local_file_header.extra_field_length + 1);
157
158 read_chars(in, local_file_header.file_name,
159 local_file_header.file_name_length);
160 read_chars(in, (char *)local_file_header.extra_field,
161 local_file_header.extra_field_length);
162
163 marker = ftell(in);
164
165 #ifdef DEBUG
166 print_zip_header(&local_file_header);
167 #endif
168
169 out = strbuf_new();
170
171 if (local_file_header.compression_method == 0) {
172 checksum =
173 copy_file_tobuf(in, out,
174 local_file_header.uncompressed_size);
175 } else if (local_file_header.compression_method == Z_DEFLATED) {
176 (void)strbuf_append_inflate(out, in);
177 checksum = strbuf_crc32(out);
178 } else {
179 fprintf(stderr, "Unknown compression method\n");
180 exit(EXIT_FAILURE);
181 }
182
183 if ((unsigned int)checksum != local_file_header.crc_32
184 && local_file_header.crc_32 != 0) {
185 fprintf(stderr,
186 "Warning: Checksum does not match: %d %d.\nPossibly the file"
187 " is corrupted otr truncated.\n", checksum,
188 local_file_header.crc_32);
189 ret_code = -4;
190 }
191
192 yfree(local_file_header.file_name);
193 yfree(local_file_header.extra_field);
194
195 fseek(in, marker + local_file_header.compressed_size, SEEK_SET);
196
197 if ((local_file_header.general_purpose_bit_flag & 8) != 0) {
198 read_int(in);
199 read_int(in);
200 read_int(in);
201 }
202
203 return out;
204 }
205
206 STRBUF *kunzip_next_tobuf(char *zip_filename, int offset)
207 {
208 FILE *in;
209 STRBUF *buf;
210 long marker;
211
212 in = fopen(zip_filename, "rb");
213 if (in == 0) {
214 return NULL;
215 }
216
217 fseek(in, offset, SEEK_SET);
218
219 buf = kunzip_file_tobuf(in);
220 marker = ftell(in);
221 fclose(in);
222
223 return buf;
224 }
225
226 /*
227 Match Flags:
228 bit 0: set to 1 if it should be exact filename match
229 set to 0 if the archived filename only needs to contain that word
230 bit 1: set to 1 if it should be case sensitive
231 set to 0 if it should be case insensitive
232 */
233
234 int kunzip_get_offset_by_name(char *zip_filename, char *compressed_filename,
235 int match_flags, int skip_offset)
236 {
237 FILE *in;
238 struct zip_local_file_header_t local_file_header;
239 int i = 0, curr;
240 char *name = 0;
241 int name_size = 0;
242 long marker;
243
244 in = fopen(zip_filename, "rb");
245 if (in == 0) {
246 return -1;
247 }
248
249 if (skip_offset != -1) {
250 fseek(in, skip_offset, SEEK_SET);
251 }
252
253 while (1) {
254 curr = ftell(in);
255 i = read_zip_header(in, &local_file_header);
256 if (i == -1)
257 break;
258
259 if (skip_offset < 0 || curr > skip_offset) {
260 marker = ftell(in); /* nasty code.. please make it nice later */
261
262 if (name_size < local_file_header.file_name_length + 1) {
263 if (name_size != 0)
264 yfree(name);
265 name_size =
266 local_file_header.file_name_length + 1;
267 name = ymalloc(name_size);
268 }
269
270 read_chars(in, name,
271 local_file_header.file_name_length);
272 name[local_file_header.file_name_length] = 0;
273
274 fseek(in, marker, SEEK_SET); /* and part 2 of nasty code */
275
276 if ((match_flags & 1) == 1) {
277 if (strcmp(compressed_filename, name) == 0)
278 break;
279 } else {
280 if (strstr(name, compressed_filename) != 0)
281 break;
282 }
283 }
284
285 fseek(in, local_file_header.compressed_size +
286 local_file_header.file_name_length +
287 local_file_header.extra_field_length +
288 local_file_header.descriptor_length, SEEK_CUR);
289
290 }
291
292 if (name_size != 0)
293 yfree(name);
294
295 fclose(in);
296
297 if (i != -1) {
298 return curr;
299 } else {
300 return -1;
301 }
302 }