gmyth/src/gmyth_uri.c
author renatofilho
Thu Nov 30 14:27:14 2006 +0000 (2006-11-30)
branchtrunk
changeset 144 352ead2e7867
parent 143 f1f98329934e
child 145 af12962f4fd2
permissions -rwxr-xr-x
[svn r145] bug fix
     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 #include <glib.h>
    31 #include <string.h>
    32 #include <stdlib.h>
    33 
    34 #include "gmyth_uri.h"
    35 #include "gmyth_debug.h"
    36 
    37 static void gmyth_string_list_class_init          (GMythURIClass *klass);
    38 static void gmyth_uri_init                (GMythURI *object);
    39 
    40 static void gmyth_uri_dispose  (GObject *object);
    41 static void gmyth_uri_finalize (GObject *object);
    42 
    43 G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT)
    44 
    45 static void
    46 gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value );
    47     
    48 static void
    49 gmyth_uri_class_init (GMythURIClass *klass)
    50 {
    51 	GObjectClass *gobject_class;
    52 
    53     gobject_class = (GObjectClass *) klass;
    54 	
    55     gobject_class->dispose  = gmyth_uri_dispose;
    56     gobject_class->finalize = gmyth_uri_finalize;	
    57 }
    58 
    59 static void
    60 gmyth_uri_init (GMythURI *gmyth_uri)
    61 {
    62 }
    63 
    64 static void
    65 gmyth_uri_dispose  (GObject *object)
    66 {
    67 	GMythURI *gmyth_uri = GMYTH_URI(object);
    68 
    69 	if ( gmyth_uri->host != NULL ) {
    70 		g_string_free( gmyth_uri->host, TRUE );
    71 		gmyth_uri->host = NULL;
    72 	}
    73 	
    74 	if ( gmyth_uri->protocol != NULL ) {
    75 		g_string_free( gmyth_uri->protocol, TRUE );
    76 		gmyth_uri->protocol = NULL;
    77 	}
    78 	
    79 	if ( gmyth_uri->path != NULL ) {
    80 		g_string_free( gmyth_uri->path, TRUE );
    81 		gmyth_uri->path = NULL;
    82 	}
    83 	
    84 	if ( gmyth_uri->fragment != NULL ) {
    85 		g_string_free( gmyth_uri->fragment, TRUE );
    86 		gmyth_uri->fragment = NULL;
    87 	}
    88 	
    89 	if ( gmyth_uri->user != NULL ) {
    90 		g_string_free( gmyth_uri->user, TRUE );
    91 		gmyth_uri->user = NULL;
    92 	}
    93 	
    94 	if ( gmyth_uri->password != NULL ) {
    95 		g_string_free( gmyth_uri->password, TRUE );
    96 		gmyth_uri->password = NULL;
    97 	}
    98 	
    99 	if ( gmyth_uri->query != NULL ) {
   100 		g_string_free( gmyth_uri->query, TRUE );
   101 		gmyth_uri->query = NULL;
   102 	}	
   103 
   104 	G_OBJECT_CLASS (gmyth_uri_parent_class)->dispose (object);
   105 }
   106 
   107 static void
   108 gmyth_uri_finalize (GObject *object)
   109 {
   110 	//GMythURI *gmyth_uri = GMYTH_URI(object);
   111 
   112 	g_signal_handlers_destroy (object);
   113 
   114 	G_OBJECT_CLASS (gmyth_uri_parent_class)->finalize (object);
   115 }
   116 
   117 /** Creates a new instance of GMythURI.
   118  * 
   119  * @return a new instance of GMythURI.
   120  */
   121 GMythURI *
   122 gmyth_uri_new (void) 
   123 {
   124     GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
   125     
   126     return gmyth_uri;
   127 }
   128 
   129 /** Creates a new instance of GMythURI.
   130  * 
   131  * @return a new instance of GMythURI.
   132  */
   133 GMythURI *
   134 gmyth_uri_new_with_value (const gchar *value) 
   135 {
   136     GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
   137     
   138     gmyth_uri_parser_setup_and_new (gmyth_uri, value);
   139     
   140     return gmyth_uri;
   141 }
   142 
   143 static gint 
   144 gmyth_strstr (const gchar *haystack, const gchar *needle)
   145 {
   146 	
   147 	gchar *strPos;
   148 	
   149 	if (haystack == NULL || needle == NULL)
   150 		return -1;
   151 	strPos = strstr(haystack, needle);
   152 	if (strPos == NULL)
   153 		return -1;
   154 		
   155 	return (strPos - haystack);
   156 
   157 }
   158 
   159 static gboolean
   160 gmyth_uri_isabsolute (const GMythURI *uri)
   161 {
   162 	gboolean ret = FALSE;
   163 	
   164 	g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->protocol != NULL, FALSE );
   165 	
   166 	if ( gmyth_strstr( uri->uri->str, GMYTH_URI_PROTOCOL_DELIM ) == 0 || strlen(uri->protocol->str) > 0 )
   167 		ret = TRUE;
   168 		
   169 	return ret;	
   170 }
   171 
   172 static gint
   173 gmyth_strrchr( const gchar *str, const gchar *chars, const gint nchars )
   174 {
   175 
   176 	gint strLen;
   177 	gint i, j;
   178 	
   179 	if ( str == NULL || chars == NULL )
   180 		return -1;
   181 		
   182 	strLen = strlen( str );
   183 	for ( i= (strLen-1); 0 <= i; i-- ) {
   184 		for ( j=0; j<nchars; j++ ) {
   185 			if ( str[i] == chars[j] )
   186 				return i;
   187 		}
   188 	}
   189 
   190 	return -1;
   191 
   192 }
   193 
   194 static void
   195 gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value )
   196 {
   197 	
   198 	gint 		uriLen;
   199 	gint 		currIdx;
   200 	gint 		protoIdx;
   201 	gint 		atIdx;
   202 	gint 		colonIdx;
   203 	gint 		shashIdx;
   204 	gchar 	    *host;
   205 	gint 		eblacketIdx;
   206 	gint 		hostLen;
   207 	gint 		sharpIdx;
   208 	gint 		questionIdx;
   209 	gint 		queryLen;
   210 	
   211 	uriLen = strlen(value);
   212 	uri->uri = g_string_new( value );
   213 		
   214 	currIdx = 0;
   215 	
   216 	/*** Protocol ****/
   217 	protoIdx = gmyth_strstr (value, GMYTH_URI_PROTOCOL_DELIM);
   218 	if (0 < protoIdx) {
   219         uri->protocol = g_string_new_len (value, protoIdx);
   220 		currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM );
   221 	}
   222 
   223 	/*** User (Password) ****/
   224 	atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM );
   225 	if ( 0 < atIdx ) {
   226 		colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM );
   227 
   228 		if (0 < colonIdx && colonIdx < atIdx) {
   229             uri->user = g_string_new_len (value+currIdx, colonIdx);
   230             uri->password = g_string_new_len (value+currIdx+colonIdx+1, atIdx - (colonIdx+1));
   231 		}
   232 		else
   233             uri->user = g_string_new_len (value+currIdx, atIdx - currIdx);
   234 		currIdx += atIdx + 1;
   235 	}
   236 
   237 	/*** Host (Port) ****/
   238 	shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM );
   239 	if (0 < shashIdx)
   240         uri->host = g_string_new_len (value+currIdx, shashIdx);
   241 	else if ( gmyth_uri_isabsolute(uri) == TRUE )
   242         uri->host = g_string_new_len (value+currIdx, strlen (value) - currIdx);
   243 	host = g_strdup( gmyth_uri_get_host(uri) );
   244 	colonIdx = gmyth_strrchr (host, GMYTH_URI_COLON_DELIM, 1);
   245 	eblacketIdx = gmyth_strrchr (host, GMYTH_URI_EBLACET_DELIM, 1);
   246 	if ( ( 0 < colonIdx ) && ( eblacketIdx < colonIdx ) ) {
   247         GString *portStr = NULL;
   248 		GString *hostStr = g_string_new  (host);
   249 
   250 		hostLen = hostStr->len;
   251 		/**** host ****/
   252 		uri->host = g_string_erase (uri->host, 0, hostLen);
   253 		uri->host = g_string_insert_len (uri->host, 0, hostStr->str, colonIdx);
   254 		if (0 < hostLen) {
   255 			if (host[0] == '[' && host[hostLen-1] == ']')
   256                 uri->host = g_string_new_len (hostStr->str+1, colonIdx-2);
   257 		}
   258 		/**** port ****/
   259 		portStr = g_string_new_len (hostStr->str+colonIdx+1, hostLen-colonIdx-1);
   260 		uri->port = (gint)g_ascii_strtoull( portStr->str, NULL, 10 );
   261 		g_string_free( portStr, TRUE );
   262 		g_string_free( hostStr, FALSE );
   263 	}
   264 	else {
   265         const gchar* protocol = gmyth_uri_get_protocol(uri);
   266 		uri->port = GMYTH_URI_KNKOWN_PORT;
   267 		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0 )
   268 			uri->port = GMYTH_URI_DEFAULT_HTTP_PORT;
   269 		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0 )
   270 			uri->port = GMYTH_URI_DEFAULT_FTP_PORT;
   271 	}
   272     g_free (host);
   273 	
   274 	if (shashIdx > 0) currIdx += shashIdx;
   275 	
   276 	/*
   277 		Handle relative URL
   278 	*/
   279 	if (gmyth_uri_isabsolute(uri) == FALSE)
   280 	{
   281 
   282 		if (shashIdx != 0)
   283 		{
   284 			/* Add slash delimiter at the beginning of the URL,
   285 			   if it doesn't exist 
   286 			*/
   287 			uri->path = g_string_new( GMYTH_URI_SLASH_DELIM );
   288 		}
   289 		uri->path = g_string_append( uri->path, value );
   290 		
   291 	} else {
   292 		/* First set path simply to the rest of URI */
   293 		uri->path = g_string_new_len (value+currIdx,  uriLen-currIdx );
   294 	}
   295 		
   296 	/**** Path (Query/Fragment) ****/
   297 	sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM);
   298 	if (0 < sharpIdx) {
   299 		uri->path = g_string_append_len( uri->path, value+currIdx, sharpIdx);
   300 		uri->fragment = g_string_new_len (value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1));
   301 	}
   302 	
   303 	questionIdx = gmyth_strstr( value+currIdx, GMYTH_URI_QUESTION_DELIM );
   304 	if ( 0 < questionIdx ) {
   305 		uri->path = g_string_append_len (uri->path, value+currIdx, questionIdx );
   306 		queryLen = uriLen-(currIdx+questionIdx+1);
   307 		if ( 0 < sharpIdx )
   308 			queryLen -= uriLen - (currIdx+sharpIdx+1);
   309 		uri->query = g_string_new_len (value+currIdx+questionIdx+1, queryLen );
   310 	}
   311 	gmyth_debug( "[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "\
   312 								"user = %s, password = %s.\n", __FUNCTION__, uri->host->str, uri->port,
   313 													uri->path->str, uri->query->str, uri->fragment->str,
   314 													uri->user->str, uri->password->str );
   315 
   316 }
   317 
   318 gboolean
   319 gmyth_uri_is_equals( GMythURI* uri1, GMythURI* uri2 )
   320 {
   321 	return ( g_ascii_strcasecmp( gmyth_uri_get_host( uri1 ), gmyth_uri_get_host( uri2 ) ) == 0 &&
   322 				gmyth_uri_get_port( uri1 ) == gmyth_uri_get_port( uri2 ) );
   323 }
   324