summaryrefslogtreecommitdiff
path: root/xps/xps_util.c
diff options
context:
space:
mode:
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;
+}