diff options
author | Tor Andersson <tor@ghostscript.com> | 2005-06-04 22:40:20 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2005-06-04 22:40:20 +0200 |
commit | 7560c64207af372f7d75763285a6e955d3e68486 (patch) | |
tree | 18a05e892eeca41ba6d4c3c7f71e51154cbdfce3 | |
parent | 7c7a2ed5417f36780da11299ed463d8861cad762 (diff) | |
download | mupdf-7560c64207af372f7d75763285a6e955d3e68486.tar.xz |
fixed document sequence parsing
-rw-r--r-- | apps/samshow.c | 40 | ||||
-rw-r--r-- | base/Jamfile | 1 | ||||
-rw-r--r-- | base/base_cleanname.c | 52 | ||||
-rw-r--r-- | include/fitz/runtime.h | 2 | ||||
-rw-r--r-- | include/samus.h | 3 | ||||
-rw-r--r-- | include/samus/fixdoc.h | 13 | ||||
-rw-r--r-- | include/samus/misc.h | 1 | ||||
-rw-r--r-- | include/samus/names.h | 96 | ||||
-rw-r--r-- | samus/Jamfile | 4 | ||||
-rw-r--r-- | samus/sa_fixdoc.c | 327 | ||||
-rw-r--r-- | samus/sa_misc.c | 26 | ||||
-rw-r--r-- | samus/sa_pack.c | 25 |
12 files changed, 580 insertions, 10 deletions
diff --git a/apps/samshow.c b/apps/samshow.c index c8351dc1..e9ce86f1 100644 --- a/apps/samshow.c +++ b/apps/samshow.c @@ -1,6 +1,33 @@ #include "fitz.h" #include "samus.h" +void showfixdocseq(sa_package *pack, char *part) +{ + fz_error *error; + sa_fixdocseq *seq; + + error = sa_loadfixdocseq(&seq, pack, part); + if (error) + fz_abort(error); + + sa_debugfixdocseq(seq); + + sa_dropfixdocseq(seq); +} + +void showreach(sa_package *pack, sa_relation *rels) +{ + while (rels) + { + if (!strcmp(rels->type, SA_REL_FIXEDREPRESENTATION)) + { + if (!rels->external) + showfixdocseq(pack, rels->target); + } + rels = rels->next; + } +} + int runpack(int argc, char **argv) { fz_error *error; @@ -14,18 +41,23 @@ int runpack(int argc, char **argv) fz_abort(error); sa_debugpackage(pack); + printf("\n"); - printf("--- root ---\n"); error = sa_loadrelations(&rels, pack, "/"); if (error) fz_abort(error); sa_debugrelations(rels); - sa_droprelations(rels); printf("\n"); + if (argc == 2) + { + showreach(pack, rels); + return 0; + } + for (i = 2; i < argc; i++) { - printf("--- %s ---\n", argv[i]); + printf("part %s\n", argv[i]); s = sa_typepart(pack, argv[i]); if (!s) @@ -121,7 +153,7 @@ int runtiff(int argc, char **argv) error = sa_readtiff(file); if (error) fz_abort(error); - + fz_dropstream(file); return 0; diff --git a/base/Jamfile b/base/Jamfile index 0436cffd..91bde812 100644 --- a/base/Jamfile +++ b/base/Jamfile @@ -8,6 +8,7 @@ Library libbase : base_memory.c base_rect.c base_rune.c + base_cleanname.c ; if $(NEED_GETOPT) = yes { Library libbase : util_getopt.c ; } diff --git a/base/base_cleanname.c b/base/base_cleanname.c new file mode 100644 index 00000000..54764630 --- /dev/null +++ b/base/base_cleanname.c @@ -0,0 +1,52 @@ +/* + * In place, rewrite name to compress multiple /, eliminate ., and process .. + */ + +#define SEP(x) ((x)=='/' || (x) == 0) + +char * +cleanname(char *name) +{ + char *p, *q, *dotdot; + int rooted; + + rooted = name[0] == '/'; + + /* + * invariants: + * p points at beginning of path element we're considering. + * q points just past the last path element we wrote (no slash). + * dotdot points just past the point where .. cannot backtrack + * any further (no slash). + */ + p = q = dotdot = name+rooted; + while(*p) { + if(p[0] == '/') /* null element */ + p++; + else if(p[0] == '.' && SEP(p[1])) + p += 1; /* don't count the separator in case it is nul */ + else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) { + p += 2; + if(q > dotdot) { /* can backtrack */ + while(--q > dotdot && *q != '/') + ; + } else if(!rooted) { /* /.. is / but ./../ is .. */ + if(q != name) + *q++ = '/'; + *q++ = '.'; + *q++ = '.'; + dotdot = q; + } + } else { /* real path element */ + if(q != name+rooted) + *q++ = '/'; + while((*q = *p) != '/' && *q != 0) + p++, q++; + } + } + if(q == name) /* empty string is really ``.'' */ + *q++ = '.'; + *q = '\0'; + return name; +} + diff --git a/include/fitz/runtime.h b/include/fitz/runtime.h index e52e3c1d..feeb7ffc 100644 --- a/include/fitz/runtime.h +++ b/include/fitz/runtime.h @@ -24,11 +24,13 @@ #define STRIDE(n, bcp) (((bpc) * (n) + 7) / 8) +/* plan9 stuff for utf-8 and path munging */ int chartorune(int *rune, char *str); int runetochar(char *str, int *rune); int runelen(long c); int runenlen(int *r, int nrune); int fullrune(char *str, int n); +char *cleanname(char *name); typedef struct fz_error_s fz_error; diff --git a/include/samus.h b/include/samus.h index e9c841f7..a7b39482 100644 --- a/include/samus.h +++ b/include/samus.h @@ -20,3 +20,6 @@ #include "samus/xml.h" #include "samus/pack.h" +#include "samus/names.h" +#include "samus/fixdoc.h" + diff --git a/include/samus/fixdoc.h b/include/samus/fixdoc.h new file mode 100644 index 00000000..1b0caad1 --- /dev/null +++ b/include/samus/fixdoc.h @@ -0,0 +1,13 @@ +/* + * FixedDocumentSequence -- the list of pages + */ + +typedef struct sa_fixdocseq_s sa_fixdocseq; + +fz_error *sa_loadfixdocseq(sa_fixdocseq **seqp, sa_package *pack, char *part); +void sa_debugfixdocseq(sa_fixdocseq *seq); +void sa_dropfixdocseq(sa_fixdocseq *seq); + +int sa_getpagecount(sa_fixdocseq *seq); +char *sa_getpagepart(sa_fixdocseq *seq, int idx); + diff --git a/include/samus/misc.h b/include/samus/misc.h index db4bfc78..50170a04 100644 --- a/include/samus/misc.h +++ b/include/samus/misc.h @@ -2,5 +2,6 @@ * Misc utility functions that Samus needs. */ +char *sa_resolvepath(char *dst, char *base, char *part, int dstlen); int sa_strcmp(char *s0, char *s1); diff --git a/include/samus/names.h b/include/samus/names.h new file mode 100644 index 00000000..03a0e505 --- /dev/null +++ b/include/samus/names.h @@ -0,0 +1,96 @@ +/* + * Various long string constants + */ + +/* + * XML Namespaces + */ + +#define SA_NS_CONTENTTYPES \ + "http://schemas.microsoft.com/metro/2005/02/content-types" +#define SA_NS_COREPROPERTIES \ + "http://schemas.microsoft.com/metro/2005/02/md/core-properties" +#define SA_NS_SIGNATURES \ + "http://schemas.microsoft.com/metro/2005/02/digsig" +#define SA_NS_RELATIONSHIPS \ + "http://schemas.microsoft.com/metro/2005/02/relationships" +#define SA_NS_VERSIONING \ + "http://schemas.microsoft.com/winfx/markup-compatibility/2005" + +#define SA_NS_DISCARDCONTROL \ + "http://schemas.microsoft.com/metro/2005/02/rp/discard-control" +#define SA_NS_FIXEDDOCUMENT \ + "http://schemas.microsoft.com/metro/2005/02/rp" +#define SA_NS_FIXEDDOCUMENTSEQUENCE \ + "http://schemas.microsoft.com/metro/2005/02/rp" +#define SA_NS_FIXEDPAGE \ + "http://schemas.microsoft.com/metro/2005/02/rp" +#define SA_NS_PRINTSCHEMAFRAMEWORK \ + "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" +#define SA_NS_PRINTSCHEMAKEYWORDS \ + "http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords" +#define SA_NS_RESOURCEDICTIONARY \ + "http://schemas.microsoft.com/metro/2005/02/rp/resourcedictionary-key" + +/* + * Content types + */ + +#define SA_TYPE_COREPROPERTIES \ + "application/vnd.ms-metro.core-properties+xml" +#define SA_TYPE_CERTIFICATE \ + "application/vnd.ms-metro.ds-certificate" +#define SA_TYPE_ORIGIN \ + "application/vnd.ms-metro.ds-origin" +#define SA_TYPE_SIGNATURE \ + "application/vnd.ms-metro.ds-xmlsignature+xml" +#define SA_TYPE_RELATIONSHIPS \ + "application/vnd.ms-metro.relationships+xml" + +#define SA_TYPE_FIXEDDOCUMENT \ + "application/vnd.ms-metro.rp-fixeddocument+xml" +#define SA_TYPE_FIXEDDOCUMENTSEQUENCE \ + "application/vnd.ms-metro.rp-fixeddocumentsequence+xml" +#define SA_TYPE_FIXEDPAGE \ + "application/vnd.ms-metro.rp-fixedpage+xml" +#define SA_TYPE_FONT \ + "application/vnd.ms-opentype" +#define SA_TYPE_OBFUSCATEDFONT \ + "application/vnd.ms-metro.obfuscated-opentype" +#define SA_TYPE_PRINTTICKET \ + "application/vnd.ms-printing.printticket+xml" +#define SA_TYPE_JPEGIMAGE \ + "image/jpeg" +#define SA_TYPE_PNGIMAGE \ + "image/png" +#define SA_TYPE_TIFFIMAGE \ + "image/tiff" + +/* + * Relationship types + */ + +#define SA_REL_COREPROPERTIES \ + "http://schemas.microsoft.com/metro/2005/02/md/core-properties" +#define SA_REL_SIGNATURE \ + "http://schemas.microsoft.com/metro/2005/02/ds/signature" +#define SA_REL_CERTIFICATE \ + "http://schemas.microsoft.com/metro/2005/02/ds/certificate" +#define SA_REL_ORIGIN \ + "http://schemas.microsoft.com/metro/2005/02/ds/origin" +#define SA_REL_THUMBNAIL \ + "http://schemas.microsoft.com/metro/2005/02/md/thumbnail" + +#define SA_REL_ANNOTATIONS \ + "http://schemas.microsoft.com/metro/2005/02/rp/annotations" +#define SA_REL_DISCARDCONTROL \ + "http://schemas.microsoft.com/metro/2005/02/rp/discard-control" +#define SA_REL_PRINTTICKET \ + "http://schemas.microsoft.com/metro/2005/02/rp/printticket" +#define SA_REL_FIXEDREPRESENTATION \ + "http://schemas.microsoft.com/metro/2005/02/rp/fixedrepresentation" +#define SA_REL_REQUIREDRESOURCE \ + "http://schemas.microsoft.com/metro/2005/02/rp/required-resource" +#define SA_REL_RESTRICTEDFONT \ + "http://schemas.microsoft.com/metro/2005/02/rp/restricted-font" + diff --git a/samus/Jamfile b/samus/Jamfile index dde4a934..45d11dd5 100644 --- a/samus/Jamfile +++ b/samus/Jamfile @@ -1,10 +1,14 @@ SubDir TOP samus ; Library libsamus : + sa_misc.c sa_zip.c sa_xml.c sa_tiff.c sa_pack.c + + sa_fixdoc.c + ; diff --git a/samus/sa_fixdoc.c b/samus/sa_fixdoc.c new file mode 100644 index 00000000..5e69064f --- /dev/null +++ b/samus/sa_fixdoc.c @@ -0,0 +1,327 @@ +/* + * FixedDocumentSequence and FixedDocument parts. + */ + +#include "fitz.h" +#include "samus.h" + +typedef struct sa_fixdoc_s sa_fixdoc; +typedef struct sa_fixpage_s sa_fixpage; + +struct sa_fixdocseq_s +{ + int count; /* pages */ + sa_fixdoc *docs; +}; + +struct sa_fixdoc_s +{ + int count; + sa_fixpage *pages; + sa_fixdoc *next; +}; + +struct sa_fixpage_s +{ + char *part; + int width; + int height; + /* char **linktargets; */ + sa_fixpage *next; +}; + +/* + * Debugging + */ + +static void +sa_debugfixdoc(sa_fixdoc *doc, int i) +{ + sa_fixpage *page = doc->pages; + printf(" FixedDocument\n {\n"); + while (page) + { + printf(" FixedPage %d w=%d h=%d %s\n", i, + page->width, page->height, page->part); + page = page->next; + i ++; + } + printf(" }\n"); +} + +void +sa_debugfixdocseq(sa_fixdocseq *seq) +{ + sa_fixdoc *doc = seq->docs; + int i = 0; + printf("FixedDocumentSequence count=%d\n{\n", seq->count); + while (doc) + { + sa_debugfixdoc(doc, i); + i += doc->count; + doc = doc->next; + } + printf("}\n"); +} + +/* + * Free data structures + */ + +static void +sa_dropfixpage(sa_fixpage *page) +{ + sa_fixpage *next; + while (page) + { + next = page->next; + fz_free(page->part); + fz_free(page); + page = next; + } +} + +static void +sa_dropfixdoc(sa_fixdoc *doc) +{ + sa_fixdoc *next; + while (doc) + { + next = doc->next; + if (doc->pages) + sa_dropfixpage(doc->pages); + fz_free(doc); + doc = next; + } +} + +void +sa_dropfixdocseq(sa_fixdocseq *seq) +{ + sa_dropfixdoc(seq->docs); + fz_free(seq); +} + +/* + * Load FixedDocument + */ +static fz_error * +sa_loadfixdoc(sa_fixdoc **docp, sa_package *pack, char *part) +{ + fz_error *error; + fz_stream *stm; + sa_xmlparser *parser; + sa_xmlitem *item; + sa_fixdoc *doc; + sa_fixpage *page; + sa_fixpage *last; + char buf[1024]; + + page = nil; + last = nil; + + error = sa_openpart(&stm, pack, part); + if (error) + return error; + + doc = fz_malloc(sizeof(sa_fixdoc)); + if (!doc) + { + error = fz_outofmem; + goto cleanupstm; + } + + doc->count = 0; + doc->pages = nil; + doc->next = nil; + + error = sa_openxml(&parser, stm, 0); + if (error) + goto cleanupdoc; + + item = sa_xmlnext(parser); + while (item) + { + if (!strcmp(sa_xmlname(item), "FixedDocument")) + { + sa_xmldown(parser); + item = sa_xmlnext(parser); + while (item) + { + if (!strcmp(sa_xmlname(item), "PageContent")) + { + char *src = sa_xmlatt(item, "Source"); + char *w = sa_xmlatt(item, "Width"); + char *h = sa_xmlatt(item, "Height"); + + if (!w) w = "0"; + if (!h) h = "0"; + + if (src) + { + sa_resolvepath(buf, part, src, sizeof buf); + page = fz_malloc(sizeof(sa_fixpage)); + if (!page) + { + error = fz_outofmem; + goto cleanupxml; + } + + page->part = fz_strdup(buf); + if (!page->part) + { + fz_free(page); + error = fz_outofmem; + goto cleanupxml; + } + + page->width = atoi(w); + page->height = atoi(h); + + if (last) + last->next = page; + else + doc->pages = page; + doc->count ++; + last = page; + } + } + item = sa_xmlnext(parser); + } + sa_xmlup(parser); + } + item = sa_xmlnext(parser); + } + + sa_closexml(parser); + fz_dropstream(stm); + *docp = doc; + return nil; + +cleanupxml: + sa_closexml(parser); +cleanupdoc: + sa_dropfixdoc(doc); +cleanupstm: + fz_dropstream(stm); + return error; +} + +/* + * Load FixedDocumentSequence + */ +fz_error * +sa_loadfixdocseq(sa_fixdocseq **seqp, sa_package *pack, char *part) +{ + fz_error *error; + fz_stream *stm; + sa_xmlparser *parser; + sa_xmlitem *item; + sa_fixdocseq *seq; + sa_fixdoc *doc; + sa_fixdoc *last; + char buf[1024]; + + seq = nil; + last = nil; + + error = sa_openpart(&stm, pack, part); + if (error) + return error; + + seq = fz_malloc(sizeof(sa_fixdocseq)); + if (!seq) + { + error = fz_outofmem; + goto cleanupstm; + } + + seq->count = 0; + seq->docs = nil; + + error = sa_openxml(&parser, stm, 0); + if (error) + goto cleanupseq; + + item = sa_xmlnext(parser); + while (item) + { + if (!strcmp(sa_xmlname(item), "FixedDocumentSequence")) + { + sa_xmldown(parser); + item = sa_xmlnext(parser); + while (item) + { + if (!strcmp(sa_xmlname(item), "DocumentReference")) + { + char *src = sa_xmlatt(item, "Source"); + if (src) + { + sa_resolvepath(buf, part, src, sizeof buf); + error = sa_loadfixdoc(&doc, pack, buf); + if (error) + goto cleanupxml; + if (last) + last->next = doc; + else + seq->docs = doc; + seq->count += doc->count; + last = doc; + } + } + item = sa_xmlnext(parser); + } + sa_xmlup(parser); + } + item = sa_xmlnext(parser); + } + + sa_closexml(parser); + fz_dropstream(stm); + *seqp = seq; + return nil; + +cleanupxml: + sa_closexml(parser); +cleanupseq: + sa_dropfixdocseq(seq); +cleanupstm: + fz_dropstream(stm); + return error; +} + +/* + * Accessors + */ + +int +sa_getpagecount(sa_fixdocseq *seq) +{ + return seq->count; +} + +char * +sa_getpagepart(sa_fixdocseq *seq, int idx) +{ + sa_fixdoc *doc = seq->docs; + int cur = 0; + + if (idx < 0 || idx >= seq->count) + return nil; + + while (doc) + { + sa_fixpage *page = doc->pages; + while (page) + { + if (idx == cur) + return page->part; + page = page->next; + cur ++; + } + doc = doc->next; + } + + return nil; +} + diff --git a/samus/sa_misc.c b/samus/sa_misc.c index 109e3693..0f71b4a2 100644 --- a/samus/sa_misc.c +++ b/samus/sa_misc.c @@ -2,6 +2,32 @@ #include "samus.h" /* + * Create a new canonical absolute path given both + * a base url (current directory) and a relative or absolute name. + */ +char * +sa_resolvepath(char *dst, char *baseurl, char *parturl, int dstlen) +{ + char *end; + + if (parturl[0] == '/') + { + strlcpy(dst, parturl, dstlen); + } + else + { + strlcpy(dst, baseurl, dstlen); + end = strrchr(dst, '/'); + if (end) + end[1] = 0; + strlcat(dst, parturl, dstlen); + cleanname(dst); + } + + return dst; +} + +/* * Test part names for equivalence. * * What we *should* do here (according to the spec) is... diff --git a/samus/sa_pack.c b/samus/sa_pack.c index 74640ebd..4c65ba38 100644 --- a/samus/sa_pack.c +++ b/samus/sa_pack.c @@ -215,16 +215,20 @@ sa_debugpackage(sa_package *pack) sa_default *def; sa_override *ovr; - printf("package {\n"); + printf("package\n{\n"); if (pack->zip) sa_debugzip(pack->zip); + printf(" defaults\n {\n"); for (def = pack->defaults; def; def = def->next) - printf("default %s %s ;\n", def->extension, def->mimetype); + printf(" %-8s %s\n", def->extension, def->mimetype); + printf(" }\n"); + printf(" overrides\n {\n"); for (ovr = pack->overrides; ovr; ovr = ovr->next) - printf("override %s %s ;\n", ovr->partname, ovr->mimetype); + printf(" %s\n %s\n", ovr->partname, ovr->mimetype); + printf(" }\n"); printf("}\n"); } @@ -256,6 +260,7 @@ sa_loadrelations(sa_relation **relsp, sa_package *pack, char *partname) int len; char *sep; char *relsname; + char buf[1024]; if (partname[0] != '/') return fz_throw("ioerror: invalid part name: %s", partname); @@ -318,9 +323,15 @@ sa_loadrelations(sa_relation **relsp, sa_package *pack, char *partname) if (!newrel) { error = fz_outofmem; goto cleanupxml; } newrel->external = !strcmp(mode, "External"); newrel->id = fz_strdup(id); - newrel->target = fz_strdup(target); newrel->type = fz_strdup(type); newrel->next = rels; + if (newrel->external) + newrel->target = fz_strdup(target); + else + { + sa_resolvepath(buf, partname, target, sizeof buf); + newrel->target = fz_strdup(buf); + } rels = newrel; } } @@ -349,12 +360,14 @@ cleanupname: void sa_debugrelations(sa_relation *rel) { + printf("relations\n{\n"); while (rel) { - printf("relation %s\n", rel->type); - printf(" %s%s\n", rel->external ? "external " : "", rel->target); + printf(" %s\n", rel->type); + printf(" %s%s\n", rel->external ? "external " : "", rel->target); rel = rel->next; } + printf("}\n"); } void |