diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/input/Makefile.am | 4 | ||||
| -rw-r--r-- | src/input/http_helper.c | 258 | ||||
| -rw-r--r-- | src/input/http_helper.h | 38 | ||||
| -rw-r--r-- | src/input/input_http.c | 216 | 
4 files changed, 353 insertions, 163 deletions
| diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 0645e9173..dfa6c631f 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -92,7 +92,7 @@ xineplug_inp_rtp_la_SOURCES = input_rtp.c  xineplug_inp_rtp_la_LIBADD = $(XINE_LIB)  xineplug_inp_rtp_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ -xineplug_inp_http_la_SOURCES = input_http.c net_buf_ctrl.c +xineplug_inp_http_la_SOURCES = input_http.c net_buf_ctrl.c http_helper.c  xineplug_inp_http_la_LIBADD = $(XINE_LIB)  xineplug_inp_http_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ @@ -125,4 +125,4 @@ xineplug_inp_pvr_la_LIBADD = $(XINE_LIB)  xineplug_inp_pvr_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@  include_HEADERS = input_plugin.h -noinst_HEADERS = net_buf_ctrl.h mms.h mmsh.h pnm.h media_helper.h videodev2.h +noinst_HEADERS = net_buf_ctrl.h mms.h mmsh.h pnm.h media_helper.h videodev2.h http_helper.h diff --git a/src/input/http_helper.c b/src/input/http_helper.c new file mode 100644 index 000000000..730deccad --- /dev/null +++ b/src/input/http_helper.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2000-2003 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA + * + * URL helper functions + * + * $Id: http_helper.c,v 1.1 2003/11/26 08:09:58 tmattern Exp $  + */ +#include "xine_internal.h" +#include "http_helper.h" + +static char *_strndup(const char *s, size_t n) { +  char *ret; +   +  ret = malloc (n + 1); +  strncpy(ret, s, n); +  ret[n] = '\0'; +  return ret; +} + +int _x_parse_url (char *url, char **proto, char** host, int *port, +                         char **user, char **password, char **uri) { +  char   *start      = NULL; +  char   *authcolon  = NULL; +  char	 *at         = NULL; +  char	 *portcolon  = NULL; +  char   *slash      = NULL; +  char   *end        = NULL; +  char   *strtol_err = NULL; + +  if (!url)      abort(); +  if (!proto)    abort(); +  if (!user)     abort(); +  if (!password) abort(); +  if (!host)     abort(); +  if (!port)     abort(); +  if (!uri)      abort(); + +  *proto    = NULL; +  *port     = 0; +  *user     = NULL; +  *host     = NULL; +  *password = NULL; +  *uri      = NULL; + +  /* proto */   +  start = strstr(url, "://"); +  end  = start + strlen(start) - 1; +  if (!start || (start == url)) +    goto error; +   +  *proto = _strndup(url, start - url); + +  /* user:password */ +  start += 3; +  at = strchr(start, '@'); +  slash = strchr(start, '/'); +   +  if (at && slash && (at > slash)) +    at = NULL; +   +  if (at) { +    authcolon = strchr(start, ':'); +    if(authcolon && authcolon < at) { +      *user = _strndup(start, authcolon - start); +      *password = _strndup(authcolon + 1, at - authcolon - 1); +      if ((authcolon == start) || (at == (authcolon + 1))) goto error; +    } else { +      /* no password */ +      *user = _strndup(start, at - start); +      if (at == start) goto error; +    } +    start = at + 1; +  } + +  /* host:port (ipv4) */ +  /* [host]:port (ipv6) */ +  if (*start != '[') +  { +    /* ipv4*/ +    portcolon = strchr(start, ':'); +    if (slash) { +      if (portcolon && portcolon < slash) { +        *host = _strndup(start, portcolon - start); +        if (portcolon == start) goto error; +        *port = strtol(portcolon + 1, &strtol_err, 10); +        if ((strtol_err != slash) || (strtol_err == portcolon + 1)) +          goto error; +      } else { +        *host = _strndup(start, slash - start); +        if (slash == start) goto error; +      } +    } else { +      if (portcolon) { +        *host = _strndup(start, portcolon - start); +        if (portcolon < end) { +          *port = strtol(portcolon + 1, &strtol_err, 10); +          if (*strtol_err != '\0') goto error; +        } else { +          goto error; +        } +      } else { +        if (*start == '\0') goto error; +        *host = strdup(start); +      } +    } +  } else { +    /* ipv6*/ +    char *hostendbracket; + +    hostendbracket = strchr(start, ']'); +    if (hostendbracket != NULL) { +      if (hostendbracket == start + 1) goto error; +      *host = _strndup(start + 1, hostendbracket - start - 1); + +      if (hostendbracket < end) { +        /* Might have a trailing port */ +        if (*(hostendbracket + 1) == ':') { +          portcolon = hostendbracket + 1; +          if (portcolon < end) { +            *port = strtol(portcolon + 1, &strtol_err, 10); +            if ((*strtol_err != '\0') && (*strtol_err != '/')) goto error; +          } else { +            goto error; +          } +        } +      } +    } else { +      goto error; +    } +  } + +  /* uri */ +  start = slash; +  if (start) +    *uri = strdup(start); +  else +    *uri = strdup("/"); +   +  return 1; +   +error: +  if (*proto) { +    free (*proto); +    *proto = NULL; +  } +  if (*user) { +    free (*user); +    *user = NULL; +  } +  if (*password) { +    free (*password); +    *password = NULL; +  } +  if (*host) { +    free (*host); +    *host = NULL; +  } +  if (*port) { +    *port = 0; +  } +  if (*uri) { +    free (*uri); +    *uri = NULL; +  } +  return 0;   +} + + +#ifdef TEST_URL +/* + * url parser test program + */ + +static int check_url(char *url, int ok) { +  char *proto, *host, *user, *password, *uri; +  int port; +  int res; +   +  printf("--------------------------------\n"); +  printf("url=%s\n", url); +  res = _x_parse_url (url, +                      &proto, &host, &port, &user, &password, &uri); +  if (res) { +    printf("proto=%s, host=%s, port=%d, user=%s, password=%s, uri=%s\n", +           proto, host, port, user, password, uri); +    free(proto); +    free(host); +    free(user); +    free(password); +    free(uri); +  } else { +    printf("bad url\n"); +  } +  if (res == ok) { +    printf("test OK\n", url); +    return 1; +  } else { +    printf("test KO\n", url); +    return 0; +  } +} + +int main(int argc, char** argv) { +  char *proto, host, port, user, password, uri; +  int res = 0; +   +  res += check_url("http://www.toto.com/test1.asx", 1); +  res += check_url("http://www.toto.com:8080/test2.asx", 1); +  res += check_url("http://titi:pass@www.toto.com:8080/test3.asx", 1); +  res += check_url("http://www.toto.com", 1); +  res += check_url("http://www.toto.com/", 1); +  res += check_url("http://www.toto.com:80", 1); +  res += check_url("http://www.toto.com:80/", 1); +  res += check_url("http://www.toto.com:", 0); +  res += check_url("http://www.toto.com:/", 0); +  res += check_url("http://www.toto.com:abc", 0); +  res += check_url("http://www.toto.com:abc/", 0); +  res += check_url("http://titi@www.toto.com:8080/test4.asx", 1); +  res += check_url("http://@www.toto.com:8080/test5.asx", 0); +  res += check_url("http://:@www.toto.com:8080/test6.asx", 0); +  res += check_url("http:///test6.asx", 0); +  res += check_url("http://:/test7.asx", 0); +  res += check_url("http://", 0); +  res += check_url("http://:", 0); +  res += check_url("http://@", 0); +  res += check_url("http://:@", 0); +  res += check_url("http://:/@", 0); +  res += check_url("http://www.toto.com:80a/", 0); +  res += check_url("http://[www.toto.com]", 1); +  res += check_url("http://[www.toto.com]/", 1); +  res += check_url("http://[www.toto.com]:80", 1); +  res += check_url("http://[www.toto.com]:80/", 1); +  res += check_url("http://[12:12]:80/", 1); +  res += check_url("http://user:pass@[12:12]:80/", 1); +  printf("================================\n"); +  if (res != 28) { +    printf("result: KO\n"); +  } else { +    printf("result: OK\n"); +  } +} +#endif diff --git a/src/input/http_helper.h b/src/input/http_helper.h new file mode 100644 index 000000000..a89f93c3b --- /dev/null +++ b/src/input/http_helper.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2000-2003 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA + * + * URL helper functions + * + * $Id: http_helper.h,v 1.1 2003/11/26 08:09:58 tmattern Exp $  + */ + +/* + * url parser + * {proto}://{user}:{password}@{host}:{port}{uri} + * {proto}://{user}:{password}@{[host]}:{port}{uri} + * + * return: + *   0  invalid url + *   1  valid url + */ +#ifndef HTTP_HELPER_H +#define HTTP_HELPER_H +int _x_parse_url (char *url, char **proto, char** host, int *port, +                  char **user, char **password, char **uri); +#endif /* HTTP_HELPER_H */ diff --git a/src/input/input_http.c b/src/input/input_http.c index 176cee289..e1a7bb9fa 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -19,7 +19,7 @@   *   * input plugin for http network streams   * - * $Id: input_http.c,v 1.74 2003/11/16 23:33:44 f1rmb Exp $ + * $Id: input_http.c,v 1.75 2003/11/26 08:09:58 tmattern Exp $   */  #ifdef HAVE_CONFIG_H @@ -46,7 +46,7 @@  #include "xineutils.h"  #include "input_plugin.h"  #include "net_buf_ctrl.h" -#include "io_helper.h" +#include "http_helper.h"  /*  #define LOG @@ -70,18 +70,17 @@ typedef struct {    off_t            contentlength;    char             buf[BUFSIZE]; -  char             mrlbuf[BUFSIZE]; -  char             mrlbuf2[BUFSIZE]; /* icecast */    char             proxybuf[BUFSIZE];    char             auth[BUFSIZE];    char             proxyauth[BUFSIZE]; +  char            *proto;    char            *user;    char            *password;    char            *host;    int              port; -  char            *filename; +  char            *uri;    char             preview[MAX_PREVIEW_SIZE];    off_t            preview_size; @@ -143,122 +142,6 @@ static void proxy_port_change_cb(void *data, xine_cfg_entry_t *cfg) {    this->proxyport = cfg->num_value;  } -static int http_plugin_parse_url (char *urlbuf, char **user, char **password, -				  char** host, int *port, char **filename) { -  char   *start = NULL; -  char   *authcolon = NULL; -  char	 *at = NULL; -  char	 *portcolon = NULL; -  char   *slash = NULL; -   -  if (user != NULL) -    *user = NULL; -   -  if (password != NULL) -    *password = NULL; -   -  if (host != NULL) -    *host = NULL; -   -  if (filename != NULL) -    *filename = NULL; -   -  if (port != NULL) -    *port = 0; -   -  start = strstr(urlbuf, "://"); -  if (start != NULL) -    start += 3; -  else -    start = urlbuf; - -  at = strchr(start, '@'); -  slash = strchr(start, '/'); -   -  if (at != NULL && slash != NULL && at > slash) -    at = NULL; -   -  if (at != NULL) -  { -    authcolon = strchr(start, ':'); -    if(authcolon != NULL && authcolon > at) -      authcolon = NULL; -     -    portcolon = strchr(at, ':'); -  } else -    portcolon = strchr(start, ':'); -   -  if (portcolon != NULL && slash != NULL && portcolon > slash) -    portcolon = NULL; -   -  if (at != NULL) -  { -    *at = '\0'; -     -    if (user != NULL) -      *user = start; -     -    if (authcolon != NULL) -    { -      *authcolon = '\0'; -       -      if (password != NULL) -      	*password = authcolon + 1; -    } - -    if (host != NULL) -      *host = at + 1; -  } else -    if (host != NULL) -      *host = start; - -#ifdef ENABLE_IPV6 -  /* Add support for RFC 2732 */ -  { -      char *hostbracket, *hostendbracket; - -      hostbracket = strchr(start, '['); -      if (hostbracket != NULL) { -	   -	  hostendbracket = strchr(hostbracket, ']'); -	   -	  if (hostendbracket != NULL) { -	       -	      *hostendbracket = '\0'; -	      *host = (hostbracket + 1); -	       -	      /* Might have a trailing port */ -	       -	      if (*(hostendbracket+1) == ':') { -		  portcolon = (hostendbracket + 1); -	      } -	  } -      } -  } -#endif - -  if (slash != 0) -  { -    *slash = '\0'; -     -    if (filename != NULL) -      *filename = slash + 1; -  } else { -    if (filename != NULL) -      *filename = urlbuf + strlen(urlbuf); -  } -   -  if (portcolon != NULL) -  { -    *portcolon = '\0'; -     -    if (port != NULL) -      *port = atoi(portcolon + 1); -  } -   -  return 0; -} -  static int http_plugin_basicauth (const char *user, const char *password, char* dest, int len) {    static char *enctable="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";    char        *tmp; @@ -563,8 +446,8 @@ static uint32_t http_plugin_get_capabilities (input_plugin_t *this_gen) {    uint32_t caps = INPUT_CAP_PREVIEW;    /* Nullsoft asked to not allow saving streaming nsv files */ -  if (this->filename &&  -      !strncmp(this->filename + strlen(this->filename) - 4, ".nsv", 4)) +  if (this->uri &&  +      !strncmp(this->uri + strlen(this->uri) - 4, ".nsv", 4))      caps |= INPUT_CAP_RIP_FORBIDDEN;    return caps; @@ -622,7 +505,7 @@ static off_t http_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin  static char* http_plugin_get_mrl (input_plugin_t *this_gen) {    http_input_plugin_t *this = (http_input_plugin_t *) this_gen; -  return this->mrlbuf2; +  return this->mrl;  }  static int http_plugin_get_optional_data (input_plugin_t *this_gen, @@ -655,6 +538,12 @@ static void http_plugin_dispose (input_plugin_t *this_gen ) {      this->nbc = NULL;    } +  if (this->mrl) free(this->mrl); +  if (this->proto) free(this->proto); +  if (this->host) free(this->host); +  if (this->user) free(this->user); +  if (this->password) free(this->password); +  if (this->uri) free(this->uri);    free (this);  } @@ -676,10 +565,10 @@ static void report_progress (xine_stream_t *stream, int p) {  static int http_plugin_open (input_plugin_t *this_gen ) {    http_input_plugin_t *this = (http_input_plugin_t *) this_gen;    http_input_class_t  *this_class = (http_input_class_t *) this->input_plugin.input_class; -  int                  done,len,linenum; +  int                  done, len, linenum;    int                  shoutcast = 0, httpcode; -  int                  length;    int                  res, progress; +  int                  buflen;    this->shoutcast_pos = 0; @@ -698,10 +587,11 @@ static int http_plugin_open (input_plugin_t *this_gen ) {    } -  if (http_plugin_parse_url (this->mrlbuf, &this->user, &this->password, -			     &this->host, &this->port, &this->filename)) +  if (!_x_parse_url(this->mrl, &this->proto, &this->host, &this->port, +                    &this->user, &this->password, &this->uri)) { +    _x_message(this->stream, XINE_MSG_GENERAL_WARNING, "malformed url", NULL);      return 0; -   +  }    if (this->port == 0)      this->port = DEFAULT_HTTP_PORT; @@ -745,40 +635,46 @@ static int http_plugin_open (input_plugin_t *this_gen ) {    if (this_class->proxyhost && strlen(this_class->proxyhost)) {      if (this->port != DEFAULT_HTTP_PORT) { -      sprintf (this->buf, "GET http://%s:%d/%s HTTP/1.0\015\012", -	       this->host, this->port, this->filename); +      snprintf (this->buf, BUFSIZE, "GET http://%s:%d%s HTTP/1.0\015\012", +	       this->host, this->port, this->uri);      } else { -      sprintf (this->buf, "GET http://%s/%s HTTP/1.0\015\012", -	       this->host, this->filename); +      snprintf (this->buf, BUFSIZE, "GET http://%s%s HTTP/1.0\015\012", +	       this->host, this->uri);      }    }     else -    sprintf (this->buf, "GET /%s HTTP/1.0\015\012", this->filename); +    snprintf (this->buf, BUFSIZE, "GET %s HTTP/1.0\015\012", this->uri); +  buflen = strlen(this->buf);    if (this->port != DEFAULT_HTTP_PORT) -    sprintf (this->buf + strlen(this->buf), "Host: %s:%d\015\012", +    snprintf (this->buf + buflen, BUFSIZE - buflen, "Host: %s:%d\015\012",  	     this->host, this->port);    else -    sprintf (this->buf + strlen(this->buf), "Host: %s\015\012", +    snprintf (this->buf + buflen, BUFSIZE - buflen, "Host: %s\015\012",  	     this->host); -  if (this_class->proxyuser && strlen(this_class->proxyuser)) -    sprintf (this->buf + strlen(this->buf), "Proxy-Authorization: Basic %s\015\012", -	     this->proxyauth); -   -  if (this->user && strlen(this->user)) -    sprintf (this->buf + strlen(this->buf), "Authorization: Basic %s\015\012", -	     this->auth); -   -  sprintf (this->buf + strlen(this->buf), "User-Agent: xine/%s\015\012", -           VERSION); -  strcat (this->buf, "Accept: */*\015\012"); /* * */ -  strcat (this->buf, "Icy-MetaData: 1\015\012"); +  buflen = strlen(this->buf); +  if (this_class->proxyuser && strlen(this_class->proxyuser)) { +    snprintf (this->buf + buflen, BUFSIZE - buflen, +              "Proxy-Authorization: Basic %s\015\012", this->proxyauth); +    buflen = strlen(this->buf); +  } +  if (this->user && strlen(this->user)) { +    snprintf (this->buf + buflen, BUFSIZE - buflen, +              "Authorization: Basic %s\015\012", this->auth); +    buflen = strlen(this->buf); +  } -  strcat (this->buf, "\015\012"); - -  length = strlen(this->buf); -  if (_x_io_tcp_write (this->stream, this->fh, this->buf, length) != length) { +  snprintf (this->buf + buflen, BUFSIZE - buflen, +           "User-Agent: xine/%s\015\012", VERSION); +  buflen = strlen(this->buf); +  strncat (this->buf, "Accept: */*\015\012", BUFSIZE - buflen); /* * */ +  buflen = strlen(this->buf); +  strncat (this->buf, "Icy-MetaData: 1\015\012", BUFSIZE - buflen); +  buflen = strlen(this->buf); +  strncat (this->buf, "\015\012", BUFSIZE - buflen); +  buflen = strlen(this->buf); +  if (_x_io_tcp_write (this->stream, this->fh, this->buf, buflen) != buflen) {      _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "couldn't send request", NULL);      xprintf(this_class->xine, XINE_VERBOSITY_DEBUG, "input_http: couldn't send request\n");      return 0; @@ -861,8 +757,8 @@ static int http_plugin_open (input_plugin_t *this_gen ) {  	  lprintf ("input_http: trying to open target of redirection: >%s<\n", href); -          strncpy (this->mrlbuf, href, BUFSIZE); -          strncpy (this->mrlbuf2, href, BUFSIZE); +          free(this->mrl); +          this->mrl = strdup(href);            return http_plugin_open(this_gen);          }        } @@ -891,10 +787,10 @@ static int http_plugin_open (input_plugin_t *this_gen ) {    this->shoutcast_songtitle = NULL;    if (shoutcast ||        !strncasecmp(this->preview, "ICY", 3)) { -    this->mrlbuf2[0] = 'i'; -    this->mrlbuf2[1] = 'c'; -    this->mrlbuf2[2] = 'e'; -    this->mrlbuf2[3] = ' '; +    this->mrl[0] = 'i'; +    this->mrl[1] = 'c'; +    this->mrl[2] = 'e'; +    this->mrl[3] = ' ';      if (read_shoutcast_header(this)) {        /* problem when reading shoutcast header */        _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "can't read shoutcast header", NULL); @@ -923,9 +819,7 @@ static input_plugin_t *http_class_get_instance (input_class_t *cls_gen, xine_str    }    this = (http_input_plugin_t *) xine_xmalloc(sizeof(http_input_plugin_t)); -  strncpy (this->mrlbuf, mrl, BUFSIZE); -  strncpy (this->mrlbuf2, mrl, BUFSIZE); -  this->mrl     = this->mrlbuf2; +  this->mrl     = strdup(mrl);    this->stream  = stream;    this->fh      = -1;    this->nbc     = nbc_init (this->stream); | 
