1 <?php
3 class faiScript extends plugin
4 {
5 /* CLI vars */
6 var $cli_summary = "Manage server basic objects";
7 var $cli_description = "Some longer text\nfor help";
8 var $cli_parameters = array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
10 /* attribute list for save action */
11 var $ignore_account = TRUE;
13 /* Attributes for this Object */
14 var $attributes = array("cn","description");
16 /* ObjectClasses for this Object*/
17 var $objectclasses = array("top","FAIclass","FAIscript");
19 /* Class name of the Ldap ObjectClass for the Sub Object */
20 var $subClass = "FAIscriptEntry";
21 var $subClasses = array("top","FAIclass","FAIscriptEntry");
23 /* Class name of the php class which allows us to edit a Sub Object */
24 var $subClassName = "faiScriptEntry";
26 /* Attributes to initialise for each subObject */
27 var $subAttributes = array("cn","description","FAIpriority");
28 var $sub_Load_Later = array("FAIscript");
29 var $sub64coded = array();
30 var $subBinary = array("FAIscript");
32 /* Specific attributes */
33 var $cn = ""; // The class name for this object
34 var $description = ""; // The description for this set of partitions
35 var $is_dialog = false; // specifies which buttons will be shown to save or abort
36 var $SubObjects = array(); // All leafobjects of this object
38 var $FAIstate = "";
39 var $sort_by = "name";
40 var $sort_order = "up";
42 var $view_logged = FALSE;
43 var $ui;
45 function faiScript (&$config, $dn= NULL)
46 {
47 /* Load Attributes */
48 plugin::plugin ($config, $dn);
50 /* If "dn==new" we try to create a new entry
51 * Else we must read all objects from ldap which belong to this entry.
52 * First read SubObjects from ldap ... and then the partition definitions for the SubObjects.
53 */
54 if($dn != "new"){
56 $this->dn =$dn;
58 /* Get FAIstate
59 */
60 if(isset($this->attrs['FAIstate'][0])){
61 $this->FAIstate = $this->attrs['FAIstate'][0];
62 }
64 /* Read all leaf objects of this object (For FAIscript this would be FAIscriptEntry)
65 */
66 $ldap = $this->config->get_ldap_link();
67 $ldap->cd ($this->dn);
69 $attrs_to_search = $this->subAttributes;
70 $attrs_to_search[] = "FAIstate";
71 $ldap->search("(&(objectClass=FAIclass)(objectClass=".$this->subClass."))",$attrs_to_search);
73 while($object = $ldap->fetch()){
75 /* Skip objects, that are tagged as removed */
76 if(isset($object['FAIstate'][0])){
77 if(preg_match("/removed$/",$object['FAIstate'][0])){
78 continue;
79 }
80 }
82 /* Set status for save management */
83 $objects = array();
84 $objects['status'] = "FreshLoaded";
85 $objects['dn'] = $object['dn'];
86 $objects = $this->get_object_attributes($objects,$this->subAttributes);
87 $this->SubObjects[$objects['cn']] = $objects;
88 }
90 }
91 $this->ui = get_userinfo();
92 }
95 /* Reload some attributes */
96 function get_object_attributes($object,$attributes)
97 {
98 $ldap = $this->config->get_ldap_link();
99 $ldap->cd($this->config->current['BASE']);
100 $ldap->cat($object['dn'],$attributes);
101 $tmp = $ldap->fetch();
103 foreach($attributes as $attrs){
104 if(isset($tmp[$attrs][0])){
105 $var = $tmp[$attrs][0];
107 /* Check if we must decode some attributes */
108 if(in_array_ics($attrs,$this->sub64coded)){
109 $var = base64_decode($var);
110 }
112 /* check if this is a binary entry */
113 if(in_array_ics($attrs,$this->subBinary)){
114 $var = $ldap->get_attribute($object['dn'], $attrs,$r_array=0);
115 }
117 /* Fix slashes */
118 $var = addslashes($var);
119 $object[$attrs] = $var;
120 }
121 }
122 return($object);
123 }
126 /* Return a valid dn to fetch acls. Because 'new' will not work. */
127 function acl_base_for_current_object($dn)
128 {
129 if($dn == "new"){
130 if($this->dn == "new"){
131 $dn= "cn=dummy,".$_SESSION['CurrentMainBase'];
132 }else{
133 $dn = $this->dn;
134 }
135 }
136 return($dn);
137 }
140 function execute()
141 {
142 /* Call parent execute */
143 plugin::execute();
145 if($this->is_account && !$this->view_logged){
146 $this->view_logged = TRUE;
147 new log("view","fai/".get_class($this),$this->dn);
148 }
150 /* Fill templating stuff */
151 $smarty= get_smarty();
152 $display= "";
154 /* Add new sub object */
155 if(isset($_POST['AddSubObject'])){
156 $this->dialog= new $this->subClassName($this->config,"new");
157 $this->dialog->set_acl_base($this->acl_base);
158 $this->dialog->set_acl_category("fai");
159 $this->dialog->parent = &$this;
160 $this->is_dialog=true;
161 }
163 if($this->dn != "new"){
164 $_SESSION['objectinfo']= $this->dn;
165 }
167 /* Handle posts */
168 $s_action = $s_entry = "";
169 foreach($_POST as $name => $value){
171 /* Edit script posted */
172 if(preg_match("/^editscript_/",$name)){
173 $s_action = "edit";
174 $s_entry = preg_replace("/^editscript_/","",$name);
175 $s_entry = base64_decode(preg_replace("/_.*/","",$s_entry));
176 break;
177 }
179 /* Delete script requested */
180 if(preg_match("/^deletescript_/",$name)){
181 $s_action = "remove";
182 $s_entry = preg_replace("/^deletescript_/","",$name);
183 $s_entry = base64_decode(preg_replace("/_.*/","",$s_entry));
184 break;
185 }
186 }
188 if(isset($_GET['act']) && $_GET['act'] == "edit" && isset($_GET['id'])){
189 $s_entry = $_GET['id'];
190 if(isset($this->SubObjects[$s_entry])){
191 $s_action = "edit";
192 }
193 }
195 if($s_action =="edit" && isset($this->SubObjects[$s_entry])){
197 /* Get object, and load missing entry values */
198 $obj = $this->SubObjects[$s_entry];
199 if($obj['status'] == "FreshLoaded"){
200 $obj = $this->get_object_attributes($obj,$this->sub_Load_Later);
201 }
203 /* Create new dialog and set acl attributes */
204 $this->dialog= new $this->subClassName($this->config,$this->dn,$obj);
205 $this->dialog->set_acl_base($this->acl_base_for_current_object($obj['dn']));
206 $this->dialog->set_acl_category("fai");
208 /* Assign some additional dialog informations like headline and parent */
209 $_SESSION['objectinfo'] = $obj['dn'];
210 $this->dialog->parent = &$this;
211 $this->is_dialog=true;
212 }
214 /* Check acls, are we allowed to delete an entry */
215 if($s_action == "remove" && isset($this->SubObjects[$s_entry])){
216 $entry = $this->SubObjects[$s_entry];
217 $acl = $this->ui->get_permissions($this->acl_base_for_current_object($entry['dn']),"fai/faiScriptEntry") ;
218 if(preg_match("/d/",$acl)){
219 $status = $entry['status'];
220 if($status == "edited" || $status == "FreshLoaded"){
221 $this->SubObjects[$s_entry]['status']= "delete";
222 }else{
223 unset($this->SubObjects[$s_entry]);
224 }
225 }
226 }
228 /* Save the edited entry */
229 if(isset($_POST['SaveSubObject'])){
231 /* Check if there are still errors remaining that must be fixed before saving */
232 $this->dialog->save_object();
233 $msgs = $this->dialog->check();
234 if(count($msgs)>0){
235 foreach($msgs as $msg){
236 print_red($msg);
237 }
238 }else{
240 /* Get return object */
241 $obj = $this->dialog->save();
243 /* If we have renamed the script entry, we must remove the old entry */
244 if(isset($obj['remove'])){
246 /* Get old entry values */
247 $old_stat = $this->SubObjects[$obj['remove']['from']]['status'];
249 /* Depending on status, set new status */
250 if($old_stat == "edited" || $old_stat == "FreshLoaded"){
251 $this->SubObjects[$obj['remove']['from']]['status'] = "delete";
252 }elseif($this->SubObjects[$obj['remove']['from']]['status']=="new"){
253 unset($this->SubObjects[$obj['remove']['from']]);
254 }
256 /* Append the new entry */
257 $obj['status'] = "new";
258 $this->SubObjects[$obj['remove']['to']] = $obj;
259 unset($this->SubObjects[$obj['remove']['to']]['remove']);
260 }else{
262 /* Set new status and append the entry */
263 if($obj['status'] == "FreshLoaded"){
264 $obj['status'] = "edited";
265 }
266 $this->SubObjects[$obj['cn']]=$obj;
267 }
268 $this->is_dialog=false;
269 unset($this->dialog);
270 $this->dialog=FALSE;
272 }
273 }
275 /* Sort entries */
276 $tmp = $keys = array();
278 if($this->sort_by == "name"){
279 foreach($this->SubObjects as $key => $entry){
280 $keys[$key]=$entry['cn'];
281 }
282 }elseif($this->sort_by == "priority"){
283 foreach($this->SubObjects as $key => $entry){
284 $keys[$key]=$entry['FAIpriority'];
285 }
286 }
288 natcasesort($keys);
290 if($this->sort_order == "down"){
291 $keys =array_reverse($keys);
292 }
294 foreach($keys as $key => $order_var){
295 $tmp[$key]=$this->SubObjects[$key];
296 }
297 $this->SubObjects = $tmp;
299 /* Cancel Dialog */
300 if(isset($_POST['CancelSubObject'])){
301 $this->is_dialog=false;
302 unset($this->dialog);
303 $this->dialog=FALSE;
304 }
306 /* Print dialog if $this->dialog is set */
307 if(is_object($this->dialog)){
308 $this->dialog->save_object();
309 $display = $this->dialog->execute();
310 return($display);
311 }
313 /* Divlist added 23.02.2006
314 Containing FAIscripts
315 */
316 $divlist = new divlist("FAIscripts");
317 $divlist->SetEntriesPerPage(0);
318 $plug = $_GET['plug'];
320 if($this->sort_order == "up"){
321 $dir = "<img src='images/sort_up.png' title='"._("Sort direction")."' alt='\/' border=0>";
322 }else{
323 $dir = "<img src='images/sort_down.png' title='"._("Sort direction")."' alt='/\' border=0>";
324 }
326 if($this->sort_by == "name"){
327 $sort_name = $dir;
328 $sort_prio = "";
329 }else{
330 $sort_name = "";
331 $sort_prio = $dir;
332 }
334 $divlist->SetHeader(array( array("string"=>"<a href='?plug=".$plug."&sort=name'>"._("Name").$sort_name."</a>"),
335 array("string"=>"<a href='?plug=".$plug."&sort=priority'>".$sort_prio._("Priority")."</a>",
336 "attach"=>"style='width:100px;'"),
337 array("string"=>_("Download"),
338 "attach"=>"style='width:100px;'"),
339 array("string"=>_("Action"),
340 "attach"=>"style='border-right: 0px;width:100px;text-align:right;'")));
341 $divlist->SetHeight(300);
342 $divlist->SetWidth("100%");
343 foreach($this->getList(true) as $key => $name){
345 $dn= $this->acl_base_for_current_object($name['dn']);
346 $acl = $this->ui->get_permissions($dn,"fai/faiScriptEntry") ;
347 $act = "";
349 /* Hide delete icon if this object is freezed */
350 if($this->FAIstate == "freeze"){
351 $act .= "<input type='image' src='images/edit.png' name='editscript_%s' title='"._("edit")."' alt='"._("edit")."'>";
352 }else{
353 $act .= "<input type='image' src='images/edit.png' name='editscript_%s' title='"._("edit")."' alt='"._("edit")."'>";
354 if(preg_match("/d/",$acl)){
355 $act .="<input type='image' src='images/edittrash.png' name='deletescript_%s' title='"._("delete")."' alt='"._("delete")."'>";
356 }
357 }
359 /* Check acls for download icon */
360 $s_acl = $this->ui->get_permissions($dn,"fai/faiScriptEntry","FAIscript") ;
361 if(($this->SubObjects[$key]['status'] == "new") || ($this->SubObjects[$key]['dn'] == "new") || !preg_match("/r/",$s_acl)){
362 $down = "";
363 }else{
364 $down = "<a href='getFAIscript.php?id=".base64_encode($name['dn'])."' >
365 <img src='images/save.png' alt='"._("Download")."' title='"._("Download")."' border=0>
366 </a>";
367 }
369 /* Check if we are allowed to view this object */
370 $s_acl = $this->ui->get_permissions($dn,"fai/faiScriptEntry","cn") ;
371 if(preg_match("/r/",$s_acl)){
372 $divlist->AddEntry(array( array("string"=>"<a href='?plug=".$_GET['plug']."&act=edit&id=".$key."'>".$name['name']."</a>"),
373 array("string"=>$name['FAIpriority'] , "attach" => "style='width:100px;'"),
374 array("string"=>$down , "attach" => "style='width:100px;'"),
375 array("string"=>str_replace("%s",base64_encode($key),$act),
376 "attach"=>"style='border-right: 0px;width:100px;text-align:right;'")));
377 }
378 }
379 $smarty->assign("Entry_divlist",$divlist->DrawList());
382 /* Magic quotes GPC, escapes every ' " \, to solve some security risks
383 * If we post the escaped strings they will be escaped again
384 */
385 foreach($this->attributes as $attrs){
386 if(get_magic_quotes_gpc()){
387 $smarty->assign($attrs,stripslashes($this->$attrs));
388 }else{
389 $smarty->assign($attrs,($this->$attrs));
390 }
391 }
393 $dn = $this->acl_base_for_current_object($this->dn);
394 $smarty->assign("sub_object_is_addable",
395 preg_match("/c/",$this->ui->get_permissions($dn,"fai/faiScriptEntry")) &&
396 !preg_match("/freeze/",$this->FAIstate));
398 $tmp = $this->plInfo();
399 foreach($tmp['plProvidedAcls'] as $name => $translated){
400 $smarty->assign($name."ACL",$this->getacl($name));
401 }
403 $display.= $smarty->fetch(get_template_path('faiScript.tpl', TRUE));
404 return($display);
405 }
407 /* Generate listbox friendly SubObject list
408 */
409 function getList($use_dns=false){
410 $a_return=array();
411 foreach($this->SubObjects as $obj){
412 if($obj['status'] != "delete"){
413 if($use_dns){
414 if((isset($obj['description']))&&(!empty($obj['description']))){
415 $a_return[$obj['cn']]['name']= $obj['cn']." [".stripslashes($obj['description'])."]";
416 }else{
417 $a_return[$obj['cn']]['name']= $obj['cn'];
418 }
419 $a_return[$obj['cn']]['dn']= $obj['dn'];
420 $a_return[$obj['cn']]['FAIpriority']= $obj['FAIpriority'];
421 }else{
422 if((isset($obj['description']))&&(!empty($obj['description']))){
423 $a_return[$obj['cn']]= $obj['cn']." [".stripslashes($obj['description'])."]";
424 }else{
425 $a_return[$obj['cn']]= $obj['cn'];
426 }
427 }
428 }
429 }
430 return($a_return);
431 }
433 /* Delete me, and all my subtrees
434 */
435 function remove_from_parent()
436 {
437 if($this->acl_is_removeable()){
438 $ldap = $this->config->get_ldap_link();
439 $ldap->cd ($this->dn);
441 $use_dn = preg_replace("/".normalizePreg(get_release_dn($this->dn))."/i", $_SESSION['faifilter']['branch'], $this->dn);
442 if($_SESSION['faifilter']['branch'] == "main"){
443 $use_dn = $this->dn;
444 }
446 new log("remove","fai/".get_class($this),$use_dn,$this->attributes);
448 prepare_to_save_FAI_object($use_dn,array(),true);
450 foreach($this->SubObjects as $name => $obj){
451 $use_dn = preg_replace("/".normalizePreg(get_release_dn($this->dn))."/i", $_SESSION['faifilter']['branch'], $obj['dn']);
452 if($_SESSION['faifilter']['branch'] == "main"){
453 $use_dn = $obj['dn'];
454 }
455 prepare_to_save_FAI_object($use_dn,array(),true);
456 }
457 $this->handle_post_events("remove");
458 }
459 }
462 /* Save data to object
463 */
464 function save_object()
465 {
466 if((isset($_POST['FAIscript_posted'])) && ($this->FAIstate != "freeze")){
467 plugin::save_object();
468 foreach($this->attributes as $attrs){
469 if(isset($_POST[$attrs])){
470 $this->$attrs = $_POST[$attrs];
471 }
472 }
473 }
475 /* Get sort order */
476 if(isset($_GET['sort']) && in_array($_GET['sort'],array("name","priority"))){
477 if($this->sort_by == $_GET['sort']){
478 if($this->sort_order == "up"){
479 $this->sort_order = "down";
480 }elseif($this->sort_order == "down"){
481 $this->sort_order = "up";
482 }
483 }
484 $this->sort_by = $_GET['sort'];
485 }
486 }
489 /* Check supplied data */
490 function check()
491 {
492 /* Call common method to give check the hook */
493 $message= plugin::check();
495 return ($message);
496 }
499 /* Save to LDAP */
500 function save()
501 {
502 plugin::save();
504 $ldap = $this->config->get_ldap_link();
506 prepare_to_save_FAI_object($this->dn,$this->attrs);
507 show_ldap_error($ldap->get_error(), sprintf(_("Creating of FAI/script with dn '%s' failed."),$this->dn));
509 if($this->initially_was_account){
510 new log("modify","fai/".get_class($this),$this->dn,$this->attributes);
511 }else{
512 new log("create","fai/".get_class($this),$this->dn,$this->attributes);
513 }
515 /* Do object tagging */
516 $this->handle_object_tagging();
518 /* Prepare FAIscriptEntry to write it to ldap
519 * First sort array.
520 * Because we must delete old entries first.
521 * After deletion, we perform add and modify
522 */
523 $Objects = array();
525 /* We do not need to save untouched objects */
526 foreach($this->SubObjects as $name => $obj){
527 if($obj['status'] == "FreshLoaded"){
528 unset($this->SubObjects[$name]);
529 }
530 }
532 foreach($this->SubObjects as $name => $obj){
533 if($obj['status'] == "delete"){
534 $Objects[$name] = $obj;
535 }
536 }
537 foreach($this->SubObjects as $name => $obj){
538 if($obj['status'] != "delete"){
539 $Objects[$name] = $obj;
540 }
541 }
543 foreach($Objects as $name => $obj){
545 foreach($this->sub64coded as $codeIt){
546 $obj[$codeIt]=base64_encode(stripslashes($obj[$codeIt]));
547 }
549 $tmp = array();
550 $attributes = array_merge($this->sub_Load_Later,$this->subAttributes);
551 foreach($attributes as $attrs){
553 if(empty($obj[$attrs])){
554 $obj[$attrs] = array();
555 }
556 if(!is_array($obj[$attrs])){
557 $tmp[$attrs] = stripslashes($obj[$attrs]);
558 }else{
559 $tmp[$attrs] = $obj[$attrs];
560 }
561 }
563 $tmp['objectClass'] = $this->subClasses;
565 $sub_dn = "cn=".$obj['cn'].",".$this->dn;
567 if($obj['status']=="new"){
568 $ldap->cat($sub_dn,array("objectClass"));
569 if($ldap->count()){
570 $obj['status']="edited";
571 }
572 }
574 if(empty($tmp['FAIpriority'])){
575 $tmp['FAIpriority'] ="0";
576 }
578 /* Check if gosaAdministrativeUnitTag is required as object class */
579 if($obj['status'] == "edited"){
580 $ldap->cat($sub_dn,array("objectClass"));
581 $attrs = $ldap->fetch();
582 if(isset($attrs['objectClass'])){
583 if(in_array_ics("gosaAdministrativeUnitTag",$attrs['objectClass'])){
584 $tmp['objectClass'][] = "gosaAdministrativeUnitTag";
585 }
586 }
587 }
589 if($obj['status'] == "delete"){
590 prepare_to_save_FAI_object($sub_dn,array(),true);
591 $this->handle_post_events("remove");
592 }elseif($obj['status'] == "edited"){
593 prepare_to_save_FAI_object($sub_dn,$tmp);
594 $this->handle_post_events("modify");
595 }elseif($obj['status']=="new"){
596 prepare_to_save_FAI_object($sub_dn,$tmp);
597 $this->handle_post_events("add");
598 }
600 $this->handle_object_tagging($sub_dn, $this->gosaUnitTag);
601 }
602 }
605 /* Return plugin informations for acl handling */
606 function plInfo()
607 {
608 return (array(
609 "plShortName" => _("Script"),
610 "plDescription" => _("FAI script"),
611 "plSelfModify" => FALSE,
612 "plDepends" => array(),
613 "plPriority" => 18,
614 "plSection" => array("administration"),
615 "plCategory" => array("fai"),
616 "plProvidedAcls" => array(
617 "cn" => _("Name")." ("._("Readonly").")",
618 "description" => _("Description"))
619 ));
620 }
621 }
623 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
624 ?>