1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #ifdef HAVE_STDBOOL_H
8 #include <stdbool.h>
9 #else
10 typedef enum { FALSE = 0, TRUE = 1 } bool;
11 #endif
12 #ifdef HAVE_GETOPT_H
13 #include <getopt.h>
14 #else
15 #include "getopt.h"
16 #endif
17 
18 #include <string.h>
19 #include <errno.h>
20 
fgetu32(FILE * f)21 static u32 fgetu32 (FILE *f)
22 {
23   register u32 r;
24 
25   r  = fgetc(f) <<  0;
26   r |= fgetc(f) <<  8;
27   r |= fgetc(f) << 16;
28   r |= fgetc(f) << 24;
29 
30   return r;
31 }
32 
fgetu16(FILE * f)33 static u32 fgetu16 (FILE *f)
34 {
35   register u32 r;
36 
37   r  = fgetc(f) <<  0;
38   r |= fgetc(f) <<  8;
39 
40   return r;
41 }
42 
parse_zip(char * path)43 static void parse_zip (char *path)
44 {
45   FILE *f = fopen (path, "rb");
46 
47   if (!f)
48     {
49       fprintf (stderr, "skipping '%s': %s\n", path, strerror (errno));
50       goto out;
51     }
52 
53   while (!feof (f))
54     {
55     u32 id = fgetu32 (f);
56 
57     if (id == 0x04034b50UL)
58       {
59         u16 version		= fgetu16 (f);
60         u16 flags		= fgetu16 (f);
61         u16 compression_method 	= fgetu16 (f);
62         u16 lastmodtime		= fgetu16 (f);
63         u16 lastmoddate		= fgetu16 (f);
64         u32 crc32		= fgetu32 (f);
65         u32 compr_size		= fgetu32 (f);
66         u32 uncompr_size	= fgetu32 (f);
67         u16 name_len		= fgetu16 (f);
68         u16 extra_field_len	= fgetu16 (f);
69 
70         char zip_path [1024];
71 
72         (void)crc32; /* suppress warning */
73 
74         /* these are unused.  */
75         (void) lastmoddate;
76         (void) lastmodtime;
77         (void) compression_method;
78         (void) version;
79 
80         if (name_len < 1024)
81           {
82             fread (zip_path, name_len, 1, f);
83             zip_path [name_len] = 0;
84           }
85         else
86           {
87             fprintf (stderr, "filename too long (>1023 bytes), skipping zipfile\n");
88             goto out;
89           }
90 
91         fseek (f, extra_field_len, SEEK_CUR);
92 
93         printf ("found file '%s', size %ld (%ld)", zip_path, (long)uncompr_size, (long)compr_size);
94 
95         if (flags & 1)
96           printf (", encrypted");
97 
98         if (compr_size >= 23)
99           {
100             u8 file[24];
101             fread (file, 24, 1, f);
102 
103             printf ("\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
104                     file[0], file[1], file[ 2], file[ 3],
105                     file[4], file[5], file[ 6], file[ 7],
106                     file[8], file[9], file[10], file[11]);
107 
108             printf (" : %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
109                     file[12], file[13], file[14], file[15],
110                     file[16], file[17], file[18], file[19],
111                     file[20], file[21], file[22], file[23]);
112 
113             compr_size -= 24;
114           }
115 
116         printf ("\n");
117 
118         fseek (f, compr_size, SEEK_CUR);
119       }
120     else if (id == 0x08074b50UL) /* extended local sig (?)  */
121       {
122         fseek (f, 12, SEEK_CUR);
123       }
124     else if (id == 0x30304b50UL)
125       {
126         /* ignore */
127       }
128     else if (id == 0x02014b50UL || id == 0x06054b50UL)
129       {
130         goto out;
131       }
132     else
133       {
134         fprintf (stderr, "found id %08lx, '%s' is not a zipfile ver 2.xx, skipping\n",
135                  (unsigned long)id, path);
136         goto out;
137       }
138     }
139 
140   out:
141   fclose (f);
142 }
143 
usage(int ec)144 static void usage (int ec)
145 {
146   printf ("\n"
147                  PACKAGE " version " VERSION ", fcrackzipinfo - tell me about a zip file\n"
148                  "written by Marc Lehmann <pcg@goof.com> You can find more info on\n"
149                  "http://www.goof.com/pcg/marc/\n"
150                  "\n"
151                  "USAGE: fcrackzipinfo file...                the zipfiles to parse\n"
152                  "\n"
153           );
154 
155   exit (ec);
156 }
157 
158 static struct option options[] = {
159   { "help"		, no_argument		, 0, 'h' },
160   { "version"		, no_argument		, 0, 'R' },
161   { 0			, 0			, 0,  0  },
162 };
163 
main(int argc,char * argv[])164 int main (int argc, char *argv[])
165 {
166   int option_index = 0;
167   int c;
168 
169   while ((c = getopt_long (argc, argv, "", options, &option_index)) != -1)
170     switch (c)
171       {
172       case 'h':
173         usage (0);
174         break;
175       case 'R':
176         printf ("fcrackzipinfo version " VERSION "\n");
177         exit (0);
178       }
179 
180   if (optind >= argc)
181     {
182       fprintf (stderr, "you have to specify one or more zip files (try --help)\n");
183       exit (1);
184     }
185 
186   for (; optind < argc; optind++)
187     parse_zip (argv[optind]);
188 
189   return 0;
190 }
191