]> git.sesse.net Git - ffmpeg/blob - libavformat/url.c
hwcontext_vulkan: remove plane size alignment checks when host importing
[ffmpeg] / libavformat / url.c
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
23 #include "avformat.h"
24 #include "internal.h"
25 #include "config.h"
26 #include "url.h"
27 #if CONFIG_NETWORK
28 #include "network.h"
29 #endif
30 #include "libavutil/avstring.h"
31
32 /**
33  * @file
34  * URL utility functions.
35  */
36
37 int ff_url_join(char *str, int size, const char *proto,
38                 const char *authorization, const char *hostname,
39                 int port, const char *fmt, ...)
40 {
41 #if CONFIG_NETWORK
42     struct addrinfo hints = { 0 }, *ai;
43 #endif
44
45     str[0] = '\0';
46     if (proto)
47         av_strlcatf(str, size, "%s://", proto);
48     if (authorization && authorization[0])
49         av_strlcatf(str, size, "%s@", authorization);
50 #if CONFIG_NETWORK && defined(AF_INET6)
51     /* Determine if hostname is a numerical IPv6 address,
52      * properly escape it within [] in that case. */
53     hints.ai_flags = AI_NUMERICHOST;
54     if (!getaddrinfo(hostname, NULL, &hints, &ai)) {
55         if (ai->ai_family == AF_INET6) {
56             av_strlcat(str, "[", size);
57             av_strlcat(str, hostname, size);
58             av_strlcat(str, "]", size);
59         } else {
60             av_strlcat(str, hostname, size);
61         }
62         freeaddrinfo(ai);
63     } else
64 #endif
65         /* Not an IPv6 address, just output the plain string. */
66         av_strlcat(str, hostname, size);
67
68     if (port >= 0)
69         av_strlcatf(str, size, ":%d", port);
70     if (fmt) {
71         va_list vl;
72         size_t len = strlen(str);
73
74         va_start(vl, fmt);
75         vsnprintf(str + len, size > len ? size - len : 0, fmt, vl);
76         va_end(vl);
77     }
78     return strlen(str);
79 }
80
81 static void trim_double_dot_url(char *buf, const char *rel, int size)
82 {
83     const char *p = rel;
84     const char *root = rel;
85     char tmp_path[MAX_URL_SIZE] = {0, };
86     char *sep;
87     char *node;
88
89     /* Get the path root of the url which start by "://" */
90     if (p && (sep = strstr(p, "://"))) {
91         sep += 3;
92         root = strchr(sep, '/');
93         if (!root)
94             return;
95     }
96
97     /* set new current position if the root node is changed */
98     p = root;
99     while (p && (node = strstr(p, ".."))) {
100         av_strlcat(tmp_path, p, node - p + strlen(tmp_path));
101         p = node + 3;
102         sep = strrchr(tmp_path, '/');
103         if (sep)
104             sep[0] = '\0';
105         else
106             tmp_path[0] = '\0';
107     }
108
109     if (!av_stristart(p, "/", NULL) && root != rel)
110         av_strlcat(tmp_path, "/", size);
111
112     av_strlcat(tmp_path, p, size);
113     /* start set buf after temp path process. */
114     av_strlcpy(buf, rel, root - rel + 1);
115
116     if (!av_stristart(tmp_path, "/", NULL) && root != rel)
117         av_strlcat(buf, "/", size);
118
119     av_strlcat(buf, tmp_path, size);
120 }
121
122 void ff_make_absolute_url(char *buf, int size, const char *base,
123                           const char *rel)
124 {
125     char *sep, *path_query;
126     char *root, *p;
127     char tmp_path[MAX_URL_SIZE];
128
129     memset(tmp_path, 0, sizeof(tmp_path));
130     /* Absolute path, relative to the current server */
131     if (base && strstr(base, "://") && rel[0] == '/') {
132         if (base != buf)
133             av_strlcpy(buf, base, size);
134         sep = strstr(buf, "://");
135         if (sep) {
136             /* Take scheme from base url */
137             if (rel[1] == '/') {
138                 sep[1] = '\0';
139             } else {
140                 /* Take scheme and host from base url */
141                 sep += 3;
142                 sep = strchr(sep, '/');
143                 if (sep)
144                     *sep = '\0';
145             }
146         }
147         av_strlcat(buf, rel, size);
148         trim_double_dot_url(tmp_path, buf, size);
149         memset(buf, 0, size);
150         av_strlcpy(buf, tmp_path, size);
151         return;
152     }
153     /* If rel actually is an absolute url, just copy it */
154     if (!base || strstr(rel, "://") || rel[0] == '/') {
155         memset(buf, 0, size);
156         trim_double_dot_url(buf, rel, size);
157         return;
158     }
159     if (base != buf)
160         av_strlcpy(buf, base, size);
161
162     /* Strip off any query string from base */
163     path_query = strchr(buf, '?');
164     if (path_query)
165         *path_query = '\0';
166
167     /* Is relative path just a new query part? */
168     if (rel[0] == '?') {
169         av_strlcat(buf, rel, size);
170         trim_double_dot_url(tmp_path, buf, size);
171         memset(buf, 0, size);
172         av_strlcpy(buf, tmp_path, size);
173         return;
174     }
175
176     root = p = buf;
177     /* Get the path root of the url which start by "://" */
178     if (p && strstr(p, "://")) {
179         sep = strstr(p, "://");
180         if (sep) {
181             sep += 3;
182             root = strchr(sep, '/');
183             if (!root)
184                 return;
185         }
186     }
187
188     /* Remove the file name from the base url */
189     sep = strrchr(buf, '/');
190     if (sep && sep <= root)
191         sep = root;
192
193     if (sep)
194         sep[1] = '\0';
195     else
196         buf[0] = '\0';
197     while (av_strstart(rel, "..", NULL) && sep) {
198         /* Remove the path delimiter at the end */
199         if (sep > root) {
200             sep[0] = '\0';
201             sep = strrchr(buf, '/');
202         }
203
204         /* If the next directory name to pop off is "..", break here */
205         if (!strcmp(sep ? &sep[1] : buf, "..")) {
206             /* Readd the slash we just removed */
207             av_strlcat(buf, "/", size);
208             break;
209         }
210         /* Cut off the directory name */
211         if (sep)
212             sep[1] = '\0';
213         else
214             buf[0] = '\0';
215         rel += 3;
216     }
217     av_strlcat(buf, rel, size);
218     trim_double_dot_url(tmp_path, buf, size);
219     memset(buf, 0, size);
220     av_strlcpy(buf, tmp_path, size);
221 }
222
223 AVIODirEntry *ff_alloc_dir_entry(void)
224 {
225     AVIODirEntry *entry = av_mallocz(sizeof(AVIODirEntry));
226     if (entry) {
227         entry->type = AVIO_ENTRY_UNKNOWN;
228         entry->size = -1;
229         entry->modification_timestamp = -1;
230         entry->access_timestamp = -1;
231         entry->status_change_timestamp = -1;
232         entry->user_id = -1;
233         entry->group_id = -1;
234         entry->filemode = -1;
235     }
236     return entry;
237 }