Code

81b6b34525b76c3328130ab3c8549fa5b204b550
[gosa.git] / include / sieve / class_sieveManagement.inc
1 <?php
2 /*
3    This code is part of GOsa (https://gosa.gonicus.de)
4    Copyright (C) 2003-2007 - Fabian Hickert <hickert@gonicus.de>
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
22 /* The sieve management class displays a list of sieve 
23  *  scripts for the given mail account. 
24  * The account is identified by the parents uid attribute. 
25  *
26  *  $config       The config object
27  *  $dn           The object edited 
28  *  $parent       The parent object that provides the uid attribute 
29  */
30 class sieveManagement extends plugin
31 {
32   var $parent = NULL;
33   var $scripts= array();  
35   var $current_script  = -1;
36   var $current_handler = NULL;
37   var $script_to_delete =-1;
38   var $sieve_handle = NULL; 
39   var $Script_Error = "";
40   var $Sieve_Error = "";
41   var $create_script = FALSE;
43   /* To add new elements we need to know 
44    *  Where to the element                  -> add_new_id
45    *  Whould we add above or below this id  -> add_above_below
46    *  What kind of element should we add    -> add_element_type
47    */
48   var $add_new_element    = FALSE;
49   var $add_new_id         = -1;
50   var $add_above_below    = "below";
51   var $add_element_type   = "sieve_comment";
54   function get_sieve()
55   {
56     /* Connect to sieve class and try to get all available sieve scripts */
57     $cfg=  $this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer];
58     $this->Sieve_Error = "";
59   
60     /* Log into the mail server */
61     $sieve= new sieve(
62         $cfg["sieve_server"], 
63         $cfg["sieve_port"], 
64         $this->parent->uid, 
65         $cfg["password"], 
66         $cfg["admin"]);
68     /* Try to login */
69     if (!$sieve->sieve_login()){
70       $this->Sieve_Error = $sieve->error_raw;
71       return(FALSE);
72     }
73     return($sieve);
74   }
76   /* Initialize the class and load all sieve scripts 
77    *  try to parse them and display errors 
78    */ 
79   function sieveManagement($config,$dn,$parent)
80   {
81     $this->parent = $parent;
82     plugin::plugin($config,$dn);
84     /* Get sieve */
85     if(!$sieve = $this->get_sieve()){
86       print_red(
87         sprintf(
88           _("Can't log into SIEVE server. Server says '%s'."),
89           to_string($this->Sieve_Error)));
90       return;
91     }
94     /* Get all sieve scripts names */
95     if($sieve->sieve_listscripts()){
96       if (is_array($sieve->response)){
97         foreach($sieve->response as $key => $name){
99           $data = array();
100           $data['NAME'] = $name;
102           if($key == "ACTIVE" && $key === "ACTIVE"){
103             $data['ACTIVE'] = TRUE;
104           }else{
105             $data['ACTIVE'] = FALSE;
106           }
107           $this->scripts[] = $data;          
108         }
109       } 
110     }
112     /* Get script contents */
113     foreach($this->scripts as $key => $script){
114       $p = new My_Parser;
115       $sieve->sieve_getscript($script['NAME']);
117       $script = "";
118       foreach($sieve->response as $line){
119         $script.=$line;
120       }
122       $this->scripts[$key]['IS_NEW'] = FALSE;;
123       $this->scripts[$key]['SCRIPT'] = $script;
124       $this->scripts[$key]['ORIG_SCRIPT'] = $script;
125       $this->scripts[$key]['MSG']   = "";
126       $ret = $p->parse($script);
127       if(!$ret){
128         $this->scripts[$key]['STATUS']   = FALSE;
129         $this->scripts[$key]['MODE']    = "Source-Only";
130         $this->scripts[$key]['MSG'] = _("Parse failed")."<font color='red'>".$p->status_text."</font>";
131       }else{
132         $this->scripts[$key]['STATUS']   = TRUE;
133         $this->scripts[$key]['MODE']    = "Structured";
134         $this->scripts[$key]['MSG'] = _("Parse successful");
135       }
136       $this->scripts[$key]['PARSER'] = $p;
137       $this->scripts[$key]['EDITED'] = FALSE;
138     }
139     $this->sieve_handle = $sieve;
140   }
143   /* Handle sieve list 
144    */
145   function execute()
146   {
147     /***************
148      * Create a new Script 
149      ***************/
151     /* Force opening the add script dialog */
152     if(isset($_POST['create_new_script'])){
153       $this->create_script = TRUE;
154     }
156     /* Close add script dialog, without adding a new one */
157     if(isset($_POST['create_script_cancel'])){
158       $this->create_script = FALSE;
159     }
161     /* Display create script dialog 
162      *  handle posts, display warnings if specified 
163      *  name is not useable. 
164      * Create a new script with given name
165      */
166     if($this->create_script){
167     
168       /* Set initial name or used posted name if available */
169       $name = "";
170       if(isset($_POST['NewScriptName'])){
171         $name = trim($_POST['NewScriptName']);
172       }
173  
174       /* Check given name */ 
175       $err = "";
177       /* Is given name in lower case characters ? */
178       if(isset($_POST['create_script_save'])){
179         if(!strlen($name)){
180           $err = _("You should specify a name for your new script.");
181         }
182         /* Is given name in lower case characters ? */
183         if($name != strtolower($name)){
184           $err = _("Only lower case names are allowed here.");
185         }
187         /* Only chars are allowed here */
188         if(preg_match("/[^a-z]/i",$name)){
189           $err = _("Only a-z are allowed in script names.");
190         }
191       }
193       /* Create script if everything is ok */
194       if($this->create_script && isset($_POST['create_script_save']) && $err == "" ){
196         /* Close dialog */
197         $this->create_script = FALSE;
199         /* Script contents to use */
200         $script = "/*New script */".
201                   "stop;";
203         /* Create a new parser and initialize default values */
204         $p = new My_Parser;
205         $ret = $p->parse($script);
206         $sc['SCRIPT'] = $script;
207         $sc['ORIG_SCRIPT'] = $script;
208         $sc['IS_NEW'] = TRUE;
209         $sc['MSG']   = "";
210         if(!$ret){
211           $sc['STATUS']   = FALSE;
212           $sc['MODE']    = "Source-Only";
213           $sc['MSG'] = _("Parse failed")."<font color='red'>".$p->status_text."</font>";
214         }else{
215           $sc['STATUS']   = TRUE;
216           $sc['MODE']    = "Strucktured";
217           $sc['MSG'] = _("Parse successful");
218         }
219         $sc['PARSER'] = $p;
220         $sc['EDITED'] = TRUE;
221         $sc['ACTIVE'] = FALSE;
222         $sc['NAME']   = $name;
223       
224         /* Add script */
225         $this->scripts[$name] = $sc;
226       }else{
227       
228         /* Display dialog to enter new script name */
229         $smarty = get_smarty();
230         $smarty->assign("NewScriptName",$name);
231         $smarty->assign("Error",$err);
232         return($smarty->fetch(get_template_path("templates/create_script.tpl",TRUE,dirname(__FILE__))));
233       }
234     }
237     /*************
238      * Handle several posts 
239      *************/
241     $once = TRUE;
242     foreach($_POST as $name => $value){
244       /* Edit script requested */
245       if(preg_match("/^editscript_/",$name) && $once && !$this->current_handler){
246         $script = preg_replace("/^editscript_/","",$name);
247         $script = preg_replace("/_(x|y)/","",$script);
248         $once = FALSE;
250         $this->current_script = $script;
251         $this->current_handler = $this->scripts[$script]['PARSER'];
252       }
254       /* remove script requested */
255       if(preg_match("/^delscript_/",$name) && $once && !$this->current_handler){
256         $script = preg_replace("/^delscript_/","",$name);
257         $script = preg_replace("/_(x|y)/","",$script);
258         $once = FALSE;
259  
260         $this->script_to_delete = $script;  
261       }
263       /* Activate script */
264       if(preg_match("/^active_script_/",$name) && $once && !$this->current_handler){
265         $script = preg_replace("/^active_script_/","",$name);
266         $script = preg_replace("/_(x|y)/","",$script);
267         $once = FALSE;
269         /* Get sieve */
270         if(!$sieve = $this->get_sieve()){
271           print_red(
272               sprintf(
273                 _("Can't log into SIEVE server. Server says '%s'."),
274                 to_string($this->Sieve_Error)));
275         }
277         /* Try to activate the given script and update 
278          *  class script array. 
279          */
280         if(!$this->sieve_handle->sieve_setactivescript($this->scripts[$script]['NAME'])){
281           print_red(sprintf(_("Can't activate sieve script on server. Server says '%s'."),to_string($this->sieve_handle->error_raw)));
282         }else{
283           foreach($this->scripts as $key => $data){
284             if($key == $script){
285               $this->scripts[$key]['ACTIVE'] = TRUE;
286             }else{
287               $this->scripts[$key]['ACTIVE'] = FALSE;
288             }
289           }
290         }
291       }
292     }
294     
295     /*************
296      * Remove script handling 
297      *************/
299     /* Remove aborted */
300     if(isset($_POST['delete_cancel'])){
301       $this->script_to_delete = -1;
302     }
304     /* Remove confirmed */
305     if(isset($_POST['delete_script_confirm'])){
307       $script = $this->scripts[$this->script_to_delete];
309       /* Just remove from array if it is a new script */
310       if($script['IS_NEW']){
311         unset($this->scripts[$this->script_to_delete]);
312       }else{
314         /* Get sieve */
315         if(!$sieve = $this->get_sieve()){
316           print_red(
317               sprintf(
318                 _("Can't log into SIEVE server. Server says '%s'."),
319                 to_string($this->Sieve_Error)));
320         }
322         if(!$this->sieve_handle->sieve_deletescript($this->scripts[$this->script_to_delete]['NAME'])){
323           print_red(sprintf(_("Can't remove sieve script from server. Server says '%s'."),to_string($this->sieve_handle->error_raw)));
324         }else{
325           unset($this->scripts[$this->script_to_delete]);
326         }
327       }
328       $this->script_to_delete = -1;
329     }
331     /* Display confirm dialog */
332     if($this->script_to_delete != -1){
333       $smarty = get_smarty();
334       $smarty->assign("Warning",
335           sprintf(_("You are going to remove the sieve script '%s' from your mail server."),
336             $this->scripts[$this->script_to_delete]['NAME']));
337       return($smarty->fetch(get_template_path("templates/remove_script.tpl",TRUE,dirname(__FILE__))));
338     }
341     /**************
342      * Save script changes 
343      **************/
345     /* Abort saving */
346     if(isset($_POST['cancel_sieve_changes'])){
347       $this->current_handler = NULL;
348     }
350     /* Save currently edited sieve script. */
351     if(isset($_POST['save_sieve_changes'])){
352       $chk = $this->current_handler->check();
353       if(!count($chk)){
355         $sc = $this->scripts[$this->current_script]['SCRIPT'];
356         $p = new My_Parser;
357         if($p -> parse($sc)){
359           if($this->scripts[$this->current_script]['MODE'] == "Source-Only"){
360             $this->scripts[$this->current_script]['MODE'] = "Source";
361           }
362   
363           $this->scripts[$this->current_script]['PARSER'] = $p;
364           $this->scripts[$this->current_script]['EDITED'] = TRUE;
365           $this->scripts[$this->current_script]['STATUS'] = TRUE;
366           $this->scripts[$this->current_script]['MSG'] = _("Edited");
367           $this->current_handler = NULL;
368         }else{
369           print_red($p->status_text);;
370         }
371       }else{
372         print_red(_("Please fix all errors before saving."));
373       }
374     }
377     /*************
378      * Display edit dialog 
379      *************/
381     /* Display edit dialog, depending on Mode display different uis
382      */
383     if($this->current_handler){
385       /****
386        * Add new element to ui
387        ****/
389       /* Abort add dialog */ 
390       if(isset($_POST['select_new_element_type_cancel'])){
391         $this->add_new_element = FALSE;
392       }
394       /* Add a new element */
395       if($this->add_new_element){
397         $element_types= array(
398             "sieve_keep"      => _("Keep"),
399             "sieve_comment"   => _("Comment"),
400             "sieve_fileinto"  => _("File into"),
401             "sieve_keep"      => _("Keep"),
402             "sieve_discard"   => _("Discard"),
403             "sieve_redirect"  => _("Redirect"),
404             "sieve_reject"    => _("Reject"),
405             "sieve_require"   => _("Require"),
406             "sieve_stop"      => _("Stop"),
407             "sieve_vacation"  => _("Vacation message"),
408             "sieve_if"        => _("If"));
411         /* Element selected */
412         if(isset($_POST['element_type']) && isset($element_types[$_POST['element_type']])){
413           $this->add_element_type = $_POST['element_type'];
414         }
416         /* Create new element and add it to
417          *  the selected position 
418          */
419         if(isset($_POST['select_new_element_type'])){
421           /* Create elements we should add */
422           $ele[] = new $this->add_element_type(NULL, preg_replace("/[^0-9]/","",microtime()));
423           if($this->add_element_type == "sieve_if"){
424             $ele[] = new sieve_block_start(NULL,preg_replace("/[^0-9]/","",microtime()));
425             $ele[] = new sieve_block_end(NULL,preg_replace("/[^0-9]/","",microtime()));
426           }
427           $start = $end = array();
428           $found = false;
429           $data = $this->current_handler->tree_->pap;
431           /* Add above current element*/
432           if($this->add_above_below == "above"){
433             foreach($data as $key => $obj){
434               if($obj->object_id == $this->add_new_id){
435                 $found = true;
436               }
437               if(!$found){
438                 $start[] = $obj;
439               }else{
440                 $end[] = $obj;
441               }
442             }
443           }else{
444             /* Add below current element */
445             foreach($data as $key => $obj){
446               if(!$found){
447                 $start[] = $obj;
448               }else{
449                 $end[] = $obj;
450               }
451               if($obj->object_id == $this->add_new_id){
452                 $found = true;
453               }
454             }
455           }
457           /* Only add, if current element could be located */
458           if($found){
459             $new = array();
460             foreach($start as $obj){
461               $new[] = $obj;
462             }
463             foreach($ele as $el){
464               $new[] = $el;
465             }
466             foreach($end as $obj){
467               $new[] = $obj;
468             }
469             $data= $new;
470             $this->current_handler->tree_->pap = $data;
471             $this->add_new_element = FALSE;
472           }else{
473             print_red(_("Something went wrong while adding a new entry."));
474           }
475         }
476       }
478       /* Only display select dialog if it is necessary */
479       if($this->add_new_element){
480         $smarty = get_smarty();
481         $smarty->assign("element_types",$element_types );
482         $smarty->assign("element_type",$this->add_element_type);
483         $str = $smarty->fetch(get_template_path("templates/add_element.tpl",TRUE,dirname(__FILE__)));
484         return($str);
485       }
489       /****************
490        * Handle test posts 
491        ****************/
493       /* handle some special posts from test elements 
494        */
495       foreach($_POST as $name => $value){
496         if(preg_match("/^Add_Test_Object_/",$name)) {
497           $name = preg_replace("/^Add_Test_Object_/","",$name);
498           $name = preg_replace("/_(x|y)$/","",$name);
500           $test_types_to_add = array(
501               "address" =>_("Address"),
502               "header"  =>_("Header"),
503               "envelope"=>_("Envelope"),
504               "size"    =>_("Size"),
505               "exists"  =>_("Exists"),
506               "allof"   =>_("All of"),
507               "anyof"   =>_("Any of"),
508               "true"    =>_("True"),
509               "false"   =>_("False"));
511           $smarty = get_smarty();
512           $smarty->assign("ID",$name);
513           $smarty->assign("test_types_to_add",$test_types_to_add);
514           $ret = $smarty->fetch(get_template_path("templates/select_test_type.tpl",TRUE,dirname(__FILE__)));
515           return($ret);
516         }
517       }
519       $current = $this->scripts[$this->current_script];
521       /* Create html results */
522       $smarty = get_smarty();
523       $smarty->assign("Mode",$current['MODE']);
524       if($current['MODE'] == "Structured"){
525         $smarty->assign("Contents",$this->current_handler->tree_->execute());
526       }else{
527         $smarty->assign("Contents",$current['SCRIPT']);
528       }
529       $smarty->assign("Script_Error",$this->Script_Error);
530       $ret = $smarty->fetch(get_template_path("templates/edit_frame_base.tpl",TRUE,dirname(__FILE__)));
531       return($ret);
532     }
535     /* Create list of available sieve scripts 
536      */
537     $List = new divSelectBox("sieveManagement");
538     foreach($this->scripts as $key => $script){
539   
540       $edited =  $script['EDITED'];
541       $active =  $script['ACTIVE'];
542       
543       $field1 = array("string" => "&nbsp;",
544                       "attach" => "style='width:20px;'");  
545       if($active){
546         $field1 = array("string" => "<img src='images/true.png' alt='"._("Active")."'>",
547                         "attach" => "style='width:20px;'");  
548       }
549       $field2 = array("string" => $script['NAME']);  
550       $field3 = array("string" => $script['MSG']);
551       $field4 = array("string" => _("Script length")."&nbsp;:&nbsp;".strlen($script['SCRIPT']));
553       if($edited){
554         $field5 = array("string" => "<img src='images/fai_new_hook.png' alt='"._("Edited")."'>",
555                         "attach" => "style='width:30px;'");
556       }else{
557         $field5 = array("string" => "",
558                         "attach" => "style='width:30px;'");
559       }
561       if($active){
562         $field6 = array("string" => "<img src='images/empty.png' alt=' '>".
563                                     "<input type='image' name='editscript_".$key."' src='images/edit.png'>".
564                                     "<input type='image' name='delscript_".$key."' src='images/edittrash.png'>");
565       }else{
566         $field6 = array("string" => "<input type='image' name='active_script_".$key."' src='images/true.png'>".
567                                     "<input type='image' name='editscript_".$key."' src='images/edit.png'>".
568                                     "<input type='image' name='delscript_".$key."' src='images/edittrash.png'>");
569       }
570       $List ->AddEntry(array($field1,$field2,$field3,$field4,$field5,$field6)); 
571     }
572   
573     $display ="<h2>Sieve script management</h2>";
574     $display .= _("Be careful. All your changes will be saved directly to sieve, if you use the save button below.");
575     $display .= "<br><input type='submit' name='create_new_script' value='"._("Create new script")."'>";
576     $display .=  $List->DrawList();
577     
578     $display .= "<p style=\"text-align:right\">\n";
579     $display .= "<input type=submit name=\"sieve_finish\" style=\"width:80px\" value=\""._("Ok")."\">\n";
580     $display .= "&nbsp;\n";
581     $display .= "<input type=submit name=\"sieve_cancel\" value=\""._("Cancel")."\">\n";
582     $display .= "</p>";
583     return($display);;
584   }
586   function save_object()
587   {
588     if($this->current_handler){
590       /* Check if there is an add object requested 
591        */
592       $data = $this->current_handler->tree_->pap;
593       $once = TRUE;
594       foreach($_POST as $name => $value){
595         foreach($data as $key => $obj){
596           if(isset($obj->object_id) && preg_match("/^Add_Object_Top_".$obj->object_id."_/",$name) && $once){
597             $once = FALSE;
598             $this->add_new_element    = TRUE;
599             $this->add_new_id         = $obj->object_id;
600             $this->add_above_below    = "above";
601           }
602           if(isset($obj->object_id) && preg_match("/^Add_Object_Bottom_".$obj->object_id."_/",$name) && $once){
603             $once = FALSE;
604             $this->add_new_element    = TRUE;
605             $this->add_new_id         = $obj->object_id;
606             $this->add_above_below    = "below";
607           }
608         
609           if(isset($obj->object_id) && preg_match("/^Remove_Object_".$obj->object_id."_/",$name) && $once){
610             $once = FALSE;
611             $this->current_handler->tree_->remove_object($key);
612           }
613           if(isset($obj->object_id) && preg_match("/^Move_Up_Object_".$obj->object_id."_/",$name) && $once){
614             $this->current_handler->tree_->move_up_down($key,"up");
615             $once = FALSE;
616           }
617           if(isset($obj->object_id) && preg_match("/^Move_Down_Object_".$obj->object_id."_/",$name) && $once){
618             $this->current_handler->tree_->move_up_down($key,"down");
619             $once = FALSE;
620           }
621         }
622       }
623       
624       /* Skip Mode changes and Parse tests 
625        *  if we are currently in a subdialog 
626        */
627       if(!$this->add_new_element) {
629         $Mode = $this->scripts[$this->current_script]['MODE'];
630         $skip_mode_change = false;
631         if(in_array($Mode,array("Source-Only","Source"))){
632           if(isset($_POST['script_contents'])){
633             $sc = stripslashes($_POST['script_contents']);
634             $this->scripts[$this->current_script]['SCRIPT'] = $sc;
635             $p = new My_Parser;
636             if($p -> parse($sc)){
637               $this->current_handler = $p;
638               $this->Script_Error = "";
639             } else {
640               $this->Script_Error = $p->status_text;
641               $skip_mode_change = TRUE;
642             }
643           }
644         }
645         if(in_array($Mode,array("Structured"))){
646           $this->current_handler->save_object();
647           $sc = $this->current_handler->get_sieve_script();
648           $this->scripts[$this->current_script]['SCRIPT'] = $sc;
649           $p = new My_Parser;
650           if($p -> parse($sc)){
651             $this->current_handler = $p;
652             $this->Script_Error = "";
653           } else {
654             $this->Script_Error = $p->status_text;
655             $skip_mode_change = TRUE;
656           }
657         }
658         if(!$skip_mode_change){
659           if($this->scripts[$this->current_script]['MODE'] != "Source-Only"){
660             if(isset($_POST['View_Source'])){
661               $this->scripts[$this->current_script]['MODE'] = "Source";
662             }
663             if(isset($_POST['View_Structured'])){
664               $this->scripts[$this->current_script]['MODE'] = "Structured";
665             }
666           }
667         }
668       }
669       $this->current_handler->save_object();
670     }
671   }
674   function save()
675   {
676     /* Connect to sieve class and try to get all available sieve scripts */
677     $cfg=  $this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer];
679     $this->sieve_handle= 
680         new sieve(  $cfg["sieve_server"], 
681                     $cfg["sieve_port"], 
682                     $this->parent->mail,
683                     $cfg["password"], 
684                     $cfg["admin"]);
686     if (!$this->sieve_handle->sieve_login()){
687       print_red(sprintf(_("Can't log into SIEVE server. Server says '%s'."),to_string($this->sieve_handle->error_raw)));
688       return;
689     }
691     $everything_went_fine = TRUE;
693     foreach($this->scripts as $key => $script){
694       if($script['EDITED']){
695         $data = $this->scripts[$key]['SCRIPT'];
696         if(!$this->sieve_handle->sieve_sendscript($script['NAME'], $data)){
697           gosa_log("Failed to save sieve script named '".$script['NAME']."': ".to_string($this->sieve_handle->error_raw));
698           $everything_went_fine = FALSE;
699           print_red(to_string($this->sieve_handle->error_raw));
700           $this->scripts[$key]['MSG'] = "<font color='red'>".
701                                            _("Failed to save sieve script").": ".
702                                            to_string($this->sieve_handle->error_raw).
703                                            "</font>";
704         }
705       }
706     }
707     return($everything_went_fine);
708   }
710 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
711 ?>