/[winpt]/trunk/PTD/wptZIP.cpp
ViewVC logotype

Annotation of /trunk/PTD/wptZIP.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations)
Tue Oct 25 07:46:20 2005 UTC (19 years, 4 months ago) by twoaday
File size: 23968 byte(s)
More bug fixes and cleanups.
See ChangeLog for details.

1 twoaday 33 /* wptZIP.cpp
2     * Copyright (C) 2002-2004 Timo Schulz
3     *
4     * This file is part of WinPT.
5     *
6     * WinPT is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * WinPT is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with PTD; if not, write to the Free Software Foundation,
18     * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20     #include <windows.h>
21     #include <assert.h>
22     #include <stdlib.h>
23     #include <stdio.h>
24     #include <string.h>
25     #include <sys/stat.h>
26     #include <direct.h>
27     #include <time.h>
28    
29     #include "wptZIP.h"
30    
31     /*static int debug = 0;*/
32    
33     enum zip_sig_t {
34     PK_SIG_LOCAL = 0x04034b50,
35     PK_SIG_FILE = 0x02014b50,
36     PK_SIG_END = 0x06054b50
37     };
38    
39     enum zip_flag_t {
40     PK_FLAG_ENCRYPTED = 1, /* archive is encrypted. */
41     PK_FLAG_8KDICT = 2, /* used 8k dictionary */
42     PK_FLAG_SF = 4
43     };
44    
45    
46     typedef struct {
47     unsigned long magic;
48     unsigned short ver;
49     unsigned short flags;
50     unsigned short method;
51     unsigned short ftime;
52     unsigned short fdate;
53     unsigned long crc;
54     unsigned long c_size;
55     unsigned long u_size;
56     unsigned short f_len;
57     unsigned short extra_len;
58     char *name;
59     FILE *fp;
60     } PK_local_hdr;
61    
62     typedef struct {
63     unsigned long magic;
64     unsigned short ver_made;
65     unsigned short ver_ext;
66     unsigned short flags;
67     unsigned short method;
68     unsigned short ftime;
69     unsigned short fdate;
70     unsigned long crc;
71     unsigned long c_size;
72     unsigned long u_size;
73     unsigned short f_len;
74     unsigned short extra_len;
75     unsigned short comment_len;
76     unsigned short disc_nr;
77     unsigned short int_attr;
78     unsigned long ext_attr;
79     unsigned long lochdr_off;
80     char *name;
81     size_t size;
82     } PK_file_hdr;
83    
84    
85     typedef struct {
86     unsigned long magic;
87     unsigned short disc_nr;
88     unsigned short disc_nr_cd;
89     unsigned short total_dirs_disc;
90     unsigned short total_dirs;
91     unsigned long size_of_dir;
92     unsigned long off_dir;
93     unsigned short comment_len;
94     char *comment;
95     } PK_end_hdr;
96    
97    
98     typedef struct {
99     union {
100     PK_local_hdr *local;
101     PK_file_hdr *file;
102     PK_end_hdr *end;
103     } u;
104     unsigned long pkttype;
105     } PK_packet;
106    
107    
108     struct PK_file_list {
109     struct PK_file_list *next;
110     PK_local_hdr *hdr;
111     size_t off;
112     size_t len;
113     char *d;
114     };
115    
116    
117     static unsigned long crc_table[256] = {
118     0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
119     0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
120     0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
121     0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
122     0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
123     0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
124     0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
125     0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
126     0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
127     0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
128     0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
129     0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
130     0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
131     0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
132     0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
133     0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
134     0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
135     0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
136     0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
137     0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
138     0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
139     0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
140     0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
141     0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
142     0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
143     0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
144     0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
145     0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
146     0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
147     0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
148     0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
149     0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
150     0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
151     0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
152     0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
153     0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
154     0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
155     0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
156     0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
157     0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
158     0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
159     0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
160     0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
161     0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
162     0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
163     0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
164     0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
165     0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
166     0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
167     0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
168     0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
169     0x2d02ef8dL
170     };
171    
172    
173     /* Update the crc in @crc with the buffer @buf and the length @buflen. */
174     static unsigned long
175     update_crc (unsigned long crc, unsigned char *buf, size_t buflen)
176     {
177     crc ^= 0xffffffffL;
178     while (buflen--)
179     crc = crc_table[((int)(crc) ^ (*buf++)) & 0xff] ^ ((crc) >> 8);
180     crc ^= 0xffffffffL;
181     return crc;
182     }
183    
184    
185     static unsigned short
186     read_16 (FILE *in)
187     {
188     unsigned short u;
189     u = fgetc (in) ;
190     u |= fgetc (in) << 8;
191     return u;
192     }
193    
194    
195     static void
196     write_16 (FILE *out, unsigned short a)
197     {
198     fputc (a , out);
199     fputc (a >> 8, out);
200     }
201    
202    
203     static unsigned long
204     read_32 (FILE *in)
205     {
206     unsigned long u;
207     u = fgetc (in) ;
208     u |= fgetc (in) << 8;
209     u |= fgetc (in) << 16;
210     u |= fgetc (in) << 24;
211     return u;
212     }
213    
214    
215     static void
216     write_32 (FILE * out, unsigned long a)
217     {
218     fputc (a , out);
219     fputc (a >> 8 , out);
220     fputc (a >> 16, out);
221     fputc (a >> 24, out);
222     }
223    
224    
225     static unsigned short
226     date_to_dos (time_t t)
227     {
228     struct tm * tm;
229     tm = localtime (&t);
230     return tm->tm_mday | (tm->tm_mon+1)<<5 | ((tm->tm_year-80)<<9);
231     }
232    
233    
234     static unsigned short
235     time_to_dos (time_t t)
236     {
237     struct tm * tm;
238     tm = localtime (&t);
239     return (tm->tm_hour<<11) | (tm->tm_min<<5) | (tm->tm_sec>>1);
240     }
241    
242    
243     static char*
244     xstrdup (const char * s)
245     {
246     char *p = new char[strlen (s)+1];
247     if (!p)
248     abort ();
249     strcpy (p, s);
250     return p;
251     }
252    
253    
254     static PK_local_hdr*
255     create_local_header (const char *name, FILE *fp)
256     {
257     struct stat statbuf;
258     PK_local_hdr *a;
259    
260     if (fstat (fileno (fp), &statbuf))
261     return NULL;
262     a = new PK_local_hdr;
263     if (!a)
264     return NULL;
265     memset (a, 0, sizeof *a);
266     a->magic = PK_SIG_LOCAL;
267     a->ver = 0 | (10 << 8);
268     a->flags = 0;
269     a->method = 0;
270     a->fdate = date_to_dos (statbuf.st_mtime);
271     a->ftime = time_to_dos (statbuf.st_mtime);
272     a->crc = 0;
273     a->c_size = statbuf.st_size;
274     a->u_size = statbuf.st_size;
275     a->f_len = strlen (name);
276     a->name = xstrdup (name);
277     a->extra_len = 0;
278     a->fp = fp;
279     return a;
280     }
281    
282    
283     static int
284     write_local_header (FILE *out, PK_local_hdr *hdr)
285     {
286     long crc_pos = 0, curr_pos = 0;
287    
288     write_32 (out, hdr->magic);
289     write_16 (out, hdr->ver);
290     write_16 (out, hdr->flags);
291     write_16 (out, hdr->method);
292     write_16 (out, hdr->ftime);
293     write_16 (out, hdr->fdate);
294     crc_pos = ftell (out);
295     write_32 (out, hdr->crc);
296     write_32 (out, hdr->c_size);
297     write_32 (out, hdr->u_size);
298     write_16 (out, hdr->f_len);
299     write_16 (out, hdr->extra_len);
300     if (hdr->f_len > 0)
301     fwrite (hdr->name, 1, hdr->f_len, out);
302     if (hdr->extra_len)
303     fwrite (NULL, 1, hdr->extra_len, out); /* xxx */
304     while (!feof (hdr->fp)) {
305     unsigned char buf[2048];
306     unsigned long nread;
307     nread = fread (buf, 1, sizeof buf-1, hdr->fp);
308     if (nread > 0) {
309     /*fprintf (stderr, "** nread=%d\n", nread);*/
310     hdr->crc = update_crc (hdr->crc, buf, nread);
311     fwrite (buf, 1, nread, out);
312     }
313     }
314     curr_pos = ftell (out);
315     fseek (out, crc_pos, SEEK_SET);
316     write_32 (out, hdr->crc);
317     fseek (out, curr_pos, SEEK_SET);
318     return 0;
319     }
320    
321    
322     static int
323     create_missing_dirs (const char *name)
324     {
325     struct stat dirbuf;
326     char *p, *dir;
327     int rc;
328    
329     p = strrchr (name, '/');
330     if (!p)
331     return PKERR_GENERAL;
332     dir = new char[(p-name)+1];
333     if (!dir)
334     abort ();
335     memset (dir, 0, (p-name)+1);
336     strncpy (dir, name, (p-name));
337     if (!stat (dir, &dirbuf) && (dirbuf.st_mode & _S_IFDIR))
338     rc = 0;
339     else
340     rc = mkdir (dir);
341     delete []dir;
342     return rc;
343     }
344    
345    
346     static PK_local_hdr*
347     read_local_header (FILE *in, unsigned long magic, int create)
348     {
349     PK_local_hdr *hdr;
350     FILE *out = NULL;
351     size_t n;
352    
353     if (magic != PK_SIG_LOCAL)
354     return NULL;
355     hdr = new PK_local_hdr;
356     if (!hdr)
357     return NULL;
358     memset (hdr, 0, sizeof * hdr);
359     hdr->magic = magic;
360     hdr->ver = read_16 (in);
361     hdr->flags = read_16 (in);
362     hdr->method = read_16 (in);
363     hdr->ftime = read_16 (in);
364     hdr->fdate = read_16 (in);
365     hdr->crc = read_32 (in);
366     hdr->c_size = read_32 (in);
367     hdr->u_size = read_32 (in);
368     hdr->f_len = read_16 (in);
369     hdr->extra_len = read_16 (in);
370    
371     /*if( debug ) {
372     printf("=====BEGIN LOCAL HEADER=====\n");
373     printf( "magic %08lX version=%d\n", hdr->magic, hdr->ver );
374     printf( "flags encrypted=%d 8k dict=%d shannon=%d\n",
375     hdr->flags & PK_FLAG_ENCRYPTED, hdr->flags & PK_FLAG_8KDICT,
376     hdr->flags & PK_FLAG_SF );
377     printf( "method=" );
378     switch( hdr->method ) {
379     case 0: printf( "stored\n" ); break;
380     default: printf( "unknown (%d)\n", hdr->method );
381     }
382     printf( "filetime=%d %d\n", hdr->ftime, hdr->fdate );
383     printf( "CRC=%08lX\n", hdr->crc );
384     printf( "size: compressed=%lu uncompressed=%lu\n",
385     hdr->c_size, hdr->u_size );
386     printf( "filename len=%d extra_len=%d\n", hdr->f_len, hdr->extra_len );
387     }*/
388    
389     if (hdr->f_len) {
390     hdr->name = new char[hdr->f_len+1];
391     if (!hdr->name)
392     abort ();
393     memset (hdr->name, 0, hdr->f_len+1);
394     fread (hdr->name, 1, hdr->f_len, in);
395     /*if (debug)
396     printf ("filename %s\n", hdr->name);*/
397     }
398     /*if (debug)
399     printf ("skip extra header (%d)\n", hdr->extra_len);*/
400     n = hdr->extra_len;
401     while (n--)
402     fgetc (in);
403     /*if (debug)
404     printf ("skip compressed data (%lu)\n", hdr->c_size);*/
405     if (create && hdr->name) {
406     create_missing_dirs (hdr->name);
407     out = fopen (hdr->name, "wb");
408     /*if (debug)
409     printf( "create output `%s' (status %s)\n", hdr->name,
410     out? "success" : "failed" );*/
411     }
412     n = hdr->c_size;
413     while (n--) {
414     int c = fgetc (in);
415     if (out)
416     fputc (c, out);
417     }
418     if (out)
419     fclose (out);
420     return hdr;
421     }
422    
423    
424     static PK_file_hdr*
425     create_file_header (PK_local_hdr * loc, long loc_off)
426     {
427     PK_file_hdr * a;
428    
429     a = new PK_file_hdr;
430     if (!a)
431     abort ();
432     memset (a, 0, sizeof *a);
433     a->magic = PK_SIG_FILE;
434     a->ver_made = loc->ver;
435     a->ver_ext = loc->ver;
436     a->flags = loc->flags;
437     a->method = loc->method;
438     a->ftime = loc->ftime;
439     a->fdate = loc->fdate;
440     a->crc = loc->crc;
441     a->c_size = loc->c_size;
442     a->u_size = loc->u_size;
443     a->f_len = loc->f_len;
444     a->extra_len = loc->extra_len;
445     a->comment_len = 0;
446     a->disc_nr = 0;
447     a->int_attr = 0;
448     a->ext_attr = 0;
449     a->lochdr_off = loc_off;
450     a->size = 46 + a->f_len;
451     a->name = xstrdup (loc->name);
452     return a;
453     }
454    
455    
456     static int
457     write_file_header (FILE *out, PK_file_hdr *hdr)
458     {
459     write_32 (out, hdr->magic);
460     write_16 (out, hdr->ver_made);
461     write_16 (out, hdr->ver_ext);
462     write_16 (out, hdr->flags);
463     write_16 (out, hdr->method);
464     write_16 (out, hdr->ftime);
465     write_16 (out, hdr->fdate);
466     write_32 (out, hdr->crc);
467     write_32 (out, hdr->c_size);
468     write_32 (out, hdr->u_size);
469     write_16 (out, hdr->f_len);
470     write_16 (out, hdr->extra_len);
471     write_16 (out, hdr->comment_len);
472     write_16 (out, hdr->disc_nr);
473     write_16 (out, hdr->int_attr);
474     write_32 (out, hdr->ext_attr);
475     write_32 (out, hdr->lochdr_off);
476     if (hdr->f_len > 0)
477     fwrite (hdr->name, 1, hdr->f_len, out);
478     if (hdr->extra_len > 0)
479     fwrite (NULL, 1, hdr->extra_len, out); /* xxx */
480     if (hdr->comment_len > 0)
481     fwrite (NULL, 1, hdr->comment_len, out); /* xxx */
482     return 0;
483     }
484    
485    
486     static PK_file_hdr*
487     read_file_header (FILE * in, unsigned long magic)
488     {
489     PK_file_hdr * hdr;
490     size_t n;
491    
492     if (magic != PK_SIG_FILE)
493     return NULL;
494     hdr = new PK_file_hdr;
495     if (!hdr)
496     return NULL;
497     memset (hdr, 0, sizeof * hdr);
498     hdr->magic = magic;
499     hdr->ver_made = read_16( in );
500     hdr->ver_ext = read_16( in );
501     hdr->flags = read_16( in );
502     hdr->method = read_16( in );
503     hdr->ftime = read_16( in );
504     hdr->fdate = read_16( in );
505     hdr->crc = read_32( in );
506     hdr->c_size = read_32( in );
507     hdr->u_size = read_32( in );
508     hdr->f_len = read_16( in );
509     hdr->extra_len = read_16( in );
510     hdr->comment_len = read_16( in );
511     hdr->disc_nr = read_16( in );
512     hdr->int_attr = read_16( in );
513     hdr->ext_attr = read_32( in );
514     hdr->lochdr_off = read_32( in );
515    
516     /*if( debug ) {
517     printf("=====BEGIN FILE HEADER=====\n");
518     printf( "magic=%08lX\n", hdr->magic );
519     printf( "version made=%d needed=%d\n", hdr->ver_made, hdr->ver_ext );
520     printf( "flags encrypted=%d endheader=%d extended=%d\n",
521     hdr->flags & PK_FLAG_ENCRYPTED, hdr->flags & PK_FLAG_8KDICT,
522     hdr->flags & PK_FLAG_SF );
523     printf( "method=" );
524     switch( hdr->method ) {
525     case 0: printf( "stored\n" ); break;
526     default: printf( "unknown (%d)\n", hdr->method );
527     }
528     printf( "filetime=%d %d\n", hdr->ftime, hdr->fdate );
529     printf( "CRC=%08lX\n", hdr->crc );
530     printf( "size compressed=%lu uncompressed=%lu\n",
531     hdr->c_size, hdr->u_size );
532     printf( "extra len=%d comment len=%d\n", hdr->extra_len,
533     hdr->comment_len );
534     printf( "disk nummer=%d\n", hdr->disc_nr );
535     printf( "attrs intern=%d extern=%lu\n", hdr->int_attr, hdr->ext_attr );
536     printf( "disk offset=%lu\n", hdr->lochdr_off );
537     }*/
538    
539     if (hdr->f_len > 0) {
540     hdr->name = new char[hdr->f_len + 1];
541     if (!hdr->name)
542     abort ();
543     memset (hdr->name, 0, hdr->f_len+1);
544     fread (hdr->name, 1, hdr->f_len, in);
545     /*if( debug )
546     printf( "filename=%s\n", hdr->name );*/
547     }
548     n = hdr->extra_len;
549     while (n--)
550     fgetc (in);
551     n = hdr->comment_len;
552     while (n--)
553     fgetc (in);
554     return hdr;
555     }
556    
557    
558     static PK_end_hdr*
559     create_end_header (size_t ntotal, size_t nsize, long off_dir)
560     {
561     PK_end_hdr *a;
562    
563     a = new PK_end_hdr;
564     if (!a)
565     abort ();
566     memset (a, 0, sizeof * a);
567     a->magic = PK_SIG_END;
568     a->disc_nr = 0;
569     a->disc_nr_cd = 0;
570     a->total_dirs = ntotal;
571     a->total_dirs_disc = ntotal;
572     a->size_of_dir = nsize;
573     a->off_dir = off_dir;
574     a->comment_len = 0;
575     return a;
576     }
577    
578    
579     static int
580     write_end_header (FILE *out, PK_end_hdr *hdr)
581     {
582     write_32 (out, hdr->magic);
583     write_16 (out, hdr->disc_nr);
584     write_16 (out, hdr->disc_nr_cd);
585     write_16 (out, hdr->total_dirs);
586     write_16 (out, hdr->total_dirs_disc);
587     write_32 (out, hdr->size_of_dir);
588     write_32 (out, hdr->off_dir);
589     write_16 (out, hdr->comment_len);
590     if (hdr->comment_len > 0)
591     fwrite (hdr->comment, 1, hdr->comment_len, out);
592     return 0;
593     }
594    
595    
596     static PK_end_hdr*
597     read_end_header (FILE * in, unsigned long magic)
598     {
599     PK_end_hdr * hdr;
600    
601     if( magic != PK_SIG_END )
602     return NULL;
603     hdr = new PK_end_hdr;
604     if( !hdr )
605     abort ();
606     memset (hdr, 0, sizeof *hdr);
607     hdr->magic = magic;
608     hdr->disc_nr = read_16( in );
609     hdr->disc_nr_cd = read_16( in );
610     hdr->total_dirs = read_16( in );
611     hdr->total_dirs_disc = read_16( in );
612     hdr->size_of_dir = read_32( in );
613     hdr->off_dir = read_32( in );
614     hdr->comment_len = read_16( in );
615    
616     /*if( debug ) {
617     printf("=====BEGIN END HEADER=====\n");
618     printf( "magic=%08lX\n", hdr->magic );
619     printf( "disc number=%d in this directory=%d\n", hdr->disc_nr,
620     hdr->disc_nr_cd );
621     printf( "total number of disc=%d in this directory=%d\n",
622     hdr->total_dirs, hdr->total_dirs_disc );
623     printf( "offset of central directory=%lu\n", hdr->off_dir );
624     printf( "size of directory=%lu\n", hdr->size_of_dir );
625     }*/
626    
627     if (hdr->comment_len > 0) {
628     hdr->comment = new char[hdr->comment_len+1];
629     if( !hdr->comment )
630     abort ();
631     memset (hdr->comment, 0, hdr->comment_len+1);
632     fread( hdr->comment, 1, hdr->comment_len, in );
633     /*if( debug )
634     printf( "comment(%d)=%s\n", hdr->comment_len, hdr->comment );*/
635     }
636     return hdr;
637     }
638    
639    
640     static void
641     free_packet (PK_packet *pkt)
642     {
643     switch( pkt->pkttype ) {
644     case PK_SIG_LOCAL:
645     if (pkt->u.local->name)
646     delete []pkt->u.local->name;
647     delete pkt->u.local;
648     break;
649     case PK_SIG_FILE:
650     if (pkt->u.file->name)
651     delete[] pkt->u.file->name;
652     delete pkt->u.file;
653     break;
654     case PK_SIG_END:
655     if (pkt->u.end->comment)
656     delete [] pkt->u.end->comment;
657     delete pkt->u.end;
658     break;
659     }
660     pkt->pkttype = 0;
661     }
662    
663    
664     int
665     pk_archiv_parse (FILE *in)
666     {
667     unsigned long magic;
668     PK_packet pkt;
669    
670     while( !feof( in ) ) {
671     magic = read_32( in );
672     if( feof( in ) )
673     break;
674     /*printf("\n** read magic value %08lX\n\n", magic );*/
675     switch( magic ) {
676     case PK_SIG_LOCAL:
677     pkt.u.local = read_local_header( in, magic, 1 );
678     pkt.pkttype = PK_SIG_LOCAL;
679     break;
680    
681     case PK_SIG_FILE:
682     pkt.u.file = read_file_header( in, magic );
683     pkt.pkttype = PK_SIG_FILE;
684     break;
685    
686     case PK_SIG_END:
687     pkt.u.end = read_end_header( in, magic );
688     pkt.pkttype = PK_SIG_END;
689     break;
690    
691     default:
692     /*printf( "unknown magic value (%08lX).\n", magic );*/
693     if( ftell( in ) == 4 ) {
694     free_packet( &pkt );
695     return PKERR_INV_FILE;
696     }
697     break;
698     }
699     free_packet( &pkt );
700     }
701     return 0;
702     }
703    
704    
705     static int
706     is_directory (const char * fname)
707     {
708     struct stat statbuf;
709     if (stat (fname, &statbuf))
710     return 0;
711     return statbuf.st_mode & S_IFDIR;
712     }
713    
714    
715     int
716     pk_archiv_create (struct PK_file_list *list, const char *output)
717     {
718     struct PK_file_list *r;
719     PK_file_hdr *f;
720     PK_end_hdr *e;
721     PK_packet pkt;
722     FILE *fp, *out;
723     long foff = 0, n = 0;
724     size_t size = 0;
725    
726     out = fopen (output, "wb");
727     if (!out)
728     return PKERR_FILE;
729    
730     for (r = list; r; r = r->next) {
731     fprintf (stderr, "process file `%s'\n", r->d);
732     if (is_directory (r->d))
733     continue;
734     fp = fopen (r->d, "rb");
735     if (!fp) {
736     fclose (out);
737     return PKERR_FILE;
738     }
739     r->off = ftell (out);
740     r->hdr = create_local_header( r->d, fp );
741     if (!r->hdr) {
742     fclose (fp);
743     fclose (out);
744     return PKERR_GENERAL;
745     }
746     if (r->off)
747     r->off += r->hdr->c_size;
748     write_local_header (out, r->hdr);
749     n++;
750     fclose (fp);
751     }
752     foff = ftell( out );
753     for (r = list; r; r = r->next) {
754     if (is_directory (r->d))
755     continue;
756     fp = fopen (r->d, "rb");
757     if (!fp) {
758     fclose (out);
759     return PKERR_FILE;
760     }
761     f = create_file_header (r->hdr, r->off);
762     size += f->size;
763     write_file_header (out, f);
764     fclose (fp);
765     pkt.u.file = f;
766     free_packet (&pkt);
767     }
768    
769     e = create_end_header (n, size, foff);
770     write_end_header (out, e);
771     fclose (out);
772     return 0;
773     }
774    
775    
776     void
777     pk_list_add (struct PK_file_list **list, const char *name)
778     {
779     struct PK_file_list * l;
780    
781     l = new PK_file_list;
782     if (!l)
783     abort ();
784     memset (l, 0, sizeof *l);
785     l->next = *list;
786     l->d = new char[strlen (name)+2];
787     if (!l->d)
788     abort ();
789     strcpy (l->d, name);
790     *list = l;
791     }
792    
793    
794     void
795     pk_list_free (struct PK_file_list *list)
796     {
797     struct PK_file_list * l;
798     PK_packet pkt;
799    
800     while (list) {
801     l = list->next;
802     if (list->hdr) {
803     pkt.pkttype = PK_SIG_LOCAL;
804     pkt.u.local = list->hdr;
805     free_packet (&pkt);
806     }
807     if (list->d)
808     delete []list->d;
809     delete list;
810     list = l;
811     }
812     }
813    
814    
815     #ifdef TEST
816    
817     static void
818     test (const char *patt, const char *path, const char *out)
819     {
820     PK_FILE_LIST list = NULL;
821     WIN32_FIND_DATA findbuf;
822     HANDLE hd;
823     int rc = 0;
824    
825     hd = FindFirstFile (patt, &findbuf );
826     if( !hd )
827     return;
828    
829     if( strcmp( findbuf.cFileName, "." ) && strcmp( findbuf.cFileName, ".." ) ) {
830     char p[256];
831     _snprintf (p, sizeof (p)-1, "%s\\%s", path, findbuf.cFileName);
832     pk_list_add (&list, p);
833     }
834     while( FindNextFile( hd, &findbuf ) ) {
835     if( strcmp( findbuf.cFileName, "." ) && strcmp( findbuf.cFileName, ".." ) ) {
836     char p[256];
837     _snprintf (p, sizeof (p)-1, "%s\\%s", path, findbuf.cFileName);
838     pk_list_add (&list, p);
839     }
840     }
841    
842     rc = pk_archiv_create (list, out);
843    
844     pk_list_free (list);
845     FindClose (hd);
846     }
847    
848     int
849     main (int argc, char **argv)
850     {
851     test ("c:\\gnupg\\*", "c:\\gnupg", "c:\\gnupg\\\\test\\sample.zip");
852     return 0;
853     }
854     #endif

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26