added whois command
[ZNCAdmin.git] / zncadmin / ZNCServerV1.class.php
1 <?php
2 /* ZNCServerV1.class.php - ZNC Server Class - ZNCAdmin
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 $classinfo = array(
20         "name" => "ZNCServerV1",
21         "version" => 1.000,
22 );
23
24 class ZNCServerV1 {
25         private $host, $port;
26         private $connector;
27         
28         public function ZNCServerV1($host, $port, $connector = NULL) {
29                 $this->host = $host;
30                 $this->port = $port;
31                 if($connector == NULL)
32                         $connector = new HTTPConnector();
33                 $this->connector = $connector;
34         }
35
36     public function login($user, $pass) {
37         $post = array(
38             "user" => $user,
39             "pass" => $pass,
40             "submitted" => "1"
41         );
42         $this->connector->post("http://".$this->host.":".$this->port."/login", $post);
43         $http = $this->connector->get("http://".$this->host.":".$this->port."/?cookie_check=true");
44         $logged_in = !preg_match("/errorbar/i", $http);
45
46         return $logged_in;
47     }
48
49     public function getUserList() {
50         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/listusers");
51         $exp = explode('<div class="toptable">', $html);
52         $exp = explode('</div>', $exp[1]);
53         $exp = explode('<tbody>', $exp[0]);
54         $exp = explode('</tbody>', $exp[1]);
55         $list = explode('<tr class=', $exp[0]);
56         $userlist = array();
57         for($i = 1; $i < count($list); $i++) {
58             $userdata = array();
59             $exp = explode('<td>', $list[$i]);
60             $exp2 = explode('</td>', $exp[2]);
61             $userdata['user'] = $exp2[0];
62             $exp2 = explode('</td>', $exp[3]);
63             $userdata['server'] = $exp2[0];
64             $exp2 = explode('</td>', $exp[4]);
65             $userdata['clients'] = $exp2[0];
66             $userlist[] = $userdata;
67         }
68         return $userlist;
69     }
70
71     public function getSeenList() {
72         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/lastseen/");
73         $exp = explode('<div class="toptable">', $html);
74         $exp = explode('</div>', $exp[1]);
75         $exp = explode('<tbody>', $exp[0]);
76         $exp = explode('</tbody>', $exp[1]);
77         $list = explode('<tr class=', $exp[0]);
78         $seenlist = array();
79         for($i = 1; $i < count($list); $i++) {
80             $userdata = array();
81             $exp = explode('<td>', $list[$i]);
82
83             $exp2 = explode('</td>', $exp[1]);
84             $userdata['user'] = $exp2[0];
85             $exp2 = explode('</td>', $exp[2]);
86             $userdata['seen'] = $exp2[0];
87             $userdata['seen_unix'] = strtotime($exp2[0]);
88             $exp2 = explode('</td>', $exp[3]);
89             $userdata['info'] = $exp2[0];
90             $seenlist[] = $userdata;
91         }
92         return $seenlist;
93     }
94
95     /*
96     $settings array elements:
97         nick
98         altnick
99         ident
100     */
101     public function addZNC($username, $password, $settings, $servers, $modules, $netmodules, $others) {
102         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/adduser");
103         $exp = explode('name="_CSRF_Check" value="', $html);
104         $exp = explode('"', $exp[1]);
105         $csrf = $exp[0];
106         $post = array();
107         $post['_CSRF_Check'] = $csrf;
108         $post['submitted'] = '1';
109         //$post['doconnect'] = '1';
110         $post['user'] = $username;
111         $post['password'] = $password;
112         $post['password2'] = $password;
113         $post['nick'] = $settings['nick'];
114         $post['altnick'] = $settings['altnick'];
115         $post['ident'] = $settings['ident'];
116         $post['statusprefix'] = '*';
117         $post['loadmod'] = array();
118         foreach($modules as $name => $args) {
119             $post['loadmod'][] = $name;
120             if($args != "")
121                 $post['modargs_'.$name] = $args;
122         }
123
124         foreach($others as $name => $value) {
125             $post[$name] = $value;
126         }
127
128         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/global/webadmin/adduser", $post);
129
130         if(!preg_match("/Invalid Submission/i", $html)) {
131             if(!$this->addNetwork($username, $settings, $servers, $netmodules, $others)) {
132                 return false;
133             }
134             return !preg_match("/Invalid Submission/i", $html);
135         }
136         return !preg_match("/Invalid Submission/i", $html);
137     }
138
139     public function addNetwork($username, $settings, $servers, $modules, $others) {
140         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/addnetwork?user=".$username);
141         $exp = explode('name="_CSRF_Check" value="', $html);
142         $exp = explode('"', $exp[1]);
143         $csrf = $exp[0];
144         $post = array();
145         $post['_CSRF_Check'] = $csrf;
146         $post['submitted'] = '1';
147         $post['network'] = 'default';
148         $post['nick'] = $settings['nick'];
149         $post['altnick'] = $settings['altnick'];
150         $post['ident'] = $settings['ident'];
151         $post['servers'] = implode("\n", $servers);
152         $post['doconnect'] = '1';
153         $post['floodprotection'] = '1';
154         $post['floodrate'] = '1.0';
155         $post['floodburst'] = '4';
156         $post['user'] = $username;
157                 
158                 $post['loadmod'] = array();
159         foreach($modules as $name => $args) {
160             $post['loadmod'][] = $name;
161             if($args != "")
162                 $post['modargs_'.$name] = $args;
163         }
164
165         foreach($others as $name => $value) {
166             $post[$name] = $value;
167         }
168
169         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/global/webadmin/addnetwork", $post);
170         return !preg_match("/Invalid Submission/i", $html);
171     }
172
173     public function delZNC($username) {
174         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/deluser?user=".$username);
175         $exp = explode('name="_CSRF_Check" value="', $html);
176         $exp = explode('"', $exp[1]);
177         $csrf = $exp[0];
178         $post = array();
179         $post['_CSRF_Check'] = $csrf;
180         $post['submitted'] = '1';
181         $post['user'] = $username;
182         $this->connector->post("http://".$this->host.":".$this->port."/mods/global/webadmin/deluser", $post);
183     }
184
185     private function parseHTMLFields($html, &$post) {
186         preg_match_all("#<input (.*?)/?>#", $html, $matches);
187         foreach($matches[1] as $input) {
188             if(preg_match("#name=\"(.*?)\"#", $input, $match))
189                                 $name = $match[1];
190                         else
191                                 $name = null;
192                         if(preg_match("#type=\"(.*?)\"#", $input, $match))
193                                 $type = $match[1];
194                         else
195                                 $type = null;
196                         if(preg_match("#value=\"(.*?)\"#", $input, $match))
197                                 $value = $match[1];
198                         else
199                                 $value= null;
200             switch($type) {
201                 case "text":
202                 case "hidden":
203                     break;
204                 case "checkbox":
205                     if(preg_match("# checked=#", $input, $match)) {
206                         $value = ($value ? $value : "1");
207                     } else
208                         $value = null;
209                     break;
210                 default:
211                     $value = null;
212             }
213             if($name && $value !== null) {
214                 if(array_key_exists($name, $post)) {
215                     if(!is_array($post[$name])) {
216                         $cvalue = $post[$name];
217                         $post[$name] = array();
218                         $post[$name][] = $cvalue;
219                     }
220                     $post[$name][] = $value;
221                 } else
222                     $post[$name] = $value;
223             }
224         }
225         //textareas
226         $textareas = explode("<textarea ", $html);
227         for($i = 1; $i < count($textareas); $i++) {
228             $exp = explode(">", $textareas[$i]);
229             $name = explode("name=\"", $exp[0]);
230             $name = explode("\"", $name[1]);
231             $name = $name[0];
232             $content = explode("</textarea", $exp[1]);
233             $content = $content[0];
234             $post[$name] = $content;
235         }
236         //select boxes
237         $selectboxes = explode("<select ", $html);
238         for($j = 1; $j < count($selectboxes); $j++) {
239             $exp = explode(">", $selectboxes[$j], 2);
240             $name = explode("name=\"", $exp[0]);
241             $name = explode("\"", $name[1]);
242             $name = $name[0];
243             $content = explode("</select", $exp[1]);
244             $content = $content[0];
245             preg_match_all("<option ([^\>]*)>", $content, $matches);
246             foreach($matches[0] as $input) {
247                 $fields = array(0 => "");
248                 $esc = false; $str = false;
249                 $fieldid = 0;
250                 for($i = 0; $i < strlen($input); $i++) {
251                     if($esc) {
252                         $esc = false;
253                         $fields[$fieldid] .= $input[$i];
254                         continue;
255                     }
256                     if($input[$i] == "\\") {
257                         $esc = true;
258                     }
259                     if($input[$i] == "\"") {
260                         $str = !$str;
261                         continue;
262                     }
263                     if($input[$i] == " " && !$str) {
264                         $fields[++$fieldid] = "";
265                         continue;
266                     }
267                     $fields[$fieldid] .= $input[$i];
268                 }
269                 $cfields = array();
270                 foreach($fields as $field) {
271                     $fieldexp = explode("=", $field, 2);
272                     if(count($fieldexp) != 2) continue;
273                     $cfields[$fieldexp[0]] = $fieldexp[1];
274                 }
275                 if(!$post[$name] || $cfields['selected']) {
276                     $post[$name] = $cfields['value'];
277                 }
278             }
279         }
280     }
281
282     public function editZNC($username, $password = NULL, $new_servers = NULL, $add_modules = NULL, $del_modules = NULL, $others = NULL) {
283         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/edituser?user=".$username);
284         if(preg_match("/No such username/i", $html)) return false;
285         $post = array();
286         $post['loadmod'] = array();
287         $this->parseHTMLFields($html, $post);
288         if($password) {
289             $post['password'] = $password;
290             $post['password2'] = $password;
291         }
292         if($new_servers) {
293             $post['servers'] = implode("\n", $new_servers);
294         }
295         if($add_modules) {
296             foreach($add_modules as $name => $args) {
297                 $post['loadmod'][] = $name;
298                 if($args != "")
299                     $post['modargs_'.$name] = $args;
300             }
301         }
302         if($del_modules) {
303             foreach($del_modules as $name => $args) {
304                 foreach($post['loadmod'] as $index => $mod) {
305                     if(strtolower($mod) == strtolower($name))
306                         unset($post['loadmod'][$index]);
307                 }
308             }
309         }
310         if($others) {
311             foreach($others as $name => $value) {
312                 $post[$name] = $value;
313             }
314         }
315         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/global/webadmin/edituser?user=".$username, $post);
316         return !preg_match("/Invalid Submission/i", $html);
317     }
318
319     public function blockZNC($username, $block) {
320         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/edituser?user=".$username);
321         if(preg_match("/No such username/i", $html)) return ERR_USER_NOT_FOUND;
322         $post = array();
323         $post['user'] = $username;
324         $post['loadmod'] = array();
325         $this->parseHTMLFields($html, $post);
326         if(!$post['embed_blockuser_presented']) return ERR_MODULE_NOT_FOUND;
327         if(!($post['embed_blockuser_block'] xor $block)) return ERR_OK;
328         $post['embed_blockuser_block'] = ($block ? "1" : null);
329         if(!$block) {
330             $post['doconnect'] = 1;
331         }
332         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/global/webadmin/edituser", $post);
333         $handle = fopen('/home/srvx/neonserv/log.txt', 'a');
334         fwrite($handle, "$html\r\n");
335         fclose($handle);
336         return (preg_match("/Invalid Submission/i", $html) ? ERR_UNKNOWN : ERR_OK);
337     }
338
339     public function simulZNC($username, $raw, &$errmsg, $server = true) {
340         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/user/send_raw/");
341         if(preg_match("/Not Found/i", $html)) return ERR_MODULE_NOT_FOUND;
342         $exp = explode('name="_CSRF_Check" value="', $html);
343         $exp = explode('"', $exp[1]);
344         $csrf = $exp[0];
345         $post = array();
346         $post['_CSRF_Check'] = $csrf;
347         $post['submitted'] = '1';
348         $post['network'] = $username.'/default';
349         $post['send_to'] = ($server ? "server" : "client");
350         $post['line'] = $raw;
351         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/user/send_raw/", $post);
352         return ERR_OK;
353     }
354
355     public function addChan($username, $channel, $key = NULL, $buffer = NULL) {
356         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/addchan?user=".$username.'&network=default');
357         if(preg_match("/No such username/i", $html)) return false;
358         $exp = explode('name="_CSRF_Check" value="', $html);
359         $exp = explode('"', $exp[1]);
360         $csrf = $exp[0];
361         $post = array();
362         $post['_CSRF_Check'] = $csrf;
363         $post['submitted'] = '1';
364         $post['network'] = 'default';
365         $post['user'] = $username;
366         $post['name'] = $channel;
367         $exp = explode('name="key" value="', $html);
368         $exp = explode('"', $exp[1]);
369         $default_key = $exp[0];
370         $post['key'] = ($key ? $key : $default_key);
371         $exp = explode('name="buffercount" value="', $html);
372         $exp = explode('"', $exp[1]);
373         $default_buffer = $exp[0];
374         $post['buffercount'] = ($buffer ? $buffer : $default_buffer);
375         $post['defmodes'] = '';
376         $post['save'] = 'true';
377         $post['autoclearchanbuffer'] = 'true';
378         $this->connector->post("http://".$this->host.":".$this->port."/mods/global/webadmin/addchan?user=".$username.'&network=default', $post);
379     }
380         
381         public function getUserInfo($username, $loadNetInfos = false) {
382                 $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/edituser?user=".$username);
383         if(preg_match("/No such username/i", $html)) return false;
384         $info = array();
385         $info['loadmod'] = array();
386         $this->parseHTMLFields($html, $info);
387                 
388                 { // parse network list
389                         $info['networks'] = array();
390                         $netlist = explode("<h3>Networks</h3>", $html);
391                         $netlist = explode("<tbody>", $netlist[1], 2);
392                         $netlist = explode("</tbody>", $netlist[1], 2);
393                         $netlist = explode("</tr>", $netlist[0]);
394                         foreach($netlist as $net) {
395                                 if(preg_match_all("#<td>(.*?)</td>#sm", $net, $matches)) {
396                                         $network = array();
397                                         $network['name'] = $matches[1][1];
398                                         $network['clients'] = $matches[1][2];
399                                         $network['server'] = $matches[1][3];
400                                         $network['nick'] = $matches[1][4];
401                                         
402                                         if($loadNetInfos) {
403                                                 $html2 = $this->connector->get("http://".$this->host.":".$this->port."/mods/global/webadmin/editnetwork?user=".$username."&network=".$network['name']);
404                                                 if(!preg_match("/No such username/i", $html2)) {
405                                                         $settings = array();
406                                                         $settings['loadmod'] = array();
407                                                         $this->parseHTMLFields($html2, $settings);
408                                                         $network['settings'] = $settings;
409                                                 }
410                                         }
411                                         
412                                         $info['networks'][] = $network;
413                                 }
414                         }
415                 }
416                 
417                 return $info;
418         }
419         
420 }
421
422 ?>