2 * Metro physical packages and parts, mapped to a zip archive.
8 typedef struct sa_default_s sa_default
;
9 typedef struct sa_override_s sa_override
;
15 sa_override
*overrides
;
19 * Load the [Content_Types].xml data structures
20 * that define content types for the parts in the package.
38 readcontenttypes(sa_package
*pack
)
45 error
= sa_openzipentry(&zipstm
, pack
->zip
, "[Content_Types].xml");
49 error
= sa_openxml(&parser
, zipstm
, 0);
53 item
= sa_xmlnext(parser
);
56 if (!strcmp(sa_xmlname(item
), "Types"))
59 item
= sa_xmlnext(parser
);
62 if (!strcmp(sa_xmlname(item
), "Default"))
64 char *ext
= sa_xmlatt(item
, "Extension");
65 char *type
= sa_xmlatt(item
, "ContentType");
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
;
80 if (!strcmp(sa_xmlname(item
), "Override"))
82 char *name
= sa_xmlatt(item
, "PartName");
83 char *type
= sa_xmlatt(item
, "ContentType");
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
;
98 item
= sa_xmlnext(parser
);
105 fz_dropstream(zipstm
);
111 fz_dropstream(zipstm
);
116 * Return the type of a part, or nil if it doenst exist or has no type.
119 sa_typepart(sa_package
*pack
, char *partname
)
125 if (partname
[0] != '/')
128 if (sa_accesszipentry(pack
->zip
, partname
+ 1))
130 for (ovr
= pack
->overrides
; ovr
; ovr
= ovr
->next
)
131 if (!sa_strcmp(partname
, ovr
->partname
))
132 return ovr
->mimetype
;
134 ext
= strrchr(partname
, '.');
137 for (def
= pack
->defaults
; def
; def
= def
->next
)
138 if (!sa_strcmp(ext
+ 1, def
->extension
))
139 return def
->mimetype
;
149 * Load the content types.
150 * Load the relations for the root.
153 sa_openpackage(sa_package
**packp
, char *filename
)
158 pack
= fz_malloc(sizeof(sa_package
));
163 pack
->defaults
= nil
;
164 pack
->overrides
= nil
;
166 error
= sa_openzip(&pack
->zip
, filename
);
169 sa_closepackage(pack
);
173 error
= readcontenttypes(pack
);
176 sa_closepackage(pack
);
185 sa_closepackage(sa_package
*pack
)
187 sa_default
*def
, *ndef
;
188 sa_override
*ovr
, *novr
;
191 sa_closezip(pack
->zip
);
193 for (def
= pack
->defaults
; def
; def
= ndef
)
196 fz_free(def
->extension
);
197 fz_free(def
->mimetype
);
201 for (ovr
= pack
->overrides
; ovr
; ovr
= novr
)
204 fz_free(ovr
->partname
);
205 fz_free(ovr
->mimetype
);
213 sa_debugpackage(sa_package
*pack
)
218 printf("package\n{\n");
221 sa_debugzip(pack
->zip
);
223 printf(" defaults\n {\n");
224 for (def
= pack
->defaults
; def
; def
= def
->next
)
225 printf(" %-8s %s\n", def
->extension
, def
->mimetype
);
228 printf(" overrides\n {\n");
229 for (ovr
= pack
->overrides
; ovr
; ovr
= ovr
->next
)
230 printf(" %s\n %s\n", ovr
->partname
, ovr
->mimetype
);
237 * Open a part for reading.
238 * It is NOT safe to open more than one part at a time.
241 sa_openpart(fz_stream
**stmp
, sa_package
*pack
, char *partname
)
243 if (partname
[0] != '/')
244 return fz_throw("ioerror: invalid part name: %s", partname
);
245 return sa_openzipentry(stmp
, pack
->zip
, partname
+ 1);
249 * Load a linked list of all the relations of a part.
250 * This is contained in <folder>/_rels/<file>.rels
253 sa_loadrelations(sa_relation
**relsp
, sa_package
*pack
, char *partname
)
257 sa_xmlparser
*parser
;
265 if (partname
[0] != '/')
266 return fz_throw("ioerror: invalid part name: %s", partname
);
268 sep
= strrchr(partname
, '/');
270 return fz_throw("ioerror: invalid part name: %s", partname
);
272 len
= strlen(partname
) + 11 + 1;
273 relsname
= fz_malloc(len
);
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");
285 if (!sa_accesszipentry(pack
->zip
, relsname
+ 1))
292 error
= sa_openzipentry(&zipstm
, pack
->zip
, relsname
+ 1);
296 error
= sa_openxml(&parser
, zipstm
, 0);
300 item
= sa_xmlnext(parser
);
303 if (!strcmp(sa_xmlname(item
), "Relationships"))
306 item
= sa_xmlnext(parser
);
309 if (!strcmp(sa_xmlname(item
), "Relationship"))
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");
319 if (id
&& target
&& type
)
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
);
328 if (newrel
->external
)
329 newrel
->target
= fz_strdup(target
);
332 sa_resolvepath(buf
, partname
, target
, sizeof buf
);
333 newrel
->target
= fz_strdup(buf
);
339 item
= sa_xmlnext(parser
);
346 fz_dropstream(zipstm
);
354 fz_dropstream(zipstm
);
361 sa_debugrelations(sa_relation
*rel
)
363 printf("relations\n{\n");
366 printf(" %s\n", rel
->type
);
367 printf(" %s%s\n", rel
->external
? "external " : "", rel
->target
);
374 sa_droprelations(sa_relation
*rel
)
380 fz_free(rel
->target
);