Commit 6ba5cbc6 authored by Petr Doubek's avatar Petr Doubek Committed by Michael Niedermayer

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
parent 1477ec35
...@@ -2714,7 +2714,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url) ...@@ -2714,7 +2714,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url)
struct sockaddr_in my_addr; struct sockaddr_in my_addr;
/* find which url is asked */ /* 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; path = path1;
if (*path == '/') if (*path == '/')
path++; path++;
...@@ -2788,7 +2788,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url, ...@@ -2788,7 +2788,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url,
RTSPActionServerSetup setup; RTSPActionServerSetup setup;
/* find which url is asked */ /* 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; path = path1;
if (*path == '/') if (*path == '/')
path++; path++;
...@@ -2943,7 +2943,7 @@ static HTTPContext *find_rtp_session_with_url(const char *url, ...@@ -2943,7 +2943,7 @@ static HTTPContext *find_rtp_session_with_url(const char *url,
return NULL; return NULL;
/* find which url is asked */ /* 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; path = path1;
if (*path == '/') if (*path == '/')
path++; path++;
......
...@@ -627,6 +627,7 @@ struct in_addr; ...@@ -627,6 +627,7 @@ struct in_addr;
int resolve_host(struct in_addr *sin_addr, const char *hostname); int resolve_host(struct in_addr *sin_addr, const char *hostname);
void url_split(char *proto, int proto_size, void url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size, char *hostname, int hostname_size,
int *port_ptr, int *port_ptr,
char *path, int path_size, char *path, int path_size,
......
...@@ -46,8 +46,10 @@ typedef struct { ...@@ -46,8 +46,10 @@ typedef struct {
char location[URL_SIZE]; char location[URL_SIZE];
} HTTPContext; } 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 int http_write(URLContext *h, uint8_t *buf, int size);
static char *b64_encode( unsigned char *src );
/* return non zero if error */ /* return non zero if error */
...@@ -55,6 +57,7 @@ static int http_open(URLContext *h, const char *uri, int flags) ...@@ -55,6 +57,7 @@ static int http_open(URLContext *h, const char *uri, int flags)
{ {
const char *path, *proxy_path; const char *path, *proxy_path;
char hostname[1024], hoststr[1024]; char hostname[1024], hoststr[1024];
char auth[1024];
char path1[1024]; char path1[1024];
char buf[1024]; char buf[1024];
int port, use_proxy, err; int port, use_proxy, err;
...@@ -76,7 +79,7 @@ static int http_open(URLContext *h, const char *uri, int flags) ...@@ -76,7 +79,7 @@ static int http_open(URLContext *h, const char *uri, int flags)
/* fill the dest addr */ /* fill the dest addr */
redo: redo:
/* needed in any case to build the host string */ /* 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); path1, sizeof(path1), uri);
if (port > 0) { if (port > 0) {
snprintf(hoststr, sizeof(hoststr), "%s:%d", hostname, port); snprintf(hoststr, sizeof(hoststr), "%s:%d", hostname, port);
...@@ -85,7 +88,7 @@ static int http_open(URLContext *h, const char *uri, int flags) ...@@ -85,7 +88,7 @@ static int http_open(URLContext *h, const char *uri, int flags)
} }
if (use_proxy) { 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); NULL, 0, proxy_path);
path = uri; path = uri;
} else { } else {
...@@ -103,7 +106,7 @@ static int http_open(URLContext *h, const char *uri, int flags) ...@@ -103,7 +106,7 @@ static int http_open(URLContext *h, const char *uri, int flags)
goto fail; goto fail;
s->hd = hd; s->hd = hd;
if (http_connect(h, path, hoststr) < 0) if (http_connect(h, path, hoststr, auth) < 0)
goto fail; goto fail;
if (s->http_code == 303 && s->location[0] != '\0') { if (s->http_code == 303 && s->location[0] != '\0') {
/* url moved, get next */ /* url moved, get next */
...@@ -172,7 +175,8 @@ static int process_line(HTTPContext *s, char *line, int line_count) ...@@ -172,7 +175,8 @@ static int process_line(HTTPContext *s, char *line, int line_count)
return 1; 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; HTTPContext *s = h->priv_data;
int post, err, ch; int post, err, ch;
...@@ -187,11 +191,13 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr) ...@@ -187,11 +191,13 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr)
"User-Agent: %s\r\n" "User-Agent: %s\r\n"
"Accept: */*\r\n" "Accept: */*\r\n"
"Host: %s\r\n" "Host: %s\r\n"
"Authorization: Basic %s\r\n"
"\r\n", "\r\n",
post ? "POST" : "GET", post ? "POST" : "GET",
path, path,
LIBAVFORMAT_IDENT, LIBAVFORMAT_IDENT,
hoststr); hoststr,
b64_encode(auth));
if (http_write(h, s->buffer, strlen(s->buffer)) < 0) if (http_write(h, s->buffer, strlen(s->buffer)) < 0)
return AVERROR_IO; return AVERROR_IO;
...@@ -277,3 +283,46 @@ URLProtocol http_protocol = { ...@@ -277,3 +283,46 @@ URLProtocol http_protocol = {
http_close, 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;
}
...@@ -57,7 +57,7 @@ int rtp_set_remote_url(URLContext *h, const char *uri) ...@@ -57,7 +57,7 @@ int rtp_set_remote_url(URLContext *h, const char *uri)
char buf[1024]; char buf[1024];
char path[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); path, sizeof(path), uri);
snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port, path); 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) ...@@ -122,7 +122,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
return -ENOMEM; return -ENOMEM;
h->priv_data = s; 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); path, sizeof(path), uri);
/* extract parameters */ /* extract parameters */
is_multicast = 0; is_multicast = 0;
......
...@@ -339,7 +339,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, ...@@ -339,7 +339,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
rtsp_st = st->priv_data; rtsp_st = st->priv_data;
/* XXX: may need to add full url resolution */ /* 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') { if (proto[0] == '\0') {
/* relative control URL */ /* relative control URL */
pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/"); pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/");
...@@ -723,7 +723,7 @@ static int rtsp_read_header(AVFormatContext *s, ...@@ -723,7 +723,7 @@ static int rtsp_read_header(AVFormatContext *s,
AVStream *st; AVStream *st;
/* extract hostname and port */ /* extract hostname and port */
url_split(NULL, 0, url_split(NULL, 0, NULL, 0,
host, sizeof(host), &port, path, sizeof(path), s->filename); host, sizeof(host), &port, path, sizeof(path), s->filename);
if (port < 0) if (port < 0)
port = RTSP_DEFAULT_PORT; port = RTSP_DEFAULT_PORT;
......
...@@ -63,25 +63,18 @@ static int tcp_open(URLContext *h, const char *uri, int flags) ...@@ -63,25 +63,18 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
int fd_max, ret; int fd_max, ret;
struct timeval tv; struct timeval tv;
socklen_t optlen; 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)); s = av_malloc(sizeof(TCPContext));
if (!s) if (!s)
return -ENOMEM; return -ENOMEM;
h->priv_data = s; 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) if (port <= 0 || port >= 65536)
goto fail; goto fail;
......
...@@ -60,7 +60,7 @@ int udp_set_remote_url(URLContext *h, const char *uri) ...@@ -60,7 +60,7 @@ int udp_set_remote_url(URLContext *h, const char *uri)
char hostname[256]; char hostname[256];
int port; 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 */ /* set the destination address */
if (resolve_host(&s->dest_addr.sin_addr, hostname) < 0) 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) ...@@ -132,7 +132,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
} }
/* fill the dest addr */ /* 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 */ /* XXX: fix url_split */
if (hostname[0] == '\0' || hostname[0] == '?') { if (hostname[0] == '\0' || hostname[0] == '?') {
......
...@@ -2499,6 +2499,7 @@ void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload) ...@@ -2499,6 +2499,7 @@ void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
} }
void url_split(char *proto, int proto_size, void url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size, char *hostname, int hostname_size,
int *port_ptr, int *port_ptr,
char *path, int path_size, char *path, int path_size,
...@@ -2519,6 +2520,8 @@ void url_split(char *proto, int proto_size, ...@@ -2519,6 +2520,8 @@ void url_split(char *proto, int proto_size,
} }
if (proto_size > 0) if (proto_size > 0)
*q = '\0'; *q = '\0';
if (authorization_size > 0)
authorization[0] = '\0';
if (*p == '\0') { if (*p == '\0') {
if (proto_size > 0) if (proto_size > 0)
proto[0] = '\0'; proto[0] = '\0';
...@@ -2526,15 +2529,32 @@ void url_split(char *proto, int proto_size, ...@@ -2526,15 +2529,32 @@ void url_split(char *proto, int proto_size,
hostname[0] = '\0'; hostname[0] = '\0';
p = url; p = url;
} else { } else {
char *at,*slash; // PETR: position of '@' character and '/' character
p++; p++;
if (*p == '/') if (*p == '/')
p++; p++;
if (*p == '/') if (*p == '/')
p++; p++;
q = hostname; at = strchr(p,'@'); // PETR: get the position of '@'
while (*p != ':' && *p != '/' && *p != '?' && *p != '\0') { slash = strchr(p,'/'); // PETR: get position of '/' - end of hostname
if ((q - hostname) < hostname_size - 1) 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; *q++ = *p;
}
p++; p++;
} }
if (hostname_size > 0) if (hostname_size > 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment