Code

Fixed some typos in Kerberos Password handling
[gosa.git] / include / functions_setup.inc
1 <?php
3 function check_schema_version($description, $version)
4 {
5   $desc= preg_replace("/^.* DESC\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $description);
7   return preg_match("/\(v$version\)/", $desc);
8 }
11 function view_schema_check($table)
12 {
13   $message="<table summary=\"\" class=\"check\">";
15   foreach ($table as $key => $values){
16     $msg = $values['msg'];
17     $message.= "<tr><td class=\"check\">$msg";
19     if($values['status']) {
20       $message.="</td><td style='text-align:center' >
21         <img src=images/true.png alt='true' /></td></tr>";
22     } else {
23       $message.="</td><td style='text-align:center' >
24         <img src=images/button_cancel.png alt='false' /></td></tr>";
25     }
26   }
27   $message.="</table>";
29   return $message;
30 }
33 function is_schema_readable($server, $admin, $password)
34 {
35   $ldap = new LDAP($admin,$password,$server);
36   $tmp = $ldap->get_objectclasses();
38   if(count($tmp)){
39     return(true);
40   }
41   return(false);
42
44 function schema_check($server, $admin, $password, $aff=0,$CalledByIndexPhP=false)
45 {
46   global $config;
48   $messages= array();
49   $required_classes= array(
50       "gosaObject"            => array("version" => "2.4"),
51       "gosaAccount"           => array("version" => "2.4"),
52       "gosaLockEntry"         => array("version" => "2.4"),
53       "gosaCacheEntry"        => array("version" => "2.4"),
54       "gosaDepartment"        => array("version" => "2.4"),
56       "goFaxAccount"          => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
57       "goFaxSBlock"           => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
58       "goFaxRBlock"           => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
60       "gosaUserTemplate"      => array("version" => "2.4", "class" => "posixAccount","file" => "nis.schema"),
61       "gosaMailAccount"       => array("version" => "2.4", "class" => "mailAccount","file" => "gosa+samba3.schema"),
62       "gosaProxyAccount"      => array("version" => "2.4", "class" => "proxyAccount","file" => "gosa+samba3.schema"),
63       "gosaApplication"       => array("version" => "2.4", "class" => "appgroup","file" => "gosa.schema"),
64       "gosaApplicationGroup"  => array("version" => "2.4", "class" => "appgroup","file" => "gosa.schema"),
66       "GOhard"                => array("version" => "2.5", "class" => "terminals","file" => "goto.schema"),
67       "gotoTerminal"          => array("version" => "2.5", "class" => "terminals","file" => "goto.schema"),
68       "goServer"              => array("version" => "2.4","class" => "server","file" => "goserver.schema"),
69       "goTerminalServer"      => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
70       "goShareServer"           => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
71       "goNtpServer"           => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
72       "goSyslogServer"        => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
73       "goLdapServer"          => array("version" => "2.4"),
74       "goCupsServer"          => array("version" => "2.4", "class" => array("posixAccount", "terminals"),),
75       "goImapServer"          => array("version" => "2.4", "class" => array("mailAccount", "mailgroup"),"file" => "gosa+samba3.schema"),
76       "goKrbServer"           => array("version" => "2.4"),
77       "goFaxServer"           => array("version" => "2.4", "class" => "gofaxAccount","file" => "gofax.schema"),
78       );
80   /* Get objectclasses */
81   $ldap = new LDAP($admin,$password, $server);
82   $objectclasses = $ldap->get_objectclasses(); 
83   if(count($objectclasses) == 0){
84     return (array(array("msg" => _("Can't get schema information from server. No schema check possible!"), "status" => FALSE)));
85   }
87   /* Walk through objectclasses and check if they are needed or not */
88   foreach ($required_classes as $key => $value){
89     if (isset($value['class'])){
90       if (!is_array($value['class'])){
91         $classes= array($value['class']);
92       } else {
93         $classes= $value['class'];
94       }
96       /* Check if we are using the class that requires */
97       foreach($classes as $class){
98         if (!isset($objectclasses[$key])){
99           $messages[$key]['msg']= sprintf(_("Optional objectclass '%s' required by plugin '%s' is not present in LDAP setup"), $key, $class);
100           $messages[$key]['status'] = FALSE;
101         } else {
102           if (!check_schema_version($objectclasses[$key], $value['version'])){
103             $messages[$key]['msg']= sprintf(_("Optional objectclass '%s' required by plugin '%s' does not have version %s"), $key, $class, $value['version']);
104             $messages[$key]['needonstartup'] = TRUE;
105             $messages[$key]['status'] =FALSE;
106           }else {
107             if(!isset($affich2[$class])){
108               $affich2[$class]['msg']   = sprintf(_("Support for '%s' enabled"), $class)."<td class=\"check\"> ".$value['file']."</td>";
109               $affich2[$class]['status']= TRUE; 
110             }
111           }
112         }
114       }
115     } else {
116       /* Required class */
117       if (!isset($objectclasses[$key])){
118         $messages[$key]['msg']= sprintf(_("Required objectclass '%s' is not present in LDAP setup"), $key);
119         $messages[$key]['status'] = FALSE;  
120       } else {
121         if (!check_schema_version($objectclasses[$key], $value['version'])){
122           $messages[$key]['msg']= sprintf(_("Required objectclass '%s' does not have version %s"), $key, $value['version']);
123           $messages[$key]['status'] = FALSE;  
124           $messages[$key]['needonstartup'] = TRUE;
125         }
126     
127       }
128     }
129   }
131   /* Check for correct samba parameters */
132   if (!isset($objectclasses['sambaSamAccount'])){
133     $messages['samba3']['msg']= _("SAMBA 3 support disabled, no schema seems to be installed");
134     $affich['samba3']['msg']= $messages['samba3']['msg']."<td class=\"check\">gosa+samba3.schema</td>";
135     $messages['samba3']['status']= FALSE;
136     $affich['samba3']['status']= FALSE;
137   }else{
138     $affich['samba3']['msg']= _("SAMBA 3 support enabled")."<td class=\"check\">gosa+samba3.schema</td>";
139     $affich['samba3']['status']= TRUE;
140   }
142   if (!isset($objectclasses['sambaAccount'])){
143     $messages['samba2']['msg']= _("SAMBA 2 support disabled, no schema seems to be installed");
144     $affich['samba2']['msg']= $messages['samba2']['msg']."<td class=\"check\">samba.schema</td>";
145     $messages['samba2']['status']= FALSE;
146     $affich['samba2']['status']= FALSE;
147   }else{
148     $affich['samba2']['msg']= _("SAMBA 2 support enabled")."<td class=\"check\">samba.schema</td>";
149     $affich['samba2']['status']= TRUE;
150   }
152   /* Check pureftp/dns/ */
153   if (!isset($objectclasses['PureFTPdUser'])){
154     $messages['pureftp']['msg']= _("Support for pureftp disabled, no schema seems to be installed");
155     $affich['pureftp']['msg']= $messages['pureftp']['msg']."<td class=\"check\">pureftpd.schema</td>";
156     $messages['pureftp']['status']= FALSE;
157     $affich['pureftp']['status']= FALSE;
158   }else{
159     $affich['pureftp']['msg']= _("Support for pureftp enabled")."<td class=\"check\">pureftpd.schema</td>";
160     $affich['pureftp']['status']= TRUE;
161   }
163   if (!isset($objectclasses['gosaWebdavAccount'])){
164     $messages['webdav']['msg']= _("Support for WebDAV disabled, no schema seems to be installed");
165     $affich['webdav']['msg']= $messages['webdav']['msg']."<td class=\"check\"></td>";
166     $messages['webdav']['status']= FALSE;
167     $affich['webdav']['status']= FALSE;
168   }else{
169     $affich['webdav']['msg']=_("Support for WebDAV enabled")."<td class=\"check\">gosa+samba3.schema</td>";
170     $affich['webdav']['status']= TRUE;
171   }
173   if (!isset($objectclasses['phpgwAccount'])){
174     $messages['phpgroupware']['msg']= _("Support for phpgroupware disabled, no schema seems to be installed");
175     $affich['phpgroupware']['msg']= $messages['phpgroupware']['msg']."<td class=\"check\">phpgwaccount.schema</td>";
176     $messages['phpgroupware']['status']= FALSE;
177     $affich['phpgroupware']['status']= FALSE;
178   }else{
179     $affich['phpgroupware']['msg']= _("Support for phpgroupware enabled")."<td class=\"check\">phpgwaccount.schema</td>";
180     $affich['phpgroupware']['status']= TRUE;
181   }
182   
183   if (!isset($objectclasses['trustAccount'])){
184     $messages['trustAccount']['msg']= _("Support for trustAccount disabled, no schema seems to be installed");
185     $affich['trustAccount']['msg']= $messages['trustAccount']['msg']."<td class=\"check\">trust.schema</td>";
186     $messages['trustAccount']['status']= FALSE;
187     $affich['trustAccount']['status']= FALSE;
188   }else{
189     $affich['trustAccount']['msg']= _("Support for trustAccount enabled")."<td class=\"check\">trust.schema</td>";
190     $affich['trustAccount']['status']= TRUE;
191   }
193   if (!isset($objectclasses['goFonAccount'])){
194     $messages['phoneaccount']['msg']= _("Support for gofon disabled, no schema seems to be installed");
195     $affich['phoneaccount']['msg']= $messages['phoneaccount']['msg']."<td class=\"check\">gofon.schema</td>";
196     $messages['phoneaccount']['status']= FALSE;
197     $affich['phoneaccount']['status']= FALSE;
198   }else{
199     $affich['phoneaccount']['msg']= _("Support for gofon enabled")."<td class=\"check\">gofon.schema</td>";
200     $affich['phoneaccount']['status']= true;
201   }
203   if (!isset($objectclasses['nagiosContact'])){
204     $messages['nagioscontact']['msg']= _("Support for nagios disabled, no schema seems to be installed");
205     $affich['nagioscontact']['msg']= $messages['nagioscontact']['msg']."<td class=\"check\">nagios.schema</td>";
206     $messages['nagioscontact']['status']= FALSE;
207     $affich['nagioscontact']['status']= FALSE;
208   }else{
209     $affich['nagioscontact']['msg']= _("Support for nagios enabled")."<td class=\"check\">nagios.schema</td>";
210     $affich['nagioscontact']['status']= true;
211   }
212   
213   if ((!isset($objectclasses['apple-user'])) || (!isset($objectclasses['mount'])) ){
214     $messages['netatalk']['msg']= _("Support for netatalk disabled, no schema seems to be installed");
215     $affich['netatalk']['msg']= $messages['netatalk']['msg']."<td class=\"check\">apple.schema</td>";
216     $messages['netatalk']['status']= FALSE;
217     $affich['netatalk']['status']= FALSE;
218   }else{
219     $affich['netatalk']['msg']= _("Support for netatalk enabled")."<td class=\"check\">apple.schema</td>";
220     $affich['netatalk']['status']= true;
221   }
222   
223   /* Fix for PHP Fehler "Undefined index: ldapconf"
224    * Ablaufverfolgung[1]: Funktion schema_check Datei: /home/hickert/gosa/include/functions_setup.inc (Zeile 230)
225    */
226   if((isset($_SESSION['ldapconf']['mail_methods']))&&(isset($_SESSION['ldapconf']))){
227         if(($_SESSION['ldapconf']['mail_methods'][$_SESSION['ldapconf']['mail']] == "kolab")&&(!$CalledByIndexPhP)){
228           if(!isset($objectclasses['kolabInetOrgPerson']))  {
229             $messages['kolab']['msg']= _("Support for Kolab disabled, no schema seems to be installed, setting mail-method to cyrus");
230             $affich['kolab']['msg']=$messages['kolab']['msg']."<td class=\"check\">kolab2.schema</td>";
231             $tmp= array_flip($_SESSION['ldapconf']['mail_methods']);
232             $_SESSION['ldapconf']['mail']=$tmp['cyrus'];
233             $messages['kolab']['status']= FALSE;
234             $affich['kolab']['status']= FALSE;
235           }else{
236             $affich['kolab']['msg']=_("Support for Kolab enabled")."<td class=\"check\">gofon.schema</td>";
237             $affich['kolab']['status']= TRUE;
238           }
239         }
240   }
241   if($aff==0){
242     return ($messages);
243   } else {
244     return(array_merge($affich,$affich2));
245   }
249 function check(&$faults, $message, $description, $test, $required= TRUE)
251   $msg= "<table summary=\"\" class='check'><tr><td class='check' style='font-size:14px;'>$message</td>
252     <td rowspan=2 style='vertical-align:middle; text-align:center;width:45px;'>";
253   if ($test){
254     $msg.= _("OK")."<br>";
255   } else {
256     if (!$required){
257       $msg.="<font color=red>"._("Ignored")."</font><br>";
258     } else {
259       $msg.="<font color=red>"._("Failed")."</font><br>";
260       $faults++;
261     }
262   }
263   $msg.= "</td></tr><tr><td class='check' style='padding-left:20px;".
264     "background-color:#F0F0F0;'>$description</td></tr></table><br>";
266   return $msg;
269 function perform_php_checks(&$faults)
271   global $check_globals;
273   $faults= 0;
274   $msg= "";
276   $msg.= "<h1>"._("PHP setup inspection")."</h1>";
278   $msg.= check (        $faults, _("Checking for PHP version (>=4.1.0)"),
279       _("PHP must be of version 4.1.0 or above for some functions and known bugs in PHP language."),
280       version_compare(phpversion(), "4.1.0")>=0);
282   $msg.= check (        $faults, _("Checking if register_globals is set to 'off'"),
283       _("register_globals is a PHP mechanism to register all global varibales to be accessible from scripts without changing the scope. This may be a security risk. GOsa will run in both modes."),
284       $check_globals == 0, FALSE);
285   
286   $msg.= check (  $faults, _("PHP session.gc_maxlifetime (>= 86400 seconds)."),
287       _("PHP uses this value for the garbage collector to delete old sessions, setting this value to one day will prevent loosing session and cookie  before they really timeout."),
288       ini_get("session.gc_maxlifetime") >= 86400,FALSE);
290   $msg.= check (        $faults, _("Checking for ldap module"),
291       _("This is the main module used by GOsa and therefore really required."),
292       is_callable('ldap_bind'));
294   $msg.= check (  $faults, _("Checking for XML functions"),
295       _("XML functions are required to parse the configuration file."),
296       is_callable('xml_parser_create'));
298   $msg.= check (        $faults, _("Checking for gettext support"),
299       _("Gettext support is required for internationalized GOsa."),
300       is_callable('bindtextdomain'));
302   $msg.= check (        $faults, _("Checking for iconv support"),
303       _("This module is used by GOsa to convert samba munged dial informations and is therefore required."),
304       is_callable('iconv'));
306   $msg.= check (        $faults, _("Checking for mhash module"),
307       _("To use SSHA encryption, you'll need this module. If you are just using crypt or md5 encryption, ignore this message. GOsa will run without it."),
308       is_callable('mhash'), FALSE);
310   $msg.= check (        $faults, _("Checking for imap module"),
311       _("The IMAP module is needed to communicate with the IMAP server. It gets status informations, creates and deletes mail users."),
312       is_callable('imap_open'));
314   $msg.= check (        $faults, _("Checking for getacl in imap"),
315       _("The getacl support is needed for shared folder permissions. The standard IMAP module is not capable of reading acl's. You need a recend PHP version for this feature."),
316       is_callable('imap_getacl'), FALSE);
318   $msg.= check (        $faults, _("Checking for mysql module"),
319       _("MySQL support is needed for reading GOfax reports from databases."),
320       is_callable('mysql_query'), FALSE);
322   $msg.= check (        $faults, _("Checking for cups module"),
323       _("In order to read available printers from IPP protocol instead of printcap files, you've to install the CUPS module."),
324       is_callable('cups_get_dest_list'), FALSE);
326   $msg.= check (        $faults, _("Checking for kadm5 module"),
327       _("Managing users in kerberos requires the kadm5 module which is downloadable via PEAR network."),
328       is_callable('kadm5_init_with_password'), FALSE);
330   $msg.= check (  $faults, _("Checking for snmp Module"),
331       _("Simple Network Management Protocol (SNMP) is required for client monitoring."),
332       is_callable('snmpget'), FALSE);
334   return ($msg);
337 function get_link($function_name) {
338   $result= "<a href='http://de.php.net/manual/en/function.";
340   /* Replace all underscores with hyphens (phpdoc convention) */
341   /* hjb: added alternative check for GraphicsMagick >= 1.1.2 */
342   $function_name= str_replace("_", "-", $function_name);
344   /* Append to base URL */
345   $result.= $function_name.".php'>$function_name</a>";
347   return $result;
350 function perform_additional_function_checks(&$faults) {
351   global $check_globals;
353   $faults= 0;
354   $msg= "";
355   $functions= array();
356   
357   $functions_list= '../include/functions_list.inc';
359   /* Make sure that we can read the file */
360   if(is_readable($functions_list)) {
361     /* Open filehandle */
362     $fh= fopen($functions_list,'rb');
363     if($fh!=null) {
364       $functions= eval(fread($fh,filesize($functions_list)));
365     }
366   }
368   $msg.= "<h1>"._("PHP detailed function inspection")."</h1>";
369   /* Only print message, if function is not callable */
370   foreach($functions as $key => $fn_name) {
371     if(!is_callable($fn_name)) {
372       $msg.= check ($faults, sprintf(_("Checking for function %s"), "<b>".get_link($fn_name)."</b>"),
373         sprintf(_("The function %s is used by GOsa. There is no information if it's optional or required yet."), "<b>".get_link($fn_name)."</b>"),
374         is_callable($fn_name), false);
375     }
376   }
377   return $msg;
380 function perform_additional_checks(&$faults)
382   $ret = NULL;
383   /* Programm check */
384   $msg= "<h1>"._("Checking for some additional programms")."</h1>";
386   /* Image Magick */
387   $query= "LC_ALL=C LANG=C convert -help";
388   $output= shell_exec ($query);
389   if ($output != ""){
390     $lines= split ("\n", $output);
391     $version= preg_replace ("/^Version: (.+Magick) ([^\s]+).*/", "\\1 \\2", $lines[0]);
392     list($prog, $version) = split(" ", $version);
393     list($major, $minor,$minor2)= split("\.", $version);
394     if (preg_match('/GraphicsMagick/', $prog)) {
395       $msg.= check (    $faults, _("Checking for GraphicsMagick (>=1.1.2)"),
396           _("GraphicsMagick is used to convert user supplied images to fit the suggested size and the unified JPEG format."),
397           ($major > 1 || ($major == 1 && $minor >= 1) || ($major == 1 && $minor == 1 && $minor2 >= 2) ) );
398     } else {
399       $msg.= check (    $faults, _("Checking for ImageMagick (>=5.4.0)"),
400           _("ImageMagick is used to convert user supplied images to fit the suggested size and the unified JPEG format."),
401           ($major > 5 || ($major == 5 && $minor >= 4)));
402         }
403   } else {
404     $msg.= check (      $faults, _("Checking imagick module for PHP"),
405         _("Imagick is used to convert user supplied images to fit the suggested size and the unified JPEG format from PHP script."), function_exists('imagick_blob2image'), TRUE);
406   }
408   /* Check for fping */
409   $query= "LC_ALL=C LANG=C fping -v 2>&1";
410   $output= shell_exec ($query);
411   $have_fping= preg_match("/^fping:/", $output);
412   $msg.= check (        $faults, _("Checking for fping utility"),
413       _("The fping utility is only used if you've got a thin client based terminal environment running."),
414       $have_fping, FALSE);
416   /* Check for smb hash generation tool */
417   $query= "mkntpwd 2>&1";
418   $output= shell_exec ($query);
419   $have_mkntpwd= preg_match("/^Usage: mkntpwd /", $output);
420   $alt = 0;
422   if (!$have_mkntpwd){
423     $query= "LC_ALL=C LANG=C perl -MCrypt::SmbHash -e 'ntlmgen \"PASSWD\", \$lm, \$nt; print \"\${lm}:\${nt}\\n\";' &>/dev/null";
424     system ($query, $ret);
425     $alt= ($ret == 0);
426   }
428   $msg.= check (        $faults, _("Checking for a way to generate LM/NT password hashes"),
429       _("In order to use SAMBA 2/3, you've to install some additional packages to generate password hashes."),
430       ($have_mkntpwd || $alt));
432   /* seesio.auto_start should be off, in order to without trouble*/
433   $session_auto_start = ini_get('session.auto_start');
434   $implicit_flush     = ini_get('implicit_flush');
435   $max_execution_time = ini_get('max_execution_time');
436   $memory_limit       = ini_get('memory_limit');
437   $expose_php         = ini_get('expose_php');
438   $magic_quotes_gpc   = ini_get('magic_quotes_gpc');
439   $register_globals   = ini_get('register_globals');
441   /* auto_register */
442   $msg.= check (  $faults, _("php.ini check -> session.auto_register"),
443       _("In Order to use GOsa without any trouble, the session.auto_register option in your php.ini must be set to 'Off'."), (!$session_auto_start['local_value']));
445   /* implicit_flush */
446   $msg.= check (  $faults, _("php.ini check -> implicit_flush"),
447       _("This option influences the Output handling. Turn this Option off, to increase performance."),
448       !$implicit_flush['local_value'],0,false);
450   /* max_execution_time */
451   if($max_execution_time['local_value'] < 30 ){
452     $max_execution_time['local_value']=false;
453   }
454   $msg.= check (  $faults, _("php.ini check -> max_execution_time"),
455       _("The Execution time should be at least 30 seconds, because some actions may consume more time."),
456       $max_execution_time['local_value'],0,false);
458   /* memory_limit */
459   if($memory_limit['local_value'] < 16 ){
460     $memory_limit['local_value']=false;
461   }
462   $msg.= check (  $faults, _("php.ini check -> memory_limit"),
463       _("GOsa needs at least 16MB of memory, less will cause unpredictable errors! Increase it for larger setups."),
464       !$implicit_flush['local_value'],0,false);
466   /* expose_php */
467   $msg.= check (  $faults, _("php.ini check -> expose_php"),
468       _("Increase the server security by setting expose_php to 'off'. PHP won't send any Information about the server you are running in this case."),
469       !$implicit_flush['local_value'],0,false);
471   /* magic_quotes_gpc */
472   $msg.= check (  $faults, _("php.ini check -> magic_quotes_gpc"),
473       _("Increase your server security by setting magic_quotes_gpc to 'on'. PHP will escape all quotes in strings in this case."),
474       $magic_quotes_gpc['local_value'],0,false);
476   return $msg;
480 function parse_contrib_conf()
483   $str                = "";
484   $used_samba_version = 0;
485   $query              = ""; 
486   $fp                 = false;
487   $output             = "";
488   $needridbase_sid    = false;
489   $pwdhash            = "";
490   $replacements       = array();
491   $ldapconf           = $_SESSION['ldapconf']; // The Installation information
492   $classes            = $_SESSION['classes'];  // Class information needed to define which features are enabled
493   $possible_plugins   = array();
495   /* Which samba version do we use? */
496   if(isset($classes['samba3'])){
497     $used_samba_version = 2;
498   } else {
499     $used_samba_version = 3;
500   }
502   /* Look for samba password generation method */
503   if(file_exists("/usr/bin/mkntpasswd")){
504     $pwdhash  = "/usr/bin/mkntpasswd";
505   } elseif (preg_match("/^Usage: mkntpwd /", shell_exec ("mkntpwd 2>&1"))){
506     $pwdhash= "mkntpwd";
507   } else {
508     $pwdhash=('perl -MCrypt::SmbHash -e "ntlmgen \"\$ARGV[0]\", \$lm, \$nt; print \"\${lm}:\${nt}\n\";" $1');
509   }
512   /* Define which variables will be replaced */
513   $replacements['{LOCATIONNAME}']  = $ldapconf['location'];
514   $replacements['{SAMBAVERSION}']  = $used_samba_version;
515   $replacements['{LDAPBASE}']      = $ldapconf['base'];
516   $replacements['{LDAPADMIN}']     = $ldapconf['admin'];
517   $replacements['{UIDBASE}']       = $ldapconf['uidbase'];
518   $replacements['{DNMODE}']        = $ldapconf['peopledn'];
519   $replacements['{LDAPHOST}']      = $ldapconf['uri'];
520   $replacements['{PASSWORD}']      = $ldapconf['password'];
521   $replacements['{CRYPT}']         = $ldapconf['arr_cryptkeys'][$ldapconf['arr_crypts']];
522   $replacements['{SID}']         = "";
523   $replacements['{RIDBASE}']     = "";
524   if($ldapconf['mail'] != "disabled"){
525     $replacements['{MAILMETHOD}']    = $ldapconf['mail_methods'][$ldapconf['mail']];
526   }   
527   $replacements['{SMBHASH}']       = $pwdhash;
528   $replacements['{GOVERNMENTMODE}']= "false"; 
529   $replacements['{kolabAccount}']  = "";
530   $replacements['{servKolab}']     = "";
531   $replacements['{errorlvl}']     = $ldapconf['errorlvl'];
533   /* This array contains all preg_replace syntax to delete all unused plugins
534      THE kEY MUST BE THE CLASSNAME so we can check it with $ldapconf['classes'] */
536   $possible_plugins['fonreport'][]   = "'\n.*<plugin.*fonreport+.*\n.*>.*\n'i";
537   $possible_plugins['phoneaccount'][]= "'\n.*<tab.*phoneAccount.*>.*\n'i";
538   $possible_plugins['logview'][]     = "'\n.*<plugin.*logview+.*\n.*>.*\n'i";
539   $possible_plugins['pureftp'][]     = "'\n.*<tab.*pureftp.*>.*\n'i";
540   $possible_plugins['webdav'][]      = "'\n.*<tab.*webdav.*>.*\n'i";
541   $possible_plugins['phpgroupware'][]= "'\n.*<tab.*phpgroupware.*>.*\n'i";
542   $possible_plugins['netatalk'][0]    = "'\n.*<plugin.*netatalk+.*\n.*>.*\n'i";
543   $possible_plugins['netatalk'][1]    = "'\n.*<tab.*netatalk.*>.*\n'i";
545   /*Header information
546      Needed to send the generated gosa.conf to the browser */
547   header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
548   header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
549   header("Cache-Control: no-cache");
550   header("Pragma: no-cache");
551   header("Cache-Control: post-check=0, pre-check=0");
552   header("Content-type: text/plain");
554   if (preg_match('/MSIE 5.5/', $_SERVER['HTTP_USER_AGENT']) ||
555       preg_match('/MSIE 6.0/', $_SERVER['HTTP_USER_AGENT'])){
556     header('Content-Disposition: filename="gosa.conf"');
557   } else {
558     header('Content-Disposition: attachment; filename="gosa.conf"');
559   }
561   if(!$fp=fopen(CONFIG_TEMPLATE_DIR."/gosa.conf","r")) {
562     echo "Can't open file ".CONFIG_TEMPLATE_DIR."/gosa.conf";
563   } else {
564     while(!feof($fp)) {
565       $str.= fread($fp,512);
566     }
568     if($ldapconf['mail_methods'][$ldapconf['mail']]=="kolab") {
569       $replacements['{kolabAccount}']  ="<tab class=\"kolabAccount\" />\n     ";
570       $replacements['{servKolab}']     ="<tab class=\"servkolab\" name=\"Kolab\" />";
571     }
573     if($used_samba_version == 2) {
574       /* Do nothing for samba 2... */
575     } else {
576       /* Create LDAP connection, to check if there's a domain
577          object defined in the LDAP schema */
578       $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']);
580       /* Try to find a Samba Domain Objekt */
581       $ldap->search("(objectClass=sambaDomain)");
582     
583       /* Something found ??? so we need to define ridbase an SID by ourselfs */
584       if($ldap->count()< 1) {
585         $replacements['{SID}']= "sid=\"123412-11\"";
586         $replacements['{RIDBASE}']= "ridbase=\"1000\"";  
587       } 
588     }
590     /* Data readed, types replaced, samba version detected and checked if
591        we need to add SID and RIDBASE. Check if there is an ivbbentry in
592        the LDAP tree, in this case we will set the governmentmode to true.
593        Create LDAP connection, to check if theres a domain Objekt definen
594        in the LDAP schema. */
595     if(!isset($ldap)){
596       $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']);
597     }
599     /* Try to find a Samba Domain Objekt */
600     $ldap->search("(objectClass=ivbbentry)");
602     /* Something found ??? so we need to define ridbase an SID by ourselfs */
603     if($ldap->count()> 0) {
604       $replacements['{GOVERNMENTMODE}']= "true";
605     }
607     /* Replace all colleted information with placeholder */
608     foreach($replacements as $key => $val) {
609       $str = preg_replace("/".$key."/",$val,$str);
610     }    
612     if($ldapconf['mail'] == "disabled"){
613       $str = str_replace("mailMethod=\"{MAILMETHOD}\"","",$str);
614     }
616     /* Remove all unused plugins */
617     foreach(array_keys($possible_plugins) as $akey) {
618       if(array_key_exists($akey,$classes)) {
619         foreach($possible_plugins[$akey] as $key=>$val) {
620           $str = preg_replace($val,"\n",$str);
621         }
622       }
623     }
624   }
626   return ((($str)));
630 /* Show setup_page 1 */
631 function show_setup_page1($withoutput = true)
633   $faults   = false;
634   $faults2  = false;
635   $smarty = get_smarty();  
636   $smarty->assign ("content", get_template_path('setup_introduction.tpl'));
637   $smarty->assign ("tests", perform_php_checks($faults));
638   $smarty->assign ("detailed_tests", perform_additional_function_checks($faults2));
640   $faults = $faults || $faults2;
642   /* This var is true if anything went wrong */
643   if ($faults){
644     $smarty->assign("mode", "disabled");
645   }
647   /* This line displays the template only if (withoutput is set) */
648   if($withoutput){
649     $smarty->display (get_template_path('headers.tpl'));
650   }
652   if (isset($_SESSION['errors'])){
653     $smarty->assign("errors", $_SESSION['errors']);
654   }
656   if($withoutput){
657     $smarty->display (get_template_path('setup.tpl'));
658   }
660   return ($faults);
664 /* Show setup_page 2 */
665 function show_setup_page2($withoutput = true)
667   $faults = false;
668   $smarty = get_smarty();
669   $smarty->assign ("content", get_template_path('setup_step2.tpl'));
670   $smarty->assign ("tests", perform_additional_checks($faults));
672   if ($faults) {
673     $smarty->assign("mode", "disabled");
674   }
675   if($withoutput){
676     $smarty->display (get_template_path('headers.tpl'));
677   }
678   if (isset($_SESSION['errors']))  {
679     $smarty->assign("errors", $_SESSION['errors']);
680   }
681   if($withoutput){
682     $smarty->display (get_template_path('setup.tpl'));
683   }
685   return ($faults);                               
689 function show_setup_page3($withoutput = true)
691   $ds = NULL;
692   $smarty = get_smarty();
694   /* Take the Post oder the Sessioin saved data */
695   if(isset($_POST['uri'])){
696     $uri = $_POST['uri'];
697   } elseif(isset($_SESSION['ldapconf']['uri'])){
698     $uri = $_SESSION['ldapconf']['uri'];
699   }
701   /* If Page called first time, field is empty */
702   if((!isset($uri))||(empty($uri))){
703     $uri = "ldap://localhost:389";
704   }
706   /* if isset $uri save it to session */
707   if(isset($uri)) {
708     $_SESSION['ldapconf']['uri'] = $uri;
709     $smarty->assign ("uri", validate($uri));
710   }
712   /* No error till now */
713   $fault = false;
715   if (!$ds = @ldap_connect (validate($uri))) {
716     $fault =true;
718     /* Output the Error */
719     if($withoutput) {
720       print_red (_("Can't connect to the specified LDAP server! Please make sure that is reachable for GOsa."));
721       $smarty->assign ("uri", validate($uri));
722       $smarty->assign ("content", get_template_path('setup_step3.tpl'));
723     }
724   } else {
725     /* Try to bind the connection */    
726     ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
728     /* if we can't bind , print error */
729     if (!$r  =  @ldap_bind ($ds)) {
730       $fault = true;
732       /* Output the Error */
733       if($withoutput) {
734         print_red (_("Can't bind to the specified LDAP server! Please make sure that it is reachable for GOsa."));
735         $smarty->assign ("content", get_template_path('setup_step3.tpl'));
736         $smarty->assign ("uri", validate($uri));
737       }
738     } else {
739       $fault = false;
740     }
741   }
743   $smarty->assign ("content", get_template_path('setup_step3.tpl'));
745   /* Load Header */
746   if($withoutput){
747     $smarty->display (get_template_path('headers.tpl'));
748   }
750   /* Set Errors to Smarty */
751   if (isset($_SESSION['errors'])) {
752     $smarty->assign("errors", $_SESSION['errors']);
753   }
755   /* Print out Template */ 
756   if($withoutput){
757     $smarty->display (get_template_path('setup.tpl'));
758   }
760   return ($fault);                             
764 function show_setup_page4($withoutput = true)
766   $smarty= get_smarty();      
768   /* check POST data */
769   if(isset($_POST['check'])) {
771     /* Check if all needed vars are submitted */
772     foreach($checkvars as $key) {
773       if($key == "peopleou"){
774         continue;
775       }
776       if($key == "groupou"){
777         continue;
778       }
780       if((isset($_POST[$key]))&&($_POST[$key]!="")) {
781         $_SESSION['ldapconf'][$key] = $_POST[$key];
782       } else {
783         if($withoutput) {
784           print_red(sprintf(_("You're missing the required attribute '%s' from this formular. Please complete!"), $key));
785         }
786         $fault = true;
787       }
788     }
789   }
791   /* Transfer base */
792   if(isset($_POST['base'])){
793     $_SESSION['ldapconf']['base']= $_POST['base'];
794   }
796         // ?
797   if(!isset($_SESSION['ldapconf']['base'])){
798     $_SESSION['ldapconf']['base']= $base;
799   }
801   if(!isset($_SESSION['ldapconf']['base'])){
802     $_SESSION['ldapconf']['base']= $base;
803   }
804   require_once("class_password-methods.inc");
806   $fault     = false;              
807   $uri       = $_SESSION['ldapconf']['uri'];
808   $ldapconf  = $_SESSION['ldapconf'];
809   $arr_crypts= array();
810   $temp      = "";
811   $checkvars = array("location", "admin", "password", "peopleou", "base",
812       "peopledn", "arr_crypts", "mail", "uidbase","errorlvl");
814   if(!isset($_SESSION['ldapconf']['arr_cryptkeys'])) {
815     require_once("class_password-methods.inc");
816     $tmp= passwordMethod::get_available_methods_if_not_loaded();
817     $_SESSION['ldapconf']['arr_cryptkeys']= $tmp['name'];
818   }
820   if(!isset($_SESSION['ldapconf']['mail_methods'])) {
821     $_SESSION['ldapconf']['mail_methods']=array();
822     $temp = get_available_mail_classes();
823     $_SESSION['ldapconf']['mail_methods']= $temp['name'];
824   }
826   /* If there are some empty vars in ldapconnect -
827      these values also represent out default values */
828   if(!$ds =  @ldap_connect (validate($uri))){
829     $fault = true;
830     if($withoutput){
831       print_red (_("Can't connect to the specified LDAP server! Please make sure that is reachable for GOsa."));
832     }
833   } elseif(!@ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)){
834     $fault = true;
835     if($withoutput){
836       print_red (_("Can't set ldap protocol version 3."));
837     }
838   } elseif(!$r= @ldap_bind ($ds)){
839     $fault = true;
840     if($withoutput){
841       print_red (_("Could not bind to the specified LDAP server! Please make sure that it is reachable for GOsa."));
842     }
843   } else {
844     $sr=   @ldap_search ($r, NULL, "objectClass=*", array("namingContexts"));
845     $attr= @ldap_get_entries($ds,$sr);
847     if((empty($attr))) {
849       if($withoutput){
850 #        print_red(_("Bind to server successful, but the server seems to be completly empty, please check all information twice"));
851       }
853     } else {
854       $base= $attr[0]['dn'];
855     }
856   }
858   if(!isset($_SESSION['ldapconf']['base'])){
859     $_SESSION['ldapconf']['base']= $base;
860   }
861   if(!isset($_SESSION['ldapconf']['admin'])){
862     $_SESSION['ldapconf']['admin']= "cn=ldapadmin,".$base;
863   }
864   if(!isset($_SESSION['ldapconf']['peopleou'])){
865     $_SESSION['ldapconf']['peopleou']= "ou=people";
866   }
867   if(!isset($_SESSION['ldapconf']['groupou'])){
868     $_SESSION['ldapconf']['groupou']= "ou=groups";
869   }
870   if(!isset($_SESSION['ldapconf']['peopledn'])){
871     $_SESSION['ldapconf']['peopledn']= "cn";
872   }
873   if(!isset($_SESSION['ldapconf']['password'])){
874     $_SESSION['ldapconf']['password']= "";
875   }
876   if(!isset($_SESSION['ldapconf']['location'])){
877     $_SESSION['ldapconf']['location']= "Example";
878   }
879   if(!isset($_SESSION['ldapconf']['uidbase'])){
880     $_SESSION['ldapconf']['uidbase']= "1000";
881   }
882   if(!isset($_SESSION['ldapconf']['mail'])){
883     $_SESSION['ldapconf']['mail']= 0;
884   }
885   $tmp= array_flip($_SESSION['ldapconf']['arr_cryptkeys']);
886   if(!isset($_SESSION['ldapconf']['arr_crypts'])){
887     $_SESSION['ldapconf']['arr_crypts']   = $tmp['md5'];
888   }
890   $smarty->assign("arr_cryptkeys",$_SESSION['ldapconf']['arr_cryptkeys']);
891   $smarty->assign("mail_methods", $_SESSION['ldapconf']['mail_methods']);
893   foreach($_SESSION['ldapconf'] as $key => $val) {
894     $smarty->assign($key,$val);
895   }
897   if(isset($_POST['check']) || (isset($_POST['admin'])) && isset($_POST['password'])) {
898     $ldap= new LDAP($_SESSION['ldapconf']['admin'],
899         $_SESSION['ldapconf']['password'],
900         $_SESSION['ldapconf']['uri']);
902     $m= schema_check($_SESSION['ldapconf']['uri'],
903         $_SESSION['ldapconf']['admin'],
904         $_SESSION['ldapconf']['password']);
905     $_SESSION['classes']= $m;
907     if(!is_schema_readable($ldapconf['uri'],$ldapconf['admin'],$ldapconf['password'])){
908       if($withoutput){
909         print_red(_("Can't read schema informations, GOsa needs to know your schema setup. Please verify that it is readable for GOsa"));
910       }
911       $fault=true;
912     }
916     if ($ldap->error != "Success") {
917       if($withoutput) {
918         print_red(sprintf(_("Can't log into LDAP server. Reason was: %s."), $ldap->get_error()));
919       }
920       $fault = true;
921     }
922   }
924   /* Set smarty output */
925   $smarty->assign ("content", get_template_path('setup_step4.tpl'));
926   $smarty->assign ("peopledns", array("cn", "uid"));
927   if($withoutput){
928     $smarty->display (get_template_path('headers.tpl'));
929   }
930   if(isset($_SESSION['errors'])) {
931     $smarty->assign("errors", $_SESSION['errors']);
932   }
933   if($withoutput){
934     $smarty->display (get_template_path('setup.tpl'));
935   }
937   return ($fault);
941 function show_setup_page5($withoutput=true)
943   /* Get ldapconf */
944   $ldapconf= $_SESSION['ldapconf'];
946   /* get smarty */
947   $smarty = get_smarty();
949   if(isset($_SESSION['classes'])){
950     $classes = $_SESSION['classes'];
951   }
953   $info= posix_getgrgid(posix_getgid());
954   $smarty->assign("webgroup", $info['name']);
955   $smarty->assign("path", CONFIG_DIR);
956   $message= "<table summary=\"\" class=\"check\">";
957   $m= schema_check($ldapconf['uri'], $ldapconf['admin'], $ldapconf['password'],1);
959   if($withoutput) {
960     $smarty->assign ("schemas", view_schema_check($m));
961     $smarty->assign ("content", get_template_path('setup_finish.tpl'));
962   }
964   /* Output templates... */
965   if($withoutput){
966     $smarty->display (get_template_path('headers.tpl'));
967   }
968   if (isset($_SESSION['errors'])) {
969     $smarty->assign("errors", $_SESSION['errors']);
970   }
971   if($withoutput){
972     $smarty->display (get_template_path('setup.tpl'));
973   }
975   return(true);
979 function create_user_for_setup($withoutput=true)
981   global $samba;
983   $ldapconf = $_SESSION['ldapconf'];
984   $smarty = get_smarty();
985   
986   $need_to_create_group = false;
987   $need_to_create_user  = false;
989   $str_there="";
991   if(isset($_SESSION['classes'])){
992     $classes= $_SESSION['classes'];
993   }
995   /* Everything runns perfect ...
996      So we do a last test on this page
997      is there a user with ACLs :all which will be able to adminsitrate GOsa
998      We check that, if this user or group is missing we ask for creating them */
999   $ldap= new LDAP($_SESSION['ldapconf']['admin'],    $_SESSION['ldapconf']['password'],   $_SESSION['ldapconf']['uri']);
1001   /* 
1002   Now we are testing for a group, with the rights :all 
1003   */
1004   
1005   $ldap->cd($ldapconf['base']);
1006   $ldap->search("(&(objectClass=gosaObject)(gosaSubtreeACL=:all))");
1008   $group_cnt  = $ldap->count();
1009   $data       = $ldap->fetch();
1011 //  $str_there  = "Searching for Aminitrative users <br><br>";
1013   /* 
1014   We need to create administrative user and group  because theres no group found 
1015   */
1016   if($group_cnt < 1) {
1017     
1018     /* 
1019     Set var to create user 
1020     */
1021 //    $str_there  =   "no group found<br>";
1023     $need_to_create_group = true;
1024     $need_to_create_user  = true;
1027     /* Output error */
1028     if(($withoutput)&&(!isset($_POST['new_admin']))){
1029       print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!"));
1030     }
1031   } else {
1032     
1033 //    $str_there = "Group found <br>".$data['dn'];    
1035     $need_to_create_group = false;
1036  
1037     $ldap->clearResult();
1038    
1039     /* We found an Administrative Group, is there a user, too */
1040     if(isset($data['memberUid'][0])) {
1041       $str = "uid=".$data['memberUid']['0'];
1042       $ldap->search("(&(objectClass=gosaAccount)(objectClass=person)(".$str."))");
1043       $data2   = $ldap->fetch();
1044   
1045       /* We must create a user */
1046       if (($ldap->count() < 1)||(!isset($data2))) {
1047 //        $str_there.="Missing user";
1048         
1049         $need_to_create_user = true;
1050       
1051         if(($withoutput)&&(!isset($_POST['new_admin']))){
1052           print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!"));
1053         }
1054       }else {
1055 //        $str_there.="<br>User found <br>".$data2['dn'];
1056         $need_to_create_user = false;
1057       }
1058     } else {
1059       $need_to_create_user=true;
1060       if(($withoutput)&&(!isset($_POST['new_admin']))){
1061           print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!"));
1062         }   
1063 //      $str_there.="<br>No User found <br>";
1064     }
1065   }
1067   if(!($need_to_create_user&&$need_to_create_group))
1068     return(true);
1070   /* We need to create a new user with group */
1071   if(isset($_POST['new_admin']))
1072   {
1073   
1074     /* Adjust password attributes according to the samba version */
1075     if (isset($classes['samba3'])) {
1076       $samba= "2";
1077       $lmPassword = "lmPassword";
1078       $ntPassword = "ntPassword";
1079     } else {
1080       $samba= "3";
1081       $lmPassword = "sambaLMPassword";
1082       $ntPassword = "sambaNtPassword";
1083     }
1085     /* Nothing submitted */
1086     if(((empty($_POST['admin_name']))||(empty($_POST['admin_pass'])))) {
1087       return(true);
1088     }
1090     if($need_to_create_user) {
1091       /* We have the order to create an Admin */
1092       /* Define the user we are going to create */
1093       $dn= "cn=".$_POST['admin_name'].",".$ldapconf['peopleou'].",".$ldapconf['base'];
1094       $arr['objectClass'][0] ="person";
1095       $arr['objectClass'][1] ="organizationalPerson";
1096       $arr['objectClass'][2] ="inetOrgPerson";
1097       $arr['objectClass'][3] ="gosaAccount";
1098       $arr['uid']            = $_POST['admin_name'];
1099       $arr['cn']             = $_POST['admin_name'];
1100       $arr['sn']             = $_POST['admin_name'];
1101       $arr['givenName']      = "GOsa main administrator";
1102       $arr[$lmPassword]      = "10974C6EFC0AEE1917306D272A9441BB";
1103       $arr[$ntPassword]      = "38F3951141D0F71A039CFA9D1EC06378";
1104       $arr['userPassword']   = crypt_single($_POST['admin_pass'],"md5");
1105     
1107       if(!$ldap->dn_exists($dn)){ 
1108         $ldap->cd($dn); 
1109         $ldap->create_missing_trees($dn);
1110         $ldap->cd($dn);
1111         $ldap->add($arr);
1112         if($ldap->error!="Success"){
1113           print_red($ldap->error);
1114           print_red("Can't create user, and / or Group, possibly this problem  depends on an empty LDAP server. Check your configuration and try again!");
1115         }
1116       }    
1117     }
1119     /* There's already a group for administrator, so we only need to add the user */
1120     if(!$need_to_create_group) {
1121       if(!isset($data['memberUid'])) {
1122         $arrr['memberUid']= $_POST['admin_name'];
1123       } else {
1124         $data['memberUid'][$data['memberUid']['count']]=$_POST['admin_name'];
1125         $arrr['memberUid'] = $data['memberUid'];
1126         unset($arrr['memberUid']['count']);
1127   
1128         $tmp = array_reverse($arrr['memberUid']);    
1129         foreach($tmp as $tt){
1130           $tmp2[]=$tt;
1131         }
1132         $arrr['memberUid']= $tmp2;
1133 //        $str_there="Group found<br>".$data['dn'];
1134       }
1136       $ldap->cd($data['dn']);
1137       $ldap->modify($arrr);
1139     } else {
1140       $dn                    = "cn=administrators,".$ldapconf['groupou'].",".$ldapconf['base'];
1141       $arrr['objectClass'][0]= "gosaObject";
1142       $arrr['objectClass'][1]= "posixGroup";
1143       $arrr['gosaSubtreeACL']= ":all";
1144       $arrr['cn']            = "administrators";
1145       $arrr['gidNumber']     = "999";
1146       $arrr['memberUid']     = $_POST['admin_name'];
1148       $ldap->cd($dn);
1149       $ldap->create_missing_trees($dn);
1150       $ldap->cd($dn);
1152       $ldap->add($arrr);
1153     }
1154     return(true);
1155   } else {
1157     if((!isset($create_user))||(!($create_user))) {
1158       $smarty->assign ("content", get_template_path('setup_useradmin.tpl'));
1159       $smarty->assign("exists",true);
1160     } else {
1161       $smarty->assign ("content", get_template_path('setup_useradmin.tpl'));
1162       $smarty->assign("exists",false);
1163     }
1165   }
1167   /* Smarty output */ 
1168   if($withoutput){
1169     $smarty->display (get_template_path('headers.tpl'));
1170   }
1171   if (isset($_SESSION['errors'])) {
1172     $smarty->assign("errors", $_SESSION['errors']);
1173   }
1174   $smarty->assign("str_there",$str_there);
1175   if($withoutput){
1176     $smarty->display (get_template_path('setup.tpl'));
1177   }
1178   return(false);
1182 /* Returns the classnames auf the mail classes */
1183 function get_available_mail_classes()
1185   $dir = opendir( "../include");
1186   $methods = array();
1187   $suffix = "class_mail-methods-";
1188   $lensuf = strlen($suffix);
1189   $prefix = ".inc";
1190   $lenpre = strlen($prefix);
1192   $i = 0;
1193   while (($file = readdir($dir)) !== false){
1195     if(stristr($file,$suffix)) {
1196       $lenfile = strlen($file);
1197       $methods['name'][$i] = substr($file,$lensuf,($lenfile-$lensuf)-$lenpre);
1198       $methods['file'][$i] = $file;
1199       $methods[$i]['file'] = $file;
1200       $methods[$i]['name'] = substr($file,$lensuf,($lenfile-$lensuf)-$lenpre);
1201       $i++;
1202     }
1204   }
1206   return($methods);
1209 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1210 ?>