xurl.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:12k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * xurl.c: URL manipulation functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2004 Commonwealth Scientific and Industrial Research
  5.  *                         Organisation (CSIRO) Australia
  6.  * Copyright (C) 2004 VideoLAN
  7.  *
  8.  * $Id: xurl.c 7774 2004-05-26 02:23:10Z andrep $
  9.  *
  10.  * Authors: Andre Pang <Andre.Pang@csiro.au>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  * 
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  25.  *****************************************************************************/
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "xurl.h"
  30. static char *streallocat( char *psz_string, char *psz_to_append );
  31. #ifndef HAVE_STRDUP
  32. static char *xurl_strdup( const char *psz_string );
  33. #else
  34. #define xurl_strdup strdup
  35. #endif
  36. static char *XURL_FindHostname          ( char *psz_url );
  37. static char *XURL_FindPath              ( char *psz_url );
  38. static char *XURL_FindFragment          ( char *psz_url );
  39. char *XURL_Join( char *psz_url1, char *psz_url2 )
  40. {
  41.     if( XURL_IsAbsolute( psz_url1 ) )
  42.         return XURL_Concat( psz_url1, psz_url2 );
  43.     else
  44.         return XURL_Concat( psz_url2, psz_url1 );
  45.     return NULL;
  46. }
  47. /* TODO: replace XURL_Concat's rel/absolute calculation with the one
  48.  * specified by RFC2396, and also test it on their test suite :) */
  49. char *XURL_Concat( char *psz_url, char *psz_append )
  50. {
  51.     char *psz_return_value = NULL;
  52.     if( XURL_IsAbsolute( psz_append ) == XURL_TRUE )
  53.         return strdup( psz_append );
  54.     if( XURL_IsAbsolute( psz_url ) )
  55.     {
  56.         if( XURL_HasAbsolutePath( psz_append ) )
  57.         {
  58.             char *psz_concat_url;
  59.             psz_concat_url = XURL_GetSchemeAndHostname( psz_url );
  60.             psz_concat_url = streallocat( psz_concat_url, psz_append );
  61. #ifdef XURL_DEBUG
  62.             fprintf( stderr, "XURL_Concat: concat is "%s"n",
  63.                      psz_concat_url );
  64. #endif
  65.             psz_return_value = psz_concat_url;
  66.         }
  67.         else
  68.         {
  69.             /* psz_append is a relative URL */
  70.             char *psz_new_url;
  71.             
  72.             /* strip off last path component */
  73.             psz_new_url = XURL_GetHead( psz_url );
  74.             psz_new_url = streallocat( psz_new_url, psz_append );
  75.             psz_return_value = psz_new_url;
  76.         }
  77.     }
  78.     else
  79.     {
  80.         /* not an absolute URL */
  81.         if( XURL_HasAbsolutePath( psz_append ) == XURL_FALSE )
  82.         {
  83.             char *psz_new_url = XURL_GetHead( psz_url );
  84.             psz_new_url = streallocat( psz_new_url, psz_append );
  85.             psz_return_value = psz_new_url;
  86.         }
  87.         else
  88.         {
  89.             /* URL to append has an absolute path -- just use that instead */
  90.             psz_return_value = xurl_strdup( psz_append );
  91.         }
  92.     }
  93.     return psz_return_value;
  94. }
  95. XURL_Bool XURL_IsAbsolute( char *psz_url )
  96. {
  97.     if( XURL_FindHostname( psz_url ) == NULL )
  98.     {
  99. #ifdef XURL_DEBUG
  100.         fprintf( stderr, "XURL_IsAbsolute(%s) returning falsen", psz_url );
  101. #endif
  102.         return XURL_FALSE;
  103.     }
  104.     else
  105.     {
  106. #ifdef XURL_DEBUG
  107.         fprintf( stderr, "XURL_IsAbsolute(%s) returning truen", psz_url );
  108. #endif
  109.         return XURL_TRUE;
  110.     }
  111. }
  112. XURL_Bool XURL_HasFragment( char *psz_url )
  113. {
  114.     if( XURL_FindFragment( psz_url ) == NULL )
  115.         return XURL_FALSE;
  116.     else
  117.         return XURL_TRUE;
  118. }
  119. char *XURL_FindHostname( char *psz_url )
  120. {
  121.     char *psz_return_value = NULL;
  122.     char *psz_scheme_separator = strstr( psz_url, "://" );
  123.     if( psz_scheme_separator != NULL)
  124.     {
  125.         char *psz_hostname = psz_scheme_separator + strlen( "://" );
  126.         if( *psz_hostname != '') psz_return_value = psz_hostname;
  127. #ifdef XURL_DEBUG
  128.         fprintf( stderr, "XURL_FindHostname(%s): returning "%s"n",
  129.                  psz_url, psz_return_value );
  130. #endif
  131.     }
  132.     return psz_return_value;
  133. }
  134. XURL_Bool XURL_HasAbsolutePath( char *psz_url )
  135. {
  136. #ifdef XURL_WIN32_PATHING
  137.     if( psz_url[0] == '/' || psz_url[0] == '\' )
  138. #else
  139.     if( psz_url[0] == '/' )
  140. #endif
  141.         return XURL_TRUE;
  142.     else
  143.         return XURL_FALSE;
  144. }
  145. char *XURL_GetHostname( char *psz_url )
  146. {
  147.     char *psz_return_value = NULL;
  148.     char *psz_hostname = XURL_FindHostname( psz_url );
  149.     if( psz_hostname != NULL )
  150.     {
  151.         char *psz_new_hostname;
  152.         size_t i_hostname_length;
  153.         char *psz_one_past_end_of_hostname = strchr( psz_hostname, '/' );
  154.         if( psz_one_past_end_of_hostname != NULL)
  155.         {
  156.             /* Found a '/' after the hostname, so copy characters between
  157.              * the hostname and the '/' to a new string */
  158.             i_hostname_length = psz_one_past_end_of_hostname -
  159.                 psz_hostname;
  160.         }
  161.         else
  162.         {
  163.             /* Didn't find a '/', so copy from the start of the hostname
  164.              * until the end of the string */
  165.             i_hostname_length = strlen( psz_url ) - ( psz_hostname - psz_url );
  166.         }
  167.         /* Copy hostname to a new string */
  168.         psz_new_hostname = xurl_malloc( i_hostname_length );
  169.         if (psz_new_hostname == NULL) return NULL;
  170.         strncpy( psz_new_hostname, psz_hostname, i_hostname_length );
  171. #ifdef XURL_DEBUG
  172.         fprintf (stderr, "XURL_GetHostname: psz_new_hostname is "%s"n",
  173.                  psz_new_hostname );
  174. #endif
  175.         psz_return_value = psz_new_hostname;
  176.     }
  177.     else
  178.     {
  179.         /* Didn't find a hostname */
  180.         return NULL;
  181.     }
  182.     return psz_return_value;
  183. }
  184. char *XURL_GetSchemeAndHostname( char *psz_url )
  185. {
  186.     char *psz_scheme, *psz_hostname, *psz_scheme_and_hostname;
  187.     psz_scheme = XURL_GetScheme( psz_url );
  188.     if( psz_scheme == NULL ) return NULL;
  189.     psz_hostname = XURL_GetHostname( psz_url );
  190.     if( psz_hostname == NULL ) return NULL;
  191.     /* malloc +1 for the terminating '' */
  192.     psz_scheme_and_hostname = xurl_malloc(
  193.             strlen( psz_scheme ) + strlen( "://" ) +
  194.             strlen( psz_hostname ) + 1);
  195.     if( psz_scheme_and_hostname == NULL ) return NULL;
  196.     (void) strcpy( psz_scheme_and_hostname, psz_scheme );
  197.     (void) strcat( psz_scheme_and_hostname, "://" );
  198.     (void) strcat( psz_scheme_and_hostname, psz_hostname );
  199.     if (psz_scheme_and_hostname == NULL ) return NULL;
  200.     return psz_scheme_and_hostname;
  201. }
  202. static 
  203. char *XURL_FindFragment( char *psz_url )
  204. {
  205.     char *pc_hash = NULL;
  206.     char *pc_return_value = NULL;
  207.     
  208.     pc_hash = strchr( psz_url, '#' );
  209.     if( pc_hash != NULL )
  210.     {
  211.         pc_return_value = pc_hash;
  212.     }
  213.     return pc_return_value;
  214. }
  215. char *XURL_FindQuery( char *psz_url )
  216. {
  217.     char *pc_question_mark = NULL;
  218.     char *pc_return_value = NULL;
  219.     
  220.     pc_question_mark = strchr( psz_url, '?' );
  221.     if( pc_question_mark != NULL )
  222.     {
  223.         pc_return_value = pc_question_mark;
  224.     }
  225.     return pc_return_value;
  226. }
  227. char *XURL_GetScheme( char *psz_url )
  228. {
  229.     char *psz_colon;
  230.     size_t i_scheme_length;
  231.     char *new_scheme;
  232.     if( XURL_IsAbsolute( psz_url ) == XURL_FALSE ) return strdup( "file" );
  233.     /* this strchr will always succeed since we have an absolute URL, and thus
  234.      * a scheme */
  235.     psz_colon = strchr( psz_url, ':' );
  236.     i_scheme_length = psz_colon - psz_url;
  237.     new_scheme = xurl_malloc( i_scheme_length );
  238.     if( new_scheme == NULL ) return NULL;
  239.     strncpy( new_scheme, psz_url, i_scheme_length );
  240.     return new_scheme;
  241. }
  242. XURL_Bool XURL_IsFileURL( char *psz_url )
  243. {
  244.     XURL_Bool b_return_value;
  245.     char *psz_scheme = XURL_GetScheme( psz_url );
  246.     if( strcasecmp( psz_scheme, "file" ) == 0 )
  247.         b_return_value = XURL_TRUE;
  248.     else
  249.         b_return_value = XURL_FALSE;
  250.     xurl_free( psz_scheme );
  251.     return b_return_value;
  252. }
  253. #ifndef HAVE_STRDUP
  254. static 
  255. char *xurl_strdup( const char *psz_string )
  256. {
  257.     size_t i_length;
  258.     char *psz_new_string;
  259.     if( !psz_string ) return NULL;
  260.     
  261.     i_length = strlen( psz_string ) + 1;
  262.     psz_new_string = (char *) xurl_malloc( i_length );
  263.     if( psz_new_string == NULL ) return NULL;
  264.     memcpy( psz_new_string, psz_string, i_length );
  265.     return psz_new_string;
  266. }
  267. #endif
  268. static 
  269. char *XURL_FindPath( char *psz_url )
  270. {
  271.     char *psz_return_value = NULL;
  272.     if( XURL_IsAbsolute( psz_url ) == XURL_TRUE )
  273.     {
  274.         char *psz_start_of_hostname = XURL_FindHostname( psz_url );
  275.         if( psz_start_of_hostname != NULL )
  276.         {
  277.             char *psz_start_of_path = strchr( psz_start_of_hostname, '/' );
  278.             psz_return_value = psz_start_of_path;
  279.         }
  280.     }
  281.     else
  282.     {
  283.         if( XURL_HasAbsolutePath( psz_url ) == XURL_TRUE )
  284.         {
  285.             psz_return_value = psz_url;
  286.         }
  287.         else
  288.         {
  289.             return xurl_strdup (".");
  290.         }
  291.     }
  292.     return psz_return_value;
  293. }
  294. char *XURL_GetPath( char *psz_url )
  295. {
  296.     char *psz_return_value = NULL;
  297.     char *psz_path = NULL;
  298.     char *pc_question_mark = NULL;
  299.     char *pc_fragment = NULL;
  300.     psz_path = xurl_strdup( XURL_FindPath( psz_url ) );
  301. #ifdef XURL_DEBUG
  302.     fprintf( stderr, "XURL_GetPath: XURL_FindPath returning "%s"n",
  303.              psz_path );
  304. #endif
  305.     psz_return_value = psz_path;
  306.     pc_question_mark = XURL_FindQuery( psz_path );
  307.     if( pc_question_mark != NULL )
  308.     {
  309.         int i_path_length = pc_question_mark - psz_path;
  310.         *( psz_path + i_path_length ) = '';
  311.     }
  312.     pc_fragment = XURL_FindFragment( psz_path );
  313.     if( pc_fragment != NULL )
  314.     {
  315. #ifdef XURL_DEBUG
  316.         fprintf( stderr, "XURL_GetPath: XURL_FindFragment returned "%s"n",
  317.                  pc_fragment );
  318. #endif
  319.         int i_path_length = pc_fragment - psz_path;
  320.         *( psz_path + i_path_length ) = '';
  321.     }
  322. #ifdef XURL_DEBUG
  323.     fprintf( stderr, "XURL_GetPath returning "%s"n", psz_return_value );
  324. #endif
  325.     return psz_return_value;
  326. }
  327. char *XURL_GetHead( const char *psz_path )
  328. {
  329.     char *psz_path_head;
  330.     char *pc_last_slash;
  331.     /* kill everything up to the last / (including the /) */
  332. #ifdef XURL_WIN32_PATHING
  333.     /* Windows: Try looking for a  first; if we don't find one, look for / */
  334.     pc_last_slash = strrchr( psz_path, '\' );
  335.     if( pc_last_slash == NULL )
  336.         pc_last_slash = strrchr( psz_path, '/' );
  337. #else
  338.     pc_last_slash = strrchr( psz_path, '/' );
  339. #endif
  340.     if( pc_last_slash == NULL )
  341.     {
  342.         psz_path_head = xurl_strdup( psz_path );
  343.     }
  344.     else
  345.     {
  346.         size_t i_characters_until_last_slash;
  347.         i_characters_until_last_slash = pc_last_slash - psz_path;
  348.         psz_path_head = malloc(
  349.                 ( i_characters_until_last_slash + 1 ) * sizeof(char) );
  350.         (void) strncpy( psz_path_head, psz_path,
  351.                 i_characters_until_last_slash + 1 );
  352.         /* terminate the resulting string with '' */
  353.         *(psz_path_head +
  354.                 i_characters_until_last_slash) = '';
  355.     }
  356.     /* append a trailing / */
  357.     streallocat( psz_path_head, "/" );
  358.     return psz_path_head;
  359. }
  360. char *XURL_GetWithoutFragment( char *psz_url )
  361. {
  362.     char *psz_return_value = NULL;
  363.     char *psz_fragment;
  364.     psz_fragment = XURL_FindFragment( psz_url );
  365.     if( psz_fragment == NULL )
  366.     {
  367.         psz_return_value = xurl_strdup( psz_url );
  368.     }
  369.     else
  370.     {
  371.         size_t i_pre_fragment_length;
  372.         char *psz_without_fragment;
  373.         i_pre_fragment_length = psz_fragment - psz_url;
  374.         psz_without_fragment = xurl_malloc( i_pre_fragment_length + 1 );
  375.         if( psz_without_fragment == NULL )
  376.         {
  377.             psz_return_value = NULL;
  378.         }
  379.         else
  380.         {
  381.             memcpy( psz_without_fragment, psz_url, i_pre_fragment_length );
  382.             *( psz_without_fragment + i_pre_fragment_length ) = '';
  383.             psz_return_value = psz_without_fragment;
  384.         }
  385.     }
  386.     
  387.     return psz_return_value;
  388. }
  389. static 
  390. char *streallocat( char *psz_string, char *psz_to_append )
  391. {
  392.     size_t i_new_string_length = strlen( psz_string ) +
  393.         strlen( psz_to_append ) + 1;
  394.     psz_string = (char *) realloc( psz_string, i_new_string_length );
  395.     
  396.     return strcat( psz_string, psz_to_append );
  397. }