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 /* Initialize the class and load all sieve scripts
55 * try to parse them and display errors
56 */
57 function sieveManagement($config,$dn,$parent)
58 {
59 $this->parent = $parent;
60 plugin::plugin($config,$dn);
62 /* Get sieve */
63 if(!$sieve = $this->get_sieve()){
64 print_red(
65 sprintf(
66 _("Can't log into SIEVE server. Server says '%s'."),
67 to_string($this->Sieve_Error)));
68 return;
69 }
72 /* Get all sieve scripts names */
73 if($sieve->sieve_listscripts()){
74 if (is_array($sieve->response)){
75 foreach($sieve->response as $key => $name){
77 $data = array();
78 $data['NAME'] = $name;
80 if($key == "ACTIVE" && $key === "ACTIVE"){
81 $data['ACTIVE'] = TRUE;
82 }else{
83 $data['ACTIVE'] = FALSE;
84 }
85 $this->scripts[] = $data;
86 }
87 }
88 }
90 /* Get script contents */
91 foreach($this->scripts as $key => $script){
92 $p = new My_Parser;
93 $sieve->sieve_getscript($script['NAME']);
95 $script = "";
96 foreach($sieve->response as $line){
97 $script.=$line;
98 }
100 $this->scripts[$key]['IS_NEW'] = FALSE;;
101 $this->scripts[$key]['SCRIPT'] = $script;
102 $this->scripts[$key]['ORIG_SCRIPT'] = $script;
103 $this->scripts[$key]['MSG'] = "";
104 $ret = $p->parse($script);
105 if(!$ret){
106 $this->scripts[$key]['STATUS'] = FALSE;
107 $this->scripts[$key]['MODE'] = "Source-Only";
108 $this->scripts[$key]['MSG'] = _("Parse failed")."<font color='red'>".$p->status_text."</font>";
109 }else{
110 $this->scripts[$key]['STATUS'] = TRUE;
111 $this->scripts[$key]['MODE'] = "Structured";
112 $this->scripts[$key]['MSG'] = _("Parse successful");
113 }
114 $this->scripts[$key]['PARSER'] = $p;
115 $this->scripts[$key]['EDITED'] = FALSE;
116 }
117 $this->sieve_handle = $sieve;
118 }
121 /* Return a sieve class hanlde,
122 * false if login fails
123 */
124 function get_sieve()
125 {
126 /* Connect to sieve class and try to get all available sieve scripts */
127 $cfg= $this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer];
128 $this->Sieve_Error = "";
130 /* Log into the mail server */
131 $sieve= new sieve(
132 $cfg["sieve_server"],
133 $cfg["sieve_port"],
134 $this->parent->uid,
135 $cfg["password"],
136 $cfg["admin"]);
138 /* Try to login */
139 if (!$sieve->sieve_login()){
140 $this->Sieve_Error = $sieve->error_raw;
141 return(FALSE);
142 }
143 return($sieve);
144 }
147 /* Handle sieve list
148 */
149 function execute()
150 {
151 /***************
152 * Create a new Script
153 ***************/
155 /* Force opening the add script dialog */
156 if(isset($_POST['create_new_script'])){
157 $this->create_script = TRUE;
158 }
160 /* Close add script dialog, without adding a new one */
161 if(isset($_POST['create_script_cancel'])){
162 $this->create_script = FALSE;
163 }
165 /* Display create script dialog
166 * handle posts, display warnings if specified
167 * name is not useable.
168 * Create a new script with given name
169 */
170 if($this->create_script){
172 /* Set initial name or used posted name if available */
173 $name = "";
174 if(isset($_POST['NewScriptName'])){
175 $name = trim($_POST['NewScriptName']);
176 }
178 /* Check given name */
179 $err = "";
181 /* Is given name in lower case characters ? */
182 if(isset($_POST['create_script_save'])){
183 if(!strlen($name)){
184 $err = _("You should specify a name for your new script.");
185 }
186 /* Is given name in lower case characters ? */
187 if($name != strtolower($name)){
188 $err = _("Only lower case names are allowed here.");
189 }
191 /* Only chars are allowed here */
192 if(preg_match("/[^a-z]/i",$name)){
193 $err = _("Only a-z are allowed in script names.");
194 }
195 }
197 /* Create script if everything is ok */
198 if($this->create_script && isset($_POST['create_script_save']) && $err == "" ){
200 /* Close dialog */
201 $this->create_script = FALSE;
203 /* Script contents to use */
204 $script = "/*New script */".
205 "stop;";
207 /* Create a new parser and initialize default values */
208 $p = new My_Parser;
209 $ret = $p->parse($script);
210 $sc['SCRIPT'] = $script;
211 $sc['ORIG_SCRIPT'] = $script;
212 $sc['IS_NEW'] = TRUE;
213 $sc['MSG'] = "";
214 if(!$ret){
215 $sc['STATUS'] = FALSE;
216 $sc['MODE'] = "Source-Only";
217 $sc['MSG'] = _("Parse failed")."<font color='red'>".$p->status_text."</font>";
218 }else{
219 $sc['STATUS'] = TRUE;
220 $sc['MODE'] = "Strucktured";
221 $sc['MSG'] = _("Parse successful");
222 }
223 $sc['PARSER'] = $p;
224 $sc['EDITED'] = TRUE;
225 $sc['ACTIVE'] = FALSE;
226 $sc['NAME'] = $name;
228 /* Add script */
229 $this->scripts[$name] = $sc;
230 }else{
232 /* Display dialog to enter new script name */
233 $smarty = get_smarty();
234 $smarty->assign("NewScriptName",$name);
235 $smarty->assign("Error",$err);
236 return($smarty->fetch(get_template_path("templates/create_script.tpl",TRUE,dirname(__FILE__))));
237 }
238 }
241 /*************
242 * Handle several posts
243 *************/
245 $once = TRUE;
246 foreach($_POST as $name => $value){
248 /* Edit script requested */
249 if(preg_match("/^editscript_/",$name) && $once && !$this->current_handler){
250 $script = preg_replace("/^editscript_/","",$name);
251 $script = preg_replace("/_(x|y)/","",$script);
252 $once = FALSE;
254 $this->current_script = $script;
255 $this->current_handler = $this->scripts[$script]['PARSER'];
256 }
258 /* remove script requested */
259 if(preg_match("/^delscript_/",$name) && $once && !$this->current_handler){
260 $script = preg_replace("/^delscript_/","",$name);
261 $script = preg_replace("/_(x|y)/","",$script);
262 $once = FALSE;
264 $this->script_to_delete = $script;
265 }
267 /* Activate script */
268 if(preg_match("/^active_script_/",$name) && $once && !$this->current_handler){
269 $script = preg_replace("/^active_script_/","",$name);
270 $script = preg_replace("/_(x|y)/","",$script);
271 $once = FALSE;
273 /* Get sieve */
274 if(!$sieve = $this->get_sieve()){
275 print_red(
276 sprintf(
277 _("Can't log into SIEVE server. Server says '%s'."),
278 to_string($this->Sieve_Error)));
279 }
281 /* Try to activate the given script and update
282 * class script array.
283 */
284 if(!$this->sieve_handle->sieve_setactivescript($this->scripts[$script]['NAME'])){
285 print_red(sprintf(_("Can't activate sieve script on server. Server says '%s'."),to_string($this->sieve_handle->error_raw)));
286 }else{
287 foreach($this->scripts as $key => $data){
288 if($key == $script){
289 $this->scripts[$key]['ACTIVE'] = TRUE;
290 }else{
291 $this->scripts[$key]['ACTIVE'] = FALSE;
292 }
293 }
294 }
295 }
296 }
299 /*************
300 * Remove script handling
301 *************/
303 /* Remove aborted */
304 if(isset($_POST['delete_cancel'])){
305 $this->script_to_delete = -1;
306 }
308 /* Remove confirmed */
309 if(isset($_POST['delete_script_confirm'])){
311 $script = $this->scripts[$this->script_to_delete];
313 /* Just remove from array if it is a new script */
314 if($script['IS_NEW']){
315 unset($this->scripts[$this->script_to_delete]);
316 }else{
318 /* Get sieve */
319 if(!$sieve = $this->get_sieve()){
320 print_red(
321 sprintf(
322 _("Can't log into SIEVE server. Server says '%s'."),
323 to_string($this->Sieve_Error)));
324 }
326 if(!$this->sieve_handle->sieve_deletescript($this->scripts[$this->script_to_delete]['NAME'])){
327 print_red(sprintf(_("Can't remove sieve script from server. Server says '%s'."),to_string($this->sieve_handle->error_raw)));
328 }else{
329 unset($this->scripts[$this->script_to_delete]);
330 }
331 }
332 $this->script_to_delete = -1;
333 }
335 /* Display confirm dialog */
336 if($this->script_to_delete != -1){
337 $smarty = get_smarty();
338 $smarty->assign("Warning",
339 sprintf(_("You are going to remove the sieve script '%s' from your mail server."),
340 $this->scripts[$this->script_to_delete]['NAME']));
341 return($smarty->fetch(get_template_path("templates/remove_script.tpl",TRUE,dirname(__FILE__))));
342 }
345 /**************
346 * Save script changes
347 **************/
349 /* Abort saving */
350 if(isset($_POST['cancel_sieve_changes'])){
351 $this->current_handler = NULL;
352 }
354 /* Save currently edited sieve script. */
355 if(isset($_POST['save_sieve_changes'])){
356 $chk = $this->current_handler->check();
357 if(!count($chk)){
359 $sc = $this->scripts[$this->current_script]['SCRIPT'];
360 $p = new My_Parser;
361 if($p -> parse($sc)){
363 if($this->scripts[$this->current_script]['MODE'] == "Source-Only"){
364 $this->scripts[$this->current_script]['MODE'] = "Source";
365 }
367 $this->scripts[$this->current_script]['PARSER'] = $p;
368 $this->scripts[$this->current_script]['EDITED'] = TRUE;
369 $this->scripts[$this->current_script]['STATUS'] = TRUE;
370 $this->scripts[$this->current_script]['MSG'] = _("Edited");
371 $this->current_handler = NULL;
372 }else{
373 print_red($p->status_text);;
374 }
375 }else{
376 print_red(_("Please fix all errors before saving."));
377 }
378 }
381 /*************
382 * Display edit dialog
383 *************/
385 /* Display edit dialog, depending on Mode display different uis
386 */
387 if($this->current_handler){
389 /* Create dump of current sieve script */
390 if(isset($_POST['Save_Copy'])){
392 /* force download dialog */
393 header("Content-type: application/tiff\n");
394 if (preg_match('/MSIE 5.5/', $HTTP_USER_AGENT) ||
395 preg_match('/MSIE 6.0/', $HTTP_USER_AGENT)) {
396 header('Content-Disposition: filename="dump.script"');
397 } else {
398 header('Content-Disposition: attachment; filename="dump.script"');
399 }
400 header("Content-transfer-encoding: binary\n");
401 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
402 header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
403 header("Cache-Control: no-cache");
404 header("Pragma: no-cache");
405 header("Cache-Control: post-check=0, pre-check=0");
406 echo $this->scripts[$this->current_script]['SCRIPT'];
407 exit();
408 }
411 /****
412 * Add new element to ui
413 ****/
415 /* Abort add dialog */
416 if(isset($_POST['select_new_element_type_cancel'])){
417 $this->add_new_element = FALSE;
418 }
420 /* Add a new element */
421 if($this->add_new_element){
423 $element_types= array(
424 "sieve_keep" => _("Keep"),
425 "sieve_comment" => _("Comment"),
426 "sieve_fileinto" => _("File into"),
427 "sieve_keep" => _("Keep"),
428 "sieve_discard" => _("Discard"),
429 "sieve_redirect" => _("Redirect"),
430 "sieve_reject" => _("Reject"),
431 "sieve_require" => _("Require"),
432 "sieve_stop" => _("Stop"),
433 "sieve_vacation" => _("Vacation message"),
434 "sieve_if" => _("If"));
437 /* Element selected */
438 if(isset($_POST['element_type']) && isset($element_types[$_POST['element_type']])){
439 $this->add_element_type = $_POST['element_type'];
440 }
442 /* Create new element and add it to
443 * the selected position
444 */
445 if(isset($_POST['select_new_element_type'])){
447 $this->add_new_id;
449 $data = $this->current_handler->tree_->pap;
451 /* Get index of the element identified by object_id == $this->add_new_id; */
452 $index = -1;
453 foreach($data as $key => $obj){
454 if($obj->object_id == $this->add_new_id && $index==-1){
455 $index = $key;
456 }
457 }
459 /* We have found the specified object_id
460 * and want to detect the next free position
461 * to insert the new element.
462 */
463 if($index != -1){
464 if($this->add_above_below == "above"){
465 $direction ="up";
466 $next_free = $this->current_handler->tree_->_get_next_free_move_slot($index,$direction);
467 $next_free ++;
468 }else{
469 $next_free = $this->current_handler->tree_->_get_next_free_move_slot($index,$direction);
470 $direction = "down";
471 }
472 $this->add_new_id = $this->current_handler->tree_->pap[$next_free]->object_id;
473 }
475 /* Create elements we should add */
476 $ele[] = new $this->add_element_type(NULL, preg_replace("/[^0-9]/","",microtime()));
477 if($this->add_element_type == "sieve_if"){
478 $ele[] = new sieve_block_start(NULL,preg_replace("/[^0-9]/","",microtime()));
479 $ele[] = new sieve_block_end(NULL,preg_replace("/[^0-9]/","",microtime()));
480 }
481 $start = $end = array();
482 $found = false;
484 /* Add above current element*/
485 if($this->add_above_below == "above"){
486 foreach($data as $key => $obj){
487 if($obj->object_id == $this->add_new_id){
488 $found = true;
489 }
490 if(!$found){
491 $start[] = $obj;
492 }else{
493 $end[] = $obj;
494 }
495 }
496 }else{
497 /* Add below current element */
498 foreach($data as $key => $obj){
499 if(!$found){
500 $start[] = $obj;
501 }else{
502 $end[] = $obj;
503 }
504 if($obj->object_id == $this->add_new_id){
505 $found = true;
506 }
507 }
508 }
510 /* Only add, if current element could be located */
511 if($found){
512 $new = array();
513 foreach($start as $obj){
514 $new[] = $obj;
515 }
516 foreach($ele as $el){
517 $new[] = $el;
518 }
519 foreach($end as $obj){
520 $new[] = $obj;
521 }
522 $data= $new;
523 $this->current_handler->tree_->pap = $data;
524 $this->add_new_element = FALSE;
525 }else{
526 print_red(_("Something went wrong while adding a new entry."));
527 }
528 }
529 }
531 /* Only display select dialog if it is necessary */
532 if($this->add_new_element){
533 $smarty = get_smarty();
534 $smarty->assign("element_types",$element_types );
535 $smarty->assign("element_type",$this->add_element_type);
536 $str = $smarty->fetch(get_template_path("templates/add_element.tpl",TRUE,dirname(__FILE__)));
537 return($str);
538 }
542 /****************
543 * Handle test posts
544 ****************/
546 /* handle some special posts from test elements
547 */
548 foreach($_POST as $name => $value){
549 if(preg_match("/^Add_Test_Object_/",$name)) {
550 $name = preg_replace("/^Add_Test_Object_/","",$name);
551 $name = preg_replace("/_(x|y)$/","",$name);
553 $test_types_to_add = array(
554 "address" =>_("Address"),
555 "header" =>_("Header"),
556 "envelope"=>_("Envelope"),
557 "size" =>_("Size"),
558 "exists" =>_("Exists"),
559 "allof" =>_("All of"),
560 "anyof" =>_("Any of"),
561 "true" =>_("True"),
562 "false" =>_("False"));
564 $smarty = get_smarty();
565 $smarty->assign("ID",$name);
566 $smarty->assign("test_types_to_add",$test_types_to_add);
567 $ret = $smarty->fetch(get_template_path("templates/select_test_type.tpl",TRUE,dirname(__FILE__)));
568 return($ret);
569 }
570 }
572 $current = $this->scripts[$this->current_script];
574 /* Create html results */
575 $smarty = get_smarty();
576 $smarty->assign("Mode",$current['MODE']);
577 if($current['MODE'] == "Structured"){
578 $smarty->assign("Contents",$this->current_handler->tree_->execute());
579 }else{
580 $smarty->assign("Contents",$current['SCRIPT']);
581 }
582 $smarty->assign("Script_Error",$this->Script_Error);
583 $ret = $smarty->fetch(get_template_path("templates/edit_frame_base.tpl",TRUE,dirname(__FILE__)));
584 return($ret);
585 }
588 /* Create list of available sieve scripts
589 */
590 $List = new divSelectBox("sieveManagement");
591 foreach($this->scripts as $key => $script){
593 $edited = $script['EDITED'];
594 $active = $script['ACTIVE'];
596 $field1 = array("string" => " ",
597 "attach" => "style='width:20px;'");
598 if($active){
599 $field1 = array("string" => "<img src='images/true.png' alt='"._("Active")."'>",
600 "attach" => "style='width:20px;'");
601 }
602 $field2 = array("string" => $script['NAME']);
603 $field3 = array("string" => $script['MSG']);
604 $field4 = array("string" => _("Script length")." : ".strlen($script['SCRIPT']));
606 if($edited){
607 $field5 = array("string" => "<img src='images/fai_new_hook.png' alt='"._("Edited")."'>",
608 "attach" => "style='width:30px;'");
609 }else{
610 $field5 = array("string" => "",
611 "attach" => "style='width:30px;'");
612 }
614 if($active){
615 $field6 = array("string" => "<img src='images/empty.png' alt=' '>".
616 "<input type='image' name='editscript_".$key."' src='images/edit.png'>".
617 "<input type='image' name='delscript_".$key."' src='images/edittrash.png'>");
618 }else{
619 $field6 = array("string" => "<input type='image' name='active_script_".$key."' src='images/true.png'>".
620 "<input type='image' name='editscript_".$key."' src='images/edit.png'>".
621 "<input type='image' name='delscript_".$key."' src='images/edittrash.png'>");
622 }
623 $List ->AddEntry(array($field1,$field2,$field3,$field4,$field5,$field6));
624 }
626 $display ="<h2>Sieve script management</h2>";
627 $display .= _("Be careful. All your changes will be saved directly to sieve, if you use the save button below.");
628 $display .= "<br><input type='submit' name='create_new_script' value='"._("Create new script")."'>";
629 $display .= $List->DrawList();
631 $display .= "<p style=\"text-align:right\">\n";
632 $display .= "<input type=submit name=\"sieve_finish\" style=\"width:80px\" value=\""._("Ok")."\">\n";
633 $display .= " \n";
634 $display .= "<input type=submit name=\"sieve_cancel\" value=\""._("Cancel")."\">\n";
635 $display .= "</p>";
636 return($display);;
637 }
639 function save_object()
640 {
641 if($this->current_handler){
643 /* Check if there is an add object requested
644 */
645 $data = $this->current_handler->tree_->pap;
646 $once = TRUE;
647 foreach($_POST as $name => $value){
648 foreach($data as $key => $obj){
649 if(isset($obj->object_id) && preg_match("/^Add_Object_Top_".$obj->object_id."_/",$name) && $once){
650 $once = FALSE;
651 $this->add_new_element = TRUE;
652 $this->add_new_id = $obj->object_id;
653 $this->add_above_below = "above";
654 }
655 if(isset($obj->object_id) && preg_match("/^Add_Object_Bottom_".$obj->object_id."_/",$name) && $once){
656 $once = FALSE;
657 $this->add_new_element = TRUE;
658 $this->add_new_id = $obj->object_id;
659 $this->add_above_below = "below";
660 }
662 if(isset($obj->object_id) && preg_match("/^Remove_Object_".$obj->object_id."_/",$name) && $once){
663 $once = FALSE;
664 $this->current_handler->tree_->remove_object($key);
665 }
666 if(isset($obj->object_id) && preg_match("/^Move_Up_Object_".$obj->object_id."_/",$name) && $once){
667 $this->current_handler->tree_->move_up_down($key,"up");
668 $once = FALSE;
669 }
670 if(isset($obj->object_id) && preg_match("/^Move_Down_Object_".$obj->object_id."_/",$name) && $once){
671 $this->current_handler->tree_->move_up_down($key,"down");
672 $once = FALSE;
673 }
674 }
675 }
677 /* Skip Mode changes and Parse tests
678 * if we are currently in a subdialog
679 */
680 if(!$this->add_new_element) {
682 $Mode = $this->scripts[$this->current_script]['MODE'];
683 $skip_mode_change = false;
684 if(in_array($Mode,array("Source-Only","Source"))){
685 if(isset($_POST['script_contents'])){
686 $sc = stripslashes($_POST['script_contents']);
687 $this->scripts[$this->current_script]['SCRIPT'] = $sc;
688 $p = new My_Parser;
689 if($p -> parse($sc)){
690 $this->current_handler = $p;
691 $this->Script_Error = "";
692 } else {
693 $this->Script_Error = $p->status_text;
694 $skip_mode_change = TRUE;
695 }
696 }
697 }
698 if(in_array($Mode,array("Structured"))){
699 $this->current_handler->save_object();
700 $sc = $this->current_handler->get_sieve_script();
701 $this->scripts[$this->current_script]['SCRIPT'] = $sc;
702 $p = new My_Parser;
703 if($p -> parse($sc)){
704 $this->current_handler = $p;
705 $this->Script_Error = "";
706 } else {
707 $this->Script_Error = $p->status_text;
708 $skip_mode_change = TRUE;
709 }
710 }
711 if(!$skip_mode_change){
712 if($this->scripts[$this->current_script]['MODE'] != "Source-Only"){
713 if(isset($_POST['View_Source'])){
714 $this->scripts[$this->current_script]['MODE'] = "Source";
715 }
716 if(isset($_POST['View_Structured'])){
717 $this->scripts[$this->current_script]['MODE'] = "Structured";
718 }
719 }
720 }
721 }
722 $this->current_handler->save_object();
723 }
724 }
727 function save()
728 {
729 /* Connect to sieve class and try to get all available sieve scripts */
730 $cfg= $this->config->data['SERVERS']['IMAP'][$this->parent->gosaMailServer];
732 $this->sieve_handle=
733 new sieve( $cfg["sieve_server"],
734 $cfg["sieve_port"],
735 $this->parent->mail,
736 $cfg["password"],
737 $cfg["admin"]);
739 if (!$this->sieve_handle->sieve_login()){
740 print_red(sprintf(_("Can't log into SIEVE server. Server says '%s'."),to_string($this->sieve_handle->error_raw)));
741 return;
742 }
744 $everything_went_fine = TRUE;
746 foreach($this->scripts as $key => $script){
747 if($script['EDITED']){
748 $data = $this->scripts[$key]['SCRIPT'];
749 if(!$this->sieve_handle->sieve_sendscript($script['NAME'], $data)){
750 gosa_log("Failed to save sieve script named '".$script['NAME']."': ".to_string($this->sieve_handle->error_raw));
751 $everything_went_fine = FALSE;
752 print_red(to_string($this->sieve_handle->error_raw));
753 $this->scripts[$key]['MSG'] = "<font color='red'>".
754 _("Failed to save sieve script").": ".
755 to_string($this->sieve_handle->error_raw).
756 "</font>";
757 }
758 }
759 }
760 return($everything_went_fine);
761 }
762 }
763 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
764 ?>