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