/[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 - (hide 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 zoff99 8 /**
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