4 * @file gmyth/gmyth_uri.c
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]
10 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
11 * @author Rosfran Borges <rosfran.borges@indt.org.br>
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.
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.
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
34 #include "gmyth_uri.h"
35 #include "gmyth_debug.h"
37 static void gmyth_string_list_class_init (GMythURIClass *klass);
38 static void gmyth_uri_init (GMythURI *object);
40 static void gmyth_uri_dispose (GObject *object);
41 static void gmyth_uri_finalize (GObject *object);
43 G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT)
46 gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value );
49 gmyth_uri_class_init (GMythURIClass *klass)
51 GObjectClass *gobject_class;
53 gobject_class = (GObjectClass *) klass;
55 gobject_class->dispose = gmyth_uri_dispose;
56 gobject_class->finalize = gmyth_uri_finalize;
60 gmyth_uri_init (GMythURI *gmyth_uri)
65 gmyth_uri_dispose (GObject *object)
67 GMythURI *gmyth_uri = GMYTH_URI(object);
69 if ( gmyth_uri->host != NULL ) {
70 g_string_free( gmyth_uri->host, TRUE );
71 gmyth_uri->host = NULL;
74 if ( gmyth_uri->protocol != NULL ) {
75 g_string_free( gmyth_uri->protocol, TRUE );
76 gmyth_uri->protocol = NULL;
79 if ( gmyth_uri->path != NULL ) {
80 g_string_free( gmyth_uri->path, TRUE );
81 gmyth_uri->path = NULL;
84 if ( gmyth_uri->fragment != NULL ) {
85 g_string_free( gmyth_uri->fragment, TRUE );
86 gmyth_uri->fragment = NULL;
89 if ( gmyth_uri->user != NULL ) {
90 g_string_free( gmyth_uri->user, TRUE );
91 gmyth_uri->user = NULL;
94 if ( gmyth_uri->password != NULL ) {
95 g_string_free( gmyth_uri->password, TRUE );
96 gmyth_uri->password = NULL;
99 if ( gmyth_uri->query != NULL ) {
100 g_string_free( gmyth_uri->query, TRUE );
101 gmyth_uri->query = NULL;
104 G_OBJECT_CLASS (gmyth_uri_parent_class)->dispose (object);
108 gmyth_uri_finalize (GObject *object)
110 //GMythURI *gmyth_uri = GMYTH_URI(object);
112 g_signal_handlers_destroy (object);
114 G_OBJECT_CLASS (gmyth_uri_parent_class)->finalize (object);
117 /** Creates a new instance of GMythURI.
119 * @return a new instance of GMythURI.
124 GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
129 /** Creates a new instance of GMythURI.
131 * @return a new instance of GMythURI.
134 gmyth_uri_new_with_value (const gchar *value)
136 GMythURI *gmyth_uri = GMYTH_URI (g_object_new (GMYTH_URI_TYPE, NULL));
138 gmyth_uri_parser_setup_and_new (gmyth_uri, value);
144 gmyth_strstr (const gchar *haystack, const gchar *needle)
149 if (haystack == NULL || needle == NULL)
151 strPos = strstr(haystack, needle);
155 return (strPos - haystack);
160 gmyth_uri_isabsolute (const GMythURI *uri)
162 gboolean ret = FALSE;
164 g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->protocol != NULL, FALSE );
166 if ( gmyth_strstr( uri->uri->str, GMYTH_URI_PROTOCOL_DELIM ) == 0 || strlen(uri->protocol->str) > 0 )
173 gmyth_strrchr( const gchar *str, const gchar *chars, const gint nchars )
179 if ( str == NULL || chars == NULL )
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] )
195 gmyth_uri_parser_setup_and_new( GMythURI *uri, const gchar *value )
211 uriLen = strlen(value);
212 uri->uri = g_string_new( value );
217 protoIdx = gmyth_strstr (value, GMYTH_URI_PROTOCOL_DELIM);
219 uri->protocol = g_string_new_len (value, protoIdx);
220 currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM );
223 /*** User (Password) ****/
224 atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM );
226 colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM );
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));
233 uri->user = g_string_new_len (value+currIdx, atIdx - currIdx);
234 currIdx += atIdx + 1;
237 /*** Host (Port) ****/
238 shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM );
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);
250 hostLen = hostStr->len;
252 uri->host = g_string_erase (uri->host, 0, hostLen);
253 uri->host = g_string_insert_len (uri->host, 0, hostStr->str, colonIdx);
255 if (host[0] == '[' && host[hostLen-1] == ']')
256 uri->host = g_string_new_len (hostStr->str+1, colonIdx-2);
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 );
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;
274 if (shashIdx > 0) currIdx += shashIdx;
279 if (gmyth_uri_isabsolute(uri) == FALSE)
284 /* Add slash delimiter at the beginning of the URL,
287 uri->path = g_string_new( GMYTH_URI_SLASH_DELIM );
289 uri->path = g_string_append( uri->path, value );
292 /* First set path simply to the rest of URI */
293 uri->path = g_string_new_len (value+currIdx, uriLen-currIdx );
296 /**** Path (Query/Fragment) ****/
297 sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM);
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));
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);
308 queryLen -= uriLen - (currIdx+sharpIdx+1);
309 uri->query = g_string_new_len (value+currIdx+questionIdx+1, queryLen );
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 );
319 gmyth_uri_is_equals( GMythURI* uri1, GMythURI* uri2 )
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 ) );