1 <?php
3 define("LDAP_DUMP_PATH","/tmp/gosa");
5 class CopyPasteHandler {
7 var $config;
8 var $current;
10 /* This array contains all dns of the currently copyied objects */
11 var $queue = array();
13 /* Attributes that should be overwritten */
14 var $setvar_array= array();
16 /* The dn of the last edited object */
17 var $lastdn = "";
20 /* Create CP handler */
21 function CopyPasteHandler(&$config)
22 {
23 $this->config = &$config;
24 $this->current= NULL;
25 $this->queue = array();
26 $this->setvar_array = array();
27 }
30 /* Entry entry to Copy & Paste queue.
31 * A Queue entry is represented as follows.
32 * array['file_name'] - Position on hdd
33 * array['method'] - copy/cut
34 * array['dn'] - the dn of the object added to the queue
35 * array['tab_class'] - Tab object that should be used to initialize the new object
36 * array['tab_object'] - Tab object name used to initialize correct object Type like USERTABS
37 */
38 function add_to_queue($dn,$action,$tab_class,$tab_object,$tab_acl_category)
39 {
40 if(!class_exists($tab_class)){
41 trigger_error(sprintf("Specified class object '%s' does not exists.",$tab_class));
42 return(FALSE);
43 }
45 if(!isset($this->config->data['TABS'][$tab_object])){
46 trigger_error(sprintf("Specified tab object '%s' does not exists.",$tab_object));
47 return(FALSE);
48 }
50 if(!in_array($action,array("cut","copy"))){
51 trigger_error(sprintf("Specified action '%s' does not exists for copy & paste.",$action));
52 return(FALSE);
53 }
55 if($file_name = $this->save_dn_attributes_to_hdd($dn)){
56 $tmp = array();
57 $tmp['file_name'] = $file_name;
58 $tmp['method'] = $action;
59 $tmp['dn'] = $dn;
60 $tmp['tab_class'] = $tab_class;
61 $tmp['tab_object']= $tab_object;
62 $tmp['tab_acl_category']= $tab_acl_category;
63 $this->queue[] = $tmp;
64 }
65 }
68 /* This removes all objects from queue.
69 * Remove hdd dumps of current entries too.
70 * Remove entries older than 24 hours.
71 */
72 function cleanup_queue()
73 {
74 $this->current = FALSE;
75 $this->setvar_array = array();
77 /* Remove all entries from queue */
78 foreach($this->queue as $key => $entry){
79 @rmdir($entry['file_name']);
80 unset($this->queue[$key]);
81 }
83 /* Create patch if it doesn't exists */
84 if(!is_dir(LDAP_DUMP_PATH)){
85 @mkdir(LDAP_DUMP_PATH);
86 }
88 /* Update folder permissions */
89 if(!@chmod(LDAP_DUMP_PATH,0700)){
90 $msg= sprintf(_("Cannot cleanup copy & paste queue: setting permissions for '%s' failed!"),LDAP_DUMP_PATH);
91 msg_dialog::display(_("Configuration error"), $msg, ERROR_DIALOG);
92 new log("copy","all/all","copy & paste, event queue.",array(), $msg);
93 return(FALSE);
94 }
96 /* check if we are able to create a new file the given directory */
97 if(!is_writeable(LDAP_DUMP_PATH)){
98 $msg= sprintf(_("Cannot cleanup copy & paste queue: no write permission inside '%s'!"),LDAP_DUMP_PATH);
99 msg_dialog::display(_("Configuration error"), $msg, ERROR_DIALOG);
100 new log("copy","all/all","copy & paste, event queue.",array(), $msg);
101 return(FALSE);
102 }
104 /* Remove entries from hdd that are older than24 hours */
105 $fp = opendir(LDAP_DUMP_PATH);
106 while($file = readdir($fp)){
107 if(is_file(LDAP_DUMP_PATH."/".$file) && !preg_match("/^\./",$file)){
108 $file_time = fileatime(LDAP_DUMP_PATH."/".$file);
109 if($file_time < (time() - (24* 60 *60))){
110 @unlink(LDAP_DUMP_PATH."/".$file);
111 }
112 }
113 }
114 }
117 /* To increase performance we save the ldap dump on hdd
118 * This function automatically creates the dumps and returns
119 * the name of the dumpfile we created
120 */
121 function save_dn_attributes_to_hdd($dn)
122 {
123 $filename = "Should not be returned";
124 $ldap = $this->config->get_ldap_link();
125 $ldap->cd($this->config->current['BASE']);
126 $res = $ldap->cat($dn);
128 /* Check if given dn is valid and ldap search was succesfull */
129 if(!$res){
130 $msg= sprintf(_("Copy and paste failed: object '%s' is not a valid ldap object!"), LDAP::fix($dn));
131 msg_dialog::display(_("Internal error"), $msg, ERROR_DIALOG);
132 new log("copy","all/all",$dn,array(), $msg);
133 return(FALSE);
134 }
136 /* Create data to save given ldap dump on the hdd */
137 $filename = "gosa_copy-paste_dump_".preg_replace("/[^0-9]/","",microtime());
138 $path = LDAP_DUMP_PATH;
140 /* Create patch if it doesn't exists */
141 if(!is_dir($path)){
142 @mkdir($path);
143 }
145 /* check if we are able to create a new file the given directory */
146 if(!is_writeable($path)){
147 $msg= sprintf(_("Cannot save LDAP dump: no write permission inside '%s'!"),LDAP_DUMP_PATH);
148 msg_dialog::display(_("Configuration error"), $msg, ERROR_DIALOG);
149 new log("copy","all/all",$dn,array(), $msg);
150 return(FALSE);
151 }
153 /* Update folder permissions */
154 if(!@chmod(LDAP_DUMP_PATH,0700)){
155 $msg= sprintf(_("Cannot save LDAP dump: setting permissions for '%s' failed!"),LDAP_DUMP_PATH);
156 msg_dialog::display(_("Configuration error"), $msg, ERROR_DIALOG);
157 new log("copy","all/all","copy & paste, event queue.",array(), $msg);
158 return(FALSE);
159 }
161 /* Create file handle */
162 $fp = @fopen($path."/".$filename,"w+");
163 if(!$fp){
164 $msg= sprintf(_("Cannot save LDAP dump: no write permission to '%s/%s'!"),$path,$filename);
165 msg_dialog::display(_("Configuration error"), $msg, ERROR_DIALOG);
166 new log("copy","all/all",$dn,array(), $msg);
167 return(FALSE);
168 }
170 $data = serialize($ldap->fetch());
171 fwrite($fp,$data,strlen($data));
172 fclose($fp);
174 /* Only the webserver should be able to read those files */
175 @chmod($path."/".$filename,0600);
176 return($path."/".$filename);
177 }
180 /* Check if there are still entries the object queue */
181 function entries_queued()
182 {
183 return( count($this->queue) >=1 || $this->current != FALSE);
184 }
187 /* Paste one entry from queue */
188 function load_entry_from_queue()
189 {
191 /* Save posted variables, handle dialog posts like 'cancel' */
192 $this->save_object();
194 /* If there is currently no object pasted
195 * create new object and prepare object to be pasted
196 */
197 if(!$this->current && $this->entries_queued()){
198 $key = key($this->queue);
199 $entry = $this->queue[$key];
200 $tab_c = $entry['tab_class'];
201 $tab_o = $entry['tab_object'];
202 $tab_a = $entry['tab_acl_category'];
204 if($entry['method'] == "copy"){
205 $entry['object'] = new $tab_c($this->config,$this->config->data['TABS'][$tab_o],"new",$tab_a);
206 }else{
207 $entry['object'] = new $tab_c($this->config,$this->config->data['TABS'][$tab_o],$entry['dn'],$tab_a);
208 }
210 $entry['source_data'] = $this->load_attributes_from_hdd($entry['file_name']);
212 if($entry['method'] == "copy"){
214 /* Prepare each plugin of this tab object to be posted */
215 foreach($entry['object']->by_object as $name => $obj){
217 /* Prepare every single class, to be copied */
218 $entry['object']->by_object[$name]->PrepareForCopyPaste($entry['source_data']);
220 /* handle some special vars */
221 foreach(array("is_account") as $attr){
222 if(isset($entry['source_data'][$attr])){
223 $entry['object']->by_object[$name]->$attr = $entry['source_data'][$attr];
224 }
225 }
226 }
227 }
229 /* Assign created object as current */
230 $this->current = $entry;
231 unset($this->queue[$key]);
232 }
233 }
236 /* Load dumped ldap entry specified by $filename and
237 * return data an unserailized data array
238 */
239 function load_attributes_from_hdd($filename)
240 {
241 $fp = @fopen($filename,"r");
242 if(is_file($filename) && is_readable($filename) && $fp){
243 $data = "";
244 while($str = fgets($fp,512)){
245 $data .= $str;
246 }
247 return(unserialize($data));
248 }else{
249 $msg= sprintf(_("Cannot load dumped file '%s'!"),$filename);
250 msg_dialog::display(_("Internal error"), $msg, ERROR_DIALOG);
251 new log("copy","all/all",$dn,array(), $msg);
252 return(FALSE);
253 }
254 }
257 /* Displays a dialog which allows the user to fix all dependencies of this object.
258 Create unique names, ids, or what ever */
259 function execute()
260 {
261 $ui = get_userinfo();
262 $type = $this->current['method'];
263 if($type == "cut"){
264 if(isset($_POST['PerformCopyPaste'])){
265 while($this->entries_queued()){
266 $this->load_entry_from_queue();
267 $this->_update_vars();
269 $msgs = $this->check();
270 $acl = $ui->get_category_permissions($this->current['dn'], $this->current['tab_acl_category']);
272 /* Check permissions */
273 if(!preg_match("/((c|w)|(w|c))/",$acl)){
274 msg_dialog::display(_("Error"), sprintf(_("You have no permission to save object '%s'."), $this->current['dn']), ERROR_DIALOG);
275 }elseif(count ($msgs) ){
276 foreach( $msgs as $msg){
277 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
278 }
279 }else{
281 /* Load next queue entry */
282 $this->lastdn = $this->current['object']->dn;
283 $this->current['object']->save();
284 }
286 $this->current =FALSE;
287 }
288 }
289 if($this->current){
291 $dns = $this->current['dn']."\n";
292 foreach($this->queue as $entry){
293 $dns .= $entry['dn']."\n";
294 }
296 $smarty = get_smarty();
297 $smarty->assign("type","cut");
298 $smarty->assign("Complete",false);
299 $smarty->assign("AttributesToFix"," ");
300 $smarty->assign("SubDialog",$this->current['object']->SubDialog);
301 $smarty->assign("objectDN" ,$dns);
302 $smarty->assign("message", sprintf(_("You are going to paste the cutted entry '%s'."), "<pre>".$dns."</pre>"));
303 return($smarty->fetch(get_template_path("copyPasteDialog.tpl",FALSE)));
304 }
305 }
306 if($type == "copy"){
307 if(isset($_POST['PerformCopyPaste'])){
308 $this->_update_vars();
309 $msgs = $this->check();
311 $acl = $ui->get_category_permissions($this->current['dn'], $this->current['tab_acl_category']);
313 /* Check permissions */
314 if(!preg_match("/((c|w)|(w|c))/",$acl)){
315 msg_dialog::display(_("Error"), sprintf(_("You have no permission to copy and paste object '%s'!"),$this->current['dn']), ERROR_DIALOG);
316 }elseif(count ($msgs) ){
317 foreach( $msgs as $msg){
318 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
319 }
320 }else{
321 $this->current['object']->save();
322 $this->lastdn = $this->current['object']->dn;
323 $this->current =FALSE;
325 /* Load next queue entry */
326 $this->load_entry_from_queue();
327 }
328 }
329 if($this->current){
330 $smarty = get_smarty();
331 $smarty->assign("type","copy");
332 $smarty->assign("Complete",false);
333 $smarty->assign("AttributesToFix",$this->generateAttributesToFix());
334 $smarty->assign("SubDialog",$this->current['object']->SubDialog);
335 $smarty->assign("objectDN" ,$this->current['source_data']['dn']);
336 $smarty->assign("message", sprintf(_("You are going to paste the copied entry '%s'."), $this->current['source_data']['dn']));
337 return($smarty->fetch(get_template_path("copyPasteDialog.tpl",FALSE)));
338 }
339 }
340 }
343 /* Return the dn of the last edited entry */
344 function last_entry()
345 {
346 return($this->lastdn);
347 }
350 /* Save new values posted by copy & paste dialog */
351 function save_object()
352 {
353 if(isset($_POST['abort_current_cut-copy_operation'])){
354 $this->current = FALSE;
355 }
357 if(isset($_POST['abort_all_cut-copy_operations'])){
358 $this->cleanup_queue();
359 $this->current = FALSE;
360 }
362 /* Assign posted var to all tabs
363 */
364 if($this->current){
365 $this->current['object']->saveCopyDialog();
366 }
367 }
370 /* Create dialog which asks unique attributes/values ...
371 * call tabs -> getCopyDialog()
372 * which calls tab -> getCopyDialog() */
373 function generateAttributesToFix()
374 {
375 if($this->current){
376 return($this->current['object']->getCopyDialog());
377 }
378 }
381 /* Set a single attribute to specified value
382 * example : ("base", $newBase ); */
383 function SetVar($name,$value)
384 {
385 $this->setvar_array[$name]=$value;
386 }
389 /* Update current object attributes, collected via SetVar */
390 function _update_vars()
391 {
392 if($this->current){
394 /* Update all attributes specified with SetVar */
395 foreach($this->setvar_array as $name => $value){
396 if(isset($this->current['object']->$name)){
397 $this->current['object']->$name = $value;
398 }
399 }
401 /* Walk through tabs */
402 foreach($this->current['object']->by_object as $key => $obj){
404 /* Update all attributes specified with SetVar */
405 foreach($this->setvar_array as $name => $value){
406 if(isset($this->current['object']->by_object[$key]->$name)){
407 $this->current['object']->by_object[$key]->$name = $value;
408 }
409 }
410 }
411 }
412 }
415 /* Returns errors from including tabs. */
416 function check()
417 {
418 $ret = array();
419 foreach($this->current['object']->by_object as $obj){
420 if($obj->is_account || $obj->ignore_account){
421 $ret = array_merge($ret , $obj->check());
422 }
423 }
424 return($ret);
425 }
428 /* returns the paste icon for headpages */
429 function generatePasteIcon()
430 {
431 $Copy_Paste= " <img class='center' src='images/list_seperator.png' align='middle' alt='' height='16' width='1'> ";
432 if($this->entries_queued()){
433 $img= "images/copypaste.png";
434 $Copy_Paste.= "<input type='image' name='editPaste' class='center'
435 src='".$img."' alt='"._("Paste")."'> ";
436 }else{
437 $Copy_Paste.= "<img class='center' src='images/cant_editpaste.png' alt=\""._("Can't paste")."\"> ";
438 }
439 return ($Copy_Paste);
440 }
441 }
442 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
443 ?>