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  }
94 
95  /* set new current position if the root node is changed */
96  p = root;
97  while (p && (node = strstr(p, ".."))) {
98  av_strlcat(tmp_path, p, node - p + strlen(tmp_path));
99  p = node + 3;
100  sep = strrchr(tmp_path, '/');
101  if (sep)
102  sep[0] = '\0';
103  else
104  tmp_path[0] = '\0';
105  }
106 
107  if (!av_stristart(p, "/", NULL) && root != rel)
108  av_strlcat(tmp_path, "/", size);
109 
110  av_strlcat(tmp_path, p, size);
111  /* start set buf after temp path process. */
112  av_strlcpy(buf, rel, root - rel + 1);
113 
114  if (!av_stristart(tmp_path, "/", NULL) && root != rel)
115  av_strlcat(buf, "/", size);
116 
117  av_strlcat(buf, tmp_path, size);
118 }
119 
120 void ff_make_absolute_url(char *buf, int size, const char *base,
121  const char *rel)
122 {
123  char *sep, *path_query;
124  char *root, *p;
125  char tmp_path[MAX_URL_SIZE];
126 
127  memset(tmp_path, 0, sizeof(tmp_path));
128  /* Absolute path, relative to the current server */
129  if (base && strstr(base, "://") && rel[0] == '/') {
130  if (base != buf)
131  av_strlcpy(buf, base, size);
132  sep = strstr(buf, "://");
133  if (sep) {
134  /* Take scheme from base url */
135  if (rel[1] == '/') {
136  sep[1] = '\0';
137  } else {
138  /* Take scheme and host from base url */
139  sep += 3;
140  sep = strchr(sep, '/');
141  if (sep)
142  *sep = '\0';
143  }
144  }
145  av_strlcat(buf, rel, size);
146  trim_double_dot_url(tmp_path, buf, size);
147  memset(buf, 0, size);
148  av_strlcpy(buf, tmp_path, size);
149  return;
150  }
151  /* If rel actually is an absolute url, just copy it */
152  if (!base || strstr(rel, "://") || rel[0] == '/') {
153  trim_double_dot_url(buf, rel, size);
154  return;
155  }
156  if (base != buf)
157  av_strlcpy(buf, base, size);
158 
159  /* Strip off any query string from base */
160  path_query = strchr(buf, '?');
161  if (path_query)
162  *path_query = '\0';
163 
164  /* Is relative path just a new query part? */
165  if (rel[0] == '?') {
166  av_strlcat(buf, rel, size);
167  trim_double_dot_url(tmp_path, buf, size);
168  memset(buf, 0, size);
169  av_strlcpy(buf, tmp_path, size);
170  return;
171  }
172 
173  root = p = buf;
174  /* Get the path root of the url which start by "://" */
175  if (p && strstr(p, "://")) {
176  sep = strstr(p, "://");
177  if (sep) {
178  sep += 3;
179  root = strchr(sep, '/');
180  }
181  }
182 
183  /* Remove the file name from the base url */
184  sep = strrchr(buf, '/');
185  if (sep && sep <= root)
186  sep = root;
187 
188  if (sep)
189  sep[1] = '\0';
190  else
191  buf[0] = '\0';
192  while (av_strstart(rel, "..", NULL) && sep) {
193  /* Remove the path delimiter at the end */
194  if (sep > root) {
195  sep[0] = '\0';
196  sep = strrchr(buf, '/');
197  }
198 
199  /* If the next directory name to pop off is "..", break here */
200  if (!strcmp(sep ? &sep[1] : buf, "..")) {
201  /* Readd the slash we just removed */
202  av_strlcat(buf, "/", size);
203  break;
204  }
205  /* Cut off the directory name */
206  if (sep)
207  sep[1] = '\0';
208  else
209  buf[0] = '\0';
210  rel += 3;
211  }
212  av_strlcat(buf, rel, size);
213  trim_double_dot_url(tmp_path, buf, size);
214  memset(buf, 0, size);
215  av_strlcpy(buf, tmp_path, size);
216 }
217 
219 {
220  AVIODirEntry *entry = av_mallocz(sizeof(AVIODirEntry));
221  if (entry) {
222  entry->type = AVIO_ENTRY_UNKNOWN;
223  entry->size = -1;
224  entry->modification_timestamp = -1;
225  entry->access_timestamp = -1;
226  entry->status_change_timestamp = -1;
227  entry->user_id = -1;
228  entry->group_id = -1;
229  entry->filemode = -1;
230  }
231  return entry;
232 }
#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:120
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:218
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