Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7643 views
1
#include "mupdf/xps.h"
2
3
static inline int xps_tolower(int c)
4
{
5
if (c >= 'A' && c <= 'Z')
6
return c + 32;
7
return c;
8
}
9
10
int
11
xps_strcasecmp(char *a, char *b)
12
{
13
while (xps_tolower(*a) == xps_tolower(*b))
14
{
15
if (*a++ == 0)
16
return 0;
17
b++;
18
}
19
return xps_tolower(*a) - xps_tolower(*b);
20
}
21
22
/* A URL is defined as consisting of a:
23
* SCHEME (e.g. http:)
24
* AUTHORITY (username, password, hostname, port, eg //test:[email protected]:999)
25
* PATH (e.g. /download)
26
* QUERY (e.g. ?view=page)
27
* FRAGMENT (e.g. #fred) (not strictly part of the URL)
28
*/
29
static char *
30
skip_scheme(char *path)
31
{
32
char *p = path;
33
34
/* Skip over: alpha *(alpha | digit | "+" | "-" | ".") looking for : */
35
if (*p >= 'a' && *p <= 'z')
36
{}
37
else if (*p >= 'A' && *p <= 'Z')
38
{}
39
else
40
return path;
41
42
while (*++p)
43
{
44
if (*p >= 'a' && *p <= 'z')
45
{}
46
else if (*p >= 'A' && *p <= 'Z')
47
{}
48
else if (*p >= '0' && *p <= '9')
49
{}
50
else if (*p == '+')
51
{}
52
else if (*p == '-')
53
{}
54
else if (*p == '.')
55
{}
56
else if (*p == ':')
57
return p+1;
58
else
59
break;
60
}
61
return path;
62
}
63
64
static char *
65
skip_authority(char *path)
66
{
67
char *p = path;
68
69
/* Authority section must start with '//' */
70
if (p[0] != '/' || p[1] != '/')
71
return path;
72
p += 2;
73
74
/* Authority is terminated by end of URL, '/' or '?' */
75
while (*p && *p != '/' && *p != '?')
76
p++;
77
78
return p;
79
}
80
81
#define SEP(x) ((x)=='/' || (x) == 0)
82
83
static char *
84
clean_path(char *name)
85
{
86
char *p, *q, *dotdot, *start;
87
int rooted;
88
89
start = skip_scheme(name);
90
start = skip_authority(start);
91
rooted = start[0] == '/';
92
93
/*
94
* invariants:
95
* p points at beginning of path element we're considering.
96
* q points just past the last path element we wrote (no slash).
97
* dotdot points just past the point where .. cannot backtrack
98
* any further (no slash).
99
*/
100
p = q = dotdot = start + rooted;
101
while (*p)
102
{
103
if(p[0] == '/') /* null element */
104
p++;
105
else if (p[0] == '.' && SEP(p[1]))
106
p += 1; /* don't count the separator in case it is nul */
107
else if (p[0] == '.' && p[1] == '.' && SEP(p[2]))
108
{
109
p += 2;
110
if (q > dotdot) /* can backtrack */
111
{
112
while(--q > dotdot && *q != '/')
113
;
114
}
115
else if (!rooted) /* /.. is / but ./../ is .. */
116
{
117
if (q != start)
118
*q++ = '/';
119
*q++ = '.';
120
*q++ = '.';
121
dotdot = q;
122
}
123
}
124
else /* real path element */
125
{
126
if (q != start+rooted)
127
*q++ = '/';
128
while ((*q = *p) != '/' && *q != 0)
129
p++, q++;
130
}
131
}
132
133
if (q == start) /* empty string is really "." */
134
*q++ = '.';
135
*q = '\0';
136
137
return name;
138
}
139
140
void
141
xps_resolve_url(fz_context *ctx, xps_document *doc, char *output, char *base_uri, char *path, int output_size)
142
{
143
char *p = skip_authority(skip_scheme(path));
144
145
if (p != path || path[0] == '/')
146
{
147
fz_strlcpy(output, path, output_size);
148
}
149
else
150
{
151
int len = fz_strlcpy(output, base_uri, output_size);
152
if (len == 0 || output[len-1] != '/')
153
fz_strlcat(output, "/", output_size);
154
fz_strlcat(output, path, output_size);
155
}
156
clean_path(output);
157
}
158
159
int
160
xps_url_is_remote(fz_context *ctx, xps_document *doc, char *path)
161
{
162
return path != skip_authority(skip_scheme(path));
163
}
164
165