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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 10284 byte(s)
new map version, lots of fixes and experimental new features
1 zoff99 8 /**
2 zoff99 31 * 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 zoff99 8 * 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 zoff99 31 struct zip_info
55     {
56 zoff99 8 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 zoff99 31 static int zip_write(struct zip_info *info, void *data, int len)
75 zoff99 8 {
76     if (fwrite(data, len, 1, info->res2) != 1)
77     return 0;
78     #ifdef HAVE_LIBCRYPTO
79 zoff99 31 if (info->md5)
80     MD5_Update(&info->md5_ctx, data, len);
81 zoff99 8 #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 zoff99 31 if (err != Z_STREAM_END)
107     {
108 zoff99 8 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 zoff99 31 void write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, int data_size)
119 zoff99 8 {
120 zoff99 31 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 zoff99 8 #ifdef HAVE_LIBCRYPTO
127 zoff99 31 struct zip_enc enc =
128     {
129 zoff99 8 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 zoff99 31 char filename[filelen + 1];
139     int error, crc = 0, len, comp_size = data_size;
140     uLongf destlen = data_size + data_size / 500 + 12;
141 zoff99 8 char *compbuffer;
142    
143     compbuffer = malloc(destlen);
144 zoff99 31 if (!compbuffer)
145     {
146     fprintf(stderr, "No more memory.\n");
147     exit(1);
148 zoff99 8 }
149     #ifdef HAVE_LIBCRYPTO
150 zoff99 31 if (zip_info->passwd)
151     {
152 zoff99 8 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 zoff99 31 }
157     else
158     {
159 zoff99 8 #endif
160 zoff99 31 crc = crc32(0, NULL, 0);
161     crc = crc32(crc, (unsigned char *) data, data_size);
162 zoff99 8 #ifdef HAVE_LIBCRYPTO
163 zoff99 31 }
164 zoff99 8 #endif
165 zoff99 31 lfh.zipmthd = zip_info->compression_level ? 8 : 0;
166 zoff99 8 #ifdef HAVE_ZLIB
167 zoff99 31 if (zip_info->compression_level)
168     {
169 zoff99 8 error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level);
170 zoff99 31 if (error == Z_OK)
171     {
172     if (destlen < data_size)
173     {
174 zoff99 8 data=compbuffer;
175     comp_size=destlen;
176 zoff99 31 }
177     else
178     lfh.zipmthd=0;
179     }
180     else
181     {
182 zoff99 8 fprintf(stderr,"compress2 returned %d\n", error);
183     }
184     }
185     #endif
186 zoff99 31 lfh.zipcrc = crc;
187     lfh.zipsize = comp_size;
188     lfh.zipuncmp = data_size;
189 zoff99 8 #ifdef HAVE_LIBCRYPTO
190 zoff99 31 if (zip_info->passwd)
191     {
192 zoff99 8 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 zoff99 31 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 zoff99 8 }
208     #ifdef HAVE_LIBCRYPTO
209 zoff99 31 if (zip_info->passwd)
210     {
211 zoff99 8 cd.zipcmthd=99;
212     cd.zipcxtl+=sizeof(enc);
213     cd.zipcflg|=1;
214     }
215     #endif
216     strcpy(filename, name);
217 zoff99 31 len = strlen(filename);
218     while (len < filelen)
219     {
220     filename[len++] = '_';
221 zoff99 8 }
222 zoff99 31 filename[filelen] = '\0';
223 zoff99 8 zip_write(zip_info, &lfh, sizeof(lfh));
224     zip_write(zip_info, filename, filelen);
225 zoff99 31 zip_info->offset += sizeof(lfh) + filelen;
226 zoff99 8 #ifdef HAVE_LIBCRYPTO
227 zoff99 31 if (zip_info->passwd)
228     {
229 zoff99 8 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 zoff99 31 while (size > 0)
239     {
240 zoff99 8 int i,curr_size,idx=0;
241 zoff99 31 do
242     {
243 zoff99 8 counter[idx]++;
244 zoff99 31 }while (!counter[idx++]);
245 zoff99 8 AES_encrypt(counter, xor, &aeskey);
246     curr_size=size;
247     if (curr_size > sizeof(xor))
248 zoff99 31 curr_size=sizeof(xor);
249     for (i = 0; i < curr_size; i++)
250     *datap++^=xor[i];
251 zoff99 8 size-=curr_size;
252     }
253     }
254     #endif
255     zip_write(zip_info, data, comp_size);
256 zoff99 31 zip_info->offset += comp_size;
257 zoff99 8 #ifdef HAVE_LIBCRYPTO
258 zoff99 31 if (zip_info->passwd)
259     {
260 zoff99 8 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 zoff99 31 zip_info->dir_size += sizeof(cd) + filelen;
270     if (zip_info->zip64)
271     {
272 zoff99 8 fwrite(&cd_ext, sizeof(cd_ext), 1, zip_info->dir);
273 zoff99 31 zip_info->dir_size += sizeof(cd_ext);
274 zoff99 8 }
275     #ifdef HAVE_LIBCRYPTO
276 zoff99 31 if (zip_info->passwd)
277     {
278 zoff99 8 fwrite(&enc, sizeof(enc), 1, zip_info->dir);
279     zip_info->dir_size+=sizeof(enc);
280     }
281     #endif
282 zoff99 31
283 zoff99 8 free(compbuffer);
284     }
285    
286 zoff99 31 void zip_write_index(struct zip_info *info)
287 zoff99 8 {
288 zoff99 31 int size = ftell(info->index);
289     char *buffer99 = NULL;
290     buffer99 = malloc(size);
291 zoff99 8 fseek(info->index, 0, SEEK_SET);
292 zoff99 31 fread(buffer99, size, 1, info->index);
293     write_zipmember(info, "index", strlen("index"), buffer99, size);
294 zoff99 8 info->zipnum++;
295 zoff99 31 free(buffer99);
296 zoff99 8 }
297    
298 zoff99 31 static void zip_write_file_data(struct zip_info *info, FILE *in)
299 zoff99 8 {
300     size_t size;
301     char buffer[4096];
302 zoff99 31 while ((size = fread(buffer, 1, 4096, in)))
303     {
304 zoff99 8 zip_write(info, buffer, size);
305 zoff99 31 }
306 zoff99 8 }
307    
308 zoff99 31 int zip_write_directory(struct zip_info *info)
309 zoff99 8 {
310 zoff99 31 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 zoff99 8
317     fseek(info->dir, 0, SEEK_SET);
318     zip_write_file_data(info, info->dir);
319 zoff99 31 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 zoff99 8 zip_write(info, &eoc64, sizeof(eoc64));
327 zoff99 31 eocl.zip64lofst = info->offset + info->dir_size;
328 zoff99 8 zip_write(info, &eocl, sizeof(eocl));
329     }
330 zoff99 31 eoc.zipenum = info->zipnum;
331     eoc.zipecenn = info->zipnum;
332     eoc.zipecsz = info->dir_size;
333     eoc.zipeofst = info->offset;
334 zoff99 8 zip_write(info, &eoc, sizeof(eoc));
335 zoff99 31 //sig_alrm(0);
336 zoff99 8 #ifndef _WIN32
337 zoff99 31 //alarm(0);
338 zoff99 8 #endif
339     return 0;
340     }
341    
342     struct zip_info *
343     zip_new(void)
344     {
345 zoff99 31 return g_new0(struct zip_info, 1);
346 zoff99 8 }
347    
348 zoff99 31 void zip_set_md5(struct zip_info *info, int on)
349 zoff99 8 {
350     #ifdef HAVE_LIBCRYPTO
351     info->md5=on;
352 zoff99 31 if (on)
353     MD5_Init(&info->md5_ctx);
354 zoff99 8 #endif
355     }
356    
357 zoff99 31 int zip_get_md5(struct zip_info *info, unsigned char *out)
358 zoff99 8 {
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 zoff99 31 void zip_set_zip64(struct zip_info *info, int on)
369 zoff99 8 {
370 zoff99 31 info->zip64 = on;
371 zoff99 8 }
372    
373 zoff99 31 void zip_set_compression_level(struct zip_info *info, int level)
374 zoff99 8 {
375 zoff99 31 info->compression_level = level;
376 zoff99 8 }
377    
378 zoff99 31 void zip_set_maxnamelen(struct zip_info *info, int max)
379 zoff99 8 {
380 zoff99 31 info->maxnamelen = max;
381 zoff99 8 }
382    
383 zoff99 31 int zip_get_maxnamelen(struct zip_info *info)
384 zoff99 8 {
385     return info->maxnamelen;
386     }
387    
388 zoff99 31 int zip_add_member(struct zip_info *info)
389 zoff99 8 {
390     return info->zipnum++;
391     }
392    
393 zoff99 31 int zip_set_timestamp(struct zip_info *info, char *timestamp)
394 zoff99 8 {
395 zoff99 31 int year, month, day, hour, min, sec;
396 zoff99 8
397 zoff99 31 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 zoff99 8 return 1;
402     }
403     return 0;
404     }
405    
406 zoff99 31 int zip_set_password(struct zip_info *info, char *passwd)
407 zoff99 8 {
408 zoff99 31 info->passwd = passwd;
409 zoff99 8 return 1;
410     }
411    
412 zoff99 31 void zip_open(struct zip_info *info, char *out, char *dir, char *index)
413 zoff99 8 {
414 zoff99 31 info->res2 = fopen(out, "wb+");
415     info->dir = fopen(dir, "wb+");
416     info->index = fopen(index, "wb+");
417 zoff99 8 }
418    
419     FILE *
420     zip_get_index(struct zip_info *info)
421     {
422     return info->index;
423     }
424    
425 zoff99 31 int zip_get_zipnum(struct zip_info *info)
426 zoff99 8 {
427     return info->zipnum;
428     }
429    
430 zoff99 31 void zip_set_zipnum(struct zip_info *info, int num)
431 zoff99 8 {
432 zoff99 31 info->zipnum = num;
433 zoff99 8 }
434    
435 zoff99 31 void zip_close(struct zip_info *info)
436 zoff99 8 {
437     fclose(info->index);
438     fclose(info->dir);
439     fclose(info->res2);
440     }
441    
442 zoff99 31 void zip_destroy(struct zip_info *info)
443 zoff99 8 {
444     g_free(info);
445     }

   
Visit the ZANavi Wiki