Another year is about to end... So we have to update these damn copyright information :P
[PHP-P10.git] / Bots / JavaGod.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/JavaGod.class.php
21  *
22  * simple Java debugger...
23  *
24  */
25
26 class {$_NAME} extends Bot {
27         private $uplink;
28         private $bot, $execcache = array();
29         
30         public function load($uplink, $old = false) {
31                 $this->uplink = $uplink;
32                 if(!$old) {
33                         $nick = "Java";
34                         $ident = "Java";
35                         $host = "Services.WebGamesNet.net";
36                         $ip = "0::0";
37                         $realname = "Java Java Java Java Java";
38                         $modes = "ioknISD";
39                         $this->bot = $this->uplink->addUser($nick,$ident,$host,$ip,$modes,$realname);
40                         if(is_a($this->bot, "P10_User")) {
41                                 $this->uplink->join($this->bot, "#java", (P10_Channel::USERPRIV_OPED | P10_Channel::USERPRIV_VOICE));
42                                 $this->uplink->join($this->bot, "#dev", P10_Channel::USERPRIV_VOICE);
43                 $this->uplink->join($this->bot, "#CoderCom", P10_Channel::USERPRIV_VOICE);
44                         }
45                 } else {
46                         $this->bot = $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->execcache as $id => $entry) {
55                         fclose($entry['pipes'][1]);
56                         fclose($entry['pipes'][2]);
57                         proc_terminate($entry['proc'],9);
58                 }
59                 $this->execcache = array();
60                 if($rehash) {
61                         return $this->bot;
62                 } else {
63                         $this->uplink->delUser($this->bot, "Bye.");
64                 }
65         }
66         
67         public function loop() {
68                 foreach($this->execcache as $id => $entry) {
69                         if(!$this->checkstate($entry)) {
70                 unlink("tmp/Debug_".$entry['id'].".java");
71                 unlink("tmp/Debug_".$entry['id'].".class");
72                                 unset($this->execcache[$id]);
73                         }
74                 }
75         }
76         
77         function recive_privmsg($user, $channel, $message) {
78                 $opOnJavaChannel = false;
79                 $JavaChannel = P10_Channel::getChannelByName("#Java");
80                 if($JavaChannel) {
81                         $privs = $JavaChannel->getUserPrivs($user);
82                         $opOnJavaChannel = ($privs & P10_Channel::USERPRIV_OPED);
83                 }
84                 if(!$user->getModes()->hasMode('o') && !$opOnJavaChannel) return 0;
85                 $exp=explode(" ", $message, 2);
86                 switch (strtolower($exp[0])) {
87                         case "~java":
88                                 if(count($this->execcache) > 5) {
89                                         $this->uplink->notice($this->bot, $user, "too many running java 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                     $javacontent = file_get_contents("http://pastebin.com/download.php?i=".$pasteid);
99                     if(preg_match("#Unknown Paste ID!#i", $javacontent)) {
100                         $this->uplink->notice($this->bot, $user, "Unknown Paste ID!");
101                         return;
102                     }
103                     $javacode = "import java.*;
104                     @SuppressWarnings(\"unused\")
105                         public class Debug_".$entry['id']." {
106                             ".$javacontent."
107                         }
108                     ";
109                 } else {
110                     $javacode = "import java.*;
111                     @SuppressWarnings(\"unused\")
112                         public class Debug_".$entry['id']." {
113                             ".$exp[1]."
114                         }
115                     ";
116                 };
117                 $fp = fopen("tmp/Debug_".$entry['id'].".java", "w");
118                 fwrite($fp, $javacode);
119                 fclose($fp);
120                 $err = shell_exec("javac tmp/Debug_".$entry['id'].".java 2>&1");
121                 if($err) {
122                     $err=str_replace("\r","",$err);
123                     $lines=explode("\n",$err);
124                     $i=0;
125                     foreach($lines as $line) {
126                         if($line == "") continue;
127                         $i++;
128                         if($i>100) {
129                             $this->uplink->privmsg($this->bot, $entry['channel'], "too many lines!");
130                             break; 
131                         }
132                         $this->uplink->privmsg($this->bot, $entry['channel'], $line);
133                     }
134                 }
135                 if(!file_exists("tmp/Debug_".$entry['id'].".class")) {
136                     unlink("tmp/Debug_".$entry['id'].".java");
137                     break;
138                 }
139                                 $descriptor = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("pipe", "w"));
140                                 $entry['proc'] = proc_open('java -classpath tmp Debug_'.$entry['id'], $descriptor, $entry['pipes']);
141                                 if(!is_resource($entry['proc'])) {
142                                         $this->uplink->notice($this->bot, $user, "error while loading c!");
143                                         return;
144                                 }
145                                 $entry['time'] = time();
146                                 fclose($entry['pipes'][0]);
147                                 $this->execcache[] = $entry;
148                                 break;
149                 }
150         }
151         
152         function recive_quit($user, $reason) {
153                 if($user === $this->bot) {
154                         $this->load($this->uplink);
155                 }
156         }
157         
158         function checkstate($entry) {
159                 $data = proc_get_status($entry['proc']);
160                 if(!$data['running']) {
161                         $out="";
162                         while(!feof($entry['pipes'][1])) {
163                                 $out .= fgets($entry['pipes'][1], 128);
164                         }
165                         $eout="";
166                         while(!feof($entry['pipes'][2])) {
167                                 $eout .= fgets($entry['pipes'][2], 128);
168                         }
169                         if($out != "") {
170                                 $out=str_replace("\r","",$out);
171                                 $lines=explode("\n",$out);
172                                 $i=0;
173                                 foreach($lines as $line) {
174                     if($line == "") continue;
175                                         $i++;
176                                         if($i>1000) {
177                                                 $this->uplink->privmsg($this->bot, $entry['channel'], "too many lines!");
178                                                 break; 
179                                         }
180                                         $this->uplink->privmsg($this->bot, $entry['channel'], $line);
181                                 }
182                         }
183                         if($eout != "") {
184                                 $eout=str_replace("\r","",$eout);
185                                 $lines=explode("\n",$eout);
186                                 $i=0;
187                                 foreach($lines as $line) {
188                     if($line == "") continue;
189                                         $i++;
190                                         if($i>1000) { 
191                                                 $this->uplink->privmsg($this->bot, $entry['channel'], "too many lines!");
192                                                 break; 
193                                         }
194                                         $this->uplink->privmsg($this->bot, $entry['channel'], "\ 34".$line."\ 3");
195                                 }
196                         }
197                         fclose($entry['pipes'][1]);
198                         fclose($entry['pipes'][2]);
199                         proc_close($entry['proc']);
200                         return false;
201                 } else {
202                         if($entry['time']+10 > time()) {
203                                 return true;
204                         } else {
205                                 //TIMEOUT
206                                 if($entry['term']) {
207                                         fclose($entry['pipes'][1]);
208                                         fclose($entry['pipes'][2]);
209                                         proc_terminate($entry['proc'],9);
210                                         $this->uplink->privmsg($this->bot, $entry['channel'], "Java hard timeout. sending SIGKILL");
211                                         return false;
212                                 } else {
213                                         proc_terminate($entry['proc']);
214                                         $entry['term']=true;
215                                         $this->uplink->privmsg($this->bot, $entry['channel'], "Java timeout. (maximum of 10 seconds exceeded)  sending SIGTERM"); 
216                                         return true;
217                                 }
218                         }
219                 }
220         }
221         
222 }
223
224 ?>