]> git.sesse.net Git - ffmpeg/blob - libavformat/url.c
Fix packet_buffer memory leak in avformat_free_context
[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 "config.h"
25 #include "url.h"
26 #if CONFIG_NETWORK
27 #include "network.h"
28 #endif
29 #include "libavutil/avstring.h"
30
31 /**
32  * @file
33  * URL utility functions.
34  */
35
36 int ff_url_join(char *str, int size, const char *proto,
37                 const char *authorization, const char *hostname,
38                 int port, const char *fmt, ...)
39 {
40 #if CONFIG_NETWORK
41     struct addrinfo hints = { 0 }, *ai;
42 #endif
43
44     str[0] = '\0';
45     if (proto)
46         av_strlcatf(str, size, "%s://", proto);
47     if (authorization && authorization[0])
48         av_strlcatf(str, size, "%s@", authorization);
49 #if CONFIG_NETWORK && defined(AF_INET6)
50     /* Determine if hostname is a numerical IPv6 address,
51      * properly escape it within [] in that case. */
52     hints.ai_flags = AI_NUMERICHOST;
53     if (!getaddrinfo(hostname, NULL, &hints, &ai)) {
54         if (ai->ai_family == AF_INET6) {
55             av_strlcat(str, "[", size);
56             av_strlcat(str, hostname, size);
57             av_strlcat(str, "]", size);
58         } else {
59             av_strlcat(str, hostname, size);
60         }
61         freeaddrinfo(ai);
62     } else
63 #endif
64         /* Not an IPv6 address, just output the plain string. */
65         av_strlcat(str, hostname, size);
66
67     if (port >= 0)
68         av_strlcatf(str, size, ":%d", port);
69     if (fmt) {
70         va_list vl;
71         int len = strlen(str);
72
73         va_start(vl, fmt);
74         vsnprintf(str + len, size > len ? size - len : 0, fmt, vl);
75         va_end(vl);
76     }
77     return strlen(str);
78 }
79
80 void ff_make_absolute_url(char *buf, int size, const char *base,
81                           const char *rel)
82 {
83     char *sep, *path_query;
84     /* Absolute path, relative to the current server */
85     if (base && strstr(base, "://") && rel[0] == '/') {
86         if (base != buf)
87             av_strlcpy(buf, base, size);
88         sep = strstr(buf, "://");
89         if (sep) {
90             /* Take scheme from base url */
91             if (rel[1] == '/') {
92                 sep[1] = '\0';
93             } else {
94                 /* Take scheme and host from base url */
95                 sep += 3;
96                 sep = strchr(sep, '/');
97                 if (sep)
98                     *sep = '\0';
99             }
100         }
101         av_strlcat(buf, rel, size);
102         return;
103     }
104     /* If rel actually is an absolute url, just copy it */
105     if (!base || strstr(rel, "://") || rel[0] == '/') {
106         av_strlcpy(buf, rel, size);
107         return;
108     }
109     if (base != buf)
110         av_strlcpy(buf, base, size);
111
112     /* Strip off any query string from base */
113     path_query = strchr(buf, '?');
114     if (path_query != NULL)
115         *path_query = '\0';
116
117     /* Is relative path just a new query part? */
118     if (rel[0] == '?') {
119         av_strlcat(buf, rel, size);
120         return;
121     }
122
123     /* Remove the file name from the base url */
124     sep = strrchr(buf, '/');
125     if (sep)
126         sep[1] = '\0';
127     else
128         buf[0] = '\0';
129     while (av_strstart(rel, "../", NULL) && sep) {
130         /* Remove the path delimiter at the end */
131         sep[0] = '\0';
132         sep = strrchr(buf, '/');
133         /* If the next directory name to pop off is "..", break here */
134         if (!strcmp(sep ? &sep[1] : buf, "..")) {
135             /* Readd the slash we just removed */
136             av_strlcat(buf, "/", size);
137             break;
138         }
139         /* Cut off the directory name */
140         if (sep)
141             sep[1] = '\0';
142         else
143             buf[0] = '\0';
144         rel += 3;
145     }
146     av_strlcat(buf, rel, size);
147 }