FFmpeg
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 }
#define NULL
Definition: coverity.c:32
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
int64_t filemode
Unix file mode, -1 if unknown.
Definition: avio.h:100
Describes single entry of the directory.
Definition: avio.h:86
#define vsnprintf
Definition: snprintf.h:36
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
#define freeaddrinfo
Definition: network.h:218
#define AI_NUMERICHOST
Definition: network.h:187
uint8_t base
Definition: vp3data.h:202
#define MAX_URL_SIZE
Definition: internal.h:30
int64_t modification_timestamp
Time of last modification in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:92
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
ptrdiff_t size
Definition: opengl_enc.c:100
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
int64_t access_timestamp
Time of last access in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:94
static void trim_double_dot_url(char *buf, const char *rel, int size)
Definition: url.c:81
int64_t size
File size in bytes, -1 if unknown.
Definition: avio.h:91
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
int type
Type of the entry.
Definition: avio.h:88
int64_t group_id
Group ID of owner, -1 if unknown.
Definition: avio.h:99
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
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
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
#define getaddrinfo
Definition: network.h:217
Main libavformat public API header.
int64_t status_change_timestamp
Time of last status change in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:96
AVIODirEntry * ff_alloc_dir_entry(void)
Allocate directory entry with default values.
Definition: url.c:223
int len
int64_t user_id
User ID of owner, -1 if unknown.
Definition: avio.h:98
int ai_flags
Definition: network.h:138
unbuffered private I/O API