Mercurial > libavformat.hg
comparison http.c @ 5879:61062082488b libavformat
Split out http authentication handling into a separate file
This prepares for adding support for more authentication methods
author | mstorsjo |
---|---|
date | Wed, 24 Mar 2010 22:32:05 +0000 |
parents | d605f589f0be |
children | 7fdda2416684 |
comparison
equal
deleted
inserted
replaced
5878:01b33a7f96ee | 5879:61062082488b |
---|---|
17 * You should have received a copy of the GNU Lesser General Public | 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 | 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 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 */ | 20 */ |
21 | 21 |
22 #include "libavutil/base64.h" | |
23 #include "libavutil/avstring.h" | 22 #include "libavutil/avstring.h" |
24 #include "avformat.h" | 23 #include "avformat.h" |
25 #include <unistd.h> | 24 #include <unistd.h> |
26 #include <strings.h> | 25 #include <strings.h> |
27 #include "internal.h" | 26 #include "internal.h" |
28 #include "network.h" | 27 #include "network.h" |
29 #include "os_support.h" | 28 #include "os_support.h" |
29 #include "httpauth.h" | |
30 | 30 |
31 /* XXX: POST protocol is not completely implemented because ffmpeg uses | 31 /* XXX: POST protocol is not completely implemented because ffmpeg uses |
32 only a subset of it. */ | 32 only a subset of it. */ |
33 | 33 |
34 /* used for protocol handling */ | 34 /* used for protocol handling */ |
42 int line_count; | 42 int line_count; |
43 int http_code; | 43 int http_code; |
44 int64_t chunksize; /**< Used if "Transfer-Encoding: chunked" otherwise -1. */ | 44 int64_t chunksize; /**< Used if "Transfer-Encoding: chunked" otherwise -1. */ |
45 int64_t off, filesize; | 45 int64_t off, filesize; |
46 char location[URL_SIZE]; | 46 char location[URL_SIZE]; |
47 HTTPAuthState auth_state; | |
47 } HTTPContext; | 48 } HTTPContext; |
48 | 49 |
49 static int http_connect(URLContext *h, const char *path, const char *hoststr, | 50 static int http_connect(URLContext *h, const char *path, const char *hoststr, |
50 const char *auth, int *new_location); | 51 const char *auth, int *new_location); |
51 static int http_write(URLContext *h, uint8_t *buf, int size); | 52 static int http_write(URLContext *h, uint8_t *buf, int size); |
58 char hostname[1024], hoststr[1024]; | 59 char hostname[1024], hoststr[1024]; |
59 char auth[1024]; | 60 char auth[1024]; |
60 char path1[1024]; | 61 char path1[1024]; |
61 char buf[1024]; | 62 char buf[1024]; |
62 int port, use_proxy, err, location_changed = 0, redirects = 0; | 63 int port, use_proxy, err, location_changed = 0, redirects = 0; |
64 HTTPAuthType cur_auth_type; | |
63 HTTPContext *s = h->priv_data; | 65 HTTPContext *s = h->priv_data; |
64 URLContext *hd = NULL; | 66 URLContext *hd = NULL; |
65 | 67 |
66 proxy_path = getenv("http_proxy"); | 68 proxy_path = getenv("http_proxy"); |
67 use_proxy = (proxy_path != NULL) && !getenv("no_proxy") && | 69 use_proxy = (proxy_path != NULL) && !getenv("no_proxy") && |
91 err = url_open(&hd, buf, URL_RDWR); | 93 err = url_open(&hd, buf, URL_RDWR); |
92 if (err < 0) | 94 if (err < 0) |
93 goto fail; | 95 goto fail; |
94 | 96 |
95 s->hd = hd; | 97 s->hd = hd; |
98 cur_auth_type = s->auth_state.auth_type; | |
96 if (http_connect(h, path, hoststr, auth, &location_changed) < 0) | 99 if (http_connect(h, path, hoststr, auth, &location_changed) < 0) |
97 goto fail; | 100 goto fail; |
101 if (s->http_code == 401) { | |
102 if (cur_auth_type == HTTP_AUTH_NONE && s->auth_state.auth_type != HTTP_AUTH_NONE) { | |
103 url_close(hd); | |
104 goto redo; | |
105 } else | |
106 goto fail; | |
107 } | |
98 if ((s->http_code == 302 || s->http_code == 303) && location_changed == 1) { | 108 if ((s->http_code == 302 || s->http_code == 303) && location_changed == 1) { |
99 /* url moved, get next */ | 109 /* url moved, get next */ |
100 url_close(hd); | 110 url_close(hd); |
101 if (redirects++ >= MAX_REDIRECTS) | 111 if (redirects++ >= MAX_REDIRECTS) |
102 return AVERROR(EIO); | 112 return AVERROR(EIO); |
123 } | 133 } |
124 h->priv_data = s; | 134 h->priv_data = s; |
125 s->filesize = -1; | 135 s->filesize = -1; |
126 s->chunksize = -1; | 136 s->chunksize = -1; |
127 s->off = 0; | 137 s->off = 0; |
138 memset(&s->auth_state, 0, sizeof(s->auth_state)); | |
128 av_strlcpy(s->location, uri, URL_SIZE); | 139 av_strlcpy(s->location, uri, URL_SIZE); |
129 | 140 |
130 ret = http_open_cnx(h); | 141 ret = http_open_cnx(h); |
131 if (ret != 0) | 142 if (ret != 0) |
132 av_free (s); | 143 av_free (s); |
191 p++; | 202 p++; |
192 s->http_code = strtol(p, NULL, 10); | 203 s->http_code = strtol(p, NULL, 10); |
193 | 204 |
194 dprintf(NULL, "http_code=%d\n", s->http_code); | 205 dprintf(NULL, "http_code=%d\n", s->http_code); |
195 | 206 |
196 /* error codes are 4xx and 5xx */ | 207 /* error codes are 4xx and 5xx, but regard 401 as a success, so we |
197 if (s->http_code >= 400 && s->http_code < 600) | 208 * don't abort until all headers have been parsed. */ |
209 if (s->http_code >= 400 && s->http_code < 600 && s->http_code != 401) | |
198 return -1; | 210 return -1; |
199 } else { | 211 } else { |
200 while (*p != '\0' && *p != ':') | 212 while (*p != '\0' && *p != ':') |
201 p++; | 213 p++; |
202 if (*p != ':') | 214 if (*p != ':') |
223 } | 235 } |
224 h->is_streamed = 0; /* we _can_ in fact seek */ | 236 h->is_streamed = 0; /* we _can_ in fact seek */ |
225 } else if (!strcmp (tag, "Transfer-Encoding") && !strncasecmp(p, "chunked", 7)) { | 237 } else if (!strcmp (tag, "Transfer-Encoding") && !strncasecmp(p, "chunked", 7)) { |
226 s->filesize = -1; | 238 s->filesize = -1; |
227 s->chunksize = 0; | 239 s->chunksize = 0; |
240 } else if (!strcmp (tag, "WWW-Authenticate")) { | |
241 ff_http_auth_handle_header(&s->auth_state, tag, p); | |
242 } else if (!strcmp (tag, "Authentication-Info")) { | |
243 ff_http_auth_handle_header(&s->auth_state, tag, p); | |
228 } | 244 } |
229 } | 245 } |
230 return 1; | 246 return 1; |
231 } | 247 } |
232 | 248 |
234 const char *auth, int *new_location) | 250 const char *auth, int *new_location) |
235 { | 251 { |
236 HTTPContext *s = h->priv_data; | 252 HTTPContext *s = h->priv_data; |
237 int post, err; | 253 int post, err; |
238 char line[1024]; | 254 char line[1024]; |
239 char *auth_b64; | 255 char *authstr = NULL; |
240 int auth_b64_len = (strlen(auth) + 2) / 3 * 4 + 1; | |
241 int64_t off = s->off; | 256 int64_t off = s->off; |
242 | 257 |
243 | 258 |
244 /* send http header */ | 259 /* send http header */ |
245 post = h->flags & URL_WRONLY; | 260 post = h->flags & URL_WRONLY; |
246 auth_b64 = av_malloc(auth_b64_len); | 261 authstr = ff_http_auth_create_response(&s->auth_state, auth, path, |
247 av_base64_encode(auth_b64, auth_b64_len, auth, strlen(auth)); | 262 post ? "POST" : "GET"); |
248 snprintf(s->buffer, sizeof(s->buffer), | 263 snprintf(s->buffer, sizeof(s->buffer), |
249 "%s %s HTTP/1.1\r\n" | 264 "%s %s HTTP/1.1\r\n" |
250 "User-Agent: %s\r\n" | 265 "User-Agent: %s\r\n" |
251 "Accept: */*\r\n" | 266 "Accept: */*\r\n" |
252 "Range: bytes=%"PRId64"-\r\n" | 267 "Range: bytes=%"PRId64"-\r\n" |
253 "Host: %s\r\n" | 268 "Host: %s\r\n" |
254 "Authorization: Basic %s\r\n" | 269 "%s" |
255 "Connection: close\r\n" | 270 "Connection: close\r\n" |
256 "%s" | 271 "%s" |
257 "\r\n", | 272 "\r\n", |
258 post ? "POST" : "GET", | 273 post ? "POST" : "GET", |
259 path, | 274 path, |
260 LIBAVFORMAT_IDENT, | 275 LIBAVFORMAT_IDENT, |
261 s->off, | 276 s->off, |
262 hoststr, | 277 hoststr, |
263 auth_b64, | 278 authstr ? authstr : "", |
264 post ? "Transfer-Encoding: chunked\r\n" : ""); | 279 post ? "Transfer-Encoding: chunked\r\n" : ""); |
265 | 280 |
266 av_freep(&auth_b64); | 281 av_freep(&authstr); |
267 if (http_write(h, s->buffer, strlen(s->buffer)) < 0) | 282 if (http_write(h, s->buffer, strlen(s->buffer)) < 0) |
268 return AVERROR(EIO); | 283 return AVERROR(EIO); |
269 | 284 |
270 /* init input buffer */ | 285 /* init input buffer */ |
271 s->buf_ptr = s->buffer; | 286 s->buf_ptr = s->buffer; |