static void xps_parse_metadata_imp(xps_context *ctx, xml_element *item) { while (item) { xps_parse_metadata_imp(ctx, xml_down(item)); if (!strcmp(xml_tag(item), "Relationship")) { char *target = xml_att(item, "Target"); char *type = xml_att(item, "Type"); if (target && type) { char tgtbuf[1024]; xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); if (!strcmp(type, REL_START_PART)) ctx->start_part = fz_strdup(tgtbuf); } } if (!strcmp(xml_tag(item), "DocumentReference")) { char *source = xml_att(item, "Source"); if (source) { char srcbuf[1024]; xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); xps_add_fixed_document(ctx, srcbuf); } } if (!strcmp(xml_tag(item), "PageContent")) { char *source = xml_att(item, "Source"); char *width_att = xml_att(item, "Width"); char *height_att = xml_att(item, "Height"); int width = width_att ? atoi(width_att) : 0; int height = height_att ? atoi(height_att) : 0; if (source) { char srcbuf[1024]; xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); xps_add_fixed_page(ctx, srcbuf, width, height); } } item = xml_next(item); } }
static int xps_find_doc_props_path(xps_context *ctx, char path[1024]) { xml_element *root; int code = xps_open_and_parse(ctx, "/_rels/.rels", &root); if (code != fz_okay) return code; *path = '\0'; if (!strcmp(xml_tag(root), "Relationships")) { xml_element *item; for (item = xml_down(root); item; item = xml_next(item)) { if (!strcmp(xml_tag(item), "Relationship") && xml_att(item, "Type") && !strcmp(xml_att(item, "Type"), REL_CORE_PROPERTIES) && xml_att(item, "Target")) { xps_absolute_path(path, "", xml_att(item, "Target"), 1024); } } } else code = fz_error_make(ctx->ctx, "couldn't parse part '/_rels/.rels'"); xml_free_element(ctx->ctx, root); return code; }
void xps_extract_link_info(xps_context *ctx, xml_element *node, fz_rect rect, char *base_uri) { xps_link *link = NULL; char *value; if (!ctx->link_root) return; if ((value = xml_att(node, "FixedPage.NavigateUri")) && !strchr(value, ':')) { char tgtbuf[1024]; xps_absolute_path(tgtbuf, base_uri, value, sizeof(tgtbuf)); link = xps_new_link(tgtbuf, rect, 0); } else if (value) // link with a protocol (e.g. http://...) link = xps_new_link(value, rect, 0); else if ((value = xml_att(node, "Name"))) link = xps_new_link(value, rect, 1); // insert the links in top-to-bottom order (first one is to be preferred) if (link) { link->next = ctx->link_root->next; ctx->link_root->next = link; } }
static void xps_parse_outline_imp(xps_outline **outlinep, xml_element *item, char *base_uri) { int lastLevel = 0; for (; item; item = xml_next(item)) { char *description, *target; int level; char tgtbuf[1024]; xps_outline *outline; xps_parse_outline_imp(outlinep, xml_down(item), base_uri); if (strcmp(xml_tag(item), "OutlineEntry") != 0 || !(description = xml_att(item, "Description")) || !(target = xml_att(item, "OutlineTarget"))) continue; if (xml_att(item, "OutlineLevel")) level = atoi(xml_att(item, "OutlineLevel")); else level = lastLevel; xps_absolute_path(tgtbuf, base_uri, target, sizeof(tgtbuf)); outline = xps_new_outline(description, tgtbuf); if (!*outlinep) *outlinep = outline; else if (level > lastLevel) xps_get_insertion_point(*outlinep, lastLevel)->child = outline; else xps_get_insertion_point(*outlinep, level)->next = outline; lastLevel = level; } }
static int xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, char *source_att) { char part_name[1024]; char part_uri[1024]; xps_resource *dict; xps_part *part; xml_element *xml; char *s; int code; /* External resource dictionaries MUST NOT reference other resource dictionaries */ xps_absolute_path(part_name, base_uri, source_att, sizeof part_name); part = xps_read_part(ctx, part_name); if (!part) { return fz_throw("cannot find remote resource part '%s'", part_name); } xml = xml_parse_document(part->data, part->size); if (!xml) { xps_free_part(ctx, part); return fz_rethrow(-1, "cannot parse xml"); } if (strcmp(xml_tag(xml), "ResourceDictionary")) { xml_free_element(xml); xps_free_part(ctx, part); return fz_throw("expected ResourceDictionary element (found %s)", xml_tag(xml)); } fz_strlcpy(part_uri, part_name, sizeof part_uri); s = strrchr(part_uri, '/'); if (s) s[1] = 0; code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml); if (code) { xml_free_element(xml); xps_free_part(ctx, part); return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri); } dict->base_xml = xml; /* pass on ownership */ xps_free_part(ctx, part); *dictp = dict; return fz_okay; }
static void xps_parse_names_imp(xps_named_dest **destsp, xps_context *ctx, xps_document *doc, xml_element *item, char *base_uri, int page) { char tgtbuf[1024]; for (; item; item = xml_next(item)) { if (!strcmp(xml_tag(item), "PageContent") && xml_att(item, "Source") && page == 0) { int i; xps_page *page; xps_absolute_path(tgtbuf, base_uri, xml_att(item, "Source"), sizeof(tgtbuf)); for (page = ctx->first_page, i = 0; page; page = page->next, i++) { if (strcmp(page->name, tgtbuf) != 0) continue; xps_parse_names_imp(destsp, ctx, doc, xml_down(item), base_uri, i + 1); break; } } else if (!strcmp(xml_tag(item), "LinkTarget") && xml_att(item, "Name") && page != 0) { xps_named_dest *dest; fz_strlcpy(tgtbuf, doc->name, sizeof(tgtbuf)); fz_strlcat(tgtbuf, "#", sizeof(tgtbuf)); fz_strlcat(tgtbuf, xml_att(item, "Name"), sizeof(tgtbuf)); dest = xps_new_named_dest(tgtbuf, page); if (!*destsp) *destsp = dest; else { xps_named_dest *next; for (next = *destsp; next->next; next = next->next); next->next = dest; } } else xps_parse_names_imp(destsp, ctx, doc, xml_down(item), base_uri, page); } }
static int xps_read_and_process_document_outline(xps_outline **outlinep, xps_context *ctx, xps_document *doc) { char base_uri[1024]; xml_element *root; xml_element *item; int code = fz_okay; xps_rels_for_part(base_uri, doc->name, sizeof(base_uri)); code = xps_open_and_parse(ctx, base_uri, &root); if (code != fz_okay) return code; *strstr(base_uri, "/_rels/") = '\0'; for (item = root; item; item = xml_next(item)) { xml_element *relItem; if (strcmp(xml_tag(item), "Relationships") != 0) continue; for (relItem = xml_down(item); relItem; relItem = xml_next(relItem)) { char *target, *type; if (!strcmp(xml_tag(relItem), "Relationship") && (target = xml_att(relItem, "Target")) && (type = xml_att(relItem, "Type")) && !strcmp(type, REL_DOC_STRUCTURE)) { char tgtbuf[1024]; xps_absolute_path(tgtbuf, base_uri, target, sizeof(tgtbuf)); code = xps_parse_outline_structure(outlinep, ctx, tgtbuf); } } } xml_free_element(root); return code; }
static void xps_parse_metadata_imp(void *zp, char *name, char **atts) { xps_context_t *ctx = zp; int i; if (!strcmp(name, "Relationship")) { char tgtbuf[1024]; char *target = NULL; char *type = NULL; for (i = 0; atts[i]; i += 2) { if (!strcmp(atts[i], "Target")) target = atts[i + 1]; if (!strcmp(atts[i], "Type")) type = atts[i + 1]; } if (target && type) { xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); if (!strcmp(type, REL_START_PART)) ctx->start_part = xps_strdup(ctx, tgtbuf); } } if (!strcmp(name, "DocumentReference")) { char *source = NULL; char srcbuf[1024]; for (i = 0; atts[i]; i += 2) { if (!strcmp(atts[i], "Source")) source = atts[i + 1]; } if (source) { xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); xps_add_fixed_document(ctx, srcbuf); } } if (!strcmp(name, "PageContent")) { char *source = NULL; char srcbuf[1024]; int width = 0; int height = 0; for (i = 0; atts[i]; i += 2) { if (!strcmp(atts[i], "Source")) source = atts[i + 1]; if (!strcmp(atts[i], "Width")) width = atoi(atts[i + 1]); if (!strcmp(atts[i], "Height")) height = atoi(atts[i + 1]); } if (source) { xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); xps_add_fixed_page(ctx, srcbuf, width, height); } } }