Code

c92488c37ef562d8ff9a0eff2968c8ca13ec7f92
[gosa.git] / gosa-core / include / class_management.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id: class_plugin.inc 14584 2009-10-12 14:04:22Z hickert $$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 class management
24 {
25   // Public 
26   public $config = null;
27   public $ui     = null;
29   public $plIcon        = "";
30   public $plDescription = "";
31   public $plHeadline    = "";
33   // Protected 
34   protected $dn = "";
35   protected $dns = array();
37   protected $storagePoints = array();
39   protected $last_dn = "";
40   protected $last_dns = array();
42   protected $tabClass = "";
43   protected $tabType = "";
44   protected $aclCategory = "";
45   protected $objectName = "";
46   protected $tabObject = null;
47   protected $dialogObject = null;
49   protected $last_tabObject = null;
50   protected $last_dialogObject = null;
52   protected $displayApplyBtn = "";
53   protected $cpHandler = null;
54   protected $cpPastingStarted = FALSE;
55  
56   protected $snapHandler = null;
58   // Private
59   protected $plugname = "";
60   protected $headpage = null;
61   protected $filter = null;
62   protected $actions = array();
63   
64   function  __construct($config,$ui,$plugname, $headpage)
65   {
66     $this->plugname = $plugname;
67     $this->headpage = $headpage;
68     $this->ui = $ui;
69     $this->config = $config;
71     if($this->cpHandler) $this->headpage->setCopyPasteHandler($this->cpHandler);
72     if($this->snapHandler) $this->headpage->setSnapshotHandler($this->snapHandler);
74     if(empty($this->plIcon)){
75       $this->plIcon = "plugins/".$plugname."/images/plugin.png";
76     }
78     // Register default actions
79     $this->registerAction("new",    "newEntry");
80     $this->registerAction("edit",   "editEntry");
81     $this->registerAction("apply",  "applyChanges");
82     $this->registerAction("save",   "saveChanges");
83     $this->registerAction("cancel", "cancelEdit");
84     $this->registerAction("remove", "removeEntryRequested");
85     $this->registerAction("removeConfirmed", "removeEntryConfirmed");
87     $this->registerAction("copy",   "copyPasteHandler");
88     $this->registerAction("cut",    "copyPasteHandler");
89     $this->registerAction("paste",  "copyPasteHandler");
91     $this->registerAction("snapshot",    "createSnapshotDialog");
92     $this->registerAction("restore",     "restoreSnapshotDialog");
93     $this->registerAction("saveSnapshot","saveSnapshot");
94     $this->registerAction("restoreSnapshot","restoreSnapshot");
95     $this->registerAction("cancelSnapshot","closeDialogs");
97   }
99   function execute()
100   {
101     // Ensure that html posts and gets are kept even if we see a 'Entry islocked' dialog.
102     $vars = array('/^act$/','/^listing/','/^PID$/','/^FILTER_PID$/');
103     session::set('LOCK_VARS_TO_USE',$vars);
105     /* Display the copy & paste dialog, if it is currently open */
106     $ret = $this->copyPasteHandler("",array());
107     if($ret){
108       return($this->getHeader().$ret);
109     }
111     // Update filter
112     if ($this->filter) {
113       $this->filter->update();
114       session::global_set(get_class($this)."_filter", $this->filter);
115       session::set('autocomplete', $this->filter);
116       if (!$this->filter->isValid()){
117         msg_dialog::display(_("Filter error"), _("The filter is incomplete!"), ERROR_DIALOG);
118       }
119     }
121     // Handle actions (POSTs and GETs)
122     $str = $this->handleActions($this->detectPostActions());
123     if($str) return($this->getHeader().$str);
125     // Open single dialog objects
126     if(is_object($this->dialogObject)){
127       if(method_exists($this->dialogObject,'save_object')) $this->dialogObject->save_object(); 
128       if(method_exists($this->dialogObject,'execute')){
129         $display = $this->dialogObject->execute(); 
130         $display.= $this->_getTabFooter();
131         return($this->getHeader().$display);
132       } 
133     }
135     // Display tab object.
136     if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
137       $this->tabObject->save_object();
138       $display = $this->tabObject->execute();
139       $display.= $this->_getTabFooter();
140       return($this->getHeader().$display);
141     }
143     // Set current restore base for snapshot handling.
144     if(is_object($this->snapHandler)){
145       $bases = array();
146       foreach($this->storagePoints as $sp){
147         $bases[] = $sp.$this->headpage->getBase();
148       }
149       $this->snapHandler->setSnapshotBases($bases);
150     }
151     
152     $this->headpage->update();
153     $display = $this->headpage->render();
154     return($this->getHeader().$display);
155   }
157   protected function getHeader()
158   {
159     if (get_object_info() != ""){
160       $display= print_header(get_template_path($this->plIcon),_($this->plDescription),
161       "<img alt=\"\" class=\"center\" src=\"".get_template_path('images/lists/locked.png')."\">".
162         LDAP::fix(get_object_info()));
163     } else {
164       $display= print_header(get_template_path($this->plIcon),_($this->plDescription));
165     }
166     return($display);
167   }
170   protected function _getTabFooter()
171   { 
172     if(!($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug)){
173       return("");
174     }
175   
176     if($this->tabObject->by_object[$this->tabObject->current]){
177       $current = $this->tabObject->by_object[$this->tabObject->current];  
178       if(is_object($current->dialog)){
179         return("");
180       }
181     }
183     $str = "";
184     if(isset($this->tabObject->read_only) && $this->tabObject->read_only == TRUE){
185       $str.= "<p style=\"text-align:right\">
186         <input type=submit name=\"edit_cancel\" value=\"".msgPool::cancelButton()."\">
187         </p>";
188       return($str);
189     }else{
190       $str.= "<p style=\"text-align:right\">\n";
191       $str.= "<input type=submit name=\"edit_finish\" style=\"width:80px\" value=\"".msgPool::okButton()."\">\n";
192       $str.= "&nbsp;\n";
193       if($this->displayApplyBtn){
194         $str.= "<input type=submit name=\"edit_apply\" value=\"".msgPool::applyButton()."\">\n";
195         $str.= "&nbsp;\n";
196       }
197       $str.= "<input type=submit name=\"edit_cancel\" value=\"".msgPool::cancelButton()."\">\n";
198       $str.= "</p>";
199     }
200     return($str);
201   }
204   protected function removeEntryRequested($action,$entry,$all)
205   {
206     $disallowed = array();
207     $this->dns = array();
208     foreach($entry as $dn){
209       $acl = $this->ui->get_permissions($dn, $this->aclCategory."/".$this->aclPlugin);
210       if(preg_match("/d/",$acl)){
211         $this->dns[] = $dn;
212       }else{
213         $disallowed[] = $dn;
214       }
215     }
217     if(count($disallowed)){
218       msg_dialog::display(_("Permission"),msgPool::permDelete($disallowed),INFO_DIALOG);
219     }
221     if(count($this->dns)){
223       /* Check locks */
224       if ($user= get_multiple_locks($this->dns)){
225         return(gen_locked_message($user,$this->dns));
226       }
228       $dns_names = array();
229       foreach($this->dns as $dn){
230         $dns_names[] =LDAP::fix($dn);
231       }
232       add_lock ($this->dns, $this->ui->dn);
234       /* Lock the current entry, so nobody will edit it during deletion */
235       $smarty = get_smarty();
236       $smarty->assign("info", msgPool::deleteInfo($dns_names,_($this->objectName)));
237       $smarty->assign("multiple", true);
238       return($smarty->fetch(get_template_path('remove.tpl', TRUE)));
239     }
240   }  
243   protected function removeEntryConfirmed()
244   {
245     foreach($this->dns as $key => $dn){
247       /* Load permissions for selected 'dn' and check if
248          we're allowed to remove this 'dn' */
249       $acl = $this->ui->get_permissions($dn, $this->aclCategory."/".$this->aclPlugin);
250       if(preg_match("/d/",$acl)){
252         /* Delete request is permitted, perform LDAP action */
253         $this->dn = $dn;
254         $tab = $this->tabClass;
255         $this->tabObject= new $tab($this->config,$this->config->data['TABS'][$this->tabType], $this->dn, $this->aclCategory);
256         $this->tabObject->set_acl_base($this->dn);
257         $this->tabObject->delete ();
258         del_lock($this->dn);        
259       } else {
261         /* Normally this shouldn't be reached, send some extra
262            logs to notify the administrator */
263         msg_dialog::display(_("Permission error"), msgPool::permDelete(), ERROR_DIALOG);
264         new log("security","groups/".get_class($this),$dn,array(),"Tried to trick deletion.");
265       }
266     }
268     $this->remove_lock();
269     $this->closeDialogs();
270   }
273   function detectPostActions()
274   {
275     $action= $this->headpage->getAction();
277     if(isset($_POST['edit_apply']))  $action['action'] = "apply";    
278     if(isset($_POST['edit_finish'])) $action['action'] = "save";    
279     if(isset($_POST['edit_cancel'])) $action['action'] = "cancel";    
280     if(isset($_POST['delete_confirmed'])) $action['action'] = "removeConfirmed";   
282     // Detect Snapshot actions
283     if(isset($_POST['CreateSnapshot'])) $action['action'] = "saveSnapshot";   
284     if(isset($_POST['CancelSnapshot'])) $action['action'] = "cancelSnapshot";   
285     foreach($_POST as $name => $value){
286       $once =TRUE;
287       if(preg_match("/^RestoreSnapShot_/",$name) && $once){
288         $once = FALSE;
289         $entry = base64_decode(preg_replace("/^RestoreSnapShot_([^_]*)_[xy]$/i","\\1",$name));
290         $action['action'] = "restoreSnapshot";
291         $action['targets'] = array($entry);
292       }
293     }
295     return($action);
296   }
298   function handleActions($action)
299   {
300     // Start action  
301     if(isset($this->actions[$action['action']])){
302       $func = $this->actions[$action['action']];
303       if(!isset($action['targets']))$action['targets']= array(); 
304       return($this->$func($action['action'],$action['targets'],$action));
305     }
306   } 
308   function createSnapshotDialog($action="",$target=array(),$all=array())
309   {
310     foreach($target as $entry){
311       if(!empty($entry) && $this->ui->allow_snapshot_create($entry,$this->aclCategory)){
312         $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
313         $this->dialogObject->aclCategories = array($this->aclCategory);
314         
315       }else{
316         msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to create a snapshot for %s."),$entry),
317             ERROR_DIALOG);
318       }
319     }
320   }
323   /*! \brief  Creates a snapshot new entry - This method is called when the somebody
324    *           clicks 'save' in the "Create snapshot dialog" (see ::createSnapshotDialog).
325    *      
326    *  @param  String  'action'  The name of the action which was the used as trigger.
327    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
328    *  @param  Array   'all'     A combination of both 'action' and 'target'.
329    */
330   function saveSnapsho($action="",$target=array(),$all=array())
331   {
332     $this->dialogObject->save_object();
333     $msgs = $this->dialogObject->check();
334     if(count($msgs)){
335       foreach($msgs as $msg){
336         msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
337       }
338     }else{
339       $this->dn =  $this->dialogObject->dn;
340       $this->snapHandler->create_snapshot( $this->dn,$this->dialogObject->CurrentDescription);
341       $this->closeDialogs();
342     }
343   }
346   /*! \brief  Restores a snapshot object.
347    *          The dn of the snapshot entry has to be given as ['target'] parameter.  
348    *      
349    *  @param  String  'action'  The name of the action which was the used as trigger.
350    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
351    *  @param  Array   'all'     A combination of both 'action' and 'target'.
352    */
353   function restoreSnapshot($action="",$target=array(),$all=array())
354   {
355     $entry = array_pop($target);
356     if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
357       $this->snapHandler->restore_snapshot($entry);
358       $this->closeDialogs();
359     }else{
360       msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),
361           ERROR_DIALOG);
362     }
363   }
366   /*! \brief  Displays the "Restore snapshot dialog" for a given target. 
367    *          If no target is specified, open the restore removed object 
368    *           dialog.
369    *  @param  String  'action'  The name of the action which was the used as trigger.
370    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
371    *  @param  Array   'all'     A combination of both 'action' and 'target'.
372    */
373   function restoreSnapshotDialog($action="",$target=array(),$all=array())
374   {
375     // Set current restore base for snapshot handling.
376     if(is_object($this->snapHandler)){
377       $bases = array();
378       foreach($this->storagePoints as $sp){
379         $bases[] = $sp.$this->headpage->getBase();
380       }
381     }
383     // No target, open the restore removed object dialog.
384     if(!count($target)){ 
385       $entry = $this->headpage->getBase();
386       if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
387         $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
388         $this->dialogObject->set_snapshot_bases($bases);
389         $this->dialogObject->display_all_removed_objects = true;
390         $this->dialogObject->display_restore_dialog = true;
391       }else{
392         msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),
393             ERROR_DIALOG);
394       } 
395     }else{
397       // Display the restore points for a given object.
398       $entry = array_pop($target);
399       if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
400         $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
401         $this->dialogObject->set_snapshot_bases($bases);
402         $this->dialogObject->display_restore_dialog = true;
403       }else{
404         msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),
405             ERROR_DIALOG);
406       } 
407     }
408   }
411   /*! \brief  This method intiates the object creation.
412    *          
413    *  @param  String  'action'  The name of the action which was the used as trigger.
414    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
415    *  @param  Array   'all'     A combination of both 'action' and 'target'.
416    */
417   function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
418   {
419     /* To handle mutliple object types overload this method.
420      * ...
421      *   registerAction('newUser', 'newEntry');
422      *   registerAction('newGroup','newEntry');
423      * ... 
424      * 
425      * function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
426      * {
427      *   switch($action){
428      *     case 'newUser' : {
429      *       mangement::newEntry($action,$target,$all,"usertabs","USERTABS","users");
430      *     }
431      *     case 'newGroup' : {
432      *       mangement::newEntry($action,$target,$all,"grouptabs","GROUPTABS","groups");
433      *     }
434      *   }
435      * }
436      **/ 
437     $tabType = $this->tabType;
438     $tabClass = $this->tabClass;
439     $aclCategory = $this->aclCategory;
440     if(!empty($altTabClass)) $tabClass = $altTabClass;
441     if(!empty($altTabType)) $tabType = $altTabType;
442     if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
443   {
444     // Check locking & lock entry if required 
445     $this->displayApplyBtn = FALSE;
446     $this->dn = "new";
447     $this->is_new = TRUE;
448     $this->is_single_edit = FALSE;
449     $this->is_multiple_edit = FALSE;
451     set_object_info($this->dn);
453     // Open object.
454     if(empty($tabClass) || empty($tabType)){
455       // No tab type defined
456     }else{
457       $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$tabType], $this->dn, $aclCategory);
458       $this->tabObject->set_acl_base($this->headpage->getBase());
459     }
460   }
463   /*! \brief  This method opens an existing object or a list of existing objects to be edited. 
464    *                  
465    * 
466    *  @param  String  'action'  The name of the action which was the used as trigger.
467    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
468    *  @param  Array   'all'     A combination of both 'action' and 'target'.
469    */
470   function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
471   {
472     /* To handle mutliple object types overload this method.
473      * ...
474      *   registerAction('editUser', 'editEntry');
475      *   registerAction('editGroup','editEntry');
476      * ... 
477      * 
478      * function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
479      * {
480      *   switch($action){
481      *     case 'editUser' : {
482      *       mangement::editEntry($action,$target,$all,"usertabs","USERTABS","users");
483      *     }
484      *     case 'editGroup' : {
485      *       mangement::editEntry($action,$target,$all,"grouptabs","GROUPTABS","groups");
486      *     }
487      *   }
488      * }
489      **/ 
490     $tabType = $this->tabType;
491     $tabClass = $this->tabClass;
492     $aclCategory = $this->aclCategory;
493     if(!empty($altTabClass)) $tabClass = $altTabClass;
494     if(!empty($altTabType)) $tabType = $altTabType;
495     if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
497     // Single edit - we only got one object dn.
498     if(count($target) == 1){
499       $this->displayApplyBtn = TRUE;
500       $this->is_new = FALSE;
501       $this->is_single_edit = TRUE;
502       $this->is_multiple_edit = FALSE;
504       // Get the dn of the object and creates lock
505       $this->dn = array_pop($target);
506       set_object_info($this->dn);
507       $user = get_lock($this->dn);
508       if ($user != ""){
509         return(gen_locked_message ($user, $this->dn,TRUE));
510       }
511       add_lock ($this->dn, $this->ui->dn);
513       // Open object.
514       if(empty($tabClass) || empty($tabType)){
515         trigger_error("We can't edit any object(s). 'tabClass' or 'tabType' is empty!");
516       }else{
517         $tab = $tabClass;
518         $this->tabObject= new $tab($this->config,$this->config->data['TABS'][$tabType], $this->dn,$aclCategory);
519         $this->tabObject->set_acl_base($this->dn);
520       }
521     }else{
523       // We've multiple entries to edit.
524       $this->is_new = FALSE;
525       $this->is_singel_edit = FALSE;
526       $this->is_multiple_edit = TRUE;
528       // Open multiple edit handler.
529       if(empty($tabClass) || empty($tabType)){
530         trigger_error("We can't edit any object(s). 'tabClass' or 'tabType' is empty!");
531       }else{
532         $this->dns = $target;
533         $tmp = new multi_plug($this->config,$tabClass,$this->config->data['TABS'][$tabType],
534             $this->dns,$this->headpage->getBase(),$aclCategory);
536         // Check for locked entries
537         if ($tmp->entries_locked()){
538           return($tmp->display_lock_message());
539         }
540         
541         // Now lock entries.
542         $tmp->lock_entries($this->ui->dn);
543         if($tmp->multiple_available()){
544           $this->tabObject = $tmp;
545           set_object_info($this->tabObject->get_object_info());
546         }
547       }
548     }
549   }
552   /*! \brief  Save object modifications and closes dialogs (returns to object listing).
553    *          - Calls '::check' to validate the given input.
554    *          - Calls '::save' to save back object modifications (e.g. to ldap).
555    *          - Calls '::remove_locks' to remove eventually created locks.
556    *          - Calls '::closeDialogs' to return to the object listing.
557    */
558   protected function saveChanges()
559   {
560     if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
561       $this->tabObject->save_object();
562       $msgs = $this->tabObject->check();
563       if(count($msgs)){
564         msg_dialog::displayChecks($msgs); 
565         return("");
566       }else{
567         $this->tabObject->save();
568         $this->remove_lock();
569         $this->closeDialogs();
570       }
571     }
572   }
575   /*! \brief  Save object modifications and keep dialogs opened. 
576    *          - Calls '::check' to validate the given input.
577    *          - Calls '::save' to save back object modifications (e.g. to ldap).
578    */
579   protected function applyChanges()
580   {
581   if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
582     $this->tabObject->save_object();
583       $msgs = $this->tabObject->check();
584       if(count($msgs)){
585         msg_dialog::displayChecks($msgs); 
586         return("");
587       }else{
588         $this->tabObject->save();
589         $this->tabObject->re_init();
590       }
591     }
592   }
594   
595   /*! \brief  This method closes dialogs
596    *           and cleans up the cached object info and the ui.
597    */
598   protected function closeDialogs()
599   {
600     $this->last_dn = $this->dn;
601     $this->last_dns = $this->dns;
602     $this->last_tabObject = $this->tabObject;
603     $this->last_dialogObject = $this->dialogObject;
604     $this->dn = "";
605     $this->dns = array();
606     $this->tabObject = null;
607     $this->dialogObject = null;
608     set_object_info();
609   }
612   /*! \brief  Editing an object was caneled. 
613    *          Close dialogs/tabs and remove locks.
614    */
615   protected function cancelEdit()
616   {
617     $this->remove_lock();
618     $this->closeDialogs();
619   }
621  
622   /*! \brief  Every click in the list user interface sends an event
623    *           here can we connect those events to a method. 
624    *          eg.  ::registerEvent('new','createUser')
625    *          When the action/event new is send, the method 'createUser' 
626    *           will be called.
627    */
628   function registerAction($action,$target)
629   {
630     $this->actions[$action] = $target;
631   }
633   
634   /*! \brief  Removes ldap object locks created by this class.
635    *          Whenever an object is edited, we create locks to avoid 
636    *           concurrent modifications.
637    *          This locks will automatically removed here.
638    */
639   function remove_lock()
640   {
641     if(!empty($this->dn) && $this->dn != "new"){
642       del_lock($this->dn);
643     }
644     if(count($this->dns)){
645       del_lock($this->dns);
646     }
647   }
650   /*! \brief  This method is used to queue and process copy&paste actions. 
651    *          Allows to copy, cut and paste mutliple entries at once.
652    *  @param  String  'action'  The name of the action which was the used as trigger.
653    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
654    *  @param  Array   'all'     A combination of both 'action' and 'target'.
655    */
656   function copyPasteHandler($action="",$target=array(),$all=array())
657   {
658     // Return without any actions while copy&paste handler is disabled.
659     if(!is_object($this->cpHandler))  return("");
661     // Save user input
662     $this->cpHandler->save_object();
664     // Add entries to queue 
665     if($s_action == "copy" || $s_action == "cut"){
666       $this->cpHandler->cleanup_queue();
667       foreach($s_entry as $dn){
668         if($s_action == "copy" && $this->ui->is_copyable($dn,$this->aclCategory,$this->aclPlugin)){
669           $this->cpHandler->add_to_queue($dn,"copy",$this->tabClass,$this->tabType,$this->aclCategory);
670         }
671         if($s_action == "cut" && $this->ui->is_cutable($dn,$this->aclCategory,$this->aclPlugin)){
672           $this->cpHandler->add_to_queue($dn,"cut",$this->tabClass,$this->tabType,$this->aclCategory);
673         }
674       }
675     }
677     // Initiate pasting
678     if($s_action == "paste"){
679       $this->cpPastingStarted = TRUE;
680     }
682     // Display any c&p dialogs, eg. object modifications required before pasting.
683     if($this->cpPastingStarted && $this->cpHandler->entries_queued()){
684       $this->cpHandler->SetVar("base",$this->headpage->getBase());
685       $data = $this->cpHandler->execute();
686       if(!empty($data)){
687         return($data);
688       }
689     }
691     // Automatically disable pasting process since there is no entry left to paste.
692     if(!$this->cpHandler->entries_queued()){
693       $this->cpPastingStarted = FALSE;
694     }
695     return("");
696   }
701 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
702 ?>