Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

util.c

00001 /*****************************************************************************
00002  * util.c : Utility functions for HTTP interface
00003  *****************************************************************************
00004  * Copyright (C) 2001-2005 the VideoLAN team
00005  * $Id: http.c 12225 2005-08-18 10:01:30Z massiot $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *          Laurent Aimar <[email protected]>
00009  *          Christophe Massiot <[email protected]>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 
00026 #include "http.h"
00027 
00028 /****************************************************************************
00029  * File and directory functions
00030  ****************************************************************************/
00031 
00032 /* ToUrl: create a good name for an url from filename */
00033 char *E_(FileToUrl)( char *name, vlc_bool_t *pb_index )
00034 {
00035     char *url, *p;
00036 
00037     url = p = malloc( strlen( name ) + 1 );
00038 
00039     *pb_index = VLC_FALSE;
00040     if( !url || !p )
00041     {
00042         return NULL;
00043     }
00044 
00045 #ifdef WIN32
00046     while( *name == '\\' || *name == '/' )
00047 #else
00048     while( *name == '/' )
00049 #endif
00050     {
00051         name++;
00052     }
00053 
00054     *p++ = '/';
00055     strcpy( p, name );
00056 
00057 #ifdef WIN32
00058     /* convert '\\' into '/' */
00059     name = p;
00060     while( *name )
00061     {
00062         if( *name == '\\' )
00063             *name = '/';
00064         name++;
00065     }
00066 #endif
00067 
00068     /* index.* -> / */
00069     if( ( p = strrchr( url, '/' ) ) != NULL )
00070     {
00071         if( !strncmp( p, "/index.", 7 ) )
00072         {
00073             p[1] = '\0';
00074             *pb_index = VLC_TRUE;
00075         }
00076     }
00077     return url;
00078 }
00079 
00080 /* Load a file */
00081 int E_(FileLoad)( FILE *f, char **pp_data, int *pi_data )
00082 {
00083     int i_read;
00084 
00085     /* just load the file */
00086     *pi_data = 0;
00087     *pp_data = malloc( 1025 );  /* +1 for \0 */
00088     while( ( i_read = fread( &(*pp_data)[*pi_data], 1, 1024, f ) ) == 1024 )
00089     {
00090         *pi_data += 1024;
00091         *pp_data = realloc( *pp_data, *pi_data  + 1025 );
00092     }
00093     if( i_read > 0 )
00094     {
00095         *pi_data += i_read;
00096     }
00097     (*pp_data)[*pi_data] = '\0';
00098 
00099     return VLC_SUCCESS;
00100 }
00101 
00102 /* Parse a directory and recursively add files */
00103 int E_(ParseDirectory)( intf_thread_t *p_intf, char *psz_root,
00104                         char *psz_dir )
00105 {
00106     intf_sys_t     *p_sys = p_intf->p_sys;
00107     char           dir[MAX_DIR_SIZE];
00108 #ifdef HAVE_SYS_STAT_H
00109     struct stat   stat_info;
00110 #endif
00111     DIR           *p_dir;
00112     struct dirent *p_dir_content;
00113     vlc_acl_t     *p_acl;
00114     FILE          *file;
00115 
00116     char          *user = NULL;
00117     char          *password = NULL;
00118 
00119     int           i_dirlen;
00120 
00121     char sep;
00122 
00123 #if defined( WIN32 )
00124     sep = '\\';
00125 #else
00126     sep = '/';
00127 #endif
00128 
00129 #ifdef HAVE_SYS_STAT_H
00130     if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) )
00131     {
00132         return VLC_EGENERIC;
00133     }
00134 #endif
00135 
00136     if( ( p_dir = opendir( psz_dir ) ) == NULL )
00137     {
00138         msg_Err( p_intf, "cannot open dir (%s)", psz_dir );
00139         return VLC_EGENERIC;
00140     }
00141 
00142     i_dirlen = strlen( psz_dir );
00143     if( i_dirlen + 10 > MAX_DIR_SIZE )
00144     {
00145         msg_Warn( p_intf, "skipping too deep dir (%s)", psz_dir );
00146         return 0;
00147     }
00148 
00149     msg_Dbg( p_intf, "dir=%s", psz_dir );
00150 
00151     sprintf( dir, "%s%c.access", psz_dir, sep );
00152     if( ( file = fopen( dir, "r" ) ) != NULL )
00153     {
00154         char line[1024];
00155         int  i_size;
00156 
00157         msg_Dbg( p_intf, "find .access in dir=%s", psz_dir );
00158 
00159         i_size = fread( line, 1, 1023, file );
00160         if( i_size > 0 )
00161         {
00162             char *p;
00163             while( i_size > 0 && ( line[i_size-1] == '\n' ||
00164                    line[i_size-1] == '\r' ) )
00165             {
00166                 i_size--;
00167             }
00168 
00169             line[i_size] = '\0';
00170 
00171             p = strchr( line, ':' );
00172             if( p )
00173             {
00174                 *p++ = '\0';
00175                 user = strdup( line );
00176                 password = strdup( p );
00177             }
00178         }
00179         msg_Dbg( p_intf, "using user=%s password=%s (read=%d)",
00180                  user, password, i_size );
00181 
00182         fclose( file );
00183     }
00184 
00185     sprintf( dir, "%s%c.hosts", psz_dir, sep );
00186     p_acl = ACL_Create( p_intf, VLC_FALSE );
00187     if( ACL_LoadFile( p_acl, dir ) )
00188     {
00189         ACL_Destroy( p_acl );
00190         p_acl = NULL;
00191     }
00192 
00193     for( ;; )
00194     {
00195         /* parse psz_src dir */
00196         if( ( p_dir_content = readdir( p_dir ) ) == NULL )
00197         {
00198             break;
00199         }
00200 
00201         if( ( p_dir_content->d_name[0] == '.' )
00202          || ( i_dirlen + strlen( p_dir_content->d_name ) > MAX_DIR_SIZE ) )
00203             continue;
00204 
00205         sprintf( dir, "%s%c%s", psz_dir, sep, p_dir_content->d_name );
00206         if( E_(ParseDirectory)( p_intf, psz_root, dir ) )
00207         {
00208             httpd_file_sys_t *f = NULL;
00209             httpd_handler_sys_t *h = NULL;
00210             vlc_bool_t b_index;
00211             char *psz_tmp, *psz_file, *psz_name, *psz_ext;
00212 
00213             psz_tmp = vlc_fix_readdir_charset( p_intf, dir );
00214             psz_file = E_(FromUTF8)( p_intf, psz_tmp );
00215             free( psz_tmp );
00216             psz_tmp = vlc_fix_readdir_charset( p_intf,
00217                                                &dir[strlen( psz_root )] );
00218             psz_name = E_(FileToUrl)( psz_tmp, &b_index );
00219             free( psz_tmp );
00220             psz_ext = strrchr( psz_file, '.' );
00221             if( psz_ext != NULL )
00222             {
00223                 int i;
00224                 psz_ext++;
00225                 for( i = 0; i < p_sys->i_handlers; i++ )
00226                     if( !strcmp( p_sys->pp_handlers[i]->psz_ext, psz_ext ) )
00227                         break;
00228                 if( i < p_sys->i_handlers )
00229                 {
00230                     f = malloc( sizeof( httpd_handler_sys_t ) );
00231                     h = (httpd_handler_sys_t *)f;
00232                     f->b_handler = VLC_TRUE;
00233                     h->p_association = p_sys->pp_handlers[i];
00234                 }
00235             }
00236             if( f == NULL )
00237             {
00238                 f = malloc( sizeof( httpd_file_sys_t ) );
00239                 f->b_handler = VLC_FALSE;
00240             }
00241 
00242             f->p_intf  = p_intf;
00243             f->p_file = NULL;
00244             f->p_redir = NULL;
00245             f->p_redir2 = NULL;
00246             f->file = psz_file;
00247             f->name = psz_name;
00248             f->b_html = strstr( &dir[strlen( psz_root )], ".htm" ) ? VLC_TRUE : VLC_FALSE;
00249 
00250             if( !f->name )
00251             {
00252                 msg_Err( p_intf , "unable to parse directory" );
00253                 closedir( p_dir );
00254                 free( f );
00255                 return( VLC_ENOMEM );
00256             }
00257             msg_Dbg( p_intf, "file=%s (url=%s)",
00258                      f->file, f->name );
00259 
00260             if( !f->b_handler )
00261             {
00262                 f->p_file = httpd_FileNew( p_sys->p_httpd_host,
00263                                            f->name,
00264                                            f->b_html ? p_sys->psz_html_type :
00265                                             NULL,
00266                                            user, password, p_acl,
00267                                            E_(HttpCallback), f );
00268                 if( f->p_file != NULL )
00269                 {
00270                     TAB_APPEND( p_sys->i_files, p_sys->pp_files, f );
00271                 }
00272             }
00273             else
00274             {
00275                 h->p_handler = httpd_HandlerNew( p_sys->p_httpd_host,
00276                                                  f->name,
00277                                                  user, password, p_acl,
00278                                                  E_(HandlerCallback), h );
00279                 if( h->p_handler != NULL )
00280                 {
00281                     TAB_APPEND( p_sys->i_files, p_sys->pp_files,
00282                                 (httpd_file_sys_t *)h );
00283                 }
00284             }
00285 
00286             /* for url that ends by / add
00287              *  - a redirect from rep to rep/
00288              *  - in case of index.* rep/index.html to rep/ */
00289             if( f && f->name[strlen(f->name) - 1] == '/' )
00290             {
00291                 char *psz_redir = strdup( f->name );
00292                 char *p;
00293                 psz_redir[strlen( psz_redir ) - 1] = '\0';
00294 
00295                 msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name );
00296                 f->p_redir = httpd_RedirectNew( p_sys->p_httpd_host, f->name, psz_redir );
00297                 free( psz_redir );
00298 
00299                 if( b_index && ( p = strstr( f->file, "index." ) ) )
00300                 {
00301                     asprintf( &psz_redir, "%s%s", f->name, p );
00302 
00303                     msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name );
00304                     f->p_redir2 = httpd_RedirectNew( p_sys->p_httpd_host,
00305                                                      f->name, psz_redir );
00306 
00307                     free( psz_redir );
00308                 }
00309             }
00310         }
00311     }
00312 
00313     if( user )
00314     {
00315         free( user );
00316     }
00317     if( password )
00318     {
00319         free( password );
00320     }
00321 
00322     ACL_Destroy( p_acl );
00323     closedir( p_dir );
00324 
00325     return VLC_SUCCESS;
00326 }
00327 
00328 
00329 /**************************************************************************
00330  * Locale functions
00331  **************************************************************************/
00332 char *E_(FromUTF8)( intf_thread_t *p_intf, char *psz_utf8 )
00333 {
00334     intf_sys_t    *p_sys = p_intf->p_sys;
00335 
00336     if ( p_sys->iconv_from_utf8 != (vlc_iconv_t)-1 )
00337     {
00338         size_t i_in = strlen(psz_utf8);
00339         size_t i_out = i_in * 2;
00340         char *psz_local = malloc(i_out + 1);
00341         char *psz_out = psz_local;
00342         size_t i_ret;
00343         char psz_tmp[i_in + 1];
00344         char *psz_in = psz_tmp;
00345         uint8_t *p = (uint8_t *)psz_tmp;
00346         strcpy( psz_tmp, psz_utf8 );
00347 
00348         /* Fix Unicode quotes. If we are here we are probably converting
00349          * to an inferior charset not understanding Unicode quotes. */
00350         while( *p )
00351         {
00352             if( p[0] == 0xe2 && p[1] == 0x80 && p[2] == 0x99 )
00353             {
00354                 *p = '\'';
00355                 memmove( &p[1], &p[3], strlen(&p[3]) + 1 );
00356             }
00357             if( p[0] == 0xe2 && p[1] == 0x80 && p[2] == 0x9a )
00358             {
00359                 *p = '"';
00360                 memmove( &p[1], &p[3], strlen(&p[3]) + 1 );
00361             }
00362             p++;
00363         }
00364         i_in = strlen( psz_tmp );
00365 
00366         i_ret = vlc_iconv( p_sys->iconv_from_utf8, &psz_in, &i_in,
00367                            &psz_out, &i_out );
00368         if( i_ret == (size_t)-1 || i_in )
00369         {
00370             msg_Warn( p_intf,
00371                       "failed to convert \"%s\" to desired charset (%s)",
00372                       psz_utf8, strerror(errno) );
00373             free( psz_local );
00374             return strdup( psz_utf8 );
00375         }
00376 
00377         *psz_out = '\0';
00378         return psz_local;
00379     }
00380     else
00381         return strdup( psz_utf8 );
00382 }
00383 
00384 char *E_(ToUTF8)( intf_thread_t *p_intf, char *psz_local )
00385 {
00386     intf_sys_t    *p_sys = p_intf->p_sys;
00387 
00388     if ( p_sys->iconv_to_utf8 != (vlc_iconv_t)-1 )
00389     {
00390         char *psz_in = psz_local;
00391         size_t i_in = strlen(psz_in);
00392         size_t i_out = i_in * 6;
00393         char *psz_utf8 = malloc(i_out + 1);
00394         char *psz_out = psz_utf8;
00395 
00396         size_t i_ret = vlc_iconv( p_sys->iconv_to_utf8, &psz_in, &i_in,
00397                                   &psz_out, &i_out );
00398         if( i_ret == (size_t)-1 || i_in )
00399         {
00400             msg_Warn( p_intf,
00401                       "failed to convert \"%s\" to desired charset (%s)",
00402                       psz_local, strerror(errno) );
00403             free( psz_utf8 );
00404             return strdup( psz_local );
00405         }
00406 
00407         *psz_out = '\0';
00408         return psz_utf8;
00409     }
00410     else
00411         return strdup( psz_local );
00412 }
00413 
00414 /*************************************************************************
00415  * Playlist stuff
00416  *************************************************************************/
00417 void E_(PlaylistListNode)( intf_thread_t *p_intf, playlist_t *p_pl,
00418                            playlist_item_t *p_node, char *name, mvar_t *s,
00419                            int i_depth )
00420 {
00421     if( p_node != NULL )
00422     {
00423         if( p_node->i_children == -1 )
00424         {
00425             char value[512];
00426             char *psz;
00427             mvar_t *itm = E_(mvar_New)( name, "set" );
00428 
00429             sprintf( value, "%d", ( p_pl->status.p_item == p_node )? 1 : 0 );
00430             E_(mvar_AppendNewVar)( itm, "current", value );
00431 
00432             sprintf( value, "%d", p_node->input.i_id );
00433             E_(mvar_AppendNewVar)( itm, "index", value );
00434 
00435             psz = E_(FromUTF8)( p_intf, p_node->input.psz_name );
00436             E_(mvar_AppendNewVar)( itm, "name", psz );
00437             free( psz );
00438 
00439             psz = E_(FromUTF8)( p_intf, p_node->input.psz_uri );
00440             E_(mvar_AppendNewVar)( itm, "uri", psz );
00441             free( psz );
00442 
00443             sprintf( value, "Item");
00444             E_(mvar_AppendNewVar)( itm, "type", value );
00445 
00446             sprintf( value, "%d", i_depth );
00447             E_(mvar_AppendNewVar)( itm, "depth", value );
00448 
00449             E_(mvar_AppendVar)( s, itm );
00450         }
00451         else
00452         {
00453             char value[512];
00454             char *psz;
00455             int i_child;
00456             mvar_t *itm = E_(mvar_New)( name, "set" );
00457 
00458             psz = E_(FromUTF8)( p_intf, p_node->input.psz_name );
00459             E_(mvar_AppendNewVar)( itm, "name", psz );
00460             E_(mvar_AppendNewVar)( itm, "uri", psz );
00461             free( psz );
00462 
00463             sprintf( value, "Node" );
00464             E_(mvar_AppendNewVar)( itm, "type", value );
00465 
00466             sprintf( value, "%d", p_node->input.i_id );
00467             E_(mvar_AppendNewVar)( itm, "index", value );
00468 
00469             sprintf( value, "%d", p_node->i_children);
00470             E_(mvar_AppendNewVar)( itm, "i_children", value );
00471 
00472             sprintf( value, "%d", i_depth );
00473             E_(mvar_AppendNewVar)( itm, "depth", value );
00474 
00475             E_(mvar_AppendVar)( s, itm );
00476 
00477             for (i_child = 0 ; i_child < p_node->i_children ; i_child++)
00478                 E_(PlaylistListNode)( p_intf, p_pl,
00479                                       p_node->pp_children[i_child],
00480                                       name, s, i_depth + 1);
00481 
00482         }
00483     }
00484 }
00485 
00486 /****************************************************************************
00487  * Seek command parsing handling
00488  ****************************************************************************/
00489 void E_(HandleSeek)( intf_thread_t *p_intf, char *p_value )
00490 {
00491     intf_sys_t     *p_sys = p_intf->p_sys;
00492     vlc_value_t val;
00493     int i_stock = 0;
00494     uint64_t i_length;
00495     int i_value = 0;
00496     int i_relative = 0;
00497 #define POSITION_ABSOLUTE 12
00498 #define POSITION_REL_FOR 13
00499 #define POSITION_REL_BACK 11
00500 #define VL_TIME_ABSOLUTE 0
00501 #define VL_TIME_REL_FOR 1
00502 #define VL_TIME_REL_BACK -1
00503     if( p_sys->p_input )
00504     {
00505         var_Get( p_sys->p_input, "length", &val );
00506         i_length = val.i_time;
00507 
00508         while( p_value[0] != '\0' )
00509         {
00510             switch(p_value[0])
00511             {
00512                 case '+':
00513                 {
00514                     i_relative = VL_TIME_REL_FOR;
00515                     p_value++;
00516                     break;
00517                 }
00518                 case '-':
00519                 {
00520                     i_relative = VL_TIME_REL_BACK;
00521                     p_value++;
00522                     break;
00523                 }
00524                 case '0': case '1': case '2': case '3': case '4':
00525                 case '5': case '6': case '7': case '8': case '9':
00526                 {
00527                     i_stock = strtol( p_value , &p_value , 10 );
00528                     break;
00529                 }
00530                 case '%': /* for percentage ie position */
00531                 {
00532                     i_relative += POSITION_ABSOLUTE;
00533                     i_value = i_stock;
00534                     i_stock = 0;
00535                     p_value[0] = '\0';
00536                     break;
00537                 }
00538                 case ':':
00539                 {
00540                     i_value = 60 * (i_value + i_stock) ;
00541                     i_stock = 0;
00542                     p_value++;
00543                     break;
00544                 }
00545                 case 'h': case 'H': /* hours */
00546                 {
00547                     i_value += 3600 * i_stock;
00548                     i_stock = 0;
00549                     /* other characters which are not numbers are not important */
00550                     while( ((p_value[0] < '0') || (p_value[0] > '9')) && (p_value[0] != '\0') )
00551                     {
00552                         p_value++;
00553                     }
00554                     break;
00555                 }
00556                 case 'm': case 'M': case '\'': /* minutes */
00557                 {
00558                     i_value += 60 * i_stock;
00559                     i_stock = 0;
00560                     p_value++;
00561                     while( ((p_value[0] < '0') || (p_value[0] > '9')) && (p_value[0] != '\0') )
00562                     {
00563                         p_value++;
00564                     }
00565                     break;
00566                 }
00567                 case 's': case 'S': case '"':  /* seconds */
00568                 {
00569                     i_value += i_stock;
00570                     i_stock = 0;
00571                     while( ((p_value[0] < '0') || (p_value[0] > '9')) && (p_value[0] != '\0') )
00572                     {
00573                         p_value++;
00574                     }
00575                     break;
00576                 }
00577                 default:
00578                 {
00579                     p_value++;
00580                     break;
00581                 }
00582             }
00583         }
00584 
00585         /* if there is no known symbol, I consider it as seconds. Otherwise, i_stock = 0 */
00586         i_value += i_stock;
00587 
00588         switch(i_relative)
00589         {
00590             case VL_TIME_ABSOLUTE:
00591             {
00592                 if( (uint64_t)( i_value ) * 1000000 <= i_length )
00593                     val.i_time = (uint64_t)( i_value ) * 1000000;
00594                 else
00595                     val.i_time = i_length;
00596 
00597                 var_Set( p_sys->p_input, "time", val );
00598                 msg_Dbg( p_intf, "requested seek position: %dsec", i_value );
00599                 break;
00600             }
00601             case VL_TIME_REL_FOR:
00602             {
00603                 var_Get( p_sys->p_input, "time", &val );
00604                 if( (uint64_t)( i_value ) * 1000000 + val.i_time <= i_length )
00605                 {
00606                     val.i_time = ((uint64_t)( i_value ) * 1000000) + val.i_time;
00607                 } else
00608                 {
00609                     val.i_time = i_length;
00610                 }
00611                 var_Set( p_sys->p_input, "time", val );
00612                 msg_Dbg( p_intf, "requested seek position forward: %dsec", i_value );
00613                 break;
00614             }
00615             case VL_TIME_REL_BACK:
00616             {
00617                 var_Get( p_sys->p_input, "time", &val );
00618                 if( (int64_t)( i_value ) * 1000000 > val.i_time )
00619                 {
00620                     val.i_time = 0;
00621                 } else
00622                 {
00623                     val.i_time = val.i_time - ((uint64_t)( i_value ) * 1000000);
00624                 }
00625                 var_Set( p_sys->p_input, "time", val );
00626                 msg_Dbg( p_intf, "requested seek position backward: %dsec", i_value );
00627                 break;
00628             }
00629             case POSITION_ABSOLUTE:
00630             {
00631                 val.f_float = __MIN( __MAX( ((float) i_value ) / 100.0 , 0.0 ) , 100.0 );
00632                 var_Set( p_sys->p_input, "position", val );
00633                 msg_Dbg( p_intf, "requested seek percent: %d", i_value );
00634                 break;
00635             }
00636             case POSITION_REL_FOR:
00637             {
00638                 var_Get( p_sys->p_input, "position", &val );
00639                 val.f_float += __MIN( __MAX( ((float) i_value ) / 100.0 , 0.0 ) , 100.0 );
00640                 var_Set( p_sys->p_input, "position", val );
00641                 msg_Dbg( p_intf, "requested seek percent forward: %d", i_value );
00642                 break;
00643             }
00644             case POSITION_REL_BACK:
00645             {
00646                 var_Get( p_sys->p_input, "position", &val );
00647                 val.f_float -= __MIN( __MAX( ((float) i_value ) / 100.0 , 0.0 ) , 100.0 );
00648                 var_Set( p_sys->p_input, "position", val );
00649                 msg_Dbg( p_intf, "requested seek percent backward: %d", i_value );
00650                 break;
00651             }
00652             default:
00653             {
00654                 msg_Dbg( p_intf, "requested seek: what the f*** is going on here ?" );
00655                 break;
00656             }
00657         }
00658     }
00659 #undef POSITION_ABSOLUTE
00660 #undef POSITION_REL_FOR
00661 #undef POSITION_REL_BACK
00662 #undef VL_TIME_ABSOLUTE
00663 #undef VL_TIME_REL_FOR
00664 #undef VL_TIME_REL_BACK
00665 }
00666 
00667 
00668 /****************************************************************************
00669  * URI Parsing functions
00670  ****************************************************************************/
00671 int E_(TestURIParam)( char *psz_uri, const char *psz_name )
00672 {
00673     char *p = psz_uri;
00674 
00675     while( (p = strstr( p, psz_name )) )
00676     {
00677         /* Verify that we are dealing with a post/get argument */
00678         if( (p == psz_uri || *(p - 1) == '&' || *(p - 1) == '\n')
00679               && p[strlen(psz_name)] == '=' )
00680         {
00681             return VLC_TRUE;
00682         }
00683         p++;
00684     }
00685 
00686     return VLC_FALSE;
00687 }
00688 char *E_(ExtractURIValue)( char *psz_uri, const char *psz_name,
00689                              char *psz_value, int i_value_max )
00690 {
00691     char *p = psz_uri;
00692 
00693     while( (p = strstr( p, psz_name )) )
00694     {
00695         /* Verify that we are dealing with a post/get argument */
00696         if( (p == psz_uri || *(p - 1) == '&' || *(p - 1) == '\n')
00697               && p[strlen(psz_name)] == '=' )
00698             break;
00699         p++;
00700     }
00701 
00702     if( p )
00703     {
00704         int i_len;
00705 
00706         p += strlen( psz_name );
00707         if( *p == '=' ) p++;
00708 
00709         if( strchr( p, '&' ) )
00710         {
00711             i_len = strchr( p, '&' ) - p;
00712         }
00713         else
00714         {
00715             /* for POST method */
00716             if( strchr( p, '\n' ) )
00717             {
00718                 i_len = strchr( p, '\n' ) - p;
00719                 if( i_len && *(p+i_len-1) == '\r' ) i_len--;
00720             }
00721             else
00722             {
00723                 i_len = strlen( p );
00724             }
00725         }
00726         i_len = __MIN( i_value_max - 1, i_len );
00727         if( i_len > 0 )
00728         {
00729             strncpy( psz_value, p, i_len );
00730             psz_value[i_len] = '\0';
00731         }
00732         else
00733         {
00734             strncpy( psz_value, "", i_value_max );
00735         }
00736         p += i_len;
00737     }
00738     else
00739     {
00740         strncpy( psz_value, "", i_value_max );
00741     }
00742 
00743     return p;
00744 }
00745 
00746 void E_(DecodeEncodedURI)( char *psz )
00747 {
00748     char *dup = strdup( psz );
00749     char *p = dup;
00750 
00751     while( *p )
00752     {
00753         if( *p == '%' )
00754         {
00755             char val[3];
00756             p++;
00757             if( !*p )
00758             {
00759                 break;
00760             }
00761 
00762             val[0] = *p++;
00763             val[1] = *p++;
00764             val[2] = '\0';
00765 
00766             *psz++ = strtol( val, NULL, 16 );
00767         }
00768         else if( *p == '+' )
00769         {
00770             *psz++ = ' ';
00771             p++;
00772         }
00773         else
00774         {
00775             *psz++ = *p++;
00776         }
00777     }
00778     *psz++ = '\0';
00779     free( dup );
00780 }
00781 
00782 /* Since the resulting string is smaller we can work in place, so it is
00783  * permitted to have psz == new. new points to the first word of the
00784  * string, the function returns the remaining string. */
00785 char *E_(FirstWord)( char *psz, char *new )
00786 {
00787     vlc_bool_t b_end;
00788 
00789     while( *psz == ' ' )
00790         psz++;
00791 
00792     while( *psz != '\0' && *psz != ' ' )
00793     {
00794         if( *psz == '\'' )
00795         {
00796             char c = *psz++;
00797             while( *psz != '\0' && *psz != c )
00798             {
00799                 if( *psz == '\\' && psz[1] != '\0' )
00800                     psz++;
00801                 *new++ = *psz++;
00802             }
00803             if( *psz == c )
00804                 psz++;
00805         }
00806         else
00807         {
00808             if( *psz == '\\' && psz[1] != '\0' )
00809                 psz++;
00810             *new++ = *psz++;
00811         }
00812     }
00813     b_end = !*psz;
00814 
00815     *new++ = '\0';
00816     if( !b_end )
00817         return psz + 1;
00818     else
00819         return NULL;
00820 }
00821 /**********************************************************************
00822  * Find_end_MRL: Find the end of the sentence :
00823  * this function parses the string psz and find the end of the item
00824  * and/or option with detecting the " and ' problems.
00825  * returns NULL if an error is detected, otherwise, returns a pointer
00826  * of the end of the sentence (after the last character)
00827 **********************************************************************/
00828 static char *Find_end_MRL( char *psz )
00829 {
00830     char *s_sent = psz;
00831 
00832     switch( *s_sent )
00833     {
00834         case '\"':
00835         {
00836             s_sent++;
00837 
00838             while( ( *s_sent != '\"' ) && ( *s_sent != '\0' ) )
00839             {
00840                 if( *s_sent == '\'' )
00841                 {
00842                     s_sent = Find_end_MRL( s_sent );
00843 
00844                     if( s_sent == NULL )
00845                     {
00846                         return NULL;
00847                     }
00848                 } else
00849                 {
00850                     s_sent++;
00851                 }
00852             }
00853 
00854             if( *s_sent == '\"' )
00855             {
00856                 s_sent++;
00857                 return s_sent;
00858             } else  /* *s_sent == '\0' , which means the number of " is incorrect */
00859             {
00860                 return NULL;
00861             }
00862             break;
00863         }
00864         case '\'':
00865         {
00866             s_sent++;
00867 
00868             while( ( *s_sent != '\'' ) && ( *s_sent != '\0' ) )
00869             {
00870                 if( *s_sent == '\"' )
00871                 {
00872                     s_sent = Find_end_MRL( s_sent );
00873 
00874                     if( s_sent == NULL )
00875                     {
00876                         return NULL;
00877                     }
00878                 } else
00879                 {
00880                     s_sent++;
00881                 }
00882             }
00883 
00884             if( *s_sent == '\'' )
00885             {
00886                 s_sent++;
00887                 return s_sent;
00888             } else  /* *s_sent == '\0' , which means the number of ' is incorrect */
00889             {
00890                 return NULL;
00891             }
00892             break;
00893         }
00894         default: /* now we can look for spaces */
00895         {
00896             while( ( *s_sent != ' ' ) && ( *s_sent != '\0' ) )
00897             {
00898                 if( ( *s_sent == '\'' ) || ( *s_sent == '\"' ) )
00899                 {
00900                     s_sent = Find_end_MRL( s_sent );
00901                 } else
00902                 {
00903                     s_sent++;
00904                 }
00905             }
00906             return s_sent;
00907         }
00908     }
00909 }
00910 /**********************************************************************
00911  * parse_MRL: parse the MRL, find the mrl string and the options,
00912  * create an item with all information in it, and return the item.
00913  * return NULL if there is an error.
00914  **********************************************************************/
00915 playlist_item_t *E_(MRLParse)( intf_thread_t *p_intf, char *psz,
00916                                    char *psz_name )
00917 {
00918     char **ppsz_options = NULL;
00919     char *mrl;
00920     char *s_mrl = psz;
00921     int i_error = 0;
00922     char *s_temp;
00923     int i = 0;
00924     int i_options = 0;
00925     playlist_item_t * p_item = NULL;
00926 
00927     /* In case there is spaces before the mrl */
00928     while( ( *s_mrl == ' ' ) && ( *s_mrl != '\0' ) )
00929     {
00930         s_mrl++;
00931     }
00932 
00933     /* extract the mrl */
00934     s_temp = strstr( s_mrl , " :" );
00935     if( s_temp == NULL )
00936     {
00937         s_temp = s_mrl + strlen( s_mrl );
00938     } else
00939     {
00940         while( (*s_temp == ' ') && (s_temp != s_mrl ) )
00941         {
00942             s_temp--;
00943         }
00944         s_temp++;
00945     }
00946 
00947     /* if the mrl is between " or ', we must remove them */
00948     if( (*s_mrl == '\'') || (*s_mrl == '\"') )
00949     {
00950         mrl = (char *)malloc( (s_temp - s_mrl - 1) * sizeof( char ) );
00951         strncpy( mrl , (s_mrl + 1) , s_temp - s_mrl - 2 );
00952         mrl[ s_temp - s_mrl - 2 ] = '\0';
00953     } else
00954     {
00955         mrl = (char *)malloc( (s_temp - s_mrl + 1) * sizeof( char ) );
00956         strncpy( mrl , s_mrl , s_temp - s_mrl );
00957         mrl[ s_temp - s_mrl ] = '\0';
00958     }
00959 
00960     s_mrl = s_temp;
00961 
00962     /* now we can take care of the options */
00963     while( (*s_mrl != '\0') && (i_error == 0) )
00964     {
00965         switch( *s_mrl )
00966         {
00967             case ' ':
00968             {
00969                 s_mrl++;
00970                 break;
00971             }
00972             case ':': /* an option */
00973             {
00974                 s_temp = Find_end_MRL( s_mrl );
00975 
00976                 if( s_temp == NULL )
00977                 {
00978                     i_error = 1;
00979                 }
00980                 else
00981                 {
00982                     i_options++;
00983                     ppsz_options = realloc( ppsz_options , i_options *
00984                                             sizeof(char *) );
00985                     ppsz_options[ i_options - 1 ] =
00986                         malloc( (s_temp - s_mrl + 1) * sizeof(char) );
00987 
00988                     strncpy( ppsz_options[ i_options - 1 ] , s_mrl ,
00989                              s_temp - s_mrl );
00990 
00991                     /* don't forget to finish the string with a '\0' */
00992                     (ppsz_options[ i_options - 1 ])[ s_temp - s_mrl ] = '\0';
00993 
00994                     s_mrl = s_temp;
00995                 }
00996                 break;
00997             }
00998             default:
00999             {
01000                 i_error = 1;
01001                 break;
01002             }
01003         }
01004     }
01005 
01006     if( i_error != 0 )
01007     {
01008         free( mrl );
01009     }
01010     else
01011     {
01012         /* now create an item */
01013         p_item = playlist_ItemNew( p_intf, mrl, psz_name );
01014         for( i = 0 ; i< i_options ; i++ )
01015         {
01016             playlist_ItemAddOption( p_item, ppsz_options[i] );
01017         }
01018     }
01019 
01020     for( i = 0; i < i_options; i++ ) free( ppsz_options[i] );
01021     if( i_options ) free( ppsz_options );
01022 
01023     return p_item;
01024 }
01025 /**********************************************************************
01026  * RealPath: parse ../, ~ and path stuff
01027  **********************************************************************/
01028 char *E_(RealPath)( intf_thread_t *p_intf, const char *psz_src )
01029 {
01030     char *psz_dir;
01031     char *p;
01032     int i_len = strlen(psz_src);
01033     char sep;
01034 
01035 #if defined( WIN32 )
01036     sep = '\\';
01037 #else
01038     sep = '/';
01039 #endif
01040 
01041     psz_dir = malloc( i_len + 2 );
01042     strcpy( psz_dir, psz_src );
01043 
01044     /* Add a trailing sep to ease the .. step */
01045     psz_dir[i_len] = sep;
01046     psz_dir[i_len + 1] = '\0';
01047 
01048 #ifdef WIN32
01049     /* Convert all / to native separator */
01050     p = psz_dir;
01051     while( (p = strchr( p, '/' )) != NULL )
01052     {
01053         *p = sep;
01054     }
01055 #endif
01056 
01057     /* Remove multiple separators and /./ */
01058     p = psz_dir;
01059     while( (p = strchr( p, sep )) != NULL )
01060     {
01061         if( p[1] == sep )
01062             memmove( &p[1], &p[2], strlen(&p[2]) + 1 );
01063         else if( p[1] == '.' && p[2] == sep )
01064             memmove( &p[1], &p[3], strlen(&p[3]) + 1 );
01065         else
01066             p++;
01067     }
01068 
01069     if( psz_dir[0] == '~' )
01070     {
01071         char *dir = malloc( strlen(psz_dir)
01072                              + strlen(p_intf->p_vlc->psz_userdir) );
01073         /* This is incomplete : we should also support the ~cmassiot/ syntax. */
01074         sprintf( dir, "%s%s", p_intf->p_vlc->psz_userdir, psz_dir + 1 );
01075         free( psz_dir );
01076         psz_dir = dir;
01077     }
01078 
01079     if( strlen(psz_dir) > 2 )
01080     {
01081         /* Fix all .. dir */
01082         p = psz_dir + 3;
01083         while( (p = strchr( p, sep )) != NULL )
01084         {
01085             if( p[-1] == '.' && p[-2] == '.' && p[-3] == sep )
01086             {
01087                 char *q;
01088                 p[-3] = '\0';
01089                 if( (q = strrchr( psz_dir, sep )) != NULL )
01090                 {
01091                     memmove( q + 1, p + 1, strlen(p + 1) + 1 );
01092                     p = q + 1;
01093                 }
01094                 else
01095                 {
01096                     memmove( psz_dir, p, strlen(p) + 1 );
01097                     p = psz_dir + 3;
01098                 }
01099             }
01100             else
01101                 p++;
01102         }
01103     }
01104 
01105     /* Remove trailing sep if there are at least 2 sep in the string
01106      * (handles the C:\ stuff) */
01107     p = strrchr( psz_dir, sep );
01108     if( p != NULL && p[1] == '\0' && p != strchr( psz_dir, sep ) )
01109         *p = '\0';
01110 
01111     return psz_dir;
01112 }

Generated on Tue Dec 20 10:14:31 2005 for vlc-0.8.4a by  doxygen 1.4.2