/[zanavi_public1]/navit/navit/maptool/zip.c
ZANavi

Contents of /navit/navit/maptool/zip.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (show annotations) (download)
Fri Oct 28 21:39:42 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 9438 byte(s)
import
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <zlib.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include "maptool.h"
24 #include "zipfile.h"
25
26 #ifdef HAVE_LIBCRYPTO
27 #include <openssl/sha.h>
28 #include <openssl/hmac.h>
29 #include <openssl/aes.h>
30 #include <openssl/evp.h>
31 #include <openssl/rand.h>
32 #include <openssl/md5.h>
33 #endif
34
35 struct zip_info {
36 int zipnum;
37 int dir_size;
38 long long offset;
39 int compression_level;
40 int maxnamelen;
41 int zip64;
42 short date;
43 short time;
44 char *passwd;
45 FILE *res2;
46 FILE *index;
47 FILE *dir;
48 #ifdef HAVE_LIBCRYPTO
49 MD5_CTX md5_ctx;
50 #endif
51 int md5;
52 };
53
54 static int
55 zip_write(struct zip_info *info, void *data, int len)
56 {
57 if (fwrite(data, len, 1, info->res2) != 1)
58 return 0;
59 #ifdef HAVE_LIBCRYPTO
60 if (info->md5)
61 MD5_Update(&info->md5_ctx, data, len);
62 #endif
63 return 1;
64 }
65
66 #ifdef HAVE_ZLIB
67 static int
68 compress2_int(Byte *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
69 {
70 z_stream stream;
71 int err;
72
73 stream.next_in = (Bytef*)source;
74 stream.avail_in = (uInt)sourceLen;
75 stream.next_out = dest;
76 stream.avail_out = (uInt)*destLen;
77 if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
78
79 stream.zalloc = (alloc_func)0;
80 stream.zfree = (free_func)0;
81 stream.opaque = (voidpf)0;
82
83 err = deflateInit2(&stream, level, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);
84 if (err != Z_OK) return err;
85
86 err = deflate(&stream, Z_FINISH);
87 if (err != Z_STREAM_END) {
88 deflateEnd(&stream);
89 return err == Z_OK ? Z_BUF_ERROR : err;
90 }
91 *destLen = stream.total_out;
92
93 err = deflateEnd(&stream);
94 return err;
95 }
96 #endif
97
98 void
99 write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, int data_size)
100 {
101 struct zip_lfh lfh = {
102 0x04034b50,
103 0x0a,
104 0x0,
105 0x0,
106 zip_info->time,
107 zip_info->date,
108 0x0,
109 0x0,
110 0x0,
111 filelen,
112 0x0,
113 };
114 struct zip_cd cd = {
115 0x02014b50,
116 0x17,
117 0x00,
118 0x0a,
119 0x00,
120 0x0000,
121 0x0,
122 zip_info->time,
123 zip_info->date,
124 0x0,
125 0x0,
126 0x0,
127 filelen,
128 0x0000,
129 0x0000,
130 0x0000,
131 0x0000,
132 0x0,
133 zip_info->offset,
134 };
135 struct zip_cd_ext cd_ext = {
136 0x1,
137 0x8,
138 zip_info->offset,
139 };
140 #ifdef HAVE_LIBCRYPTO
141 struct zip_enc enc = {
142 0x9901,
143 0x7,
144 0x2,
145 'A','E',
146 0x1,
147 0x0,
148 };
149 unsigned char salt[8], key[34], verify[2], mac[10];
150 #endif
151 char filename[filelen+1];
152 int error,crc=0,len,comp_size=data_size;
153 uLongf destlen=data_size+data_size/500+12;
154 char *compbuffer;
155
156 compbuffer = malloc(destlen);
157 if (!compbuffer) {
158 fprintf(stderr, "No more memory.\n");
159 exit (1);
160 }
161 #ifdef HAVE_LIBCRYPTO
162 if (zip_info->passwd) {
163 RAND_bytes(salt, sizeof(salt));
164 PKCS5_PBKDF2_HMAC_SHA1(zip_info->passwd, strlen(zip_info->passwd), salt, sizeof(salt), 1000, sizeof(key), key);
165 verify[0]=key[32];
166 verify[1]=key[33];
167 } else {
168 #endif
169 crc=crc32(0, NULL, 0);
170 crc=crc32(crc, (unsigned char *)data, data_size);
171 #ifdef HAVE_LIBCRYPTO
172 }
173 #endif
174 lfh.zipmthd=zip_info->compression_level ? 8:0;
175 #ifdef HAVE_ZLIB
176 if (zip_info->compression_level) {
177 error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level);
178 if (error == Z_OK) {
179 if (destlen < data_size) {
180 data=compbuffer;
181 comp_size=destlen;
182 } else
183 lfh.zipmthd=0;
184 } else {
185 fprintf(stderr,"compress2 returned %d\n", error);
186 }
187 }
188 #endif
189 lfh.zipcrc=crc;
190 lfh.zipsize=comp_size;
191 lfh.zipuncmp=data_size;
192 #ifdef HAVE_LIBCRYPTO
193 if (zip_info->passwd) {
194 enc.compress_method=lfh.zipmthd;
195 lfh.zipmthd=99;
196 lfh.zipxtraln+=sizeof(enc);
197 lfh.zipgenfld|=1;
198 lfh.zipsize+=sizeof(salt)+sizeof(verify)+sizeof(mac);
199 }
200 #endif
201 cd.zipccrc=crc;
202 cd.zipcsiz=lfh.zipsize;
203 cd.zipcunc=data_size;
204 cd.zipcmthd=lfh.zipmthd;
205 if (zip_info->zip64) {
206 cd.zipofst=0xffffffff;
207 cd.zipcxtl+=sizeof(cd_ext);
208 }
209 #ifdef HAVE_LIBCRYPTO
210 if (zip_info->passwd) {
211 cd.zipcmthd=99;
212 cd.zipcxtl+=sizeof(enc);
213 cd.zipcflg|=1;
214 }
215 #endif
216 strcpy(filename, name);
217 len=strlen(filename);
218 while (len < filelen) {
219 filename[len++]='_';
220 }
221 filename[filelen]='\0';
222 zip_write(zip_info, &lfh, sizeof(lfh));
223 zip_write(zip_info, filename, filelen);
224 zip_info->offset+=sizeof(lfh)+filelen;
225 #ifdef HAVE_LIBCRYPTO
226 if (zip_info->passwd) {
227 unsigned char counter[16], xor[16], *datap=(unsigned char *)data;
228 int size=comp_size;
229 AES_KEY aeskey;
230 zip_write(zip_info, &enc, sizeof(enc));
231 zip_write(zip_info, salt, sizeof(salt));
232 zip_write(zip_info, verify, sizeof(verify));
233 zip_info->offset+=sizeof(enc)+sizeof(salt)+sizeof(verify);
234 AES_set_encrypt_key(key, 128, &aeskey);
235 memset(counter, 0, sizeof(counter));
236 while (size > 0) {
237 int i,curr_size,idx=0;
238 do {
239 counter[idx]++;
240 } while (!counter[idx++]);
241 AES_encrypt(counter, xor, &aeskey);
242 curr_size=size;
243 if (curr_size > sizeof(xor))
244 curr_size=sizeof(xor);
245 for (i = 0 ; i < curr_size ; i++)
246 *datap++^=xor[i];
247 size-=curr_size;
248 }
249 }
250 #endif
251 zip_write(zip_info, data, comp_size);
252 zip_info->offset+=comp_size;
253 #ifdef HAVE_LIBCRYPTO
254 if (zip_info->passwd) {
255 unsigned int maclen=sizeof(mac);
256 unsigned char mactmp[maclen*2];
257 HMAC(EVP_sha1(), key+16, 16, (unsigned char *)data, comp_size, mactmp, &maclen);
258 zip_write(zip_info, mactmp, sizeof(mac));
259 zip_info->offset+=sizeof(mac);
260 }
261 #endif
262 fwrite(&cd, sizeof(cd), 1, zip_info->dir);
263 fwrite(filename, filelen, 1, zip_info->dir);
264 zip_info->dir_size+=sizeof(cd)+filelen;
265 if (zip_info->zip64) {
266 fwrite(&cd_ext, sizeof(cd_ext), 1, zip_info->dir);
267 zip_info->dir_size+=sizeof(cd_ext);
268 }
269 #ifdef HAVE_LIBCRYPTO
270 if (zip_info->passwd) {
271 fwrite(&enc, sizeof(enc), 1, zip_info->dir);
272 zip_info->dir_size+=sizeof(enc);
273 }
274 #endif
275
276 free(compbuffer);
277 }
278
279 void
280 zip_write_index(struct zip_info *info)
281 {
282 int size=ftell(info->index);
283 char buffer[size];
284
285 fseek(info->index, 0, SEEK_SET);
286 fread(buffer, size, 1, info->index);
287 write_zipmember(info, "index", strlen("index"), buffer, size);
288 info->zipnum++;
289 }
290
291 static void
292 zip_write_file_data(struct zip_info *info, FILE *in)
293 {
294 size_t size;
295 char buffer[4096];
296 while ((size=fread(buffer, 1, 4096, in)))
297 zip_write(info, buffer, size);
298 }
299
300 int
301 zip_write_directory(struct zip_info *info)
302 {
303 struct zip_eoc eoc = {
304 0x06054b50,
305 0x0000,
306 0x0000,
307 0x0000,
308 0x0000,
309 0x0,
310 0x0,
311 0x0,
312 };
313 struct zip64_eoc eoc64 = {
314 0x06064b50,
315 0x0,
316 0x0,
317 0x0403,
318 0x0,
319 0x0,
320 0x0,
321 0x0,
322 0x0,
323 0x0,
324 };
325 struct zip64_eocl eocl = {
326 0x07064b50,
327 0x0,
328 0x0,
329 0x0,
330 };
331
332 fseek(info->dir, 0, SEEK_SET);
333 zip_write_file_data(info, info->dir);
334 if (info->zip64) {
335 eoc64.zip64esize=sizeof(eoc64)-12;
336 eoc64.zip64enum=info->zipnum;
337 eoc64.zip64ecenn=info->zipnum;
338 eoc64.zip64ecsz=info->dir_size;
339 eoc64.zip64eofst=info->offset;
340 zip_write(info, &eoc64, sizeof(eoc64));
341 eocl.zip64lofst=info->offset+info->dir_size;
342 zip_write(info, &eocl, sizeof(eocl));
343 }
344 eoc.zipenum=info->zipnum;
345 eoc.zipecenn=info->zipnum;
346 eoc.zipecsz=info->dir_size;
347 eoc.zipeofst=info->offset;
348 zip_write(info, &eoc, sizeof(eoc));
349 sig_alrm(0);
350 #ifndef _WIN32
351 alarm(0);
352 #endif
353 return 0;
354 }
355
356 struct zip_info *
357 zip_new(void)
358 {
359 return g_new0(struct zip_info, 1);
360 }
361
362 void
363 zip_set_md5(struct zip_info *info, int on)
364 {
365 #ifdef HAVE_LIBCRYPTO
366 info->md5=on;
367 if (on)
368 MD5_Init(&info->md5_ctx);
369 #endif
370 }
371
372 int
373 zip_get_md5(struct zip_info *info, unsigned char *out)
374 {
375 if (!info->md5)
376 return 0;
377 #ifdef HAVE_LIBCRYPTO
378 MD5_Final(out, &info->md5_ctx);
379 return 1;
380 #endif
381 return 0;
382 }
383
384 void
385 zip_set_zip64(struct zip_info *info, int on)
386 {
387 info->zip64=on;
388 }
389
390 void
391 zip_set_compression_level(struct zip_info *info, int level)
392 {
393 info->compression_level=level;
394 }
395
396 void
397 zip_set_maxnamelen(struct zip_info *info, int max)
398 {
399 info->maxnamelen=max;
400 }
401
402 int
403 zip_get_maxnamelen(struct zip_info *info)
404 {
405 return info->maxnamelen;
406 }
407
408 int
409 zip_add_member(struct zip_info *info)
410 {
411 return info->zipnum++;
412 }
413
414
415 int
416 zip_set_timestamp(struct zip_info *info, char *timestamp)
417 {
418 int year,month,day,hour,min,sec;
419
420 if (sscanf(timestamp,"%d-%d-%dT%d:%d:%d",&year,&month,&day,&hour,&min,&sec) == 6) {
421 info->date=day | (month << 5) | ((year-1980) << 9);
422 info->time=(sec >> 1) | (min << 5) | (hour << 11);
423 return 1;
424 }
425 return 0;
426 }
427
428 int
429 zip_set_password(struct zip_info *info, char *passwd)
430 {
431 info->passwd=passwd;
432 return 1;
433 }
434
435
436 void
437 zip_open(struct zip_info *info, char *out, char *dir, char *index)
438 {
439 info->res2=fopen(out,"wb+");
440 info->dir=fopen(dir,"wb+");
441 info->index=fopen(index,"wb+");
442 }
443
444 FILE *
445 zip_get_index(struct zip_info *info)
446 {
447 return info->index;
448 }
449
450 int
451 zip_get_zipnum(struct zip_info *info)
452 {
453 return info->zipnum;
454 }
455
456 void
457 zip_set_zipnum(struct zip_info *info, int num)
458 {
459 info->zipnum=num;
460 }
461
462 void
463 zip_close(struct zip_info *info)
464 {
465 fclose(info->index);
466 fclose(info->dir);
467 fclose(info->res2);
468 }
469
470 void
471 zip_destroy(struct zip_info *info)
472 {
473 g_free(info);
474 }

   
Visit the ZANavi Wiki