]> git.sesse.net Git - vlc/blob - modules/codec/cmml/xurl.c
Remove stdlib.h
[vlc] / modules / codec / cmml / xurl.c
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 the VideoLAN team
7  *
8  * $Id$
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "xurl.h"
31
32 static char *streallocat( char *psz_string, char *psz_to_append );
33
34 #ifndef HAVE_STRDUP
35 static char *xurl_strdup( const char *psz_string );
36 #else
37 #define xurl_strdup strdup
38 #endif
39
40 static char *XURL_FindHostname          ( char *psz_url );
41 static char *XURL_FindPath              ( char *psz_url );
42 static char *XURL_FindFragment          ( char *psz_url );
43
44
45 char *XURL_Join( char *psz_url1, char *psz_url2 )
46 {
47     if( XURL_IsAbsolute( psz_url1 ) )
48         return XURL_Concat( psz_url1, psz_url2 );
49     else
50         return XURL_Concat( psz_url2, psz_url1 );
51
52     return NULL;
53 }
54
55 /* TODO: replace XURL_Concat's rel/absolute calculation with the one
56  * specified by RFC2396, and also test it on their test suite :) */
57
58
59 char *XURL_Concat( char *psz_url, char *psz_append )
60 {
61     char *psz_return_value = NULL;
62
63     if( XURL_IsAbsolute( psz_append ) == XURL_TRUE )
64         return strdup( psz_append );
65
66     if( XURL_IsAbsolute( psz_url ) )
67     {
68         if( XURL_HasAbsolutePath( psz_append ) )
69         {
70             char *psz_concat_url;
71
72             psz_concat_url = XURL_GetSchemeAndHostname( psz_url );
73
74             psz_concat_url = streallocat( psz_concat_url, psz_append );
75 #ifdef XURL_DEBUG
76             fprintf( stderr, "XURL_Concat: concat is \"%s\"\n",
77                      psz_concat_url );
78 #endif
79             psz_return_value = psz_concat_url;
80         }
81         else
82         {
83             /* psz_append is a relative URL */
84             char *psz_new_url;
85             
86             /* strip off last path component */
87             psz_new_url = XURL_GetHead( psz_url );
88             psz_new_url = streallocat( psz_new_url, psz_append );
89
90             psz_return_value = psz_new_url;
91         }
92     }
93     else
94     {
95         /* not an absolute URL */
96         if( XURL_HasAbsolutePath( psz_append ) == XURL_FALSE )
97         {
98             char *psz_new_url = XURL_GetHead( psz_url );
99
100             psz_new_url = streallocat( psz_new_url, psz_append );
101             psz_return_value = psz_new_url;
102         }
103         else
104         {
105             /* URL to append has an absolute path -- just use that instead */
106             psz_return_value = xurl_strdup( psz_append );
107         }
108     }
109
110     return psz_return_value;
111 }
112
113
114 XURL_Bool XURL_IsAbsolute( char *psz_url )
115 {
116     if( XURL_FindHostname( psz_url ) == NULL )
117     {
118 #ifdef XURL_DEBUG
119         fprintf( stderr, "XURL_IsAbsolute(%s) returning false\n", psz_url );
120 #endif
121         return XURL_FALSE;
122     }
123     else
124     {
125 #ifdef XURL_DEBUG
126         fprintf( stderr, "XURL_IsAbsolute(%s) returning true\n", psz_url );
127 #endif
128         return XURL_TRUE;
129     }
130 }
131
132
133 XURL_Bool XURL_HasFragment( char *psz_url )
134 {
135     if( XURL_FindFragment( psz_url ) == NULL )
136         return XURL_FALSE;
137     else
138         return XURL_TRUE;
139 }
140
141
142 char *XURL_FindHostname( char *psz_url )
143 {
144     char *psz_return_value = NULL;
145
146     char *psz_scheme_separator = strstr( psz_url, "://" );
147     if( psz_scheme_separator != NULL)
148     {
149         char *psz_hostname = psz_scheme_separator + strlen( "://" );
150         if( *psz_hostname != '\0') psz_return_value = psz_hostname;
151
152 #ifdef XURL_DEBUG
153         fprintf( stderr, "XURL_FindHostname(%s): returning \"%s\"\n",
154                  psz_url, psz_return_value );
155 #endif
156     }
157
158     return psz_return_value;
159 }
160
161
162 XURL_Bool XURL_HasAbsolutePath( char *psz_url )
163 {
164 #ifdef XURL_WIN32_PATHING
165     if( psz_url[0] == '/' || psz_url[0] == '\\' )
166 #else
167     if( psz_url[0] == '/' )
168 #endif
169         return XURL_TRUE;
170     else
171         return XURL_FALSE;
172 }
173
174
175 char *XURL_GetHostname( char *psz_url )
176 {
177     char *psz_return_value = NULL;
178     char *psz_hostname = XURL_FindHostname( psz_url );
179
180     if( psz_hostname != NULL )
181     {
182         char *psz_new_hostname;
183         size_t i_hostname_length;
184
185         char *psz_one_past_end_of_hostname = strchr( psz_hostname, '/' );
186         if( psz_one_past_end_of_hostname != NULL)
187         {
188             /* Found a '/' after the hostname, so copy characters between
189              * the hostname and the '/' to a new string */
190             i_hostname_length = psz_one_past_end_of_hostname -
191                 psz_hostname;
192         }
193         else
194         {
195             /* Didn't find a '/', so copy from the start of the hostname
196              * until the end of the string */
197             i_hostname_length = strlen( psz_url ) - ( psz_hostname - psz_url );
198         }
199
200         /* Copy hostname to a new string */
201         psz_new_hostname = xurl_malloc( i_hostname_length );
202         if (psz_new_hostname == NULL) return NULL;
203         strncpy( psz_new_hostname, psz_hostname, i_hostname_length );
204
205 #ifdef XURL_DEBUG
206         fprintf (stderr, "XURL_GetHostname: psz_new_hostname is \"%s\"\n",
207                  psz_new_hostname );
208 #endif
209         psz_return_value = psz_new_hostname;
210     }
211     else
212     {
213         /* Didn't find a hostname */
214         return NULL;
215     }
216
217     return psz_return_value;
218 }
219
220
221 char *XURL_GetSchemeAndHostname( char *psz_url )
222 {
223     char *psz_scheme, *psz_hostname, *psz_scheme_and_hostname;
224
225     psz_scheme = XURL_GetScheme( psz_url );
226     if( psz_scheme == NULL ) return NULL;
227
228     psz_hostname = XURL_GetHostname( psz_url );
229     if( psz_hostname == NULL ) return NULL;
230
231     /* malloc +1 for the terminating '\0' */
232     psz_scheme_and_hostname = xurl_malloc(
233             strlen( psz_scheme ) + strlen( "://" ) +
234             strlen( psz_hostname ) + 1);
235     if( psz_scheme_and_hostname == NULL ) return NULL;
236     (void) strcpy( psz_scheme_and_hostname, psz_scheme );
237     (void) strcat( psz_scheme_and_hostname, "://" );
238     (void) strcat( psz_scheme_and_hostname, psz_hostname );
239
240     if (psz_scheme_and_hostname == NULL ) return NULL;
241     return psz_scheme_and_hostname;
242 }
243
244 static 
245 char *XURL_FindFragment( char *psz_url )
246 {
247     char *pc_hash = NULL;
248     char *pc_return_value = NULL;
249     
250     pc_hash = strchr( psz_url, '#' );
251     if( pc_hash != NULL )
252     {
253         pc_return_value = pc_hash;
254     }
255
256     return pc_return_value;
257 }
258
259
260 char *XURL_FindQuery( char *psz_url )
261 {
262     char *pc_question_mark = NULL;
263     char *pc_return_value = NULL;
264     
265     pc_question_mark = strchr( psz_url, '?' );
266     if( pc_question_mark != NULL )
267     {
268         pc_return_value = pc_question_mark;
269     }
270
271     return pc_return_value;
272 }
273
274
275 char *XURL_GetScheme( char *psz_url )
276 {
277     char *psz_colon;
278     size_t i_scheme_length;
279     char *new_scheme;
280
281     if( XURL_IsAbsolute( psz_url ) == XURL_FALSE ) return strdup( "file" );
282
283     /* this strchr will always succeed since we have an absolute URL, and thus
284      * a scheme */
285     psz_colon = strchr( psz_url, ':' );
286
287     i_scheme_length = psz_colon - psz_url;
288
289     new_scheme = xurl_malloc( i_scheme_length );
290     if( new_scheme == NULL ) return NULL;
291
292     strncpy( new_scheme, psz_url, i_scheme_length );
293
294     return new_scheme;
295 }
296
297
298 XURL_Bool XURL_IsFileURL( char *psz_url )
299 {
300     XURL_Bool b_return_value;
301     char *psz_scheme = XURL_GetScheme( psz_url );
302
303     if( strcasecmp( psz_scheme, "file" ) == 0 )
304         b_return_value = XURL_TRUE;
305     else
306         b_return_value = XURL_FALSE;
307
308     xurl_free( psz_scheme );
309
310     return b_return_value;
311 }
312
313 #ifndef HAVE_STRDUP
314 static 
315 char *xurl_strdup( const char *psz_string )
316 {
317     size_t i_length;
318     char *psz_new_string;
319
320     if( !psz_string ) return NULL;
321     
322     i_length = strlen( psz_string ) + 1;
323     psz_new_string = (char *) xurl_malloc( i_length );
324     if( psz_new_string == NULL ) return NULL;
325
326     memcpy( psz_new_string, psz_string, i_length );
327
328     return psz_new_string;
329 }
330 #endif
331
332 static 
333 char *XURL_FindPath( char *psz_url )
334 {
335     char *psz_return_value = NULL;
336
337     if( XURL_IsAbsolute( psz_url ) == XURL_TRUE )
338     {
339         char *psz_start_of_hostname = XURL_FindHostname( psz_url );
340         if( psz_start_of_hostname != NULL )
341         {
342             char *psz_start_of_path = strchr( psz_start_of_hostname, '/' );
343             psz_return_value = psz_start_of_path;
344         }
345     }
346     else
347     {
348         if( XURL_HasAbsolutePath( psz_url ) == XURL_TRUE )
349         {
350             psz_return_value = psz_url;
351         }
352         else
353         {
354             return xurl_strdup (".");
355         }
356     }
357
358     return psz_return_value;
359 }
360
361
362 char *XURL_GetPath( char *psz_url )
363 {
364     char *psz_return_value = NULL;
365     char *psz_path = NULL;
366     char *pc_question_mark = NULL;
367     char *pc_fragment = NULL;
368
369     psz_path = xurl_strdup( XURL_FindPath( psz_url ) );
370 #ifdef XURL_DEBUG
371     fprintf( stderr, "XURL_GetPath: XURL_FindPath returning \"%s\"\n",
372              psz_path );
373 #endif
374     psz_return_value = psz_path;
375
376     pc_question_mark = XURL_FindQuery( psz_path );
377     if( pc_question_mark != NULL )
378     {
379         int i_path_length = pc_question_mark - psz_path;
380         *( psz_path + i_path_length ) = '\0';
381     }
382
383     pc_fragment = XURL_FindFragment( psz_path );
384     if( pc_fragment != NULL )
385     {
386 #ifdef XURL_DEBUG
387         fprintf( stderr, "XURL_GetPath: XURL_FindFragment returned \"%s\"\n",
388                  pc_fragment );
389 #endif
390         int i_path_length = pc_fragment - psz_path;
391         *( psz_path + i_path_length ) = '\0';
392     }
393
394 #ifdef XURL_DEBUG
395     fprintf( stderr, "XURL_GetPath returning \"%s\"\n", psz_return_value );
396 #endif
397
398     return psz_return_value;
399 }
400
401
402 char *XURL_GetHead( const char *psz_path )
403 {
404     char *psz_path_head;
405     char *pc_last_slash;
406
407     /* kill everything up to the last / (including the /) */
408 #ifdef XURL_WIN32_PATHING
409     /* Windows: Try looking for a \ first; if we don't find one, look for / */
410     pc_last_slash = strrchr( psz_path, '\\' );
411     if( pc_last_slash == NULL )
412         pc_last_slash = strrchr( psz_path, '/' );
413 #else
414     pc_last_slash = strrchr( psz_path, '/' );
415 #endif
416     if( pc_last_slash == NULL )
417     {
418         psz_path_head = xurl_strdup( psz_path );
419     }
420     else
421     {
422         size_t i_characters_until_last_slash;
423
424         i_characters_until_last_slash = pc_last_slash - psz_path;
425         psz_path_head = malloc(
426                 ( i_characters_until_last_slash + 1 ) * sizeof(char) );
427         (void) strncpy( psz_path_head, psz_path,
428                 i_characters_until_last_slash + 1 );
429
430         /* terminate the resulting string with '\0' */
431         *(psz_path_head +
432                 i_characters_until_last_slash) = '\0';
433     }
434
435     /* append a trailing / */
436     streallocat( psz_path_head, "/" );
437
438     return psz_path_head;
439 }
440
441
442 char *XURL_GetWithoutFragment( char *psz_url )
443 {
444     char *psz_return_value = NULL;
445     char *psz_fragment;
446
447     psz_fragment = XURL_FindFragment( psz_url );
448     if( psz_fragment == NULL )
449     {
450         psz_return_value = xurl_strdup( psz_url );
451     }
452     else
453     {
454         size_t i_pre_fragment_length;
455         char *psz_without_fragment;
456
457         i_pre_fragment_length = psz_fragment - psz_url;
458
459         psz_without_fragment = xurl_malloc( i_pre_fragment_length + 1 );
460         if( psz_without_fragment == NULL )
461         {
462             psz_return_value = NULL;
463         }
464         else
465         {
466             memcpy( psz_without_fragment, psz_url, i_pre_fragment_length );
467             *( psz_without_fragment + i_pre_fragment_length ) = '\0';
468             psz_return_value = psz_without_fragment;
469         }
470     }
471     
472     return psz_return_value;
473 }
474
475 static 
476 char *streallocat( char *psz_string, char *psz_to_append )
477 {
478     size_t i_new_string_length = strlen( psz_string ) +
479         strlen( psz_to_append ) + 1;
480
481     psz_string = (char *) realloc( psz_string, i_new_string_length );
482     
483     return strcat( psz_string, psz_to_append );
484 }
485