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