mvar.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:18k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mvar.c : Variables handling for the HTTP Interface
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2007 the VideoLAN team
  5.  * $Id: c25dd34d29cd6b2c9ae17b55d7003ffdcafd4a27 $
  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. #ifdef HAVE_CONFIG_H
  26. # include "config.h"
  27. #endif
  28. #include "http.h"
  29. #include <limits.h>
  30. #include <assert.h>
  31. /* Utility function for scandir */
  32. static int Filter( const char *foo )
  33. {
  34.     return strcmp( foo, "." );
  35. };
  36. static int InsensitiveAlphasort( const char **foo1,
  37.                                  const char **foo2 )
  38. {
  39.     return strcasecmp( *foo1, *foo2 );
  40. };
  41. mvar_t *mvar_New( const char *name, const char *value )
  42. {
  43.     mvar_t *v = malloc( sizeof( mvar_t ) );
  44.     if( !v ) return NULL;
  45.     v->name = strdup( name );
  46.     v->value = strdup( value ? value : "" );
  47.     v->i_field = 0;
  48.     v->field = malloc( sizeof( mvar_t * ) );
  49.     v->field[0] = NULL;
  50.     return v;
  51. }
  52. void mvar_Delete( mvar_t *v )
  53. {
  54.     int i;
  55.     free( v->name );
  56.     free( v->value );
  57.     for( i = 0; i < v->i_field; i++ )
  58.     {
  59.         mvar_Delete( v->field[i] );
  60.     }
  61.     free( v->field );
  62.     free( v );
  63. }
  64. void mvar_AppendVar( mvar_t *v, mvar_t *f )
  65. {
  66.     v->field = realloc( v->field, sizeof( mvar_t * ) * ( v->i_field + 2 ) );
  67.     v->field[v->i_field] = f;
  68.     v->i_field++;
  69. }
  70. mvar_t *mvar_Duplicate( const mvar_t *v )
  71. {
  72.     int i;
  73.     mvar_t *n;
  74.     n = mvar_New( v->name, v->value );
  75.     for( i = 0; i < v->i_field; i++ )
  76.     {
  77.         mvar_AppendVar( n, mvar_Duplicate( v->field[i] ) );
  78.     }
  79.     return n;
  80. }
  81. void mvar_PushVar( mvar_t *v, mvar_t *f )
  82. {
  83.     v->field = realloc( v->field, sizeof( mvar_t * ) * ( v->i_field + 2 ) );
  84.     if( v->i_field > 0 )
  85.     {
  86.         memmove( &v->field[1], &v->field[0], sizeof( mvar_t * ) * v->i_field );
  87.     }
  88.     v->field[0] = f;
  89.     v->i_field++;
  90. }
  91. void mvar_RemoveVar( mvar_t *v, mvar_t *f )
  92. {
  93.     int i;
  94.     for( i = 0; i < v->i_field; i++ )
  95.     {
  96.         if( v->field[i] == f )
  97.         {
  98.             break;
  99.         }
  100.     }
  101.     if( i >= v->i_field )
  102.     {
  103.         return;
  104.     }
  105.     if( i + 1 < v->i_field )
  106.     {
  107.         memmove( &v->field[i], &v->field[i+1], sizeof( mvar_t * ) * ( v->i_field - i - 1 ) );
  108.     }
  109.     v->i_field--;
  110.     /* FIXME should do a realloc */
  111. }
  112. mvar_t *mvar_GetVar( mvar_t *s, const char *name )
  113. {
  114.     /* format: name[index].field */
  115.     const char *field = strchr( name, '.' );
  116.     char base[1 + (field ? (size_t)(field - name) : strlen( name ))];
  117.     char *p;
  118.     int i_index, i;
  119.     strlcpy( base, name, sizeof (base) );
  120.     if( field != NULL )
  121.         field++;
  122.     if( ( p = strchr( base, '[' ) ) != NULL )
  123.     {
  124.         char *end;
  125.         unsigned long l = strtoul( p, &end, 0 );
  126.         if( ( l > INT_MAX ) || strcmp( "]", end ) )
  127.             return NULL;
  128.         *p++ = '';
  129.         i_index = (int)l;
  130.     }
  131.     else
  132.     {
  133.         i_index = 0;
  134.     }
  135.     for( i = 0; i < s->i_field; i++ )
  136.     {
  137.         if( !strcmp( s->field[i]->name, base ) )
  138.         {
  139.             if( i_index > 0 )
  140.             {
  141.                 i_index--;
  142.             }
  143.             else
  144.             {
  145.                 if( field )
  146.                 {
  147.                     return mvar_GetVar( s->field[i], field );
  148.                 }
  149.                 else
  150.                 {
  151.                     return s->field[i];
  152.                 }
  153.             }
  154.         }
  155.     }
  156.     return NULL;
  157. }
  158. const char *mvar_GetValue( mvar_t *v, const char *field )
  159. {
  160.     if( *field == '' )
  161.     {
  162.         return v->value;
  163.     }
  164.     else
  165.     {
  166.         mvar_t *f = mvar_GetVar( v, field );
  167.         if( f )
  168.         {
  169.             return f->value;
  170.         }
  171.         else
  172.         {
  173.             return field;
  174.         }
  175.     }
  176. }
  177. void mvar_PushNewVar( mvar_t *vars, const char *name,
  178.                           const char *value )
  179. {
  180.     mvar_t *f = mvar_New( name, value );
  181.     mvar_PushVar( vars, f );
  182. }
  183. void mvar_AppendNewVar( mvar_t *vars, const char *name,
  184.                             const char *value )
  185. {
  186.     mvar_t *f = mvar_New( name, value );
  187.     mvar_AppendVar( vars, f );
  188. }
  189. /* arg= start[:stop[:step]],.. */
  190. mvar_t *mvar_IntegerSetNew( const char *name, const char *arg )
  191. {
  192.     char *dup = strdup( arg );
  193.     char *str = dup;
  194.     mvar_t *s = mvar_New( name, "set" );
  195.     while( str )
  196.     {
  197.         char *p;
  198.         int  i_start,i_stop,i_step;
  199.         int  i_match;
  200.         p = strchr( str, ',' );
  201.         if( p )
  202.         {
  203.             *p++ = '';
  204.         }
  205.         i_step = 0;
  206.         i_match = sscanf( str, "%d:%d:%d", &i_start, &i_stop, &i_step );
  207.         if( i_match == 1 )
  208.         {
  209.             i_stop = i_start;
  210.             i_step = 1;
  211.         }
  212.         else if( i_match == 2 )
  213.         {
  214.             i_step = i_start < i_stop ? 1 : -1;
  215.         }
  216.         if( i_match >= 1 )
  217.         {
  218.             int i;
  219.             if( ( i_start <= i_stop && i_step > 0 ) ||
  220.                 ( i_start >= i_stop && i_step < 0 ) )
  221.             {
  222.                 for( i = i_start; ; i += i_step )
  223.                 {
  224.                     char   value[79];
  225.                     if( ( i_step > 0 && i > i_stop ) ||
  226.                         ( i_step < 0 && i < i_stop ) )
  227.                     {
  228.                         break;
  229.                     }
  230.                     sprintf( value, "%d", i );
  231.                     mvar_PushNewVar( s, name, value );
  232.                 }
  233.             }
  234.         }
  235.         str = p;
  236.     }
  237.     free( dup );
  238.     return s;
  239. }
  240. /********************************************************************
  241.  * Special sets handling
  242.  ********************************************************************/
  243. mvar_t *mvar_PlaylistSetNew( intf_thread_t *p_intf, char *name,
  244.                                  playlist_t *p_pl )
  245. {
  246.     mvar_t *s = mvar_New( name, "set" );
  247.     playlist_Lock( p_pl );
  248.     PlaylistListNode( p_intf, p_pl, p_pl->p_root_category , name, s, 0 );
  249.     playlist_Unlock( p_pl );
  250.     return s;
  251. }
  252. mvar_t *mvar_InfoSetNew( char *name, input_thread_t *p_input )
  253. {
  254.     mvar_t *s = mvar_New( name, "set" );
  255.     int i, j;
  256.     if( p_input == NULL || p_input->p == NULL /* workarround assert in input_GetItem */ )
  257.     {
  258.         return s;
  259.     }
  260.     vlc_mutex_lock( &input_GetItem(p_input)->lock );
  261.     for ( i = 0; i < input_GetItem(p_input)->i_categories; i++ )
  262.     {
  263.         info_category_t *p_category = input_GetItem(p_input)->pp_categories[i];
  264.         mvar_t *cat  = mvar_New( name, "set" );
  265.         mvar_t *iset = mvar_New( "info", "set" );
  266.         mvar_AppendNewVar( cat, "name", p_category->psz_name );
  267.         mvar_AppendVar( cat, iset );
  268.         for ( j = 0; j < p_category->i_infos; j++ )
  269.         {
  270.             info_t *p_info = p_category->pp_infos[j];
  271.             mvar_t *info = mvar_New( "info", "" );
  272.             /* msg_Dbg( p_input, "adding info name=%s value=%s",
  273.                      psz_name, psz_value ); */
  274.             mvar_AppendNewVar( info, "name",  p_info->psz_name );
  275.             mvar_AppendNewVar( info, "value", p_info->psz_value );
  276.             mvar_AppendVar( iset, info );
  277.         }
  278.         mvar_AppendVar( s, cat );
  279.     }
  280.     vlc_mutex_unlock( &input_GetItem(p_input)->lock );
  281.     return s;
  282. }
  283. mvar_t *mvar_ObjectSetNew( intf_thread_t *p_intf, char *psz_name,
  284.                                const char *psz_capability )
  285. {
  286.     mvar_t *s = mvar_New( psz_name, "set" );
  287.     size_t i;
  288.     module_t **p_list = module_list_get( NULL );
  289.     for( i = 0; p_list[i]; i++ )
  290.     {
  291.         module_t *p_parser = p_list[i];
  292.         if( module_provides( p_parser, psz_capability ) )
  293.         {
  294.             mvar_t *sd = mvar_New( "sd", module_get_object( p_parser ) );
  295.             mvar_AppendNewVar( sd, "name",
  296.                                    module_get_name( p_parser, true ) );
  297.             mvar_AppendVar( s, sd );
  298.         }
  299.     }
  300.     module_list_free( p_list );
  301.     return s;
  302. }
  303. mvar_t *mvar_InputVarSetNew( intf_thread_t *p_intf, char *name,
  304.                                  input_thread_t *p_input,
  305.                                  const char *psz_variable )
  306. {
  307.     intf_sys_t     *p_sys = p_intf->p_sys;
  308.     mvar_t *s = mvar_New( name, "set" );
  309.     vlc_value_t val, val_list, text_list;
  310.     int i_type, i;
  311.     if( p_input == NULL )
  312.     {
  313.         return s;
  314.     }
  315.     /* Check the type of the object variable */
  316.     i_type = var_Type( p_sys->p_input, psz_variable );
  317.     /* Make sure we want to display the variable */
  318.     if( i_type & VLC_VAR_HASCHOICE )
  319.     {
  320.         var_Change( p_sys->p_input, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
  321.         if( val.i_int == 0 ) return s;
  322.         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
  323.             return s;
  324.     }
  325.     else
  326.     {
  327.         return s;
  328.     }
  329.     switch( i_type & VLC_VAR_TYPE )
  330.     {
  331.     case VLC_VAR_VOID:
  332.     case VLC_VAR_BOOL:
  333.     case VLC_VAR_VARIABLE:
  334.     case VLC_VAR_STRING:
  335.     case VLC_VAR_INTEGER:
  336.         break;
  337.     default:
  338.         /* Variable doesn't exist or isn't handled */
  339.         return s;
  340.     }
  341.     if( var_Get( p_sys->p_input, psz_variable, &val ) < 0 )
  342.     {
  343.         return s;
  344.     }
  345.     if( var_Change( p_sys->p_input, psz_variable, VLC_VAR_GETLIST,
  346.                     &val_list, &text_list ) < 0 )
  347.     {
  348.         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
  349.         return s;
  350.     }
  351.     for( i = 0; i < val_list.p_list->i_count; i++ )
  352.     {
  353.         char psz_int[16];
  354.         mvar_t *itm;
  355.         switch( i_type & VLC_VAR_TYPE )
  356.         {
  357.         case VLC_VAR_STRING:
  358.             itm = mvar_New( name, "set" );
  359.             mvar_AppendNewVar( itm, "name", text_list.p_list->p_values[i].psz_string );
  360.             mvar_AppendNewVar( itm, "id", val_list.p_list->p_values[i].psz_string );
  361.             snprintf( psz_int, sizeof(psz_int), "%d",
  362.                       ( !strcmp( val.psz_string,
  363.                                    val_list.p_list->p_values[i].psz_string )
  364.                            && !( i_type & VLC_VAR_ISCOMMAND ) ) );
  365.             mvar_AppendNewVar( itm, "selected", psz_int );
  366.             mvar_AppendVar( s, itm );
  367.             break;
  368.         case VLC_VAR_INTEGER:
  369.             itm = mvar_New( name, "set" );
  370.             mvar_AppendNewVar( itm, "name", text_list.p_list->p_values[i].psz_string );
  371.             snprintf( psz_int, sizeof(psz_int), "%d",
  372.                       val_list.p_list->p_values[i].i_int );
  373.             mvar_AppendNewVar( itm, "id", psz_int );
  374.             snprintf( psz_int, sizeof(psz_int), "%d",
  375.                       ( val.i_int == val_list.p_list->p_values[i].i_int )
  376.                          && !( i_type & VLC_VAR_ISCOMMAND ) );
  377.             mvar_AppendNewVar( itm, "selected", psz_int );
  378.             mvar_AppendVar( s, itm );
  379.             break;
  380.         default:
  381.             break;
  382.         }
  383.     }
  384.     /* clean up everything */
  385.     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
  386.     var_Change( p_sys->p_input, psz_variable, VLC_VAR_FREELIST, &val_list,
  387.                 &text_list );
  388.     return s;
  389. }
  390. #if 0
  391. mvar_t *mvar_HttpdInfoSetNew( char *name, httpd_t *p_httpd, int i_type )
  392. {
  393.     mvar_t       *s = mvar_New( name, "set" );
  394.     httpd_info_t info;
  395.     int          i;
  396.     if( !p_httpd->pf_control( p_httpd, i_type, &info, NULL ) )
  397.     {
  398.         for( i= 0; i < info.i_count; )
  399.         {
  400.             mvar_t *inf;
  401.             inf = mvar_New( name, "set" );
  402.             do
  403.             {
  404.                 /* fprintf( stderr," mvar_HttpdInfoSetNew: append name=`%s' value=`%s'n",
  405.                             info.info[i].psz_name, info.info[i].psz_value ); */
  406.                 mvar_AppendNewVar( inf,
  407.                                    info.info[i].psz_name,
  408.                                    info.info[i].psz_value );
  409.                 i++;
  410.             } while( i < info.i_count && strcmp( info.info[i].psz_name, "id" ) );
  411.             mvar_AppendVar( s, inf );
  412.         }
  413.     }
  414.     /* free mem */
  415.     for( i = 0; i < info.i_count; i++ )
  416.     {
  417.         free( info.info[i].psz_name );
  418.         free( info.info[i].psz_value );
  419.     }
  420.     if( info.i_count > 0 )
  421.     {
  422.         free( info.info );
  423.     }
  424.     return s;
  425. }
  426. #endif
  427. mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name,
  428.                              char *psz_dir )
  429. {
  430.     mvar_t *s = mvar_New( name, "set" );
  431.     char        **ppsz_dir_content;
  432.     int           i_dir_content, i;
  433.     psz_dir = RealPath( psz_dir );
  434.     /* parse psz_src dir */
  435.     if( ( i_dir_content = utf8_scandir( psz_dir, &ppsz_dir_content, Filter,
  436.                                         InsensitiveAlphasort ) ) == -1 )
  437.     {
  438.         if( errno != ENOENT && errno != ENOTDIR )
  439.             msg_Warn( p_intf, "error while scanning dir %s (%m)", psz_dir );
  440.         free( psz_dir );
  441.         return s;
  442.     }
  443.     for( i = 0; i < i_dir_content; i++ )
  444.     {
  445. #ifdef HAVE_SYS_STAT_H
  446.         struct stat stat_info;
  447. #endif
  448.         char *psz_name = ppsz_dir_content[i], *psz_ext, *psz_dummy;
  449.         char psz_tmp[strlen( psz_dir ) + 1 + strlen( psz_name ) + 1];
  450.         mvar_t *f;
  451. #if defined( WIN32 )
  452.         if( psz_dir[0] == '' || (psz_dir[0] == '\' && psz_dir[1] == '') )
  453.         {
  454.             strcpy( psz_tmp, psz_name );
  455.         }
  456.         else
  457. #endif
  458.         {
  459.             sprintf( psz_tmp, "%s"DIR_SEP"%s", psz_dir, psz_name );
  460. #ifdef HAVE_SYS_STAT_H
  461.             if( utf8_stat( psz_tmp, &stat_info ) == -1 )
  462.             {
  463.                 free( psz_name );
  464.                 continue;
  465.             }
  466. #endif
  467.         }
  468.         f = mvar_New( name, "set" );
  469.         /* put lower-case file extension in 'ext' */
  470.         psz_ext = strrchr( psz_name, '.' );
  471.         psz_ext = strdup( psz_ext != NULL ? psz_ext + 1 : "" );
  472.         for( psz_dummy = psz_ext; *psz_dummy != ''; psz_dummy++ )
  473.             *psz_dummy = tolower( *psz_dummy );
  474.         mvar_AppendNewVar( f, "ext", psz_ext );
  475.         free( psz_ext );
  476. #if defined( WIN32 )
  477.         if( psz_dir[0] == '' || (psz_dir[0] == '\' && psz_dir[1] == '') )
  478.         {
  479.             char psz_tmp[3];
  480.             sprintf( psz_tmp, "%c:", psz_name[0] );
  481.             mvar_AppendNewVar( f, "name", psz_name );
  482.             mvar_AppendNewVar( f, "basename", psz_tmp );
  483.             mvar_AppendNewVar( f, "type", "directory" );
  484.             mvar_AppendNewVar( f, "size", "unknown" );
  485.             mvar_AppendNewVar( f, "date", "unknown" );
  486.         }
  487.         else
  488. #endif
  489.         {
  490.             char psz_buf[26];
  491.             char psz_tmp[strlen( psz_dir ) + 1 + strlen( psz_name ) + 1];
  492.             sprintf( psz_tmp, "%s"DIR_SEP"%s", psz_dir, psz_name );
  493.             mvar_AppendNewVar( f, "name", psz_tmp );
  494.             mvar_AppendNewVar( f, "basename", psz_name );
  495. #ifdef HAVE_SYS_STAT_H
  496.             if( S_ISDIR( stat_info.st_mode ) )
  497.             {
  498.                 mvar_AppendNewVar( f, "type", "directory" );
  499.             }
  500.             else if( S_ISREG( stat_info.st_mode ) )
  501.             {
  502.                 mvar_AppendNewVar( f, "type", "file" );
  503.             }
  504.             else
  505.             {
  506.                 mvar_AppendNewVar( f, "type", "unknown" );
  507.             }
  508.             snprintf( psz_buf, sizeof( psz_buf ), "%"PRId64,
  509.                       (int64_t)stat_info.st_size );
  510.             mvar_AppendNewVar( f, "size", psz_buf );
  511.             /* FIXME memory leak FIXME */
  512. #   ifdef HAVE_CTIME_R
  513.             ctime_r( &stat_info.st_mtime, psz_buf );
  514.             mvar_AppendNewVar( f, "date", psz_buf );
  515. #   else
  516.             mvar_AppendNewVar( f, "date", ctime( &stat_info.st_mtime ) );
  517. #   endif
  518. #else
  519.             mvar_AppendNewVar( f, "type", "unknown" );
  520.             mvar_AppendNewVar( f, "size", "unknown" );
  521.             mvar_AppendNewVar( f, "date", "unknown" );
  522. #endif
  523.         }
  524.         mvar_AppendVar( s, f );
  525.         free( psz_name );
  526.     }
  527.     free( psz_dir );
  528.     free( ppsz_dir_content );
  529.     return s;
  530. }
  531. static void mvar_VlmSetNewLoop( char *name, vlm_t *vlm, mvar_t *s,
  532.                                 vlm_message_t *el, bool b_name )
  533. {
  534.     /* Over name */
  535.     mvar_t        *set;
  536.     int k;
  537.     /* Add a node with name and info */
  538.     set = mvar_New( name, "set" );
  539.     if( b_name == true )
  540.     {
  541.         mvar_AppendNewVar( set, "name", el->psz_name );
  542.     }
  543.     for( k = 0; k < el->i_child; k++ )
  544.     {
  545.         vlm_message_t *ch = el->child[k];
  546.         if( ch->i_child > 0 )
  547.         {
  548.             mvar_VlmSetNewLoop( ch->psz_name, vlm, set, ch, false );
  549.         }
  550.         else
  551.         {
  552.             if( ch->psz_value )
  553.             {
  554.                 mvar_AppendNewVar( set, ch->psz_name, ch->psz_value );
  555.             }
  556.             else
  557.             {
  558.                 mvar_AppendNewVar( set, el->psz_name, ch->psz_name );
  559.             }
  560.         }
  561.     }
  562.     mvar_AppendVar( s, set );
  563. }
  564. mvar_t *mvar_VlmSetNew( char *name, vlm_t *vlm )
  565. {
  566.     mvar_t        *s = mvar_New( name, "set" );
  567. #ifdef ENABLE_VLM
  568.     vlm_message_t *msg;
  569.     int    i;
  570.     if( vlm == NULL ) return s;
  571.     if( vlm_ExecuteCommand( vlm, "show", &msg ) )
  572.         return s;
  573.     for( i = 0; i < msg->i_child; i++ )
  574.     {
  575.         /* Over media, schedule */
  576.         vlm_message_t *ch = msg->child[i];
  577.         int j;
  578.         for( j = 0; j < ch->i_child; j++ )
  579.         {
  580.             /* Over name */
  581.             vlm_message_t *el = ch->child[j];
  582.             vlm_message_t *inf, *desc;
  583.             char          psz[6 + strlen(el->psz_name)];
  584.             sprintf( psz, "show %s", el->psz_name );
  585.             if( vlm_ExecuteCommand( vlm, psz, &inf ) )
  586.                 continue;
  587.             desc = inf->child[0];
  588.             mvar_VlmSetNewLoop( el->psz_name, vlm, s, desc, true );
  589.             vlm_MessageDelete( inf );
  590.         }
  591.     }
  592.     vlm_MessageDelete( msg );
  593. #endif /* ENABLE_VLM */
  594.     return s;
  595. }