1 /* imposter (OO.org Impress viewer)
2 ** Copyright (C) 2003-2005 Gurer Ozen
3 ** This code is free software; you can redistribute it and/or
4 ** modify it under the terms of GNU General Public License.
12 typedef unsigned long ulong;
36 struct zipfile *files;
55 ret = _("Not enough memory");
58 ret = _("Cannot find zip signature");
61 ret = _("Invalid zip file");
64 ret = _("Multi file zips are not supported");
67 ret = _("Cannot open the file");
70 ret = _("Cannot read data from file");
73 ret = _("Cannot find file in the zip archive");
76 ret = _("Unknown error");
87 ulong size, pos, i, flag;
90 if (fseek (f, 0, SEEK_END) != 0) return 1;
92 if (size < 0xffff) pos = 0; else pos = size - 0xffff;
93 buf = malloc (size - pos + 1);
95 if (fseek (f, pos, SEEK_SET) != 0) {
99 if (fread (buf, size - pos, 1, f) != 1) {
104 for (i = size - pos - 3; i > 0; i--) {
105 if (buf[i] == 0x50 && buf[i+1] == 0x4b && buf[i+2] == 0x05 && buf[i+3] == 0x06) {
112 if (flag != 1) return 1;
117 get_long (unsigned char *buf)
119 return buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
123 get_word (unsigned char *buf)
125 return buf[0] + (buf[1] << 8);
131 unsigned char buf[46];
132 struct zipfile *zfile;
137 while (nr < z->nr_files) {
138 fseek (z->f, pat + z->head_size, SEEK_SET);
140 if (fread (buf, 46, 1, z->f) != 1) return ZIP_EREAD;
141 if (get_long (buf) != 0x02014b50) return ZIP_BADZIP;
143 zfile = malloc (sizeof (struct zipfile));
144 if (!zfile) return ZIP_NOMEM;
145 memset (zfile, 0, sizeof (struct zipfile));
147 zfile->crc = get_long (buf + 16);
148 zfile->zip_size = get_long (buf + 20);
149 zfile->real_size = get_long (buf + 24);
150 fn_size = get_word (buf + 28);
151 zfile->pos = get_long (buf + 42);
153 zfile->name = malloc (fn_size + 1);
158 fread (zfile->name, fn_size, 1, z->f);
159 zfile->name[fn_size] = '\0';
161 zfile->next = z->files;
164 pat += 0x2e + fn_size + get_word (buf + 30) + get_word (buf + 32);
171 zip_open (const char *fname, int *err)
173 unsigned char buf[22];
177 f = fopen (fname, "rb");
183 z = malloc (sizeof (zip));
184 memset (z, 0, sizeof (zip));
193 fseek (f, z->cd_pos, SEEK_SET);
194 if (fread (buf, 22, 1, f) != 1) {
199 z->nr_files = get_word (buf + 10);
200 if (get_word (buf + 8) != z->nr_files) {
205 z->cd_size = get_long (buf + 12);
206 z->cd_offset = get_long (buf + 16);
207 z->rem_size = get_word (buf + 20);
208 z->head_size = z->cd_pos - (z->cd_offset + z->cd_size);
210 *err = list_files (z);
211 if (*err != ZIP_OK) {
223 struct zipfile *zfile, *tmp;
228 if (zfile->name) free (zfile->name);
233 if (z->f) fclose (z->f);
237 static struct zipfile *
238 find_file (zip *z, const char *name)
240 struct zipfile *zfile;
244 if (strcmp (zfile->name, name) == 0) return zfile;
251 seek_file (zip *z, struct zipfile *zfile)
253 unsigned char buf[30];
255 fseek (z->f, zfile->pos + z->head_size, SEEK_SET);
256 if (fread (buf, 30, 1, z->f) != 1) return ZIP_EREAD;
257 if (get_long (buf) != 0x04034b50) return ZIP_BADZIP;
258 fseek (z->f, get_word (buf + 26) + get_word (buf + 28), SEEK_CUR);
263 zip_load_xml (zip *z, const char *name, int *err)
268 struct zipfile *zfile;
272 zfile = find_file (z, name);
278 seek_file (z, zfile);
280 real_buf = malloc (zfile->real_size + 1);
281 if (zfile->zip_size < zfile->real_size) {
287 zip_buf = malloc (zfile->zip_size);
288 fread (zip_buf, zfile->zip_size, 1, z->f);
289 zs.next_in = zip_buf;
290 zs.avail_in = zfile->zip_size;
291 zs.next_out = real_buf;
292 zs.avail_out = zfile->real_size;
293 inflateInit2 (&zs, -MAX_WBITS);
294 inflate (&zs, Z_FINISH);
298 fread (real_buf, zfile->real_size, 1, z->f);
301 real_buf[zfile->real_size] = '\0';
302 prs = iks_dom_new (&x);
303 iks_parse (prs, real_buf, zfile->real_size, 1);
304 iks_parser_delete (prs);
309 unsigned long zip_get_size (zip *z, const char *name)
313 zf = find_file (z, name);
315 return zf->real_size;
318 int zip_load (zip *z, const char *name, char *buf)
320 struct zipfile *zfile;
322 zfile = find_file (z, name);
323 if (!zfile) return ZIP_NOFILE;
325 seek_file (z, zfile);
327 if (zfile->zip_size < zfile->real_size) {
333 zip_buf = malloc (zfile->zip_size);
334 fread (zip_buf, zfile->zip_size, 1, z->f);
335 zs.next_in = zip_buf;
336 zs.avail_in = zfile->zip_size;
338 zs.avail_out = zfile->real_size;
339 inflateInit2 (&zs, -MAX_WBITS);
340 inflate (&zs, Z_FINISH);
344 fread (buf, zfile->real_size, 1, z->f);