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.
13 typedef unsigned long ulong;
37 struct zipfile *files;
56 ret = _("Not enough memory");
59 ret = _("Cannot find zip signature");
62 ret = _("Invalid zip file");
65 ret = _("Multi file zips are not supported");
68 ret = _("Cannot open the file");
71 ret = _("Cannot read data from file");
74 ret = _("Cannot find file in the zip archive");
77 ret = _("Unknown error");
88 ulong size, pos, i, flag;
91 if (fseek (f, 0, SEEK_END) != 0) return 1;
93 if (size < 0xffff) pos = 0; else pos = size - 0xffff;
94 buf = malloc (size - pos + 1);
96 if (fseek (f, pos, SEEK_SET) != 0) {
100 if (fread (buf, size - pos, 1, f) != 1) {
105 for (i = size - pos - 3; i > 0; i--) {
106 if (buf[i] == 0x50 && buf[i+1] == 0x4b && buf[i+2] == 0x05 && buf[i+3] == 0x06) {
113 if (flag != 1) return 1;
118 get_long (unsigned char *buf)
120 return buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
124 get_word (unsigned char *buf)
126 return buf[0] + (buf[1] << 8);
132 unsigned char buf[46];
133 struct zipfile *zfile;
138 while (nr < z->nr_files) {
139 fseek (z->f, pat + z->head_size, SEEK_SET);
141 if (fread (buf, 46, 1, z->f) != 1) return ZIP_EREAD;
142 if (get_long (buf) != 0x02014b50) return ZIP_BADZIP;
144 zfile = malloc (sizeof (struct zipfile));
145 if (!zfile) return ZIP_NOMEM;
146 memset (zfile, 0, sizeof (struct zipfile));
148 zfile->crc = get_long (buf + 16);
149 zfile->zip_size = get_long (buf + 20);
150 zfile->real_size = get_long (buf + 24);
151 fn_size = get_word (buf + 28);
152 zfile->pos = get_long (buf + 42);
154 zfile->name = malloc (fn_size + 1);
159 fread (zfile->name, fn_size, 1, z->f);
160 zfile->name[fn_size] = '\0';
162 zfile->next = z->files;
165 pat += 0x2e + fn_size + get_word (buf + 30) + get_word (buf + 32);
172 zip_open (const char *fname, int *err)
174 unsigned char buf[22];
178 f = fopen (fname, "rb");
184 z = malloc (sizeof (zip));
185 memset (z, 0, sizeof (zip));
194 fseek (f, z->cd_pos, SEEK_SET);
195 if (fread (buf, 22, 1, f) != 1) {
200 z->nr_files = get_word (buf + 10);
201 if (get_word (buf + 8) != z->nr_files) {
206 z->cd_size = get_long (buf + 12);
207 z->cd_offset = get_long (buf + 16);
208 z->rem_size = get_word (buf + 20);
209 z->head_size = z->cd_pos - (z->cd_offset + z->cd_size);
211 *err = list_files (z);
212 if (*err != ZIP_OK) {
224 struct zipfile *zfile, *tmp;
229 if (zfile->name) free (zfile->name);
234 if (z->f) fclose (z->f);
238 static struct zipfile *
239 find_file (zip *z, const char *name)
241 struct zipfile *zfile;
245 if (strcmp (zfile->name, name) == 0) return zfile;
252 seek_file (zip *z, struct zipfile *zfile)
254 unsigned char buf[30];
256 fseek (z->f, zfile->pos + z->head_size, SEEK_SET);
257 if (fread (buf, 30, 1, z->f) != 1) return ZIP_EREAD;
258 if (get_long (buf) != 0x04034b50) return ZIP_BADZIP;
259 fseek (z->f, get_word (buf + 26) + get_word (buf + 28), SEEK_CUR);
264 zip_load_xml (zip *z, const char *name, int *err)
269 struct zipfile *zfile;
273 zfile = find_file (z, name);
279 seek_file (z, zfile);
281 real_buf = malloc (zfile->real_size + 1);
282 if (zfile->zip_size < zfile->real_size) {
288 zip_buf = malloc (zfile->zip_size);
289 fread (zip_buf, zfile->zip_size, 1, z->f);
290 zs.next_in = zip_buf;
291 zs.avail_in = zfile->zip_size;
292 zs.next_out = real_buf;
293 zs.avail_out = zfile->real_size;
294 inflateInit2 (&zs, -MAX_WBITS);
295 inflate (&zs, Z_FINISH);
299 fread (real_buf, zfile->real_size, 1, z->f);
302 real_buf[zfile->real_size] = '\0';
303 prs = iks_dom_new (&x);
304 iks_parse (prs, real_buf, zfile->real_size, 1);
305 iks_parser_delete (prs);
310 unsigned long zip_get_size (zip *z, const char *name)
314 zf = find_file (z, name);
316 return zf->real_size;
319 int zip_load (zip *z, const char *name, char *buf)
321 struct zipfile *zfile;
323 zfile = find_file (z, name);
324 if (!zfile) return ZIP_NOFILE;
326 seek_file (z, zfile);
328 if (zfile->zip_size < zfile->real_size) {
334 zip_buf = malloc (zfile->zip_size);
335 fread (zip_buf, zfile->zip_size, 1, z->f);
336 zs.next_in = zip_buf;
337 zs.avail_in = zfile->zip_size;
339 zs.avail_out = zfile->real_size;
340 inflateInit2 (&zs, -MAX_WBITS);
341 inflate (&zs, Z_FINISH);
345 fread (buf, zfile->real_size, 1, z->f);