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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki