Till Brehm
2014-10-27 1e67c170df357c0d0831d223e93a6512d84c523e
commit | author | age
e2d6ed 1 <?php
436ed8 2
e2d6ed 3 /*
436ed8 4 Copyright (c) 2007, Till Brehm, projektfarm Gmbh
e2d6ed 5 All rights reserved.
T 6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10     * Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 class system{
32
3b4c28 33     var $FILE = '/root/ispconfig/scripts/lib/classes/ispconfig_system.lib.php';
55da90 34     var $server_id;
B 35     var $server_conf;
36     var $data;
64ea56 37     var $min_uid = 500;
MC 38     var $min_gid = 500;
39     
55da90 40     /**
B 41      * Construct for this class
42      *
43      * @return system
44      */
7fe908 45
MC 46
55da90 47     public function system(){
cea1e5 48         //global $go_info;
7fe908 49         //$this->server_id = $go_info['isp']['server_id'];
MC 50         //$this->server_conf = $go_info['isp']['server_conf'];
51         $this->server_conf['passwd_datei'] = '/etc/passwd';
52         $this->server_conf['shadow_datei'] = '/etc/shadow';
53         $this->server_conf['group_datei'] = '/etc/group';
55da90 54     }
7fe908 55
MC 56
57
55da90 58     /**
B 59      * Get the hostname from the server
60      *
61      * @return string
62      */
63     public function hostname(){
3b4c28 64         $dist = $this->server_conf['dist'];
7fe908 65
MC 66         ob_start();
67         passthru('hostname');
68         $hostname = ob_get_contents();
69         ob_end_clean();
55da90 70         $hostname = trim($hostname);
7fe908 71         ob_start();
MC 72         if(!strstr($dist, 'freebsd')){
73             passthru('dnsdomainname');
74         } else {
75             passthru('domainname');
76         }
77         $domainname = ob_get_contents();
78         ob_end_clean();
79         $domainname = trim($domainname);
80         if($domainname != ""){
81             if(!strstr($hostname, $domainname)) $hostname .= ".".$domainname;
82         }
83         return $hostname;
55da90 84     }
7fe908 85
MC 86
87
55da90 88     /**
B 89      * Add an user to the system
7fe908 90      *
55da90 91      */
B 92     public function adduser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort = '*'){
93         global $app;
7fe908 94         if($this->is_user($user_username)){
MC 95             return false;
96         } else {
97             if(trim($user_username) != '') {
98                 $user_datei = $this->server_conf['passwd_datei'];
99                 $shadow_datei = $this->server_conf['shadow_datei'];
100                 $shell = realpath($shell);
101                 if(trim($passwort) == '') $passwort = '*';
102                 $new_user = "\n$user_username:x:$uid:$gid:$username:$homedir:$shell\n";
103                 $app->log->msg('USER: '.$new_user);
104                 $app->file->af($user_datei, $new_user);
105                 if($shadow_datei == '/etc/shadow'){
106                     $datum = time();
107                     $tage = floor($datum/86400);
108                     $new_passwd = "\n$user_username:$passwort:$tage:0:99999:7:::\n";
109                 } else {
110                     $new_passwd = "\n$user_username:$passwort:$uid:$gid::0:0:$username:$homedir:$shell\n";
111                 }
112                 $app->file->af($shadow_datei, $new_passwd);
55da90 113                 // TB: leere Zeilen entfernen
7fe908 114                 $app->file->remove_blank_lines($shadow_datei);
MC 115                 $app->file->remove_blank_lines($user_datei);
116                 // TB: user Sortierung deaktiviert
117                 //$this->order_users_groups();
118                 if($shadow_datei != '/etc/shadow'){
119                     $app->file->af($shadow_datei, "\n");
55da90 120                     // TB: leere Zeilen entfernen
7fe908 121                     $app->file->remove_blank_lines($shadow_datei);
55da90 122                     $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__);
7fe908 123                 }
MC 124                 return true;
125             }
126         }
55da90 127     }
7fe908 128
MC 129
130
131
132
55da90 133     /**
B 134      * Update users when someone edit it
135      *
136      */
137     function updateuser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort = '*'){
138         //* First delete the users
139         $this->deluser($user_username);
140         //* Add the user again
7fe908 141         $this->adduser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort);
55da90 142     }
7fe908 143
MC 144
145
146
147
55da90 148     /**
B 149      * Lock the user
150      *
151      */
152     function deactivateuser($user_username){
153         $passwort = str_rot13($this->getpasswd($user_username));
7fe908 154         $user_attr = $this->get_user_attributes($user_username);
MC 155         $uid = $user_attr['uid'];
156         $gid = $user_attr['gid'];
157         $username = $user_attr['name'];
158         $homedir = $user_attr['homedir'];
159         $shell = '/dev/null';
160         $this->deluser($user_username);
161         $this->adduser($user_username, $uid, $gid, $username, $homedir, $shell, $passwort);
55da90 162     }
7fe908 163
MC 164
55da90 165     /**
B 166      * Delete a user from the system
167      *
168      */
169     function deluser($user_username){
170         global $app;
7fe908 171         if($this->is_user($user_username)){
MC 172             $user_datei = $this->server_conf['passwd_datei'];
173             $shadow_datei = $this->server_conf['shadow_datei'];
174             $users = $app->file->rf($user_datei);
175             $lines = explode("\n", $users);
176             if(is_array($lines)){
177                 $num_lines = sizeof($lines);
178                 for($i=0;$i<$num_lines;$i++){
179                     if(trim($lines[$i]) != ''){
180                         list($f1, ) = explode(':', $lines[$i]);
181                         if($f1 != $user_username) $new_lines[] = $lines[$i];
182                     }
183                 }
184                 $new_users = implode("\n", $new_lines);
185                 $app->file->wf($user_datei, $new_users);
186                 unset($new_lines);
187                 unset($lines);
188                 unset($new_users);
189             }
190             $app->file->remove_blank_lines($user_datei);
191
192             $passwds = $app->file->rf($shadow_datei);
193             $lines = explode("\n", $passwds);
194             if(is_array($lines)){
195                 $num_lines = sizeof($lines);
196                 for($i=0;$i<$num_lines;$i++){
197                     if(trim($lines[$i]) != ''){
198                         list($f1, ) = explode(':', $lines[$i]);
199                         if($f1 != $user_username) $new_lines[] = $lines[$i];
200                     }
201                 }
202                 $new_passwds = implode("\n", $new_lines);
203                 $app->file->wf($shadow_datei, $new_passwds);
204                 unset($new_lines);
205                 unset($lines);
206                 unset($new_passwds);
207             }
208             $app->file->remove_blank_lines($shadow_datei);
209
210             $group_file = $app->file->rf($this->server_conf['group_datei']);
211             $group_file_lines = explode("\n", $group_file);
212             foreach($group_file_lines as $group_file_line){
213                 if(trim($group_file_line) != ''){
214                     list($f1, $f2, $f3, $f4) = explode(':', $group_file_line);
215                     $group_users = explode(',', str_replace(' ', '', $f4));
216                     if(in_array($user_username, $group_users)){
217                         $g_users = array();
218                         foreach($group_users as $group_user){
219                             if($group_user != $user_username) $g_users[] = $group_user;
220                         }
221                         $f4 = implode(',', $g_users);
222                     }
223                     $new_group_file[] = $f1.':'.$f2.':'.$f3.':'.$f4;
224                 }
225             }
226             $new_group_file = implode("\n", $new_group_file);
227             $app->file->wf($this->server_conf['group_datei'], $new_group_file);
228             // TB: auskommentiert
229             //$this->order_users_groups();
230
231             if($shadow_datei != '/etc/shadow'){
232                 $app->file->af($shadow_datei, "\n");
233                 $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__);
234             }
235             return true;
236         } else {
237             return false;
238         }
55da90 239     }
7fe908 240
MC 241
242
243
244
55da90 245     /**
B 246      * Add a usergroup to the system
247      *
248      */
249     function addgroup($group, $gid, $members = ''){
250         global $app;
7fe908 251         if($this->is_group($group)){
MC 252             return false;
253         } else {
254             $group_datei = $this->server_conf['group_datei'];
255             $shadow_datei = $this->server_conf['shadow_datei'];
256             $new_group = "\n$group:x:$gid:$members\n";
257             $app->file->af($group_datei, $new_group);
258
259             // TB: auskommentiert
260             //$this->order_users_groups();
261             if($shadow_datei != '/etc/shadow'){
262                 $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__);
263             }
264             return true;
265         }
55da90 266     }
7fe908 267
MC 268
269
270
271
55da90 272     /**
B 273      * Update usersgroup in way to delete and add it again
274      *
275      */
276     function updategroup($group, $gid, $members = ''){
277         $this->delgroup($group);
7fe908 278         $this->addgroup($group, $gid, $members);
55da90 279     }
7fe908 280
MC 281
282
283
284
55da90 285     /**
B 286      * Delete a usergroup from the system
287      *
288      */
289     function delgroup($group){
290         global $app;
7fe908 291         if($this->is_group($group)){
MC 292             $group_datei = $this->server_conf['group_datei'];
293             $shadow_datei = $this->server_conf['shadow_datei'];
294             $groups = $app->file->rf($group_datei);
295             $lines = explode("\n", $groups);
296             if(is_array($lines)){
297                 $num_lines = sizeof($lines);
298                 for($i=0;$i<$num_lines;$i++){
299                     if(trim($lines[$i]) != ''){
300                         list($f1, ) = explode(':', $lines[$i]);
301                         if($f1 != $group) $new_lines[] = $lines[$i];
302                     }
303                 }
304                 $new_groups = implode("\n", $new_lines);
305                 $app->file->wf($group_datei, $new_groups);
306                 unset($new_lines);
307                 unset($lines);
308                 unset($new_groups);
309             }
310             // TB: auskommentiert
311             //$this->order_users_groups();
312             if($shadow_datei != '/etc/shadow'){
313                 $app->log->caselog("pwd_mkdb $shadow_datei &> /dev/null", $this->FILE, __LINE__);
314             }
315             return true;
316         } else {
317             return false;
318         }
55da90 319     }
7fe908 320
MC 321
55da90 322     /**
B 323      * Order usergroups
324      *
325      */
326     function order_users_groups(){
327         global $app;
7fe908 328         $user_datei = $this->server_conf['passwd_datei'];
MC 329         $shadow_datei = $this->server_conf['shadow_datei'];
330         $group_datei = $this->server_conf['group_datei'];
331
332         $groups = $app->file->no_comments($group_datei);
333         $lines = explode("\n", $groups);
334         if(is_array($lines)){
335             foreach($lines as $line){
336                 if(trim($line) != ''){
337                     list($f1, $f2, $f3, $f4) = explode(':', $line);
338                     $arr[$f3] = $line;
339                 }
340             }
341         }
342         ksort($arr);
343         reset($arr);
344         if($shadow_datei != '/etc/shadow'){
345             $app->file->wf($group_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0)."\n");
346         }else {
347             $app->file->wf($group_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0));
348         }
349         unset($arr);
350
351         $users = $app->file->no_comments($user_datei);
352         $lines = explode("\n", $users);
353         if(is_array($lines)){
354             foreach($lines as $line){
355                 if(trim($line) != ""){
356                     list($f1, $f2, $f3, ) = explode(':', $line);
357                     if($f1 != 'toor'){
358                         $arr[$f3] = $line;
359                     } else {
360                         $arr[70000] = $line;
361                     }
362                 }
363             }
364         }
365         ksort($arr);
366         reset($arr);
367         $app->file->wf($user_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0));
368         unset($arr);
369
370         $passwds = $app->file->no_comments($shadow_datei);
371         $lines = explode("\n", $passwds);
372         if(is_array($lines)){
373             foreach($lines as $line){
374                 if(trim($line) != ''){
375                     list($f1, $f2, $f3, ) = explode(':', $line);
376                     if($f1 != 'toor'){
377                         $uid = $this->getuid($f1);
378                         if(!is_bool($uid)) $arr[$uid] = $line;
379                     } else {
380                         $arr[70000] = $line;
381                     }
382                 }
383             }
384         }
385         ksort($arr);
386         reset($arr);
387         $app->file->wf($shadow_datei, $app->file->remove_blank_lines(implode("\n", $arr), 0));
388         unset($arr);
55da90 389     }
7fe908 390
MC 391
392
393
394
55da90 395     /**
B 396      * Find a user / group id
397      *
398      */
399     function find_uid_gid($min, $max){
400         global $app;
7fe908 401         if($min < $max && $min >= 0 && $max >= 0 && $min <= 65536 && $max <= 65536 && is_int($min) && is_int($max)){
MC 402             for($i=$min;$i<=$max;$i++){
403                 $uid_arr[$i] = $gid_arr[$i] = 1;
404             }
405             $user_datei = $this->server_conf['passwd_datei'];
406             $group_datei = $this->server_conf['group_datei'];
407
408             $users = $app->file->no_comments($user_datei);
409             $lines = explode("\n", $users);
410             if(is_array($lines)){
411                 foreach($lines as $line){
412                     if(trim($line) != ''){
413                         list($f1, $f2, $f3, $f4, $f5, $f6, $f7) = explode(':', $line);
414                         if($f3 >= $min && $f3 <= $max) unset($uid_arr[$f3]);
415                     }
416                 }
417                 if(!empty($uid_arr)){
418                     foreach($uid_arr as $key => $val){
419                         $uids[] = $key;
420                     }
421                     $min_uid = min($uids);
422                     unset($uid_arr);
423                 } else {
424                     return false;
425                 }
426             }
427
428             $groups = $app->file->no_comments($group_datei);
429             $lines = explode("\n", $groups);
430             if(is_array($lines)){
431                 foreach($lines as $line){
432                     if(trim($line) != ''){
433                         list($f1, $f2, $f3, $f4) = explode(':', $line);
434                         if($f3 >= $min && $f3 <= $max) unset($gid_arr[$f3]);
435                     }
436                 }
437                 if(!empty($gid_arr)){
438                     foreach($gid_arr as $key => $val){
439                         $gids[] = $key;
440                     }
441                     $min_gid = min($gids);
442                     unset($gid_arr);
443                 } else {
444                     return false;
445                 }
446             }
447
448             $result = array_intersect($uids, $gids);
449             $new_id = (max($result));
450             unset($uids);
451             unset($gids);
452             unset($result);
453             if($new_id <= $max){
454                 return $new_id;
455             } else {
456                 return false;
457             }
458         } else {
459             return false;
460         }
55da90 461     }
7fe908 462
MC 463
464
465
466
55da90 467     /**
B 468      * Check if the users is really a user into the system
469      *
470      */
471     function is_user($user){
472         global $app;
7fe908 473         $user_datei = $this->server_conf['passwd_datei'];
MC 474         $users = $app->file->no_comments($user_datei);
475         $lines = explode("\n", $users);
476         if(is_array($lines)){
55da90 477             foreach($lines as $line){
7fe908 478                 if(trim($line) != ''){
MC 479                     list($f1, $f2, $f3, $f4, $f5, $f6, $f7) = explode(':', $line);
480                     if($f1 == $user) return true;
481                 }
482             }
483         }
484         return false;
55da90 485     }
7fe908 486
MC 487
488
489
490
55da90 491     /**
B 492      * Check if the group is on this system
493      *
494      */
495     function is_group($group){
496         global $app;
7fe908 497         $group_datei = $this->server_conf['group_datei'];
MC 498         $groups = $app->file->no_comments($group_datei);
499         $lines = explode("\n", $groups);
500         if(is_array($lines)){
501             foreach($lines as $line){
502                 if(trim($line) != ""){
503                     list($f1, $f2, $f3, $f4) = explode(':', $line);
504                     if($f1 == $group) return true;
505                 }
506             }
507         }
508         return false;
55da90 509     }
7fe908 510
89a57f 511     /*
T 512     // Alternative implementation of the is_group function. Should be faster then the old one To be tested.
513     function is_group($group) {
514     $groupfile = '/etc/group';
515     if(is_file($groupfile)) {
516         $handle = fopen ($groupfile, "r");
517         while (!feof($handle)) {
518             $line = trim(fgets($handle, 4096));
519             if($line != ""){
520                 $parts = explode(":", $line);
521                 if($parts[0] == $group) {
522                     fclose ($handle);
523                     return true;
524                 }
525             }
526         }
527         fclose ($handle);
528     }
529     return false;
530     }
531     */
7fe908 532
55da90 533     function root_group(){
B 534         global $app;
7fe908 535         $group_datei = $this->server_conf['group_datei'];
MC 536         $groups = $app->file->no_comments($group_datei);
537         $lines = explode("\n", $groups);
538         if(is_array($lines)){
539             foreach($lines as $line){
540                 if(trim($line) != ''){
541                     list($f1, $f2, $f3, $f4) = explode(':', $line);
542                     if($f3 == 0) return $f1;
543                 }
544             }
545         }
546         return false;
55da90 547     }
7fe908 548
MC 549
550
551
552
55da90 553     /**
B 554      * Get the groups of an user
555      *
556      */
557     function get_user_groups($username){
558         global $app;
7fe908 559         $user_groups = array();
MC 560         $group_datei = $this->server_conf['group_datei'];
561         $groups = $app->file->no_comments($group_datei);
562         $lines = explode("\n", $groups);
563         if(is_array($lines)){
564             foreach($lines as $line){
565                 if(trim($line) != ''){
566                     list($f1, $f2, $f3, $f4) = explode(':', $line);
567                     if(intval($f3) < intval($this->server_conf['groupid_von']) && trim($f1) != 'users'){
568                         $tmp_group_users = explode(',', str_replace(' ', '', $f4));
569                         if(in_array($username, $tmp_group_users) && trim($f1) != '') $user_groups[] = $f1;
570                         unset($tmp_group_users);
571                     }
572                 }
573             }
574         }
575         if(!empty($user_groups)) return implode(',', $user_groups);
576         return '';
55da90 577     }
7fe908 578
MC 579
580
581
582
55da90 583     /**
B 584      * Get a user password
585      *
586      */
587     function getpasswd($user){
588         global $app;
7fe908 589         if($this->is_user($user)){
MC 590             $shadow_datei = $this->server_conf['shadow_datei'];
591             $passwds = $app->file->no_comments($shadow_datei);
592             $lines = explode("\n", $passwds);
593             if(is_array($lines)){
594                 foreach($lines as $line){
595                     if(trim($line) != ''){
596                         list($f1, $f2, ) = explode(':', $line);
597                         if($f1 == $user) return $f2;
598                     }
599                 }
600             }
601         } else {
602             return false;
603         }
55da90 604     }
7fe908 605
MC 606
607
608
609
55da90 610     /**
B 611      * Get the user id from an user
612      *
613      */
614     function getuid($user){
615         global $app;
7fe908 616         if($this->is_user($user)){
MC 617             $user_datei = $this->server_conf['passwd_datei'];
618             $users = $app->file->no_comments($user_datei);
619             $lines = explode("\n", $users);
620             if(is_array($lines)){
621                 foreach($lines as $line){
622                     if(trim($line) != ''){
623                         list($f1, $f2, $f3, ) = explode(':', $line);
624                         if($f1 == $user) return $f3;
625                     }
626                 }
627             }
628         } else {
629             return false;
630         }
55da90 631     }
7fe908 632
MC 633
634
635
636
55da90 637     /**
3f478f 638      * Get the group id from an group
T 639      *
640      */
641     function getgid($group){
642         global $app;
7fe908 643         if($this->is_group($group)){
MC 644             $group_datei = $this->server_conf['group_datei'];
3f478f 645             $groups = $app->file->no_comments($group_datei);
T 646             $lines = explode("\n", $groups);
647             if(is_array($lines)){
7fe908 648                 foreach($lines as $line){
3f478f 649                     if(trim($line) != ""){
T 650                         list($f1, $f2, $f3, $f4) = explode(':', $line);
651                         if($f1 == $group) return $f3;
652                     }
653                 }
654             }
7fe908 655         } else {
MC 656             return false;
657         }
3f478f 658     }
7fe908 659
MC 660
661
662
663
3f478f 664     /**
7fe908 665      * Return info about a group by name
MC 666      *
667      */
3f478f 668     function posix_getgrnam($group) {
T 669         if(!function_exists('posix_getgrnam')){
670             $group_datei = $this->server_conf['group_datei'];
671             $cmd = 'grep -m 1 "^'.$group.':" '.$group_datei;
672             exec($cmd, $output, $return_var);
673             if($return_var != 0 || !$output[0]) return false;
674             list($f1, $f2, $f3, $f4) = explode(':', $output[0]);
675             $f2 = trim($f2);
676             $f3 = trim($f3);
677             $f4 = trim($f4);
678             if($f4 != ''){
679                 $members = explode(',', $f4);
680             } else {
681                 $members = array();
682             }
7fe908 683             $group_details = array( 'name' => $group,
MC 684                 'passwd' => $f2,
685                 'members' => $members,
686                 'gid' => $f3);
687             return $group_details;
3f478f 688         } else {
T 689             return posix_getgrnam($group);
690         }
7fe908 691     }
MC 692
693
694
695
696
3f478f 697     /**
55da90 698      * Get all information from a user
B 699      *
700      */
701     function get_user_attributes($user){
702         global $app;
7fe908 703         if($this->is_user($user)){
MC 704             $user_datei = $this->server_conf['passwd_datei'];
705             $users = $app->file->no_comments($user_datei);
706             $lines = explode("\n", $users);
707             if(is_array($lines)){
708                 foreach($lines as $line){
709                     if(trim($line) != ''){
710                         list($f1, $f2, $f3, $f4, $f5, $f6, $f7) = explode(':', $line);
711                         if($f1 == $user){
712                             $user_attr['username'] = $f1;
713                             $user_attr['x'] = $f2;
714                             $user_attr['uid'] = $f3;
715                             $user_attr['gid'] = $f4;
716                             $user_attr['name'] = $f5;
717                             $user_attr['homedir'] = $f6;
718                             $user_attr['shell'] = $f7;
719                             return $user_attr;
720                         }
721                     }
722                 }
723             }
724         } else {
725             return false;
726         }
55da90 727     }
7fe908 728
MC 729
730
731
732
55da90 733     /**
B 734      * Edit the owner of a file
735      *
736      */
c3ac0a 737     function chown($file, $owner, $allow_symlink = false){
7fe908 738         global $app;
MC 739         if($allow_symlink == false && $this->checkpath($file) == false) {
740             $app->log("Action aborted, file is a symlink: $file", LOGLEVEL_WARN);
d87f76 741             return false;
T 742         }
7fe908 743         if(file_exists($file)) {
MC 744             if(@chown($file, $owner)) {
745                 return true;
746             } else {
747                 $app->log("chown failed: $file : $owner", LOGLEVEL_DEBUG);
748                 return false;
749             }
750         }
c3ac0a 751     }
7fe908 752
c3ac0a 753     function chgrp($file, $group = '', $allow_symlink = false){
7fe908 754         global $app;
MC 755         if($allow_symlink == false && $this->checkpath($file) == false) {
756             $app->log("Action aborted, file is a symlink: $file", LOGLEVEL_WARN);
d87f76 757             return false;
T 758         }
7fe908 759         if(file_exists($file)) {
MC 760             if(@chgrp($file, $group)) {
761                 return true;
762             } else {
763                 $app->log("chgrp failed: $file : $group", LOGLEVEL_DEBUG);
764                 return false;
765             }
766         }
c3ac0a 767     }
7fe908 768
c3ac0a 769     //* Change the mode of a file
T 770     function chmod($file, $mode, $allow_symlink = false) {
c77103 771         global $app;
c3ac0a 772         if($allow_symlink == false && $this->checkpath($file) == false) {
7fe908 773             $app->log("Action aborted, file is a symlink: $file", LOGLEVEL_WARN);
c3ac0a 774             return false;
T 775         }
d87f76 776         if(@chmod($file, $mode)) {
T 777             return true;
778         } else {
7fe908 779             $app->log("chmod failed: $file : $mode", LOGLEVEL_DEBUG);
d87f76 780             return false;
T 781         }
c3ac0a 782     }
7fe908 783
c3ac0a 784     function file_put_contents($filename, $data, $allow_symlink = false) {
c77103 785         global $app;
c3ac0a 786         if($allow_symlink == false && $this->checkpath($filename) == false) {
7fe908 787             $app->log("Action aborted, file is a symlink: $filename", LOGLEVEL_WARN);
c3ac0a 788             return false;
T 789         }
c77103 790         if(file_exists($filename)) unlink($filename);
c3ac0a 791         return file_put_contents($filename, $data);
T 792     }
7fe908 793
c3ac0a 794     function file_get_contents($filename, $allow_symlink = false) {
c77103 795         global $app;
c3ac0a 796         if($allow_symlink == false && $this->checkpath($filename) == false) {
7fe908 797             $app->log("Action aborted, file is a symlink: $filename", LOGLEVEL_WARN);
c3ac0a 798             return false;
T 799         }
b889ed 800         return file_get_contents($filename, $data);
c3ac0a 801     }
7fe908 802
c3ac0a 803     function rename($filename, $new_filename, $allow_symlink = false) {
c77103 804         global $app;
c3ac0a 805         if($allow_symlink == false && $this->checkpath($filename) == false) {
7fe908 806             $app->log("Action aborted, file is a symlink: $filename", LOGLEVEL_WARN);
c3ac0a 807             return false;
T 808         }
809         return rename($filename, $new_filename);
810     }
7fe908 811
c3ac0a 812     function mkdir($dirname, $allow_symlink = false) {
c77103 813         global $app;
c3ac0a 814         if($allow_symlink == false && $this->checkpath($dirname) == false) {
7fe908 815             $app->log("Action aborted, file is a symlink: $dirname", LOGLEVEL_WARN);
c3ac0a 816             return false;
T 817         }
d87f76 818         if(@mkdir($dirname)) {
T 819             return true;
820         } else {
7fe908 821             $app->log("mkdir failed: $dirname", LOGLEVEL_DEBUG);
d87f76 822             return false;
T 823         }
c3ac0a 824     }
7fe908 825
58053e 826     function unlink($filename) {
b889ed 827         if(file_exists($filename) || is_link($filename)) {
c77103 828             return unlink($filename);
T 829         }
c3ac0a 830     }
7fe908 831
MC 832     function copy($file1, $file2) {
833         return copy($file1, $file2);
c3ac0a 834     }
7fe908 835
4bd960 836     function touch($file, $allow_symlink = false){
7fe908 837         global $app;
MC 838         if($allow_symlink == false && @file_exists($file) && $this->checkpath($file) == false) {
839             $this->unlink($file);
840         }
841         if(@touch($file)) {
4bd960 842             return true;
7fe908 843         } else {
MC 844             $app->log("touch failed: $file", LOGLEVEL_DEBUG);
4bd960 845             return false;
7fe908 846         }
4bd960 847     }
7fe908 848
c3ac0a 849     function checkpath($path) {
T 850         $path = trim($path);
851         //* We allow only absolute paths
7fe908 852         if(substr($path, 0, 1) != '/') return false;
MC 853
c3ac0a 854         //* We allow only some characters in the path
992797 855         // * is allowed, for example it is part of wildcard certificates/keys: *.example.com.crt
c6e989 856         if(!preg_match('@^/[-a-zA-Z0-9_/.*]{1,}[~]?$@', $path)) return false;
7fe908 857
c3ac0a 858         //* Check path for symlinks
7fe908 859         $path_parts = explode('/', $path);
c3ac0a 860         $testpath = '';
T 861         foreach($path_parts as $p) {
862             $testpath .= '/'.$p;
863             if(is_link($testpath)) return false;
864         }
7fe908 865
c3ac0a 866         return true;
55da90 867     }
7fe908 868
MC 869
870
871
872
55da90 873     /**
B 874      * Add an user to a specific group
875      *
876      */
877     function add_user_to_group($group, $user = 'admispconfig'){
878         global $app;
7fe908 879         $group_file = $app->file->rf($this->server_conf['group_datei']);
MC 880         $group_file_lines = explode("\n", $group_file);
881         foreach($group_file_lines as $group_file_line){
882             list($group_name, $group_x, $group_id, $group_users) = explode(':', $group_file_line);
883             if($group_name == $group){
884                 $group_users = explode(',', str_replace(' ', '', $group_users));
885                 if(!in_array($user, $group_users)){
886                     $group_users[] = $user;
887                 }
888                 $group_users = implode(',', $group_users);
889                 if(substr($group_users, 0, 1) == ',') $group_users = substr($group_users, 1);
890                 $group_file_line = $group_name.':'.$group_x.':'.$group_id.':'.$group_users;
891             }
892             $new_group_file[] = $group_file_line;
893         }
894         $new_group_file = implode("\n", $new_group_file);
895         $app->file->wf($this->server_conf['group_datei'], $new_group_file);
896         $app->file->remove_blank_lines($this->server_conf['group_datei']);
897         if($this->server_conf['shadow_datei'] != '/etc/shadow'){
898             $app->log->caselog('pwd_mkdb '.$this->server_conf['shadow_datei'].' &> /dev/null', $this->FILE, __LINE__);
899         }
55da90 900     }
7fe908 901
ff6a68 902     /*
55da90 903     function usermod($user, $groups){
B 904         global $app;
905           if($this->is_user($user)){
3b4c28 906             $groups = explode(',', str_replace(' ', '', $groups));
J 907             $group_file = $app->file->rf($this->server_conf['group_datei']);
55da90 908             $group_file_lines = explode("\n", $group_file);
B 909             foreach($group_file_lines as $group_file_line){
910                   if(trim($group_file_line) != ""){
3b4c28 911                     list($f1, $f2, $f3, $f4) = explode(':', $group_file_line);
J 912                     $group_users = explode(',', str_replace(' ', '', $f4));
55da90 913                     if(!in_array($f1, $groups)){
B 914                           if(in_array($user, $group_users)){
915                             $g_users = array();
916                             foreach($group_users as $group_user){
917                                   if($group_user != $user) $g_users[] = $group_user;
918                             }
3b4c28 919                             $f4 = implode(',', $g_users);
55da90 920                           }
B 921                     } else {
922                           if(!in_array($user, $group_users)){
3b4c28 923                             if(trim($group_users[0]) == '') unset($group_users);
55da90 924                             $group_users[] = $user;
B 925                           }
3b4c28 926                           $f4 = implode(',', $group_users);
55da90 927                     }
3b4c28 928                     $new_group_file[] = $f1.':'.$f2.':'.$f3.':'.$f4;
55da90 929                   }
B 930             }
931             $new_group_file = implode("\n", $new_group_file);
3b4c28 932             $app->file->wf($this->server_conf['group_datei'], $new_group_file);
J 933             $app->file->remove_blank_lines($this->server_conf['group_datei']);
934             if($this->server_conf['shadow_datei'] != '/etc/shadow'){
935                   $app->log->caselog('pwd_mkdb '.$this->server_conf['shadow_datei'].' &> /dev/null', $this->FILE, __LINE__);
55da90 936             }
B 937             return true;
938           } else {
939             return false;
940           }
941     }
ff6a68 942     */
7fe908 943
55da90 944     /**boot autostart etc
B 945      *
946      */
947     function rc_edit($service, $rl, $action){
948         // $action = "on|off";
7fe908 949         global $app;
MC 950         $dist_init_scripts = $app->system->server_conf['dist_init_scripts'];
951         $dist_runlevel = $app->system->server_conf['dist_runlevel'];
952         $dist = $app->system->server_conf['dist'];
953         if(trim($dist_runlevel) == ''){ // falls es keine runlevel gibt (FreeBSD)
954             if($action == 'on'){
955                 @symlink($dist_init_scripts.'/'.$service, $dist_init_scripts.'/'.$service.'.sh');
956             }
957             if($action == 'off'){
958                 if(is_link($dist_init_scripts.'/'.$service.'.sh')){
959                     unlink($dist_init_scripts.'/'.$service.'.sh');
960                 } else {
961                     rename($dist_init_scripts.'/'.$service.'.sh', $dist_init_scripts.'/'.$service);
962                 }
963             }
964         } else { // Linux
965             if(substr($dist, 0, 4) == 'suse'){
966                 if($action == 'on'){
967                     exec("chkconfig --add $service &> /dev/null");
968                 }
969                 if($action == 'off'){
970                     exec("chkconfig --del $service &> /dev/null");
971                 }
972             } else {
973                 $runlevels = explode(',', $rl);
974                 foreach($runlevels as $runlevel){
975                     $runlevel = trim($runlevel);
976                     if($runlevel != '' && is_dir($dist_runlevel.'/rc'.$runlevel.'.d')){
977                         $handle=opendir($dist_runlevel.'/rc'.$runlevel.'.d');
978                         while($file = readdir($handle)){
979                             if($file != '.' && $file != '..'){
980                                 $target = @readlink($dist_runlevel.'/rc'.$runlevel.'.d/'.$file);
981                                 if(strstr($file, $service) && strstr($target, $service) && substr($file, 0, 1) == 'S') $ln_arr[$runlevel][] = $dist_runlevel.'/rc'.$runlevel.'.d/'.$file;
982                             }
983                         }
984                         closedir($handle);
985                     }
986                     if($action == 'on'){
987                         if(!is_array($ln_arr[$runlevel])) @symlink($dist_init_scripts.'/'.$service, $dist_runlevel.'/rc'.$runlevel.'.d/S99'.$service);
988                     }
989                     if($action == 'off'){
990                         if(is_array($ln_arr[$runlevel])){
991                             foreach($ln_arr[$runlevel] as $link){
992                                 unlink($link);
993                             }
994                         }
995                     }
996                 }
997             }
998         }
55da90 999     }
7fe908 1000
MC 1001
1002
1003
1004
55da90 1005     /**
B 1006      * Filter information from the commands
1007      *
1008      */
1009     function grep($content, $string, $params = ''){
1010         global $app;
7fe908 1011         // params: i, v, w
MC 1012         $content = $app->file->unix_nl($content);
1013         $lines = explode("\n", $content);
1014         foreach($lines as $line){
1015             if(!strstr($params, 'w')){
1016                 if(strstr($params, 'i')){
1017                     if(strstr($params, 'v')){
1018                         if(!stristr($line, $string)) $find[] = $line;
1019                     } else {
1020                         if(stristr($line, $string)) $find[] = $line;
1021                     }
1022                 } else {
1023                     if(strstr($params, 'v')){
1024                         if(!strstr($line, $string)) $find[] = $line;
1025                     } else {
1026                         if(strstr($line, $string)) $find[] = $line;
1027                     }
1028                 }
1029             } else {
1030                 if(strstr($params, 'i')){
1031                     if(strstr($params, 'v')){
1032                         if(!$app->string->is_word($string, $line, 'i')) $find[] = $line;
1033                     } else {
1034                         if($app->string->is_word($string, $line, 'i')) $find[] = $line;
1035                     }
1036                 } else {
1037                     if(strstr($params, 'v')){
1038                         if(!$app->string->is_word($string, $line)) $find[] = $line;
1039                     } else {
1040                         if($app->string->is_word($string, $line)) $find[] = $line;
1041                     }
1042                 }
1043             }
1044         }
1045         if(is_array($find)){
1046             $ret_val = implode("\n", $find);
1047             if(substr($ret_val, -1) != "\n") $ret_val .= "\n";
1048             $find = NULL;
1049             return $ret_val;
1050         } else {
1051             return false;
1052         }
55da90 1053     }
7fe908 1054
MC 1055
1056
1057
1058
55da90 1059     /**
B 1060      * Strip content from fields
1061      *
1062      */
1063     function cut($content, $field, $delimiter = ':'){
1064         global $app;
7fe908 1065         $content = $app->file->unix_nl($content);
MC 1066         $lines = explode("\n", $content);
1067         foreach($lines as $line){
1068             $elms = explode($delimiter, $line);
1069             $find[] = $elms[($field-1)];
1070         }
1071         if(is_array($find)){
1072             $ret_val = implode("\n", $find);
1073             if(substr($ret_val, -1) != "\n") $ret_val .= "\n";
1074             $find = NULL;
1075             return $ret_val;
1076         } else {
1077             return false;
1078         }
55da90 1079     }
7fe908 1080
MC 1081
1082
1083
1084
55da90 1085     /**
B 1086      * Get the content off a file
1087      *
1088      */
1089     function cat($file){
1090         global $app;
7fe908 1091         return $app->file->rf($file);
55da90 1092     }
7fe908 1093
MC 1094
1095
1096
1097
55da90 1098     /**
B 1099      * Control services to restart etc
1100      *
1101      */
1102     function daemon_init($daemon, $action){
1103         //* $action = start|stop|restart|reload
7fe908 1104         global $app;
MC 1105         $dist = $this->server_conf['dist'];
1106         $dist_init_scripts = $this->server_conf['dist_init_scripts'];
1107         if(!strstr($dist, 'freebsd')){
1108             $app->log->caselog("$dist_init_scripts/$daemon $action &> /dev/null", $this->FILE, __LINE__);
1109         } else {
1110             if(is_file($dist_init_scripts.'/'.$daemon.'.sh') || is_link($dist_init_scripts.'/'.$daemon.'.sh')){
1111                 if($action == 'start' || $action == 'stop'){
1112                     $app->log->caselog($dist_init_scripts.'/'.$daemon.'.sh '.$action.' &> /dev/null', $this->FILE, __LINE__);
1113                 } else {
1114                     $app->log->caselog($dist_init_scripts.'/'.$daemon.'.sh stop &> /dev/null', $this->FILE, __LINE__);
1115                     sleep(3);
1116                     $app->log->caselog($dist_init_scripts.'/'.$daemon.'.sh start &> /dev/null', $this->FILE, __LINE__);
1117                 }
1118             } else {
1119                 if(is_file($dist_init_scripts.'/'.$daemon) || is_link($dist_init_scripts.'/'.$daemon)){
1120                     if($action == 'start' || $action == 'stop'){
1121                         $app->log->caselog($dist_init_scripts.'/'.$daemon.' '.$action.' &> /dev/null', $this->FILE, __LINE__);
1122                     } else {
1123                         $app->log->caselog($dist_init_scripts.'/'.$daemon.' stop &> /dev/null', $this->FILE, __LINE__);
1124                         sleep(3);
1125                         $app->log->caselog($dist_init_scripts.'/'.$daemon.' start &> /dev/null', $this->FILE, __LINE__);
1126                     }
1127                 } else {
1128                     if(is_file('/etc/rc.d/'.$daemon) || is_link('/etc/rc.d/'.$daemon)){
1129                         if($action == 'start' || $action == 'stop'){
1130                             $app->log->caselog('/etc/rc.d/'.$daemon.' '.$action.' &> /dev/null', $this->FILE, __LINE__);
1131                         } else {
1132                             $app->log->caselog('/etc/rc.d/'.$daemon.' stop &> /dev/null', $this->FILE, __LINE__);
1133                             sleep(3);
1134                             $app->log->caselog('/etc/rc.d/'.$daemon.' start &> /dev/null', $this->FILE, __LINE__);
1135                         }
1136                     }
1137                 }
1138             }
1139         }
55da90 1140     }
7fe908 1141
55da90 1142     function netmask($netmask){
7fe908 1143         list($f1, $f2, $f3, $f4) = explode('.', trim($netmask));
MC 1144         $bin = str_pad(decbin($f1), 8, '0', STR_PAD_LEFT).str_pad(decbin($f2), 8, '0', STR_PAD_LEFT).str_pad(decbin($f3), 8, '0', STR_PAD_LEFT).str_pad(decbin($f4), 8, '0', STR_PAD_LEFT);
1145         $parts = explode('0', $bin);
1146         $bin = str_pad($parts[0], 32, '0', STR_PAD_RIGHT);
1147         $bin = wordwrap($bin, 8, '.', 1);
1148         list($f1, $f2, $f3, $f4) = explode('.', trim($bin));
1149         return bindec($f1).'.'.bindec($f2).'.'.bindec($f3).'.'.bindec($f4);
55da90 1150     }
7fe908 1151
55da90 1152     function binary_netmask($netmask){
7fe908 1153         list($f1, $f2, $f3, $f4) = explode('.', trim($netmask));
MC 1154         $bin = str_pad(decbin($f1), 8, '0', STR_PAD_LEFT).str_pad(decbin($f2), 8, '0', STR_PAD_LEFT).str_pad(decbin($f3), 8, '0', STR_PAD_LEFT).str_pad(decbin($f4), 8, '0', STR_PAD_LEFT);
1155         $parts = explode('0', $bin);
1156         return substr_count($parts[0], '1');
55da90 1157     }
7fe908 1158
55da90 1159     function network($ip, $netmask){
7fe908 1160         $netmask = $this->netmask($netmask);
MC 1161         list($f1, $f2, $f3, $f4) = explode('.', $netmask);
1162         $netmask_bin = str_pad(decbin($f1), 8, '0', STR_PAD_LEFT).str_pad(decbin($f2), 8, '0', STR_PAD_LEFT).str_pad(decbin($f3), 8, '0', STR_PAD_LEFT).str_pad(decbin($f4), 8, '0', STR_PAD_LEFT);
1163         list($f1, $f2, $f3, $f4) = explode('.', $ip);
1164         $ip_bin = str_pad(decbin($f1), 8, '0', STR_PAD_LEFT).str_pad(decbin($f2), 8, '0', STR_PAD_LEFT).str_pad(decbin($f3), 8, '0', STR_PAD_LEFT).str_pad(decbin($f4), 8, '0', STR_PAD_LEFT);
1165         for($i=0;$i<32;$i++){
1166             $network_bin .= substr($netmask_bin, $i, 1) * substr($ip_bin, $i, 1);
1167         }
1168         $network_bin = wordwrap($network_bin, 8, '.', 1);
1169         list($f1, $f2, $f3, $f4) = explode('.', trim($network_bin));
1170         return bindec($f1).'.'.bindec($f2).'.'.bindec($f3).'.'.bindec($f4);
55da90 1171     }
7fe908 1172
MC 1173
1174
1175
1176
55da90 1177     /**
B 1178      * Make a broadcast address from an IP number in combination with netmask
1179      *
1180      */
1181     function broadcast($ip, $netmask){
1182         $netmask = $this->netmask($netmask);
7fe908 1183         $binary_netmask = $this->binary_netmask($netmask);
MC 1184         list($f1, $f2, $f3, $f4) = explode('.', $ip);
1185         $ip_bin = str_pad(decbin($f1), 8, '0', STR_PAD_LEFT).str_pad(decbin($f2), 8, '0', STR_PAD_LEFT).str_pad(decbin($f3), 8, '0', STR_PAD_LEFT).str_pad(decbin($f4), 8, '0', STR_PAD_LEFT);
1186         $broadcast_bin = str_pad(substr($ip_bin, 0, $binary_netmask), 32, '1', STR_PAD_RIGHT);
1187         $broadcast_bin = wordwrap($broadcast_bin, 8, '.', 1);
1188         list($f1, $f2, $f3, $f4) = explode('.', trim($broadcast_bin));
1189         return bindec($f1).'.'.bindec($f2).'.'.bindec($f3).'.'.bindec($f4);
55da90 1190     }
7fe908 1191
MC 1192
1193
1194
1195
55da90 1196     /**
B 1197      * Get the network address information
1198      *
1199      */
1200     function network_info(){
458767 1201         $dist = $this->server_conf['dist'];
7fe908 1202         ob_start();
MC 1203         passthru('ifconfig');
1204         $output = ob_get_contents();
1205         ob_end_clean();
1206         $lines = explode("\n", $output);
1207         foreach($lines as $line){
1208             $elms = explode(' ', $line);
1209             if(trim($elms[0]) != '' && substr($elms[0], 0, 1) != "\t"){
1210                 $elms[0] = trim($elms[0]);
1211                 if(strstr($dist, 'freebsd')) $elms[0] = substr($elms[0], 0, -1);
1212                 $interfaces[] = $elms[0];
1213             }
1214         }
1215         if(!empty($interfaces)){
1216             foreach($interfaces as $interface){
1217                 ob_start();
1218                 if(!strstr($dist, 'freebsd')){
1219                     passthru('ifconfig '.$interface." | grep -iw 'inet' | cut -f2 -d: | cut -f1 -d' '");
1220                 } else {
1221                     passthru('ifconfig '.$interface." | grep -iw 'inet' | grep -iv 'inet6' | cut -f2 -d' '");
1222                 }
1223                 $output = trim(ob_get_contents());
1224                 ob_end_clean();
1225                 if($output != ''){
1226                     $ifconfig['INTERFACE'][$interface] = $output;
1227                     $ifconfig['IP'][$output] = $interface;
1228                 }
1229             }
1230             if(!empty($ifconfig)){
1231                 return $ifconfig;
1232             } else {
1233                 return false;
1234             }
1235         } else {
1236             return false;
1237         }
55da90 1238     }
7fe908 1239
MC 1240
1241
1242
1243
55da90 1244     /**
B 1245      * Configure the network settings from the system
1246      *
1247      */
1248     function network_config(){
1249         $ifconfig = $this->network_info();
7fe908 1250         if($ifconfig){
MC 1251             $main_interface = $ifconfig['IP'][$this->server_conf['server_ip']];
1252             if(strstr($main_interface, ':')){
1253                 $parts = explode(':', $main_interface);
1254                 $main_interface = trim($parts[0]);
1255             }
1256             if($main_interface != ''){
1257                 $ips = $this->data['isp_server_ip'];
1258                 if(!empty($ips)){
1259                     foreach($ips as $ip){
1260                         if(!isset($ifconfig['IP'][$ip['server_ip']])){
1261                             $to_set[] = $ip['server_ip'];
1262                         } else {
1263                             unset($ifconfig['IP'][$ip['server_ip']]);
1264                         }
1265                     }
1266                     if(!empty($ifconfig['IP'])){
1267                         foreach($ifconfig['IP'] as $key => $val){
1268                             if(!strstr($val, 'lo') && !strstr($val, 'lp') && strstr($val, $main_interface)){
1269                                 exec('ifconfig '.$val.' down &> /dev/null');
1270                                 unset($ifconfig['INTERFACE'][$val]);
1271                             }
1272                         }
1273                     }
1274                     if(!empty($to_set)){
1275                         foreach($to_set as $to){
1276                             $i = 0;
1277                             while($i >= 0){
1278                                 if(isset($ifconfig['INTERFACE'][$main_interface.':'.$i])){
1279                                     $i++;
1280                                 } else {
1281                                     $new_interface = $main_interface.':'.$i;
1282                                     $i = -1;
1283                                 }
1284                             }
1285                             exec('ifconfig '.$new_interface.' '.$to.' netmask '.$this->server_conf['server_netzmaske'].' up &> /dev/null');
1286                             $ifconfig['INTERFACE'][$new_interface] = $to;
1287                         }
1288                     }
1289                 }
1290             }
1291         }
55da90 1292     }
7fe908 1293
55da90 1294     function quota_dirs(){
7fe908 1295         global $app;
MC 1296         $content = $app->file->unix_nl($app->file->no_comments('/etc/fstab'));
1297         $lines = explode("\n", $content);
1298         foreach($lines as $line){
1299             $line = trim($line);
1300             if($line != ''){
1301                 $elms = explode("\t", $line);
1302                 foreach($elms as $elm){
1303                     if(trim($elm) != '') $f[] = $elm;
1304                 }
1305                 if(!empty($f) && stristr($f[3], 'userquota') && stristr($f[3], 'groupquota')){
1306                     $q_dirs[] = trim($f[1]);
1307                 }
1308                 unset($f);
1309             }
1310         }
1311         if(!empty($q_dirs)){
1312             return $q_dirs;
1313         } else {
1314             return false;
1315         }
55da90 1316     }
7fe908 1317
MC 1318
1319
1320
1321
55da90 1322     /**
B 1323      * Scan the trash for virusses infection
1324      *
1325      */
1326     function make_trashscan(){
1327         global $app;
7fe908 1328         //trashscan erstellen
MC 1329         // Template Ã–ffnen
1330         $app->tpl->clear_all();
1331         $app->tpl->define( array(table    => 'trashscan.master'));
1332
1333         if(!isset($this->server_conf['virusadmin']) || trim($this->server_conf['virusadmin']) == '') $this->server_conf['virusadmin'] = 'admispconfig@localhost';
1334         if(substr($this->server_conf['virusadmin'], 0, 1) == '#'){
1335             $notify = 'no';
1336         } else {
1337             $notify = 'yes';
1338         }
1339
1340         // Variablen zuweisen
1341         $app->tpl->assign( array(VIRUSADMIN => $this->server_conf['virusadmin'],
1342                 NOTIFICATION => $notify));
1343
1344         $app->tpl->parse(TABLE, table);
1345
1346         $trashscan_text = $app->tpl->fetch();
1347
1348         $datei = '/home/admispconfig/ispconfig/tools/clamav/bin/trashscan';
1349         $app->file->wf($datei, $trashscan_text);
1350
1351         chmod($datei, 0755);
1352         chown($datei, 'admispconfig');
1353         chgrp($datei, 'admispconfig');
55da90 1354     }
7fe908 1355
MC 1356
1357
1358
1359
55da90 1360     /**
B 1361      * Get the current time
1362      *
1363      */
1364     function get_time(){
7fe908 1365         $addr = 'http://www.ispconfig.org/';
MC 1366         $timeout = 1;
1367         $url_parts = parse_url($addr);
1368         $path = $url_parts['path'];
1369         $port = 80;
1370         $urlHandle = @fsockopen($url_parts['host'], $port, $errno, $errstr, $timeout);
1371         if ($urlHandle){
1372             socket_set_timeout($urlHandle, $timeout);
1373
1374             $urlString = 'GET '.$path." HTTP/1.0\r\nHost: ".$url_parts['host']."\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n";
1375             if ($user) $urlString .= 'Authorization: Basic '.base64_encode($user.':'.$pass)."\r\n";
1376             $urlString .= "\r\n";
1377             fputs($urlHandle, $urlString);
1378
1379             $month['Jan'] = '01';
1380             $month['Feb'] = '02';
1381             $month['Mar'] = '03';
1382             $month['Apr'] = '04';
1383             $month['May'] = '05';
1384             $month['Jun'] = '06';
1385             $month['Jul'] = '07';
1386             $month['Aug'] = '08';
1387             $month['Sep'] = '09';
1388             $month['Oct'] = '10';
1389             $month['Nov'] = '11';
1390             $month['Dec'] = '12';
1391             $c = 0;
1392             $l = 0;
1393             $startzeit = time();
1394             while(!feof($urlHandle) && $c < 2 && $l == 0){
1395                 $line = trim(fgets($urlHandle, 128));
1396                 $response .= $line;
1397                 $c = time() - $startzeit;
1398                 if($line == '' || substr($line, 0, 5) == 'Date:') $l += 1; // nur den Header auslesen
1399                 if(substr($line, 0, 5) == 'Date:'){
1400                     $parts = explode(' ', $line);
1401                     $tag = $parts[2];
1402                     $monat = $month[$parts[3]];
1403                     $jahr = $parts[4];
1404                     list($stunde, $minute, $sekunde) = explode(':', $parts[5]);
1405                     $timestamp = mktime($stunde, $minute, $sekunde, $monat, $tag, $jahr);
1406                 }
1407             }
1408
1409             @fclose($urlHandle);
1410
1411             return $timestamp;
1412         } else {
1413             @fclose($urlHandle);
1414             return false;
1415         }
55da90 1416     }
7fe908 1417
MC 1418     function replaceLine($filename, $search_pattern, $new_line, $strict = 0, $append = 1) {
c77103 1419         global $app;
c3ac0a 1420         if($this->checkpath($filename) == false) {
7fe908 1421             $app->log("Action aborted, file is a symlink: $filename", LOGLEVEL_WARN);
c3ac0a 1422             return false;
T 1423         }
fdb514 1424         $lines = @file($filename);
T 1425         $out = '';
1426         $found = 0;
1427         if(is_array($lines)) {
1428             foreach($lines as $line) {
1429                 if($strict == 0) {
7fe908 1430                     if(stristr($line, $search_pattern)) {
fdb514 1431                         $out .= $new_line."\n";
T 1432                         $found = 1;
1433                     } else {
1434                         $out .= $line;
1435                     }
1436                 } else {
1437                     if(trim($line) == $search_pattern) {
1438                         $out .= $new_line."\n";
1439                         $found = 1;
1440                     } else {
1441                         $out .= $line;
1442                     }
1443                 }
1444             }
1445         }
7fe908 1446
fdb514 1447         if($found == 0) {
T 1448             //* add \n if the last line does not end with \n or \r
7fe908 1449             if(substr($out, -1) != "\n" && substr($out, -1) != "\r" && filesize($filename) > 0) $out .= "\n";
fdb514 1450             //* add the new line at the end of the file
9f56bd 1451             if($append == 1) {
T 1452                 $out .= $new_line."\n";
1453             }
fdb514 1454         }
7fe908 1455         file_put_contents($filename, $out);
fdb514 1456     }
7fe908 1457
MC 1458     function removeLine($filename, $search_pattern, $strict = 0) {
1459         global $app;
1460         if($this->checkpath($filename) == false) {
1461             $app->log("Action aborted, file is a symlink: $filename", LOGLEVEL_WARN);
1462             return false;
1463         }
1464         if($lines = @file($filename)) {
1465             $out = '';
1466             foreach($lines as $line) {
1467                 if($strict == 0) {
1468                     if(!stristr($line, $search_pattern)) {
1469                         $out .= $line;
1470                     }
1471                 } else {
1472                     if(!trim($line) == $search_pattern) {
1473                         $out .= $line;
1474                     }
fdb514 1475                 }
T 1476             }
7fe908 1477             file_put_contents($filename, $out);
fdb514 1478         }
T 1479     }
7fe908 1480
fdb514 1481     function maildirmake($maildir_path, $user = '', $subfolder = '') {
7fe908 1482
128d3b 1483         global $app, $conf;
TB 1484         
1485         // load the server configuration options
1486         $app->uses("getconf");
1487         $mail_config = $app->getconf->get_server_config($conf["server_id"], 'mail');
7fe908 1488
fdb514 1489         if($subfolder != '') {
d2212d 1490             $dir = escapeshellcmd($maildir_path.'/.'.$subfolder);
fdb514 1491         } else {
d2212d 1492             $dir = escapeshellcmd($maildir_path);
2ebadd 1493         }
7fe908 1494
fb3a98 1495         if(!is_dir($dir)) mkdir($dir, 0700, true);
2ebadd 1496
J 1497         if($user != '' && $user != 'root' && $this->is_user($user)) {
d2212d 1498             $user = escapeshellcmd($user);
2ebadd 1499             // I assume that the name of the (vmail group) is the same as the name of the mail user in ISPConfig 3
J 1500             $group = $user;
7fe908 1501             if(is_dir($dir)) $this->chown($dir, $user);
MC 1502             if(is_dir($dir)) $this->chgrp($dir, $group);
2ebadd 1503
J 1504             $chown_mdsub = true;
fdb514 1505         }
7fe908 1506
MC 1507         $maildirsubs = array('cur', 'new', 'tmp');
2ebadd 1508
J 1509         foreach ($maildirsubs as $mdsub) {
9f56bd 1510             if(!is_dir($dir.'/'.$mdsub)) mkdir($dir.'/'.$mdsub, 0700, true);
2ebadd 1511             if ($chown_mdsub) {
J 1512                 chown($dir.'/'.$mdsub, $user);
1513                 chgrp($dir.'/'.$mdsub, $group);
1514             }
1515         }
1516
1517         chmod($dir, 0700);
7fe908 1518
d2212d 1519         /*
fdb514 1520         if($user != '' && $this->is_user($user) && $user != 'root') {
d2212d 1521             $user = escapeshellcmd($user);
3b4c28 1522             // I assume that the name of the (vmail group) is the same as the name of the mail user in ISPConfig 3
a59ad3 1523             $group = $user;
T 1524             exec("chown $user:$group $dir $dir_cur $dir_new $dir_tmp");
fdb514 1525         }
d2212d 1526         */
7fe908 1527
fdb514 1528         //* Add the subfolder to the subscriptions and courierimapsubscribed files
T 1529         if($subfolder != '') {
128d3b 1530             
fdb514 1531             // Courier
128d3b 1532             if($mail_config['pop3_imap_daemon'] == 'courier') {
TB 1533                 if(!is_file($maildir_path.'/courierimapsubscribed')) {
1534                     $tmp_file = escapeshellcmd($maildir_path.'/courierimapsubscribed');
1535                     touch($tmp_file);
1536                     chmod($tmp_file, 0744);
1537                     chown($tmp_file, 'vmail');
1538                     chgrp($tmp_file, 'vmail');
1539                 }
1540                 $this->replaceLine($maildir_path.'/courierimapsubscribed', 'INBOX.'.$subfolder, 'INBOX.'.$subfolder, 1, 1);
fdb514 1541             }
7fe908 1542
fdb514 1543             // Dovecot
128d3b 1544             if($mail_config['pop3_imap_daemon'] == 'dovecot') {
TB 1545                 if(!is_file($maildir_path.'/subscriptions')) {
1546                     $tmp_file = escapeshellcmd($maildir_path.'/subscriptions');
1547                     touch($tmp_file);
1548                     chmod($tmp_file, 0744);
1549                     chown($tmp_file, 'vmail');
1550                     chgrp($tmp_file, 'vmail');
1551                 }
1552                 $this->replaceLine($maildir_path.'/subscriptions', $subfolder, $subfolder, 1, 1);
fdb514 1553             }
T 1554         }
7fe908 1555
MC 1556         $app->log('Created Maildir '.$maildir_path.' with subfolder: '.$subfolder, LOGLEVEL_DEBUG);
1557
fdb514 1558     }
7fe908 1559
355efb 1560     //* Function to create directory paths and chown them to a user and group
T 1561     function mkdirpath($path, $mode = 0755, $user = '', $group = '') {
7fe908 1562         $path_parts = explode('/', $path);
355efb 1563         $new_path = '';
T 1564         if(is_array($path_parts)) {
1565             foreach($path_parts as $part) {
1566                 $new_path .= '/'.$part;
1567                 if(!@is_dir($new_path)) {
c3ac0a 1568                     $this->mkdir($new_path);
7fe908 1569                     $this->chmod($new_path, $mode);
MC 1570                     if($user != '') $this->chown($new_path, $user);
1571                     if($group != '') $this->chgrp($new_path, $group);
355efb 1572                 }
T 1573             }
1574         }
7fe908 1575
355efb 1576     }
7fe908 1577
42f191 1578     //* Check if a application is installed
T 1579     function is_installed($appname) {
7fe908 1580         exec('which '.escapeshellcmd($appname).' 2> /dev/null', $out, $returncode);
MC 1581         if(isset($out[0]) && stristr($out[0], $appname) && $returncode == 0) {
42f191 1582             return true;
T 1583         } else {
1584             return false;
1585         }
1586     }
7fe908 1587
MC 1588     function web_folder_protection($document_root, $protect) {
1589         global $app, $conf;
1590
c3ac0a 1591         if($this->checkpath($document_root) == false) {
7fe908 1592             $app->log("Action aborted, target is a symlink: $document_root", LOGLEVEL_DEBUG);
c3ac0a 1593             return false;
T 1594         }
7fe908 1595
4b9329 1596         //* load the server configuration options
T 1597         $app->uses('getconf');
1598         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
7fe908 1599
4b9329 1600         if($protect == true && $web_config['web_folder_protection'] == 'y') {
T 1601             //* Add protection
7fe908 1602             if($document_root != '' && $document_root != '/' && strlen($document_root) > 6 && !stristr($document_root, '..')) exec('chattr +i '.escapeshellcmd($document_root));
4b9329 1603         } else {
T 1604             //* Remove protection
7fe908 1605             if($document_root != '' && $document_root != '/' && strlen($document_root) > 6 && !stristr($document_root, '..')) exec('chattr -i '.escapeshellcmd($document_root));
4b9329 1606         }
T 1607     }
7fe908 1608
ff6a68 1609     function usermod($username, $uid = 0, $gid = 0, $home = '', $shell = '', $password = '', $login = '') {
T 1610         global $app;
7fe908 1611
ff6a68 1612         if($login == '') $login = $username;
7fe908 1613
ff6a68 1614         //* Change values in /etc/passwd
T 1615         $passwd_file_array = file('/etc/passwd');
1616         if(is_array($passwd_file_array)) {
1617             foreach($passwd_file_array as $line) {
1618                 $line = trim($line);
7fe908 1619                 $parts = explode(':', $line);
ff6a68 1620                 if($parts[0] == $username) {
T 1621                     if(trim($login) != '' && trim($login) != trim($username)) $parts[0] = trim($login);
1622                     if(!empty($uid)) $parts[2] = trim($uid);
1623                     if(!empty($gid)) $parts[3] = trim($gid);
1624                     if(trim($home) != '') $parts[5] = trim($home);
1625                     if(trim($shell) != '') $parts[6] = trim($shell);
7fe908 1626                     $new_line = implode(':', $parts);
MC 1627                     copy('/etc/passwd', '/etc/passwd~');
1628                     chmod('/etc/passwd~', 0600);
ff6a68 1629                     $app->uses('system');
7fe908 1630                     $app->system->replaceLine('/etc/passwd', $line, $new_line, 1, 0);
ff6a68 1631                 }
T 1632             }
1633             unset($passwd_file_array);
1634         }
7fe908 1635
ff6a68 1636         //* If username != login, change username in group and gshadow file
T 1637         if($username  != $login) {
1638             $group_file_array = file('/etc/group');
1639             if(is_array($group_file_array)) {
1640                 foreach($group_file_array as $line) {
1641                     $line = trim($line);
7fe908 1642                     $parts = explode(':', $line);
MC 1643                     if(strstr($parts[3], $username)) {
1644                         $uparts = explode(',', $parts[3]);
ff6a68 1645                         if(is_array($uparts)) {
T 1646                             foreach($uparts as $key => $val) {
1647                                 if($val == $username) $uparts[$key] = $login;
1648                             }
1649                         }
7fe908 1650                         $parts[3] = implode(',', $uparts);
MC 1651                         $new_line = implode(':', $parts);
1652                         copy('/etc/group', '/etc/group~');
1653                         chmod('/etc/group~', 0600);
1654                         $app->system->replaceLine('/etc/group', $line, $new_line, 1, 0);
ff6a68 1655                     }
T 1656                 }
1657             }
1658             unset($group_file_array);
7fe908 1659
ff6a68 1660             $gshadow_file_array = file('/etc/gshadow');
T 1661             if(is_array($gshadow_file_array)) {
1662                 foreach($gshadow_file_array as $line) {
1663                     $line = trim($line);
7fe908 1664                     $parts = explode(':', $line);
MC 1665                     if(strstr($parts[3], $username)) {
1666                         $uparts = explode(',', $parts[3]);
ff6a68 1667                         if(is_array($uparts)) {
T 1668                             foreach($uparts as $key => $val) {
1669                                 if($val == $username) $uparts[$key] = $login;
1670                             }
1671                         }
7fe908 1672                         $parts[3] = implode(',', $uparts);
MC 1673                         $new_line = implode(':', $parts);
1674                         copy('/etc/gshadow', '/etc/gshadow~');
1675                         chmod('/etc/gshadow~', 0600);
1676                         $app->system->replaceLine('/etc/gshadow', $line, $new_line, 1, 0);
ff6a68 1677                     }
T 1678                 }
1679             }
1680             unset($group_file_array);
1681         }
7fe908 1682
MC 1683
ff6a68 1684         //* When password or login name has been changed
T 1685         if($password != '' || $username  != $login) {
1686             $shadow_file_array = file('/etc/shadow');
1687             if(is_array($shadow_file_array)) {
1688                 foreach($shadow_file_array as $line) {
1689                     $line = trim($line);
7fe908 1690                     $parts = explode(':', $line);
ff6a68 1691                     if($parts[0] == $username) {
T 1692                         if(trim($login) != '' && trim($login) != trim($username)) $parts[0] = trim($login);
1693                         if(trim($password) != '') $parts[1] = trim($password);
7fe908 1694                         $new_line = implode(':', $parts);
MC 1695                         copy('/etc/shadow', '/etc/shadow~');
1696                         chmod('/etc/shadow~', 0600);
1697                         $app->system->replaceLine('/etc/shadow', $line, $new_line, 1, 0);
ff6a68 1698                     }
T 1699                 }
1700             }
1701             unset($shadow_file_array);
1702         }
1703     }
7fe908 1704
bfcdef 1705     function intval($string, $force_numeric = false) {
7fe908 1706         if(intval($string) == 2147483647) {
MC 1707             if($force_numeric == true) return floatval($string);
1708             elseif(preg_match('/^([-]?)[0]*([1-9][0-9]*)([^0-9].*)*$/', $string, $match)) return $match[1].$match[2];
1709             else return 0;
1710         } else {
1711             return intval($string);
1712         }
1713     }
1714
526b99 1715     function is_mounted($mountpoint){
cc6568 1716         //$cmd = 'df 2>/dev/null | grep " '.$mountpoint.'$"';
H 1717         $cmd = 'mount 2>/dev/null | grep " on '.$mountpoint.' type "';
526b99 1718         exec($cmd, $output, $return_var);
7fe908 1719         return $return_var == 0 ? true : false;
526b99 1720     }
7fe908 1721
33bcd0 1722     function getinitcommand($servicename, $action, $init_script_directory = ''){
FT 1723         global $conf;
1724         // upstart
1725         if(is_executable('/sbin/initctl')){
1726             exec('/sbin/initctl version 2>/dev/null | /bin/grep -q upstart', $retval['output'], $retval['retval']);
1727             if(intval($retval['retval']) == 0) return 'service '.$servicename.' '.$action;
1728         }
bc04c3 1729         // systemd
TB 1730         if(is_executable('/bin/systemd') || is_executable('/usr/bin/systemctl')){
1731             return 'systemctl '.$action.' '.$servicename.'.service';
1732         }
33bcd0 1733         // sysvinit
FT 1734         if($init_script_directory == '') $init_script_directory = $conf['init_scripts'];
1735         if(substr($init_script_directory, -1) === '/') $init_script_directory = substr($init_script_directory, 0, -1);
1736         return $init_script_directory.'/'.$servicename.' '.$action;
1737     }
8133de 1738     
MC 1739     function getapacheversion($get_minor = false) {
1740         global $app;
1741         
1742         $cmd = '';
1743         if($this->is_installed('apache2ctl')) $cmd = 'apache2ctl -v';
1744         elseif($this->is_installed('apachectl')) $cmd = 'apachectl -v';
1745         else {
1746             $app->log("Could not check apache version, apachectl not found.", LOGLEVEL_WARN);
1747             return '2.2';
1748         }
1749         
1750         exec($cmd, $output, $return_var);
1751         if($return_var != 0 || !$output[0]) {
1752             $app->log("Could not check apache version, apachectl did not return any data.", LOGLEVEL_WARN);
1753             return '2.2';
1754         }
1755         
1756         if(preg_match('/version:\s*Apache\/(\d+)(\.(\d+)(\.(\d+))*)?(\D|$)/i', $output[0], $matches)) {
1757             return $matches[1] . (isset($matches[3]) ? '.' . $matches[3] : '') . (isset($matches[5]) && $get_minor == true ? '.' . $matches[5] : '');
1758         } else {
1759             $app->log("Could not check apache version, did not find version string in apachectl output.", LOGLEVEL_WARN);
1760             return '2.2';
1761         }
1762     }
e2d6ed 1763
60b700 1764     function getapachemodules() {
MC 1765         global $app;
1766         
1767         $cmd = '';
1e67c1 1768         if($this->is_installed('apache2ctl')) $cmd = 'apache2ctl -t -D DUMP_MODULES';
TB 1769         elseif($this->is_installed('apachectl')) $cmd = 'apachectl -t -D DUMP_MODULES';
60b700 1770         else {
MC 1771             $app->log("Could not check apache modules, apachectl not found.", LOGLEVEL_WARN);
1772             return array();
1773         }
1774         
0a0ca4 1775         exec($cmd . ' 2>/dev/null', $output, $return_var);
60b700 1776         if($return_var != 0 || !$output[0]) {
MC 1777             $app->log("Could not check apache modules, apachectl did not return any data.", LOGLEVEL_WARN);
1778             return array();
1779         }
1780         
1781         $modules = array();
1782         for($i = 0; $i < count($output); $i++) {
1783             if(preg_match('/^\s*(\w+)\s+\((shared|static)\)\s*$/', $output[$i], $matches)) {
1784                 $modules[] = $matches[1];
1785             }
1786         }
1787         
1788         return $modules;
1789     }
d67883 1790     
TB 1791     //* ISPConfig mail function
1792     public function mail($to, $subject, $text, $from, $filepath = '', $filetype = 'application/pdf', $filename = '', $cc = '', $bcc = '', $from_name = '') {
1793         global $app, $conf;
1794
1795         if($conf['demo_mode'] == true) $app->error("Mail sending disabled in demo mode.");
1796
1797         $app->uses('getconf,ispcmail');
1798         $mail_config = $app->getconf->get_global_config('mail');
1799         if($mail_config['smtp_enabled'] == 'y') {
1800             $mail_config['use_smtp'] = true;
1801             $app->ispcmail->setOptions($mail_config);
1802         }
1803         $app->ispcmail->setSender($from, $from_name);
1804         $app->ispcmail->setSubject($subject);
1805         $app->ispcmail->setMailText($text);
1806
1807         if($filepath != '') {
1808             if(!file_exists($filepath)) $app->error("Mail attachement does not exist ".$filepath);
1809             $app->ispcmail->readAttachFile($filepath);
1810         }
1811
1812         if($cc != '') $app->ispcmail->setHeader('Cc', $cc);
1813         if($bcc != '') $app->ispcmail->setHeader('Bcc', $bcc);
1814
1815         $app->ispcmail->send($to);
1816         $app->ispcmail->finish();
1817         
1818         return true;
1819     }
1820     
64ea56 1821     public function is_allowed_user($username, $check_id = true, $restrict_names = false) {
MC 1822         global $app;
1823         
f2fc77 1824         $name_blacklist = array('root','ispconfig','vmail','getmail');
TB 1825         if(in_array($username,$name_blacklist)) return false;
1826         
373e88 1827         if(preg_match('/^[a-zA-Z0-9\.\-_]{1,32}$/', $username) == false) return false;
f2fc77 1828         
64ea56 1829         if($check_id && intval($this->getuid($username)) < $this->min_uid) return false;
MC 1830         
1831         if($restrict_names == true && preg_match('/^web\d+$/', $username) == false) return false;
1832         
1833         return true;
1834     }
1835     
15687e 1836     public function is_allowed_group($groupname, $check_id = true, $restrict_names = false) {
64ea56 1837         global $app;
0cba4e 1838         
f2fc77 1839         $name_blacklist = array('root','ispconfig','vmail','getmail');
TB 1840         if(in_array($groupname,$name_blacklist)) return false;
0cba4e 1841         
373e88 1842         if(preg_match('/^[a-zA-Z0-9\.\-_]{1,32}$/', $groupname) == false) return false;
0cba4e 1843         
15687e 1844         if($check_id && intval($this->getgid($groupname)) < $this->min_gid) return false;
0cba4e 1845         
64ea56 1846         if($restrict_names == true && preg_match('/^client\d+$/', $groupname) == false) return false;
0cba4e 1847         
64ea56 1848         return true;
MC 1849     }
1850     
e2d6ed 1851 }
7fe908 1852
3b4c28 1853 ?>