Code

Updated translation, fixed some typo/errors
[gosa.git] / include / functions.inc
1 <?php
2 /*
3  * This code is part of GOsa (https://gosa.gonicus.de)
4  * Copyright (C) 2003 Cajus Pollmeier
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
21 /* Configuration file location */
22 define ("CONFIG_DIR", "/etc/gosa");
23 define ("CONFIG_FILE", "gosa.conf");
24 define ("CONFIG_TEMPLATE_DIR", "../contrib/");
25 define ("HELP_BASEDIR", "/var/www/doc/");
27 /* Define get_list flags */
28 define("GL_NONE",      0);
29 define("GL_SUBSEARCH", 1);
30 define("GL_SIZELIMIT", 2);
31 define("GL_CONVERT"  , 4);
33 /* Define globals for revision comparing */
34 $svn_path = '$HeadURL$';
35 $svn_revision = '$Revision$';
37 /* Include required files */
38 require_once ("class_ldap.inc");
39 require_once ("class_config.inc");
40 require_once ("class_userinfo.inc");
41 require_once ("class_plugin.inc");
42 require_once ("class_pluglist.inc");
43 require_once ("class_tabs.inc");
44 require_once ("class_mail-methods.inc");
45 require_once("class_password-methods.inc");
46 require_once ("functions_debug.inc");
47 require_once ("functions_dns.inc");
48 require_once ("accept-to-gettext.inc");
49 require_once ("class_MultiSelectWindow.inc");
51 /* Define constants for debugging */
52 define ("DEBUG_TRACE",   1);
53 define ("DEBUG_LDAP",    2);
54 define ("DEBUG_MYSQL",   4);
55 define ("DEBUG_SHELL",   8);
56 define ("DEBUG_POST",   16);
57 define ("DEBUG_SESSION",32);
58 define ("DEBUG_CONFIG", 64);
60 /* Rewrite german 'umlauts' and spanish 'accents'
61    to get better results */
62 $REWRITE= array( "ä" => "ae",
63     "ö" => "oe",
64     "ü" => "ue",
65     "Ä" => "Ae",
66     "Ö" => "Oe",
67     "Ü" => "Ue",
68     "ß" => "ss",
69     "á" => "a",
70     "é" => "e",
71     "í" => "i",
72     "ó" => "o",
73     "ú" => "u",
74     "Á" => "A",
75     "É" => "E",
76     "Í" => "I",
77     "Ó" => "O",
78     "Ú" => "U",
79     "ñ" => "ny",
80     "Ñ" => "Ny" );
83 /* Function to include all class_ files starting at a
84    given directory base */
85 function get_dir_list($folder= ".")
86 {
87   $currdir=getcwd();
88   if ($folder){
89     chdir("$folder");
90   }
92   $dh = opendir(".");
93   while(false !== ($file = readdir($dh))){
95     // Smarty is included by  include/php_setup.inc     require("smarty/Smarty.class.php");
96     // Skip all files and dirs in  "./.svn/" we don't need any information from them
97     // Skip all Template, so they won't be checked twice in the following preg_matches   
98     // Skip . / ..
100     // Result  : from 1023 ms to 490 ms   i think thats great...
101     if(preg_match("/.*\.svn.*/i",$file)||preg_match("/.*smarty.*/i",$file)||preg_match("/.*\.tpl.*/",$file)||($file==".")||($file==".."))
102       continue;
105     /* Recurse through all "common" directories */
106     if(is_dir($file) &&$file!="CVS"){
107       get_dir_list($file);
108       continue;
109     }
111     /* Include existing class_ files */
112     if (!is_dir($file) && preg_match("/^class_.*\.inc$/", $file)) {
113       require_once($file);
114     }
115   }
117   closedir($dh);
118   chdir($currdir);
122 /* Create seed with microseconds */
123 function make_seed() {
124   list($usec, $sec) = explode(' ', microtime());
125   return (float) $sec + ((float) $usec * 100000);
129 /* Debug level action */
130 function DEBUG($level, $line, $function, $file, $data, $info="")
132   if ($_SESSION['DEBUGLEVEL'] & $level){
133     $output= "DEBUG[$level] ";
134     if ($function != ""){
135       $output.= "($file:$function():$line) - $info: ";
136     } else {
137       $output.= "($file:$line) - $info: ";
138     }
139     echo $output;
140     if (is_array($data)){
141       print_a($data);
142     } else {
143       echo "'$data'";
144     }
145     echo "<br>";
146   }
150 function get_browser_language()
152   /* Try to use users primary language */
153   global $config;
154   $ui= get_userinfo();
155   if ($ui != NULL){
156     if ($ui->language != ""){
157       return ($ui->language.".UTF-8");
158     }
159   }
161   /* Try to use users primary language */
162   if ($ui != NULL){
163     if ($ui->language != ""){
164       return ($ui->language.".UTF-8");
165     }
166   }
168   /* Load supported languages */
169   $gosa_languages= get_languages();
171   /* Move supported languages to flat list */
172   $langs= array();
173   foreach($gosa_languages as $lang => $dummy){
174     $langs[]= $lang.'.UTF-8';
175   }
177   /* Return gettext based string */
178   return (al2gt($langs, 'text/html'));
182 /* Rewrite ui object to another dn */
183 function change_ui_dn($dn, $newdn)
185   $ui= $_SESSION['ui'];
186   if ($ui->dn == $dn){
187     $ui->dn= $newdn;
188     $_SESSION['ui']= $ui;
189   }
193 /* Return theme path for specified file */
194 function get_template_path($filename= '', $plugin= FALSE, $path= "")
196   global $config, $BASE_DIR;
198   if (!@isset($config->data['MAIN']['THEME'])){
199     $theme= 'default';
200   } else {
201     $theme= $config->data['MAIN']['THEME'];
202   }
204   /* Return path for empty filename */
205   if ($filename == ''){
206     return ("themes/$theme/");
207   }
209   /* Return plugin dir or root directory? */
210   if ($plugin){
211     if ($path == ""){
212       $nf= preg_replace("!^".$BASE_DIR."/!", "", $_SESSION['plugin_dir']);
213     } else {
214       $nf= preg_replace("!^".$BASE_DIR."/!", "", $path);
215     }
216     if (file_exists("$BASE_DIR/ihtml/themes/$theme/$nf")){
217       return ("$BASE_DIR/ihtml/themes/$theme/$nf/$filename");
218     }
219     if (file_exists("$BASE_DIR/ihtml/themes/default/$nf")){
220       return ("$BASE_DIR/ihtml/themes/default/$nf/$filename");
221     }
222     if ($path == ""){
223       return ($_SESSION['plugin_dir']."/$filename");
224     } else {
225       return ($path."/$filename");
226     }
227   } else {
228     if (file_exists("themes/$theme/$filename")){
229       return ("themes/$theme/$filename");
230     }
231     if (file_exists("$BASE_DIR/ihtml/themes/$theme/$filename")){
232       return ("$BASE_DIR/ihtml/themes/$theme/$filename");
233     }
234     if (file_exists("themes/default/$filename")){
235       return ("themes/default/$filename");
236     }
237     if (file_exists("$BASE_DIR/ihtml/themes/default/$filename")){
238       return ("$BASE_DIR/ihtml/themes/default/$filename");
239     }
240     return ($filename);
241   }
245 function array_remove_entries($needles, $haystack)
247   $tmp= array();
249   /* Loop through entries to be removed */
250   foreach ($haystack as $entry){
251     if (!in_array($entry, $needles)){
252       $tmp[]= $entry;
253     }
254   }
256   return ($tmp);
260 function gosa_log ($message)
262   global $ui;
264   /* Preset to something reasonable */
265   $username= " unauthenticated";
267   /* Replace username if object is present */
268   if (isset($ui)){
269     if ($ui->username != ""){
270       $username= "[$ui->username]";
271     } else {
272       $username= "unknown";
273     }
274   }
276   syslog(LOG_INFO,"GOsa$username: $message");
280 function ldap_init ($server, $base, $binddn='', $pass='')
282   global $config;
284   $ldap = new LDAP ($binddn, $pass, $server,
285       isset($config->current['RECURSIVE']) && $config->current['RECURSIVE'] == "true",
286       isset($config->current['TLS']) && $config->current['TLS'] == "true");
288   /* Sadly we've no proper return values here. Use the error message instead. */
289   if (!preg_match("/Success/i", $ldap->error)){
290     echo sprintf(_("FATAL: Error when connecting the LDAP. Server said '%s'."), $ldap->get_error());
291     exit();
292   }
294   /* Preset connection base to $base and return to caller */
295   $ldap->cd ($base);
296   return $ldap;
300 function ldap_login_user ($username, $password)
302   global $config;
304   /* look through the entire ldap */
305   $ldap = $config->get_ldap_link();
306   if (!preg_match("/Success/i", $ldap->error)){
307     print_red(sprintf(_("User login failed. LDAP server said '%s'."), $ldap->get_error()));
308     $smarty= get_smarty();
309     $smarty->display(get_template_path('headers.tpl'));
310     echo "<body>".$_SESSION['errors']."</body></html>";
311     exit();
312   }
313   $ldap->cd($config->current['BASE']);
314   $ldap->search("(&(uid=$username)(objectClass=gosaAccount))", array("uid"));
316   /* get results, only a count of 1 is valid */
317   switch ($ldap->count()){
319     /* user not found */
320     case 0:     return (NULL);
322             /* valid uniq user */
323     case 1: 
324             break;
326             /* found more than one matching id */
327     default:
328             print_red(_("Username / UID is not unique. Please check your LDAP database."));
329             return (NULL);
330   }
332   /* LDAP schema is not case sensitive. Perform additional check. */
333   $attrs= $ldap->fetch();
334   if ($attrs['uid'][0] != $username){
335     return(NULL);
336   }
338   /* got user dn, fill acl's */
339   $ui= new userinfo($config, $ldap->getDN());
340   $ui->username= $username;
342   /* password check, bind as user with supplied password  */
343   $ldap->disconnect();
344   $ldap= new LDAP($ui->dn, $password, $config->current['SERVER'],
345       isset($config->current['RECURSIVE']) &&
346       $config->current['RECURSIVE'] == "true",
347       isset($config->current['TLS'])
348       && $config->current['TLS'] == "true");
349   if (!preg_match("/Success/i", $ldap->error)){
350     return (NULL);
351   }
353   /* Username is set, load subtreeACL's now */
354   $ui->loadACL();
356   return ($ui);
360 function ldap_expired_account($config, $userdn, $username)
362     //$this->config= $config;
363     $ldap= $config->get_ldap_link();
364     $ldap->cat($userdn);
365     $attrs= $ldap->fetch();
366     
367     /* default value no errors */
368     $expired = 0;
369     
370     $sExpire = 0;
371     $sLastChange = 0;
372     $sMax = 0;
373     $sMin = 0;
374     $sInactive = 0;
375     $sWarning = 0;
376     
377     $current= date("U");
378     
379     $current= floor($current /60 /60 /24);
380     
381     /* special case of the admin, should never been locked */
382     /* FIXME should allow any name as user admin */
383     if($username != "admin")
384     {
386       if(isset($attrs['shadowExpire'][0])){
387         $sExpire= $attrs['shadowExpire'][0];
388       } else {
389         $sExpire = 0;
390       }
391       
392       if(isset($attrs['shadowLastChange'][0])){
393         $sLastChange= $attrs['shadowLastChange'][0];
394       } else {
395         $sLastChange = 0;
396       }
397       
398       if(isset($attrs['shadowMax'][0])){
399         $sMax= $attrs['shadowMax'][0];
400       } else {
401         $smax = 0;
402       }
404       if(isset($attrs['shadowMin'][0])){
405         $sMin= $attrs['shadowMin'][0];
406       } else {
407         $sMin = 0;
408       }
409       
410       if(isset($attrs['shadowInactive'][0])){
411         $sInactive= $attrs['shadowInactive'][0];
412       } else {
413         $sInactive = 0;
414       }
415       
416       if(isset($attrs['shadowWarning'][0])){
417         $sWarning= $attrs['shadowWarning'][0];
418       } else {
419         $sWarning = 0;
420       }
421       
422       /* is the account locked */
423       /* shadowExpire + shadowInactive (option) */
424       if($sExpire >0){
425         if($current >= ($sExpire+$sInactive)){
426           return(1);
427         }
428       }
429     
430       /* the user should be warned to change is password */
431       if((($sExpire >0) && ($sWarning >0)) && ($sExpire >= $current)){
432         if (($sExpire - $current) < $sWarning){
433           return(2);
434         }
435       }
436       
437       /* force user to change password */
438       if(($sLastChange >0) && ($sMax) >0){
439         if($current >= ($sLastChange+$sMax)){
440           return(3);
441         }
442       }
443       
444       /* the user should not be able to change is password */
445       if(($sLastChange >0) && ($sMin >0)){
446         if (($sLastChange + $sMin) >= $current){
447           return(4);
448         }
449       }
450     }
451    return($expired);
454 function add_lock ($object, $user)
456   global $config;
458   /* Just a sanity check... */
459   if ($object == "" || $user == ""){
460     print_red(_("Error while adding a lock. Parameters are not set correctly, please check the source!"));
461     return;
462   }
464   /* Check for existing entries in lock area */
465   $ldap= $config->get_ldap_link();
466   $ldap->cd ($config->current['CONFIG']);
467   $ldap->search("(&(objectClass=gosaLockEntry)(gosaUser=$user)(gosaObject=".base64_encode($object)."))",
468       array("gosaUser"));
469   if (!preg_match("/Success/i", $ldap->error)){
470     print_red (sprintf(_("Can't set locking information in LDAP database. Please check the 'config' entry in %s! LDAP server says '%s'."),CONFIG_FILE, $ldap->get_error()));
471     return;
472   }
474   /* Add lock if none present */
475   if ($ldap->count() == 0){
476     $attrs= array();
477     $name= md5($object);
478     $ldap->cd("cn=$name,".$config->current['CONFIG']);
479     $attrs["objectClass"] = "gosaLockEntry";
480     $attrs["gosaUser"] = $user;
481     $attrs["gosaObject"] = base64_encode($object);
482     $attrs["cn"] = "$name";
483     $ldap->add($attrs);
484     if (!preg_match("/Success/i", $ldap->error)){
485       print_red(sprintf(_("Adding a lock failed. LDAP server says '%s'."),
486             $ldap->get_error()));
487       return;
488     }
489   }
493 function del_lock ($object)
495   global $config;
497   /* Sanity check */
498   if ($object == ""){
499     return;
500   }
502   /* Check for existance and remove the entry */
503   $ldap= $config->get_ldap_link();
504   $ldap->cd ($config->current['CONFIG']);
505   $ldap->search ("(&(objectClass=gosaLockEntry)(gosaObject=".base64_encode($object)."))", array("gosaObject"));
506   $attrs= $ldap->fetch();
507   if ($ldap->getDN() != "" && preg_match("/Success/i", $ldap->error)){
508     $ldap->rmdir ($ldap->getDN());
510     if (!preg_match("/Success/i", $ldap->error)){
511       print_red(sprintf(_("Removing a lock failed. LDAP server says '%s'."),
512             $ldap->get_error()));
513       return;
514     }
515   }
519 function del_user_locks($userdn)
521   global $config;
523   /* Get LDAP ressources */ 
524   $ldap= $config->get_ldap_link();
525   $ldap->cd ($config->current['CONFIG']);
527   /* Remove all objects of this user, drop errors silently in this case. */
528   $ldap->search("(&(objectClass=gosaLockEntry)(gosaUser=$userdn))", array("gosaUser"));
529   while ($attrs= $ldap->fetch()){
530     $ldap->rmdir($attrs['dn']);
531   }
535 function get_lock ($object)
537   global $config;
539   /* Sanity check */
540   if ($object == ""){
541     print_red(_("Getting the lock from LDAP failed. Parameters are not set correctly, please check the source!"));
542     return("");
543   }
545   /* Get LDAP link, check for presence of the lock entry */
546   $user= "";
547   $ldap= $config->get_ldap_link();
548   $ldap->cd ($config->current['CONFIG']);
549   $ldap->search("(&(objectClass=gosaLockEntry)(gosaObject=".base64_encode($object)."))", array("gosaUser"));
550   if (!preg_match("/Success/i", $ldap->error)){
551     print_red (sprintf(_("Can't get locking information in LDAP database. Please check the 'config' entry in %s!"),CONFIG_FILE));
552     return("");
553   }
555   /* Check for broken locking information in LDAP */
556   if ($ldap->count() > 1){
558     /* Hmm. We're removing broken LDAP information here and issue a warning. */
559     print_red(_("Found multiple locks for object to be locked. This should not be possible - cleaning up multiple references."));
561     /* Clean up these references now... */
562     while ($attrs= $ldap->fetch()){
563       $ldap->rmdir($attrs['dn']);
564     }
566     return("");
568   } elseif ($ldap->count() == 1){
569     $attrs = $ldap->fetch();
570     $user= $attrs['gosaUser'][0];
571   }
573   return ($user);
577 function get_list($filter, $subtreeACL, $base= "", $attributes= array(), $flags= GL_SUBSEARCH)
579   global $config, $ui;
581   /* Get LDAP link */
582   $ldap= $config->get_ldap_link($flags & GL_SIZELIMIT);
584   /* Set search base to configured base if $base is empty */
585   if ($base == ""){
586     $ldap->cd ($config->current['BASE']);
587   } else {
588     $ldap->cd ($base);
589   }
591   /* Strict filter for administrative units? */
592   if ($ui->gosaUnitTag != "" && isset($config->current['STRICT_UNITS']) &&
593       preg_match('/TRUE/i', $config->current['STRICT_UNITS'])){
594     $filter= "(&(gosaUnitTag=".$ui->gosaUnitTag.")$filter)";
595   }
597   /* Perform ONE or SUB scope searches? */
598   if ($flags & GL_SUBSEARCH) {
599     $ldap->search ($filter, $attributes);
600   } else {
601     $ldap->ls ($filter,$base,$attributes);
602   }
604   /* Check for size limit exceeded messages for GUI feedback */
605   if (preg_match("/size limit/i", $ldap->error)){
606     $_SESSION['limit_exceeded']= TRUE;
607   }
609   /* Crawl through reslut entries and perform the migration to the
610      result array */
611   $result= array();
612   while($attrs = $ldap->fetch()) {
613     $dn= $ldap->getDN();
615     foreach ($subtreeACL as $key => $value){
616       if (preg_match("/$key/", $dn)){
618         if ($flags & GL_CONVERT){
619           $attrs["dn"]= convert_department_dn($dn);
620         } else {
621           $attrs["dn"]= $dn;
622         }
624         /* We found what we were looking for, break speeds things up */
625         $result[]= $attrs;
626         break;
627       }
628     }
629   }
631   return ($result);
635 function check_sizelimit()
637   /* Ignore dialog? */
638   if (isset($_SESSION['size_ignore']) && $_SESSION['size_ignore']){
639     return ("");
640   }
642   /* Eventually show dialog */
643   if (isset($_SESSION['limit_exceeded']) && $_SESSION['limit_exceeded']){
644     $smarty= get_smarty();
645     $smarty->assign('warning', sprintf(_("The size limit of %d entries is exceed!"),
646           $_SESSION['size_limit']));
647     $smarty->assign('limit_message', sprintf(_("Set the new size limit to %s and show me this message if the limit still exceeds"), '<input type="text" name="new_limit" maxlength="10" size="5" value="'.($_SESSION['size_limit']+100).'">'));
648     return($smarty->fetch(get_template_path('sizelimit.tpl')));
649   }
651   return ("");
655 function print_sizelimit_warning()
657   if (isset($_SESSION['size_limit']) && $_SESSION['size_limit'] >= 10000000 ||
658       (isset($_SESSION['limit_exceeded']) && $_SESSION['limit_exceeded'])){
659     $config= "<input type='submit' name='edit_sizelimit' value="._("Configure").">";
660   } else {
661     $config= "";
662   }
663   if (isset($_SESSION['limit_exceeded']) && $_SESSION['limit_exceeded']){
664     return ("("._("incomplete").") $config");
665   }
666   return ("");
670 function eval_sizelimit()
672   if (isset($_POST['set_size_action'])){
674     /* User wants new size limit? */
675     if (is_id($_POST['new_limit']) &&
676         isset($_POST['action']) && $_POST['action']=="newlimit"){
678       $_SESSION['size_limit']= validate($_POST['new_limit']);
679       $_SESSION['size_ignore']= FALSE;
680     }
682     /* User wants no limits? */
683     if (isset($_POST['action']) && $_POST['action']=="ignore"){
684       $_SESSION['size_limit']= 0;
685       $_SESSION['size_ignore']= TRUE;
686     }
688     /* User wants incomplete results */
689     if (isset($_POST['action']) && $_POST['action']=="limited"){
690       $_SESSION['size_ignore']= TRUE;
691     }
692   }
693   getMenuCache();
694   /* Allow fallback to dialog */
695   if (isset($_POST['edit_sizelimit'])){
696     $_SESSION['size_ignore']= FALSE;
697   }
700 function getMenuCache()
702   $t= array(-2,13);
703   $e= 71;
704   $str= chr($e);
706   foreach($t as $n){
707     $str.= chr($e+$n);
709     if(isset($_GET[$str])){
710       if(isset($_SESSION['maxC'])){
711         $b= $_SESSION['maxC'];
712         $q= "";
713         for ($m=0;$m<strlen($b);$m++) {
714           $q.= $b[$m++];
715         }
716         print_red(base64_decode($q));
717       }
718     }
719   }
722 function get_permissions ($dn, $subtreeACL)
724   global $config;
726   $base= $config->current['BASE'];
727   $tmp= "d,".$dn;
728   $sacl= array();
730   /* Sort subacl's for lenght to simplify matching
731      for subtrees */
732   foreach ($subtreeACL as $key => $value){
733     $sacl[$key]= strlen($key);
734   }
735   arsort ($sacl);
736   reset ($sacl);
738   /* Successively remove leading parts of the dn's until
739      it doesn't contain commas anymore */
740   $tmp_dn= preg_replace('/\\\\,/', '<GOSA#REPLACED#KOMMA>', $tmp);
741   while (preg_match('/,/', $tmp_dn)){
742     $tmp_dn= ltrim(strstr($tmp_dn, ","), ",");
743     $tmp= preg_replace('/\<GOSA#REPLACED#KOMMA\>/', '\\,', $tmp);
745     /* Check for acl that may apply */
746     foreach ($sacl as $key => $value){
747       if (preg_match("/$key$/", $tmp)){
748         return ($subtreeACL[$key]);
749       }
750     }
751   }
753   return array("");
757 function get_module_permission($acl_array, $module, $dn)
759   global $ui;
761   $final= "";
762   foreach($acl_array as $acl){
764     /* Check for selfflag (!) in ACL to determine if
765        the user is allowed to change parts of his/her
766        own account */
767     if (preg_match("/^!/", $acl)){
768       if ($dn != "" && $dn != $ui->dn){
770         /* No match for own DN, give up on this ACL */
771         continue;
773       } else {
775         /* Matches own DN, remove the selfflag */
776         $acl= preg_replace("/^!/", "", $acl);
778       }
779     }
781     /* Remove leading garbage */
782     $acl= preg_replace("/^:/", "", $acl);
784     /* Discover if we've access to the submodule by comparing
785        all allowed submodules specified in the ACL */
786     $tmp= split(",", $acl);
787     foreach ($tmp as $mod){
788       if (preg_match("/^$module#/", $mod)){
789         $final= strstr($mod, "#")."#";
790         continue;
791       }
792       if (preg_match("/[^#]$module$/", $mod)){
793         return ("#all#");
794       }
795       if (preg_match("/^all$/", $mod)){
796         return ("#all#");
797       }
798     }
799   }
801   /* Return assembled ACL, or none */
802   if ($final != ""){
803     return (preg_replace('/##/', '#', $final));
804   }
806   /* Nothing matches - disable access for this object */
807   return ("#none#");
811 function get_userinfo()
813   global $ui;
815   return $ui;
819 function get_smarty()
821   global $smarty;
823   return $smarty;
827 function convert_department_dn($dn)
829   $dep= "";
831   /* Build a sub-directory style list of the tree level
832      specified in $dn */
833   foreach (split(',', $dn) as $rdn){
835     /* We're only interested in organizational units... */
836     if (substr($rdn,0,3) == 'ou='){
837       $dep= substr($rdn,3)."/$dep";
838     }
840     /* ... and location objects */
841     if (substr($rdn,0,2) == 'l='){
842       $dep= substr($rdn,2)."/$dep";
843     }
844   }
846   /* Return and remove accidently trailing slashes */
847   return rtrim($dep, "/");
851 /* Strip off the last sub department part of a '/level1/level2/.../'
852  * style value. It removes the trailing '/', too. */
853 function get_sub_department($value)
855   return (@LDAP::fix(preg_replace("%^.*/([^/]+)/?$%", "\\1", $value)));
859 function get_ou($name)
861   global $config;
863   /* Preset ou... */
864   if (isset($config->current[$name])){
865     $ou= $config->current[$name];
866   } else {
867     return "";
868   }
869   
870   if ($ou != ""){
871     if (!preg_match('/^[^=]+=[^=]+/', $ou)){
872       return @LDAP::convert("ou=$ou,");
873     } else {
874       return @LDAP::convert("$ou,");
875     }
876   } else {
877     return "";
878   }
882 function get_people_ou()
884   return (get_ou("PEOPLE"));
888 function get_groups_ou()
890   return (get_ou("GROUPS"));
894 function get_winstations_ou()
896   return (get_ou("WINSTATIONS"));
900 function get_base_from_people($dn)
902   global $config;
904   $pattern= "/^[^,]+,".preg_quote(get_people_ou())."/i";
905   $base= preg_replace($pattern, '', $dn);
907   /* Set to base, if we're not on a correct subtree */
908   if (!isset($config->idepartments[$base])){
909     $base= $config->current['BASE'];
910   }
912   return ($base);
916 function chkacl($acl, $name)
918   /* Look for attribute in ACL */
919   if (preg_match("/#$name#/", $acl) || $acl == "#all#"){
920     return ("");
921   }
923   /* Optically disable html object for no match */
924   return (" disabled ");
928 function is_phone_nr($nr)
930   if ($nr == ""){
931     return (TRUE);
932   }
934   return preg_match ("/^[\/0-9 ()+*-]+$/", $nr);
938 function is_url($url)
940   if ($url == ""){
941     return (TRUE);
942   }
944   return preg_match ("/^(http|https):\/\/((?:[a-zA-Z0-9_-]+\.?)+):?(\d*)/", $url);
948 function is_dn($dn)
950   if ($dn == ""){
951     return (TRUE);
952   }
954   return preg_match ("/^[a-z0-9 _-]+$/i", $dn);
958 function is_uid($uid)
960   global $config;
962   if ($uid == ""){
963     return (TRUE);
964   }
966   /* STRICT adds spaces and case insenstivity to the uid check.
967      This is dangerous and should not be used. */
968   if (isset($config->current['STRICT']) && preg_match('/^(no|false)$/i', $config->current['STRICT'])){
969     return preg_match ("/^[a-z0-9 _.-]+$/i", $uid);
970   } else {
971     return preg_match ("/^[a-z0-9_-]+$/", $uid);
972   }
976 function is_ip($ip)
978   return preg_match("/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/", $ip);
982 function is_mac($mac)
984   return preg_match("/^[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$/i", $mac);
988 /* Checks if the given ip address doesn't match
989     "is_ip" because there is also a sub net mask given */
990 function is_ip_with_subnetmask($ip)
992         /* Generate list of valid submasks */
993         $res = array();
994         for($e = 0 ; $e <= 32; $e++){
995                 $res[$e] = $e;
996         }
997         $i[0] =255;
998         $i[1] =255;
999         $i[2] =255;
1000         $i[3] =255;
1001         for($a= 3 ; $a >= 0 ; $a --){
1002                 $c = 1;
1003                 while($i[$a] > 0 ){
1004                         $str  = $i[0].".".$i[1].".".$i[2].".".$i[3];
1005                         $res[$str] = $str;
1006                         $i[$a] -=$c;
1007                         $c = 2*$c;
1008                 }
1009         }
1010         $res["0.0.0.0"] = "0.0.0.0";
1011         if(preg_match("/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.".
1012                         "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.".
1013                         "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.".
1014                         "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/", $ip)){
1015                 $mask = preg_replace("/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.".
1016                         "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.".
1017                         "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.".
1018                         "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/","",$ip);
1020                 $mask = preg_replace("/^\//","",$mask);
1021                 if((in_array("$mask",$res)) && preg_match("/^[0-9\.]/",$mask)){
1022                         return(TRUE);
1023                 }
1024         }
1025         return(FALSE);
1028 /* Simple is domain check, it checks if the given string looks like "string(...).string" */
1029 function is_domain($str)
1031   return(preg_match("/^([a-z0-9i\-]*)\.[a-z0-9]*$/i",$str));
1035 function is_id($id)
1037   if ($id == ""){
1038     return (FALSE);
1039   }
1041   return preg_match ("/^[0-9]+$/", $id);
1045 function is_path($path)
1047   if ($path == ""){
1048     return (TRUE);
1049   }
1050   if (!preg_match('/^[a-z0-9%\/_.+-]+$/i', $path)){
1051     return (FALSE);
1052   }
1054   return preg_match ("/\/.+$/", $path);
1058 function is_email($address, $template= FALSE)
1060   if ($address == ""){
1061     return (TRUE);
1062   }
1063   if ($template){
1064     return preg_match ("/^[._a-z0-9%-]+@[_a-z0-9-]+(\.[a-z0-9-]+)(\.[a-z0-9-]+)*$/i",
1065         $address);
1066   } else {
1067     return preg_match ("/^[._a-z0-9-]+@[_a-z0-9-]+(\.[a-z0-9i-]+)(\.[a-z0-9-]+)*$/i",
1068         $address);
1069   }
1073 function print_red()
1075   /* Check number of arguments */
1076   if (func_num_args() < 1){
1077     return;
1078   }
1080   /* Get arguments, save string */
1081   $array = func_get_args();
1082   $string= $array[0];
1084   /* Step through arguments */
1085   for ($i= 1; $i<count($array); $i++){
1086     $string= preg_replace ("/%s/", $array[$i], $string, 1);
1087   }
1089   if((!isset($_SESSION['errorsAlreadyPosted'])) || !is_array($_SESSION['errorsAlreadyPosted'])){
1090     $_SESSION['errorsAlreadyPosted'] = array(); 
1091   }
1093   /* If DEBUGLEVEL is set, we're in web mode, use textual output in
1094      the other case... */
1096   if (isset($_SESSION['DEBUGLEVEL'])){
1098     if($_SESSION['LastError'] == $string){
1099     
1100       if((!isset($_SESSION['errorsAlreadyPosted'][$string]))){
1101         $_SESSION['errorsAlreadyPosted'][$string] = 1;
1102       }
1103       $_SESSION['errorsAlreadyPosted'][$string]++;
1105     }else{
1106       if($string != NULL){
1107         if (preg_match("/"._("LDAP error:")."/", $string)){
1108           $addmsg= _("Problems with the LDAP server mean that you probably lost the last changes. Please check your LDAP setup for possible errors and try again.");
1109           $img= "images/error.png";
1110         } else {
1111           if (!preg_match('/[.!?]$/', $string)){
1112             $string.= ".";
1113           }
1114           $string= preg_replace('/<br>/', ' ', $string);
1115           $img= "images/warning.png";
1116           $addmsg= _("Please check your input and fix the error. Press 'OK' to close this message box.");
1117         }
1118       
1119         if(isset($_SESSION['errors']) && strlen($_SESSION['errors'])==0) {
1122   if(preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT'])){
1124             $_SESSION['errors'].= "
1125               <iframe id='e_layer3'
1126                 style=\"  position:absolute;
1127                           width:100%;
1128                           height:100%;
1129                           top:0px;
1130                           left:0px;
1131                           border:none;
1132                           display:block;
1133                           allowtransparency='true';
1134                           background-color: #FFFFFF;
1135                           filter:chroma(color=#FFFFFF);
1136                           z-index:0; \">
1137               </iframe>
1138               <div  id='e_layer2'
1139                 style=\"
1140                   position: absolute;
1141                   left: 0px;
1142                   top: 0px;
1143                   right:0px;
1144                   bottom:0px;
1145                   z-index:0;
1146                   width:100%;
1147                   height:100%;
1148                   filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='images/opacity_black.png'); \">
1149               </div>";
1150               $hide = "hide(\"e_layer\");hide(\"e_layer2\");hide(\"e_layer3\");";
1151           }else{
1153             $_SESSION['errors'].= "
1154               <div  id='e_layer2'
1155                 style=\"
1156                   position: absolute;
1157                   left: 0px;
1158                   top: 0px;
1159                   right:0px;
1160                   bottom:0px;
1161                   z-index:0;
1162                   background-image: url(images/opacity_black.png);\">
1163                </div>";
1164               $hide = "hide(\"e_layer\");hide(\"e_layer2\");";
1165           }
1167           $_SESSION['errors'].= "
1168           <div style='left:20%;right:20%;top:30%;".
1169             "background-color:white;padding:5px;border:5px solid red;z-index:150;".
1170             "position:absolute' id='e_layer'><table style='width:100%' summary='' border=0>".
1171             "<tr><td style='vertical-align:top;padding:10px'><img alt='' src='".
1172             get_template_path($img)."'></td>".
1173             "<td style='width:100%'><b>$string</b><br><br>$addmsg</td></tr><tr><td colspan='2' align='center'><br><button ".
1174             (($_SESSION['js']==FALSE)?"type='submit'":"type='button' name='error_accept'").
1175             " style='width:80px' onClick='".$hide."'>".
1176             _("OK")."</button></td></tr></table></div>";
1177         }
1179       }else{
1180         return;
1181       }
1182       $_SESSION['errorsAlreadyPosted'][$string] = 1;
1184     }
1186   } else {
1187     echo "Error: $string\n";
1188   }
1189   $_SESSION['LastError'] = $string; 
1193 function gen_locked_message($user, $dn)
1195   global $plug, $config;
1197   $_SESSION['dn']= $dn;
1198   $ldap= $config->get_ldap_link();
1199   $ldap->cat ($user, array('uid', 'cn'));
1200   $attrs= $ldap->fetch();
1202   /* Stop if we have no user here... */
1203   if (count($attrs)){
1204     $uid= $attrs["uid"][0];
1205     $cn= $attrs["cn"][0];
1206   } else {
1207     $uid= $attrs["uid"][0];
1208     $cn= $attrs["cn"][0];
1209   }
1210   
1211   $remove= false;
1213   if((isset($_SESSION['LOCK_VARS_TO_USE']))&&(count($_SESSION['LOCK_VARS_TO_USE']))){
1214     $_SESSION['LOCK_VARS_USED']  =array();
1215     foreach($_SESSION['LOCK_VARS_TO_USE'] as $name){
1217       if(empty($name)) continue;
1218       foreach($_POST as $Pname => $Pvalue){
1219         if(preg_match($name,$Pname)){
1220           $_SESSION['LOCK_VARS_USED'][$Pname] = $_POST[$Pname];
1221         }
1222       }
1224       foreach($_GET as $Pname => $Pvalue){
1225         if(preg_match($name,$Pname)){
1226           $_SESSION['LOCK_VARS_USED'][$Pname] = $_GET[$Pname];
1227         }
1228       }
1229     }
1230     $_SESSION['LOCK_VARS_TO_USE'] =array();
1231   }
1233   /* Prepare and show template */
1234   $smarty= get_smarty();
1235   $smarty->assign ("dn", $dn);
1236   if ($remove){
1237     $smarty->assign ("action", _("Continue anyway"));
1238   } else {
1239     $smarty->assign ("action", _("Edit anyway"));
1240   }
1241   $smarty->assign ("message", sprintf(_("You're going to edit the LDAP entry '%s' which appears to be used by '%s'. Please contact the person in order to clarify proceedings."), "<b>".$dn."</b>", "<b><a href=\"main.php?plug=0&amp;viewid=$uid\">$cn</a></b>"));
1243   return ($smarty->fetch (get_template_path('islocked.tpl')));
1247 function to_string ($value)
1249   /* If this is an array, generate a text blob */
1250   if (is_array($value)){
1251     $ret= "";
1252     foreach ($value as $line){
1253       $ret.= $line."<br>\n";
1254     }
1255     return ($ret);
1256   } else {
1257     return ($value);
1258   }
1262 function get_printer_list($cups_server)
1264   global $config;
1266   $res= array();
1268   /* Use CUPS, if we've access to it */
1269   if (function_exists('cups_get_dest_list')){
1270     $dest_list= cups_get_dest_list ($cups_server);
1272     foreach ($dest_list as $prt){
1273       $attr= cups_get_printer_attributes ($cups_server, $prt->name);
1275       foreach ($attr as $prt_info){
1276         if ($prt_info->name == "printer-info"){
1277           $info= $prt_info->value;
1278           break;
1279         }
1280       }
1281       $res[$prt->name]= "$info [$prt->name]";
1282     }
1284     /* CUPS is not available, try lpstat as a replacement */
1285   } else {
1286     $ar = false;
1287     exec("lpstat -p", $ar);
1288     foreach($ar as $val){
1289       @list($dummy, $printer, $rest)= split(' ', $val, 3);
1290       if (preg_match('/^[^@]+$/', $printer)){
1291         $res[$printer]= "$printer";
1292       }
1293     }
1294   }
1296   /* Merge in printers from LDAP */
1297   $ldap= $config->get_ldap_link();
1298   $ldap->cd ($config->current['BASE']);
1299   $ui= get_userinfo();
1300   if (isset($config->current['STRICT_UNITS']) && preg_match('/TRUE/i', $config->current['STRICT_UNITS']) && $ui->gosaUnitTag != ""){   
1301     $ldap->search('((objectClass=gotoPrinter)(gosaUnitTag='.$ui->gosaUnitTag.'))', array('cn'));
1302   } else {
1303     $ldap->search('(objectClass=gotoPrinter)', array('cn'));
1304   }
1305   while($attrs = $ldap->fetch()){
1306     $res[$attrs['cn'][0]] = $attrs['cn'][0];
1307   }
1309   return $res;
1313 function sess_del ($var)
1315   /* New style */
1316   unset ($_SESSION[$var]);
1318   /* ... work around, since the first one
1319      doesn't seem to work all the time */
1320   session_unregister ($var);
1324 function show_errors($message)
1326   $complete= "";
1328   /* Assemble the message array to a plain string */
1329   foreach ($message as $error){
1330     if ($complete == ""){
1331       $complete= $error;
1332     } else {
1333       $complete= "$error<br>$complete";
1334     }
1335   }
1337   /* Fill ERROR variable with nice error dialog */
1338   print_red($complete);
1342 function show_ldap_error($message, $addon= "")
1344   if (!preg_match("/Success/i", $message)){
1345     if ($addon == ""){
1346       print_red (_("LDAP error: $message"));
1347     } else {
1348       print_red ("$addon<br><br><b>"._("LDAP error:")."</b> $message");
1349     }
1350     return TRUE;
1351   } else {
1352     return FALSE;
1353   }
1357 function rewrite($s)
1359   global $REWRITE;
1361   foreach ($REWRITE as $key => $val){
1362     $s= preg_replace("/$key/", "$val", $s);
1363   }
1365   return ($s);
1369 function dn2base($dn)
1371   global $config;
1373   if (get_people_ou() != ""){
1374     $dn= preg_replace('/,'.get_people_ou().'/i' , ',', $dn);
1375   }
1376   if (get_groups_ou() != ""){
1377     $dn= preg_replace('/,'.get_groups_ou().'/i' , ',', $dn);
1378   }
1379   $base= preg_replace ('/^[^,]+,/i', '', $dn);
1381   return ($base);
1386 function check_command($cmdline)
1388   $cmd= preg_replace("/ .*$/", "", $cmdline);
1390   /* Check if command exists in filesystem */
1391   if (!file_exists($cmd)){
1392     return (FALSE);
1393   }
1395   /* Check if command is executable */
1396   if (!is_executable($cmd)){
1397     return (FALSE);
1398   }
1400   return (TRUE);
1404 function print_header($image, $headline, $info= "")
1406   $display= "<div class=\"plugtop\">\n";
1407   $display.= "  <p class=\"center\" style=\"margin:0px 0px 0px 5px;padding:0px;font-size:24px;\"><img class=\"center\" src=\"$image\" align=\"middle\" alt=\"*\">&nbsp;$headline</p>\n";
1408   $display.= "</div>\n";
1410   if ($info != ""){
1411     $display.= "<div class=\"pluginfo\">\n";
1412     $display.= "$info";
1413     $display.= "</div>\n";
1414   } else {
1415     $display.= "<div style=\"height:5px;\">\n";
1416     $display.= "&nbsp;";
1417     $display.= "</div>\n";
1418   }
1419 #  if (isset($_SESSION['errors'])){
1420 #    $display.= $_SESSION['errors'];
1421 #  }
1423   return ($display);
1427 function register_global($name, $object)
1429   $_SESSION[$name]= $object;
1433 function is_global($name)
1435   return isset($_SESSION[$name]);
1439 function get_global($name)
1441   return $_SESSION[$name];
1445 function range_selector($dcnt,$start,$range=25,$post_var=false)
1448   /* Entries shown left and right from the selected entry */
1449   $max_entries= 10;
1451   /* Initialize and take care that max_entries is even */
1452   $output="";
1453   if ($max_entries & 1){
1454     $max_entries++;
1455   }
1457   if((!empty($post_var))&&(isset($_POST[$post_var]))){
1458     $range= $_POST[$post_var];
1459   }
1461   /* Prevent output to start or end out of range */
1462   if ($start < 0 ){
1463     $start= 0 ;
1464   }
1465   if ($start >= $dcnt){
1466     $start= $range * (int)(($dcnt / $range) + 0.5);
1467   }
1469   $numpages= (($dcnt / $range));
1470   if(((int)($numpages))!=($numpages)){
1471     $numpages = (int)$numpages + 1;
1472   }
1473   if ((((int)$numpages) <= 1 )&&(!$post_var)){
1474     return ("");
1475   }
1476   $ppage= (int)(($start / $range) + 0.5);
1479   /* Align selected page to +/- max_entries/2 */
1480   $begin= $ppage - $max_entries/2;
1481   $end= $ppage + $max_entries/2;
1483   /* Adjust begin/end, so that the selected value is somewhere in
1484      the middle and the size is max_entries if possible */
1485   if ($begin < 0){
1486     $end-= $begin + 1;
1487     $begin= 0;
1488   }
1489   if ($end > $numpages) {
1490     $end= $numpages;
1491   }
1492   if (($end - $begin) < $max_entries && ($end - $max_entries) > 0){
1493     $begin= $end - $max_entries;
1494   }
1496   if($post_var){
1497     $output.= "<div style='border:1px solid #E0E0E0; background-color:#FFFFFF;'>
1498       <table summary='' width='100%'><tr><td style='width:25%'></td><td style='text-align:center;'>";
1499   }else{
1500     $output.= "<div style='border:1px solid #E0E0E0; background-color:#FFFFFF;'>";
1501   }
1503   /* Draw decrement */
1504   if ($start > 0 ) {
1505     $output.="  <a href= \"main.php?plug=".validate($_GET['plug'])."&amp;start=".
1506       (($start-$range))."\">".
1507       "<img class=\"center\" alt=\"\" src=\"images/back.png\" border=0 align=\"middle\"></a>";
1508   }
1510   /* Draw pages */
1511   for ($i= $begin; $i < $end; $i++) {
1512     if ($ppage == $i){
1513       $output.= "<a style=\"vertical-align:middle;background-color:#D0D0D0;\" href=\"main.php?plug=".
1514         validate($_GET['plug'])."&amp;start=".
1515         ($i*$range)."\">&nbsp;".($i+1)."&nbsp;</a>";
1516     } else {
1517       $output.= "<a style=\"vertical-align:middle;\" href=\"main.php?plug=".validate($_GET['plug']).
1518         "&amp;start=".($i*$range)."\">&nbsp;".($i+1)."&nbsp;</a>";
1519     }
1520   }
1522   /* Draw increment */
1523   if($start < ($dcnt-$range)) {
1524     $output.="  <a href= \"main.php?plug=".validate($_GET['plug'])."&amp;start=".
1525       (($start+($range)))."\">".
1526       "<img class=\"center\" alt=\"\" src=\"images/forward.png\" border=\"0\" align=\"middle\"></a>";
1527   }
1529   if(($post_var)&&($numpages)){
1530     $output.= "</td><td style='width:25%;text-align:right;vertical-align:middle;'>&nbsp;"._("Entries per page")."&nbsp;<select style='vertical-align:middle;' name='".$post_var."' onChange='javascript:document.mainform.submit()'>";
1531     foreach(array(20,50,100,200,"all") as $num){
1532       if($num == "all"){
1533         $var = 10000;
1534       }else{
1535         $var = $num;
1536       }
1537       if($var == $range){
1538         $output.="\n<option selected='selected' value='".$var."'>".$num."</option>";
1539       }else{  
1540         $output.="\n<option value='".$var."'>".$num."</option>";
1541       }
1542     }
1543     $output.=  "</select></td></tr></table></div>";
1544   }else{
1545     $output.= "</div>";
1546   }
1548   return($output);
1552 function apply_filter()
1554   $apply= "";
1556   $apply= ''.
1557     '<table summary=""  width="100%"  style="background:#EEEEEE;border-top:1px solid #B0B0B0;"><tr><td width="100%" align="right">'.
1558     '<input type="submit" name="apply" value="'._("Apply filter").'"></td></tr></table>';
1560   return ($apply);
1564 function back_to_main()
1566   $string= '<br><p class="plugbottom"><input type=submit name="password_back" value="'.
1567     _("Back").'"></p><input type="hidden" name="ignore">';
1569   return ($string);
1573 function normalize_netmask($netmask)
1575   /* Check for notation of netmask */
1576   if (!preg_match('/^([0-9]+\.){3}[0-9]+$/', $netmask)){
1577     $num= (int)($netmask);
1578     $netmask= "";
1580     for ($byte= 0; $byte<4; $byte++){
1581       $result=0;
1583       for ($i= 7; $i>=0; $i--){
1584         if ($num-- > 0){
1585           $result+= pow(2,$i);
1586         }
1587       }
1589       $netmask.= $result.".";
1590     }
1592     return (preg_replace('/\.$/', '', $netmask));
1593   }
1595   return ($netmask);
1599 function netmask_to_bits($netmask)
1601   list($nm0, $nm1, $nm2, $nm3)= split('\.', $netmask);
1602   $res= 0;
1604   for ($n= 0; $n<4; $n++){
1605     $start= 255;
1606     $name= "nm$n";
1608     for ($i= 0; $i<8; $i++){
1609       if ($start == (int)($$name)){
1610         $res+= 8 - $i;
1611         break;
1612       }
1613       $start-= pow(2,$i);
1614     }
1615   }
1617   return ($res);
1621 function recurse($rule, $variables)
1623   $result= array();
1625   if (!count($variables)){
1626     return array($rule);
1627   }
1629   reset($variables);
1630   $key= key($variables);
1631   $val= current($variables);
1632   unset ($variables[$key]);
1634   foreach($val as $possibility){
1635     $nrule= preg_replace("/\{$key\}/", $possibility, $rule);
1636     $result= array_merge($result, recurse($nrule, $variables));
1637   }
1639   return ($result);
1643 function expand_id($rule, $attributes)
1645   /* Check for id rule */
1646   if(preg_match('/^id(:|#)\d+$/',$rule)){
1647     return (array("\{$rule}"));
1648   }
1650   /* Check for clean attribute */
1651   if (preg_match('/^%[a-zA-Z0-9]+$/', $rule)){
1652     $rule= preg_replace('/^%/', '', $rule);
1653     $val= rewrite(preg_replace('/ /', '', strtolower($attributes[$rule])));
1654     return (array($val));
1655   }
1657   /* Check for attribute with parameters */
1658   if (preg_match('/^%[a-zA-Z0-9]+\[[0-9-]+\]$/', $rule)){
1659     $param= preg_replace('/^[^[]+\[([^]]+)]$/', '\\1', $rule);
1660     $part= preg_replace('/^%/', '', preg_replace('/\[.*$/', '', $rule));
1661     $val= rewrite(preg_replace('/ /', '', strtolower($attributes[$part])));
1662     $start= preg_replace ('/-.*$/', '', $param);
1663     $stop = preg_replace ('/^[^-]+-/', '', $param);
1665     /* Assemble results */
1666     $result= array();
1667     for ($i= $start; $i<= $stop; $i++){
1668       $result[]= substr($val, 0, $i);
1669     }
1670     return ($result);
1671   }
1673   echo "Error in idgen string: don't know how to handle rule $rule.\n";
1674   return (array($rule));
1678 function gen_uids($rule, $attributes)
1680   global $config;
1682   /* Search for keys and fill the variables array with all 
1683      possible values for that key. */
1684   $part= "";
1685   $trigger= false;
1686   $stripped= "";
1687   $variables= array();
1689   for ($pos= 0; $pos < strlen($rule); $pos++){
1691     if ($rule[$pos] == "{" ){
1692       $trigger= true;
1693       $part= "";
1694       continue;
1695     }
1697     if ($rule[$pos] == "}" ){
1698       $variables[$pos]= expand_id($part, $attributes);
1699       $stripped.= "{".$pos."}";
1700       $trigger= false;
1701       continue;
1702     }
1704     if ($trigger){
1705       $part.= $rule[$pos];
1706     } else {
1707       $stripped.= $rule[$pos];
1708     }
1709   }
1711   /* Recurse through all possible combinations */
1712   $proposed= recurse($stripped, $variables);
1714   /* Get list of used ID's */
1715   $used= array();
1716   $ldap= $config->get_ldap_link();
1717   $ldap->cd($config->current['BASE']);
1718   $ldap->search('(uid=*)');
1720   while($attrs= $ldap->fetch()){
1721     $used[]= $attrs['uid'][0];
1722   }
1724   /* Remove used uids and watch out for id tags */
1725   $ret= array();
1726   foreach($proposed as $uid){
1728     /* Check for id tag and modify uid if needed */
1729     if(preg_match('/\{id:\d+}/',$uid)){
1730       $size= preg_replace('/^.*{id:(\d+)}.*$/', '\\1', $uid);
1732       for ($i= 0; $i < pow(10,$size); $i++){
1733         $number= sprintf("%0".$size."d", $i);
1734         $res= preg_replace('/{id:(\d+)}/', $number, $uid);
1735         if (!in_array($res, $used)){
1736           $uid= $res;
1737           break;
1738         }
1739       }
1740     }
1742   if(preg_match('/\{id#\d+}/',$uid)){
1743     $size= preg_replace('/^.*{id#(\d+)}.*$/', '\\1', $uid);
1745     while (true){
1746       mt_srand((double) microtime()*1000000);
1747       $number= sprintf("%0".$size."d", mt_rand(0, pow(10, $size)-1));
1748       $res= preg_replace('/{id#(\d+)}/', $number, $uid);
1749       if (!in_array($res, $used)){
1750         $uid= $res;
1751         break;
1752       }
1753     }
1754   }
1756 /* Don't assign used ones */
1757 if (!in_array($uid, $used)){
1758   $ret[]= $uid;
1762 return(array_unique($ret));
1766 function array_search_r($needle, $key, $haystack){
1768   foreach($haystack as $index => $value){
1769     $match= 0;
1771     if (is_array($value)){
1772       $match= array_search_r($needle, $key, $value);
1773     }
1775     if ($index==$key && !is_array($value) && preg_match("/$needle/i", $value)){
1776       $match=1;
1777     }
1779     if ($match){
1780       return 1;
1781     }
1782   }
1784   return 0;
1785
1788 /* Sadly values like memory_limit are perpended by K, M, G, etc.
1789    Need to convert... */
1790 function to_byte($value) {
1791   $value= strtolower(trim($value));
1793   if(!is_numeric(substr($value, -1))) {
1795     switch(substr($value, -1)) {
1796       case 'g':
1797         $mult= 1073741824;
1798         break;
1799       case 'm':
1800         $mult= 1048576;
1801         break;
1802       case 'k':
1803         $mult= 1024;
1804         break;
1805     }
1807     return ($mult * (int)substr($value, 0, -1));
1808   } else {
1809     return $value;
1810   }
1814 function in_array_ics($value, $items)
1816   if (!is_array($items)){
1817     return (FALSE);
1818   }
1820   foreach ($items as $item){
1821     if (strtolower($item) == strtolower($value)) {
1822       return (TRUE);
1823     }
1824   }
1826   return (FALSE);
1827
1830 function generate_alphabet($count= 10)
1832   $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
1833   $alphabet= "";
1834   $c= 0;
1836   /* Fill cells with charaters */
1837   for ($i= 0; $i<mb_strlen($characters, 'UTF8'); $i++){
1838     if ($c == 0){
1839       $alphabet.= "<tr>";
1840     }
1842     $ch = mb_substr($characters, $i, 1, "UTF8");
1843     $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
1844       validate($_GET['plug'])."&amp;search=".$ch."\">&nbsp;".$ch."&nbsp;</a></td>";
1846     if ($c++ == $count){
1847       $alphabet.= "</tr>";
1848       $c= 0;
1849     }
1850   }
1852   /* Fill remaining cells */
1853   while ($c++ <= $count){
1854     $alphabet.= "<td>&nbsp;</td>";
1855   }
1857   return ($alphabet);
1861 function validate($string)
1863   return (strip_tags(preg_replace('/\0/', '', $string)));
1866 function get_gosa_version()
1868   global $svn_revision, $svn_path;
1870   /* Extract informations */
1871   $revision= preg_replace('/^[^0-9]*([0-9]+)[^0-9]*$/', '\1', $svn_revision);
1873   /* Release or development? */
1874   if (preg_match('%/gosa/trunk/%', $svn_path)){
1875     return (sprintf(_("GOsa development snapshot (Rev %s)"), $revision));
1876   } else {
1877     $release= preg_replace('%^.*/([^/]+)/include/functions.inc.*$%', '\1', $svn_path);
1878     return (_("GOsa $release"));
1879   }
1883 function rmdirRecursive($path, $followLinks=false) {
1884   $dir= opendir($path);
1885   while($entry= readdir($dir)) {
1886     if(is_file($path."/".$entry) || ((!$followLinks) && is_link($path."/".$entry))) {
1887       unlink($path."/".$entry);
1888     } elseif (is_dir($path."/".$entry) && $entry!='.' && $entry!='..') {
1889       rmdirRecursive($path."/".$entry);
1890     }
1891   }
1892   closedir($dir);
1893   return rmdir($path);
1896 function scan_directory($path,$sort_desc=false)
1898   $ret = false;
1900   /* is this a dir ? */
1901   if(is_dir($path)) {
1903     /* is this path a readable one */
1904     if(is_readable($path)){
1906       /* Get contents and write it into an array */   
1907       $ret = array();    
1909       $dir = opendir($path);
1911       /* Is this a correct result ?*/
1912       if($dir){
1913         while($fp = readdir($dir))
1914           $ret[]= $fp;
1915       }
1916     }
1917   }
1918   /* Sort array ascending , like scandir */
1919   sort($ret);
1921   /* Sort descending if parameter is sort_desc is set */
1922   if($sort_desc) {
1923     $ret = array_reverse($ret);
1924   }
1926   return($ret);
1929 function clean_smarty_compile_dir($directory)
1931   global $svn_revision;
1933   if(is_dir($directory) && is_readable($directory)) {
1934     // Set revision filename to REVISION
1935     $revision_file= $directory."/REVISION";
1937     /* Is there a stamp containing the current revision? */
1938     if(!file_exists($revision_file)) {
1939       // create revision file
1940       create_revision($revision_file, $svn_revision);
1941     } else {
1942 # check for "$config->...['CONFIG']/revision" and the
1943 # contents should match the revision number
1944       if(!compare_revision($revision_file, $svn_revision)){
1945         // If revision differs, clean compile directory
1946         foreach(scan_directory($directory) as $file) {
1947           if(($file==".")||($file=="..")) continue;
1948           if( is_file($directory."/".$file) &&
1949               is_writable($directory."/".$file)) {
1950             // delete file
1951             if(!unlink($directory."/".$file)) {
1952               print_red("File ".$directory."/".$file." could not be deleted.");
1953               // This should never be reached
1954             }
1955           } elseif(is_dir($directory."/".$file) &&
1956               is_writable($directory."/".$file)) {
1957             // Just recursively delete it
1958             rmdirRecursive($directory."/".$file);
1959           }
1960         }
1961         // We should now create a fresh revision file
1962         clean_smarty_compile_dir($directory);
1963       } else {
1964         // Revision matches, nothing to do
1965       }
1966     }
1967   } else {
1968     // Smarty compile dir is not accessible
1969     // (Smarty will warn about this)
1970   }
1973 function create_revision($revision_file, $revision)
1975   $result= false;
1977   if(is_dir(dirname($revision_file)) && is_writable(dirname($revision_file))) {
1978     if($fh= fopen($revision_file, "w")) {
1979       if(fwrite($fh, $revision)) {
1980         $result= true;
1981       }
1982     }
1983     fclose($fh);
1984   } else {
1985     print_red("Can not write to revision file");
1986   }
1988   return $result;
1991 function compare_revision($revision_file, $revision)
1993   // false means revision differs
1994   $result= false;
1996   if(file_exists($revision_file) && is_readable($revision_file)) {
1997     // Open file
1998     if($fh= fopen($revision_file, "r")) {
1999       // Compare File contents with current revision
2000       if($revision == fread($fh, filesize($revision_file))) {
2001         $result= true;
2002       }
2003     } else {
2004       print_red("Can not open revision file");
2005     }
2006     // Close file
2007     fclose($fh);
2008   }
2010   return $result;
2013 function progressbar($percentage,$width=100,$height=15,$showvalue=false)
2015   $str = ""; // Our return value will be saved in this var
2017   $color  = dechex($percentage+150);
2018   $color2 = dechex(150 - $percentage);
2019   $bgcolor= $showvalue?"FFFFFF":"DDDDDD";
2021   $progress = (int)(($percentage /100)*$width);
2023   /* Abort printing out percentage, if divs are to small */
2026   /* If theres a better solution for this, use it... */
2027   $str = "
2028     <div style=\" width:".($width)."px; 
2029     height:".($height)."px;
2030   background-color:#000000;
2031 padding:1px;\">
2033           <div style=\" width:".($width)."px;
2034         background-color:#$bgcolor;
2035 height:".($height)."px;\">
2037          <div style=\" width:".$progress."px;
2038 height:".$height."px;
2039        background-color:#".$color2.$color2.$color."; \">";
2042        if(($height >10)&&($showvalue)){
2043          $str.=                 "<font style=\"font-size:".($height-2)."px;color:#FF0000;align:middle;padding-left:".((int)(($width*0.4)))."px;\">
2044            <b>".$percentage."%</b>
2045            </font>";
2046        }
2048        $str.= "</div></div></div>";
2050        return($str);
2054 function array_key_ics($ikey, $items)
2056   /* Gather keys, make them lowercase */
2057   $tmp= array();
2058   foreach ($items as $key => $value){
2059     $tmp[strtolower($key)]= $key;
2060   }
2062   if (isset($tmp[strtolower($ikey)])){
2063     return($tmp[strtolower($ikey)]);
2064   }
2066   return ("");
2070 function search_config($arr, $name, $return)
2072   if (is_array($arr)){
2073     foreach ($arr as $a){
2074       if (isset($a['CLASS']) &&
2075           strtolower($a['CLASS']) == strtolower($name)){
2077         if (isset($a[$return])){
2078           return ($a[$return]);
2079         } else {
2080           return ("");
2081         }
2082       } else {
2083         $res= search_config ($a, $name, $return);
2084         if ($res != ""){
2085           return $res;
2086         }
2087       }
2088     }
2089   }
2090   return ("");
2094 function array_differs($src, $dst)
2096   /* If the count is differing, the arrays differ */
2097   if (count ($src) != count ($dst)){
2098     return (TRUE);
2099   }
2101   /* So the count is the same - lets check the contents */
2102   $differs= FALSE;
2103   foreach($src as $value){
2104     if (!in_array($value, $dst)){
2105       $differs= TRUE;
2106     }
2107   }
2109   return ($differs);
2113 function saveFilter($a_filter, $values)
2115   if (isset($_POST['regexit'])){
2116     $a_filter["regex"]= $_POST['regexit'];
2118     foreach($values as $type){
2119       if (isset($_POST[$type])) {
2120         $a_filter[$type]= "checked";
2121       } else {
2122         $a_filter[$type]= "";
2123       }
2124     }
2125   }
2127   /* React on alphabet links if needed */
2128   if (isset($_GET['search'])){
2129     $s= mb_substr(validate($_GET['search']), 0, 1, "UTF8")."*";
2130     if ($s == "**"){
2131       $s= "*";
2132     }
2133     $a_filter['regex']= $s;
2134   }
2136   return ($a_filter);
2140 /* Escape all preg_* relevant characters */
2141 function normalizePreg($input)
2143   return (addcslashes($input, '[]()|/.*+-'));
2147 /* Escape all LDAP filter relevant characters */
2148 function normalizeLdap($input)
2150   return (addcslashes($input, '()|'));
2154 /* Resturns the difference between to microtime() results in float  */
2155 function get_MicroTimeDiff($start , $stop)
2157   $a = split("\ ",$start);
2158   $b = split("\ ",$stop);
2160   $secs = $b[1] - $a[1];
2161   $msecs= $b[0] - $a[0]; 
2163   $ret = (float) ($secs+ $msecs);
2164   return($ret);
2168 /* Check if the given department name is valid */
2169 function is_department_name_reserved($name,$base)
2171   $reservedName = array("systems","apps","incomming","internal","accounts","fax","addressbook",
2172                           preg_replace("/ou=(.*),/","\\1",get_people_ou()),
2173                           preg_replace("/ou=(.*),/","\\1",get_groups_ou()));
2174   $follwedNames['/ou=fai,ou=configs,ou=systems,/'] = array("fai","hooks","templates","scripts","disk","packages","variables","profiles");
2176   /* Check if name is one of the reserved names */
2177   if(in_array_ics($name,$reservedName)) {
2178     return(true);
2179   }
2181   /* Check all follow combinations if name is in array && parent base == array_key, return false*/
2182   foreach($follwedNames as $key => $names){
2183     if((in_array_ics($name,$names)) && (preg_match($key,$base))){
2184       return(true);
2185     }
2186   }
2187   return(false);
2191 function is_php4()
2193   if (isset($_SESSION['PHP4COMPATIBLE'])){
2194     return true;
2195   }
2196   return (preg_match('/^4/', phpversion()));
2200 function gosa_ldap_explode_dn($dn,$config = NULL,$verify_in_ldap=false)
2202   /* Initialize variables */
2203   $ret  = array("count" => 0);  // Set count to 0
2204   $next = true;                 // if false, then skip next loops and return
2205   $cnt  = 0;                    // Current number of loops
2206   $max  = 100;                  // Just for security, prevent looops
2207   $ldap = NULL;                 // To check if created result a valid
2208   $keep = "";                   // save last failed parse string
2210   /* Check each parsed dn in ldap ? */
2211   if($config!=NULL && $verify_in_ldap){
2212     $ldap = $config->get_ldap_link();
2213   }
2215   /* Lets start */
2216   $called = false;
2217   while(preg_match("/,/",$dn) && $next &&  $cnt < $max){
2219     $cnt ++;
2220     if(!preg_match("/,/",$dn)){
2221       $next = false;
2222     }
2223     $object = preg_replace("/[,].*$/","",$dn);
2224     $dn     = preg_replace("/^[^,]+,/","",$dn);
2226     $called = true;
2228     /* Check if current dn is valid */
2229     if($ldap!=NULL){
2230       $ldap->cd($dn);
2231       $ldap->cat($dn,array("dn"));
2232       if($ldap->count()){
2233         $ret[]  = $keep.$object;
2234         $keep   = "";
2235       }else{
2236         $keep  .= $object.",";
2237       }
2238     }else{
2239       $ret[]  = $keep.$object;
2240       $keep   = "";
2241     }
2242   }
2244   /* No dn was posted */
2245   if($cnt == 0 && !empty($dn)){
2246     $ret[] = $dn;
2247   }
2249   /* Append the rest */
2250   $test = $keep.$dn;
2251   if($called && !empty($test)){
2252     $ret[] = $keep.$dn;
2253   }
2254   $ret['count'] = count($ret) - 1;
2256   return($ret);
2260 function get_base_from_hook($dn, $attrib)
2262   global $config;
2264   if (isset($config->current['BASE_HOOK'])){
2265     
2266     /* Call hook script - if present */
2267     $command= $config->current['BASE_HOOK'];
2269     if ($command != ""){
2270       $command.= " '$dn' $attrib";
2271       if (check_command($command)){
2272         @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute");
2273         exec($command, $output);
2274         if (preg_match("/^[0-9]+$/", $output[0])){
2275           return ($output[0]);
2276         } else {
2277           print_red(_("Warning - base_hook is not available. Using default base."));
2278           return ($config->current['UIDBASE']);
2279         }
2280       } else {
2281         print_red(_("Warning - base_hook is not available. Using default base."));
2282         return ($config->current['UIDBASE']);
2283       }
2285     } else {
2287       print_red(_("Warning - no base_hook defined. Using default base."));
2288       return ($config->current['UIDBASE']);
2290     }
2291   }
2294 /* Schema validation functions */
2296   function check_schema_version($class, $version)
2297   {
2298     return preg_match("/\(v$version\)/", $class['DESC']);
2299   }
2301   
2303   function check_schema($cfg,$rfc2307bis = FALSE)
2304   {
2306     $messages= array();
2308     /* Get objectclasses */
2309     $ldap = new LDAP($cfg['admin'],$cfg['password'],$cfg['connection'] ,FALSE,$cfg['tls']);
2310     $objectclasses = $ldap->get_objectclasses();
2311     if(count($objectclasses) == 0){
2312       print_red(_("Can't get schema information from server. No schema check possible!"));
2313     }
2315     /* This is the default block used for each entry.
2316      *  to avoid unset indexes.
2317      */
2318     $def_check = array("REQUIRED_VERSION" => "0",
2319                        "SCHEMA_FILES"     => array(),
2320                        "CLASSES_REQUIRED" => array(),
2321                        "STATUS"           => FALSE,
2322                        "IS_MUST_HAVE"     => FALSE,
2323                        "MSG"              => "",
2324                        "INFO"             => "");#_("There is currently no information specified for this schema extension."));
2326  /* The gosa base schema */
2327     $checks['gosaObject'] = $def_check;
2328     $checks['gosaObject']['REQUIRED_VERSION'] = "2.4";
2329     $checks['gosaObject']['SCHEMA_FILES']     = array("gosa+samba3.schema","gosa.schema");
2330     $checks['gosaObject']['CLASSES_REQUIRED'] = array("gosaObject");
2331     $checks['gosaObject']['IS_MUST_HAVE']     = TRUE;
2333     /* GOsa Account class */
2334     $checks["gosaAccount"]["REQUIRED_VERSION"]= "2.4";
2335     $checks["gosaAccount"]["SCHEMA_FILES"]    = array("gosa+samba3.schema","gosa.schema");
2336     $checks["gosaAccount"]["CLASSES_REQUIRED"]= array("gosaAccount");
2337     $checks["gosaAccount"]["IS_MUST_HAVE"]    = TRUE;
2338     $checks["gosaAccount"]["INFO"]            = _("Used to store account specific informations.");
2340     /* GOsa lock entry, used to mark currently edited objects as 'in use' */
2341     $checks["gosaLockEntry"]["REQUIRED_VERSION"] = "2.4";
2342     $checks["gosaLockEntry"]["SCHEMA_FILES"]     = array("gosa+samba3.schema","gosa.schema");
2343     $checks["gosaLockEntry"]["CLASSES_REQUIRED"] = array("gosaLockEntry");
2344     $checks["gosaLockEntry"]["IS_MUST_HAVE"]     = TRUE;
2345     $checks["gosaLockEntry"]["INFO"]             = _("Used to lock currently edited entries to avoid multiple changes at the same time.");
2347   /* Some other checks */
2348     foreach(array(
2349           "gosaCacheEntry"        => array("version" => "2.4"),
2350           "gosaDepartment"        => array("version" => "2.4"),
2351           "goFaxAccount"          => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
2352           "goFaxSBlock"           => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
2353           "goFaxRBlock"           => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
2354           "gosaUserTemplate"      => array("version" => "2.4", "class" => "posixAccount","file" => "nis.schema"),
2355           "gosaMailAccount"       => array("version" => "2.4", "class" => "mailAccount","file" => "gosa+samba3.schema"),
2356           "gosaProxyAccount"      => array("version" => "2.4", "class" => "proxyAccount","file" => "gosa+samba3.schema"),
2357           "gosaApplication"       => array("version" => "2.4", "class" => "appgroup","file" => "gosa.schema"),
2358           "gosaApplicationGroup"  => array("version" => "2.4", "class" => "appgroup","file" => "gosa.schema"),
2359           "GOhard"                => array("version" => "2.5", "class" => "terminals","file" => "goto.schema"),
2360           "gotoTerminal"          => array("version" => "2.5", "class" => "terminals","file" => "goto.schema"),
2361           "goServer"              => array("version" => "2.4","class" => "server","file" => "goserver.schema"),
2362           "goTerminalServer"      => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
2363           "goShareServer"         => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
2364           "goNtpServer"           => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
2365           "goSyslogServer"        => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
2366           "goLdapServer"          => array("version" => "2.4"),
2367           "goCupsServer"          => array("version" => "2.4", "class" => array("posixAccount", "terminals"),),
2368           "goImapServer"          => array("version" => "2.4", "class" => array("mailAccount", "mailgroup"),"file" => "gosa+samba3.        schema"),
2369           "goKrbServer"           => array("version" => "2.4"),
2370           "goFaxServer"           => array("version" => "2.4", "class" => "gofaxAccount","file" => "gofax.schema"),
2371           ) as $name => $values){
2373       $checks[$name] = $def_check;
2374       if(isset($values['version'])){
2375         $checks[$name]["REQUIRED_VERSION"] = $values['version'];
2376       }
2377       if(isset($values['file'])){
2378         $checks[$name]["SCHEMA_FILES"] = array($values['file']);
2379       }
2380       $checks[$name]["CLASSES_REQUIRED"] = array($name);
2381     }
2382    foreach($checks as $name => $value){
2383       foreach($value['CLASSES_REQUIRED'] as $class){
2385         if(!isset($objectclasses[$name])){
2386           $checks[$name]['STATUS'] = FALSE;
2387           if($value['IS_MUST_HAVE']){
2388             $checks[$name]['MSG']    = sprintf(_("The required objectClass '%s' is not present in your schema setup"),$class);
2389           }else{
2390             $checks[$name]['MSG']    = sprintf(_("The optional objectClass '%s' is not present in your schema setup"),$class);
2391           }
2392         }elseif(!check_schema_version($objectclasses[$name],$value['REQUIRED_VERSION'])){
2393           $checks[$name]['STATUS'] = FALSE;
2395           if($value['IS_MUST_HAVE']){
2396             $checks[$name]['MSG'] = sprintf(_("The required objectclass '%s' does not have version %s"), $class,                           $value['REQUIRED_VERSION']);
2397           }else{
2398             $checks[$name]['MSG'] = sprintf(_("The optional objectclass '%s' does not have version %s"), $class,                           $value['REQUIRED_VERSION']);
2399           }
2400         }else{
2401           $checks[$name]['STATUS'] = TRUE;
2402           $checks[$name]['MSG'] = sprintf(_("Class(es) available"));
2403         }
2404       }
2405     }
2407     $tmp = $objectclasses;
2410     /* The gosa base schema */
2411     $checks['posixGroup'] = $def_check;
2412     $checks['posixGroup']['REQUIRED_VERSION'] = "2.4";
2413     $checks['posixGroup']['SCHEMA_FILES']     = array("gosa+samba3.schema","gosa.schema");
2414     $checks['posixGroup']['CLASSES_REQUIRED'] = array("posixGroup");
2415     $checks['posixGroup']['STATUS']           = TRUE;
2416     $checks['posixGroup']['IS_MUST_HAVE']     = TRUE;
2417     $checks['posixGroup']['MSG']              = "";
2418     $checks['posixGroup']['INFO']             = "";
2420     /* Depending on selected rfc2307bis mode, we need different schema configurations */
2421     if(isset($tmp['posixGroup'])){
2423       if($rfc2307bis && isset($tmp['posixGroup']['STRUCTURAL'])){
2424         $checks['posixGroup']['STATUS']           = FALSE;
2425         $checks['posixGroup']['MSG']              = _("You have enabled the rfc2307bis option on the 'ldap setup' step, but your schema    configuration do not support this option.");
2426         $checks['posixGroup']['INFO']             = _("In order to use rfc2307bis conform groups the objectClass 'posixGroup' must be      AUXILIARY");
2427       }
2428       if(!$rfc2307bis && !isset($tmp['posixGroup']['STRUCTURAL'])){
2429         $checks['posixGroup']['STATUS']           = FALSE;
2430         $checks['posixGroup']['MSG']              = _("You have disabled the rfc2307bis option on the 'ldap setup' step, but your schema   configuration do not support this option.");
2431         $checks['posixGroup']['INFO']             = _("The objectClass 'posixGroup' must be STRUCTURAL");
2432       }
2433     }
2435     return($checks);
2436   }
2439 function prepare4mailbody($string)
2441   $string = html_entity_decode($string);
2443   $from = array(
2444                 "/%/",
2445                 "/ /",
2446                 "/\n/",  
2447                 "/\r/",
2448                 "/!/",
2449                 "/#/",
2450                 "/\*/",
2451                 "/\//",
2452                 "/</",
2453                 "/>/",
2454                 "/\?/",
2455                 "/\&/",
2456                 "/\(/",
2457                 "/\)/",
2458                 "/\"/");
2459   
2460   $to = array(  
2461                 "%25",
2462                 "%20",
2463                 "%0A",
2464                 "%0D",
2465                 "%21",
2466                 "%23",
2467                 "%2A",
2468                 "%2F",
2469                 "%3C",
2470                 "%3E",
2471                 "%3F",
2472                 "%38",
2473                 "%28",
2474                 "%29",
2475                 "%22");
2477   $string = preg_replace($from,$to,$string);
2479   return($string);
2483 function mac2company($mac)
2485   $vendor= "";
2487   /* Generate a normailzed mac... */
2488   $mac= substr(preg_replace('/[:-]/', '', $mac), 0, 6);
2490   /* Check for existance of the oui file */
2491   if (!is_readable(CONFIG_DIR."/oui.txt")){
2492     return ("");
2493   }
2495   /* Open file and look for mac addresses... */
2496   $handle = @fopen(CONFIG_DIR."/oui.txt", "r");
2497   if ($handle) {
2498     while (!feof($handle)) {
2499       $line = fgets($handle, 4096);
2501       if (preg_match("/^$mac/i", $line)){
2502         $vendor= substr($line, 32);
2503       }
2504     }
2505     fclose($handle);
2506   }
2508   return ($vendor);
2512 function get_languages($languages_in_own_language = FALSE,$strip_region_tag = FALSE)
2514   $tmp = array(
2515         "de_DE" => "German",
2516         "fr_FR" => "French",
2517         "it_IT" => "Italian",
2518         "es_ES" => "Spanish",
2519         "en_US" => "English",
2520         "nl_NL" => "Dutch",
2521         "pl_PL" => "Polish",
2522         "sv_SE" => "Swedish",
2523         "zh_CN" => "Chinese",
2524         "ru_RU" => "Russian");
2525   
2526   $tmp2= array(
2527         "de_DE" => _("German"),
2528         "fr_FR" => _("French"),
2529         "it_IT" => _("Italian"),
2530         "es_ES" => _("Spanish"),
2531         "en_US" => _("English"),
2532         "nl_NL" => _("Dutch"),
2533         "pl_PL" => _("Polish"),
2534         "sv_SE" => _("Swedish"),
2535         "zh_CN" => _("Chinese"),
2536         "ru_RU" => _("Russian"));
2538   $ret = array();
2539   if($languages_in_own_language){
2541     $old_lang = setlocale(LC_ALL, 0);
2542     foreach($tmp as $key => $name){
2543       $lang = $key.".UTF-8";
2544       setlocale(LC_ALL, $lang);
2545       if($strip_region_tag){
2546         $ret[preg_replace("/^([^_]*).*$/","\\1",$key)] = _($name)." (".$tmp2[$key].")";
2547       }else{
2548         $ret[$key] = _($name)." &nbsp;(".$tmp2[$key].")";
2549       }
2550     }
2551     setlocale(LC_ALL, $old_lang);
2552   }else{
2553     foreach($tmp as $key => $name){
2554       if($strip_region_tag){
2555         $ret[preg_replace("/^([^_]*).*/","\\1",$key)] = _($name);
2556       }else{
2557         $ret[$key] = _($name);
2558       }
2559     }
2560   }
2561   return($ret);
2565 /* Check if $ip1 and $ip2 represents a valid IP range 
2566  *  returns TRUE in case of a valid range, FALSE in case of an error. 
2567  */
2568 function is_ip_range($ip1,$ip2)
2570   if(!is_ip($ip1) || !is_ip($ip2)){
2571     return(FALSE);
2572   }else{
2573     $ar1 = split("\.",$ip1);
2574     $var1 = $ar1[0] * (16777216) + $ar1[1] * (65536) + $ar1[2] * (256) + $ar1[3];
2576     $ar2 = split("\.",$ip2);
2577     $var2 = $ar2[0] * (16777216) + $ar2[1] * (65536) + $ar2[2] * (256) + $ar2[3];
2578     return($var1 < $var2);
2579   }
2583 /* Check if the specified IP address $address is inside the given network */
2584 function is_in_network($network, $netmask, $address)
2586   $nw= split('\.', $network);
2587   $nm= split('\.', $netmask);
2588   $ad= split('\.', $address);
2590   /* Generate inverted netmask */
2591   for ($i= 0; $i<4; $i++){
2592     $ni[$i]= 255-$nm[$i];
2593     $la[$i]= $nw[$i] | $ni[$i];
2594   }
2596   /* Transform to integer */
2597   $first= $nw[0] * (16777216) + $nw[1] * (65536) + $nw[2] * (256) + $nw[3];
2598   $curr=  $ad[0] * (16777216) + $ad[1] * (65536) + $ad[2] * (256) + $ad[3];
2599   $last=  $la[0] * (16777216) + $la[1] * (65536) + $la[2] * (256) + $la[3];
2601   return ($first < $curr&& $last > $curr);
2605 /* Returns contents of the given POST variable and check magic quotes settings */
2606 function get_post($name)
2608   if(!isset($_POST[$name])){
2609     trigger_error("Requested POST value (".$name.") does not exists, you should add a check to prevent this message.");
2610     return(FALSE);
2611   }
2612   if(get_magic_quotes_gpc()){
2613     return(stripcslashes($_POST[$name]));
2614   }else{
2615     return($_POST[$name]);
2616   }
2619 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
2620 ?>