gmyth/src/gmyth_uri.c
author morphbr
Fri Jan 12 21:26:30 2007 +0000 (2007-01-12)
branchtrunk
changeset 268 91eb7e03b1b1
parent 150 ae6deaca5e7b
child 279 5a224299ab37
permissions -rwxr-xr-x
[svn r269] Changed structure from gmyth_http to use *libcurl*.
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@139
    42
static void gmyth_string_list_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;
renatofilho@143
   218
	gchar 	    *host;
rosfran@139
   219
	gint 		eblacketIdx;
rosfran@139
   220
	gint 		hostLen;
rosfran@139
   221
	gint 		sharpIdx;
rosfran@139
   222
	gint 		questionIdx;
rosfran@139
   223
	gint 		queryLen;
rosfran@41
   224
	
rosfran@41
   225
	uriLen = strlen(value);
rosfran@41
   226
	uri->uri = g_string_new( value );
rosfran@41
   227
		
rosfran@41
   228
	currIdx = 0;
rosfran@41
   229
	
rosfran@41
   230
	/*** Protocol ****/
renatofilho@143
   231
	protoIdx = gmyth_strstr (value, GMYTH_URI_PROTOCOL_DELIM);
rosfran@41
   232
	if (0 < protoIdx) {
renatofilho@144
   233
        uri->protocol = g_string_new_len (value, protoIdx);
rosfran@41
   234
		currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM );
rosfran@41
   235
	}
rosfran@41
   236
rosfran@41
   237
	/*** User (Password) ****/
rosfran@41
   238
	atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM );
rosfran@41
   239
	if ( 0 < atIdx ) {
rosfran@41
   240
		colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM );
rosfran@41
   241
rosfran@41
   242
		if (0 < colonIdx && colonIdx < atIdx) {
renatofilho@144
   243
            uri->user = g_string_new_len (value+currIdx, colonIdx);
renatofilho@144
   244
            uri->password = g_string_new_len (value+currIdx+colonIdx+1, atIdx - (colonIdx+1));
rosfran@41
   245
		}
renatofilho@144
   246
		else
renatofilho@144
   247
            uri->user = g_string_new_len (value+currIdx, atIdx - currIdx);
rosfran@41
   248
		currIdx += atIdx + 1;
rosfran@41
   249
	}
rosfran@41
   250
rosfran@41
   251
	/*** Host (Port) ****/
rosfran@41
   252
	shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM );
renatofilho@144
   253
	if (0 < shashIdx)
renatofilho@144
   254
        uri->host = g_string_new_len (value+currIdx, shashIdx);
rosfran@41
   255
	else if ( gmyth_uri_isabsolute(uri) == TRUE )
renatofilho@144
   256
        uri->host = g_string_new_len (value+currIdx, strlen (value) - currIdx);
renatofilho@147
   257
renatofilho@147
   258
	host = gmyth_uri_get_host(uri);
renatofilho@143
   259
	colonIdx = gmyth_strrchr (host, GMYTH_URI_COLON_DELIM, 1);
renatofilho@143
   260
	eblacketIdx = gmyth_strrchr (host, GMYTH_URI_EBLACET_DELIM, 1);
rosfran@41
   261
	if ( ( 0 < colonIdx ) && ( eblacketIdx < colonIdx ) ) {
renatofilho@143
   262
        GString *portStr = NULL;
rosfran@145
   263
		GString *hostStr = g_string_new  (host != NULL ? host : "");
rosfran@41
   264
rosfran@41
   265
		hostLen = hostStr->len;
rosfran@41
   266
		/**** host ****/
renatofilho@143
   267
		uri->host = g_string_erase (uri->host, 0, hostLen);
renatofilho@143
   268
		uri->host = g_string_insert_len (uri->host, 0, hostStr->str, colonIdx);
rosfran@41
   269
		if (0 < hostLen) {
rosfran@41
   270
			if (host[0] == '[' && host[hostLen-1] == ']')
renatofilho@144
   271
                uri->host = g_string_new_len (hostStr->str+1, colonIdx-2);
rosfran@41
   272
		}
rosfran@41
   273
		/**** port ****/
renatofilho@144
   274
		portStr = g_string_new_len (hostStr->str+colonIdx+1, hostLen-colonIdx-1);
rosfran@139
   275
		uri->port = (gint)g_ascii_strtoull( portStr->str, NULL, 10 );
renatofilho@147
   276
		g_string_free (portStr, TRUE);
renatofilho@147
   277
		g_string_free (hostStr, TRUE);
rosfran@41
   278
	}
rosfran@41
   279
	else {
renatofilho@143
   280
        const gchar* protocol = gmyth_uri_get_protocol(uri);
rosfran@41
   281
		uri->port = GMYTH_URI_KNKOWN_PORT;
rosfran@41
   282
		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0 )
rosfran@41
   283
			uri->port = GMYTH_URI_DEFAULT_HTTP_PORT;
rosfran@41
   284
		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0 )
rosfran@41
   285
			uri->port = GMYTH_URI_DEFAULT_FTP_PORT;
rosfran@41
   286
	}
rosfran@41
   287
	
rosfran@41
   288
	if (shashIdx > 0) currIdx += shashIdx;
rosfran@41
   289
	
rosfran@41
   290
	/*
rosfran@41
   291
		Handle relative URL
rosfran@41
   292
	*/
rosfran@41
   293
	if (gmyth_uri_isabsolute(uri) == FALSE)
rosfran@41
   294
	{
rosfran@41
   295
rosfran@41
   296
		if (shashIdx != 0)
rosfran@41
   297
		{
rosfran@41
   298
			/* Add slash delimiter at the beginning of the URL,
rosfran@41
   299
			   if it doesn't exist 
rosfran@41
   300
			*/
rosfran@41
   301
			uri->path = g_string_new( GMYTH_URI_SLASH_DELIM );
rosfran@41
   302
		}
rosfran@41
   303
		uri->path = g_string_append( uri->path, value );
rosfran@41
   304
		
rosfran@41
   305
	} else {
rosfran@41
   306
		/* First set path simply to the rest of URI */
renatofilho@144
   307
		uri->path = g_string_new_len (value+currIdx,  uriLen-currIdx );
rosfran@41
   308
	}
rosfran@41
   309
		
rosfran@41
   310
	/**** Path (Query/Fragment) ****/
rosfran@41
   311
	sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM);
rosfran@41
   312
	if (0 < sharpIdx) {
rosfran@41
   313
		uri->path = g_string_append_len( uri->path, value+currIdx, sharpIdx);
renatofilho@144
   314
		uri->fragment = g_string_new_len (value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1));
rosfran@41
   315
	}
rosfran@41
   316
	
rosfran@41
   317
	questionIdx = gmyth_strstr( value+currIdx, GMYTH_URI_QUESTION_DELIM );
rosfran@41
   318
	if ( 0 < questionIdx ) {
renatofilho@144
   319
		uri->path = g_string_append_len (uri->path, value+currIdx, questionIdx );
rosfran@41
   320
		queryLen = uriLen-(currIdx+questionIdx+1);
rosfran@41
   321
		if ( 0 < sharpIdx )
rosfran@41
   322
			queryLen -= uriLen - (currIdx+sharpIdx+1);
renatofilho@144
   323
		uri->query = g_string_new_len (value+currIdx+questionIdx+1, queryLen );
rosfran@41
   324
	}
rosfran@139
   325
	gmyth_debug( "[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "\
rosfran@145
   326
								"user = %s, password = %s.\n", __FUNCTION__, gmyth_uri_print_field( uri->host ), uri->port,
rosfran@145
   327
													gmyth_uri_print_field( uri->path ), gmyth_uri_print_field( uri->query ), gmyth_uri_print_field( uri->fragment ),
rosfran@145
   328
													gmyth_uri_print_field ( uri->user ), gmyth_uri_print_field( uri->password ) );
rosfran@41
   329
rosfran@41
   330
}
rosfran@104
   331
rosfran@104
   332
gboolean
rosfran@104
   333
gmyth_uri_is_equals( GMythURI* uri1, GMythURI* uri2 )
rosfran@104
   334
{
rosfran@119
   335
	return ( g_ascii_strcasecmp( gmyth_uri_get_host( uri1 ), gmyth_uri_get_host( uri2 ) ) == 0 &&
rosfran@119
   336
				gmyth_uri_get_port( uri1 ) == gmyth_uri_get_port( uri2 ) );
rosfran@104
   337
}
rosfran@104
   338