fixed ZNCServer::parseHTMLFields(): parse select boxes
[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/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['clients'] = $exp2[0];
62                         $exp2 = explode('</td>', $exp[4]);
63                         $userdata['server'] = $exp2[0];
64                         $exp2 = explode('</td>', $exp[5]);
65                         $userdata['nick'] = $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/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, $others) {
102         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/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['servers'] = implode("\n", $servers);
118         $post['loadmod'] = array();
119         foreach($modules as $name => $args) {
120             $post['loadmod'][] = $name;
121             if($args != "")
122                 $post['modargs_'.$name] = $args;
123         }
124         foreach($others as $name => $value) {
125             $post[$name] = $value;
126         }
127         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/webadmin/adduser", $post);
128         return !preg_match("/Invalid Submission/i", $html);
129     }
130         
131     public function delZNC($username) {
132         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/webadmin/deluser?user=".$username);
133                 $exp = explode('name="_CSRF_Check" value="', $html);
134         $exp = explode('"', $exp[1]);
135         $csrf = $exp[0];
136         $post = array();
137         $post['_CSRF_Check'] = $csrf;
138         $post['submitted'] = '1';
139         $post['user'] = $username;
140         $this->connector->post("http://".$this->host.":".$this->port."/mods/webadmin/deluser", $post);
141     }
142     
143     private function parseHTMLFields($html, &$post) {
144         preg_match_all("<input ([^\>]*)>", $html, $matches);
145         foreach($matches[0] as $input) {
146             $fields = array(0 => "");
147             $esc = false; $str = false;
148             $fieldid = 0;
149             for($i = 0; $i < strlen($input); $i++) {
150                 if($esc) {
151                     $esc = false;
152                     $fields[$fieldid] .= $input[$i];
153                     continue;
154                 }
155                 if($input[$i] == "\\") {
156                     $esc = true;
157                 }
158                 if($input[$i] == "\"") {
159                     $str = !$str;
160                     continue;
161                 }
162                 if($input[$i] == " " && !$str) {
163                     $fields[++$fieldid] = "";
164                     continue;
165                 }
166                 $fields[$fieldid] .= $input[$i];
167             }
168             $cfields = array();
169             foreach($fields as $field) {
170                 $fieldexp = explode("=", $field, 2);
171                 if(count($fieldexp) != 2) continue;
172                 $cfields[$fieldexp[0]] = $fieldexp[1];
173             }
174             $name = $cfields['name'];
175             switch($cfields['type']) {
176                 case "text":
177                 case "hidden":
178                     $value = $cfields['value'];
179                     break;
180                 case "checkbox":
181                     if($cfields['checked']) {
182                         $value = ($cfields['value'] ? $cfields['value'] : "1");
183                     } else 
184                         $value = null;
185                     break;
186                 default:
187                     $value = null;
188             }
189             if($name && $value) {
190                 if(array_key_exists($name, $post)) {
191                     if(!is_array($post[$name])) {
192                         $cvalue = $post[$name];
193                         $post[$name] = array();
194                         $post[$name][] = $cvalue;
195                     }
196                     $post[$name][] = $value;
197                 } else
198                     $post[$name] = $value;
199             }
200         }
201         //textareas
202         $textareas = explode("<textarea ", $html);
203         for($i = 1; $i < count($textareas); $i++) {
204             $exp = explode(">", $textareas[$i]);
205             $name = explode("name=\"", $exp[0]);
206             $name = explode("\"", $name[1]);
207             $name = $name[0];
208             $content = explode("</textarea", $exp[1]);
209             $content = $content[0];
210             $post[$name] = $content;
211         }
212         //select boxes
213         $selectboxes = explode("<select ", $html);
214         for($j = 1; $j < count($selectboxes); $j++) {
215             $exp = explode(">", $selectboxes[$j], 2);
216             $name = explode("name=\"", $exp[0]);
217             $name = explode("\"", $name[1]);
218             $name = $name[0];
219             $content = explode("</select", $exp[1]);
220             $content = $content[0];
221             preg_match_all("<option ([^\>]*)>", $content, $matches);
222             foreach($matches[0] as $input) {
223                 $fields = array(0 => "");
224                 $esc = false; $str = false;
225                 $fieldid = 0;
226                 for($i = 0; $i < strlen($input); $i++) {
227                     if($esc) {
228                         $esc = false;
229                         $fields[$fieldid] .= $input[$i];
230                         continue;
231                     }
232                     if($input[$i] == "\\") {
233                         $esc = true;
234                     }
235                     if($input[$i] == "\"") {
236                         $str = !$str;
237                         continue;
238                     }
239                     if($input[$i] == " " && !$str) {
240                         $fields[++$fieldid] = "";
241                         continue;
242                     }
243                     $fields[$fieldid] .= $input[$i];
244                 }
245                 $cfields = array();
246                 foreach($fields as $field) {
247                     $fieldexp = explode("=", $field, 2);
248                     if(count($fieldexp) != 2) continue;
249                     $cfields[$fieldexp[0]] = $fieldexp[1];
250                 }
251                 if(!$post[$name] || $cfields['selected']) {
252                     $post[$name] = $cfields['value'];
253                 }
254             }
255         }
256     }
257     
258     public function editZNC($username, $password = NULL, $new_servers = NULL, $add_modules = NULL, $del_modules = NULL, $others = NULL) {
259         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/webadmin/edituser?user=".$username);
260         if(preg_match("/No such username/i", $html)) return false;
261         $post = array();
262         $post['loadmod'] = array();
263         $this->parseHTMLFields($html, $post);
264         if($password) {
265             $post['password'] = $password;
266             $post['password2'] = $password;
267         }
268         if($new_servers) {
269             $post['servers'] = implode("\n", $new_servers);
270         }
271         foreach($add_modules as $name => $args) {
272             $post['loadmod'][] = $name;
273             if($args != "")
274                 $post['modargs_'.$name] = $args;
275         }
276         foreach($del_modules as $name => $args) {
277             foreach($post['loadmod'] as $index => $mod) {
278                 if(strtolower($mod) == strtolower($name))
279                     unset($post['loadmod'][$index]);
280             }
281         }
282         foreach($others as $name => $value) {
283             $post[$name] = $value;
284         }
285         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/webadmin/edituser?user=".$username, $post);
286         return !preg_match("/Invalid Submission/i", $html);
287     }
288     
289     public function blockZNC($username, $block) {
290         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/webadmin/edituser?user=".$username);
291         if(preg_match("/No such username/i", $html)) return ERR_USER_NOT_FOUND;
292         $post = array();
293         $post['loadmod'] = array();
294         $this->parseHTMLFields($html, $post);
295         if(!$post['embed_blockuser_presented']) return ERR_MODULE_NOT_FOUND;
296         if(!($post['embed_blockuser_block'] xor $block)) return ERR_OK;
297         $post['embed_blockuser_block'] = ($block ? "1" : null);
298         if(!$block) {
299             $post['doconnect'] = 1;
300         }
301         $html = $this->connector->post("http://".$this->host.":".$this->port."/mods/webadmin/edituser?user=".$username, $post);
302         return (preg_match("/Invalid Submission/i", $html) ? ERR_UNKNOWN : ERR_OK);
303     }
304     
305     public function simulZNC($username, $raw, &$errmsg, $server = true) {
306         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/send_raw/");
307         if(preg_match("/Not Found/i", $html)) return ERR_MODULE_NOT_FOUND;
308                 $exp = explode('name="_CSRF_Check" value="', $html);
309         $exp = explode('"', $exp[1]);
310         $csrf = $exp[0];
311         $post = array();
312         $post['_CSRF_Check'] = $csrf;
313         $post['submitted'] = '1';
314         $post['user'] = $username;
315         $post['send_to'] = ($server ? "server" : "client");
316         $post['line'] = $raw;
317         $this->connector->post("http://".$this->host.":".$this->port."/mods/send_raw/", $post);
318         return ERR_OK;
319     }
320     
321     public function addChan($username, $channel, $key = NULL, $buffer = NULL) {
322         $html = $this->connector->get("http://".$this->host.":".$this->port."/mods/webadmin/addchan?user=".$username);
323         if(preg_match("/No such username/i", $html)) return false;
324                 $exp = explode('name="_CSRF_Check" value="', $html);
325         $exp = explode('"', $exp[1]);
326         $csrf = $exp[0];
327         $post = array();
328         $post['_CSRF_Check'] = $csrf;
329         $post['submitted'] = '1';
330         $post['user'] = $username;
331         $post['name'] = $channel;
332         $exp = explode('name="key" value="', $html);
333         $exp = explode('"', $exp[1]);
334         $default_key = $exp[0];
335         $post['key'] = ($key ? $key : $default_key);
336         $exp = explode('name="buffercount" value="', $html);
337         $exp = explode('"', $exp[1]);
338         $default_buffer = $exp[0];
339         $post['buffercount'] = ($buffer ? $buffer : $default_buffer);
340         $post['save'] = 'true';
341         $this->connector->post("http://".$this->host.":".$this->port."/mods/webadmin/addchan?user=".$username, $post);
342     }
343     
344 }
345
346 ?>