summaryrefslogtreecommitdiff
path: root/xps/xps_util.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-02-02 16:18:13 +0000
committerRobin Watts <robin.watts@artifex.com>2012-02-02 17:21:20 +0000
commitbb1e3c973526e66024e1a3260255368034cb2008 (patch)
tree9102d5d22818788e88c6407a0e4a358dfa7011b5 /xps/xps_util.c
parent4ab5924753d32b5eaeb80138c6626057f61b516f (diff)
downloadmupdf-bb1e3c973526e66024e1a3260255368034cb2008.tar.xz
Support remote links in XPS documents.
Update xps path handling to cope with URLs. Fix premature freeing of links. Spot remote URLs and use appropriate link type.
Diffstat (limited to 'xps/xps_util.c')
-rw-r--r--xps/xps_util.c97
1 files changed, 83 insertions, 14 deletions
diff --git a/xps/xps_util.c b/xps/xps_util.c
index 6af4da91..5a3b1fbf 100644
--- a/xps/xps_util.c
+++ b/xps/xps_util.c
@@ -20,15 +20,77 @@ xps_strcasecmp(char *a, char *b)
return xps_tolower(*a) - xps_tolower(*b);
}
+/* A URL is defined as consisting of a:
+ * SCHEME (e.g. http:)
+ * AUTHORITY (username, password, hostname, port, eg //test:passwd@mupdf.com:999)
+ * PATH (e.g. /download)
+ * QUERY (e.g. ?view=page)
+ * FRAGMENT (e.g. #fred) (not strictly part of the URL)
+ */
+static char *
+skip_scheme(char *path)
+{
+ char *p = path;
+
+ /* Skip over: alpha *(alpha | digit | "+" | "-" | ".") looking for : */
+ if (*p >= 'a' && *p <= 'z')
+ {}
+ else if (*p >= 'A' && *p <= 'Z')
+ {}
+ else
+ return path;
+
+ while (*++p)
+ {
+ if (*p >= 'a' && *p <= 'z')
+ {}
+ else if (*p >= 'A' && *p <= 'Z')
+ {}
+ else if (*p >= '0' && *p <= '9')
+ {}
+ else if (*p == '+')
+ {}
+ else if (*p == '-')
+ {}
+ else if (*p == '.')
+ {}
+ else if (*p == ':')
+ return p+1;
+ else
+ break;
+ }
+ return path;
+}
+
+static char *
+skip_authority(char *path)
+{
+ char *p = path;
+
+ /* Authority section must start with '//' */
+ if (p[0] != '/' || p[1] != '/')
+ return path;
+ p += 2;
+
+ /* Authority is terminated by end of URL, '/' or '?' */
+ while (*p && *p != '/' && *p != '?')
+ p++;
+
+ return p;
+}
+
+
#define SEP(x) ((x)=='/' || (x) == 0)
static char *
xps_clean_path(char *name)
{
- char *p, *q, *dotdot;
+ char *p, *q, *dotdot, *start;
int rooted;
- rooted = name[0] == '/';
+ start = skip_scheme(name);
+ start = skip_authority(start);
+ rooted = start[0] == '/';
/*
* invariants:
@@ -37,7 +99,7 @@ xps_clean_path(char *name)
* dotdot points just past the point where .. cannot backtrack
* any further (no slash).
*/
- p = q = dotdot = name + rooted;
+ p = q = dotdot = start + rooted;
while (*p)
{
if(p[0] == '/') /* null element */
@@ -54,7 +116,7 @@ xps_clean_path(char *name)
}
else if (!rooted) /* /.. is / but ./../ is .. */
{
- if (q != name)
+ if (q != start)
*q++ = '/';
*q++ = '.';
*q++ = '.';
@@ -63,36 +125,43 @@ xps_clean_path(char *name)
}
else /* real path element */
{
- if (q != name+rooted)
+ if (q != start+rooted)
*q++ = '/';
while ((*q = *p) != '/' && *q != 0)
p++, q++;
}
}
- if (q == name) /* empty string is really "." */
+ if (q == start) /* empty string is really "." */
*q++ = '.';
*q = '\0';
return name;
}
-/* RJW: Possible problems here:
- * "/foo" + "../../bar" = "/bar" not "../bar"
- * "http://something/" + ... doesn't work.
- */
void
-xps_absolute_path(char *output, char *base_uri, char *path, int output_size)
+xps_resolve_url(char *output, char *base_uri, char *path, int output_size)
{
- if (path[0] == '/')
+ char *p = skip_authority(skip_scheme(path));
+
+ if (p != path || path[0] == '/')
{
fz_strlcpy(output, path, output_size);
}
else
{
- fz_strlcpy(output, base_uri, output_size);
- fz_strlcat(output, "/", output_size);
+ int len = fz_strlcpy(output, base_uri, output_size);
+ if (len == 0 || output[len-1] != '/')
+ fz_strlcat(output, "/", output_size);
fz_strlcat(output, path, output_size);
}
xps_clean_path(output);
}
+
+int
+xps_url_is_remote(char *path)
+{
+ char *p = skip_authority(skip_scheme(path));
+
+ return p != path;
+}