comparison plugins/filters/filters.php @ 0:1e000243b222

vanilla 1.3.3 distro, I hope
author Charlie Root
date Thu, 04 Jan 2018 15:50:29 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e000243b222
1 <?php
2
3 /**
4 * Filters
5 *
6 * Plugin that adds a new tab to the settings section to create client-side e-mail filtering.
7 *
8 * @version 2.1.6
9 * @author Roberto Zarrelli <zarrelli@unimol.it>
10 * @developer Artur Petrov <admin@gtn18.ru>
11 */
12
13 class filters extends rcube_plugin{
14
15 public $task = 'login|mail|settings';
16
17 private $autoAddSpamFilterRule;
18 private $spam_subject;
19 private $caseInsensitiveSearch;
20 private $decodeBase64Msg;
21 private $searchstring = array();
22 private $destfolder = array();
23 private $msg_uids = array();
24 private $open_mbox;
25
26
27 function init(){
28
29 /* Filters parameters initialization. See readme.txt */
30 $this->load_config();
31 /* ***************************************************** */
32
33 $rcmail = rcmail::get_instance();
34 $this->rc = &$rcmail;
35
36 $this->autoAddSpamFilterRule = $this->rc->config->get('autoAddSpamFilterRule',TRUE);
37 $this->spam_subject = $this->rc->config->get('spam_subject','[SPAM]');
38 $this->caseInsensitiveSearch = $this->rc->config->get('caseInsensitiveSearch',TRUE);
39 $this->decodeBase64Msg = $this->rc->config->get('decodeBase64Msg',FALSE);
40
41 if($this->rc->task == 'mail' && !isset($_GET["_q"]))
42 $this->add_hook('messages_list', array($this, 'filters_checkmsg'));
43 else if ($this->rc->task == 'settings'){
44 $this->register_action('plugin.filters', array($this, 'filters_init'));
45 $this->register_action('plugin.filters-save', array($this, 'filters_save'));
46 $this->register_action('plugin.filters-delete', array($this, 'filters_delete'));
47 $this->add_texts('localization/', array('filters','nosearchstring'));
48 $this->rc->output->add_label('filters');
49 $this->include_script('filters.js');
50 }
51 else if ($this->rc->task == 'login'){
52 if ($this->autoAddSpamFilterRule)
53 $this->add_hook('login_after', array($this, 'filters_addMoveSpamRule'));
54 }
55
56 }
57
58 function filters_checkmsg($mlist){
59 $user = $this->rc->user;
60 if (method_exists($this->rc->imap,'get_mailbox_name')) {
61 $imap = $this->rc->imap;
62 $open_mbox = $imap->get_mailbox_name();
63 }
64 else {
65 $imap = $this->rc->storage;
66 $open_mbox = $imap->get_folder();
67 }
68
69 $this->open_mbox=$open_mbox;
70
71 // does not consider the messages already in the trash
72 if ($open_mbox == $this->rc->config->get('trash_mbox'))
73 return;
74
75 //load filters
76 $arr_prefs = $this->rc->config->get('filters', array());
77
78 foreach ($arr_prefs as $key => $saved_filter){
79 // if saved destination folder exists and current folder is INBOX
80 if (method_exists($imap,'mailbox_exists')){
81 if ($imap->mailbox_exists($saved_filter['destfolder']) && 'INBOX'==$open_mbox){
82 $saved_filter['searchstring'] = html_entity_decode($saved_filter['searchstring']);
83 // if (!isset($saved_filter['filterpriority'])) $saved_filter['filterpriority'] = '';
84 // destfolder#messages#filterpriority#markread
85 $this->searchstring[ $saved_filter['whatfilter'] ][ $saved_filter['searchstring'] ] =
86 $saved_filter['destfolder']."#".$saved_filter['messages']."#".$saved_filter['filterpriority']."#".$saved_filter['markread'];
87 }
88 }
89 if (!method_exists($imap,'mailbox_exists')){
90 if ($imap->folder_exists($saved_filter['destfolder']) && 'INBOX'==$open_mbox){
91 $saved_filter['searchstring'] = html_entity_decode($saved_filter['searchstring']);
92 // if (!isset($saved_filter['filterpriority'])) $saved_filter['filterpriority'] = '';
93 // destfolder#messages#filterpriority#markread
94 $this->searchstring[ $saved_filter['whatfilter'] ][ $saved_filter['searchstring'] ] =
95 $saved_filter['destfolder']."#".$saved_filter['messages']."#".$saved_filter['filterpriority']."#".$saved_filter['markread'];
96 }
97 }
98 }
99 // if there aren't filters return
100 if(!count($arr_prefs) || !count($this->searchstring) || !isset($mlist['messages']) || !is_array($mlist['messages']))
101 return;
102
103 // scan the messages
104 foreach($mlist["messages"] as $message){
105 $this->filters_search($message);
106 }
107
108 // move the filtered messages
109 if (count($this->destfolder) > 0){
110 foreach ($this->destfolder as $dfolder){
111 $uids = array();
112 foreach ($this->msg_uids[$dfolder] as $muids){
113 $uids[] = $muids;
114 }
115 if (count($uids)){
116 $imap->move_message($uids, $dfolder, $open_mbox);
117 // refresh
118 $unseen = $this->rc->storage->count($dfolder, 'UNSEEN');
119 $this->api->output->command('set_unread_count',$dfolder, $unseen);
120 $this->api->output->command('list_mailbox');
121 $this->api->output->send();
122 }
123 }
124 }
125
126 }
127
128
129 function filters_init(){
130 $this->add_texts('localization/');
131 $this->register_handler('plugin.body', array($this, 'filters_form'));
132 $this->rc->output->set_pagetitle($this->gettext('filters'));
133 $this->rc->output->send('plugin');
134 }
135
136 function filters_save(){
137 $user = $this->rc->user;
138
139 $this->add_texts('localization/');
140 $this->register_handler('plugin.body', array($this, 'filters_form'));
141 $this->rc->output->set_pagetitle($this->gettext('filters'));
142
143 $searchstring = trim(rcube_utils::get_input_value('_searchstring', RCUBE_INPUT_POST, true));
144 $destfolder = trim(rcube_utils::get_input_value('_folders', RCUBE_INPUT_POST, true));
145 $whatfilter = trim(rcube_utils::get_input_value('_whatfilter', RCUBE_INPUT_POST, true));
146 $messages = trim(rcube_utils::get_input_value('_messages', RCUBE_INPUT_POST, true));
147 $filterpriority = trim(rcube_utils::get_input_value('_checkbox', RCUBE_INPUT_POST, true));
148 $markread = trim(rcube_utils::get_input_value('_markread', RCUBE_INPUT_POST, true));
149
150 if ($searchstring == "")
151 $this->rc->output->command('display_message', $this->gettext('nosearchstring'), 'error');
152 else{
153 $new_arr['whatfilter'] = $whatfilter;
154 $new_arr['searchstring'] = htmlspecialchars(addslashes($searchstring));
155 $new_arr['destfolder'] = addslashes($destfolder);
156 $new_arr['messages'] = $messages;
157 $new_arr['filterpriority'] = $filterpriority;
158 $new_arr['markread'] = $markread;
159 $arr_prefs = $user->get_prefs();
160 $arr_prefs['filters'][] = $new_arr;
161 if ($user->save_prefs($arr_prefs))
162 $this->rc->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation');
163 else
164 $this->rc->output->command('display_message', $this->gettext('unsuccessfullysaved'), 'error');
165 }
166 $this->rc->overwrite_action('plugin.filters');
167 $this->rc->output->send('plugin');
168 }
169
170 function filters_delete(){
171 $user = $this->rc->user;
172
173 $this->add_texts('localization/');
174 $this->register_handler('plugin.body', array($this, 'filters_form'));
175 $this->rc->output->set_pagetitle($this->gettext('filters'));
176
177 if (isset($_GET[filterid])){
178 $filter_id = $_GET[filterid];
179 $arr_prefs = $user->get_prefs();
180 $arr_prefs['filters'][$filter_id] = '';
181 $arr_prefs['filters'] = array_diff($arr_prefs['filters'], array(''));
182 if ($user->save_prefs($arr_prefs))
183 $this->rc->output->command('display_message', $this->gettext('successfullydeleted'), 'confirmation');
184 else
185 $this->rc->output->command('display_message', $this->gettext('unsuccessfullydeleted'), 'error');
186 }
187
188 if (function_exists('rcmail::get_instance()->overwrite_action'))
189 rcmail::get_instance()->overwrite_action('plugin.filters');
190 else $this->rc->overwrite_action('plugin.filters');
191
192 $this->rc->output->send('plugin');
193 }
194
195 function filters_form(){
196
197 if (method_exists($this->rc,'imap_connect')) $this->rc->imap_connect();
198 else $this->rc->storage_connect();
199
200 $table = new html_table(array('cols' => 2));
201 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('whatfilter').":", 'html'));
202
203 $select = new html_select(array('name' => '_whatfilter', 'id' => 'whatfilter'));
204 $select->add($this->gettext('from'), 'from');
205 $select->add($this->gettext('to'), 'to');
206 $select->add($this->gettext('cc'), 'cc');
207 $select->add($this->gettext('subject'), 'subject');
208 $table->add('', $select->show($this->gettext('from')));
209
210 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('searchstring').":"), 'html');
211 $inputfield = new html_inputfield(array('name' => '_searchstring', 'id' => 'searchstring'));
212 $table->add('', $inputfield->show(""));
213
214 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('moveto').":"));
215 if (function_exists('rcmail::get_instance()->folder_selector'))
216 $select = rcmail::get_instance()->folder_selector(array('name' => '_folders', 'id' => 'folders'));
217 else $select = $this->rc->folder_selector(array('name' => '_folders', 'id' => 'folders'));
218 $table->add('title', $select->show());
219
220 # new option: all, read and unread messages
221 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('messagecount').":"), 'html');
222 $select = new html_select(array('name' => '_messages', 'id' => 'messages'));
223 $select->add($this->gettext('all'), 'all');
224 $select->add($this->gettext('unread'), 'unread');
225 $select->add($this->gettext('isread'), 'isread');
226 $table->add('', $select->show($this->gettext('all')));
227
228 # new option: markread or markunread messages
229 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('markmessages').":"), 'html');
230 $select = new html_select(array('name' => '_markread', 'id' => 'markread'));
231 $select->add($this->gettext('none'), 'none');
232 $select->add($this->gettext('markunread'), 'markunread');
233 $select->add($this->gettext('markread'), 'markread');
234 $table->add('', $select->show($this->gettext('none')));
235
236 # new option: filter priority, "on" as enable and "" as disable
237 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('filterpriority').":"), 'html');
238 $checkbox = new html_checkbox(array('name' => '_checkbox', 'id' => 'checkbox'));
239 $table->add('', $checkbox->show("0"));
240
241 // load saved filters
242 $user = $this->rc->user;
243 $arr_prefs = $user->get_prefs();
244 $i = 1;
245 $flag=false;
246 $table2 = new html_table(array('cols' => 2));
247 foreach ($arr_prefs['filters'] as $key => $saved_filter){
248 $flag=true;
249 if (empty($saved_filter['markread'])) $saved_filter['markread'] = 'none';
250 $folder_id = $saved_filter['destfolder'];
251 if (function_exists('rcmail::get_instance()->localize_folderpath'))
252 $folder_name = rcmail::get_instance()->localize_folderpath($folder_id);
253 else $folder_name = $this->rc->localize_folderpath($folder_id);
254
255 $messages = $saved_filter['messages'];
256
257 $msg = $i." - ".$this->gettext('msg_if_field')." <b>".$this->gettext($saved_filter['whatfilter'])."</b> ".$this->gettext('msg_contains').
258 " <b>".stripslashes($saved_filter['searchstring'])."</b> ".
259 $this->gettext('msg_move_msg_in')." <b>".$folder_name."</b> ".
260 "(".$this->gettext('messagecount').": ".$this->gettext($saved_filter['messages']).
261 ", ".$this->gettext('mark').": ".$this->gettext($saved_filter['markread']).")";
262 if ( !empty($saved_filter['filterpriority']))
263 $msg = "<font color='green'>".$msg."</font>";
264
265 $table2->add('title',$msg);
266 $dlink = "<a href='./?_task=settings&_action=plugin.filters-delete&filterid=".$key."'>".$this->gettext('delete')."</a>";
267 $table2->add('title',$dlink);
268 $i++;
269 }
270
271 if (!$flag){
272 $table2->add('title',rcube_utils::rep_specialchars_output($this->gettext('msg_no_stored_filters'), 'html'));
273 }
274
275 $out = html::div(array('class' => 'box'),
276 html::div(array('id' => 'prefs-title', 'class' => 'boxtitle'), $this->gettext('filters')) .
277 html::div(array('class' => 'boxcontent'), $table->show() .
278 html::p(null,
279 $this->rc->output->button(array(
280 'command' => 'plugin.filters-save',
281 'type' => 'input',
282 'class' => 'button mainaction',
283 'label' => 'save'
284 )))));
285 $out.= html::div(array('id' => 'prefs-title','class' => 'boxtitle'), $this->gettext('storedfilters')). html::div(array('class' => 'uibox listbox scroller','style'=>'margin-top:250px;'),
286 html::div(array('class' => 'boxcontent'), $table2->show() ));
287
288 $this->rc->output->add_gui_object('filtersform', 'filters-form');
289
290 return $this->rc->output->form_tag(array(
291 'id' => 'filters-form',
292 'name' => 'filters-form',
293 'method' => 'post',
294 'class' => 'propform',
295 'action' => './?_task=settings&_action=plugin.filters-save',
296 ), $out);
297
298 }
299
300 function filters_search($message){
301 // check if a message has been read
302 if (isset($message->flags['SEEN']) && $message->flags['SEEN'])
303 $msg_read = 1;
304 $headers = array('from','to','cc','subject');
305 $destination_folder = '';
306 $filter_flag = '';
307 $mark_flag = '';
308 foreach($headers as $whatfilter){
309 if (isset($this->searchstring[$whatfilter])){
310 foreach ($this->searchstring[$whatfilter] as $from => $dest){
311 $arr = explode("#",$dest);
312 $destination = $arr[0];
313 $msg_filter = $arr[1];
314 $filterpriority = $arr[2];
315 $markread = $arr[3];
316
317 switch ($whatfilter){
318 case 'from':
319 $field = $message->from;
320 break;
321 case 'to':
322 $field = $message->to;
323 break;
324 case 'cc':
325 $field = $message->cc;
326 break;
327 case 'subject':
328 $field = $message->subject;
329 break;
330 default:
331 $field = "";
332 }
333
334 if ($this->filters_searchString($field, $from) != false && $destination!=$this->open_mbox){
335 if (!empty($filterpriority)){
336 $destination_folder = $destination;
337 $filter_flag = $msg_filter;
338 $mark_flag = $markread;
339 break 2;
340 }
341 if (empty($destination_folder)){
342 $destination_folder = $destination;
343 $filter_flag = $msg_filter;
344 $mark_flag = $markread;
345 }
346 }
347 }
348 }
349 }
350 if (!empty($destination_folder)){
351 // if message as read and need unread message, then exit from function
352 // Если сообщение как прочитанное и нужно непрочитанное сообщение, то выход из функции
353 if (!empty($msg_read) && $filter_flag == "unread") return;
354 // if message as unread and need read message, then exit from function
355 // Если сообщение как непрочитанное и нужно прочитанное сообщение, то выход из функции
356 if (empty($msg_read) && $filter_flag == "isread") return;
357 $this->msg_uids[$destination_folder][] = $message->uid;
358 if (!in_array($destination_folder, $this->destfolder)) $this->destfolder[] = $destination_folder;
359 // Mark message as read if need mark message as read
360 // Отметить сообщение как прочитанное
361 if ($mark_flag == "markread") $this->filters_markread($message);
362 // Mark message as unread if need mark message as unread
363 // Отметить сообщение как непрочитанное
364 if ($mark_flag == "markunread") $this->filters_markread($message,'UNSEEN');
365 }
366 }
367 // Mark message as read (SEEN) or as unread (UNSEEN)
368 function filters_markread($message,$markread='SEEN'){
369 $storage = $this->rc->storage;
370 $storage->set_flag($message->uid, $markread, NULL);
371 }
372
373 function filters_searchString($msg,$stringToSearch){
374 $ret = FALSE;
375
376 $ciSearch = $this->caseInsensitiveSearch;
377 $decode_msg = rcube_mime::decode_header((string)$msg);
378
379 $stringToSearch=stripslashes($stringToSearch);
380
381 $decode_msg = addslashes($decode_msg);
382 $stringToSearch = addslashes($stringToSearch);
383
384 if ($ciSearch){
385 if (function_exists('mb_stripos')){
386 $tmp = mb_stripos($decode_msg, $stringToSearch);
387 }
388 else{
389 $tmp = stripos($decode_msg, $stringToSearch);
390 }
391 }
392 else{
393 if (function_exists('mb_strpos')){
394 $tmp = mb_strpos($decode_msg, $stringToSearch);
395 }
396 else{
397 $tmp = strpos($decode_msg, $stringToSearch);
398 }
399 }
400
401 if ($tmp !== FALSE){
402 $ret = TRUE;
403 }
404
405 else{
406 if ($this->decodeBase64Msg === TRUE){
407 // decode and search BASE64 msg
408 $decode_msg = rcube_mime::decode_header(base64_decode($msg));
409
410 if ($decode_msg !== FALSE){
411
412 if ($ciSearch){
413 if (function_exists('mb_stripos')){
414 $tmp = mb_stripos($decode_msg, $stringToSearch);
415 }
416 else{
417 $tmp = stripos($decode_msg, $stringToSearch);
418 }
419 }
420 else{
421 if (function_exists('mb_strpos')){
422 $tmp = mb_strpos($decode_msg, $stringToSearch);
423 }
424 else{
425 $tmp = strpos($decode_msg, $stringToSearch);
426 }
427 }
428 if ($tmp !== FALSE){
429 $ret = TRUE;
430 }
431 }
432 }
433 }
434
435 return $ret;
436 }
437
438
439 function filters_addMoveSpamRule(){
440
441 $user = $this->rc->user;
442
443 $searchstring = $this->spam_subject;
444 $destfolder = $this->rc->config->get('junk_mbox', null);
445 $whatfilter = "subject";
446 $messages = "all";
447
448 //load filters
449 $arr_prefs = $this->rc->config->get('filters', array());
450
451 // check if the rule is already enabled
452 $found = false;
453 foreach ($arr_prefs as $key => $saved_filter){
454 if ($saved_filter['searchstring'] == $searchstring && $saved_filter['whatfilter'] == $whatfilter){
455 $found = true;
456 }
457 }
458
459 if (!$found && $destfolder !== null && $destfolder !== ""){
460 $new_arr['whatfilter'] = $whatfilter;
461 $new_arr['searchstring'] = $searchstring;
462 $new_arr['destfolder'] = $destfolder;
463 $new_arr['messages'] = $messages;
464 $arr_prefs = $user->get_prefs();
465 $arr_prefs['filters'][] = $new_arr;
466 $user->save_prefs($arr_prefs);
467 }
468 }
469
470 }
471 ?>