]> git.sesse.net Git - vlc/blob - modules/control/http/rpn.c
* src/extras/libc.c: Implemented a vlc_readdir_wrapper under Win32. This
[vlc] / modules / control / http / rpn.c
1 /*****************************************************************************
2  * rpn.c : RPN evaluator for the HTTP Interface
3  *****************************************************************************
4  * Copyright (C) 2001-2005 the VideoLAN team
5  * $Id: http.c 12225 2005-08-18 10:01:30Z massiot $
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 #include "http.h"
27
28 static vlc_object_t *GetVLCObject( intf_thread_t *p_intf,
29                                    const char *psz_object,
30                                    vlc_bool_t *pb_need_release )
31 {
32     intf_sys_t    *p_sys = p_intf->p_sys;
33     int i_object_type = 0;
34     vlc_object_t *p_object = NULL;
35     *pb_need_release = VLC_FALSE;
36
37     if( !strcmp( psz_object, "VLC_OBJECT_ROOT" ) )
38         i_object_type = VLC_OBJECT_ROOT;
39     else if( !strcmp( psz_object, "VLC_OBJECT_VLC" ) )
40         p_object = VLC_OBJECT(p_intf->p_vlc);
41     else if( !strcmp( psz_object, "VLC_OBJECT_INTF" ) )
42         p_object = VLC_OBJECT(p_intf);
43     else if( !strcmp( psz_object, "VLC_OBJECT_PLAYLIST" ) )
44         p_object = VLC_OBJECT(p_sys->p_playlist);
45     else if( !strcmp( psz_object, "VLC_OBJECT_INPUT" ) )
46         p_object = VLC_OBJECT(p_sys->p_input);
47     else if( !strcmp( psz_object, "VLC_OBJECT_VOUT" ) )
48         i_object_type = VLC_OBJECT_VOUT;
49     else if( !strcmp( psz_object, "VLC_OBJECT_AOUT" ) )
50         i_object_type = VLC_OBJECT_AOUT;
51     else if( !strcmp( psz_object, "VLC_OBJECT_SOUT" ) )
52         i_object_type = VLC_OBJECT_SOUT;
53     else
54         msg_Warn( p_intf, "unknown object type (%s)", psz_object );
55
56     if( p_object == NULL && i_object_type )
57     {
58         *pb_need_release = VLC_TRUE;
59         p_object = vlc_object_find( p_intf, i_object_type, FIND_ANYWHERE );
60     }
61
62     return p_object;
63 }
64
65 void E_(SSInit)( rpn_stack_t *st )
66 {
67     st->i_stack = 0;
68 }
69
70 void E_(SSClean)( rpn_stack_t *st )
71 {
72     while( st->i_stack > 0 )
73     {
74         free( st->stack[--st->i_stack] );
75     }
76 }
77
78 void E_(SSPush)( rpn_stack_t *st, const char *s )
79 {
80     if( st->i_stack < STACK_MAX )
81     {
82         st->stack[st->i_stack++] = strdup( s );
83     }
84 }
85
86 char *E_(SSPop)( rpn_stack_t *st )
87 {
88     if( st->i_stack <= 0 )
89     {
90         return strdup( "" );
91     }
92     else
93     {
94         return st->stack[--st->i_stack];
95     }
96 }
97
98 int E_(SSPopN)( rpn_stack_t *st, mvar_t  *vars )
99 {
100     char *name;
101     char *value;
102
103     char *end;
104     int  i;
105
106     name = E_(SSPop)( st );
107     i = strtol( name, &end, 0 );
108     if( end == name )
109     {
110         value = E_(mvar_GetValue)( vars, name );
111         i = atoi( value );
112     }
113     free( name );
114
115     return( i );
116 }
117
118 void E_(SSPushN)( rpn_stack_t *st, int i )
119 {
120     char v[512];
121
122     sprintf( v, "%d", i );
123     E_(SSPush)( st, v );
124 }
125
126 void E_(EvaluateRPN)( intf_thread_t *p_intf, mvar_t  *vars,
127                       rpn_stack_t *st, char *exp )
128 {
129     intf_sys_t    *p_sys = p_intf->p_sys;
130
131     while( exp != NULL && *exp != '\0' )
132     {
133         char *p, *s;
134
135         /* skip space */
136         while( *exp == ' ' )
137         {
138             exp++;
139         }
140
141         if( *exp == '\'' )
142         {
143             /* extract string */
144             p = E_(FirstWord)( exp, exp );
145             E_(SSPush)( st, exp );
146             exp = p;
147             continue;
148         }
149
150         /* extract token */
151         p = E_(FirstWord)( exp, exp );
152         s = exp;
153         if( p == NULL )
154         {
155             exp += strlen( exp );
156         }
157         else
158         {
159             exp = p;
160         }
161
162         if( *s == '\0' )
163         {
164             break;
165         }
166
167         /* 1. Integer function */
168         if( !strcmp( s, "!" ) )
169         {
170             E_(SSPushN)( st, ~E_(SSPopN)( st, vars ) );
171         }
172         else if( !strcmp( s, "^" ) )
173         {
174             E_(SSPushN)( st, E_(SSPopN)( st, vars ) ^ E_(SSPopN)( st, vars ) );
175         }
176         else if( !strcmp( s, "&" ) )
177         {
178             E_(SSPushN)( st, E_(SSPopN)( st, vars ) & E_(SSPopN)( st, vars ) );
179         }
180         else if( !strcmp( s, "|" ) )
181         {
182             E_(SSPushN)( st, E_(SSPopN)( st, vars ) | E_(SSPopN)( st, vars ) );
183         }
184         else if( !strcmp( s, "+" ) )
185         {
186             E_(SSPushN)( st, E_(SSPopN)( st, vars ) + E_(SSPopN)( st, vars ) );
187         }
188         else if( !strcmp( s, "-" ) )
189         {
190             int j = E_(SSPopN)( st, vars );
191             int i = E_(SSPopN)( st, vars );
192             E_(SSPushN)( st, i - j );
193         }
194         else if( !strcmp( s, "*" ) )
195         {
196             E_(SSPushN)( st, E_(SSPopN)( st, vars ) * E_(SSPopN)( st, vars ) );
197         }
198         else if( !strcmp( s, "/" ) )
199         {
200             int i, j;
201
202             j = E_(SSPopN)( st, vars );
203             i = E_(SSPopN)( st, vars );
204
205             E_(SSPushN)( st, j != 0 ? i / j : 0 );
206         }
207         else if( !strcmp( s, "%" ) )
208         {
209             int i, j;
210
211             j = E_(SSPopN)( st, vars );
212             i = E_(SSPopN)( st, vars );
213
214             E_(SSPushN)( st, j != 0 ? i % j : 0 );
215         }
216         /* 2. integer tests */
217         else if( !strcmp( s, "=" ) )
218         {
219             E_(SSPushN)( st, E_(SSPopN)( st, vars ) == E_(SSPopN)( st, vars ) ? -1 : 0 );
220         }
221         else if( !strcmp( s, "!=" ) )
222         {
223             E_(SSPushN)( st, E_(SSPopN)( st, vars ) != E_(SSPopN)( st, vars ) ? -1 : 0 );
224         }
225         else if( !strcmp( s, "<" ) )
226         {
227             int j = E_(SSPopN)( st, vars );
228             int i = E_(SSPopN)( st, vars );
229
230             E_(SSPushN)( st, i < j ? -1 : 0 );
231         }
232         else if( !strcmp( s, ">" ) )
233         {
234             int j = E_(SSPopN)( st, vars );
235             int i = E_(SSPopN)( st, vars );
236
237             E_(SSPushN)( st, i > j ? -1 : 0 );
238         }
239         else if( !strcmp( s, "<=" ) )
240         {
241             int j = E_(SSPopN)( st, vars );
242             int i = E_(SSPopN)( st, vars );
243
244             E_(SSPushN)( st, i <= j ? -1 : 0 );
245         }
246         else if( !strcmp( s, ">=" ) )
247         {
248             int j = E_(SSPopN)( st, vars );
249             int i = E_(SSPopN)( st, vars );
250
251             E_(SSPushN)( st, i >= j ? -1 : 0 );
252         }
253         /* 3. string functions */
254         else if( !strcmp( s, "strcat" ) )
255         {
256             char *s2 = E_(SSPop)( st );
257             char *s1 = E_(SSPop)( st );
258             char *str = malloc( strlen( s1 ) + strlen( s2 ) + 1 );
259
260             strcpy( str, s1 );
261             strcat( str, s2 );
262
263             E_(SSPush)( st, str );
264             free( s1 );
265             free( s2 );
266             free( str );
267         }
268         else if( !strcmp( s, "strcmp" ) )
269         {
270             char *s2 = E_(SSPop)( st );
271             char *s1 = E_(SSPop)( st );
272
273             E_(SSPushN)( st, strcmp( s1, s2 ) );
274             free( s1 );
275             free( s2 );
276         }
277         else if( !strcmp( s, "strncmp" ) )
278         {
279             int n = E_(SSPopN)( st, vars );
280             char *s2 = E_(SSPop)( st );
281             char *s1 = E_(SSPop)( st );
282
283             E_(SSPushN)( st, strncmp( s1, s2 , n ) );
284             free( s1 );
285             free( s2 );
286         }
287         else if( !strcmp( s, "strsub" ) )
288         {
289             int n = E_(SSPopN)( st, vars );
290             int m = E_(SSPopN)( st, vars );
291             int i_len;
292             char *s = E_(SSPop)( st );
293             char *str;
294
295             if( n >= m )
296             {
297                 i_len = n - m + 1;
298             }
299             else
300             {
301                 i_len = 0;
302             }
303
304             str = malloc( i_len + 1 );
305
306             memcpy( str, s + m - 1, i_len );
307             str[ i_len ] = '\0';
308
309             E_(SSPush)( st, str );
310             free( s );
311             free( str );
312         }
313         else if( !strcmp( s, "strlen" ) )
314         {
315             char *str = E_(SSPop)( st );
316
317             E_(SSPushN)( st, strlen( str ) );
318             free( str );
319         }
320         else if( !strcmp( s, "str_replace" ) )
321         {
322             char *psz_to = E_(SSPop)( st );
323             char *psz_from = E_(SSPop)( st );
324             char *psz_in = E_(SSPop)( st );
325             char *psz_in_current = psz_in;
326             char *psz_out = malloc( strlen(psz_in) * strlen(psz_to) + 1 );
327             char *psz_out_current = psz_out;
328
329             while( (p = strstr( psz_in_current, psz_from )) != NULL )
330             {
331                 memcpy( psz_out_current, psz_in_current, p - psz_in_current );
332                 psz_out_current += p - psz_in_current;
333                 strcpy( psz_out_current, psz_to );
334                 psz_out_current += strlen(psz_to);
335                 psz_in_current = p + strlen(psz_from);
336             }
337             strcpy( psz_out_current, psz_in_current );
338             psz_out_current += strlen(psz_in_current);
339             *psz_out_current = '\0';
340
341             E_(SSPush)( st, psz_out );
342             free( psz_to );
343             free( psz_from );
344             free( psz_in );
345             free( psz_out );
346         }
347         else if( !strcmp( s, "url_extract" ) )
348         {
349             char *url = E_(mvar_GetValue)( vars, "url_value" );
350             char *name = E_(SSPop)( st );
351             char value[512];
352             char *tmp;
353
354             E_(ExtractURIValue)( url, name, value, 512 );
355             E_(DecodeEncodedURI)( value );
356             tmp = E_(FromUTF8)( p_intf, value );
357             E_(SSPush)( st, tmp );
358             free( tmp );
359             free( name );
360         }
361         else if( !strcmp( s, "url_encode" ) )
362         {
363             char *url = E_(SSPop)( st );
364             char *value;
365
366             value = E_(ToUTF8)( p_intf, url );
367             free( url );
368             url = value;
369             value = vlc_UrlEncode( url );
370             free( url );
371             E_(SSPush)( st, value );
372             free( value );
373         }
374         else if( !strcmp( s, "addslashes" ) )
375         {
376             char *psz_src = E_(SSPop)( st );
377             char *psz_dest;
378             char *str = psz_src;
379
380             p = psz_dest = malloc( strlen( str ) * 2 + 1 );
381
382             while( *str != '\0' )
383             {
384                 if( *str == '"' || *str == '\'' || *str == '\\' )
385                 {
386                     *p++ = '\\';
387                 }
388                 *p++ = *str;
389                 str++;
390             }
391             *p = '\0';
392
393             E_(SSPush)( st, psz_dest );
394             free( psz_src );
395             free( psz_dest );
396         }
397         else if( !strcmp( s, "stripslashes" ) )
398         {
399             char *psz_src = E_(SSPop)( st );
400             char *psz_dest;
401
402             p = psz_dest = strdup( psz_src );
403
404             while( *psz_src != '\0' )
405             {
406                 if( *psz_src == '\\' )
407                 {
408                     *psz_src++;
409                 }
410                 *p++ = *psz_src;
411                 psz_src++;
412             }
413             *p = '\0';
414
415             E_(SSPush)( st, psz_dest );
416             free( psz_src );
417             free( psz_dest );
418         }
419         else if( !strcmp( s, "htmlspecialchars" ) )
420         {
421             char *psz_src = E_(SSPop)( st );
422             char *psz_dest;
423             char *str = psz_src;
424
425             p = psz_dest = malloc( strlen( str ) * 6 + 1 );
426
427             while( *str != '\0' )
428             {
429                 if( *str == '&' )
430                 {
431                     strcpy( p, "&amp;" );
432                     p += 5;
433                 }
434                 else if( *str == '\"' )
435                 {
436                     strcpy( p, "&quot;" );
437                     p += 6;
438                 }
439                 else if( *str == '\'' )
440                 {
441                     strcpy( p, "&#039;" );
442                     p += 6;
443                 }
444                 else if( *str == '<' )
445                 {
446                     strcpy( p, "&lt;" );
447                     p += 4;
448                 }
449                 else if( *str == '>' )
450                 {
451                     strcpy( p, "&gt;" );
452                     p += 4;
453                 }
454                 else
455                 {
456                     *p++ = *str;
457                 }
458                 str++;
459             }
460             *p = '\0';
461
462             E_(SSPush)( st, psz_dest );
463             free( psz_src );
464             free( psz_dest );
465         }
466         else if( !strcmp( s, "realpath" ) )
467         {
468             char *psz_src = E_(SSPop)( st );
469             char *psz_dir = E_(RealPath)( p_intf, psz_src );
470
471             E_(SSPush)( st, psz_dir );
472             free( psz_src );
473             free( psz_dir );
474         }
475         /* 4. stack functions */
476         else if( !strcmp( s, "dup" ) )
477         {
478             char *str = E_(SSPop)( st );
479             E_(SSPush)( st, str );
480             E_(SSPush)( st, str );
481             free( str );
482         }
483         else if( !strcmp( s, "drop" ) )
484         {
485             char *str = E_(SSPop)( st );
486             free( str );
487         }
488         else if( !strcmp( s, "swap" ) )
489         {
490             char *s1 = E_(SSPop)( st );
491             char *s2 = E_(SSPop)( st );
492
493             E_(SSPush)( st, s1 );
494             E_(SSPush)( st, s2 );
495             free( s1 );
496             free( s2 );
497         }
498         else if( !strcmp( s, "flush" ) )
499         {
500             E_(SSClean)( st );
501             E_(SSInit)( st );
502         }
503         else if( !strcmp( s, "store" ) )
504         {
505             char *value = E_(SSPop)( st );
506             char *name  = E_(SSPop)( st );
507
508             E_(mvar_PushNewVar)( vars, name, value );
509             free( name );
510             free( value );
511         }
512         else if( !strcmp( s, "value" ) )
513         {
514             char *name  = E_(SSPop)( st );
515             char *value = E_(mvar_GetValue)( vars, name );
516
517             E_(SSPush)( st, value );
518
519             free( name );
520         }
521         /* 5. player control */
522         else if( !strcmp( s, "vlc_play" ) )
523         {
524             int i_id = E_(SSPopN)( st, vars );
525             int i_ret;
526
527             i_ret = playlist_Control( p_sys->p_playlist, PLAYLIST_ITEMPLAY,
528                                       playlist_ItemGetById( p_sys->p_playlist,
529                                       i_id ) );
530             msg_Dbg( p_intf, "requested playlist item: %i", i_id );
531             E_(SSPushN)( st, i_ret );
532         }
533         else if( !strcmp( s, "vlc_stop" ) )
534         {
535             playlist_Control( p_sys->p_playlist, PLAYLIST_STOP );
536             msg_Dbg( p_intf, "requested playlist stop" );
537         }
538         else if( !strcmp( s, "vlc_pause" ) )
539         {
540             playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE );
541             msg_Dbg( p_intf, "requested playlist pause" );
542         }
543         else if( !strcmp( s, "vlc_next" ) )
544         {
545             playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, 1 );
546             msg_Dbg( p_intf, "requested playlist next" );
547         }
548         else if( !strcmp( s, "vlc_previous" ) )
549         {
550             playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, -1 );
551             msg_Dbg( p_intf, "requested playlist previous" );
552         }
553         else if( !strcmp( s, "vlc_seek" ) )
554         {
555             char *psz_value = E_(SSPop)( st );
556             E_(HandleSeek)( p_intf, psz_value );
557             msg_Dbg( p_intf, "requested playlist seek: %s", psz_value );
558             free( psz_value );
559         }
560         else if( !strcmp( s, "vlc_var_type" )
561                   || !strcmp( s, "vlc_config_type" ) )
562         {
563             vlc_object_t *p_object;
564             const char *psz_type = NULL;
565             int i_type = 0;
566
567             if( !strcmp( s, "vlc_var_type" ) )
568             {
569                 char *psz_object = E_(SSPop)( st );
570                 char *psz_variable = E_(SSPop)( st );
571                 vlc_bool_t b_need_release;
572
573                 p_object = GetVLCObject( p_intf, psz_object, &b_need_release );
574
575                 if( p_object != NULL )
576                     i_type = var_Type( p_object, psz_variable );
577                 free( psz_variable );
578                 free( psz_object );
579                 if( b_need_release && p_object != NULL )
580                     vlc_object_release( p_object );
581             }
582             else
583             {
584                 char *psz_variable = E_(SSPop)( st );
585                 p_object = VLC_OBJECT(p_intf);
586                 i_type = config_GetType( p_object, psz_variable );
587                 free( psz_variable );
588             }
589
590             if( p_object != NULL )
591             {
592                 switch( i_type & VLC_VAR_TYPE )
593                 {
594                 case VLC_VAR_BOOL:
595                     psz_type = "VLC_VAR_BOOL";
596                     break;
597                 case VLC_VAR_INTEGER:
598                     psz_type = "VLC_VAR_INTEGER";
599                     break;
600                 case VLC_VAR_HOTKEY:
601                     psz_type = "VLC_VAR_HOTKEY";
602                     break;
603                 case VLC_VAR_STRING:
604                     psz_type = "VLC_VAR_STRING";
605                     break;
606                 case VLC_VAR_MODULE:
607                     psz_type = "VLC_VAR_MODULE";
608                     break;
609                 case VLC_VAR_FILE:
610                     psz_type = "VLC_VAR_FILE";
611                     break;
612                 case VLC_VAR_DIRECTORY:
613                     psz_type = "VLC_VAR_DIRECTORY";
614                     break;
615                 case VLC_VAR_VARIABLE:
616                     psz_type = "VLC_VAR_VARIABLE";
617                     break;
618                 case VLC_VAR_FLOAT:
619                     psz_type = "VLC_VAR_FLOAT";
620                     break;
621                 default:
622                     psz_type = "UNDEFINED";
623                 }
624             }
625             else
626                 psz_type = "INVALID";
627
628             E_(SSPush)( st, psz_type );
629         }
630         else if( !strcmp( s, "vlc_var_set" ) )
631         {
632             char *psz_object = E_(SSPop)( st );
633             char *psz_variable = E_(SSPop)( st );
634             vlc_bool_t b_need_release;
635
636             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
637                                                    &b_need_release );
638
639             if( p_object != NULL )
640             {
641                 vlc_bool_t b_error = VLC_FALSE;
642                 char *psz_value = NULL;
643                 vlc_value_t val;
644                 int i_type;
645
646                 i_type = var_Type( p_object, psz_variable );
647
648                 switch( i_type & VLC_VAR_TYPE )
649                 {
650                 case VLC_VAR_BOOL:
651                     val.b_bool = E_(SSPopN)( st, vars );
652                     msg_Dbg( p_intf, "requested %s var change: %s->%d",
653                              psz_object, psz_variable, val.b_bool );
654                     break;
655                 case VLC_VAR_INTEGER:
656                 case VLC_VAR_HOTKEY:
657                     val.i_int = E_(SSPopN)( st, vars );
658                     msg_Dbg( p_intf, "requested %s var change: %s->%d",
659                              psz_object, psz_variable, val.i_int );
660                     break;
661                 case VLC_VAR_STRING:
662                 case VLC_VAR_MODULE:
663                 case VLC_VAR_FILE:
664                 case VLC_VAR_DIRECTORY:
665                 case VLC_VAR_VARIABLE:
666                     val.psz_string = psz_value = E_(SSPop)( st );
667                     msg_Dbg( p_intf, "requested %s var change: %s->%s",
668                              psz_object, psz_variable, psz_value );
669                     break;
670                 case VLC_VAR_FLOAT:
671                     psz_value = E_(SSPop)( st );
672                     val.f_float = atof( psz_value );
673                     msg_Dbg( p_intf, "requested %s var change: %s->%f",
674                              psz_object, psz_variable, val.f_float );
675                     break;
676                 default:
677                     E_(SSPopN)( st, vars );
678                     msg_Warn( p_intf, "invalid %s variable type %d (%s)",
679                               psz_object, i_type & VLC_VAR_TYPE, psz_variable );
680                     b_error = VLC_TRUE;
681                 }
682
683                 if( !b_error )
684                     var_Set( p_object, psz_variable, val );
685                 if( psz_value != NULL )
686                     free( psz_value );
687             }
688             else
689                 msg_Warn( p_intf, "vlc_var_set called without an object" );
690             free( psz_variable );
691             free( psz_object );
692
693             if( b_need_release && p_object != NULL )
694                 vlc_object_release( p_object );
695         }
696         else if( !strcmp( s, "vlc_var_get" ) )
697         {
698             char *psz_object = E_(SSPop)( st );
699             char *psz_variable = E_(SSPop)( st );
700             vlc_bool_t b_need_release;
701
702             vlc_object_t *p_object = GetVLCObject( p_intf, psz_object,
703                                                    &b_need_release );
704
705             if( p_object != NULL )
706             {
707                 vlc_value_t val;
708                 int i_type;
709
710                 i_type = var_Type( p_object, psz_variable );
711                 var_Get( p_object, psz_variable, &val );
712
713                 switch( i_type & VLC_VAR_TYPE )
714                 {
715                 case VLC_VAR_BOOL:
716                     E_(SSPushN)( st, val.b_bool );
717                     break;
718                 case VLC_VAR_INTEGER:
719                 case VLC_VAR_HOTKEY:
720                     E_(SSPushN)( st, val.i_int );
721                     break;
722                 case VLC_VAR_STRING:
723                 case VLC_VAR_MODULE:
724                 case VLC_VAR_FILE:
725                 case VLC_VAR_DIRECTORY:
726                 case VLC_VAR_VARIABLE:
727                     E_(SSPush)( st, val.psz_string );
728                     free( val.psz_string );
729                     break;
730                 case VLC_VAR_FLOAT:
731                 {
732                     char psz_value[20];
733                     snprintf( psz_value, sizeof(psz_value), "%f", val.f_float );
734                     E_(SSPush)( st, psz_value );
735                     break;
736                 }
737                 default:
738                     msg_Warn( p_intf, "invalid %s variable type %d (%s)",
739                               psz_object, i_type & VLC_VAR_TYPE, psz_variable );
740                     E_(SSPush)( st, "" );
741                 }
742             }
743             else
744             {
745                 msg_Warn( p_intf, "vlc_var_get called without an object" );
746                 E_(SSPush)( st, "" );
747             }
748             free( psz_variable );
749             free( psz_object );
750
751             if( b_need_release && p_object != NULL )
752                 vlc_object_release( p_object );
753         }
754         else if( !strcmp( s, "vlc_config_set" ) )
755         {
756             char *psz_variable = E_(SSPop)( st );
757             int i_type = config_GetType( p_intf, psz_variable );
758
759             switch( i_type & VLC_VAR_TYPE )
760             {
761             case VLC_VAR_BOOL:
762             case VLC_VAR_INTEGER:
763                 config_PutInt( p_intf, psz_variable, E_(SSPopN)( st, vars ) );
764                 break;
765             case VLC_VAR_STRING:
766             case VLC_VAR_MODULE:
767             case VLC_VAR_FILE:
768             case VLC_VAR_DIRECTORY:
769             {
770                 char *psz_string = E_(SSPop)( st );
771                 config_PutPsz( p_intf, psz_variable, psz_string );
772                 free( psz_string );
773                 break;
774             }
775             case VLC_VAR_FLOAT:
776             {
777                 char *psz_string = E_(SSPop)( st );
778                 config_PutFloat( p_intf, psz_variable, atof(psz_string) );
779                 free( psz_string );
780                 break;
781             }
782             default:
783                 msg_Warn( p_intf, "vlc_config_set called on unknown var (%s)",
784                           psz_variable );
785             }
786             free( psz_variable );
787         }
788         else if( !strcmp( s, "vlc_config_get" ) )
789         {
790             char *psz_variable = E_(SSPop)( st );
791             int i_type = config_GetType( p_intf, psz_variable );
792
793             switch( i_type & VLC_VAR_TYPE )
794             {
795             case VLC_VAR_BOOL:
796             case VLC_VAR_INTEGER:
797                 E_(SSPushN)( st, config_GetInt( p_intf, psz_variable ) );
798                 break;
799             case VLC_VAR_STRING:
800             case VLC_VAR_MODULE:
801             case VLC_VAR_FILE:
802             case VLC_VAR_DIRECTORY:
803             {
804                 char *psz_string = config_GetPsz( p_intf, psz_variable );
805                 E_(SSPush)( st, psz_string );
806                 free( psz_string );
807                 break;
808             }
809             case VLC_VAR_FLOAT:
810             {
811                 char psz_string[20];
812                 snprintf( psz_string, sizeof(psz_string), "%f",
813                           config_GetFloat( p_intf, psz_variable ) );
814                 E_(SSPush)( st, psz_string );
815                 break;
816             }
817             default:
818                 msg_Warn( p_intf, "vlc_config_get called on unknown var (%s)",
819                           psz_variable );
820             }
821             free( psz_variable );
822         }
823         else if( !strcmp( s, "vlc_config_save" ) )
824         {
825             char *psz_module = E_(SSPop)( st );
826             int i_result;
827
828             if( !*psz_module )
829             {
830                 free( psz_module );
831                 psz_module = NULL;
832             }
833             i_result = config_SaveConfigFile( p_intf, psz_module );
834
835             if( psz_module != NULL )
836                 free( psz_module );
837             E_(SSPushN)( st, i_result );
838         }
839         else if( !strcmp( s, "vlc_config_reset" ) )
840         {
841             config_ResetAll( p_intf );
842         }
843         /* 6. playlist functions */
844         else if( !strcmp( s, "playlist_add" ) )
845         {
846             char *psz_name = E_(SSPop)( st );
847             char *mrl = E_(SSPop)( st );
848             char *tmp;
849             playlist_item_t *p_item;
850             int i_id;
851
852             tmp = E_(ToUTF8)( p_intf, psz_name );
853             free( psz_name );
854             psz_name = tmp;
855             tmp = E_(ToUTF8)( p_intf, mrl );
856             free( mrl );
857             mrl = tmp;
858
859             if( !*psz_name )
860             {
861                 p_item = E_(MRLParse)( p_intf, mrl, mrl );
862             }
863             else
864             {
865                 p_item = E_(MRLParse)( p_intf, mrl, psz_name );
866             }
867
868             if( p_item == NULL || p_item->input.psz_uri == NULL ||
869                  !*p_item->input.psz_uri )
870             {
871                 i_id = VLC_EGENERIC;
872                 msg_Dbg( p_intf, "invalid requested mrl: %s", mrl );
873             }
874             else
875             {
876                 i_id = playlist_AddItem( p_sys->p_playlist, p_item,
877                                          PLAYLIST_APPEND, PLAYLIST_END );
878                 msg_Dbg( p_intf, "requested mrl add: %s", mrl );
879             }
880             E_(SSPushN)( st, i_id );
881
882             free( mrl );
883             free( psz_name );
884         }
885         else if( !strcmp( s, "playlist_empty" ) )
886         {
887             playlist_LockClear( p_sys->p_playlist );
888             msg_Dbg( p_intf, "requested playlist empty" );
889         }
890         else if( !strcmp( s, "playlist_delete" ) )
891         {
892             int i_id = E_(SSPopN)( st, vars );
893             playlist_LockDelete( p_sys->p_playlist, i_id );
894             msg_Dbg( p_intf, "requested playlist delete: %d", i_id );
895         }
896         else if( !strcmp( s, "playlist_move" ) )
897         {
898             int i_newpos = E_(SSPopN)( st, vars );
899             int i_pos = E_(SSPopN)( st, vars );
900             if ( i_pos < i_newpos )
901             {
902                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos + 1 );
903             }
904             else
905             {
906                 playlist_Move( p_sys->p_playlist, i_pos, i_newpos );
907             }
908             msg_Dbg( p_intf, "requested to move playlist item %d to %d",
909                      i_pos, i_newpos);
910         }
911         else
912         {
913             E_(SSPush)( st, s );
914         }
915     }
916 }