~nik90/ubuntu/precise/vlc/keywords

« back to all changes in this revision

Viewing changes to modules/control/http/util.c

  • Committer: Package Import Robot
  • Author(s): Benjamin Drung
  • Date: 2012-02-13 01:34:02 UTC
  • mfrom: (1.1.44)
  • Revision ID: package-import@ubuntu.com-20120213013402-7utx6r7s9dg3r0pf
Tags: 2.0.0~unix-0ubuntu1
* New upstream release (Closes: #499381, #573064, #624027, LP: #455825,
  #573775, #695882, #705151, #708448, #738381, #743581, #747757, #817924,
  #931083).
* Remove dropped mozilla-plugin-vlc, vlc-plugin-ggi, and vlc-plugin-svgalib.
  The Mozilla browser plug-in is now provided by a separate source tarball.
* Add new plugins to and remove dropped plugins from vlc-nox.
* Add new and remove dropped build dependencies:
  + libbluray-dev (for Blu-ray support)
  + libresid-builder-dev
  + libsamplerate0-dev
  + libsidplay2-dev
  + lbspeexdsp-dev
  + libxcb-composite0-dev
  - libgtk2.0-dev
  - xulrunner-dev
* vlc-plugin-fluidsynth depends on fluid-soundfont-gm or
  musescore-soundfont-gm for having a sound font for playing MIDI files.
* Drop all patches (they were either backported or accepted by upstream).
* Update symbols for libvlc5.
* Install plugins.dat instead of running vlc-cache-gen in postinst.
* Update minimum version of build dependencies.
* Change Build-Dependency from libupnp3-dev to unversioned libupnp-dev.
  (Closes: #656831)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 * util.c : Utility functions for HTTP interface
3
 
 *****************************************************************************
4
 
 * Copyright (C) 2001-2005 the VideoLAN team
5
 
 * $Id: 565c100b1120c3d630a89c8a889dc4e65477b3b7 $
6
 
 *
7
 
 * Authors: Gildas Bazin <gbazin@netcourrier.com>
8
 
 *          Laurent Aimar <fenrir@via.ecp.fr>
9
 
 *          Christophe Massiot <massiot@via.ecp.fr>
10
 
 *
11
 
 * This program is free software; you can redistribute it and/or modify
12
 
 * it under the terms of the GNU General Public License as published by
13
 
 * the Free Software Foundation; either version 2 of the License, or
14
 
 * (at your option) any later version.
15
 
 *
16
 
 * This program is distributed in the hope that it will be useful,
17
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 
 * GNU General Public License for more details.
20
 
 *
21
 
 * You should have received a copy of the GNU General Public License
22
 
 * along with this program; if not, write to the Free Software
23
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
 
 *****************************************************************************/
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
# include "config.h"
28
 
#endif
29
 
 
30
 
#include <vlc_common.h>
31
 
#include "http.h"
32
 
#include <vlc_strings.h>
33
 
#include <errno.h>
34
 
#include <fcntl.h>
35
 
#include <sys/stat.h>
36
 
#include <vlc_fs.h>
37
 
 
38
 
/****************************************************************************
39
 
 * File and directory functions
40
 
 ****************************************************************************/
41
 
 
42
 
/* ToUrl: create a good name for an url from filename */
43
 
static char *FileToUrl( const char *name, bool *pb_index )
44
 
{
45
 
    *pb_index = false;
46
 
 
47
 
    char *url = malloc( strlen( name ) + 2 );
48
 
    if( unlikely(url == NULL) )
49
 
        return NULL;
50
 
 
51
 
#if (DIR_SEP_CHAR == '/')
52
 
    name += strspn( name, "/" );
53
 
#else
54
 
    name += strspn( name, "/"DIR_SEP );
55
 
#endif
56
 
    *url = '/';
57
 
    strcpy( url + 1, name );
58
 
 
59
 
#if (DIR_SEP_CHAR != '/')
60
 
    /* convert '\\' into '/' */
61
 
    for( char *ptr = url; *ptr; ptr++ )
62
 
        if( *ptr == DIR_SEP_CHAR )
63
 
            *ptr = '/';
64
 
#endif
65
 
 
66
 
    /* index.* -> / */
67
 
    char *p = strrchr( url, '/' );
68
 
    if( p != NULL && !strncmp( p, "/index.", 7 ) )
69
 
    {
70
 
        p[1] = '\0';
71
 
        *pb_index = true;
72
 
    }
73
 
    return url;
74
 
}
75
 
 
76
 
/* Load a file */
77
 
int FileLoad( FILE *f, char **pp_data, int *pi_data )
78
 
{
79
 
    int i_read;
80
 
 
81
 
    /* just load the file */
82
 
    *pi_data = 0;
83
 
    *pp_data = xmalloc( 1025 );  /* +1 for \0 */
84
 
 
85
 
    while( ( i_read = fread( &(*pp_data)[*pi_data], 1, 1024, f ) ) == 1024 )
86
 
    {
87
 
        *pi_data += 1024;
88
 
        *pp_data = xrealloc( *pp_data, *pi_data  + 1025 );
89
 
    }
90
 
    if( i_read > 0 )
91
 
    {
92
 
        *pi_data += i_read;
93
 
    }
94
 
    (*pp_data)[*pi_data] = '\0';
95
 
 
96
 
    return VLC_SUCCESS;
97
 
}
98
 
 
99
 
/* Parse a directory and recursively add files */
100
 
int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
101
 
                        char *psz_dir )
102
 
{
103
 
    intf_sys_t     *p_sys = p_intf->p_sys;
104
 
    char           dir[MAX_DIR_SIZE];
105
 
    DIR           *p_dir;
106
 
    vlc_acl_t     *p_acl;
107
 
    FILE          *file;
108
 
 
109
 
    char          *user = NULL;
110
 
    char          *password = NULL;
111
 
 
112
 
    int           i_dirlen;
113
 
 
114
 
    if( ( p_dir = vlc_opendir( psz_dir ) ) == NULL )
115
 
    {
116
 
        if( errno != ENOENT && errno != ENOTDIR )
117
 
            msg_Err( p_intf, "cannot open directory (%s)", psz_dir );
118
 
        return VLC_EGENERIC;
119
 
    }
120
 
 
121
 
    i_dirlen = strlen( psz_dir );
122
 
    if( i_dirlen + 10 > MAX_DIR_SIZE )
123
 
    {
124
 
        msg_Warn( p_intf, "skipping too deep directory (%s)", psz_dir );
125
 
        closedir( p_dir );
126
 
        return 0;
127
 
    }
128
 
 
129
 
    msg_Dbg( p_intf, "dir=%s", psz_dir );
130
 
 
131
 
    snprintf( dir, sizeof( dir ), "%s"DIR_SEP".access", psz_dir );
132
 
    if( ( file = vlc_fopen( dir, "r" ) ) != NULL )
133
 
    {
134
 
        char line[1024];
135
 
        int  i_size;
136
 
 
137
 
        msg_Dbg( p_intf, "find .access in dir=%s", psz_dir );
138
 
 
139
 
        i_size = fread( line, 1, 1023, file );
140
 
        if( i_size > 0 )
141
 
        {
142
 
            char *p;
143
 
            while( i_size > 0 && ( line[i_size-1] == '\n' ||
144
 
                   line[i_size-1] == '\r' ) )
145
 
            {
146
 
                i_size--;
147
 
            }
148
 
 
149
 
            line[i_size] = '\0';
150
 
 
151
 
            p = strchr( line, ':' );
152
 
            if( p )
153
 
            {
154
 
                *p++ = '\0';
155
 
                user = strdup( line );
156
 
                password = strdup( p );
157
 
            }
158
 
        }
159
 
        msg_Dbg( p_intf, "using user=%s (read=%d)", user, i_size );
160
 
 
161
 
        fclose( file );
162
 
    }
163
 
 
164
 
    snprintf( dir, sizeof( dir ), "%s"DIR_SEP".hosts", psz_dir );
165
 
    p_acl = ACL_Create( p_intf, false );
166
 
    if( ACL_LoadFile( p_acl, dir ) )
167
 
    {
168
 
        ACL_Destroy( p_acl );
169
 
 
170
 
        struct stat st;
171
 
        if( vlc_stat( dir, &st ) == 0 )
172
 
        {
173
 
            free( user );
174
 
            free( password );
175
 
            closedir( p_dir );
176
 
            return VLC_EGENERIC;
177
 
        }
178
 
        p_acl = NULL;
179
 
    }
180
 
 
181
 
    for( ;; )
182
 
    {
183
 
        char *psz_filename;
184
 
        /* parse psz_src dir */
185
 
        if( ( psz_filename = vlc_readdir( p_dir ) ) == NULL )
186
 
        {
187
 
            break;
188
 
        }
189
 
 
190
 
        if( ( psz_filename[0] == '.' )
191
 
         || ( i_dirlen + strlen( psz_filename ) > MAX_DIR_SIZE ) )
192
 
        {
193
 
            free( psz_filename );
194
 
            continue;
195
 
        }
196
 
 
197
 
        snprintf( dir, sizeof( dir ), "%s"DIR_SEP"%s", psz_dir, psz_filename );
198
 
        free( psz_filename );
199
 
 
200
 
        if( ParseDirectory( p_intf, psz_root, dir ) )
201
 
        {
202
 
            httpd_file_sys_t *f = NULL;
203
 
            httpd_handler_sys_t *h = NULL;
204
 
            bool b_index;
205
 
            char *psz_name, *psz_ext;
206
 
 
207
 
            psz_name = FileToUrl( &dir[strlen( psz_root )], &b_index );
208
 
            psz_ext = strrchr( dir, '.' );
209
 
            if( psz_ext != NULL )
210
 
            {
211
 
                int i;
212
 
                psz_ext++;
213
 
                for( i = 0; i < p_sys->i_handlers; i++ )
214
 
                    if( !strcmp( p_sys->pp_handlers[i]->psz_ext, psz_ext ) )
215
 
                        break;
216
 
                if( i < p_sys->i_handlers )
217
 
                {
218
 
                    f = malloc( sizeof( httpd_handler_sys_t ) );
219
 
                    h = (httpd_handler_sys_t *)f;
220
 
                    f->b_handler = true;
221
 
                    h->p_association = p_sys->pp_handlers[i];
222
 
                }
223
 
            }
224
 
            if( f == NULL )
225
 
            {
226
 
                f = xmalloc( sizeof( httpd_file_sys_t ) );
227
 
                f->b_handler = false;
228
 
            }
229
 
 
230
 
            f->p_intf  = p_intf;
231
 
            f->p_file = NULL;
232
 
            f->p_redir = NULL;
233
 
            f->p_redir2 = NULL;
234
 
            f->file = strdup (dir);
235
 
            f->name = psz_name;
236
 
            f->b_html = strstr( &dir[strlen( psz_root )], ".htm" ) || strstr( &dir[strlen( psz_root )], ".xml" ) ? true : false;
237
 
 
238
 
            if( !f->name )
239
 
            {
240
 
                msg_Err( p_intf , "unable to parse directory" );
241
 
                closedir( p_dir );
242
 
                free( f );
243
 
                return( VLC_ENOMEM );
244
 
            }
245
 
            msg_Dbg( p_intf, "file=%s (url=%s)",
246
 
                     f->file, f->name );
247
 
 
248
 
            if( !f->b_handler )
249
 
            {
250
 
                char *psz_type = strdup( "text/html; charset=UTF-8" );
251
 
                if( strstr( &dir[strlen( psz_root )], ".xml" ) )
252
 
                {
253
 
                    char *psz = strstr( psz_type, "html;" );
254
 
                    if( psz )
255
 
                    {
256
 
                        psz[0] = 'x';
257
 
                        psz[1] = 'm';
258
 
                        psz[2] = 'l';
259
 
                        psz[3] = ';';
260
 
                        psz[4] = ' ';
261
 
                    }
262
 
                }
263
 
                f->p_file = httpd_FileNew( p_sys->p_httpd_host,
264
 
                                           f->name,
265
 
                                           f->b_html ? psz_type : NULL,
266
 
                                           user, password, p_acl,
267
 
                                           HttpCallback, f );
268
 
                free( psz_type );
269
 
                if( f->p_file != NULL )
270
 
                {
271
 
                    TAB_APPEND( p_sys->i_files, p_sys->pp_files, f );
272
 
                }
273
 
            }
274
 
            else
275
 
            {
276
 
                h->p_handler = httpd_HandlerNew( p_sys->p_httpd_host,
277
 
                                                 f->name,
278
 
                                                 user, password, p_acl,
279
 
                                                 HandlerCallback, h );
280
 
                if( h->p_handler != NULL )
281
 
                {
282
 
                    TAB_APPEND( p_sys->i_files, p_sys->pp_files,
283
 
                                (httpd_file_sys_t *)h );
284
 
                }
285
 
            }
286
 
 
287
 
            /* for url that ends by / add
288
 
             *  - a redirect from rep to rep/
289
 
             *  - in case of index.* rep/index.html to rep/ */
290
 
            if( f && f->name[strlen(f->name) - 1] == '/' )
291
 
            {
292
 
                char *psz_redir = strdup( f->name );
293
 
                char *p;
294
 
                psz_redir[strlen( psz_redir ) - 1] = '\0';
295
 
 
296
 
                msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name );
297
 
                f->p_redir = httpd_RedirectNew( p_sys->p_httpd_host, f->name, psz_redir );
298
 
                free( psz_redir );
299
 
 
300
 
                if( b_index && ( p = strstr( f->file, "index." ) ) )
301
 
                {
302
 
                    if( asprintf( &psz_redir, "%s%s", f->name, p ) != -1 )
303
 
                    {
304
 
                        msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name );
305
 
                        f->p_redir2 = httpd_RedirectNew( p_sys->p_httpd_host,
306
 
                                                         f->name, psz_redir );
307
 
 
308
 
                        free( psz_redir );
309
 
                    }
310
 
                }
311
 
            }
312
 
        }
313
 
    }
314
 
 
315
 
    free( user );
316
 
    free( password );
317
 
 
318
 
    ACL_Destroy( p_acl );
319
 
    closedir( p_dir );
320
 
 
321
 
    return VLC_SUCCESS;
322
 
}
323
 
 
324
 
 
325
 
/*************************************************************************
326
 
 * Playlist stuff
327
 
 *************************************************************************/
328
 
void PlaylistListNode( intf_thread_t *p_intf, playlist_t *p_pl,
329
 
                           playlist_item_t *p_node, char *name, mvar_t *s,
330
 
                           int i_depth )
331
 
{
332
 
    if( !p_node || !p_node->p_input )
333
 
        return;
334
 
 
335
 
    if( p_node->i_children == -1 )
336
 
    {
337
 
        char value[512];
338
 
        char *psz;
339
 
        playlist_item_t * p_item = playlist_CurrentPlayingItem( p_pl );
340
 
        if( !p_item || !p_item->p_input )
341
 
            return;
342
 
 
343
 
        mvar_t *itm = mvar_New( name, "set" );
344
 
        if( p_item->p_input == p_node->p_input )
345
 
            mvar_AppendNewVar( itm, "current", "1" );
346
 
        else
347
 
            mvar_AppendNewVar( itm, "current", "0" );
348
 
 
349
 
        sprintf( value, "%d", p_node->i_id );
350
 
        mvar_AppendNewVar( itm, "index", value );
351
 
 
352
 
        psz = input_item_GetName( p_node->p_input );
353
 
        mvar_AppendNewVar( itm, "name", psz );
354
 
        free( psz );
355
 
 
356
 
        psz = input_item_GetURI( p_node->p_input );
357
 
        mvar_AppendNewVar( itm, "uri", psz );
358
 
        free( psz );
359
 
 
360
 
        mvar_AppendNewVar( itm, "type", "Item" );
361
 
 
362
 
        sprintf( value, "%d", i_depth );
363
 
        mvar_AppendNewVar( itm, "depth", value );
364
 
 
365
 
        if( p_node->i_flags & PLAYLIST_RO_FLAG )
366
 
            mvar_AppendNewVar( itm, "ro", "ro" );
367
 
        else
368
 
            mvar_AppendNewVar( itm, "ro", "rw" );
369
 
 
370
 
        sprintf( value, "%"PRId64, input_item_GetDuration( p_node->p_input ) );
371
 
        mvar_AppendNewVar( itm, "duration", value );
372
 
 
373
 
        //Adding extra meta-information to each playlist item
374
 
 
375
 
        psz = input_item_GetTitle( p_node->p_input );
376
 
        mvar_AppendNewVar( itm, "title", psz );
377
 
        free( psz );
378
 
 
379
 
        psz = input_item_GetArtist( p_node->p_input );
380
 
        mvar_AppendNewVar( itm, "artist", psz );
381
 
        free( psz );
382
 
 
383
 
        psz = input_item_GetGenre( p_node->p_input );
384
 
        mvar_AppendNewVar( itm, "genre", psz );
385
 
        free( psz );
386
 
 
387
 
        psz = input_item_GetCopyright( p_node->p_input );
388
 
        mvar_AppendNewVar( itm, "copyright", psz );
389
 
        free( psz );
390
 
 
391
 
        psz = input_item_GetAlbum( p_node->p_input );
392
 
        mvar_AppendNewVar( itm, "album", psz );
393
 
        free( psz );
394
 
 
395
 
        psz = input_item_GetTrackNum( p_node->p_input );
396
 
        mvar_AppendNewVar( itm, "track", psz );
397
 
        free( psz );
398
 
 
399
 
        psz = input_item_GetDescription( p_node->p_input );
400
 
        mvar_AppendNewVar( itm, "description", psz );
401
 
        free( psz );
402
 
 
403
 
        psz = input_item_GetRating( p_node->p_input );
404
 
        mvar_AppendNewVar( itm, "rating", psz );
405
 
        free( psz );
406
 
 
407
 
        psz = input_item_GetDate( p_node->p_input );
408
 
        mvar_AppendNewVar( itm, "date", psz );
409
 
        free( psz );
410
 
 
411
 
        psz = input_item_GetURL( p_node->p_input );
412
 
        mvar_AppendNewVar( itm, "url", psz );
413
 
        free( psz );
414
 
 
415
 
        psz = input_item_GetLanguage( p_node->p_input );
416
 
        mvar_AppendNewVar( itm, "language", psz );
417
 
        free( psz );
418
 
 
419
 
        psz = input_item_GetNowPlaying( p_node->p_input );
420
 
        mvar_AppendNewVar( itm, "now_playing", psz );
421
 
        free( psz );
422
 
 
423
 
        psz = input_item_GetPublisher( p_node->p_input );
424
 
        mvar_AppendNewVar( itm, "publisher", psz );
425
 
        free( psz );
426
 
 
427
 
        psz = input_item_GetEncodedBy( p_node->p_input );
428
 
        mvar_AppendNewVar( itm, "encoded_by", psz );
429
 
        free( psz );
430
 
 
431
 
        psz = input_item_GetArtURL( p_node->p_input );
432
 
        mvar_AppendNewVar( itm, "art_url", psz );
433
 
        free( psz );
434
 
 
435
 
        psz = input_item_GetTrackID( p_node->p_input );
436
 
        mvar_AppendNewVar( itm, "track_id", psz );
437
 
        free( psz );
438
 
 
439
 
        mvar_AppendVar( s, itm );
440
 
    }
441
 
    else
442
 
    {
443
 
        char value[512];
444
 
        int i_child;
445
 
        mvar_t *itm = mvar_New( name, "set" );
446
 
 
447
 
        mvar_AppendNewVar( itm, "name", p_node->p_input->psz_name );
448
 
        mvar_AppendNewVar( itm, "uri", p_node->p_input->psz_name );
449
 
 
450
 
        mvar_AppendNewVar( itm, "type", "Node" );
451
 
 
452
 
        sprintf( value, "%d", p_node->i_id );
453
 
        mvar_AppendNewVar( itm, "index", value );
454
 
 
455
 
        sprintf( value, "%d", p_node->i_children);
456
 
        mvar_AppendNewVar( itm, "i_children", value );
457
 
 
458
 
        sprintf( value, "%d", i_depth );
459
 
        mvar_AppendNewVar( itm, "depth", value );
460
 
 
461
 
        if( p_node->i_flags & PLAYLIST_RO_FLAG )
462
 
            mvar_AppendNewVar( itm, "ro", "ro" );
463
 
        else
464
 
            mvar_AppendNewVar( itm, "ro", "rw" );
465
 
 
466
 
        mvar_AppendVar( s, itm );
467
 
 
468
 
        for( i_child = 0 ; i_child < p_node->i_children ; i_child++ )
469
 
             PlaylistListNode( p_intf, p_pl, p_node->pp_children[i_child],
470
 
                               name, s, i_depth + 1);
471
 
    }
472
 
}
473
 
 
474
 
/****************************************************************************
475
 
 * Seek command parsing handling
476
 
 ****************************************************************************/
477
 
void HandleSeek( intf_thread_t *p_intf, char *p_value )
478
 
{
479
 
    intf_sys_t     *p_sys = p_intf->p_sys;
480
 
    vlc_value_t val;
481
 
    int i_stock = 0;
482
 
    uint64_t i_length;
483
 
    int i_value = 0;
484
 
    int i_relative = 0;
485
 
#define POSITION_ABSOLUTE 12
486
 
#define POSITION_REL_FOR 13
487
 
#define POSITION_REL_BACK 11
488
 
#define VL_TIME_ABSOLUTE 0
489
 
#define VL_TIME_REL_FOR 1
490
 
#define VL_TIME_REL_BACK -1
491
 
    if( p_sys->p_input )
492
 
    {
493
 
        var_Get( p_sys->p_input, "length", &val );
494
 
        i_length = val.i_time;
495
 
 
496
 
        while( p_value[0] != '\0' )
497
 
        {
498
 
            switch(p_value[0])
499
 
            {
500
 
                case '+':
501
 
                {
502
 
                    i_relative = VL_TIME_REL_FOR;
503
 
                    p_value++;
504
 
                    break;
505
 
                }
506
 
                case '-':
507
 
                {
508
 
                    i_relative = VL_TIME_REL_BACK;
509
 
                    p_value++;
510
 
                    break;
511
 
                }
512
 
                case '0': case '1': case '2': case '3': case '4':
513
 
                case '5': case '6': case '7': case '8': case '9':
514
 
                {
515
 
                    i_stock = strtol( p_value , &p_value , 10 );
516
 
                    break;
517
 
                }
518
 
                case '%': /* for percentage ie position */
519
 
                {
520
 
                    i_relative += POSITION_ABSOLUTE;
521
 
                    i_value = i_stock;
522
 
                    i_stock = 0;
523
 
                    p_value[0] = '\0';
524
 
                    break;
525
 
                }
526
 
                case ':':
527
 
                {
528
 
                    i_value = 60 * (i_value + i_stock) ;
529
 
                    i_stock = 0;
530
 
                    p_value++;
531
 
                    break;
532
 
                }
533
 
                case 'h': case 'H': /* hours */
534
 
                {
535
 
                    i_value += 3600 * i_stock;
536
 
                    i_stock = 0;
537
 
                    /* other characters which are not numbers are not
538
 
                     * important */
539
 
                    while( ((p_value[0] < '0') || (p_value[0] > '9'))
540
 
                           && (p_value[0] != '\0') )
541
 
                    {
542
 
                        p_value++;
543
 
                    }
544
 
                    break;
545
 
                }
546
 
                case 'm': case 'M': case '\'': /* minutes */
547
 
                {
548
 
                    i_value += 60 * i_stock;
549
 
                    i_stock = 0;
550
 
                    p_value++;
551
 
                    while( ((p_value[0] < '0') || (p_value[0] > '9'))
552
 
                           && (p_value[0] != '\0') )
553
 
                    {
554
 
                        p_value++;
555
 
                    }
556
 
                    break;
557
 
                }
558
 
                case 's': case 'S': case '"':  /* seconds */
559
 
                {
560
 
                    i_value += i_stock;
561
 
                    i_stock = 0;
562
 
                    while( ((p_value[0] < '0') || (p_value[0] > '9'))
563
 
                           && (p_value[0] != '\0') )
564
 
                    {
565
 
                        p_value++;
566
 
                    }
567
 
                    break;
568
 
                }
569
 
                default:
570
 
                {
571
 
                    p_value++;
572
 
                    break;
573
 
                }
574
 
            }
575
 
        }
576
 
 
577
 
        /* if there is no known symbol, I consider it as seconds.
578
 
         * Otherwise, i_stock = 0 */
579
 
        i_value += i_stock;
580
 
 
581
 
        switch(i_relative)
582
 
        {
583
 
            case VL_TIME_ABSOLUTE:
584
 
            {
585
 
                if( (uint64_t)( i_value ) * 1000000 <= i_length )
586
 
                    val.i_time = (uint64_t)( i_value ) * 1000000;
587
 
                else
588
 
                    val.i_time = i_length;
589
 
 
590
 
                var_Set( p_sys->p_input, "time", val );
591
 
                msg_Dbg( p_intf, "requested seek position: %dsec", i_value );
592
 
                break;
593
 
            }
594
 
            case VL_TIME_REL_FOR:
595
 
            {
596
 
                var_Get( p_sys->p_input, "time", &val );
597
 
                if( (uint64_t)( i_value ) * 1000000 + val.i_time <= i_length )
598
 
                {
599
 
                    val.i_time = ((uint64_t)( i_value ) * 1000000) + val.i_time;
600
 
                } else
601
 
                {
602
 
                    val.i_time = i_length;
603
 
                }
604
 
                var_Set( p_sys->p_input, "time", val );
605
 
                msg_Dbg( p_intf, "requested seek position forward: %dsec", i_value );
606
 
                break;
607
 
            }
608
 
            case VL_TIME_REL_BACK:
609
 
            {
610
 
                var_Get( p_sys->p_input, "time", &val );
611
 
                if( (int64_t)( i_value ) * 1000000 > val.i_time )
612
 
                {
613
 
                    val.i_time = 0;
614
 
                } else
615
 
                {
616
 
                    val.i_time = val.i_time - ((uint64_t)( i_value ) * 1000000);
617
 
                }
618
 
                var_Set( p_sys->p_input, "time", val );
619
 
                msg_Dbg( p_intf, "requested seek position backward: %dsec", i_value );
620
 
                break;
621
 
            }
622
 
            case POSITION_ABSOLUTE:
623
 
            {
624
 
                val.f_float = __MIN( __MAX( ((float) i_value ) / 100.0 ,
625
 
                                            0.0 ), 100.0 );
626
 
                var_Set( p_sys->p_input, "position", val );
627
 
                msg_Dbg( p_intf, "requested seek percent: %d%%", i_value );
628
 
                break;
629
 
            }
630
 
            case POSITION_REL_FOR:
631
 
            {
632
 
                var_Get( p_sys->p_input, "position", &val );
633
 
                val.f_float += __MIN( __MAX( ((float) i_value ) / 100.0,
634
 
                                             0.0 ) , 100.0 );
635
 
                var_Set( p_sys->p_input, "position", val );
636
 
                msg_Dbg( p_intf, "requested seek percent forward: %d%%",
637
 
                         i_value );
638
 
                break;
639
 
            }
640
 
            case POSITION_REL_BACK:
641
 
            {
642
 
                var_Get( p_sys->p_input, "position", &val );
643
 
                val.f_float -= __MIN( __MAX( ((float) i_value ) / 100.0,
644
 
                                             0.0 ) , 100.0 );
645
 
                var_Set( p_sys->p_input, "position", val );
646
 
                msg_Dbg( p_intf, "requested seek percent backward: %d%%",
647
 
                         i_value );
648
 
                break;
649
 
            }
650
 
            default:
651
 
            {
652
 
                msg_Dbg( p_intf, "invalid seek request" );
653
 
                break;
654
 
            }
655
 
        }
656
 
    }
657
 
#undef POSITION_ABSOLUTE
658
 
#undef POSITION_REL_FOR
659
 
#undef POSITION_REL_BACK
660
 
#undef VL_TIME_ABSOLUTE
661
 
#undef VL_TIME_REL_FOR
662
 
#undef VL_TIME_REL_BACK
663
 
}
664
 
 
665
 
 
666
 
/****************************************************************************
667
 
 * URI Parsing functions
668
 
 ****************************************************************************/
669
 
int TestURIParam( char *psz_uri, const char *psz_name )
670
 
{
671
 
    char *p = psz_uri;
672
 
 
673
 
    while( (p = strstr( p, psz_name )) )
674
 
    {
675
 
        /* Verify that we are dealing with a post/get argument */
676
 
        if( (p == psz_uri || *(p - 1) == '&' || *(p - 1) == '\n')
677
 
              && p[strlen(psz_name)] == '=' )
678
 
        {
679
 
            return true;
680
 
        }
681
 
        p++;
682
 
    }
683
 
 
684
 
    return false;
685
 
}
686
 
 
687
 
static const char *FindURIValue( const char *psz_uri, const char *restrict psz_name,
688
 
                           size_t *restrict p_len )
689
 
{
690
 
    const char *p = psz_uri, *end;
691
 
    size_t len;
692
 
 
693
 
    while( (p = strstr( p, psz_name )) )
694
 
    {
695
 
        /* Verify that we are dealing with a post/get argument */
696
 
        if( (p == psz_uri || *(p - 1) == '&' || *(p - 1) == '\n')
697
 
              && p[strlen(psz_name)] == '=' )
698
 
            break;
699
 
        p++;
700
 
    }
701
 
 
702
 
    if( p == NULL )
703
 
    {
704
 
        *p_len = 0;
705
 
        return NULL;
706
 
    }
707
 
 
708
 
    p += strlen( psz_name );
709
 
    if( *p == '=' ) p++;
710
 
 
711
 
    if( ( end = strchr( p, '\n' ) ) != NULL )
712
 
    {
713
 
        /* POST method */
714
 
        if( ( end > p ) && ( end[-1] == '\r' ) )
715
 
            end--;
716
 
 
717
 
        len = end - p;
718
 
    }
719
 
    else
720
 
    {
721
 
        /* GET method */
722
 
        if( ( end = strchr( p, '&' ) ) != NULL )
723
 
            len = end - p;
724
 
        else
725
 
            len = strlen( p );
726
 
    }
727
 
 
728
 
    *p_len = len;
729
 
    return p;
730
 
}
731
 
 
732
 
const char *ExtractURIValue( const char *restrict psz_uri,
733
 
                           const char *restrict psz_name,
734
 
                           char *restrict psz_buf, size_t bufsize )
735
 
{
736
 
    size_t len;
737
 
    const char *psz_value = FindURIValue( psz_uri, psz_name, &len );
738
 
    const char *psz_next;
739
 
 
740
 
    if( psz_value == NULL )
741
 
    {
742
 
        if( bufsize > 0 )
743
 
            *psz_buf = '\0';
744
 
        return NULL;
745
 
    }
746
 
 
747
 
    psz_next = psz_value + len;
748
 
 
749
 
    if( len >= bufsize )
750
 
        len = bufsize - 1;
751
 
 
752
 
    if( len > 0 )
753
 
        strncpy( psz_buf, psz_value, len );
754
 
    if( bufsize > 0 )
755
 
        psz_buf[len] = '\0';
756
 
 
757
 
    return psz_next;
758
 
}
759
 
 
760
 
char *ExtractURIString( const char *restrict psz_uri,
761
 
                            const char *restrict psz_name )
762
 
{
763
 
    size_t len;
764
 
    const char *psz_value = FindURIValue( psz_uri, psz_name, &len );
765
 
 
766
 
    if( psz_value == NULL )
767
 
        return NULL;
768
 
 
769
 
    char *res = malloc( len + 1 );
770
 
    if( res == NULL )
771
 
        return NULL;
772
 
 
773
 
    memcpy( res, psz_value, len );
774
 
    res[len] = '\0';
775
 
 
776
 
    return res;
777
 
}
778
 
 
779
 
/* Since the resulting string is smaller we can work in place, so it is
780
 
 * permitted to have psz == new. new points to the first word of the
781
 
 * string, the function returns the remaining string. */
782
 
char *FirstWord( char *psz, char *new )
783
 
{
784
 
    bool b_end;
785
 
 
786
 
    while( *psz == ' ' )
787
 
        psz++;
788
 
 
789
 
    while( *psz != '\0' && *psz != ' ' )
790
 
    {
791
 
        if( *psz == '\'' )
792
 
        {
793
 
            char c = *psz++;
794
 
            while( *psz != '\0' && *psz != c )
795
 
            {
796
 
                if( *psz == '\\' && psz[1] != '\0' )
797
 
                    psz++;
798
 
                *new++ = *psz++;
799
 
            }
800
 
            if( *psz == c )
801
 
                psz++;
802
 
        }
803
 
        else
804
 
        {
805
 
            if( *psz == '\\' && psz[1] != '\0' )
806
 
                psz++;
807
 
            *new++ = *psz++;
808
 
        }
809
 
    }
810
 
    b_end = !*psz;
811
 
 
812
 
    *new++ = '\0';
813
 
    if( !b_end )
814
 
        return psz + 1;
815
 
    else
816
 
        return NULL;
817
 
}
818
 
 
819
 
/**********************************************************************
820
 
 * MRLParse: parse the MRL, find the MRL string and the options,
821
 
 * create an item with all information in it, and return the item.
822
 
 * return NULL if there is an error.
823
 
 **********************************************************************/
824
 
 
825
 
/* Function analog to FirstWord except that it relies on colon instead
826
 
 * of space to delimit option boundaries. */
827
 
static char *FirstOption( char *psz, char *new )
828
 
{
829
 
    bool b_end, b_start = true;
830
 
 
831
 
    while( *psz == ' ' )
832
 
        psz++;
833
 
 
834
 
    while( *psz != '\0' && (*psz != ' ' || psz[1] != ':') )
835
 
    {
836
 
        if( *psz == '\'' )
837
 
        {
838
 
            char c = *psz++;
839
 
            while( *psz != '\0' && *psz != c )
840
 
            {
841
 
                if( *psz == '\\' && psz[1] != '\0' )
842
 
                    psz++;
843
 
                *new++ = *psz++;
844
 
                b_start = false;
845
 
            }
846
 
            if( *psz == c )
847
 
                psz++;
848
 
        }
849
 
        else
850
 
        {
851
 
            if( *psz == '\\' && psz[1] != '\0' )
852
 
                psz++;
853
 
            *new++ = *psz++;
854
 
            b_start = false;
855
 
        }
856
 
    }
857
 
    b_end = !*psz;
858
 
 
859
 
    if ( !b_start )
860
 
        while (new[-1] == ' ')
861
 
            new--;
862
 
 
863
 
    *new++ = '\0';
864
 
    if( !b_end )
865
 
        return psz + 1;
866
 
    else
867
 
        return NULL;
868
 
}
869
 
 
870
 
input_item_t *MRLParse( intf_thread_t *p_intf, const char *mrl,
871
 
                                   char *psz_name )
872
 
{
873
 
    char *psz = strdup( mrl ), *s_mrl = psz, *s_temp;
874
 
    if( psz == NULL )
875
 
        return NULL;
876
 
    /* extract the mrl */
877
 
    s_temp = FirstOption( s_mrl, s_mrl );
878
 
    if( s_temp == NULL )
879
 
    {
880
 
        s_temp = s_mrl + strlen( s_mrl );
881
 
    }
882
 
 
883
 
    input_item_t *p_input = input_item_New( p_intf, s_mrl, psz_name );
884
 
    if( p_input == NULL )
885
 
        return NULL;
886
 
    s_mrl = s_temp;
887
 
 
888
 
    /* now we can take care of the options */
889
 
    while ( *s_mrl != '\0' )
890
 
    {
891
 
        s_temp = FirstOption( s_mrl, s_mrl );
892
 
        if( s_mrl == '\0' )
893
 
            break;
894
 
        if( s_temp == NULL )
895
 
        {
896
 
            s_temp = s_mrl + strlen( s_mrl );
897
 
        }
898
 
        input_item_AddOption( p_input, s_mrl, VLC_INPUT_OPTION_TRUSTED );
899
 
        s_mrl = s_temp;
900
 
    }
901
 
 
902
 
    return p_input;
903
 
}
904
 
 
905
 
/**********************************************************************
906
 
 * RealPath: parse ../, ~ and path stuff
907
 
 **********************************************************************/
908
 
char *RealPath( const char *psz_src )
909
 
{
910
 
    char *psz_dir;
911
 
    char *p;
912
 
    int i_len = strlen(psz_src);
913
 
 
914
 
    psz_dir = xmalloc( i_len + 2 );
915
 
    strcpy( psz_dir, psz_src );
916
 
 
917
 
    /* Add a trailing sep to ease the .. step */
918
 
    psz_dir[i_len] = DIR_SEP_CHAR;
919
 
    psz_dir[i_len + 1] = '\0';
920
 
 
921
 
#if (DIR_SEP_CHAR != '/')
922
 
    /* Convert all / to native separator */
923
 
    p = psz_dir;
924
 
    while( (p = strchr( p, '/' )) != NULL )
925
 
    {
926
 
        *p = DIR_SEP_CHAR;
927
 
    }
928
 
#endif
929
 
 
930
 
    /* FIXME: this could be O(N) rather than O(N²)... */
931
 
    /* Remove multiple separators and /./ */
932
 
    p = psz_dir;
933
 
    while( (p = strchr( p, DIR_SEP_CHAR )) != NULL )
934
 
    {
935
 
        if( p[1] == DIR_SEP_CHAR )
936
 
            memmove( &p[1], &p[2], strlen(&p[2]) + 1 );
937
 
        else if( p[1] == '.' && p[2] == DIR_SEP_CHAR )
938
 
            memmove( &p[1], &p[3], strlen(&p[3]) + 1 );
939
 
        else
940
 
            p++;
941
 
    }
942
 
 
943
 
    if( psz_dir[0] == '~' )
944
 
    {
945
 
        char *home = config_GetUserDir( VLC_HOME_DIR ), *dir;
946
 
        if( asprintf( &dir, "%s%s", home, psz_dir + 1 ) != -1 )
947
 
        {
948
 
            free( psz_dir );
949
 
            psz_dir = dir;
950
 
        }
951
 
        free( home );
952
 
    }
953
 
 
954
 
    if( strlen(psz_dir) > 2 )
955
 
    {
956
 
        /* Fix all .. dir */
957
 
        p = psz_dir + 3;
958
 
        while( (p = strchr( p, DIR_SEP_CHAR )) != NULL )
959
 
        {
960
 
            if( p[-1] == '.' && p[-2] == '.' && p[-3] == DIR_SEP_CHAR )
961
 
            {
962
 
                char *q;
963
 
                p[-3] = '\0';
964
 
                if( (q = strrchr( psz_dir, DIR_SEP_CHAR )) != NULL )
965
 
                {
966
 
                    memmove( q + 1, p + 1, strlen(p + 1) + 1 );
967
 
                    p = q + 1;
968
 
                }
969
 
                else
970
 
                {
971
 
                    memmove( psz_dir, p, strlen(p) + 1 );
972
 
                    p = psz_dir + 3;
973
 
                }
974
 
            }
975
 
            else
976
 
                p++;
977
 
        }
978
 
    }
979
 
 
980
 
    /* Remove trailing sep if there are at least 2 sep in the string
981
 
     * (handles the C:\ stuff) */
982
 
    p = strrchr( psz_dir, DIR_SEP_CHAR );
983
 
    if( p != NULL && p[1] == '\0' && p != strchr( psz_dir, DIR_SEP_CHAR ) )
984
 
        *p = '\0';
985
 
 
986
 
    return psz_dir;
987
 
}