669fca5a00e73976a87bca76aa276309e819a232
[ZNCAdmin.git] / zncadmin.php
1 <?php
2 /* czncadmin.php - main script - 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 error_reporting(E_ALL & ~E_NOTICE);
20 require_once("zncadmin/HTTPConnector.class.php");
21 require_once("zncadmin/ZNCServer.class.php");
22 require_once("zncadmin/Table.class.php");
23
24 require_once("config.inc.php");
25
26 /*
27 $argv[1]   subcommand
28 */
29
30 function error($msg) {
31     echo"\00304ZNCAdmin error:\003 ".$msg."\n";
32 }
33
34 if(strtolower($argv[1]) == "force") {
35     $argv = array_slice($argv, 1);
36     $force = true;
37 } else
38     $force = false;
39
40 switch(strtolower($argv[1])) {
41     case "add":
42         zncadmin_add();
43         break;
44     case "del":
45         zncadmin_del();
46         break;
47     case "search":
48         zncadmin_search();
49         break;
50         case "seen":
51         zncadmin_seen();
52         break;
53     case "resetpass":
54         zncadmin_resetpass();
55         break;
56     case "simul":
57         zncadmin_simul();
58         break;
59     default:
60         error("invalid subcommand '".$argv[1]."'");
61         break;
62 }
63
64 function preg_prepare($string,$wildcards = true,$pregstart = "#") {
65     $in = array("\\","^",".","$","|","(",")","[","]","+","?","{","}",",",$pregstart);
66     if(!$wildcards) array_push($in,"*");
67     $out = array();
68     foreach($in as $item) {
69         $out[] = "\\".$item;
70     }
71     if($wildcards) { 
72         array_push($in,"*");
73         array_push($out,"(.*)");
74     }
75     $string = str_replace($in,$out,$string);
76     return $string;
77 }
78
79 function generate_password() {
80     $password_chars = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
81     $password_length = 10;
82     $password = 0;
83     srand();
84     for($i = 0; $i < $password_length; $i++) {
85         $password .= $password_chars[rand(0, strlen($password_chars))-1];
86     }
87     return $password;
88 }
89
90 function str2time($duration) {
91     $str="0";
92     $dur=0;
93     $mult=1;
94     for($i=0;$i<strlen($duration);$i++) {
95         if(is_numeric($duration[$i])) {
96             $str.=$duration[$i];
97         } else if($duration[$i] != " ") {
98             switch ($duration[$i]) {
99                 case "y":
100                     $mult=365*24*60*60;
101                     break;
102                 case "M":
103                     $mult=31*24*60*60;
104                     break;
105                 case "w":
106                     $mult=7*24*60*60;
107                     break;
108                 case "d":
109                     $mult=24*60*60;
110                     break;
111                 case "h":
112                     $mult=60*60;
113                     break;
114                 case "m":
115                     $mult=60;
116                     break;
117                 case "s":
118                     $mult=1;
119                     break;
120                 case "*":
121                     $mult=0;
122                     break;
123                 default:
124                     return null;
125                     break;
126             }
127             $dur=$dur+($str*$mult);
128             $str="0";
129         }
130     }
131     $dur=$dur+$str;
132     return $dur;
133 }
134
135 /***********************************************************
136  *                   ZNCAdmin SUBCOMMANDS                  *
137  ***********************************************************/
138
139 //SUBCOMMAND: search
140 function zncadmin_search() {
141     global $argv, $zncservers;
142     $mask = $argv[2];
143     if(!$mask) {
144         error("missing mask parameter");
145         return;
146     }
147     $extraflags = array();
148     if($argv[3]) {
149         $extraflags = explode(" ", $argv[3]);
150     }
151     $mask = preg_prepare($mask);
152     $table = new Table(5);
153     $table->add("Server", "User", "Clients", "Server", "Nick");
154     $count = 0;
155     foreach($zncservers as $zncserver) {
156         $zncserver['conn'] = new ZNCServer($zncserver['host'], $zncserver['port']);
157         $zncserver['conn']->login($zncserver['auser'], $zncserver['apass']);
158         foreach($zncserver['conn']->getUserList() as $user) {
159             $skip = false;
160             foreach($extraflags as $flag) {
161                 //some additional flags ;)
162                 if($flag[0] == '-') {
163                     $flag = substr($flag, 1);
164                     $positive = false;
165                 } else if($flag[0] == '+') {
166                     $flag = substr($flag, 1);
167                     $positive = true;
168                 } else
169                     $positive = true;
170                 $flag = explode("=", $flag, 2);
171                 $flagval = $flag[1];
172                 switch (strtolower($flag[0])) {
173                     case "online":
174                         $skip = (($user['clients'] > 0) != $positive);
175                         break;
176                     case "connected":
177                         $skip = (($user['server'] == "-N/A-") == $positive);
178                         break;
179                     case "server":
180                         $skip = (preg_match("#^".preg_prepare($flagval)."$#i", $user['server']) != $positive);
181                         break;
182                     case "server_regex":
183                         $skip = (preg_match("#^".$flagval."$#i", $user['server']) != $positive);
184                         break;
185                     case "nick":
186                         $skip = (preg_match("#^".preg_prepare($flagval)."$#i", $user['nick']) != $positive);
187                         break;
188                     case "nick_regex":
189                         $skip = (preg_match("#^".$flagval."$#i", $user['nick']) != $positive);
190                         break;
191                     case "znc":
192                         $skip = (preg_match("#^".preg_prepare($flagval)."$#i", $zncserver['name']) != $positive);
193                         break;
194                     default:
195                         
196                         break;
197                 }
198                 if($skip)
199                     break;
200             }
201             if($skip) continue;
202             if(preg_match("#^".$mask."$#i", $user['user'])) {
203                 $table->add($zncserver['name'], $user['user'], $user['clients'], $user['server'], $user['nick']);
204                 $count++;
205             }
206         }
207     }
208     if($count) {
209         foreach($table->end() as $line) {
210             echo$line."\n";
211         }
212         echo"Found \002".$count."\002 users.\n";
213     } else {
214         echo "no user matching \002".$argv[2]."\002 found.\n";
215     }
216 }
217
218 //SUBCOMMAND: search
219 function zncadmin_seen() {
220     global $argv, $zncservers;
221         $time = $argv[2];
222         $over_time = true;
223         if($time[0] == '>' || $time[0] == '<') {
224                 if($time[0] == '<') $over_time = false;
225                 $time = substr($time, 1);
226         }
227         $time = time() - str2time($time);
228     $mask = $argv[3];
229     if(!$time) {
230         error("missing time parameter");
231         return;
232     }
233     if($mask)
234         $mask = preg_prepare($mask);
235     else
236         $mask = "(.*)";
237     $table = new Table(4);
238     $table->add("Server", "User", "Seen", "Info");
239     $found = false;
240     foreach($zncservers as $zncserver) {
241         $zncserver['conn'] = new ZNCServer($zncserver['host'], $zncserver['port']);
242         $zncserver['conn']->login($zncserver['auser'], $zncserver['apass']);
243         foreach($zncserver['conn']->getSeenList() as $user) {
244             if(preg_match("#^".$mask."$#i", $user['user']) && (($over_time && $user['seen_unix'] < $time) || (!$over_time && $user['seen_unix'] > $time))) {
245                 $table->add($zncserver['name'], $user['user'], $user['seen'], $user['info']);
246                 $found = true;
247             }
248         }
249     }
250     if($found) {
251         foreach($table->end() as $line) {
252             echo$line."\n";
253         }
254     } else {
255         echo "no user matching \002".$argv[2]."\002 found.\n";
256     }
257 }
258
259 //SUBCOMMAND: del
260 function zncadmin_del() {
261     global $argv, $zncservers, $force;
262     $username = strtolower($argv[2]);
263     if(!$username) {
264         error("missing username");
265         return;
266     }
267     $delusers = array();
268     foreach($zncservers as $zncserver) {
269         if($argv[3] && (strtolower($argv[3]) != strtolower($zncserver['name']))) continue;
270         if($username == strtolower($zncserver['auser'])) continue;
271         $zncserver['conn'] = new ZNCServer($zncserver['host'], $zncserver['port']);
272         $zncserver['conn']->login($zncserver['auser'], $zncserver['apass']);
273         foreach($zncserver['conn']->getUserList() as $user) {
274             if(strtolower($user['user']) == $username) {
275                 $delusers[] = array("server" => $zncserver, "user" => $user);
276             }
277         }
278     }
279     if(count($delusers) > 1) {
280         error($argv[2]." exists on multiple servers! please add the server name, the user should be removed from.");
281         echo"Found User on following Servers:\n";
282         foreach($delusers as $server) {
283             echo "\002".$server['server']['name']."\002  Server: ".$server['user']['server']."  Nick: ".$server['user']['nick']."  Clients: ".$server['user']['clients']."\n";
284         }
285     } else if(count($delusers) == 0) {
286         error("Couldn't find an user called \002".$argv[2]."\002.");
287     } else if($delusers[0]['server']['protected'] && !$force) {
288         error("Access denied\n");
289     } else {
290         $deluser = $delusers[0];
291         $deluser['server']['conn']->delZNC($deluser['user']['user']);
292         echo "Deleted \002".$deluser['user']['user']."\002 from Server \002".$deluser['server']['name']."\002\n";
293         echo"/log\n";
294     }
295 }
296
297 //SUBCOMMAND: add
298 function zncadmin_add() {
299     global $argv, $zncservers, $add_settings, $force;
300     $username = strtolower($argv[2]);
301     if(!$username) {
302         error("missing username");
303         return;
304     }
305     $addserv = array();
306     $priority = 1;
307     foreach($zncservers as $zncserver) {
308         if($argv[3] && (strtolower($argv[3]) != strtolower($zncserver['name']))) continue;
309         if(!$argv[3] && $zncserver['priority'] < $priority) continue;
310         $zncserver['conn'] = new ZNCServer($zncserver['host'], $zncserver['port']);
311         $zncserver['conn']->login($zncserver['auser'], $zncserver['apass']);
312         $zncserver['users'] = $zncserver['conn']->getUserList();
313         $existing = false;
314         foreach($zncserver['users'] as $user) {
315             if(strtolower($user['user']) == $username) $existing = true;
316         }
317         if(!$existing && count($zncserver['users']) < $zncserver['maxznc']) {
318             if($zncserver['priority'] > $priority) {
319                 $priority = $zncserver['priority'];
320                 $addserv = array();
321             }
322             $addserv[] = $zncserver;
323         }
324     }
325     if(count($addserv) > 1) {
326         //select server with lowest user count
327         $usercount = count($addserv[0]['users']);
328         $selected = 0;
329         for($i = 1; $i < count($addserv); $i++) {
330             if(count($addserv[$i]['users']) < $usercount) {
331                 $usercount = count($addserv[$i]['users']);
332                 $selected = $i;
333             }
334         }
335         $addserv = $addserv[$selected];
336     } else if(count($addserv) == 0) {
337         error("Couldn't find a server the user could be added to.");
338         return;
339     } else {
340         $addserv = $addserv[0];
341     }
342     $password = generate_password();
343     $settings = array();
344     $settings['nick'] = $argv[2];
345     $settings['altnick'] = $argv[2]."`";
346     $settings['ident'] = $username;
347     $ret = $addserv['conn']->addZNC($argv[2], $password, $settings, $add_settings['servers'], $add_settings['modules'], $add_settings['other']);
348     if($ret) {
349         echo "Added user ".$argv[2]." to Server ".$addserv['name'].".\n";
350         echo "  Server Host: ".$addserv['public']."  Port: ".$addserv['port']."  SSL Port: ".$addserv['sslport']."\n";
351         echo "  Password: ".$password."\n";
352         echo "[mIRC]\n";
353         echo " /server -a ".$addserv['public']." -p ".$addserv['port']." -g KryptonZNC -w ".$argv[2].":".$password." -d KryptonZNC\n";
354         echo " /AS addmask *@*.free-bnc.de\n";
355         echo " /AS addmask *@*.krypton-bouncer.de\n";
356         echo " /server -m KryptonZNC\n";
357         echo"/log\n";
358         $addserv['conn']->addChan($argv[2], "#Krypton");
359     } else
360         error("Error while adding user.");
361 }
362
363 //SUBCOMMAND: resetpass
364 function zncadmin_resetpass() {
365     global $argv, $zncservers, $force;
366     $username = strtolower($argv[2]);
367     if(!$username) {
368         error("missing username");
369         return;
370     }
371     $delusers = array();
372     foreach($zncservers as $zncserver) {
373         if($argv[3] && (strtolower($argv[3]) != strtolower($zncserver['name']))) continue;
374         if($username == strtolower($zncserver['auser'])) continue;
375         $zncserver['conn'] = new ZNCServer($zncserver['host'], $zncserver['port']);
376         $zncserver['conn']->login($zncserver['auser'], $zncserver['apass']);
377         foreach($zncserver['conn']->getUserList() as $user) {
378             if(strtolower($user['user']) == $username) {
379                 $delusers[] = array("server" => $zncserver, "user" => $user);
380             }
381         }
382     }
383     if(count($delusers) > 1) {
384         error($argv[2]." exists on multiple servers! please add the server name the user, the password should be resetted, is on.");
385         echo"Found User on following Servers:\n";
386         foreach($delusers as $server) {
387             echo "\002".$server['server']['name']."\002  Server: ".$server['user']['server']."  Nick: ".$server['user']['nick']."  Clients: ".$server['user']['clients']."\n";
388         }
389     } else if(count($delusers) == 0) {
390         error("Couldn't find an user called \002".$argv[2]."\002.");
391     } else if($delusers[0]['server']['protected'] && !$force) {
392         error("Access denied\n");
393     } else {
394         $deluser = $delusers[0];
395         $password = generate_password();
396         $deluser['server']['conn']->editZNC($deluser['user']['user'], $password);
397         echo "Changed password of \002".$deluser['user']['user']."\002 on Server ".$deluser['server']['name']." to \002".$password."\002\n";
398         echo"/log\n";
399     }
400 }
401
402 //SUBCOMMAND: simul
403 function zncadmin_simul() {
404     global $argv, $zncservers, $force;
405     $username = strtolower($argv[2]);
406     $server = strtolower($argv[3]);
407     $raw = $argv[4];
408     if(!$username) {
409         error("missing username");
410         return;
411     }
412     if($server) {
413         $found = false;
414         foreach($zncservers as $zncserver) {
415             if(strtolower($server) == strtolower($zncserver['name'])) {
416                 $found = true;
417                 break;
418             }
419         }
420         if(!$found) {
421             $raw = $argv[3]." ".$raw;
422             $server = null;
423         }
424     }
425     if(!$raw) {
426         error("missing raw");
427         return;
428     }
429     $delusers = array();
430     foreach($zncservers as $zncserver) {
431         if($server && (strtolower($server) != strtolower($zncserver['name']))) continue;
432         if($username == strtolower($zncserver['auser'])) continue;
433         $zncserver['conn'] = new ZNCServer($zncserver['host'], $zncserver['port']);
434         $zncserver['conn']->login($zncserver['auser'], $zncserver['apass']);
435         foreach($zncserver['conn']->getUserList() as $user) {
436             if(strtolower($user['user']) == $username) {
437                 $delusers[] = array("server" => $zncserver, "user" => $user);
438             }
439         }
440     }
441     if(count($delusers) > 1) {
442         error($argv[2]." exists on multiple servers! please add the server name the user should be simuled on.");
443         echo"Found User on following Servers:\n";
444         foreach($delusers as $server) {
445             echo "\002".$server['server']['name']."\002  Server: ".$server['user']['server']."  Nick: ".$server['user']['nick']."  Clients: ".$server['user']['clients']."\n";
446         }
447     } else if(count($delusers) == 0) {
448         error("Couldn't find an user called \002".$argv[2]."\002.");
449     } else if($delusers[0]['server']['protected'] && !$force) {
450         error("Access denied\n");
451     } else {
452         $deluser = $delusers[0];
453         $deluser['server']['conn']->simulZNC($deluser['user']['user'], $raw);
454         echo "Simuled \002".$deluser['user']['user']."\002 on Server ".$deluser['server']['name'].": ".$raw."\n";
455         echo"/log\n";
456     }
457 }
458
459 ?>