+ *rout = out;
+ return 0;
+}
+
+int ff_make_absolute_url(char *buf, int size, const char *base,
+ const char *rel)
+{
+ URLComponents ub, uc;
+ char *out, *out_end, *path;
+ const char *keep, *base_path_end;
+ int use_base_path, simplify_path = 0, ret;
+
+ /* 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 ((ret = ff_url_decompose(&ub, base, NULL)) < 0 ||
+ (ret = ff_url_decompose(&uc, rel, NULL)) < 0)
+ goto error;
+
+ keep = ub.url;
+#define KEEP(component, also) do { \
+ if (uc.url_component_end_##component == uc.url && \
+ ub.url_component_end_##component > keep) { \
+ keep = ub.url_component_end_##component; \
+ also \
+ } \
+ } while (0)
+ KEEP(scheme, );
+ KEEP(authority_full, simplify_path = 1;);
+ KEEP(path,);
+ KEEP(query,);
+ KEEP(fragment,);
+#undef KEEP
+#define COPY(start, end) do { \
+ size_t len = end - start; \
+ if (len > out_end - out) { \
+ ret = AVERROR(ENOMEM); \
+ goto error; \
+ } \
+ memmove(out, start, len); \
+ out += len; \
+ } while (0)
+ COPY(ub.url, keep);
+ COPY(uc.url, uc.path);
+
+ use_base_path = URL_COMPONENT_HAVE(ub, path) && keep <= ub.path;
+ if (uc.path > uc.url)
+ use_base_path = 0;
+ if (URL_COMPONENT_HAVE(uc, path) && uc.path[0] == '/')
+ use_base_path = 0;
+ if (use_base_path) {
+ base_path_end = ub.url_component_end_path;
+ if (URL_COMPONENT_HAVE(uc, path))
+ while (base_path_end > ub.path && base_path_end[-1] != '/')
+ base_path_end--;