branches/gmyth-0.1b/src/gmyth_uri.c
author rosfran
Wed Feb 14 21:28:49 2007 +0000 (2007-02-14)
branchtrunk
changeset 360 6d5596b9eb95
permissions -rwxr-xr-x
[svn r362] Some fixes in the GIOWatcher clean-ups, and changed the API version number.
     1 /** 
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_uri.c
     5  * 
     6  * @brief <p> GMythURI utils
     7  *  - Extracts and parses a URI char string, in according with the RFC 2396 
     8  *    [http://www.ietf.org/rfc/rfc2396.txt]
     9  * 
    10  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    11  * @author Rosfran Borges <rosfran.borges@indt.org.br>
    12  *
    13  *//*
    14  * 
    15  * This program is free software; you can redistribute it and/or modify
    16  * it under the terms of the GNU Lesser General Public License as published by
    17  * the Free Software Foundation; either version 2 of the License, or
    18  * (at your option) any later version.
    19  *
    20  * This program is distributed in the hope that it will be useful,
    21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    23  * GNU General Public License for more details.
    24  *
    25  * You should have received a copy of the GNU Lesser General Public License
    26  * along with this program; if not, write to the Free Software
    27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    28  */
    29  
    30 #ifdef HAVE_CONFIG_H
    31 #include "config.h"
    32 #endif
    33 
    34 #include "gmyth_uri.h"
    35 
    36 #include <glib.h>
    37 #include <string.h>
    38 #include <stdlib.h>
    39 
    40 #include "gmyth_debug.h"
    41 
    42 static void gmyth_uri_class_init          (GMythURIClass *klass);
    43 static void gmyth_uri_init                (GMythURI *object);
    44 
    45 static void gmyth_uri_dispose  (GObject *object);
    46 static void gmyth_uri_finalize (GObject *object);
    47 
    48 G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT)
    49 
    50 static void
    51 gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value );
    52     
    53 static void
    54 gmyth_uri_class_init (GMythURIClass *klass)
    55 {
    56 	GObjectClass *gobject_class;
    57 
    58     gobject_class = (GObjectClass *) klass;
    59 	
    60     gobject_class->dispose  = gmyth_uri_dispose;
    61     gobject_class->finalize = gmyth_uri_finalize;	
    62 }
    63 
    64 static void
    65 gmyth_uri_init (GMythURI *gmyth_uri)
    66 {
    67 }
    68 
    69 static void
    70 gmyth_uri_dispose  (GObject *object)
    71 {
    72 	GMythURI *gmyth_uri = GMYTH_URI(object);
    73 
    74 	if ( gmyth_uri->host != NULL ) {
    75 		g_string_free( gmyth_uri->host, TRUE );
    76 		gmyth_uri->host = NULL;
    77 	}
    78 	
    79 	if ( gmyth_uri->protocol != NULL ) {
    80 		g_string_free( gmyth_uri->protocol, TRUE );
    81 		gmyth_uri->protocol = NULL;
    82 	}
    83 	
    84 	if ( gmyth_uri->path != NULL ) {
    85 		g_string_free( gmyth_uri->path, TRUE );
    86 		gmyth_uri->path = NULL;
    87 	}
    88 	
    89 	if ( gmyth_uri->fragment != NULL ) {
    90 		g_string_free( gmyth_uri->fragment, TRUE );
    91 		gmyth_uri->fragment = NULL;
    92 	}
    93 	
    94 	if ( gmyth_uri->user != NULL ) {
    95 		g_string_free( gmyth_uri->user, TRUE );
    96 		gmyth_uri->user = NULL;
    97 	}
    98 	
    99 	if ( gmyth_uri->password != NULL ) {
   100 		g_string_free( gmyth_uri->password, TRUE );
   101 		gmyth_uri->password = NULL;
   102 	}
   103 	
   104 	if ( gmyth_uri->query != NULL ) {
   105 		g_string_free( gmyth_uri->query, TRUE );
   106 		gmyth_uri->query = NULL;
   107 	}	
   108 
   109 	G_OBJECT_CLASS (gmyth_uri_parent_class)->dispose (object);
   110 }
   111 
   112 static void
   113 gmyth_uri_finalize (GObject *object)
   114 {
   115 	//GMythURI *gmyth_uri = GMYTH_URI(object);
   116 
   117 	g_signal_handlers_destroy (object);
   118 
   119 	G_OBJECT_CLASS (gmyth_uri_parent_class)->finalize (object);
   120 }
   121 
   122 /** Creates a new instance of GMythURI.
   123  * 
   124  * @return a new instance of GMythURI.
   125  */
   126 GMythURI *
   127 gmyth_uri_new (void) 
   128 {
   129     GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
   130     
   131     return gmyth_uri;
   132 }
   133 
   134 /** Creates a new instance of GMythURI.
   135  * 
   136  * @return a new instance of GMythURI.
   137  */
   138 GMythURI *
   139 gmyth_uri_new_with_value (const gchar *value) 
   140 {
   141     GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
   142     
   143     gmyth_uri_parser_setup_and_new (gmyth_uri, value);
   144     
   145     return gmyth_uri;
   146 }
   147 
   148 static gint 
   149 gmyth_strstr (const gchar *haystack, const gchar *needle)
   150 {
   151 	
   152 	gchar *strPos;
   153 	
   154 	if (haystack == NULL || needle == NULL)
   155 		return -1;
   156 	strPos = strstr(haystack, needle);
   157 	if (strPos == NULL)
   158 		return -1;
   159 		
   160 	return (strPos - haystack);
   161 
   162 }
   163 
   164 static gboolean
   165 gmyth_uri_isabsolute (const GMythURI *uri)
   166 {
   167 	gboolean ret = FALSE;
   168 	
   169 	g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->protocol != NULL, FALSE );
   170 	
   171 	if ( gmyth_strstr( uri->uri->str, GMYTH_URI_PROTOCOL_DELIM ) == 0 || strlen(uri->protocol->str) > 0 )
   172 		ret = TRUE;
   173 		
   174 	return ret;	
   175 }
   176 
   177 static gint
   178 gmyth_strrchr( const gchar *str, const gchar *chars, const gint nchars )
   179 {
   180 
   181 	gint strLen;
   182 	gint i, j;
   183 	
   184 	if ( str == NULL || chars == NULL )
   185 		return -1;
   186 		
   187 	strLen = strlen( str );
   188 	for ( i= (strLen-1); 0 <= i; i-- ) {
   189 		for ( j=0; j<nchars; j++ ) {
   190 			if ( str[i] == chars[j] )
   191 				return i;
   192 		}
   193 	}
   194 
   195 	return -1;
   196 
   197 }
   198 
   199 static gchar*
   200 gmyth_uri_print_field( const GString* field )
   201 {
   202 	if ( field != NULL && field->str != NULL && strlen(field->str) > 0 )
   203 		return field->str;
   204 	else
   205 		return "";		
   206 }
   207 
   208 static void
   209 gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value )
   210 {
   211 	
   212 	gint 		uriLen;
   213 	gint 		currIdx;
   214 	gint 		protoIdx;
   215 	gint 		atIdx;
   216 	gint 		colonIdx;
   217 	gint 		shashIdx;
   218 	gint 		eIdx;
   219 	gchar 	*host;
   220 	gint 		eblacketIdx;
   221 	gint 		hostLen;
   222 	gint 		sharpIdx;
   223 	/*
   224 	gint 		questionIdx;
   225 	gint 		queryLen;
   226 	*/
   227 	
   228 	uriLen = strlen(value);
   229 	uri->uri = g_string_new( value );
   230 		
   231 	currIdx = 0;
   232 	
   233 	/*** Protocol ****/
   234 	protoIdx = gmyth_strstr (value, GMYTH_URI_PROTOCOL_DELIM);
   235 	if (0 < protoIdx) {
   236         uri->protocol = g_string_new_len (value, protoIdx);
   237 		currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM );
   238 	}
   239 
   240 	/*** User (Password) ****/
   241 	atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM );
   242 	if ( 0 < atIdx ) {
   243 		colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM );
   244 
   245 		if (0 < colonIdx && colonIdx < atIdx) {
   246             uri->user = g_string_new_len (value+currIdx, colonIdx);
   247             uri->password = g_string_new_len (value+currIdx+colonIdx+1, atIdx - (colonIdx+1));
   248 		}
   249 		else
   250             uri->user = g_string_new_len (value+currIdx, atIdx - currIdx);
   251 		currIdx += atIdx + 1;
   252 	}
   253 
   254 	/*** Host (Port) ****/
   255 	shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM );
   256 	if (0 < shashIdx)
   257         uri->host = g_string_new_len (value+currIdx, shashIdx);
   258 	else if ( gmyth_uri_isabsolute(uri) == TRUE )
   259         uri->host = g_string_new_len (value+currIdx, strlen (value) - currIdx);
   260 
   261 	host = gmyth_uri_get_host(uri);
   262 	colonIdx = gmyth_strrchr (host, GMYTH_URI_COLON_DELIM, 1);
   263 	eblacketIdx = gmyth_strrchr (host, GMYTH_URI_EBLACET_DELIM, 1);
   264 	if ( ( 0 < colonIdx ) && ( eblacketIdx < colonIdx ) ) {
   265         GString *portStr = NULL;
   266 		GString *hostStr = g_string_new  (host != NULL ? host : "");
   267 
   268 		hostLen = hostStr->len;
   269 		/**** host ****/
   270 		uri->host = g_string_erase (uri->host, 0, hostLen);
   271 		uri->host = g_string_insert_len (uri->host, 0, hostStr->str, colonIdx);
   272 		if (0 < hostLen) {
   273 			if (host[0] == '[' && host[hostLen-1] == ']')
   274                 uri->host = g_string_new_len (hostStr->str+1, colonIdx-2);
   275 		}
   276 		/**** port ****/
   277 		portStr = g_string_new_len (hostStr->str+colonIdx+1, hostLen-colonIdx-1);
   278 		uri->port = (gint)g_ascii_strtoull( portStr->str, NULL, 10 );
   279 		g_string_free (portStr, TRUE);
   280 		g_string_free (hostStr, TRUE);
   281 	}
   282 	else {
   283         const gchar* protocol = gmyth_uri_get_protocol(uri);
   284 		uri->port = GMYTH_URI_KNKOWN_PORT;
   285 		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0 )
   286 			uri->port = GMYTH_URI_DEFAULT_HTTP_PORT;
   287 		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0 )
   288 			uri->port = GMYTH_URI_DEFAULT_FTP_PORT;
   289 	}
   290 	
   291 	if (shashIdx > 0) currIdx += shashIdx;
   292 	
   293 	/*
   294 		Handle relative URL
   295 	*/
   296 	if (gmyth_uri_isabsolute(uri) == FALSE)
   297 	{
   298 
   299 		if (shashIdx != 0)
   300 		{
   301 			/* Add slash delimiter at the beginning of the URL,
   302 			   if it doesn't exist 
   303 			*/
   304 			uri->path = g_string_new( GMYTH_URI_SLASH_DELIM );
   305 		}
   306 		uri->path = g_string_append( uri->path, value );
   307 		
   308 	} else {
   309 		/* First set path simply to the rest of URI */
   310 		uri->path = g_string_new_len (value+currIdx,  uriLen-currIdx );
   311 	}
   312 	
   313 	gmyth_debug( "uri value:  %s", value );
   314 	uri->query = g_string_new ( g_strstr_len( value, strlen(value), GMYTH_URI_E_DELIM ) );
   315 	
   316 	eIdx = gmyth_strstr( value+currIdx, GMYTH_URI_E_DELIM );
   317 	
   318 	if ( 0 < eIdx ) {
   319 		uri->query = g_string_new ( g_strstr_len( value, strlen(value), GMYTH_URI_E_DELIM ) );
   320 		gmyth_debug( "query = %s", uri->query->str );
   321 	}
   322 	
   323 	/**** Path (Query/Fragment) ****/
   324 	sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM);
   325 	if (0 < sharpIdx) {
   326 		uri->path = g_string_append_len( uri->path, value+currIdx, sharpIdx);
   327 		uri->fragment = g_string_new_len (value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1));
   328 	}	
   329 
   330 	gmyth_debug( "[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "\
   331 								"user = %s, password = %s.\n", __FUNCTION__, gmyth_uri_print_field( uri->host ), uri->port,
   332 													gmyth_uri_print_field( uri->path ), gmyth_uri_print_field( uri->query ), gmyth_uri_print_field( uri->fragment ),
   333 													gmyth_uri_print_field ( uri->user ), gmyth_uri_print_field( uri->password ) );
   334 
   335 }
   336 
   337 gboolean
   338 gmyth_uri_is_equals( GMythURI* uri1, GMythURI* uri2 )
   339 {
   340 	return ( g_ascii_strcasecmp( gmyth_uri_get_host( uri1 ), gmyth_uri_get_host( uri2 ) ) == 0 &&
   341 				gmyth_uri_get_port( uri1 ) == gmyth_uri_get_port( uri2 ) );
   342 }
   343 
   344 gboolean
   345 gmyth_uri_is_livetv( GMythURI* uri )
   346 {
   347 	gboolean ret = FALSE;
   348 	
   349 	g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->uri->str != NULL, FALSE );
   350 	
   351 	ret = ( g_strstr_len( uri->uri->str, strlen( uri->uri->str ), "/?" ) != NULL );
   352 	
   353 	if ( ret )
   354 		gmyth_debug( "This URI is a LiveTV recording..." );
   355 	
   356 	return ret;
   357 	
   358 }
   359 
   360 gchar*
   361 gmyth_uri_get_channel_name( GMythURI* uri )
   362 {
   363 	gchar* channel = NULL;
   364 	
   365 	g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->uri->str != NULL, FALSE );
   366 	
   367 	gchar *channel_query = g_strstr_len( gmyth_uri_get_query( uri ), strlen( gmyth_uri_get_query( uri ) ), "channel" );
   368 	
   369 	if ( channel_query != NULL )
   370 	{
   371 		gmyth_debug( "TV Channel is in the following URI segment: %s", channel_query );
   372 		
   373 		gchar **chan_key_value = g_strsplit( gmyth_uri_get_query( uri ), "=", 2 );
   374 		
   375 		/* gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0], chan_key_value[1] ); */
   376 
   377 		if ( chan_key_value[1] != NULL )
   378 		{
   379 			channel = g_strdup( chan_key_value[1] ); 
   380 		}
   381 
   382 		if ( chan_key_value != NULL )		
   383 			g_strfreev( chan_key_value );
   384 	}
   385 	
   386 	gmyth_debug( "Got channel decimal value from the URI: %s", channel );
   387 
   388 	return channel;
   389 	
   390 }
   391 
   392 gint
   393 gmyth_uri_get_channel_num( GMythURI* uri )
   394 {
   395 	gchar *channel_name = gmyth_uri_get_channel_name( uri );
   396 	
   397 	if ( channel_name != NULL )
   398 	{
   399 		return g_ascii_strtoull( channel_name, NULL, 10 ); 
   400 	}
   401 	
   402 	return -1;
   403 	
   404 }