SmartPDF - lightweight pdf viewer app for rosapps
[reactos.git] / rosapps / smartpdf / fitz / samus / sa_pack.c
1 /*
2 * Metro physical packages and parts, mapped to a zip archive.
3 */
4
5 #include "fitz.h"
6 #include "samus.h"
7
8 typedef struct sa_default_s sa_default;
9 typedef struct sa_override_s sa_override;
10
11 struct sa_package_s
12 {
13 sa_zip *zip;
14 sa_default *defaults;
15 sa_override *overrides;
16 };
17
18 /*
19 * Load the [Content_Types].xml data structures
20 * that define content types for the parts in the package.
21 */
22
23 struct sa_default_s
24 {
25 char *extension;
26 char *mimetype;
27 sa_default *next;
28 };
29
30 struct sa_override_s
31 {
32 char *partname;
33 char *mimetype;
34 sa_override *next;
35 };
36
37 static fz_error *
38 readcontenttypes(sa_package *pack)
39 {
40 fz_error *error;
41 fz_stream *zipstm;
42 sa_xmlparser *parser;
43 sa_xmlitem *item;
44
45 error = sa_openzipentry(&zipstm, pack->zip, "[Content_Types].xml");
46 if (error)
47 return error;
48
49 error = sa_openxml(&parser, zipstm, 0);
50 if (error)
51 goto cleanupzip;
52
53 item = sa_xmlnext(parser);
54 while (item)
55 {
56 if (!strcmp(sa_xmlname(item), "Types"))
57 {
58 sa_xmldown(parser);
59 item = sa_xmlnext(parser);
60 while (item)
61 {
62 if (!strcmp(sa_xmlname(item), "Default"))
63 {
64 char *ext = sa_xmlatt(item, "Extension");
65 char *type = sa_xmlatt(item, "ContentType");
66 if (ext && type)
67 {
68 sa_default *newdef;
69 if (strchr(type, ';'))
70 strchr(type, ';')[0] = 0;
71 newdef = fz_malloc(sizeof(sa_default));
72 if (!newdef) { error = fz_outofmem; goto cleanupxml; }
73 newdef->extension = fz_strdup(ext);
74 newdef->mimetype = fz_strdup(type);
75 newdef->next = pack->defaults;
76 pack->defaults = newdef;
77 }
78 }
79
80 if (!strcmp(sa_xmlname(item), "Override"))
81 {
82 char *name = sa_xmlatt(item, "PartName");
83 char *type = sa_xmlatt(item, "ContentType");
84 if (name && type)
85 {
86 sa_override *newovr;
87 if (strchr(type, ';'))
88 strchr(type, ';')[0] = 0;
89 newovr = fz_malloc(sizeof(sa_override));
90 if (!newovr) { error = fz_outofmem; goto cleanupxml; }
91 newovr->partname = fz_strdup(name);
92 newovr->mimetype = fz_strdup(type);
93 newovr->next = pack->overrides;
94 pack->overrides = newovr;
95 }
96 }
97
98 item = sa_xmlnext(parser);
99 }
100 sa_xmlup(parser);
101 }
102 }
103
104 sa_closexml(parser);
105 fz_dropstream(zipstm);
106 return nil;
107
108 cleanupxml:
109 sa_closexml(parser);
110 cleanupzip:
111 fz_dropstream(zipstm);
112 return error;
113 }
114
115 /*
116 * Return the type of a part, or nil if it doenst exist or has no type.
117 */
118 char *
119 sa_typepart(sa_package *pack, char *partname)
120 {
121 sa_default *def;
122 sa_override *ovr;
123 char *ext;
124
125 if (partname[0] != '/')
126 return nil;
127
128 if (sa_accesszipentry(pack->zip, partname + 1))
129 {
130 for (ovr = pack->overrides; ovr; ovr = ovr->next)
131 if (!sa_strcmp(partname, ovr->partname))
132 return ovr->mimetype;
133
134 ext = strrchr(partname, '.');
135 if (ext)
136 {
137 for (def = pack->defaults; def; def = def->next)
138 if (!sa_strcmp(ext + 1, def->extension))
139 return def->mimetype;
140 }
141 }
142
143 return nil;
144 }
145
146 /*
147 * Open a package...
148 * Open the ZIP file.
149 * Load the content types.
150 * Load the relations for the root.
151 */
152 fz_error *
153 sa_openpackage(sa_package **packp, char *filename)
154 {
155 fz_error *error;
156 sa_package *pack;
157
158 pack = fz_malloc(sizeof(sa_package));
159 if (!pack)
160 return fz_outofmem;
161
162 pack->zip = nil;
163 pack->defaults = nil;
164 pack->overrides = nil;
165
166 error = sa_openzip(&pack->zip, filename);
167 if (error)
168 {
169 sa_closepackage(pack);
170 return error;
171 }
172
173 error = readcontenttypes(pack);
174 if (error)
175 {
176 sa_closepackage(pack);
177 return error;
178 }
179
180 *packp = pack;
181 return nil;
182 }
183
184 void
185 sa_closepackage(sa_package *pack)
186 {
187 sa_default *def, *ndef;
188 sa_override *ovr, *novr;
189
190 if (pack->zip)
191 sa_closezip(pack->zip);
192
193 for (def = pack->defaults; def; def = ndef)
194 {
195 ndef = def->next;
196 fz_free(def->extension);
197 fz_free(def->mimetype);
198 fz_free(def);
199 }
200
201 for (ovr = pack->overrides; ovr; ovr = novr)
202 {
203 novr = ovr->next;
204 fz_free(ovr->partname);
205 fz_free(ovr->mimetype);
206 fz_free(ovr);
207 }
208
209 fz_free(pack);
210 }
211
212 void
213 sa_debugpackage(sa_package *pack)
214 {
215 sa_default *def;
216 sa_override *ovr;
217
218 printf("package\n{\n");
219
220 if (pack->zip)
221 sa_debugzip(pack->zip);
222
223 printf(" defaults\n {\n");
224 for (def = pack->defaults; def; def = def->next)
225 printf(" %-8s %s\n", def->extension, def->mimetype);
226 printf(" }\n");
227
228 printf(" overrides\n {\n");
229 for (ovr = pack->overrides; ovr; ovr = ovr->next)
230 printf(" %s\n %s\n", ovr->partname, ovr->mimetype);
231 printf(" }\n");
232
233 printf("}\n");
234 }
235
236 /*
237 * Open a part for reading.
238 * It is NOT safe to open more than one part at a time.
239 */
240 fz_error *
241 sa_openpart(fz_stream **stmp, sa_package *pack, char *partname)
242 {
243 if (partname[0] != '/')
244 return fz_throw("ioerror: invalid part name: %s", partname);
245 return sa_openzipentry(stmp, pack->zip, partname + 1);
246 }
247
248 /*
249 * Load a linked list of all the relations of a part.
250 * This is contained in <folder>/_rels/<file>.rels
251 */
252 fz_error *
253 sa_loadrelations(sa_relation **relsp, sa_package *pack, char *partname)
254 {
255 fz_error *error;
256 fz_stream *zipstm;
257 sa_xmlparser *parser;
258 sa_xmlitem *item;
259 sa_relation *rels;
260 int len;
261 char *sep;
262 char *relsname;
263 char buf[1024];
264
265 if (partname[0] != '/')
266 return fz_throw("ioerror: invalid part name: %s", partname);
267
268 sep = strrchr(partname, '/');
269 if (!sep)
270 return fz_throw("ioerror: invalid part name: %s", partname);
271
272 len = strlen(partname) + 11 + 1;
273 relsname = fz_malloc(len);
274 if (!relsname)
275 return fz_outofmem;
276
277 memcpy(relsname, partname, sep - partname + 1);
278 relsname[sep - partname + 1] = 0;
279 strcat(relsname, "_rels/");
280 strcat(relsname, sep + 1);
281 strcat(relsname, ".rels");
282
283 rels = nil;
284
285 if (!sa_accesszipentry(pack->zip, relsname + 1))
286 {
287 fz_free(relsname);
288 *relsp = nil;
289 return nil;
290 }
291
292 error = sa_openzipentry(&zipstm, pack->zip, relsname + 1);
293 if (error)
294 goto cleanupname;
295
296 error = sa_openxml(&parser, zipstm, 0);
297 if (error)
298 goto cleanupzip;
299
300 item = sa_xmlnext(parser);
301 while (item)
302 {
303 if (!strcmp(sa_xmlname(item), "Relationships"))
304 {
305 sa_xmldown(parser);
306 item = sa_xmlnext(parser);
307 while (item)
308 {
309 if (!strcmp(sa_xmlname(item), "Relationship"))
310 {
311 char *mode = sa_xmlatt(item, "TargetMode");
312 char *id = sa_xmlatt(item, "Id");
313 char *target = sa_xmlatt(item, "Target");
314 char *type = sa_xmlatt(item, "Type");
315
316 if (!mode)
317 mode = "Internal";
318
319 if (id && target && type)
320 {
321 sa_relation *newrel;
322 newrel = fz_malloc(sizeof(sa_relation));
323 if (!newrel) { error = fz_outofmem; goto cleanupxml; }
324 newrel->external = !strcmp(mode, "External");
325 newrel->id = fz_strdup(id);
326 newrel->type = fz_strdup(type);
327 newrel->next = rels;
328 if (newrel->external)
329 newrel->target = fz_strdup(target);
330 else
331 {
332 sa_resolvepath(buf, partname, target, sizeof buf);
333 newrel->target = fz_strdup(buf);
334 }
335 rels = newrel;
336 }
337 }
338
339 item = sa_xmlnext(parser);
340 }
341 sa_xmlup(parser);
342 }
343 }
344
345 sa_closexml(parser);
346 fz_dropstream(zipstm);
347 fz_free(relsname);
348 *relsp = rels;
349 return nil;
350
351 cleanupxml:
352 sa_closexml(parser);
353 cleanupzip:
354 fz_dropstream(zipstm);
355 cleanupname:
356 fz_free(relsname);
357 return error;
358 }
359
360 void
361 sa_debugrelations(sa_relation *rel)
362 {
363 printf("relations\n{\n");
364 while (rel)
365 {
366 printf(" %s\n", rel->type);
367 printf(" %s%s\n", rel->external ? "external " : "", rel->target);
368 rel = rel->next;
369 }
370 printf("}\n");
371 }
372
373 void
374 sa_droprelations(sa_relation *rel)
375 {
376 sa_relation *nrel;
377 while (rel)
378 {
379 nrel = rel->next;
380 fz_free(rel->target);
381 fz_free(rel->id);
382 fz_free(rel->type);
383 fz_free(rel);
384 rel = nrel;
385 }
386 }
387