added scriptpaste.com support
[PHP-P10.git] / Bots / PHPGod.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/PHPGod.class.php
21  *
22  * simple PHP debugger...
23  *
24  */
25
26 class {$_NAME} extends Bot {
27         private $uplink;
28         private $php, $phpcache = array();
29
30         public function load($uplink, $old = false) {
31                 $this->uplink = $uplink;
32                 if(!$old) {
33                         $nick = "PHP";
34                         $ident = "php";
35                         $host = "Services.WebGamesNet.net";
36                         $ip = "0::0";
37                         $realname = "PHP PHP PHP PHP PHP";
38                         $modes = "ioknISD";
39                         $this->php = $this->uplink->addUser($nick,$ident,$host,$ip,$modes,$realname);
40                         if(is_a($this->php, "P10_User")) {
41                                 $this->uplink->join($this->php, "#php", (P10_Channel::USERPRIV_OPED | P10_Channel::USERPRIV_VOICE));
42                                 $this->uplink->join($this->php, "#dev", P10_Channel::USERPRIV_VOICE);
43                                 $this->uplink->join($this->php, "#CoderCom", P10_Channel::USERPRIV_VOICE);
44                         }
45                 } else {
46                         $this->php = $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->phpcache as $id => $php) {
55                         fclose($php['pipes'][1]);
56                         fclose($php['pipes'][2]);
57                         proc_terminate($php['proc'],9);
58                 }
59                 $this->phpcache = array();
60                 if($rehash) {
61                         return $this->php;
62                 } else {
63                         $this->uplink->delUser($this->php, "Bye.");
64                 }
65         }
66
67         public function loop() {
68                 foreach($this->phpcache as $id => $php) {
69                         if(!$this->checkstate($php)) {
70                                 unset($this->phpcache[$id]);
71                         }
72                 }
73         }
74
75         function recive_privmsg($user, $channel, $message) {
76                 $opOnPHPChannel = false;
77                 $PHPChannel = P10_Channel::getChannelByName("#PHP");
78                 if($PHPChannel) {
79                         $privs = $PHPChannel->getUserPrivs($user);
80                         $opOnPHPChannel = ($privs & P10_Channel::USERPRIV_OPED);
81                 }
82                 if(!$user->getModes()->hasMode('o') && !$opOnPHPChannel) return 0;
83                 $exp=explode(" ", $message, 2);
84                 switch (strtolower($exp[0])) {
85                         case "~php":
86                                 if(count($this->phpcache) > 5) {
87                                         $this->uplink->notice($this->php, $user, "too many running php processes at the moment!");
88                                         return;
89                                 }
90                                 $entry=array();
91                                 $entry['channel'] = $channel;
92                                 $descriptor = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("pipe", "w"));
93                                 $entry['proc'] = proc_open('php', $descriptor, $entry['pipes']);
94                                 if(!is_resource($entry['proc'])) {
95                                         $this->uplink->notice($this->php, $user, "error while loading php!");
96                                         return;
97                                 }
98                                 $entry['time'] = time();
99                                 if(preg_match("#pastebin\.com/([a-zA-Z0-9]*)$#i", $exp[1])) {
100                                         $pasteid = explode("/", $exp[1]);
101                                         $pasteid = $pasteid[count($pasteid)-1];
102                                         $codecontent = file_get_contents("http://pastebin.com/download.php?i=".$pasteid);
103                                         if(preg_match("#Unknown Paste ID!#i", $codecontent)) {
104                                                 $this->uplink->notice($this->bot, $user, "Unknown Paste ID!");
105                                                 return;
106                                         }
107                                         $code = $codecontent;
108                 } elseif(preg_match("#scriptpaste\.(com|de)/([a-zA-Z0-9]*)$#i", $exp[1])) {
109                                         $pasteid = explode("/", $exp[1]);
110                                         $pasteid = $pasteid[count($pasteid)-1];
111                                         $codecontent = file_get_contents("http://scriptpaste.com/".$pasteid."/download");
112                                         $code = $codecontent;
113                                 } else {
114                                         $code = "<"."?php " . $exp[1] . " ?".">";
115                                 };
116                                 fwrite($entry['pipes'][0], $code);
117                                 fclose($entry['pipes'][0]);
118                                 $this->phpcache[] = $entry;
119                                 break;
120                 }
121         }
122
123         function recive_quit($user, $reason) {
124                 if($user === $this->php) {
125                         $this->load($this->uplink);
126                 }
127         }
128
129         function checkstate($php) {
130                 $data = proc_get_status($php['proc']);
131                 if(!$data['running']) {
132                         $out="";
133                         while(!feof($php['pipes'][1])) {
134                                 $out .= fgets($php['pipes'][1], 128);
135                         }
136                         $eout="";
137                         while(!feof($php['pipes'][2])) {
138                                 $eout .= fgets($php['pipes'][2], 128);
139                         }
140                         if($out != "") {
141                                 $out=str_replace("\r","",$out);
142                                 $lines=explode("\n",$out);
143                                 $i=0;
144                                 foreach($lines as $line) {
145                                         $i++;
146                                         if($i>1000) {
147                                                 $this->uplink->privmsg($this->php, $php['channel'], "too many lines!");
148                                                 break;
149                                         }
150                                         $this->uplink->privmsg($this->php, $php['channel'], $line);
151                                 }
152                         }
153                         if($eout != "") {
154                                 $eout=str_replace("\r","",$eout);
155                                 $lines=explode("\n",$eout);
156                                 $i=0;
157                                 foreach($lines as $line) {
158                                         $i++;
159                                         if($i>1000) {
160                                                 $this->uplink->privmsg($this->php, $php['channel'], "too many lines!");
161                                                 break;
162                                         }
163                                         $this->uplink->privmsg($this->php, $php['channel'], "\ 34".$line."\ 3");
164                                 }
165                         }
166                         fclose($php['pipes'][1]);
167                         fclose($php['pipes'][2]);
168                         proc_close($php['proc']);
169                         return false;
170                 } else {
171                         if($php['time']+10 > time()) {
172                                 return true;
173                         } else {
174                                 //TIMEOUT
175                                 if($php['term']) {
176                                         fclose($php['pipes'][1]);
177                                         fclose($php['pipes'][2]);
178                                         proc_terminate($php['proc'],9);
179                                         $this->uplink->privmsg($this->php, $php['channel'], "php hard timeout. sending SIGKILL");
180                                         return false;
181                                 } else {
182                                         proc_terminate($php['proc']);
183                                         $php['term']=true;
184                                         $this->uplink->privmsg($this->php, $php['channel'], "php timeout. (maximum of 10 seconds exceeded)  sending SIGTERM");
185                                         return true;
186                                 }
187                         }
188                 }
189         }
190
191 }
192
193 ?>