diff options
author | Petr Doubek <doubek@vision.ee.ethz.ch> | 2004-08-12 00:09:32 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2004-08-12 00:09:32 +0000 |
commit | 6ba5cbc699e77cae66bb719354fa142114b64eab (patch) | |
tree | 4d0862ca409f9db2ad6f121e66fc40275557dfa4 | |
parent | 1477ec35dd958bf2c1ec7b4221a3d571c5b61449 (diff) | |
download | ffmpeg-6ba5cbc699e77cae66bb719354fa142114b64eab.tar.gz |
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
tested and submitted by (Torsten Spindler <spindler at hbt dot arch dot ethz dot ch>)
Originally committed as revision 3381 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | ffserver.c | 6 | ||||
-rw-r--r-- | libavformat/avformat.h | 1 | ||||
-rw-r--r-- | libavformat/http.c | 61 | ||||
-rw-r--r-- | libavformat/rtpproto.c | 4 | ||||
-rw-r--r-- | libavformat/rtsp.c | 4 | ||||
-rw-r--r-- | libavformat/tcp.c | 21 | ||||
-rw-r--r-- | libavformat/udp.c | 4 | ||||
-rw-r--r-- | libavformat/utils.c | 26 |
8 files changed, 95 insertions, 32 deletions
diff --git a/ffserver.c b/ffserver.c index b6d9905a02..c7c7a9f053 100644 --- a/ffserver.c +++ b/ffserver.c @@ -2714,7 +2714,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url) struct sockaddr_in my_addr; /* find which url is asked */ - url_split(NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); + url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') path++; @@ -2788,7 +2788,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPActionServerSetup setup; /* find which url is asked */ - url_split(NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); + url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') path++; @@ -2943,7 +2943,7 @@ static HTTPContext *find_rtp_session_with_url(const char *url, return NULL; /* find which url is asked */ - url_split(NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); + url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') path++; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index e88a59e39d..5f2e56c67b 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -627,6 +627,7 @@ struct in_addr; int resolve_host(struct in_addr *sin_addr, const char *hostname); void url_split(char *proto, int proto_size, + char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, diff --git a/libavformat/http.c b/libavformat/http.c index 6800370549..d8ab4d3f44 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -46,8 +46,10 @@ typedef struct { char location[URL_SIZE]; } HTTPContext; -static int http_connect(URLContext *h, const char *path, const char *hoststr); +static int http_connect(URLContext *h, const char *path, const char *hoststr, + const char *auth); static int http_write(URLContext *h, uint8_t *buf, int size); +static char *b64_encode( unsigned char *src ); /* return non zero if error */ @@ -55,6 +57,7 @@ static int http_open(URLContext *h, const char *uri, int flags) { const char *path, *proxy_path; char hostname[1024], hoststr[1024]; + char auth[1024]; char path1[1024]; char buf[1024]; int port, use_proxy, err; @@ -76,7 +79,7 @@ static int http_open(URLContext *h, const char *uri, int flags) /* fill the dest addr */ redo: /* needed in any case to build the host string */ - url_split(NULL, 0, hostname, sizeof(hostname), &port, + url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, path1, sizeof(path1), uri); if (port > 0) { snprintf(hoststr, sizeof(hoststr), "%s:%d", hostname, port); @@ -85,7 +88,7 @@ static int http_open(URLContext *h, const char *uri, int flags) } if (use_proxy) { - url_split(NULL, 0, hostname, sizeof(hostname), &port, + url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, NULL, 0, proxy_path); path = uri; } else { @@ -103,7 +106,7 @@ static int http_open(URLContext *h, const char *uri, int flags) goto fail; s->hd = hd; - if (http_connect(h, path, hoststr) < 0) + if (http_connect(h, path, hoststr, auth) < 0) goto fail; if (s->http_code == 303 && s->location[0] != '\0') { /* url moved, get next */ @@ -172,7 +175,8 @@ static int process_line(HTTPContext *s, char *line, int line_count) return 1; } -static int http_connect(URLContext *h, const char *path, const char *hoststr) +static int http_connect(URLContext *h, const char *path, const char *hoststr, + const char *auth) { HTTPContext *s = h->priv_data; int post, err, ch; @@ -187,11 +191,13 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr) "User-Agent: %s\r\n" "Accept: */*\r\n" "Host: %s\r\n" + "Authorization: Basic %s\r\n" "\r\n", post ? "POST" : "GET", path, LIBAVFORMAT_IDENT, - hoststr); + hoststr, + b64_encode(auth)); if (http_write(h, s->buffer, strlen(s->buffer)) < 0) return AVERROR_IO; @@ -277,3 +283,46 @@ URLProtocol http_protocol = { http_close, }; +/***************************************************************************** + * b64_encode: stolen from VLC's http.c + *****************************************************************************/ + +static char *b64_encode( unsigned char *src ) +{ + static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + char *dst = av_malloc( strlen( src ) * 4 / 3 + 12 ); + char *ret = dst; + unsigned i_bits = 0; + unsigned i_shift = 0; + + for( ;; ) + { + if( *src ) + { + i_bits = ( i_bits << 8 )|( *src++ ); + i_shift += 8; + } + else if( i_shift > 0 ) + { + i_bits <<= 6 - i_shift; + i_shift = 6; + } + else + { + *dst++ = '='; + break; + } + + while( i_shift >= 6 ) + { + i_shift -= 6; + *dst++ = b64[(i_bits >> i_shift)&0x3f]; + } + } + + *dst++ = '\0'; + + return ret; +} + diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 71a4a05ded..26565ed10a 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -57,7 +57,7 @@ int rtp_set_remote_url(URLContext *h, const char *uri) char buf[1024]; char path[1024]; - url_split(NULL, 0, hostname, sizeof(hostname), &port, + url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port, path); @@ -122,7 +122,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) return -ENOMEM; h->priv_data = s; - url_split(NULL, 0, hostname, sizeof(hostname), &port, + url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); /* extract parameters */ is_multicast = 0; diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index c1c645bee3..6037f9035e 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -339,7 +339,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, rtsp_st = st->priv_data; /* XXX: may need to add full url resolution */ - url_split(proto, sizeof(proto), NULL, 0, NULL, NULL, 0, p); + url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p); if (proto[0] == '\0') { /* relative control URL */ pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/"); @@ -723,7 +723,7 @@ static int rtsp_read_header(AVFormatContext *s, AVStream *st; /* extract hostname and port */ - url_split(NULL, 0, + url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, path, sizeof(path), s->filename); if (port < 0) port = RTSP_DEFAULT_PORT; diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 6475c1277b..8ec84ec4b6 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -63,25 +63,18 @@ static int tcp_open(URLContext *h, const char *uri, int flags) int fd_max, ret; struct timeval tv; socklen_t optlen; + char proto[1024],path[1024],tmp[1024]; // PETR: protocol and path strings + + url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), + &port, path, sizeof(path), uri); // PETR: use url_split + if (strcmp(proto,"tcp")) goto fail; // PETR: check protocol + if ((q = strchr(hostname,'@'))) { strcpy(tmp,q+1); strcpy(hostname,tmp); } // PETR: take only the part after '@' for tcp protocol s = av_malloc(sizeof(TCPContext)); if (!s) return -ENOMEM; h->priv_data = s; - p = uri; - if (!strstart(p, "tcp://", &p)) - goto fail; - q = hostname; - while (*p != ':' && *p != '/' && *p != '\0') { - if ((q - hostname) < sizeof(hostname) - 1) - *q++ = *p; - p++; - } - *q = '\0'; - if (*p != ':') - goto fail; - p++; - port = strtoul(p, (char **)&p, 10); + if (port <= 0 || port >= 65536) goto fail; diff --git a/libavformat/udp.c b/libavformat/udp.c index 87805c1519..0ba76fa141 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -60,7 +60,7 @@ int udp_set_remote_url(URLContext *h, const char *uri) char hostname[256]; int port; - url_split(NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); + url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* set the destination address */ if (resolve_host(&s->dest_addr.sin_addr, hostname) < 0) @@ -132,7 +132,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) } /* fill the dest addr */ - url_split(NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); + url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* XXX: fix url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { diff --git a/libavformat/utils.c b/libavformat/utils.c index be3df4a6e7..94169adf92 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2499,6 +2499,7 @@ void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload) } void url_split(char *proto, int proto_size, + char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, @@ -2519,6 +2520,8 @@ void url_split(char *proto, int proto_size, } if (proto_size > 0) *q = '\0'; + if (authorization_size > 0) + authorization[0] = '\0'; if (*p == '\0') { if (proto_size > 0) proto[0] = '\0'; @@ -2526,15 +2529,32 @@ void url_split(char *proto, int proto_size, hostname[0] = '\0'; p = url; } else { + char *at,*slash; // PETR: position of '@' character and '/' character + p++; if (*p == '/') p++; if (*p == '/') p++; - q = hostname; - while (*p != ':' && *p != '/' && *p != '?' && *p != '\0') { - if ((q - hostname) < hostname_size - 1) + at = strchr(p,'@'); // PETR: get the position of '@' + slash = strchr(p,'/'); // PETR: get position of '/' - end of hostname + if (at && slash && at > slash) at = NULL; // PETR: not interested in '@' behind '/' + + q = at ? authorization : hostname; // PETR: if '@' exists starting with auth. + + while ((at || *p != ':') && *p != '/' && *p != '?' && *p != '\0') { // PETR: + if (*p == '@') { // PETR: passed '@' + if (authorization_size > 0) + *q = '\0'; + q = hostname; + at = NULL; + } else if (!at) { // PETR: hostname + if ((q - hostname) < hostname_size - 1) + *q++ = *p; + } else { + if ((q - authorization) < authorization_size - 1) *q++ = *p; + } p++; } if (hostname_size > 0) |