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