changeset 511:056991ab9f10 libavformat

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>)
author michael
date Thu, 12 Aug 2004 00:09:32 +0000
parents 133287132e1d
children 8dfd00fb6a6d
files avformat.h http.c rtpproto.c rtsp.c tcp.c udp.c utils.c
diffstat 7 files changed, 92 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/avformat.h	Wed Aug 04 20:57:35 2004 +0000
+++ b/avformat.h	Thu Aug 12 00:09:32 2004 +0000
@@ -627,6 +627,7 @@
 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,
--- a/http.c	Wed Aug 04 20:57:35 2004 +0000
+++ b/http.c	Thu Aug 12 00:09:32 2004 +0000
@@ -46,8 +46,10 @@
     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 @@
 {
     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 @@
     /* 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 @@
     }
 
     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 @@
         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 @@
     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 @@
              "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 @@
     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;
+}
+
--- a/rtpproto.c	Wed Aug 04 20:57:35 2004 +0000
+++ b/rtpproto.c	Thu Aug 12 00:09:32 2004 +0000
@@ -57,7 +57,7 @@
     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 @@
         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;
--- a/rtsp.c	Wed Aug 04 20:57:35 2004 +0000
+++ b/rtsp.c	Thu Aug 12 00:09:32 2004 +0000
@@ -339,7 +339,7 @@
             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 @@
     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;
--- a/tcp.c	Wed Aug 04 20:57:35 2004 +0000
+++ b/tcp.c	Thu Aug 12 00:09:32 2004 +0000
@@ -63,25 +63,18 @@
     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;
     
--- a/udp.c	Wed Aug 04 20:57:35 2004 +0000
+++ b/udp.c	Thu Aug 12 00:09:32 2004 +0000
@@ -60,7 +60,7 @@
     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 @@
     }
 
     /* 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] == '?') {
--- a/utils.c	Wed Aug 04 20:57:35 2004 +0000
+++ b/utils.c	Thu Aug 12 00:09:32 2004 +0000
@@ -2499,6 +2499,7 @@
 }
 
 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 @@
     }
     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 @@
             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)