Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

xurl.c

00001 /*****************************************************************************
00002  * xurl.c: URL manipulation functions
00003  *****************************************************************************
00004  * Copyright (C) 2003-2004 Commonwealth Scientific and Industrial Research
00005  *                         Organisation (CSIRO) Australia
00006  * Copyright (C) 2004 the VideoLAN team
00007  *
00008  * $Id: xurl.c 11664 2005-07-09 06:17:09Z courmisch $
00009  *
00010  * Authors: Andre Pang <[email protected]>
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  * 
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00025  *****************************************************************************/
00026 
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 
00031 #include "xurl.h"
00032 
00033 static char *streallocat( char *psz_string, char *psz_to_append );
00034 
00035 #ifndef HAVE_STRDUP
00036 static char *xurl_strdup( const char *psz_string );
00037 #else
00038 #define xurl_strdup strdup
00039 #endif
00040 
00041 static char *XURL_FindHostname          ( char *psz_url );
00042 static char *XURL_FindPath              ( char *psz_url );
00043 static char *XURL_FindFragment          ( char *psz_url );
00044 
00045 
00046 char *XURL_Join( char *psz_url1, char *psz_url2 )
00047 {
00048     if( XURL_IsAbsolute( psz_url1 ) )
00049         return XURL_Concat( psz_url1, psz_url2 );
00050     else
00051         return XURL_Concat( psz_url2, psz_url1 );
00052 
00053     return NULL;
00054 }
00055 
00056 /* TODO: replace XURL_Concat's rel/absolute calculation with the one
00057  * specified by RFC2396, and also test it on their test suite :) */
00058 
00059 
00060 char *XURL_Concat( char *psz_url, char *psz_append )
00061 {
00062     char *psz_return_value = NULL;
00063 
00064     if( XURL_IsAbsolute( psz_append ) == XURL_TRUE )
00065         return strdup( psz_append );
00066 
00067     if( XURL_IsAbsolute( psz_url ) )
00068     {
00069         if( XURL_HasAbsolutePath( psz_append ) )
00070         {
00071             char *psz_concat_url;
00072 
00073             psz_concat_url = XURL_GetSchemeAndHostname( psz_url );
00074 
00075             psz_concat_url = streallocat( psz_concat_url, psz_append );
00076 #ifdef XURL_DEBUG
00077             fprintf( stderr, "XURL_Concat: concat is \"%s\"\n",
00078                      psz_concat_url );
00079 #endif
00080             psz_return_value = psz_concat_url;
00081         }
00082         else
00083         {
00084             /* psz_append is a relative URL */
00085             char *psz_new_url;
00086             
00087             /* strip off last path component */
00088             psz_new_url = XURL_GetHead( psz_url );
00089             psz_new_url = streallocat( psz_new_url, psz_append );
00090 
00091             psz_return_value = psz_new_url;
00092         }
00093     }
00094     else
00095     {
00096         /* not an absolute URL */
00097         if( XURL_HasAbsolutePath( psz_append ) == XURL_FALSE )
00098         {
00099             char *psz_new_url = XURL_GetHead( psz_url );
00100 
00101             psz_new_url = streallocat( psz_new_url, psz_append );
00102             psz_return_value = psz_new_url;
00103         }
00104         else
00105         {
00106             /* URL to append has an absolute path -- just use that instead */
00107             psz_return_value = xurl_strdup( psz_append );
00108         }
00109     }
00110 
00111     return psz_return_value;
00112 }
00113 
00114 
00115 XURL_Bool XURL_IsAbsolute( char *psz_url )
00116 {
00117     if( XURL_FindHostname( psz_url ) == NULL )
00118     {
00119 #ifdef XURL_DEBUG
00120         fprintf( stderr, "XURL_IsAbsolute(%s) returning false\n", psz_url );
00121 #endif
00122         return XURL_FALSE;
00123     }
00124     else
00125     {
00126 #ifdef XURL_DEBUG
00127         fprintf( stderr, "XURL_IsAbsolute(%s) returning true\n", psz_url );
00128 #endif
00129         return XURL_TRUE;
00130     }
00131 }
00132 
00133 
00134 XURL_Bool XURL_HasFragment( char *psz_url )
00135 {
00136     if( XURL_FindFragment( psz_url ) == NULL )
00137         return XURL_FALSE;
00138     else
00139         return XURL_TRUE;
00140 }
00141 
00142 
00143 char *XURL_FindHostname( char *psz_url )
00144 {
00145     char *psz_return_value = NULL;
00146 
00147     char *psz_scheme_separator = strstr( psz_url, "://" );
00148     if( psz_scheme_separator != NULL)
00149     {
00150         char *psz_hostname = psz_scheme_separator + strlen( "://" );
00151         if( *psz_hostname != '\0') psz_return_value = psz_hostname;
00152 
00153 #ifdef XURL_DEBUG
00154         fprintf( stderr, "XURL_FindHostname(%s): returning \"%s\"\n",
00155                  psz_url, psz_return_value );
00156 #endif
00157     }
00158 
00159     return psz_return_value;
00160 }
00161 
00162 
00163 XURL_Bool XURL_HasAbsolutePath( char *psz_url )
00164 {
00165 #ifdef XURL_WIN32_PATHING
00166     if( psz_url[0] == '/' || psz_url[0] == '\\' )
00167 #else
00168     if( psz_url[0] == '/' )
00169 #endif
00170         return XURL_TRUE;
00171     else
00172         return XURL_FALSE;
00173 }
00174 
00175 
00176 char *XURL_GetHostname( char *psz_url )
00177 {
00178     char *psz_return_value = NULL;
00179     char *psz_hostname = XURL_FindHostname( psz_url );
00180 
00181     if( psz_hostname != NULL )
00182     {
00183         char *psz_new_hostname;
00184         size_t i_hostname_length;
00185 
00186         char *psz_one_past_end_of_hostname = strchr( psz_hostname, '/' );
00187         if( psz_one_past_end_of_hostname != NULL)
00188         {
00189             /* Found a '/' after the hostname, so copy characters between
00190              * the hostname and the '/' to a new string */
00191             i_hostname_length = psz_one_past_end_of_hostname -
00192                 psz_hostname;
00193         }
00194         else
00195         {
00196             /* Didn't find a '/', so copy from the start of the hostname
00197              * until the end of the string */
00198             i_hostname_length = strlen( psz_url ) - ( psz_hostname - psz_url );
00199         }
00200 
00201         /* Copy hostname to a new string */
00202         psz_new_hostname = xurl_malloc( i_hostname_length );
00203         if (psz_new_hostname == NULL) return NULL;
00204         strncpy( psz_new_hostname, psz_hostname, i_hostname_length );
00205 
00206 #ifdef XURL_DEBUG
00207         fprintf (stderr, "XURL_GetHostname: psz_new_hostname is \"%s\"\n",
00208                  psz_new_hostname );
00209 #endif
00210         psz_return_value = psz_new_hostname;
00211     }
00212     else
00213     {
00214         /* Didn't find a hostname */
00215         return NULL;
00216     }
00217 
00218     return psz_return_value;
00219 }
00220 
00221 
00222 char *XURL_GetSchemeAndHostname( char *psz_url )
00223 {
00224     char *psz_scheme, *psz_hostname, *psz_scheme_and_hostname;
00225 
00226     psz_scheme = XURL_GetScheme( psz_url );
00227     if( psz_scheme == NULL ) return NULL;
00228 
00229     psz_hostname = XURL_GetHostname( psz_url );
00230     if( psz_hostname == NULL ) return NULL;
00231 
00232     /* malloc +1 for the terminating '\0' */
00233     psz_scheme_and_hostname = xurl_malloc(
00234             strlen( psz_scheme ) + strlen( "://" ) +
00235             strlen( psz_hostname ) + 1);
00236     if( psz_scheme_and_hostname == NULL ) return NULL;
00237     (void) strcpy( psz_scheme_and_hostname, psz_scheme );
00238     (void) strcat( psz_scheme_and_hostname, "://" );
00239     (void) strcat( psz_scheme_and_hostname, psz_hostname );
00240 
00241     if (psz_scheme_and_hostname == NULL ) return NULL;
00242     return psz_scheme_and_hostname;
00243 }
00244 
00245 static 
00246 char *XURL_FindFragment( char *psz_url )
00247 {
00248     char *pc_hash = NULL;
00249     char *pc_return_value = NULL;
00250     
00251     pc_hash = strchr( psz_url, '#' );
00252     if( pc_hash != NULL )
00253     {
00254         pc_return_value = pc_hash;
00255     }
00256 
00257     return pc_return_value;
00258 }
00259 
00260 
00261 char *XURL_FindQuery( char *psz_url )
00262 {
00263     char *pc_question_mark = NULL;
00264     char *pc_return_value = NULL;
00265     
00266     pc_question_mark = strchr( psz_url, '?' );
00267     if( pc_question_mark != NULL )
00268     {
00269         pc_return_value = pc_question_mark;
00270     }
00271 
00272     return pc_return_value;
00273 }
00274 
00275 
00276 char *XURL_GetScheme( char *psz_url )
00277 {
00278     char *psz_colon;
00279     size_t i_scheme_length;
00280     char *new_scheme;
00281 
00282     if( XURL_IsAbsolute( psz_url ) == XURL_FALSE ) return strdup( "file" );
00283 
00284     /* this strchr will always succeed since we have an absolute URL, and thus
00285      * a scheme */
00286     psz_colon = strchr( psz_url, ':' );
00287 
00288     i_scheme_length = psz_colon - psz_url;
00289 
00290     new_scheme = xurl_malloc( i_scheme_length );
00291     if( new_scheme == NULL ) return NULL;
00292 
00293     strncpy( new_scheme, psz_url, i_scheme_length );
00294 
00295     return new_scheme;
00296 }
00297 
00298 
00299 XURL_Bool XURL_IsFileURL( char *psz_url )
00300 {
00301     XURL_Bool b_return_value;
00302     char *psz_scheme = XURL_GetScheme( psz_url );
00303 
00304     if( strcasecmp( psz_scheme, "file" ) == 0 )
00305         b_return_value = XURL_TRUE;
00306     else
00307         b_return_value = XURL_FALSE;
00308 
00309     xurl_free( psz_scheme );
00310 
00311     return b_return_value;
00312 }
00313 
00314 #ifndef HAVE_STRDUP
00315 static 
00316 char *xurl_strdup( const char *psz_string )
00317 {
00318     size_t i_length;
00319     char *psz_new_string;
00320 
00321     if( !psz_string ) return NULL;
00322     
00323     i_length = strlen( psz_string ) + 1;
00324     psz_new_string = (char *) xurl_malloc( i_length );
00325     if( psz_new_string == NULL ) return NULL;
00326 
00327     memcpy( psz_new_string, psz_string, i_length );
00328 
00329     return psz_new_string;
00330 }
00331 #endif
00332 
00333 static 
00334 char *XURL_FindPath( char *psz_url )
00335 {
00336     char *psz_return_value = NULL;
00337 
00338     if( XURL_IsAbsolute( psz_url ) == XURL_TRUE )
00339     {
00340         char *psz_start_of_hostname = XURL_FindHostname( psz_url );
00341         if( psz_start_of_hostname != NULL )
00342         {
00343             char *psz_start_of_path = strchr( psz_start_of_hostname, '/' );
00344             psz_return_value = psz_start_of_path;
00345         }
00346     }
00347     else
00348     {
00349         if( XURL_HasAbsolutePath( psz_url ) == XURL_TRUE )
00350         {
00351             psz_return_value = psz_url;
00352         }
00353         else
00354         {
00355             return xurl_strdup (".");
00356         }
00357     }
00358 
00359     return psz_return_value;
00360 }
00361 
00362 
00363 char *XURL_GetPath( char *psz_url )
00364 {
00365     char *psz_return_value = NULL;
00366     char *psz_path = NULL;
00367     char *pc_question_mark = NULL;
00368     char *pc_fragment = NULL;
00369 
00370     psz_path = xurl_strdup( XURL_FindPath( psz_url ) );
00371 #ifdef XURL_DEBUG
00372     fprintf( stderr, "XURL_GetPath: XURL_FindPath returning \"%s\"\n",
00373              psz_path );
00374 #endif
00375     psz_return_value = psz_path;
00376 
00377     pc_question_mark = XURL_FindQuery( psz_path );
00378     if( pc_question_mark != NULL )
00379     {
00380         int i_path_length = pc_question_mark - psz_path;
00381         *( psz_path + i_path_length ) = '\0';
00382     }
00383 
00384     pc_fragment = XURL_FindFragment( psz_path );
00385     if( pc_fragment != NULL )
00386     {
00387 #ifdef XURL_DEBUG
00388         fprintf( stderr, "XURL_GetPath: XURL_FindFragment returned \"%s\"\n",
00389                  pc_fragment );
00390 #endif
00391         int i_path_length = pc_fragment - psz_path;
00392         *( psz_path + i_path_length ) = '\0';
00393     }
00394 
00395 #ifdef XURL_DEBUG
00396     fprintf( stderr, "XURL_GetPath returning \"%s\"\n", psz_return_value );
00397 #endif
00398 
00399     return psz_return_value;
00400 }
00401 
00402 
00403 char *XURL_GetHead( const char *psz_path )
00404 {
00405     char *psz_path_head;
00406     char *pc_last_slash;
00407 
00408     /* kill everything up to the last / (including the /) */
00409 #ifdef XURL_WIN32_PATHING
00410     /* Windows: Try looking for a \ first; if we don't find one, look for / */
00411     pc_last_slash = strrchr( psz_path, '\\' );
00412     if( pc_last_slash == NULL )
00413         pc_last_slash = strrchr( psz_path, '/' );
00414 #else
00415     pc_last_slash = strrchr( psz_path, '/' );
00416 #endif
00417     if( pc_last_slash == NULL )
00418     {
00419         psz_path_head = xurl_strdup( psz_path );
00420     }
00421     else
00422     {
00423         size_t i_characters_until_last_slash;
00424 
00425         i_characters_until_last_slash = pc_last_slash - psz_path;
00426         psz_path_head = malloc(
00427                 ( i_characters_until_last_slash + 1 ) * sizeof(char) );
00428         (void) strncpy( psz_path_head, psz_path,
00429                 i_characters_until_last_slash + 1 );
00430 
00431         /* terminate the resulting string with '\0' */
00432         *(psz_path_head +
00433                 i_characters_until_last_slash) = '\0';
00434     }
00435 
00436     /* append a trailing / */
00437     streallocat( psz_path_head, "/" );
00438 
00439     return psz_path_head;
00440 }
00441 
00442 
00443 char *XURL_GetWithoutFragment( char *psz_url )
00444 {
00445     char *psz_return_value = NULL;
00446     char *psz_fragment;
00447 
00448     psz_fragment = XURL_FindFragment( psz_url );
00449     if( psz_fragment == NULL )
00450     {
00451         psz_return_value = xurl_strdup( psz_url );
00452     }
00453     else
00454     {
00455         size_t i_pre_fragment_length;
00456         char *psz_without_fragment;
00457 
00458         i_pre_fragment_length = psz_fragment - psz_url;
00459 
00460         psz_without_fragment = xurl_malloc( i_pre_fragment_length + 1 );
00461         if( psz_without_fragment == NULL )
00462         {
00463             psz_return_value = NULL;
00464         }
00465         else
00466         {
00467             memcpy( psz_without_fragment, psz_url, i_pre_fragment_length );
00468             *( psz_without_fragment + i_pre_fragment_length ) = '\0';
00469             psz_return_value = psz_without_fragment;
00470         }
00471     }
00472     
00473     return psz_return_value;
00474 }
00475 
00476 static 
00477 char *streallocat( char *psz_string, char *psz_to_append )
00478 {
00479     size_t i_new_string_length = strlen( psz_string ) +
00480         strlen( psz_to_append ) + 1;
00481 
00482     psz_string = (char *) realloc( psz_string, i_new_string_length );
00483     
00484     return strcat( psz_string, psz_to_append );
00485 }
00486 

Generated on Tue Dec 20 10:14:28 2005 for vlc-0.8.4a by  doxygen 1.4.2