added cmd_extscript
[NeonServV5.git] / src / cmd_neonserv_extscript.c
1 /* cmd_neonserv_extscript.c - NeonServ v5.1
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 answere_channel = 0;
36     //check first arg
37     if(argc && !stricmp(argv[0], "toys")) {
38         if(!chan) return; //toys are not allowed via query
39         MYSQL_RES *res;
40         MYSQL_ROW row;
41         printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name));
42         res = mysql_use();
43         row = mysql_fetch_row(res);
44         if(!row || !strcmp(row[0], "0")) {
45             //disabled
46             reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name);
47             return;
48         } else if(!strcmp(row[0], "2"))
49             answere_channel = 1;
50         argc--;
51         argv++;
52     }
53     //parse arguments
54     if(argc < 2) return;
55     curr = argv[argc-1];
56     while(curr) {
57         next = strstr(curr, " ");
58         args[argpos++] = curr;
59         if(next) {
60             *next = '\0';
61             curr = next+1;
62         } else
63             curr = NULL;
64     }
65     //parse command pattern and build command
66     commandpos = sprintf(command, "%s", argv[0]);
67     for(i = 1; i < argc-1; i++) {
68         partpos = 0;
69         if(argv[i][0] == '$') {
70             argv[i]++;
71             if(argv[i][strlen(argv[i])-1] == '-') {
72                 argv[i][strlen(argv[i])-1] = '\0';
73                 j = atoi(argv[i]);
74                 if(j <= argpos)
75                     partpos = sprintf(part, "%s", merge_argv(args, j-1, argpos));
76             } else if((j = atoi(argv[i])) > 0) {
77                 if(j <= argpos)
78                     partpos = sprintf(part, "%s", args[j-1]);
79             } else if(!strcmp(argv[i], "c")) {
80                 partpos = sprintf(part, "%s", (chan ? chan->name : ""));
81             } else if(!strcmp(argv[i], "n")) {
82                 partpos = sprintf(part, "%s", user->nick);
83             } else if(!strcmp(argv[i], "a")) {
84                 partpos = sprintf(part, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : ""));
85             } else if(!strcmp(argv[i], "access")) {
86                 if(chan)
87                     partpos = sprintf(part, "%d", getChannelAccess(user, chan, 0));
88             }
89         } else {
90             partpos = sprintf(part, "%s", argv[i]);
91         }
92         //escape shell argument
93         command[commandpos++] = ' ';
94         command[commandpos++] = '\'';
95         for(j = 0; j < partpos; j++) {
96             if(part[j] == '\'') {
97                 command[commandpos++] = '\'';
98                 command[commandpos++] = '\\';
99                 command[commandpos++] = '\'';
100                 command[commandpos++] = '\'';
101             } else
102                 command[commandpos++] = part[j];
103         }
104         command[commandpos++] = '\'';
105     }
106     command[commandpos] = '\0';
107     //we should now have a valid command
108     FILE *fp;
109     fp = popen(command, "r");
110     if (fp) {
111         char *a;
112         while (fgets(command, 1024, fp) != NULL) {
113             if((a = strchr(command, '\n'))) 
114                 *a = '\0';
115             if(answere_channel) {
116                 putsock(client, "PRIVMSG %s :%s", chan->name, command);
117             } else
118                 reply(getTextBot(), user, "%s", command);
119         }
120         pclose(fp);
121     } else {
122         //error
123         reply(getTextBot(), user, "internal bot error - please contact an administrator!");
124         return;
125     }
126 }
127