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 $ds= ldap_connect ($server);
36 if (!$ds) {
37 return (false);
38 }
39 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
40 $r= ldap_bind ($ds, $admin, $password);
42 /* Get base to look for schema */
43 $sr = @ldap_read ($ds, NULL, "objectClass=*", array("subschemaSubentry"));
44 $attr= @ldap_get_entries($ds,$sr);
45 if (!isset($attr[0]['subschemasubentry'][0])){
46 return (false);
47 }
49 $nb= $attr[0]['subschemasubentry'][0];
50 $objectclasses= array();
51 $sr= ldap_read ($ds, $nb, "objectClass=*", array("objectclasses"));
52 $attrs= ldap_get_entries($ds,$sr);
53 if (!isset($attrs[0])){
54 return (false);
55 }
56 return(true);
57 }
59 function schema_check($server, $admin, $password, $aff=0,$CalledByIndexPhP=false)
60 {
61 global $config;
63 $messages= array();
64 $required_classes= array(
65 "gosaObject" => array("version" => "2.4"),
66 "gosaAccount" => array("version" => "2.4"),
67 "gosaLockEntry" => array("version" => "2.4"),
68 "gosaCacheEntry" => array("version" => "2.4"),
69 "gosaDepartment" => array("version" => "2.4"),
71 "goFaxAccount" => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
72 "goFaxSBlock" => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
73 "goFaxRBlock" => array("version" => "1.0.4", "class" => "gofaxAccount","file" => "gofax.schema"),
75 "gosaUserTemplate" => array("version" => "2.4", "class" => "posixAccount","file" => "nis.schema"),
76 "gosaMailAccount" => array("version" => "2.4", "class" => "mailAccount","file" => "gosa+samba3.schema"),
77 "gosaProxyAccount" => array("version" => "2.4", "class" => "proxyAccount","file" => "gosa+samba3.schema"),
78 "gosaApplication" => array("version" => "2.4", "class" => "appgroup","file" => "gosa.schema"),
79 "gosaApplicationGroup" => array("version" => "2.4", "class" => "appgroup","file" => "gosa.schema"),
81 "GOhard" => array("version" => "2.5", "class" => "terminals","file" => "goto.schema"),
82 "gotoTerminal" => array("version" => "2.5", "class" => "terminals","file" => "goto.schema"),
83 "goServer" => array("version" => "2.4","class" => "server","file" => "goserver.schema"),
84 "goTerminalServer" => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
85 "goShareServer" => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
86 "goNtpServer" => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
87 "goSyslogServer" => array("version" => "2.4", "class" => "terminals","file" => "goto.schema"),
88 "goLdapServer" => array("version" => "2.4"),
89 "goCupsServer" => array("version" => "2.4", "class" => array("posixAccount", "terminals"),),
90 "goImapServer" => array("version" => "2.4", "class" => array("mailAccount", "mailgroup"),"file" => "gosa+samba3.schema"),
91 "goKrbServer" => array("version" => "2.4"),
92 "goFaxServer" => array("version" => "2.4", "class" => "gofaxAccount","file" => "gofax.schema"),
93 );
95 /* Get objectclasses */
96 $ldap = new LDAP($admin,$password, $server);
97 $objectclasses = $ldap->get_objectclasses();
98 if(count($objectclasses) == 0){
99 return (array(array("msg" => _("Can't get schema information from server. No schema check possible!"), "status" => FALSE)));
100 }
102 /* Walk through objectclasses and check if they are needed or not */
103 foreach ($required_classes as $key => $value){
104 if (isset($value['class'])){
105 if (!is_array($value['class'])){
106 $classes= array($value['class']);
107 } else {
108 $classes= $value['class'];
109 }
111 /* Check if we are using the class that requires */
112 foreach($classes as $class){
113 if (!isset($objectclasses[$key])){
114 $messages[$key]['msg']= sprintf(_("Optional objectclass '%s' required by plugin '%s' is not present in LDAP setup"), $key, $class);
115 $messages[$key]['status'] = FALSE;
116 } else {
117 if (!check_schema_version($objectclasses[$key], $value['version'])){
118 $messages[$key]['msg']= sprintf(_("Optional objectclass '%s' required by plugin '%s' does not have version %s"), $key, $class, $value['version']);
119 $messages[$key]['needonstartup'] = TRUE;
120 $messages[$key]['status'] =FALSE;
121 }else {
122 if(!isset($affich2[$class])){
123 $affich2[$class]['msg'] = sprintf(_("Support for '%s' enabled"), $class)."<td class=\"check\"> ".$value['file']."</td>";
124 $affich2[$class]['status']= TRUE;
125 }
126 }
127 }
129 }
130 } else {
131 /* Required class */
132 if (!isset($objectclasses[$key])){
133 $messages[$key]['msg']= sprintf(_("Required objectclass '%s' is not present in LDAP setup"), $key);
134 $messages[$key]['status'] = FALSE;
135 } else {
136 if (!check_schema_version($objectclasses[$key], $value['version'])){
137 $messages[$key]['msg']= sprintf(_("Required objectclass '%s' does not have version %s"), $key, $value['version']);
138 $messages[$key]['status'] = FALSE;
139 $messages[$key]['needonstartup'] = TRUE;
140 }
142 }
143 }
144 }
146 /* Check for correct samba parameters */
147 if (!isset($objectclasses['sambaSamAccount'])){
148 $messages['samba3']['msg']= _("SAMBA 3 support disabled, no schema seems to be installed");
149 $affich['samba3']['msg']= $messages['samba3']['msg']."<td class=\"check\">gosa+samba3.schema</td>";
150 $messages['samba3']['status']= FALSE;
151 $affich['samba3']['status']= FALSE;
152 }else{
153 $affich['samba3']['msg']= _("SAMBA 3 support enabled")."<td class=\"check\">gosa+samba3.schema</td>";
154 $affich['samba3']['status']= TRUE;
155 }
157 if (!isset($objectclasses['sambaAccount'])){
158 $messages['samba2']['msg']= _("SAMBA 2 support disabled, no schema seems to be installed");
159 $affich['samba2']['msg']= $messages['samba2']['msg']."<td class=\"check\">samba.schema</td>";
160 $messages['samba2']['status']= FALSE;
161 $affich['samba2']['status']= FALSE;
162 }else{
163 $affich['samba2']['msg']= _("SAMBA 2 support enabled")."<td class=\"check\">samba.schema</td>";
164 $affich['samba2']['status']= TRUE;
165 }
167 /* Check pureftp/dns/ */
168 if (!isset($objectclasses['PureFTPdUser'])){
169 $messages['pureftp']['msg']= _("Support for pureftp disabled, no schema seems to be installed");
170 $affich['pureftp']['msg']= $messages['pureftp']['msg']."<td class=\"check\">pureftpd.schema</td>";
171 $messages['pureftp']['status']= FALSE;
172 $affich['pureftp']['status']= FALSE;
173 }else{
174 $affich['pureftp']['msg']= _("Support for pureftp enabled")."<td class=\"check\">pureftpd.schema</td>";
175 $affich['pureftp']['status']= TRUE;
176 }
178 if (!isset($objectclasses['gosaWebdavAccount'])){
179 $messages['webdav']['msg']= _("Support for WebDAV disabled, no schema seems to be installed");
180 $affich['webdav']['msg']= $messages['webdav']['msg']."<td class=\"check\"></td>";
181 $messages['webdav']['status']= FALSE;
182 $affich['webdav']['status']= FALSE;
183 }else{
184 $affich['webdav']['msg']=_("Support for WebDAV enabled")."<td class=\"check\">gosa+samba3.schema</td>";
185 $affich['webdav']['status']= TRUE;
186 }
188 if (!isset($objectclasses['phpgwAccount'])){
189 $messages['phpgroupware']['msg']= _("Support for phpgroupware disabled, no schema seems to be installed");
190 $affich['phpgroupware']['msg']= $messages['phpgroupware']['msg']."<td class=\"check\">phpgwaccount.schema</td>";
191 $messages['phpgroupware']['status']= FALSE;
192 $affich['phpgroupware']['status']= FALSE;
193 }else{
194 $affich['phpgroupware']['msg']= _("Support for phpgroupware enabled")."<td class=\"check\">phpgwaccount.schema</td>";
195 $affich['phpgroupware']['status']= TRUE;
196 }
198 if (!isset($objectclasses['trustAccount'])){
199 $messages['trustAccount']['msg']= _("Support for trustAccount disabled, no schema seems to be installed");
200 $affich['trustAccount']['msg']= $messages['trustAccount']['msg']."<td class=\"check\">trust.schema</td>";
201 $messages['trustAccount']['status']= FALSE;
202 $affich['trustAccount']['status']= FALSE;
203 }else{
204 $affich['trustAccount']['msg']= _("Support for trustAccount enabled")."<td class=\"check\">trust.schema</td>";
205 $affich['trustAccount']['status']= TRUE;
206 }
208 if (!isset($objectclasses['goFonAccount'])){
209 $messages['phoneaccount']['msg']= _("Support for gofon disabled, no schema seems to be installed");
210 $affich['phoneaccount']['msg']= $messages['phoneaccount']['msg']."<td class=\"check\">gofon.schema</td>";
211 $messages['phoneaccount']['status']= FALSE;
212 $affich['phoneaccount']['status']= FALSE;
213 }else{
214 $affich['phoneaccount']['msg']= _("Support for gofon enabled")."<td class=\"check\">gofon.schema</td>";
215 $affich['phoneaccount']['status']= true;
216 }
218 if (!isset($objectclasses['nagiosContact'])){
219 $messages['nagioscontact']['msg']= _("Support for nagios disabled, no schema seems to be installed");
220 $affich['nagioscontact']['msg']= $messages['nagioscontact']['msg']."<td class=\"check\">nagios.schema</td>";
221 $messages['nagioscontact']['status']= FALSE;
222 $affich['nagioscontact']['status']= FALSE;
223 }else{
224 $affich['nagioscontact']['msg']= _("Support for nagios enabled")."<td class=\"check\">nagios.schema</td>";
225 $affich['nagioscontact']['status']= true;
226 }
228 if ((!isset($objectclasses['apple-user'])) || (!isset($objectclasses['mount'])) ){
229 $messages['netatalk']['msg']= _("Support for netatalk disabled, no schema seems to be installed");
230 $affich['netatalk']['msg']= $messages['netatalk']['msg']."<td class=\"check\">apple.schema</td>";
231 $messages['netatalk']['status']= FALSE;
232 $affich['netatalk']['status']= FALSE;
233 }else{
234 $affich['netatalk']['msg']= _("Support for netatalk enabled")."<td class=\"check\">apple.schema</td>";
235 $affich['netatalk']['status']= true;
236 }
238 /* Fix for PHP Fehler "Undefined index: ldapconf"
239 * Ablaufverfolgung[1]: Funktion schema_check Datei: /home/hickert/gosa/include/functions_setup.inc (Zeile 230)
240 */
241 if((isset($_SESSION['ldapconf']['mail_methods']))&&(isset($_SESSION['ldapconf']))){
242 if(($_SESSION['ldapconf']['mail_methods'][$_SESSION['ldapconf']['mail']] == "kolab")&&(!$CalledByIndexPhP)){
243 if(!isset($objectclasses['kolabInetOrgPerson'])) {
244 $messages['kolab']['msg']= _("Support for Kolab disabled, no schema seems to be installed, setting mail-method to cyrus");
245 $affich['kolab']['msg']=$messages['kolab']['msg']."<td class=\"check\">kolab2.schema</td>";
246 $tmp= array_flip($_SESSION['ldapconf']['mail_methods']);
247 $_SESSION['ldapconf']['mail']=$tmp['cyrus'];
248 $messages['kolab']['status']= FALSE;
249 $affich['kolab']['status']= FALSE;
250 }else{
251 $affich['kolab']['msg']=_("Support for Kolab enabled")."<td class=\"check\">gofon.schema</td>";
252 $affich['kolab']['status']= TRUE;
253 }
254 }
255 }
256 if($aff==0){
257 return ($messages);
258 } else {
259 return(array_merge($affich,$affich2));
260 }
261 }
264 function check(&$faults, $message, $description, $test, $required= TRUE)
265 {
266 $msg= "<table summary=\"\" class='check'><tr><td class='check' style='font-size:14px;'>$message</td>
267 <td rowspan=2 style='vertical-align:middle; text-align:center;width:45px;'>";
268 if ($test){
269 $msg.= _("OK")."<br>";
270 } else {
271 if (!$required){
272 $msg.="<font color=red>"._("Ignored")."</font><br>";
273 } else {
274 $msg.="<font color=red>"._("Failed")."</font><br>";
275 $faults++;
276 }
277 }
278 $msg.= "</td></tr><tr><td class='check' style='padding-left:20px;".
279 "background-color:#F0F0F0;'>$description</td></tr></table><br>";
281 return $msg;
282 }
284 function perform_php_checks(&$faults)
285 {
286 global $check_globals;
288 $faults= 0;
289 $msg= "";
291 $msg.= "<h1>"._("PHP setup inspection")."</h1>";
293 $msg.= check ( $faults, _("Checking for PHP version (>=4.1.0)"),
294 _("PHP must be of version 4.1.0 or above for some functions and known bugs in PHP language."),
295 version_compare(phpversion(), "4.1.0")>=0);
297 $msg.= check ( $faults, _("Checking if register_globals is set to 'off'"),
298 _("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."),
299 $check_globals == 0, FALSE);
301 $msg.= check ( $faults, _("PHP session.gc_maxlifetime (>= 86400 seconds)."),
302 _("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."),
303 ini_get("session.gc_maxlifetime") >= 86400,FALSE);
305 $msg.= check ( $faults, _("Checking for ldap module"),
306 _("This is the main module used by GOsa and therefore really required."),
307 is_callable('ldap_bind'));
309 $msg.= check ( $faults, _("Checking for XML functions"),
310 _("XML functions are required to parse the configuration file."),
311 is_callable('xml_parser_create'));
313 $msg.= check ( $faults, _("Checking for gettext support"),
314 _("Gettext support is required for internationalized GOsa."),
315 is_callable('bindtextdomain'));
317 $msg.= check ( $faults, _("Checking for iconv support"),
318 _("This module is used by GOsa to convert samba munged dial informations and is therefore required."),
319 is_callable('iconv'));
321 $msg.= check ( $faults, _("Checking for mhash module"),
322 _("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."),
323 is_callable('mhash'), FALSE);
325 $msg.= check ( $faults, _("Checking for imap module"),
326 _("The IMAP module is needed to communicate with the IMAP server. It gets status informations, creates and deletes mail users."),
327 is_callable('imap_open'));
329 $msg.= check ( $faults, _("Checking for getacl in imap"),
330 _("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."),
331 is_callable('imap_getacl'), FALSE);
333 $msg.= check ( $faults, _("Checking for mysql module"),
334 _("MySQL support is needed for reading GOfax reports from databases."),
335 is_callable('mysql_query'), FALSE);
337 $msg.= check ( $faults, _("Checking for cups module"),
338 _("In order to read available printers from IPP protocol instead of printcap files, you've to install the CUPS module."),
339 is_callable('cups_get_dest_list'), FALSE);
341 $msg.= check ( $faults, _("Checking for kadm5 module"),
342 _("Managing users in kerberos requires the kadm5 module which is downloadable via PEAR network."),
343 is_callable('kadm5_init_with_password'), FALSE);
345 $msg.= check ( $faults, _("Checking for snmp Module"),
346 _("Simple Network Management Protocol (SNMP) is required for client monitoring."),
347 is_callable('snmpget'), FALSE);
349 return ($msg);
350 }
352 function get_link($function_name) {
353 $result= "<a href='http://de.php.net/manual/en/function.";
355 /* Replace all underscores with hyphens (phpdoc convention) */
356 $function_name= str_replace("_", "-", $function_name);
358 /* Append to base URL */
359 $result.= $function_name.".php'>$function_name</a>";
361 return $result;
362 }
364 function perform_additional_function_checks(&$faults) {
365 global $check_globals;
367 $faults= 0;
368 $msg= "";
369 $functions= array();
371 $functions_list= '../include/functions_list.inc';
373 /* Make sure that we can read the file */
374 if(is_readable($functions_list)) {
375 /* Open filehandle */
376 $fh= fopen($functions_list,'rb');
377 if($fh!=null) {
378 $functions= eval(fread($fh,filesize($functions_list)));
379 }
380 }
382 $msg.= "<h1>"._("PHP detailed function inspection")."</h1>";
383 /* Only print message, if function is not callable */
384 foreach($functions as $key => $fn_name) {
385 if(!is_callable($fn_name)) {
386 $msg.= check ($faults, sprintf(_("Checking for function %s"), "<b>".get_link($fn_name)."</b>"),
387 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>"),
388 is_callable($fn_name), false);
389 }
390 }
391 return $msg;
392 }
394 function perform_additional_checks(&$faults)
395 {
396 $ret = NULL;
397 /* Programm check */
398 $msg= "<h1>"._("Checking for some additional programms")."</h1>";
400 /* Image Magick */
401 $query= "LC_ALL=C LANG=C convert -help";
402 $output= shell_exec ($query);
403 if ($output != ""){
404 $lines= split ("\n", $output);
405 $version= preg_replace ("/^Version:.+Magick ([^\s]+).*/", "\\1", $lines[0]);
406 list($major, $minor)= split("\.", $version);
407 $msg.= check ( $faults, _("Checking for ImageMagick (>=5.4.0)"),
408 _("ImageMagick is used to convert user supplied images to fit the suggested size and the unified JPEG format."),
409 ($major > 5 || ($major == 5 && $minor >= 4)));
410 } else {
411 $msg.= check ( $faults, _("Checking imagick module for PHP"),
412 _("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);
413 }
415 /* Check for fping */
416 $query= "LC_ALL=C LANG=C fping -v 2>&1";
417 $output= shell_exec ($query);
418 $have_fping= preg_match("/^fping:/", $output);
419 $msg.= check ( $faults, _("Checking for fping utility"),
420 _("The fping utility is only used if you've got a thin client based terminal environment running."),
421 $have_fping, FALSE);
423 /* Check for smb hash generation tool */
424 $query= "mkntpwd 2>&1";
425 $output= shell_exec ($query);
426 $have_mkntpwd= preg_match("/^Usage: mkntpwd /", $output);
427 $alt = 0;
429 if (!$have_mkntpwd){
430 $query= "LC_ALL=C LANG=C perl -MCrypt::SmbHash -e 'ntlmgen \"PASSWD\", \$lm, \$nt; print \"\${lm}:\${nt}\\n\";' &>/dev/null";
431 system ($query, $ret);
432 $alt= ($ret == 0);
433 }
435 $msg.= check ( $faults, _("Checking for a way to generate LM/NT password hashes"),
436 _("In order to use SAMBA 2/3, you've to install some additional packages to generate password hashes."),
437 ($have_mkntpwd || $alt));
439 /* seesio.auto_start should be off, in order to without trouble*/
440 $session_auto_start = ini_get('session.auto_start');
441 $implicit_flush = ini_get('implicit_flush');
442 $max_execution_time = ini_get('max_execution_time');
443 $memory_limit = ini_get('memory_limit');
444 $expose_php = ini_get('expose_php');
445 $magic_quotes_gpc = ini_get('magic_quotes_gpc');
446 $register_globals = ini_get('register_globals');
448 /* auto_register */
449 $msg.= check ( $faults, _("php.ini check -> session.auto_register"),
450 _("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']));
452 /* implicit_flush */
453 $msg.= check ( $faults, _("php.ini check -> implicit_flush"),
454 _("This option influences the Output handling. Turn this Option off, to increase performance."),
455 !$implicit_flush['local_value'],0,false);
457 /* max_execution_time */
458 if($max_execution_time['local_value'] < 30 ){
459 $max_execution_time['local_value']=false;
460 }
461 $msg.= check ( $faults, _("php.ini check -> max_execution_time"),
462 _("The Execution time should be at least 30 seconds, because some actions may consume more time."),
463 $max_execution_time['local_value'],0,false);
465 /* memory_limit */
466 if($memory_limit['local_value'] < 16 ){
467 $memory_limit['local_value']=false;
468 }
469 $msg.= check ( $faults, _("php.ini check -> memory_limit"),
470 _("GOsa needs at least 16MB of memory, less will cause unpredictable errors! Increase it for larger setups."),
471 !$implicit_flush['local_value'],0,false);
473 /* expose_php */
474 $msg.= check ( $faults, _("php.ini check -> expose_php"),
475 _("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."),
476 !$implicit_flush['local_value'],0,false);
478 /* magic_quotes_gpc */
479 $msg.= check ( $faults, _("php.ini check -> magic_quotes_gpc"),
480 _("Increase your server security by setting magic_quotes_gpc to 'on'. PHP will escape all quotes in strings in this case."),
481 $magic_quotes_gpc['local_value'],0,false);
483 return $msg;
484 }
487 function parse_contrib_conf()
488 {
490 $str = "";
491 $used_samba_version = 0;
492 $query = "";
493 $fp = false;
494 $output = "";
495 $needridbase_sid = false;
496 $pwdhash = "";
497 $replacements = array();
498 $ldapconf = $_SESSION['ldapconf']; // The Installation information
499 $classes = $_SESSION['classes']; // Class information needed to define which features are enabled
500 $possible_plugins = array();
502 /* Which samba version do we use? */
503 if(isset($classes['samba3'])){
504 $used_samba_version = 2;
505 } else {
506 $used_samba_version = 3;
507 }
509 /* Look for samba password generation method */
510 if(file_exists("/usr/bin/mkntpasswd")){
511 $pwdhash = "/usr/bin/mkntpasswd";
512 } elseif (preg_match("/^Usage: mkntpwd /", shell_exec ("mkntpwd 2>&1"))){
513 $pwdhash= "mkntpwd";
514 } else {
515 $pwdhash=('perl -MCrypt::SmbHash -e "ntlmgen \"\$ARGV[0]\", \$lm, \$nt; print \"\${lm}:\${nt}\n\";" $1');
516 }
519 /* Define which variables will be replaced */
520 $replacements['{LOCATIONNAME}'] = $ldapconf['location'];
521 $replacements['{SAMBAVERSION}'] = $used_samba_version;
522 $replacements['{LDAPBASE}'] = $ldapconf['base'];
523 $replacements['{LDAPADMIN}'] = $ldapconf['admin'];
524 $replacements['{UIDBASE}'] = $ldapconf['uidbase'];
525 $replacements['{DNMODE}'] = $ldapconf['peopledn'];
526 $replacements['{LDAPHOST}'] = $ldapconf['uri'];
527 $replacements['{PASSWORD}'] = $ldapconf['password'];
528 $replacements['{CRYPT}'] = $ldapconf['arr_cryptkeys'][$ldapconf['arr_crypts']];
529 $replacements['{SID}'] = "";
530 $replacements['{RIDBASE}'] = "";
531 if($ldapconf['mail'] != "disabled"){
532 $replacements['{MAILMETHOD}'] = $ldapconf['mail_methods'][$ldapconf['mail']];
533 }
534 $replacements['{SMBHASH}'] = $pwdhash;
535 $replacements['{GOVERNMENTMODE}']= "false";
536 $replacements['{kolabAccount}'] = "";
537 $replacements['{servKolab}'] = "";
538 $replacements['{errorlvl}'] = $ldapconf['errorlvl'];
540 /* This array contains all preg_replace syntax to delete all unused plugins
541 THE kEY MUST BE THE CLASSNAME so we can check it with $ldapconf['classes'] */
543 $possible_plugins['fonreport'][] = "'\n.*<plugin.*fonreport+.*\n.*>.*\n'i";
544 $possible_plugins['phoneaccount'][]= "'\n.*<tab.*phoneAccount.*>.*\n'i";
545 $possible_plugins['logview'][] = "'\n.*<plugin.*logview+.*\n.*>.*\n'i";
546 $possible_plugins['pureftp'][] = "'\n.*<tab.*pureftp.*>.*\n'i";
547 $possible_plugins['webdav'][] = "'\n.*<tab.*webdav.*>.*\n'i";
548 $possible_plugins['phpgroupware'][]= "'\n.*<tab.*phpgroupware.*>.*\n'i";
549 $possible_plugins['netatalk'][0] = "'\n.*<plugin.*netatalk+.*\n.*>.*\n'i";
550 $possible_plugins['netatalk'][1] = "'\n.*<tab.*netatalk.*>.*\n'i";
552 /*Header information
553 Needed to send the generated gosa.conf to the browser */
554 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
555 header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
556 header("Cache-Control: no-cache");
557 header("Pragma: no-cache");
558 header("Cache-Control: post-check=0, pre-check=0");
559 header("Content-type: text/plain");
561 if (preg_match('/MSIE 5.5/', $_SERVER['HTTP_USER_AGENT']) ||
562 preg_match('/MSIE 6.0/', $_SERVER['HTTP_USER_AGENT'])){
563 header('Content-Disposition: filename="gosa.conf"');
564 } else {
565 header('Content-Disposition: attachment; filename="gosa.conf"');
566 }
568 if(!$fp=fopen(CONFIG_TEMPLATE_DIR."/gosa.conf","r")) {
569 echo "Can't open file ".CONFIG_TEMPLATE_DIR."/gosa.conf";
570 } else {
571 while(!feof($fp)) {
572 $str.= fread($fp,512);
573 }
575 if($ldapconf['mail_methods'][$ldapconf['mail']]=="kolab") {
576 $replacements['{kolabAccount}'] ="<tab class=\"kolabAccount\" />\n ";
577 $replacements['{servKolab}'] ="<tab class=\"servkolab\" name=\"Kolab\" />";
578 }
580 if($used_samba_version == 2) {
581 /* Do nothing for samba 2... */
582 } else {
583 /* Create LDAP connection, to check if there's a domain
584 object defined in the LDAP schema */
585 $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']);
587 /* Try to find a Samba Domain Objekt */
588 $ldap->search("(objectClass=sambaDomain)");
590 /* Something found ??? so we need to define ridbase an SID by ourselfs */
591 if($ldap->count()< 1) {
592 $replacements['{SID}']= "sid=\"123412-11\"";
593 $replacements['{RIDBASE}']= "ridbase=\"1000\"";
594 }
595 }
597 /* Data readed, types replaced, samba version detected and checked if
598 we need to add SID and RIDBASE. Check if there is an ivbbentry in
599 the LDAP tree, in this case we will set the governmentmode to true.
600 Create LDAP connection, to check if theres a domain Objekt definen
601 in the LDAP schema. */
602 if(!isset($ldap)){
603 $ldap= new LDAP($ldapconf['admin'], $ldapconf['password'], $ldapconf['uri']);
604 }
606 /* Try to find a Samba Domain Objekt */
607 $ldap->search("(objectClass=ivbbentry)");
609 /* Something found ??? so we need to define ridbase an SID by ourselfs */
610 if($ldap->count()> 0) {
611 $replacements['{GOVERNMENTMODE}']= "true";
612 }
614 /* Replace all colleted information with placeholder */
615 foreach($replacements as $key => $val) {
616 $str = preg_replace("/".$key."/",$val,$str);
617 }
619 if($ldapconf['mail'] == "disabled"){
620 $str = str_replace("mailMethod=\"{MAILMETHOD}\"","",$str);
621 }
623 /* Remove all unused plugins */
624 foreach(array_keys($possible_plugins) as $akey) {
625 if(array_key_exists($akey,$classes)) {
626 foreach($possible_plugins[$akey] as $key=>$val) {
627 $str = preg_replace($val,"\n",$str);
628 }
629 }
630 }
631 }
633 return ((($str)));
634 }
637 /* Show setup_page 1 */
638 function show_setup_page1($withoutput = true)
639 {
640 $faults = array();
641 $smarty = get_smarty();
642 $smarty->assign ("content", get_template_path('setup_introduction.tpl'));
643 $smarty->assign ("tests", perform_php_checks($faults));
644 $smarty->assign ("detailed_tests", perform_additional_function_checks($faults));
646 /* This var is true if anything went wrong */
647 if ($faults){
648 $smarty->assign("mode", "disabled");
649 }
651 /* This line displays the template only if (withoutput is set) */
652 if($withoutput){
653 $smarty->display (get_template_path('headers.tpl'));
654 }
656 if (isset($_SESSION['errors'])){
657 $smarty->assign("errors", $_SESSION['errors']);
658 }
660 if($withoutput){
661 $smarty->display (get_template_path('setup.tpl'));
662 }
664 return (!$faults);
665 }
668 /* Show setup_page 2 */
669 function show_setup_page2($withoutput = true)
670 {
671 $faults = array();
672 $smarty = get_smarty();
673 $smarty->assign ("content", get_template_path('setup_step2.tpl'));
674 $smarty->assign ("tests", perform_additional_checks($faults));
676 if ($faults) {
677 $smarty->assign("mode", "disabled");
678 }
679 if($withoutput){
680 $smarty->display (get_template_path('headers.tpl'));
681 }
682 if (isset($_SESSION['errors'])) {
683 $smarty->assign("errors", $_SESSION['errors']);
684 }
685 if($withoutput){
686 $smarty->display (get_template_path('setup.tpl'));
687 }
689 return (!$faults);
690 }
693 function show_setup_page3($withoutput = true)
694 {
695 $ds = NULL;
696 $smarty = get_smarty();
698 /* Take the Post oder the Sessioin saved data */
699 if(isset($_POST['uri'])){
700 $uri = $_POST['uri'];
701 } elseif(isset($_SESSION['ldapconf']['uri'])){
702 $uri = $_SESSION['ldapconf']['uri'];
703 }
705 /* If Page called first time, field is empty */
706 if((!isset($uri))||(empty($uri))){
707 $uri = "ldap://localhost:389";
708 }
710 /* if isset $uri save it to session */
711 if(isset($uri)) {
712 $_SESSION['ldapconf']['uri'] = $uri;
713 $smarty->assign ("uri", validate($uri));
714 }
716 /* No error till now */
717 $fault = false;
719 /* If we pushed the Button continue */
720 if(isset($_POST['continue3'])){
721 if(!isset($uri)) {
722 $fault = true;
724 /* Output the Error */
725 if($withoutput) {
726 print_red (_("You've to specify an ldap server before continuing!"));
727 $smarty->assign ("content", get_template_path('setup_step3.tpl'));
728 }
729 }
730 } elseif (!$ds = @ldap_connect (validate($uri))) {
731 $fault =true;
733 /* Output the Error */
734 if($withoutput) {
735 print_red (_("Can't connect to the specified LDAP server! Please make sure that is reachable for GOsa."));
736 $smarty->assign ("uri", validate($uri));
737 $smarty->assign ("content", get_template_path('setup_step3.tpl'));
738 }
739 } else {
740 /* Try to bind the connection */
741 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
743 /* if we can't bind , print error */
744 if (!$r = @ldap_bind ($ds)) {
745 $fault = true;
747 /* Output the Error */
748 if($withoutput) {
749 print_red (_("Can't bind to the specified LDAP server! Please make sure that it is reachable for GOsa."));
750 $smarty->assign ("content", get_template_path('setup_step3.tpl'));
751 $smarty->assign ("uri", validate($uri));
752 }
753 } else {
754 $fault = false;
755 }
756 }
758 $smarty->assign ("content", get_template_path('setup_step3.tpl'));
760 /* Load Header */
761 if($withoutput){
762 $smarty->display (get_template_path('headers.tpl'));
763 }
765 /* Set Errors to Smarty */
766 if (isset($_SESSION['errors'])) {
767 $smarty->assign("errors", $_SESSION['errors']);
768 }
770 /* Print out Template */
771 if($withoutput){
772 $smarty->display (get_template_path('setup.tpl'));
773 }
775 return (!$fault);
776 }
779 function show_setup_page4($withoutput = true)
780 {
781 $smarty= get_smarty();
783 // ?
784 if(!isset($_SESSION['ldapconf']['base'])){
785 $_SESSION['ldapconf']['base']= $base;
786 }
788 if(!isset($_SESSION['ldapconf']['base'])){
789 $_SESSION['ldapconf']['base']= $base;
790 }
791 require_once("class_password-methods.inc");
793 $fault = false;
794 $uri = $_SESSION['ldapconf']['uri'];
795 $ldapconf = $_SESSION['ldapconf'];
796 $arr_crypts= array();
797 $temp = "";
798 $checkvars = array("location", "admin", "password", "peopleou", "base",
799 "peopledn", "arr_crypts", "mail", "uidbase","errorlvl");
801 if(!isset($_SESSION['ldapconf']['arr_cryptkeys'])) {
802 require_once("class_password-methods.inc");
803 $tmp= passwordMethod::get_available_methods_if_not_loaded();
804 $_SESSION['ldapconf']['arr_cryptkeys']= $tmp['name'];
805 }
807 if(!isset($_SESSION['ldapconf']['mail_methods'])) {
808 $_SESSION['ldapconf']['mail_methods']=array();
809 $temp = get_available_mail_classes();
810 $_SESSION['ldapconf']['mail_methods']= $temp['name'];
811 }
813 /* If there are some empty vars in ldapconnect -
814 these values also represent out default values */
815 if(!$ds = @ldap_connect (validate($uri))){
816 $fault = true;
817 if($withoutput){
818 print_red (_("Can't connect to the specified LDAP server! Please make sure that is reachable for GOsa."));
819 }
820 } elseif(!@ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)){
821 $fault = true;
822 if($withoutput){
823 print_red (_("Can't bind to the specified LDAP server! Please make sure that it is reachable for GOsa."));
824 }
825 } elseif(!$r= @ldap_bind ($ds)){
826 $fault = true;
827 if($withoutput){
828 print_red (_("Can't bind to the specified LDAP server! Please make sure that it is reachable for GOsa."));
829 }
830 } else {
831 $sr= @ldap_search ($ds, NULL, "objectClass=*", array("namingContexts"));
832 $attr= @ldap_get_entries($ds,$sr);
834 if((empty($attr))) {
835 $base= "dc=example,dc=net";
837 if($withoutput){
838 print_red(_("Bind to server successful, but the server seems to be completly empty, please check all information twice"));
839 }
841 } else {
842 $base= $attr[0]['dn'];
843 }
844 }
846 if(!isset($_SESSION['ldapconf']['base'])){
847 $_SESSION['ldapconf']['base']= $base;
848 }
849 if(!isset($_SESSION['ldapconf']['admin'])){
850 $_SESSION['ldapconf']['admin']= "cn=ldapadmin,".$base;
851 }
852 if(!isset($_SESSION['ldapconf']['peopleou'])){
853 $_SESSION['ldapconf']['peopleou']= "ou=people";
854 }
855 if(!isset($_SESSION['ldapconf']['groupou'])){
856 $_SESSION['ldapconf']['groupou']= "ou=groups";
857 }
858 if(!isset($_SESSION['ldapconf']['peopledn'])){
859 $_SESSION['ldapconf']['peopledn']= "cn";
860 }
861 if(!isset($_SESSION['ldapconf']['password'])){
862 $_SESSION['ldapconf']['password']= "";
863 }
864 if(!isset($_SESSION['ldapconf']['location'])){
865 $_SESSION['ldapconf']['location']= "Example";
866 }
867 if(!isset($_SESSION['ldapconf']['uidbase'])){
868 $_SESSION['ldapconf']['uidbase']= "1000";
869 }
870 if(!isset($_SESSION['ldapconf']['mail'])){
871 $_SESSION['ldapconf']['mail']= 0;
872 }
873 $tmp= array_flip($_SESSION['ldapconf']['arr_cryptkeys']);
874 if(!isset($_SESSION['ldapconf']['arr_crypts'])){
875 $_SESSION['ldapconf']['arr_crypts'] = $tmp['md5'];
876 }
878 /* check POST data */
879 if(isset($_POST['check'])) {
881 /* Check if all needed vars are submitted */
882 foreach($checkvars as $key) {
883 if($key == "peopleou"){
884 continue;
885 }
886 if($key == "groupou"){
887 continue;
888 }
890 if((isset($_POST[$key]))&&($_POST[$key]!="")) {
891 $_SESSION['ldapconf'][$key] = $_POST[$key];
892 } else {
893 if($withoutput) {
894 print_red(sprintf(_("You're missing the required attribute '%s' from this formular. Please complete!"), $key));
895 }
896 $fault = true;
897 }
898 }
899 }
901 /* Transfer base */
902 if(isset($_POST['base'])){
903 $_SESSION['ldapconf']['base']= $_POST['base'];
904 }
906 $smarty->assign("arr_cryptkeys",$_SESSION['ldapconf']['arr_cryptkeys']);
907 $smarty->assign("mail_methods", $_SESSION['ldapconf']['mail_methods']);
909 foreach($_SESSION['ldapconf'] as $key => $val) {
910 $smarty->assign($key,$val);
911 }
913 if(isset($_POST['check'])) {
914 $ldap= new LDAP($_SESSION['ldapconf']['admin'],
915 $_SESSION['ldapconf']['password'],
916 $_SESSION['ldapconf']['uri']);
918 $m= schema_check($_SESSION['ldapconf']['uri'],
919 $_SESSION['ldapconf']['admin'],
920 $_SESSION['ldapconf']['password']);
921 $_SESSION['classes']= $m;
923 if(!is_schema_readable($ldapconf['uri'],$ldapconf['admin'],$ldapconf['password'])){
924 if($withoutput){
925 print_red(_("Can't read schema informations, GOsa needs to know your schema setup. Please verify that it is readable for GOsa"));
926 }
927 $fault=true;
928 }
932 if ($ldap->error != "Success") {
933 if($withoutput) {
934 print_red(sprintf(_("Can't log into LDAP server. Reason was: %s."), $ldap->get_error()));
935 }
936 $fault = true;
937 }
938 }
940 /* Set smarty output */
941 $smarty->assign ("content", get_template_path('setup_step4.tpl'));
942 $smarty->assign ("peopledns", array("cn", "uid"));
943 if($withoutput){
944 $smarty->display (get_template_path('headers.tpl'));
945 }
946 if(isset($_SESSION['errors'])) {
947 $smarty->assign("errors", $_SESSION['errors']);
948 }
949 if($withoutput){
950 $smarty->display (get_template_path('setup.tpl'));
951 }
952 return (!$fault);
953 }
956 function show_setup_page5($withoutput=true)
957 {
958 /* Get ldapconf */
959 $ldapconf= $_SESSION['ldapconf'];
961 /* get smarty */
962 $smarty = get_smarty();
964 if(isset($_SESSION['classes'])){
965 $classes = $_SESSION['classes'];
966 }
968 $info= posix_getgrgid(posix_getgid());
969 $smarty->assign("webgroup", $info['name']);
970 $smarty->assign("path", CONFIG_DIR);
971 $message= "<table summary=\"\" class=\"check\">";
972 $m= schema_check($ldapconf['uri'], $ldapconf['admin'], $ldapconf['password'],1);
974 if($withoutput) {
975 $smarty->assign ("schemas", view_schema_check($m));
976 $smarty->assign ("content", get_template_path('setup_finish.tpl'));
977 }
979 /* Output templates... */
980 if($withoutput){
981 $smarty->display (get_template_path('headers.tpl'));
982 }
983 if (isset($_SESSION['errors'])) {
984 $smarty->assign("errors", $_SESSION['errors']);
985 }
986 if($withoutput){
987 $smarty->display (get_template_path('setup.tpl'));
988 }
990 return(true);
991 }
994 function create_user_for_setup($withoutput=true)
995 {
996 global $samba;
998 $ldapconf = $_SESSION['ldapconf'];
999 $smarty = get_smarty();
1001 $need_to_create_group = false;
1002 $need_to_create_user = false;
1004 $str_there="";
1006 if(isset($_SESSION['classes'])){
1007 $classes= $_SESSION['classes'];
1008 }
1010 /* Everything runns perfect ...
1011 So we do a last test on this page
1012 is there a user with ACLs :all which will be able to adminsitrate GOsa
1013 We check that, if this user or group is missing we ask for creating them */
1014 $ldap= new LDAP($_SESSION['ldapconf']['admin'], $_SESSION['ldapconf']['password'], $_SESSION['ldapconf']['uri']);
1016 /*
1017 Now we are testing for a group, with the rights :all
1018 */
1020 $ldap->cd($ldapconf['base']);
1021 $ldap->search("(&(objectClass=gosaObject)(gosaSubtreeACL=:all))");
1023 $group_cnt = $ldap->count();
1024 $data = $ldap->fetch();
1026 // $str_there = "Searching for Aminitrative users <br><br>";
1028 /*
1029 We need to create administrative user and group because theres no group found
1030 */
1031 if($group_cnt < 1) {
1033 /*
1034 Set var to create user
1035 */
1036 // $str_there = "no group found<br>";
1038 $need_to_create_group = true;
1039 $need_to_create_user = true;
1042 /* Output error */
1043 if(($withoutput)&&(!isset($_POST['new_admin']))){
1044 print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!"));
1045 }
1046 } else {
1048 // $str_there = "Group found <br>".$data['dn'];
1050 $need_to_create_group = false;
1052 $ldap->clearResult();
1054 /* We found an Administrative Group, is there a user, too */
1055 if(isset($data['memberUid'][0])) {
1056 $str = "uid=".$data['memberUid']['0'];
1057 $ldap->search("(&(objectClass=gosaAccount)(objectClass=person)(".$str."))");
1058 $data2 = $ldap->fetch();
1060 /* We must create a user */
1061 if (($ldap->count() < 1)||(!isset($data2))) {
1062 // $str_there.="Missing user";
1064 $need_to_create_user = true;
1066 if(($withoutput)&&(!isset($_POST['new_admin']))){
1067 print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!"));
1068 }
1069 }else {
1070 // $str_there.="<br>User found <br>".$data2['dn'];
1071 $need_to_create_user = false;
1072 }
1073 } else {
1074 $need_to_create_user=true;
1075 if(($withoutput)&&(!isset($_POST['new_admin']))){
1076 print_red(_("You're missing an administrative account for GOsa, you'll not be able to administrate anything!"));
1077 }
1078 // $str_there.="<br>No User found <br>";
1079 }
1080 }
1082 if(!($need_to_create_user&&$need_to_create_group))
1083 return(true);
1085 /* We need to create a new user with group */
1086 if(isset($_POST['new_admin']))
1087 {
1089 /* Adjust password attributes according to the samba version */
1090 if (isset($classes['samba3'])) {
1091 $samba= "2";
1092 $lmPassword = "lmPassword";
1093 $ntPassword = "ntPassword";
1094 } else {
1095 $samba= "3";
1096 $lmPassword = "sambaLMPassword";
1097 $ntPassword = "sambaNtPassword";
1098 }
1100 /* Nothing submitted */
1101 if(((empty($_POST['admin_name']))||(empty($_POST['admin_pass'])))) {
1102 return(true);
1103 }
1105 if($need_to_create_user) {
1106 /* We have the order to create an Admin */
1107 /* Define the user we are going to create */
1108 $dn= "cn=".$_POST['admin_name'].",".$ldapconf['peopleou'].",".$ldapconf['base'];
1109 $arr['objectClass'][0] ="person";
1110 $arr['objectClass'][1] ="organizationalPerson";
1111 $arr['objectClass'][2] ="inetOrgPerson";
1112 $arr['objectClass'][3] ="gosaAccount";
1113 $arr['uid'] = $_POST['admin_name'];
1114 $arr['cn'] = $_POST['admin_name'];
1115 $arr['sn'] = $_POST['admin_name'];
1116 $arr['givenName'] = "GOsa main administrator";
1117 $arr[$lmPassword] = "10974C6EFC0AEE1917306D272A9441BB";
1118 $arr[$ntPassword] = "38F3951141D0F71A039CFA9D1EC06378";
1119 $arr['userPassword'] = crypt_single($_POST['admin_pass'],"md5");
1122 if(!$ldap->dn_exists($dn)){
1123 $ldap->cd($dn);
1124 $ldap->create_missing_trees($dn);
1125 $ldap->cd($dn);
1126 $ldap->add($arr);
1127 if($ldap->error!="Success"){
1128 print_red($ldap->error);
1129 print_red("Can't create user, and / or Group, possibly this problem depends on an empty LDAP server. Check your configuration and try again!");
1130 }
1131 }
1132 }
1134 /* There's already a group for administrator, so we only need to add the user */
1135 if(!$need_to_create_group) {
1136 if(!isset($data['memberUid'])) {
1137 $arrr['memberUid']= $_POST['admin_name'];
1138 } else {
1139 $data['memberUid'][$data['memberUid']['count']]=$_POST['admin_name'];
1140 $arrr['memberUid'] = $data['memberUid'];
1141 unset($arrr['memberUid']['count']);
1143 $tmp = array_reverse($arrr['memberUid']);
1144 foreach($tmp as $tt){
1145 $tmp2[]=$tt;
1146 }
1147 $arrr['memberUid']= $tmp2;
1148 // $str_there="Group found<br>".$data['dn'];
1149 }
1151 $ldap->cd($data['dn']);
1152 $ldap->modify($arrr);
1154 } else {
1155 $dn = "cn=administrators,".$ldapconf['groupou'].",".$ldapconf['base'];
1156 $arrr['objectClass'][0]= "gosaObject";
1157 $arrr['objectClass'][1]= "posixGroup";
1158 $arrr['gosaSubtreeACL']= ":all";
1159 $arrr['cn'] = "administrators";
1160 $arrr['gidNumber'] = "999";
1161 $arrr['memberUid'] = $_POST['admin_name'];
1163 $ldap->cd($dn);
1164 $ldap->create_missing_trees($dn);
1165 $ldap->cd($dn);
1167 $ldap->add($arrr);
1168 }
1169 return(true);
1170 } else {
1172 if((!isset($create_user))||(!($create_user))) {
1173 $smarty->assign ("content", get_template_path('setup_useradmin.tpl'));
1174 $smarty->assign("exists",true);
1175 } else {
1176 $smarty->assign ("content", get_template_path('setup_useradmin.tpl'));
1177 $smarty->assign("exists",false);
1178 }
1180 }
1182 /* Smarty output */
1183 if($withoutput){
1184 $smarty->display (get_template_path('headers.tpl'));
1185 }
1186 if (isset($_SESSION['errors'])) {
1187 $smarty->assign("errors", $_SESSION['errors']);
1188 }
1189 $smarty->assign("str_there",$str_there);
1190 if($withoutput){
1191 $smarty->display (get_template_path('setup.tpl'));
1192 }
1193 return(false);
1194 }
1197 /* Returns the classnames auf the mail classes */
1198 function get_available_mail_classes()
1199 {
1200 $dir = opendir( "../include");
1201 $methods = array();
1202 $suffix = "class_mail-methods-";
1203 $lensuf = strlen($suffix);
1204 $prefix = ".inc";
1205 $lenpre = strlen($prefix);
1207 $i = 0;
1208 while (($file = readdir($dir)) !== false){
1210 if(stristr($file,$suffix)) {
1211 $lenfile = strlen($file);
1212 $methods['name'][$i] = substr($file,$lensuf,($lenfile-$lensuf)-$lenpre);
1213 $methods['file'][$i] = $file;
1214 $methods[$i]['file'] = $file;
1215 $methods[$i]['name'] = substr($file,$lensuf,($lenfile-$lensuf)-$lenpre);
1216 $i++;
1217 }
1219 }
1221 return($methods);
1222 }
1224 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1225 ?>