+
+ /* path */
+ uc->path = cur;
+ cur = find_delim("?#", cur, end);
+
+ /* query */
+ uc->query = cur;
+ if (*cur == '?')
+ cur = find_delim("#", cur, end);
+
+ /* fragment */
+ uc->fragment = cur;
+
+ uc->end = end;
+ return 0;
+}
+
+static int is_fq_dos_path(const char *path)
+{
+ if ((path[0] >= 'a' && path[0] <= 'z' || path[0] >= 'A' && path[0] <= 'Z') &&
+ path[1] == ':' &&
+ (path[2] == '/' || path[2] == '\\'))
+ return 1;
+ if ((path[0] == '/' || path[0] == '\\') &&
+ (path[1] == '/' || path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+static int append_path(char *root, char *out_end, char **rout,
+ const char *in, const char *in_end)
+{
+ char *out = *rout;
+ const char *d, *next;
+
+ if (in < in_end && *in == '/')
+ in++; /* already taken care of */
+ while (in < in_end) {
+ d = find_delim("/", in, in_end);
+ next = d + (d < in_end && *d == '/');
+ if (d - in == 1 && in[0] == '.') {
+ /* skip */
+ } else if (d - in == 2 && in[0] == '.' && in[1] == '.') {
+ av_assert1(out[-1] == '/');
+ if (out - root > 1)
+ while (out > root && (--out)[-1] != '/');
+ } else {
+ if (out_end - out < next - in)
+ return AVERROR(ENOMEM);
+ memmove(out, in, next - in);
+ out += next - in;
+ }
+ in = next;
+ }
+ *rout = out;
+ return 0;
+}
+
+int ff_make_absolute_url2(char *buf, int size, const char *base,
+ const char *rel, int handle_dos_paths)
+{
+ URLComponents ub, uc;
+ char *out, *out_end, *path;
+ const char *keep, *base_path_end;
+ int use_base_path, simplify_path = 0, ret;
+ const char *base_separators = "/";
+
+ /* This is tricky.
+ For HTTP, http://server/site/page + ../media/file
+ should resolve into http://server/media/file
+ but for filesystem access, dir/playlist + ../media/file
+ should resolve into dir/../media/file
+ because dir could be a symlink, and .. points to
+ the actual parent of the target directory.
+
+ We'll consider that URLs with an actual scheme and authority,
+ i.e. starting with scheme://, need parent dir simplification,
+ while bare paths or pseudo-URLs starting with proto: without
+ the double slash do not.
+
+ For real URLs, the processing is similar to the algorithm described
+ here:
+ https://tools.ietf.org/html/rfc3986#section-5
+ */
+
+ if (!size)
+ return AVERROR(ENOMEM);
+ out = buf;
+ out_end = buf + size - 1;
+
+ if (!base)
+ base = "";
+ if (handle_dos_paths) {
+ if ((ret = ff_url_decompose(&ub, base, NULL)) < 0)
+ goto error;
+ if (is_fq_dos_path(base) || av_strstart(base, "file:", NULL) || ub.path == ub.url) {
+ base_separators = "/\\";
+ if (is_fq_dos_path(rel))
+ base = "";
+ }