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