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