*** VERSION 5.2.0 ***
[NeonServV5.git] / src / cmd_neonserv_extscript.c
1 /* cmd_neonserv_extscript.c - NeonServ v5.2
2  * Copyright (C) 2011  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonserv.h"
19
20 /*
21 * argv[0]      'toys' if it's a toy command (check if toys are enabled)
22 * argv[0-*]    script name & parameter patterns
23 * argv[argc-1] all arguments passed to the command
24 */
25
26 CMD_BIND(neonserv_cmd_extscript) {
27     int i, j;
28     char *args[MAXNUMPARAMS];
29     int argpos = 0;
30     char *next, *curr;
31     char command[1024];
32     int commandpos = 0;
33     char part[MAXLEN];
34     int partpos;
35     int escape_param;
36     int answere_channel = 0;
37     //check first arg
38     if(argc && !stricmp(argv[0], "toys")) {
39         if(!chan) return; //toys are not allowed via query
40         MYSQL_RES *res;
41         MYSQL_ROW row;
42         printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name));
43         res = mysql_use();
44         row = mysql_fetch_row(res);
45         if(!row || !strcmp(row[0], "0")) {
46             //disabled
47             reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name);
48             return;
49         } else if(!strcmp(row[0], "2"))
50             answere_channel = 1;
51         argc--;
52         argv++;
53     }
54     //parse arguments
55     if(argc < 2) return;
56     curr = argv[argc-1];
57     while(curr) {
58         next = strstr(curr, " ");
59         args[argpos++] = curr;
60         if(next) {
61             *next = '\0';
62             curr = next+1;
63         } else
64             curr = NULL;
65     }
66     //parse command pattern and build command
67     commandpos = sprintf(command, "%s", argv[0]);
68     for(i = 1; i < argc-1; i++) {
69         partpos = 0;
70         escape_param = 1;
71         if(argv[i][0] == '$') {
72             argv[i]++;
73             if(argv[i][strlen(argv[i])-1] == '-') {
74                 argv[i][strlen(argv[i])-1] = '\0';
75                 j = atoi(argv[i]);
76                 if(j <= argpos)
77                     partpos = sprintf(part, "%s", merge_argv(args, j-1, argpos));
78             } else if((j = atoi(argv[i])) > 0) {
79                 if(j <= argpos)
80                     partpos = sprintf(part, "%s", args[j-1]);
81             } else if(!strcmp(argv[i], "c")) {
82                 partpos = sprintf(part, "%s", (chan ? chan->name : ""));
83             } else if(!strcmp(argv[i], "n")) {
84                 partpos = sprintf(part, "%s", user->nick);
85             } else if(!strcmp(argv[i], "a")) {
86                 partpos = sprintf(part, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : ""));
87             } else if(!strcmp(argv[i], "access")) {
88                 if(chan)
89                     partpos = sprintf(part, "%d", getChannelAccess(user, chan, 0));
90             }
91         } else {
92             partpos = sprintf(part, "%s", argv[i]);
93             escape_param = 0;
94         }
95         //escape shell argument
96         command[commandpos++] = ' ';
97         if(escape_param) {
98             command[commandpos++] = '\'';
99             for(j = 0; j < partpos; j++) {
100                 if(part[j] == '\'') {
101                     command[commandpos++] = '\'';
102                     command[commandpos++] = '\\';
103                     command[commandpos++] = '\'';
104                     command[commandpos++] = '\'';
105                 } else
106                     command[commandpos++] = part[j];
107             }
108             command[commandpos++] = '\'';
109         } else
110             commandpos += sprintf(command + commandpos, " %s", part);
111     }
112     command[commandpos] = '\0';
113     //we should now have a valid command
114     FILE *fp;
115     fp = popen(command, "r");
116     if (fp) {
117         char *a;
118         while (fgets(command, 1024, fp) != NULL) {
119             if((a = strchr(command, '\n'))) 
120                 *a = '\0';
121             if(answere_channel) {
122                 putsock(client, "PRIVMSG %s :%s", chan->name, command);
123             } else
124                 reply(getTextBot(), user, "%s", command);
125         }
126         pclose(fp);
127     } else {
128         //error
129         reply(getTextBot(), user, "internal bot error - please contact an administrator!");
130         return;
131     }
132 }
133