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