]> git.sesse.net Git - vlc/blob - modules/control/http/rpn.c
Input access locking, part 3 (final).
[vlc] / modules / control / http / rpn.c
1 /*****************************************************************************
2  * rpn.c : RPN evaluator for the HTTP Interface
3  *****************************************************************************
4  * Copyright (C) 2001-2006 the VideoLAN team
5  * $Id$
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 #include "http.h"
27 #include "vlc_url.h"
28 #include "vlc_meta.h"
29 #include "vlc_strings.h"
30
31 static vlc_object_t *GetVLCObject( intf_thread_t *p_intf,
32                                    const char *psz_object,
33                                    vlc_bool_t *pb_need_release )
34 {
35     intf_sys_t    *p_sys = p_intf->p_sys;
36     int i_object_type = 0;
37     vlc_object_t *p_object = NULL;
38     *pb_need_release = VLC_FALSE;
39
40     if( !strcmp( psz_object, "VLC_OBJECT_LIBVLC" ) )
41         p_object = VLC_OBJECT(p_intf->p_libvlc);
42     else if( !strcmp( psz_object, "VLC_OBJECT_INTF" ) )
43         p_object = VLC_OBJECT(p_intf);
44     else if( !strcmp( psz_object, "VLC_OBJECT_PLAYLIST" ) )
45         p_object = VLC_OBJECT(p_sys->p_playlist);
46     else if( !strcmp( psz_object, "VLC_OBJECT_INPUT" ) )
47         p_object = VLC_OBJECT(p_sys->p_input);
48     else if( !strcmp( psz_object, "VLC_OBJECT_VOUT" ) )
49         i_object_type = VLC_OBJECT_VOUT;
50     else if( !strcmp( psz_object, "VLC_OBJECT_AOUT" ) )
51         i_object_type = VLC_OBJECT_AOUT;
52     else if( !strcmp( psz_object, "VLC_OBJECT_SOUT" ) )
53         i_object_type = VLC_OBJECT_SOUT;
54     else
55         msg_Warn( p_intf, "unknown object type (%s)", psz_object );
56
57     if( p_object == NULL && i_object_type )
58     {
59         *pb_need_release = VLC_TRUE;
60         p_object = vlc_object_find( p_intf, i_object_type, FIND_ANYWHERE );
61     }
62
63     return p_object;
64 }
65
66 void E_(SSInit)( rpn_stack_t *st )
67 {
68     st->i_stack = 0;
69 }
70
71 void E_(SSClean)( rpn_stack_t *st )
72 {
73     while( st->i_stack > 0 )
74     {
75         free( st->stack[--st->i_stack] );
76     }
77 }
78
79 void E_(SSPush)( rpn_stack_t *st, const char *s )
80 {
81     if( st->i_stack < STACK_MAX )
82     {
83         st->stack[st->i_stack++] = strdup( s );
84     }
85 }
86
87 char *E_(SSPop)( rpn_stack_t *st )
88 {
89     if( st->i_stack <= 0 )
90     {
91         return strdup( "" );
92     }
93     else
94     {
95         return st->stack[--st->i_stack];
96     }
97 }
98
99 int E_(SSPopN)( rpn_stack_t *st, mvar_t  *vars )
100 {
101     char *name;
102     char *value;
103
104     char *end;
105     int  i;
106
107     name = E_(SSPop)( st );
108     i = strtol( name, &end, 0 );
109     if( end == name )
110     {
111         value = E_(mvar_GetValue)( vars, name );
112         i = atoi( value );
113     }
114     free( name );
115
116     return( i );
117 }
118
119 void E_(SSPushN)( rpn_stack_t *st, int i )
120 {
121     char v[12];
122
123     snprintf( v, sizeof (v), "%d", i );
124     E_(SSPush)( st, v );
125 }
126
127 void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t  *vars,
128                       rpn_stack_t *st, char *exp )
129 {
130     intf_sys_t    *p_sys = p_intf->p_sys;
131
132     while( exp != NULL && *exp != '\0' )
133     {
134         char *p, *s;
135
136         /* skip space */
137         while( *exp == ' ' )
138         {
139             exp++;
140         }
141
142         if( *exp == '\'' )
143         {
144             /* extract string */
145             p = E_(FirstWord)( exp, exp );
146             E_(SSPush)( st, exp );
147             exp = p;
148             continue;
149         }
150
151         /* extract token */
152         p = E_(FirstWord)( exp, exp );
153         s = exp;
154         if( p == NULL )
155         {
156             exp += strlen( exp );
157         }
158         else
159         {
160             exp = p;
161         }
162
163         if( *s == '\0' )
164         {
165             break;
166         }
167
168         /* 1. Integer function */
169         if( !strcmp( s, "!" ) )
170         {
171             E_(SSPushN)( st, ~E_(SSPopN)( st, vars ) );
172         }
173         else if( !strcmp( s, "^" ) )
174         {
175             E_(SSPushN)( st, E_(SSPopN)( st, vars ) ^ E_(SSPopN)( st, vars ) );
176         }
177         else if( !strcmp( s, "&" ) )
178         {
179             E_(SSPushN)( st, E_(SSPopN)( st, vars ) & E_(SSPopN)( st, vars ) );
180         }
181         else if( !strcmp( s, "|" ) )
182         {
183             E_(SSPushN)( st, E_(SSPopN)( st, vars ) | E_(SSPopN)( st, vars ) );
184         }
185         else if( !strcmp( s, "+" ) )
186         {
187             E_(SSPushN)( st, E_(SSPopN)( st, vars ) + E_(SSPopN)( st, vars ) );
188         }
189         else if( !strcmp( s, "-" ) )
190         {
191             int j = E_(SSPopN)( st, vars );
192             int i = E_(SSPopN)( st, vars );
193             E_(SSPushN)( st, i - j );
194         }
195         else if( !strcmp( s, "*" ) )
196         {
197             E_(SSPushN)( st, E_(SSPopN)( st, vars ) * E_(SSPopN)( st, vars ) );
198         }
199         else if( !strcmp( s, "/" ) )
200         {
201             int i, j;
202
203             j = E_(SSPopN)( st, vars );
204             i = E_(SSPopN)( st, vars );
205
206             E_(SSPushN)( st, j != 0 ? i / j : 0 );
207         }
208         else if( !strcmp( s, "%" ) )
209         {
210             int i, j;
211
212             j = E_(SSPopN)( st, vars );
213             i = E_(SSPopN)( st, vars );
214
215             E_(SSPushN)( st, j != 0 ? i % j : 0 );
216         }
217         /* 2. integer tests */
218         else if( !strcmp( s, "=" ) )
219         {
220             E_(SSPushN)( st, E_(SSPopN)( st, vars ) == E_(SSPopN)( st, vars ) ? -1 : 0 );
221         }
222         else if( !strcmp( s, "!=" ) )
223         {
224             E_(SSPushN)( st, E_(SSPopN)( st, vars ) != E_(SSPopN)( st, vars ) ? -1 : 0 );
225         }
226         else if( !strcmp( s, "<" ) )
227         {
228             int j = E_(SSPopN)( st, vars );
229             int i = E_(SSPopN)( st, vars );
230
231             E_(SSPushN)( st, i < j ? -1 : 0 );
232         }
233         else if( !strcmp( s, ">" ) )
234         {
235             int j = E_(SSPopN)( st, vars );
236             int i = E_(SSPopN)( st, vars );
237
238             E_(SSPushN)( st, i > j ? -1 : 0 );
239         }
240         else if( !strcmp( s, "<=" ) )
241         {
242             int j = E_(SSPopN)( st, vars );
243             int i = E_(SSPopN)( st, vars );
244
245             E_(SSPushN)( st, i <= j ? -1 : 0 );
246         }
247         else if( !strcmp( s, ">=" ) )
248         {
249             int j = E_(SSPopN)( st, vars );
250             int i = E_(SSPopN)( st, vars );
251
252             E_(SSPushN)( st, i >= j ? -1 : 0 );
253         }
254         /* 3. string functions */
255         else if( !strcmp( s, "strcat" ) )
256         {
257             char *s2 = E_(SSPop)( st );
258             char *s1 = E_(SSPop)( st );
259             char *str = malloc( strlen( s1 ) + strlen( s2 ) + 1 );
260
261             strcpy( str, s1 );
262             strcat( str, s2 );
263
264             E_(SSPush)( st, str );
265             free( s1 );
266             free( s2 );
267             free( str );
268         }
269         else if( !strcmp( s, "strcmp" ) )
270         {
271             char *s2 = E_(SSPop)( st );
272             char *s1 = E_(SSPop)( st );
273
274             E_(SSPushN)( st, strcmp( s1, s2 ) );
275             free( s1 );
276             free( s2 );
277         }
278         else if( !strcmp( s, "strncmp" ) )
279         {
280             int n = E_(SSPopN)( st, vars );
281             char *s2 = E_(SSPop)( st );
282             char *s1 = E_(SSPop)( st );
283
284             E_(SSPushN)( st, strncmp( s1, s2 , n ) );
285             free( s1 );
286             free( s2 );
287         }
288         else if( !strcmp( s, "strsub" ) )
289         {
290             int n = E_(SSPopN)( st, vars );
291             int m = E_(SSPopN)( st, vars );
292             int i_len;
293             char *s = E_(SSPop)( st );
294             char *str;
295
296             if( n >= m )
297             {
298                 i_len = n - m + 1;
299             }
300             else
301             {
302                 i_len = 0;
303             }
304
305             str = malloc( i_len + 1 );
306
307             memcpy( str, s + m - 1, i_len );
308             str[ i_len ] = '\0';
309
310             E_(SSPush)( st, str );
311             free( s );
312             free( str );
313         }
314         else if( !strcmp( s, "strlen" ) )
315         {
316             char *str = E_(SSPop)( st );
317
318             E_(SSPushN)( st, strlen( str ) );
319             free( str );
320         }
321         else if( !strcmp( s, "str_replace" ) )
322         {
323             char *psz_to = E_(SSPop)( st );
324             char *psz_from = E_(SSPop)( st );
325             char *psz_in = E_(SSPop)( st );
326             char *psz_in_current = psz_in;
327             char *psz_out = malloc( strlen(psz_in) * strlen(psz_to) + 1 );
328             char *psz_out_current = psz_out;
329
330             while( (p = strstr( psz_in_current, psz_from )) != NULL )
331             {
332                 memcpy( psz_out_current, psz_in_current, p - psz_in_current );
333                 psz_out_current += p - psz_in_current;
334                 strcpy( psz_out_current, psz_to );
335                 psz_out_current += strlen(psz_to);
336                 psz_in_current = p + strlen(psz_from);
337             }
338             strcpy( psz_out_current, psz_in_current );
339             psz_out_current += strlen(psz_in_current);
340             *psz_out_current = '\0';
341
342             E_(SSPush)( st, psz_out );
343             free( psz_to );
344             free( psz_from );
345             free( psz_in );
346             free( psz_out );
347         }
348         else if( !strcmp( s, "url_extract" ) )
349         {
350             char *url = E_(mvar_GetValue)( vars, "url_value" );
351             char *name = E_(SSPop)( st );
352             char *value = E_(ExtractURIString)( url, name );
353             if( value != NULL )
354             {
355                 char *tmp;
356                 decode_URI( value );
357                 tmp = E_(FromUTF8)( p_intf, value );
358                 E_(SSPush)( st, tmp );
359                 free( tmp );
360                 free( value );
361             }
362             else
363                 E_(SSPush)( st, "" );
364
365             free( name );
366         }
367         else if( !strcmp( s, "url_encode" ) )
368         {
369             char *url = E_(SSPop)( st );
370             char *value;
371
372             value = E_(ToUTF8)( p_intf, url );
373             free( url );
374             url = value;
375             value = vlc_UrlEncode( url );
376             free( url );
377             E_(SSPush)( st, value );
378             free( value );
379         }
380         else if( !strcmp( s, "addslashes" ) )
381         {
382             char *psz_src = E_(SSPop)( st );
383             char *psz_dest;
384             char *str = psz_src;
385
386             p = psz_dest = malloc( strlen( str ) * 2 + 1 );
387
388             while( *str != '\0' )
389             {
390                 if( *str == '"' || *str == '\'' || *str == '\\' )
391                 {
392                     *p++ = '\\';
393                 }
394                 *p++ = *str;
395                 str++;
396             }
397             *p = '\0';
398
399             E_(SSPush)( st, psz_dest );
400             free( psz_src );
401             free( psz_dest );
402         }
403         else if( !strcmp( s, "stripslashes" ) )
404         {
405             char *psz_src = E_(SSPop)( st );
406             char *psz_dest;
407             char *str = psz_src;
408
409             p = psz_dest = strdup( psz_src );
410
411             while( *str )
412             {
413                 if( *str == '\\' && *(str + 1) )
414                 {
415                     str++;
416                 }
417                 *p++ = *str++;
418             }
419             *p = '\0';
420
421             E_(SSPush)( st, psz_dest );
422             free( psz_src );
423             free( psz_dest );
424         }
425         else if( !strcmp( s, "htmlspecialchars" ) )
426         {
427             char *psz_src = E_(SSPop)( st );
428             char *psz_dest;
429
430             psz_dest = convert_xml_special_chars( psz_src );
431
432             E_(SSPush)( st, psz_dest );
433             free( psz_src );
434             free( psz_dest );
435         }
436         else if( !strcmp( s, "realpath" ) )
437         {
438             char *psz_src = E_(SSPop)( st );
439             char *psz_dir = E_(RealPath)( p_intf, psz_src );
440
441             E_(SSPush)( st, psz_dir );
442             free( psz_src );
443             free( psz_dir );
444         }
445         /* 4. stack functions */
446         else if( !strcmp( s, "dup" ) )
447         {
448             char *str = E_(SSPop)( st );
449             E_(SSPush)( st, str );
450             E_(SSPush)( st, str );
451             free( str );
452         }
453         else if( !strcmp( s, "drop" ) )
454         {
455             char *str = E_(SSPop)( st );
456             free( str );
457         }
458         else if( !strcmp( s, "swap" ) )
459         {
460             char *s1 = E_(SSPop)( st );
461             char *s2 = E_(SSPop)( st );
462
463             E_(SSPush)( st, s1 );
464             E_(SSPush)( st, s2 );
465             free( s1 );
466             free( s2 );
467         }
468         else if( !strcmp( s, "flush" ) )
469         {
470             E_(SSClean)( st );
471             E_(SSInit)( st );
472         }
473         else if( !strcmp( s, "store" ) )
474         {
475             char *value = E_(SSPop)( st );
476             char *name  = E_(SSPop)( st );
477
478             E_(mvar_PushNewVar)( vars, name, value );
479             free( name );
480             free( value );
481         }
482         else if( !strcmp( s, "value" ) )
483         {
484             char *name  = E_(SSPop)( st );
485             char *value = E_(mvar_GetValue)( vars, name );
486
487             E_(SSPush)( st, value );
488
489             free( name );
490         }
491         /* 5. player control */
492         else if( !strcmp( s, "vlc_play" ) )
493         {
494             int i_id = E_(SSPopN)( st, vars );
495             int i_ret;
496
497             i_ret = playlist_Control( p_sys->p_playlist, PLAYLIST_VIEWPLAY,
498                                       VLC_TRUE, NULL,
499                                       playlist_ItemGetById( p_sys->p_playlist,
500                                       i_id, VLC_TRUE ) );
501             msg_Dbg( p_intf, "requested playlist item: %i", i_id );
502             E_(SSPushN)( st, i_ret );
503         }
504         else if( !strcmp( s, "vlc_stop" ) )
505         {
506             playlist_Control( p_sys->p_playlist, PLAYLIST_STOP, VLC_TRUE );
507             msg_Dbg( p_intf, "requested playlist stop" );
508         }
509         else if( !strcmp( s, "vlc_pause" ) )
510         {
511             playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE, VLC_TRUE );
512             msg_Dbg( p_intf, "requested playlist pause" );
513         }
514         else if( !strcmp( s, "vlc_next" ) )
515         {
516             playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, VLC_TRUE, 1 );
517             msg_Dbg( p_intf, "requested playlist next" );
518         }
519         else if( !strcmp( s, "vlc_previous" ) )
520         {
521             playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, VLC_TRUE, -1 );
522             msg_Dbg( p_intf, "requested playlist previous" );
523         }
524         else if( !strcmp( s, "vlc_seek" ) )
525         {
526             char *psz_value = E_(SSPop)( st );
527             E_(HandleSeek)( p_intf, psz_value );
528             msg_Dbg( p_intf, "requested playlist seek: %s", psz_value );
529             free( psz_value );
530         }
531         else if( !strcmp( s, "vlc_var_type" )
532                   || !strcmp( s, "vlc_config_type" ) )
533         {
534             vlc_object_t *p_object;
535             const char *psz_type = NULL;
536             int i_type = 0;
537
538             if( !strcmp( s, "vlc_var_type" ) )
539             {
540                 char *psz_object = E_(SSPop)( st );
541                 char *psz_variable = E_(SSPop)( st );
542                 vlc_bool_t b_need_release;
543
544                 p_object = GetVLCObject( p_intf, psz_object, &b_need_release );
545
546                 if( p_object != NULL )
547                     i_type = var_Type( p_object, psz_variable );
548                 free( psz_variable );
549                 free( psz_object );
550                 if( b_need_release && p_object != NULL )
551                     vlc_object_release( p_object );
552             }
553             else
554             {
555                 char *psz_variable = E_(SSPop)( st );
556                 p_object = VLC_OBJECT(p_intf);
557                 i_type = config_GetType( p_object, psz_variable );
558                 free( psz_variable );
559             }
560
561             if( p_object != NULL )
562             {
563                 switch( i_type & VLC_VAR_TYPE )
564                 {
565                 case VLC_VAR_BOOL:
566                     psz_type = "VLC_VAR_BOOL";
567                     break;
568                 case VLC_VAR_INTEGER:
569                     psz_type = "VLC_VAR_INTEGER";
570                     break;
571                 case VLC_VAR_HOTKEY:
572                     psz_type = "VLC_VAR_HOTKEY";
573                     break;
574                 case VLC_VAR_STRING:
575                     psz_type = "VLC_VAR_STRING";
576                     break;
577                 case VLC_VAR_MODULE:
578                     psz_type = "VLC_VAR_MODULE";
579                     break;
580                 case VLC_VAR_FILE:
581                     psz_type = "VLC_VAR_FILE";
582                     break;
583                 case VLC_VAR_DIRECTORY:
584                     psz_type = "VLC_VAR_DIRECTORY";
585                     break;
586                 case VLC_VAR_VARIABLE:
587                     psz_type = "VLC_VAR_VARIABLE";
588                     break;
589                 case VLC_VAR_FLOAT:
590                     psz_type = "VLC_VAR_FLOAT";
591                     break;
592                 default:
593                     psz_type = "UNDEFINED";
594                 }
595             }
596             else
597                 psz_type = "INVALID";
598
599             E_(SSPush)( st, psz_type );
600         }
601         else if( !strcmp( s, "vlc_var_set" ) )
602         {
603             char *psz_object = E_(SSPop)( st );
604             char *psz_variable = E_(SSPop)( st );
605             vlc_bool_t b_need_release;
606
607             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
608                                                    &b_need_release );
609
610             if( p_object != NULL )
611             {
612                 vlc_bool_t b_error = VLC_FALSE;
613                 char *psz_value = NULL;
614                 vlc_value_t val;
615                 int i_type;
616
617                 i_type = var_Type( p_object, psz_variable );
618
619                 switch( i_type & VLC_VAR_TYPE )
620                 {
621                 case VLC_VAR_BOOL:
622                     val.b_bool = E_(SSPopN)( st, vars );
623                     msg_Dbg( p_intf, "requested %s var change: %s->%d",
624                              psz_object, psz_variable, val.b_bool );
625                     break;
626                 case VLC_VAR_INTEGER:
627                 case VLC_VAR_HOTKEY:
628                     val.i_int = E_(SSPopN)( st, vars );
629                     msg_Dbg( p_intf, "requested %s var change: %s->%d",
630                              psz_object, psz_variable, val.i_int );
631                     break;
632                 case VLC_VAR_STRING:
633                 case VLC_VAR_MODULE:
634                 case VLC_VAR_FILE:
635                 case VLC_VAR_DIRECTORY:
636                 case VLC_VAR_VARIABLE:
637                     val.psz_string = psz_value = E_(SSPop)( st );
638                     msg_Dbg( p_intf, "requested %s var change: %s->%s",
639                              psz_object, psz_variable, psz_value );
640                     break;
641                 case VLC_VAR_FLOAT:
642                     psz_value = E_(SSPop)( st );
643                     val.f_float = atof( psz_value );
644                     msg_Dbg( p_intf, "requested %s var change: %s->%f",
645                              psz_object, psz_variable, val.f_float );
646                     break;
647                 default:
648                     E_(SSPopN)( st, vars );
649                     msg_Warn( p_intf, "invalid %s variable type %d (%s)",
650                               psz_object, i_type & VLC_VAR_TYPE, psz_variable );
651                     b_error = VLC_TRUE;
652                 }
653
654                 if( !b_error )
655                     var_Set( p_object, psz_variable, val );
656                 if( psz_value != NULL )
657                     free( psz_value );
658             }
659             else
660                 msg_Warn( p_intf, "vlc_var_set called without an object" );
661             free( psz_variable );
662             free( psz_object );
663
664             if( b_need_release && p_object != NULL )
665                 vlc_object_release( p_object );
666         }
667         else if( !strcmp( s, "vlc_var_get" ) )
668         {
669             char *psz_object = E_(SSPop)( st );
670             char *psz_variable = E_(SSPop)( st );
671             vlc_bool_t b_need_release;
672
673             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
674                                                    &b_need_release );
675
676             if( p_object != NULL )
677             {
678                 vlc_value_t val;
679                 int i_type;
680
681                 i_type = var_Type( p_object, psz_variable );
682                 var_Get( p_object, psz_variable, &val );
683
684                 switch( i_type & VLC_VAR_TYPE )
685                 {
686                 case VLC_VAR_BOOL:
687                     E_(SSPushN)( st, val.b_bool );
688                     break;
689                 case VLC_VAR_INTEGER:
690                 case VLC_VAR_HOTKEY:
691                     E_(SSPushN)( st, val.i_int );
692                     break;
693                 case VLC_VAR_STRING:
694                 case VLC_VAR_MODULE:
695                 case VLC_VAR_FILE:
696                 case VLC_VAR_DIRECTORY:
697                 case VLC_VAR_VARIABLE:
698                     E_(SSPush)( st, val.psz_string );
699                     free( val.psz_string );
700                     break;
701                 case VLC_VAR_FLOAT:
702                 {
703                     char psz_value[20];
704                     lldiv_t value = lldiv( val.f_float * 1000000, 1000000 );
705                     snprintf( psz_value, sizeof(psz_value), "%lld.%06u",
706                                     value.quot, (unsigned int)value.rem );
707                     E_(SSPush)( st, psz_value );
708                     break;
709                 }
710                 default:
711                     msg_Warn( p_intf, "invalid %s variable type %d (%s)",
712                               psz_object, i_type & VLC_VAR_TYPE, psz_variable );
713                     E_(SSPush)( st, "" );
714                 }
715             }
716             else
717             {
718                 msg_Warn( p_intf, "vlc_var_get called without an object" );
719                 E_(SSPush)( st, "" );
720             }
721             free( psz_variable );
722             free( psz_object );
723
724             if( b_need_release && p_object != NULL )
725                 vlc_object_release( p_object );
726         }
727         else if( !strcmp( s, "vlc_object_exists" ) )
728         {
729             char *psz_object = E_(SSPop)( st );
730             vlc_bool_t b_need_release;
731
732             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
733                                                    &b_need_release );
734             if( b_need_release && p_object != NULL )
735                 vlc_object_release( p_object );
736
737             if( p_object != NULL )
738                 E_(SSPush)( st, "1" );
739             else
740                 E_(SSPush)( st, "0" );
741         }
742         else if( !strcmp( s, "vlc_config_set" ) )
743         {
744             char *psz_variable = E_(SSPop)( st );
745             int i_type = config_GetType( p_intf, psz_variable );
746
747             switch( i_type & VLC_VAR_TYPE )
748             {
749             case VLC_VAR_BOOL:
750             case VLC_VAR_INTEGER:
751                 config_PutInt( p_intf, psz_variable, E_(SSPopN)( st, vars ) );
752                 break;
753             case VLC_VAR_STRING:
754             case VLC_VAR_MODULE:
755             case VLC_VAR_FILE:
756             case VLC_VAR_DIRECTORY:
757             {
758                 char *psz_string = E_(SSPop)( st );
759                 config_PutPsz( p_intf, psz_variable, psz_string );
760                 free( psz_string );
761                 break;
762             }
763             case VLC_VAR_FLOAT:
764             {
765                 char *psz_string = E_(SSPop)( st );
766                 config_PutFloat( p_intf, psz_variable, atof(psz_string) );
767                 free( psz_string );
768                 break;
769             }
770             default:
771                 msg_Warn( p_intf, "vlc_config_set called on unknown var (%s)",
772                           psz_variable );
773             }
774             free( psz_variable );
775         }
776         else if( !strcmp( s, "vlc_config_get" ) )
777         {
778             char *psz_variable = E_(SSPop)( st );
779             int i_type = config_GetType( p_intf, psz_variable );
780
781             switch( i_type & VLC_VAR_TYPE )
782             {
783             case VLC_VAR_BOOL:
784             case VLC_VAR_INTEGER:
785                 E_(SSPushN)( st, config_GetInt( p_intf, psz_variable ) );
786                 break;
787             case VLC_VAR_STRING:
788             case VLC_VAR_MODULE:
789             case VLC_VAR_FILE:
790             case VLC_VAR_DIRECTORY:
791             {
792                 char *psz_string = config_GetPsz( p_intf, psz_variable );
793                 E_(SSPush)( st, psz_string );
794                 free( psz_string );
795                 break;
796             }
797             case VLC_VAR_FLOAT:
798             {
799                 char psz_string[20];
800                 lldiv_t value = lldiv( config_GetFloat( p_intf, psz_variable )
801                                        * 1000000, 1000000 );
802                 snprintf( psz_string, sizeof(psz_string), "%lld.%06u",
803                           value.quot, (unsigned int)value.rem );
804                 E_(SSPush)( st, psz_string );
805                 break;
806             }
807             default:
808                 msg_Warn( p_intf, "vlc_config_get called on unknown var (%s)",
809                           psz_variable );
810             }
811             free( psz_variable );
812         }
813         else if( !strcmp( s, "vlc_config_save" ) )
814         {
815             char *psz_module = E_(SSPop)( st );
816             int i_result;
817
818             if( !*psz_module )
819             {
820                 free( psz_module );
821                 psz_module = NULL;
822             }
823             i_result = config_SaveConfigFile( p_intf, psz_module );
824
825             if( psz_module != NULL )
826                 free( psz_module );
827             E_(SSPushN)( st, i_result );
828         }
829         else if( !strcmp( s, "vlc_config_reset" ) )
830         {
831             config_ResetAll( p_intf );
832         }
833         /* 6. playlist functions */
834         else if( !strcmp( s, "playlist_add" ) )
835         {
836             char *psz_name = E_(SSPop)( st );
837             char *mrl = E_(SSPop)( st );
838             char *tmp;
839             input_item_t *p_input;
840             int i_ret;
841
842             tmp = E_(ToUTF8)( p_intf, psz_name );
843             free( psz_name );
844             psz_name = tmp;
845             tmp = E_(ToUTF8)( p_intf, mrl );
846             free( mrl );
847             mrl = tmp;
848
849             p_input = E_(MRLParse)( p_intf, mrl, psz_name );
850
851             char *psz_uri = input_item_GetURI( p_input );
852             if( !p_input || !psz_uri || !*psz_uri )
853             {
854                 i_ret = VLC_EGENERIC;
855                 msg_Dbg( p_intf, "invalid requested mrl: %s", mrl );
856             }
857             else
858             {
859                 i_ret = playlist_AddInput( p_sys->p_playlist, p_input,
860                                    PLAYLIST_APPEND, PLAYLIST_END, VLC_TRUE,
861                                    VLC_FALSE);
862                 msg_Dbg( p_intf, "requested mrl add: %s", mrl );
863             }
864             free( psz_uri );
865             E_(SSPushN)( st, i_ret );
866
867             free( mrl );
868             free( psz_name );
869         }
870         else if( !strcmp( s, "playlist_empty" ) )
871         {
872             playlist_Clear( p_sys->p_playlist, VLC_FALSE );
873             msg_Dbg( p_intf, "requested playlist empty" );
874         }
875         else if( !strcmp( s, "playlist_delete" ) )
876         {
877             int i_id = E_(SSPopN)( st, vars );
878             playlist_item_t *p_item = playlist_ItemGetById( p_sys->p_playlist,
879                                                             i_id, VLC_FALSE );
880             if( p_item )
881             {
882                 playlist_DeleteFromInput( p_sys->p_playlist,
883                                           p_item->p_input->i_id, VLC_FALSE );
884                 msg_Dbg( p_intf, "requested playlist delete: %d", i_id );
885             }
886             else
887             {
888                 msg_Dbg( p_intf, "couldn't find playlist item to delete (%d)",
889                          i_id );
890             }
891         }
892         else if( !strcmp( s, "playlist_move" ) )
893         {
894             /*int i_newpos =*/ E_(SSPopN)( st, vars );
895             /*int i_pos =*/ E_(SSPopN)( st, vars );
896             /* FIXME FIXME TODO TODO XXX XXX
897             do not release before fixing this
898             if ( i_pos < i_newpos )
899             {
900                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos + 1 );
901             }
902             else
903             {
904                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos );
905             }
906             msg_Dbg( p_intf, "requested to move playlist item %d to %d",
907                      i_pos, i_newpos);
908                FIXME FIXME TODO TODO XXX XXX */
909             msg_Err( p_intf, "moving using indexes is obsolete. We need to update this function" );
910         }
911         else if( !strcmp( s, "playlist_sort" ) )
912         {
913             int i_order = E_(SSPopN)( st, vars );
914             int i_sort = E_(SSPopN)( st, vars );
915             i_order = i_order % 2;
916             i_sort = i_sort % 9;
917             /* FIXME FIXME TODO TODO XXX XXX
918             do not release before fixing this
919             playlist_RecursiveNodeSort(  p_sys->p_playlist,
920                                          p_sys->p_playlist->p_general,
921                                          i_sort, i_order );
922             msg_Dbg( p_intf, "requested sort playlist by : %d in order : %d",
923                      i_sort, i_order );
924                FIXME FIXME TODO TODO XXX XXX */
925             msg_Err( p_intf, "this needs to be fixed to use the new playlist framework" );
926         }
927         else if( !strcmp( s, "services_discovery_add" ) )
928         {
929             char *psz_sd = E_(SSPop)( st );
930             playlist_ServicesDiscoveryAdd( p_sys->p_playlist, psz_sd );
931             free( psz_sd );
932         }
933         else if( !strcmp( s, "services_discovery_remove" ) )
934         {
935             char *psz_sd = E_(SSPop)( st );
936             playlist_ServicesDiscoveryRemove( p_sys->p_playlist, psz_sd );
937             free( psz_sd );
938         }
939         else if( !strcmp( s, "services_discovery_is_loaded" ) )
940         {
941             char *psz_sd = E_(SSPop)( st );
942             E_(SSPushN)( st,
943             playlist_IsServicesDiscoveryLoaded( p_sys->p_playlist, psz_sd ) );
944             free( psz_sd );
945         }
946         else if( !strcmp( s, "vlc_volume_set" ) )
947         {
948             char *psz_vol = E_(SSPop)( st );
949             int i_value;
950             audio_volume_t i_volume;
951             aout_VolumeGet( p_intf, &i_volume );
952             if( psz_vol[0] == '+' )
953             {
954                 i_value = atoi( psz_vol );
955                 if( (i_volume + i_value) > AOUT_VOLUME_MAX )
956                     aout_VolumeSet( p_intf, AOUT_VOLUME_MAX );
957                 else
958                     aout_VolumeSet( p_intf, i_volume + i_value );
959             }
960             else if( psz_vol[0] == '-' )
961             {
962                 i_value = atoi( psz_vol );
963                 if( (i_volume + i_value) < AOUT_VOLUME_MIN )
964                     aout_VolumeSet( p_intf, AOUT_VOLUME_MIN );
965                 else
966                     aout_VolumeSet( p_intf, i_volume + i_value );
967             }
968             else if( strstr( psz_vol, "%") != NULL )
969             {
970                 i_value = atoi( psz_vol );
971                 if( i_value < 0 ) i_value = 0;
972                 if( i_value > 400 ) i_value = 400;
973                 aout_VolumeSet( p_intf, (i_value * (AOUT_VOLUME_MAX - AOUT_VOLUME_MIN))/400+AOUT_VOLUME_MIN);
974             }
975             else
976             {
977                 i_value = atoi( psz_vol );
978                 if( i_value > AOUT_VOLUME_MAX ) i_value = AOUT_VOLUME_MAX;
979                 if( i_value < AOUT_VOLUME_MIN ) i_value = AOUT_VOLUME_MIN;
980                 aout_VolumeSet( p_intf, i_value );
981             }
982             aout_VolumeGet( p_intf, &i_volume );
983             free( psz_vol );
984         }
985         else if( !strcmp( s, "vlc_get_meta" ) )
986         {
987             char *psz_meta = E_(SSPop)( st );
988             char *psz_val = NULL;
989             if( p_sys->p_input && input_GetItem(p_sys->p_input) )
990             {
991 #define p_item input_GetItem( p_sys->p_input )
992                 if( !strcmp( psz_meta, "ARTIST" ) )
993                 {
994                     psz_val = input_ItemGetInfo( p_item,
995                                 _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) );
996                 }
997                 else if( !strcmp( psz_meta, "TITLE" ) )
998                 {
999                     psz_val = input_ItemGetInfo( p_item,
1000                                 _(VLC_META_INFO_CAT), _(VLC_META_TITLE) );
1001                     if( psz_val == NULL )
1002                         psz_val = strdup( p_item->psz_name );
1003                 }
1004                 else if( !strcmp( psz_meta, "ALBUM" ) )
1005                 {
1006                     psz_val = input_ItemGetInfo( p_item,
1007                                 _(VLC_META_INFO_CAT), _(VLC_META_COLLECTION) );
1008                 }
1009                 else if( !strcmp( psz_meta, "GENRE" ) )
1010                 {
1011                     psz_val = input_ItemGetInfo( p_item,
1012                                 _(VLC_META_INFO_CAT), _(VLC_META_GENRE) );
1013                 }
1014                 else
1015                 {
1016                     psz_val = input_ItemGetInfo( p_item,
1017                                             _(VLC_META_INFO_CAT), psz_meta );
1018                 }
1019 #undef p_item
1020             }
1021             if( psz_val == NULL ) psz_val = strdup( "" );
1022             E_(SSPush)( st, psz_val );
1023             free( psz_meta );
1024             free( psz_val );
1025         }
1026         else if( !strcmp( s, "vlm_command" ) || !strcmp( s, "vlm_cmd" ) )
1027         {
1028             char *psz_elt;
1029             char *psz_cmd = strdup( "" );
1030             char *psz_error;
1031             vlm_message_t *vlm_answer;
1032
1033             /* make sure that we have a vlm object */
1034             if( p_intf->p_sys->p_vlm == NULL )
1035                 p_intf->p_sys->p_vlm = vlm_New( p_intf );
1036
1037
1038             /* vlm command uses the ';' delimiter
1039              * (else we can't know when to stop) */
1040             while( strcmp( psz_elt = E_(SSPop)( st ), "" )
1041                    && strcmp( psz_elt, ";" ) )
1042             {
1043                 char *psz_buf =
1044                     (char *)malloc( strlen( psz_cmd ) + strlen( psz_elt ) + 2 );
1045                 sprintf( psz_buf, "%s %s", psz_cmd, psz_elt );
1046                 free( psz_cmd );
1047                 free( psz_elt );
1048                 psz_cmd = psz_buf;
1049             }
1050
1051             msg_Dbg( p_intf, "executing vlm command: %s", psz_cmd );
1052             vlm_ExecuteCommand( p_intf->p_sys->p_vlm, psz_cmd, &vlm_answer );
1053
1054             if( vlm_answer->psz_value == NULL )
1055             {
1056                 psz_error = strdup( "" );
1057             }
1058             else
1059             {
1060                 psz_error = malloc( strlen(vlm_answer->psz_name) +
1061                                     strlen(vlm_answer->psz_value) +
1062                                     strlen( " : ") + 1 );
1063                 sprintf( psz_error , "%s : %s" , vlm_answer->psz_name,
1064                                                  vlm_answer->psz_value );
1065             }
1066
1067             E_(mvar_AppendNewVar)( vars, "vlm_error", psz_error );
1068             /* this is kind of a duplicate but we need to have the message
1069              * without the command name for the "export" command */
1070             E_(mvar_AppendNewVar)( vars, "vlm_value", vlm_answer->psz_value );
1071             vlm_MessageDelete( vlm_answer );
1072
1073             free( psz_cmd );
1074             free( psz_error );
1075         }
1076         else if( !strcmp( s, "snapshot" ) )
1077         {
1078             if( p_sys->p_input )
1079             {
1080                 vout_thread_t *p_vout;
1081                 p_vout = vlc_object_find( p_sys->p_input,
1082                                           VLC_OBJECT_VOUT, FIND_CHILD );
1083
1084                 if( p_vout )
1085                 {
1086                     vout_Control( p_vout, VOUT_SNAPSHOT );
1087                     vlc_object_release( p_vout );
1088                     msg_Dbg( p_intf, "requested snapshot" );
1089                 }
1090             }
1091             break;
1092
1093         }
1094         else
1095         {
1096             E_(SSPush)( st, s );
1097         }
1098     }
1099 }