added isLocalAddress method to IPAddr.class.php to check for local addresses (RFC1918...
[PHP-P10.git] / Bots / CGod.class.php
1 <?php
2 /******************************* PHP-P10 v2 *****************************
3  * Copyright (C) 2011-2012  Philipp Kreil (pk910)                       *
4  *                                                                      *
5  * This program is free software: you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation, either version 3 of the License, or    *
8  * (at your option) any later version.                                  *
9  *                                                                      *
10  * This program is distributed in the hope that it will be useful,      *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
13  * GNU General Public License for more details.                         *
14  *                                                                      *
15  * You should have received a copy of the GNU General Public License    *
16  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17  *                                                                      *
18  ************************************************************************
19  *
20  *  Bots/CGod.class.php
21  *
22  * simple C debugger...
23  *
24  */
25
26 class {$_NAME} extends Bot {
27         private $uplink;
28         private $c, $ccache = array();
29
30         public function load($uplink, $old = false) {
31                 $this->uplink = $uplink;
32                 if(!$old) {
33                         $nick = "C";
34                         $ident = "c";
35                         $host = "Services.WebGamesNet.net";
36                         $ip = "0::0";
37                         $realname = "C C C C C";
38                         $modes = "ioknISD";
39                         $this->c = $this->uplink->addUser($nick,$ident,$host,$ip,$modes,$realname);
40                         if(is_a($this->c, "P10_User")) {
41                                 $this->uplink->join($this->c, "#c", (P10_Channel::USERPRIV_OPED | P10_Channel::USERPRIV_VOICE));
42                                 $this->uplink->join($this->c, "#dev", P10_Channel::USERPRIV_VOICE);
43                                 $this->uplink->join($this->c, "#CoderCom", P10_Channel::USERPRIV_VOICE);
44                         }
45                 } else {
46                         $this->c = $old;
47                 }
48
49                 ModCMD::bind($this, BIND_CHANMSG, "recive_privmsg");
50                 ModCMD::bind($this, BIND_QUIT, "recive_quit");
51         }
52
53         public function unload($rehash = false) {
54                 foreach($this->ccache as $id => $c) {
55                         fclose($c['pipes'][1]);
56                         fclose($c['pipes'][2]);
57                         proc_terminate($c['proc'],9);
58                 }
59                 $this->ccache = array();
60                 if($rehash) {
61                         return $this->c;
62                 } else {
63                         $this->uplink->delUser($this->c, "Bye.");
64                 }
65         }
66
67         public function loop() {
68                 foreach($this->ccache as $id => $c) {
69                         if(!$this->checkstate($c)) {
70                                 unlink("tmp/debug_".$c['id'].".c");
71                                 unlink("tmp/debug_".$c['id']);
72                                 unset($this->ccache[$id]);
73                         }
74                 }
75         }
76
77         function recive_privmsg($user, $channel, $message) {
78                 $opOnCChannel = false;
79                 $CChannel = P10_Channel::getChannelByName("#C");
80                 if($CChannel) {
81                         $privs = $CChannel->getUserPrivs($user);
82                         $opOnCChannel = ($privs & P10_Channel::USERPRIV_OPED);
83                 }
84                 if(!$user->getModes()->hasMode('o') && !$opOnCChannel) return 0;
85                 $exp=explode(" ", $message, 2);
86                 switch (strtolower($exp[0])) {
87                         case "~c":
88                                 if(count($this->ccache) > 5) {
89                                         $this->uplink->notice($this->c, $user, "too many running c processes at the moment!");
90                                         return;
91                                 }
92                                 $entry=array();
93                                 $entry['channel'] = $channel;
94                                 $entry['id'] = rand(1, 999999);
95                                 if(preg_match("#pastebin\.com/([a-zA-Z0-9]*)$#i", $exp[1])) {
96                                         $pasteid = explode("/", $exp[1]);
97                                         $pasteid = $pasteid[count($pasteid)-1];
98                                         $codecontent = file_get_contents("http://pastebin.com/download.php?i=".$pasteid);
99                                         if(preg_match("#Unknown Paste ID!#i", $codecontent)) {
100                                                 $this->uplink->notice($this->bot, $user, "Unknown Paste ID!");
101                                                 return;
102                                         }
103                                         $code = "#include \"includes.h\"
104                     ".$codecontent;
105                                 } else {
106                                         $code = "#include \"includes.h\"
107                     ".$exp[1];
108                                 };
109                                 $fp = fopen("tmp/debug_".$entry['id'].".c", "w");
110                                 fwrite($fp, $code);
111                                 fclose($fp);
112                                 $err = shell_exec("gcc -o tmp/debug_".$entry['id']." tmp/debug_".$entry['id'].".c 2>&1");
113                                 if($err) {
114                                         $err=str_replace("\r","",$err);
115                                         $lines=explode("\n",$err);
116                                         $i=0;
117                                         foreach($lines as $line) {
118                                                 if($line == "") continue;
119                                                 $i++;
120                                                 if($i>100) {
121                                                         $this->uplink->privmsg($this->c, $entry['channel'], "too many lines!");
122                                                         break;
123                                                 }
124                                                 $this->uplink->privmsg($this->c, $entry['channel'], $line);
125                                         }
126                                 }
127                                 if(!file_exists("tmp/debug_".$entry['id'])) {
128                                         unlink("tmp/debug_".$entry['id'].".c");
129                                         break;
130                                 }
131                                 $descriptor = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("pipe", "w"));
132                                 $entry['proc'] = proc_open('tmp/debug_'.$entry['id'], $descriptor, $entry['pipes']);
133                                 if(!is_resource($entry['proc'])) {
134                                         $this->uplink->notice($this->c, $user, "error while loading c!");
135                                         return;
136                                 }
137                                 $entry['time'] = time();
138                                 fclose($entry['pipes'][0]);
139                                 $this->ccache[] = $entry;
140                                 break;
141                 }
142         }
143
144         function recive_quit($user, $reason) {
145                 if($user === $this->c) {
146                         $this->load($this->uplink);
147                 }
148         }
149
150         function checkstate($c) {
151                 $data = proc_get_status($c['proc']);
152                 if(!$data['running']) {
153                         $out="";
154                         while(!feof($c['pipes'][1])) {
155                                 $out .= fgets($c['pipes'][1], 128);
156                         }
157                         $eout="";
158                         while(!feof($c['pipes'][2])) {
159                                 $eout .= fgets($c['pipes'][2], 128);
160                         }
161                         if($out != "") {
162                                 $out=str_replace("\r","",$out);
163                                 $lines=explode("\n",$out);
164                                 $i=0;
165                                 foreach($lines as $line) {
166                                         if($line == "") continue;
167                                         $i++;
168                                         if($i>1000) {
169                                                 $this->uplink->privmsg($this->c, $c['channel'], "too many lines!");
170                                                 break;
171                                         }
172                                         $this->uplink->privmsg($this->c, $c['channel'], $line);
173                                 }
174                         }
175                         if($eout != "") {
176                                 $eout=str_replace("\r","",$eout);
177                                 $lines=explode("\n",$eout);
178                                 $i=0;
179                                 foreach($lines as $line) {
180                                         if($line == "") continue;
181                                         $i++;
182                                         if($i>1000) {
183                                                 $this->uplink->privmsg($this->c, $c['channel'], "too many lines!");
184                                                 break;
185                                         }
186                                         $this->uplink->privmsg($this->c, $c['channel'], "\ 34".$line."\ 3");
187                                 }
188                         }
189                         fclose($c['pipes'][1]);
190                         fclose($c['pipes'][2]);
191                         proc_close($c['proc']);
192                         return false;
193                 } else {
194                         if($c['time']+10 > time()) {
195                                 return true;
196                         } else {
197                                 //TIMEOUT
198                                 if($c['term']) {
199                                         fclose($c['pipes'][1]);
200                                         fclose($c['pipes'][2]);
201                                         proc_terminate($c['proc'],9);
202                                         $this->uplink->privmsg($this->c, $c['channel'], "c hard timeout. sending SIGKILL");
203                                         return false;
204                                 } else {
205                                         proc_terminate($c['proc']);
206                                         $c['term']=true;
207                                         $this->uplink->privmsg($this->c, $c['channel'], "c timeout. (maximum of 10 seconds exceeded)  sending SIGTERM");
208                                         return true;
209                                 }
210                         }
211                 }
212         }
213
214 }
215
216 ?>