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