FFmpeg  4.3
url.c
Go to the documentation of this file.
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 
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 }
AVIODirEntry::type
int type
Type of the entry.
Definition: avio.h:88
base
uint8_t base
Definition: vp3data.h:202
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
AVIO_ENTRY_UNKNOWN
@ AVIO_ENTRY_UNKNOWN
Definition: avio.h:67
AVIODirEntry::access_timestamp
int64_t access_timestamp
Time of last access in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:94
freeaddrinfo
#define freeaddrinfo
Definition: network.h:218
AVIODirEntry::modification_timestamp
int64_t modification_timestamp
Time of last modification in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:92
AI_NUMERICHOST
#define AI_NUMERICHOST
Definition: network.h:187
ff_url_join
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:37
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
av_stristart
int av_stristart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str independent of case.
Definition: avstring.c:45
internal.h
NULL
#define NULL
Definition: coverity.c:32
AVIODirEntry::size
int64_t size
File size in bytes, -1 if unknown.
Definition: avio.h:91
AVIODirEntry::group_id
int64_t group_id
Group ID of owner, -1 if unknown.
Definition: avio.h:99
AVIODirEntry::filemode
int64_t filemode
Unix file mode, -1 if unknown.
Definition: avio.h:100
size
int size
Definition: twinvq_data.h:11134
AVIODirEntry
Describes single entry of the directory.
Definition: avio.h:86
AVIODirEntry::status_change_timestamp
int64_t status_change_timestamp
Time of last status change in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:96
av_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
getaddrinfo
#define getaddrinfo
Definition: network.h:217
AVIODirEntry::user_id
int64_t user_id
User ID of owner, -1 if unknown.
Definition: avio.h:98
ff_alloc_dir_entry
AVIODirEntry * ff_alloc_dir_entry(void)
Allocate directory entry with default values.
Definition: url.c:223
trim_double_dot_url
static void trim_double_dot_url(char *buf, const char *rel, int size)
Definition: url.c:81
vsnprintf
#define vsnprintf
Definition: snprintf.h:36
url.h
len
int len
Definition: vorbis_enc_data.h:452
av_strlcat
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition: avstring.c:93
avformat.h
network.h
ff_make_absolute_url
void ff_make_absolute_url(char *buf, int size, const char *base, const char *rel)
Convert a relative url into an absolute url, given a base url.
Definition: url.c:122
MAX_URL_SIZE
#define MAX_URL_SIZE
Definition: internal.h:30
addrinfo::ai_flags
int ai_flags
Definition: network.h:138
config.h
convert_header.str
string str
Definition: convert_header.py:20
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
avstring.h
addrinfo
Definition: network.h:137