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.
34 struct zipfile *files;
53 ret = _("Not enough memory");
56 ret = _("Cannot find zip signature");
59 ret = _("Invalid zip file");
62 ret = _("Multi file zips are not supported");
65 ret = _("Cannot open the file");
68 ret = _("Cannot read data from file");
71 ret = _("Cannot find file in the zip archive");
74 ret = _("Unknown error");
85 ulong size, pos, i, flag;
88 if (fseek (f, 0, SEEK_END) != 0) return 1;
90 if (size < 0xffff) pos = 0; else pos = size - 0xffff;
91 buf = malloc (size - pos + 1);
93 if (fseek (f, pos, SEEK_SET) != 0) {
97 if (fread (buf, size - pos, 1, f) != 1) {
102 for (i = size - pos - 3; i > 0; i--) {
103 if (buf[i] == 0x50 && buf[i+1] == 0x4b && buf[i+2] == 0x05 && buf[i+3] == 0x06) {
110 if (flag != 1) return 1;
115 get_long (unsigned char *buf)
117 return buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
121 get_word (unsigned char *buf)
123 return buf[0] + (buf[1] << 8);
129 unsigned char buf[46];
130 struct zipfile *zfile;
135 while (nr < z->nr_files) {
136 fseek (z->f, pat + z->head_size, SEEK_SET);
138 if (fread (buf, 46, 1, z->f) != 1) return ZIP_EREAD;
139 if (get_long (buf) != 0x02014b50) return ZIP_BADZIP;
141 zfile = malloc (sizeof (struct zipfile));
142 if (!zfile) return ZIP_NOMEM;
143 memset (zfile, 0, sizeof (struct zipfile));
145 zfile->crc = get_long (buf + 16);
146 zfile->zip_size = get_long (buf + 20);
147 zfile->real_size = get_long (buf + 24);
148 fn_size = get_word (buf + 28);
149 zfile->pos = get_long (buf + 42);
151 zfile->name = malloc (fn_size + 1);
156 fread (zfile->name, fn_size, 1, z->f);
157 zfile->name[fn_size] = '\0';
159 zfile->next = z->files;
162 pat += 0x2e + fn_size + get_word (buf + 30) + get_word (buf + 32);
169 zip_open (const char *fname, int *err)
171 unsigned char buf[22];
175 f = fopen (fname, "rb");
181 z = malloc (sizeof (zip));
182 memset (z, 0, sizeof (zip));
191 fseek (f, z->cd_pos, SEEK_SET);
192 if (fread (buf, 22, 1, f) != 1) {
197 z->nr_files = get_word (buf + 10);
198 if (get_word (buf + 8) != z->nr_files) {
203 z->cd_size = get_long (buf + 12);
204 z->cd_offset = get_long (buf + 16);
205 z->rem_size = get_word (buf + 20);
206 z->head_size = z->cd_pos - (z->cd_offset + z->cd_size);
208 *err = list_files (z);
209 if (*err != ZIP_OK) {
221 struct zipfile *zfile, *tmp;
226 if (zfile->name) free (zfile->name);
231 if (z->f) fclose (z->f);
235 static struct zipfile *
236 find_file (zip *z, const char *name)
238 struct zipfile *zfile;
242 if (strcmp (zfile->name, name) == 0) return zfile;
249 seek_file (zip *z, struct zipfile *zfile)
251 unsigned char buf[30];
253 fseek (z->f, zfile->pos + z->head_size, SEEK_SET);
254 if (fread (buf, 30, 1, z->f) != 1) return ZIP_EREAD;
255 if (get_long (buf) != 0x04034b50) return ZIP_BADZIP;
256 fseek (z->f, get_word (buf + 26) + get_word (buf + 28), SEEK_CUR);
261 zip_load_xml (zip *z, const char *name, int *err)
266 struct zipfile *zfile;
270 zfile = find_file (z, name);
276 seek_file (z, zfile);
278 real_buf = malloc (zfile->real_size + 1);
279 if (zfile->zip_size < zfile->real_size) {
285 zip_buf = malloc (zfile->zip_size);
286 fread (zip_buf, zfile->zip_size, 1, z->f);
287 zs.next_in = zip_buf;
288 zs.avail_in = zfile->zip_size;
289 zs.next_out = real_buf;
290 zs.avail_out = zfile->real_size;
291 inflateInit2 (&zs, -MAX_WBITS);
292 inflate (&zs, Z_FINISH);
296 fread (real_buf, zfile->real_size, 1, z->f);
299 real_buf[zfile->real_size] = '\0';
300 prs = iks_dom_new (&x);
301 iks_parse (prs, real_buf, zfile->real_size, 1);
302 iks_parser_delete (prs);
307 unsigned long zip_get_size (zip *z, const char *name)
311 zf = find_file (z, name);
313 return zf->real_size;
316 int zip_load (zip *z, const char *name, char *buf)
318 struct zipfile *zfile;
320 zfile = find_file (z, name);
321 if (!zfile) return ZIP_NOFILE;
323 seek_file (z, zfile);
325 if (zfile->zip_size < zfile->real_size) {
331 zip_buf = malloc (zfile->zip_size);
332 fread (zip_buf, zfile->zip_size, 1, z->f);
333 zs.next_in = zip_buf;
334 zs.avail_in = zfile->zip_size;
336 zs.avail_out = zfile->real_size;
337 inflateInit2 (&zs, -MAX_WBITS);
338 inflate (&zs, Z_FINISH);
342 fread (buf, zfile->real_size, 1, z->f);