1 /*
2 * URL utility functions
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
25 #include "config.h"
27 #if CONFIG_NETWORK
29 #endif
32
33 /**
34 * @file
35 * URL utility functions.
36 */
37
39 const char *authorization, const char *hostname,
40 int port, const char *fmt, ...)
41 {
42 #if CONFIG_NETWORK
44 #endif
45
47 if (proto)
49 if (authorization && authorization[0])
51 #if CONFIG_NETWORK && defined(AF_INET6)
52 /* Determine if hostname is a numerical IPv6 address,
53 * properly escape it within [] in that case. */
56 if (ai->ai_family == AF_INET6) {
60 } else {
62 }
64 } else
65 #endif
66 /* Not an IPv6 address, just output the plain string. */
68
69 if (port >= 0)
71 if (fmt) {
72 va_list vl;
74
75 va_start(vl, fmt);
77 va_end(vl);
78 }
80 }
81
82 static const char *
find_delim(
const char *delim,
const char *cur,
const char *end)
83 {
84 while (cur < end && !strchr(delim, *cur))
85 cur++;
86 return cur;
87 }
88
90 {
91 const char *cur, *aend, *p;
92
94 if (!end)
95 end = url + strlen(url);
97
98 /* scheme */
100 p =
find_delim(
":/?#", cur, end);
/* lavf "schemes" can contain options but not some RFC 3986 delimiters */
101 if (*p == ':')
102 cur = p + 1;
103
104 /* authority */
106 if (end - cur >= 2 && cur[0] == '/' && cur[1] == '/') {
107 cur += 2;
109
110 /* userinfo */
113 if (*p == '@')
114 cur = p + 1;
115
116 /* host */
118 if (*cur == '[') { /* hello IPv6, thanks for using colons! */
120 if (*p != ']')
122 if (p + 1 < aend && p[1] != ':')
124 cur = p + 1;
125 } else {
127 }
128
129 /* port */
131 cur = aend;
132 } else {
134 }
135
136 /* path */
139
140 /* query */
142 if (*cur == '?')
144
145 /* fragment */
147
149 return 0;
150 }
151
153 {
154 if ((path[0] >= 'a' && path[0] <= 'z' || path[0] >= 'A' && path[0] <= 'Z') &&
155 path[1] == ':' &&
156 (path[2] == '/' || path[2] == '\\'))
157 return 1;
158 if ((path[0] == '/' || path[0] == '\\') &&
159 (path[1] == '/' || path[1] == '\\'))
160 return 1;
161 return 0;
162 }
163
165 const char *in, const char *in_end)
166 {
168 const char *
d, *next;
169
170 if (in < in_end && *in == '/')
171 in++; /* already taken care of */
172 while (in < in_end) {
174 next =
d + (
d < in_end && *
d ==
'/');
175 if (
d - in == 1 && in[0] ==
'.') {
176 /* skip */
177 }
else if (
d - in == 2 && in[0] ==
'.' && in[1] ==
'.') {
180 while (
out > root && (--
out)[-1] !=
'/');
181 } else {
182 if (out_end -
out < next - in)
184 memmove(
out, in, next - in);
186 }
187 in = next;
188 }
190 return 0;
191 }
192
194 const char *rel, int handle_dos_paths)
195 {
197 char *
out, *out_end, *path;
198 const char *keep, *base_path_end;
199 int use_base_path, simplify_path = 0,
ret;
200 const char *base_separators = "/";
201
202 /* This is tricky.
203 For HTTP, http://server/site/page + ../media/file
204 should resolve into http://server/media/file
205 but for filesystem access, dir/playlist + ../media/file
206 should resolve into dir/../media/file
207 because dir could be a symlink, and .. points to
208 the actual parent of the target directory.
209
210 We'll consider that URLs with an actual scheme and authority,
211 i.e. starting with scheme://, need parent dir simplification,
212 while bare paths or pseudo-URLs starting with proto: without
213 the double slash do not.
214
215 For real URLs, the processing is similar to the algorithm described
216 here:
217 https://tools.ietf.org/html/rfc3986#section-5
218 */
219
223 out_end = buf +
size - 1;
224
227 if (handle_dos_paths) {
231 base_separators = "/\\";
234 }
235 }
239
241 #define KEEP(component, also) do { \
242 if (uc.url_component_end_##component == uc.url && \
243 ub.url_component_end_##component > keep) { \
244 keep = ub.url_component_end_##component; \
245 also \
246 } \
247 } while (0)
249 KEEP(authority_full, simplify_path = 1;);
253 #undef KEEP
254 #define COPY(start, end) do { \
255 size_t len = end - start; \
256 if (len > out_end - out) { \
257 ret = AVERROR(ENOMEM); \
258 goto error; \
259 } \
260 memmove(out, start, len); \
261 out += len; \
262 } while (0)
265
268 use_base_path = 0;
270 use_base_path = 0;
271 if (use_base_path) {
272 base_path_end =
ub.url_component_end_path;
274 while (base_path_end >
ub.path && !strchr(base_separators, base_path_end[-1]))
275 base_path_end--;
276 }
278 simplify_path = 0;
280 simplify_path = 0;
282 simplify_path = 1;
283 /* No path at all, leave it */
285 simplify_path = 0;
286
287 if (simplify_path) {
288 const char *root = "/";
289 COPY(root, root + 1);
291 if (use_base_path) {
295 }
300 }
301 } else {
302 if (use_base_path)
303 COPY(
ub.path, base_path_end);
304 COPY(uc.
path, uc.url_component_end_path);
305 }
306
307 COPY(uc.url_component_end_path, uc.
end);
308 #undef COPY
310 return 0;
311
315 ret ==
AVERROR(EINVAL) ?
"syntax_error" :
"");
317 }
318
320 const char *rel)
321 {
323 }
324
326 {
328 if (entry) {
337 }
338 return entry;
339 }