1 <?php
5 /* This class is inherited from the original 'Tree'
6 * class written by Heiko Hund.
7 * It is partly rewritten to create a useable html interface
8 * for each single sieve token.
9 * This gives us the ability to edit existing sieve filters.
10 */
11 class My_Tree extends Tree
12 {
13 var $dumpFn_;
14 var $dump_;
16 var $mode_stack = array();
17 var $pap = array();
20 /* Create a html interface for the current sieve filter
21 */
22 function dump()
23 {
24 error_reporting(E_ALL);
26 /* Only parse the tokens once */
27 if(!count($this->pap)){
28 $this->dump_ = "";
29 $this->mode_stack = array();
30 $this->pap = array();
31 $this->doDump_(0, '', true);
32 }
34 /* Create html results */
35 $this->dump_ ="<table width='100%'><tr><td style='background-color:#BBBBBB;border: 0px;padding-left:20px;'>";
36 foreach($this->pap as $key => $object){
37 if(is_object($object)){
38 $this->dump_ .= preg_replace("/>/",">\n",$object->execute());
39 }
40 }
41 $this->dump_ .= "</td></tr></table>";
42 return $this->dump_;
43 }
46 /* This function walks through the object tree generated by the "Parse" class.
47 * All Commands will be resolved and grouped. So the Commands and their
48 * parameter are combined. Like "IF" and ":comparator"...
49 */
50 function doDump_($node_id, $prefix, $last,$num = 1)
51 {
52 /* Indicates that current comman will only be valid for a single line.
53 * this command type will be removed from mode_stack after displaying it.
54 */
55 $rewoke_last = FALSE;
57 /* Get node */
58 $node = $this->nodes_[$node_id];
60 /* This closes the last mode */
61 if($node['class'] == "block-start"){
62 $tmp = array_pop($this->mode_stack);
63 $this->handle_elements($tmp,$node_id);
64 $this->handle_elements(array("TYPE" => "block_start"),$node_id);
65 }
67 /* This closes the last mode */
68 if($node['class'] == "block-end"){
69 $tmp = array_pop($this->mode_stack);
70 $this->handle_elements($tmp,$node_id);
71 $this->handle_elements(array("TYPE" => "block_end"),$node_id);
72 }
74 /* Semicolon indicates a new command */
75 if($node['class'] == "semicolon"){
76 $tmp =array_pop($this->mode_stack);
77 $this->handle_elements($tmp,$node_id);
78 }
80 /* Handle comments */
81 if($node['class'] == "comment"){
82 $this->mode_stack[] = array("TYPE" => $node['class']);
83 $rewoke_last = TRUE;
84 }
86 /* Handle identifiers */
87 $identifiers = array("else","if","elsif","end","reject","redirect","vacation","keep","discard","comment","fileinto","require","stop");
88 if($node['class'] == "identifier" && in_array($node['text'],$identifiers)){
89 $this->mode_stack[] = array("TYPE" => $node['text']);
90 }
92 /* Add current node to current command stack */
93 end($this->mode_stack);
94 $key = key($this->mode_stack);
95 $this->mode_stack[$key]['ELEMENTS'][] = $node;
97 /* Remove last mode from mode stack, cause it was only valid for a single line */
98 if($rewoke_last){
99 $tmp =array_pop($this->mode_stack);
100 $this->handle_elements($tmp,$node_id);
101 }
103 /* If this is a sub element, just call this for all childs */
104 if(isset($this->childs_[$node_id])){
105 $childs = $this->childs_[$node_id];
106 for ($i=0; $i<count($childs); ++$i)
107 {
108 $c_last = false;
109 if ($i+1 == count($childs))
110 {
111 $c_last = true;
112 }
113 $this->doDump_($childs[$i], "", $num);
114 }
115 }
116 }
119 /* Create a class for each resolved object.
120 * And append this class to a list of objects.
121 */
122 function handle_elements($data,$id)
123 {
124 if(!isset($data['TYPE'])){
125 return;
126 }
127 $type = $data['TYPE'];
129 $class_name= "sieve_".$type ;
130 if(class_exists($class_name)){
131 $this->pap[] = new $class_name($data,$id);
132 }else{
133 echo "<font color='red'>Missing : ".$class_name."</font>"."<br>";
134 }
135 }
137 function save_object()
138 {
139 foreach($this->pap as $key => $obj){
141 if(in_array(get_class($obj),array("sieve_if","sieve_elsif","sieve_vacation","sieve_comment","sieve_reject","sieve_fileinto","sieve_require","sieve_redirect"))){
142 $this->pap[$key]->save_object();
143 }
144 }
145 }
147 /* Need to be reviewed */
148 function get_sieve_script()
149 {
150 $tmp ="";
151 if(count($this->pap)){
152 $buffer = "";
153 foreach($this->pap as $part) {
154 if(get_class($part) == "sieve_block_end"){
155 $buffer = substr($buffer,0,strlen($buffer)-(strlen(SIEVE_INDENT_TAB)));
156 }
157 $tmp2 = $part->get_sieve_script_part();
159 if(get_class($part) == "sieve_reject"){
160 $tmp.=$tmp2;
161 }else{
163 $tmp3 = split("\n",$tmp2);
164 foreach($tmp3 as $str){
165 $str2 = trim($str);
166 if(empty($str2)) continue;
167 $tmp.= $buffer.$str."\n";
168 }
169 }
170 if(get_class($part) == "sieve_block_start"){
171 $buffer .= SIEVE_INDENT_TAB;
172 }
173 }
174 }
175 if(!preg_match("/Generated by GOsa - Gonicus System Administrator/",$tmp)){
176 $tmp = "#Generated by GOsa - Gonicus System Administrator \n ".$tmp;
177 }
178 return($tmp);
179 }
180 }
183 /* Create valid sieve string/string-list
184 * out of a given array
185 */
186 function sieve_create_strings($data)
187 {
188 $ret = "";
189 if(is_array($data)){
190 if(count($data) == 1){
191 $ret = "\"";
192 foreach($data as $dat){
193 $ret .=$dat;
194 }
195 $ret.="\"";
196 }else{
197 foreach($data as $dat){
198 $ret.= "\"";
199 $ret.=$dat;
200 $ret.="\", ";
201 }
202 $ret = preg_replace("/,$/","",trim($ret));
203 $ret = "[".$ret."]";
204 }
205 }else{
207 $Multiline = preg_match("/\n/",$data);
208 $data = preg_replace("/\r/","",$data);;
210 if($Multiline){
211 $ret = "text: \r\n".$data."\r\n.\r\n";
212 }else{
213 $ret = "\"".$data."\"";
214 }
215 }
216 $ret = preg_replace("/\"\"/","\"",$ret);
217 $ret = preg_replace("/\n/","\r\n",$ret);
219 return($ret);
220 }
222 /* This checks if there is a string at the current position
223 * in the token array.
224 * If there is a string list at the current position,
225 * this function will return a complete list of all
226 * strings used in this list.
227 * It also returns an offset of the last token position
228 */
229 function sieve_get_strings($data,$id)
230 {
231 $ret = array();
232 if($data[$id]['class'] == "left-bracket"){
233 while($data[$id]['class'] != "right-bracket" && $id < count($data)){
235 if($data[$id]['class'] == "quoted-string"){
236 $ret[] = $data[$id]['text'];
237 }
238 $id ++;
239 }
240 }elseif($data[$id]['class'] == "quoted-string"){
241 $ret[] = $data[$id]['text'];
242 }elseif($data[$id]['class'] == "number"){
243 $ret[] = $data[$id]['text'];
244 }
245 return(array("OFFSET" => $id, "STRINGS" => $ret));
246 }
248 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
249 ?>