1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/branches/gmyth-0.1b/src/gmyth_uri.c Wed Feb 14 23:06:17 2007 +0000
1.3 @@ -0,0 +1,404 @@
1.4 +/**
1.5 + * GMyth Library
1.6 + *
1.7 + * @file gmyth/gmyth_uri.c
1.8 + *
1.9 + * @brief <p> GMythURI utils
1.10 + * - Extracts and parses a URI char string, in according with the RFC 2396
1.11 + * [http://www.ietf.org/rfc/rfc2396.txt]
1.12 + *
1.13 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
1.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
1.15 + *
1.16 + *//*
1.17 + *
1.18 + * This program is free software; you can redistribute it and/or modify
1.19 + * it under the terms of the GNU Lesser General Public License as published by
1.20 + * the Free Software Foundation; either version 2 of the License, or
1.21 + * (at your option) any later version.
1.22 + *
1.23 + * This program is distributed in the hope that it will be useful,
1.24 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.25 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.26 + * GNU General Public License for more details.
1.27 + *
1.28 + * You should have received a copy of the GNU Lesser General Public License
1.29 + * along with this program; if not, write to the Free Software
1.30 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.31 + */
1.32 +
1.33 +#ifdef HAVE_CONFIG_H
1.34 +#include "config.h"
1.35 +#endif
1.36 +
1.37 +#include "gmyth_uri.h"
1.38 +
1.39 +#include <glib.h>
1.40 +#include <string.h>
1.41 +#include <stdlib.h>
1.42 +
1.43 +#include "gmyth_debug.h"
1.44 +
1.45 +static void gmyth_uri_class_init (GMythURIClass *klass);
1.46 +static void gmyth_uri_init (GMythURI *object);
1.47 +
1.48 +static void gmyth_uri_dispose (GObject *object);
1.49 +static void gmyth_uri_finalize (GObject *object);
1.50 +
1.51 +G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT)
1.52 +
1.53 +static void
1.54 +gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value );
1.55 +
1.56 +static void
1.57 +gmyth_uri_class_init (GMythURIClass *klass)
1.58 +{
1.59 + GObjectClass *gobject_class;
1.60 +
1.61 + gobject_class = (GObjectClass *) klass;
1.62 +
1.63 + gobject_class->dispose = gmyth_uri_dispose;
1.64 + gobject_class->finalize = gmyth_uri_finalize;
1.65 +}
1.66 +
1.67 +static void
1.68 +gmyth_uri_init (GMythURI *gmyth_uri)
1.69 +{
1.70 +}
1.71 +
1.72 +static void
1.73 +gmyth_uri_dispose (GObject *object)
1.74 +{
1.75 + GMythURI *gmyth_uri = GMYTH_URI(object);
1.76 +
1.77 + if ( gmyth_uri->host != NULL ) {
1.78 + g_string_free( gmyth_uri->host, TRUE );
1.79 + gmyth_uri->host = NULL;
1.80 + }
1.81 +
1.82 + if ( gmyth_uri->protocol != NULL ) {
1.83 + g_string_free( gmyth_uri->protocol, TRUE );
1.84 + gmyth_uri->protocol = NULL;
1.85 + }
1.86 +
1.87 + if ( gmyth_uri->path != NULL ) {
1.88 + g_string_free( gmyth_uri->path, TRUE );
1.89 + gmyth_uri->path = NULL;
1.90 + }
1.91 +
1.92 + if ( gmyth_uri->fragment != NULL ) {
1.93 + g_string_free( gmyth_uri->fragment, TRUE );
1.94 + gmyth_uri->fragment = NULL;
1.95 + }
1.96 +
1.97 + if ( gmyth_uri->user != NULL ) {
1.98 + g_string_free( gmyth_uri->user, TRUE );
1.99 + gmyth_uri->user = NULL;
1.100 + }
1.101 +
1.102 + if ( gmyth_uri->password != NULL ) {
1.103 + g_string_free( gmyth_uri->password, TRUE );
1.104 + gmyth_uri->password = NULL;
1.105 + }
1.106 +
1.107 + if ( gmyth_uri->query != NULL ) {
1.108 + g_string_free( gmyth_uri->query, TRUE );
1.109 + gmyth_uri->query = NULL;
1.110 + }
1.111 +
1.112 + G_OBJECT_CLASS (gmyth_uri_parent_class)->dispose (object);
1.113 +}
1.114 +
1.115 +static void
1.116 +gmyth_uri_finalize (GObject *object)
1.117 +{
1.118 + //GMythURI *gmyth_uri = GMYTH_URI(object);
1.119 +
1.120 + g_signal_handlers_destroy (object);
1.121 +
1.122 + G_OBJECT_CLASS (gmyth_uri_parent_class)->finalize (object);
1.123 +}
1.124 +
1.125 +/** Creates a new instance of GMythURI.
1.126 + *
1.127 + * @return a new instance of GMythURI.
1.128 + */
1.129 +GMythURI *
1.130 +gmyth_uri_new (void)
1.131 +{
1.132 + GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
1.133 +
1.134 + return gmyth_uri;
1.135 +}
1.136 +
1.137 +/** Creates a new instance of GMythURI.
1.138 + *
1.139 + * @return a new instance of GMythURI.
1.140 + */
1.141 +GMythURI *
1.142 +gmyth_uri_new_with_value (const gchar *value)
1.143 +{
1.144 + GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
1.145 +
1.146 + gmyth_uri_parser_setup_and_new (gmyth_uri, value);
1.147 +
1.148 + return gmyth_uri;
1.149 +}
1.150 +
1.151 +static gint
1.152 +gmyth_strstr (const gchar *haystack, const gchar *needle)
1.153 +{
1.154 +
1.155 + gchar *strPos;
1.156 +
1.157 + if (haystack == NULL || needle == NULL)
1.158 + return -1;
1.159 + strPos = strstr(haystack, needle);
1.160 + if (strPos == NULL)
1.161 + return -1;
1.162 +
1.163 + return (strPos - haystack);
1.164 +
1.165 +}
1.166 +
1.167 +static gboolean
1.168 +gmyth_uri_isabsolute (const GMythURI *uri)
1.169 +{
1.170 + gboolean ret = FALSE;
1.171 +
1.172 + g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->protocol != NULL, FALSE );
1.173 +
1.174 + if ( gmyth_strstr( uri->uri->str, GMYTH_URI_PROTOCOL_DELIM ) == 0 || strlen(uri->protocol->str) > 0 )
1.175 + ret = TRUE;
1.176 +
1.177 + return ret;
1.178 +}
1.179 +
1.180 +static gint
1.181 +gmyth_strrchr( const gchar *str, const gchar *chars, const gint nchars )
1.182 +{
1.183 +
1.184 + gint strLen;
1.185 + gint i, j;
1.186 +
1.187 + if ( str == NULL || chars == NULL )
1.188 + return -1;
1.189 +
1.190 + strLen = strlen( str );
1.191 + for ( i= (strLen-1); 0 <= i; i-- ) {
1.192 + for ( j=0; j<nchars; j++ ) {
1.193 + if ( str[i] == chars[j] )
1.194 + return i;
1.195 + }
1.196 + }
1.197 +
1.198 + return -1;
1.199 +
1.200 +}
1.201 +
1.202 +static gchar*
1.203 +gmyth_uri_print_field( const GString* field )
1.204 +{
1.205 + if ( field != NULL && field->str != NULL && strlen(field->str) > 0 )
1.206 + return field->str;
1.207 + else
1.208 + return "";
1.209 +}
1.210 +
1.211 +static void
1.212 +gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value )
1.213 +{
1.214 +
1.215 + gint uriLen;
1.216 + gint currIdx;
1.217 + gint protoIdx;
1.218 + gint atIdx;
1.219 + gint colonIdx;
1.220 + gint shashIdx;
1.221 + gint eIdx;
1.222 + gchar *host;
1.223 + gint eblacketIdx;
1.224 + gint hostLen;
1.225 + gint sharpIdx;
1.226 + /*
1.227 + gint questionIdx;
1.228 + gint queryLen;
1.229 + */
1.230 +
1.231 + uriLen = strlen(value);
1.232 + uri->uri = g_string_new( value );
1.233 +
1.234 + currIdx = 0;
1.235 +
1.236 + /*** Protocol ****/
1.237 + protoIdx = gmyth_strstr (value, GMYTH_URI_PROTOCOL_DELIM);
1.238 + if (0 < protoIdx) {
1.239 + uri->protocol = g_string_new_len (value, protoIdx);
1.240 + currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM );
1.241 + }
1.242 +
1.243 + /*** User (Password) ****/
1.244 + atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM );
1.245 + if ( 0 < atIdx ) {
1.246 + colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM );
1.247 +
1.248 + if (0 < colonIdx && colonIdx < atIdx) {
1.249 + uri->user = g_string_new_len (value+currIdx, colonIdx);
1.250 + uri->password = g_string_new_len (value+currIdx+colonIdx+1, atIdx - (colonIdx+1));
1.251 + }
1.252 + else
1.253 + uri->user = g_string_new_len (value+currIdx, atIdx - currIdx);
1.254 + currIdx += atIdx + 1;
1.255 + }
1.256 +
1.257 + /*** Host (Port) ****/
1.258 + shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM );
1.259 + if (0 < shashIdx)
1.260 + uri->host = g_string_new_len (value+currIdx, shashIdx);
1.261 + else if ( gmyth_uri_isabsolute(uri) == TRUE )
1.262 + uri->host = g_string_new_len (value+currIdx, strlen (value) - currIdx);
1.263 +
1.264 + host = gmyth_uri_get_host(uri);
1.265 + colonIdx = gmyth_strrchr (host, GMYTH_URI_COLON_DELIM, 1);
1.266 + eblacketIdx = gmyth_strrchr (host, GMYTH_URI_EBLACET_DELIM, 1);
1.267 + if ( ( 0 < colonIdx ) && ( eblacketIdx < colonIdx ) ) {
1.268 + GString *portStr = NULL;
1.269 + GString *hostStr = g_string_new (host != NULL ? host : "");
1.270 +
1.271 + hostLen = hostStr->len;
1.272 + /**** host ****/
1.273 + uri->host = g_string_erase (uri->host, 0, hostLen);
1.274 + uri->host = g_string_insert_len (uri->host, 0, hostStr->str, colonIdx);
1.275 + if (0 < hostLen) {
1.276 + if (host[0] == '[' && host[hostLen-1] == ']')
1.277 + uri->host = g_string_new_len (hostStr->str+1, colonIdx-2);
1.278 + }
1.279 + /**** port ****/
1.280 + portStr = g_string_new_len (hostStr->str+colonIdx+1, hostLen-colonIdx-1);
1.281 + uri->port = (gint)g_ascii_strtoull( portStr->str, NULL, 10 );
1.282 + g_string_free (portStr, TRUE);
1.283 + g_string_free (hostStr, TRUE);
1.284 + }
1.285 + else {
1.286 + const gchar* protocol = gmyth_uri_get_protocol(uri);
1.287 + uri->port = GMYTH_URI_KNKOWN_PORT;
1.288 + if ( strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0 )
1.289 + uri->port = GMYTH_URI_DEFAULT_HTTP_PORT;
1.290 + if ( strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0 )
1.291 + uri->port = GMYTH_URI_DEFAULT_FTP_PORT;
1.292 + }
1.293 +
1.294 + if (shashIdx > 0) currIdx += shashIdx;
1.295 +
1.296 + /*
1.297 + Handle relative URL
1.298 + */
1.299 + if (gmyth_uri_isabsolute(uri) == FALSE)
1.300 + {
1.301 +
1.302 + if (shashIdx != 0)
1.303 + {
1.304 + /* Add slash delimiter at the beginning of the URL,
1.305 + if it doesn't exist
1.306 + */
1.307 + uri->path = g_string_new( GMYTH_URI_SLASH_DELIM );
1.308 + }
1.309 + uri->path = g_string_append( uri->path, value );
1.310 +
1.311 + } else {
1.312 + /* First set path simply to the rest of URI */
1.313 + uri->path = g_string_new_len (value+currIdx, uriLen-currIdx );
1.314 + }
1.315 +
1.316 + gmyth_debug( "uri value: %s", value );
1.317 + uri->query = g_string_new ( g_strstr_len( value, strlen(value), GMYTH_URI_E_DELIM ) );
1.318 +
1.319 + eIdx = gmyth_strstr( value+currIdx, GMYTH_URI_E_DELIM );
1.320 +
1.321 + if ( 0 < eIdx ) {
1.322 + uri->query = g_string_new ( g_strstr_len( value, strlen(value), GMYTH_URI_E_DELIM ) );
1.323 + gmyth_debug( "query = %s", uri->query->str );
1.324 + }
1.325 +
1.326 + /**** Path (Query/Fragment) ****/
1.327 + sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM);
1.328 + if (0 < sharpIdx) {
1.329 + uri->path = g_string_append_len( uri->path, value+currIdx, sharpIdx);
1.330 + uri->fragment = g_string_new_len (value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1));
1.331 + }
1.332 +
1.333 + gmyth_debug( "[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "\
1.334 + "user = %s, password = %s.\n", __FUNCTION__, gmyth_uri_print_field( uri->host ), uri->port,
1.335 + gmyth_uri_print_field( uri->path ), gmyth_uri_print_field( uri->query ), gmyth_uri_print_field( uri->fragment ),
1.336 + gmyth_uri_print_field ( uri->user ), gmyth_uri_print_field( uri->password ) );
1.337 +
1.338 +}
1.339 +
1.340 +gboolean
1.341 +gmyth_uri_is_equals( GMythURI* uri1, GMythURI* uri2 )
1.342 +{
1.343 + return ( g_ascii_strcasecmp( gmyth_uri_get_host( uri1 ), gmyth_uri_get_host( uri2 ) ) == 0 &&
1.344 + gmyth_uri_get_port( uri1 ) == gmyth_uri_get_port( uri2 ) );
1.345 +}
1.346 +
1.347 +gboolean
1.348 +gmyth_uri_is_livetv( GMythURI* uri )
1.349 +{
1.350 + gboolean ret = FALSE;
1.351 +
1.352 + g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->uri->str != NULL, FALSE );
1.353 +
1.354 + ret = ( g_strstr_len( uri->uri->str, strlen( uri->uri->str ), "/?" ) != NULL );
1.355 +
1.356 + if ( ret )
1.357 + gmyth_debug( "This URI is a LiveTV recording..." );
1.358 +
1.359 + return ret;
1.360 +
1.361 +}
1.362 +
1.363 +gchar*
1.364 +gmyth_uri_get_channel_name( GMythURI* uri )
1.365 +{
1.366 + gchar* channel = NULL;
1.367 +
1.368 + g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->uri->str != NULL, FALSE );
1.369 +
1.370 + gchar *channel_query = g_strstr_len( gmyth_uri_get_query( uri ), strlen( gmyth_uri_get_query( uri ) ), "channel" );
1.371 +
1.372 + if ( channel_query != NULL )
1.373 + {
1.374 + gmyth_debug( "TV Channel is in the following URI segment: %s", channel_query );
1.375 +
1.376 + gchar **chan_key_value = g_strsplit( gmyth_uri_get_query( uri ), "=", 2 );
1.377 +
1.378 + /* gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0], chan_key_value[1] ); */
1.379 +
1.380 + if ( chan_key_value[1] != NULL )
1.381 + {
1.382 + channel = g_strdup( chan_key_value[1] );
1.383 + }
1.384 +
1.385 + if ( chan_key_value != NULL )
1.386 + g_strfreev( chan_key_value );
1.387 + }
1.388 +
1.389 + gmyth_debug( "Got channel decimal value from the URI: %s", channel );
1.390 +
1.391 + return channel;
1.392 +
1.393 +}
1.394 +
1.395 +gint
1.396 +gmyth_uri_get_channel_num( GMythURI* uri )
1.397 +{
1.398 + gchar *channel_name = gmyth_uri_get_channel_name( uri );
1.399 +
1.400 + if ( channel_name != NULL )
1.401 + {
1.402 + return g_ascii_strtoull( channel_name, NULL, 10 );
1.403 + }
1.404 +
1.405 + return -1;
1.406 +
1.407 +}