summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2005-06-04 22:40:20 +0200
committerTor Andersson <tor@ghostscript.com>2005-06-04 22:40:20 +0200
commit7560c64207af372f7d75763285a6e955d3e68486 (patch)
tree18a05e892eeca41ba6d4c3c7f71e51154cbdfce3
parent7c7a2ed5417f36780da11299ed463d8861cad762 (diff)
downloadmupdf-7560c64207af372f7d75763285a6e955d3e68486.tar.xz
fixed document sequence parsing
-rw-r--r--apps/samshow.c40
-rw-r--r--base/Jamfile1
-rw-r--r--base/base_cleanname.c52
-rw-r--r--include/fitz/runtime.h2
-rw-r--r--include/samus.h3
-rw-r--r--include/samus/fixdoc.h13
-rw-r--r--include/samus/misc.h1
-rw-r--r--include/samus/names.h96
-rw-r--r--samus/Jamfile4
-rw-r--r--samus/sa_fixdoc.c327
-rw-r--r--samus/sa_misc.c26
-rw-r--r--samus/sa_pack.c25
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