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