Mercurial > hg > rc1
view plugins/filters/filters.php @ 1:5821049f1791
most of the way to allowing arbitrarily many labels
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 16:23:36 -0500 |
parents | 1e000243b222 |
children |
line wrap: on
line source
<?php /** * Filters * * Plugin that adds a new tab to the settings section to create client-side e-mail filtering. * * @version 2.1.6 * @author Roberto Zarrelli <zarrelli@unimol.it> * @developer Artur Petrov <admin@gtn18.ru> */ class filters extends rcube_plugin{ public $task = 'login|mail|settings'; private $autoAddSpamFilterRule; private $spam_subject; private $caseInsensitiveSearch; private $decodeBase64Msg; private $searchstring = array(); private $destfolder = array(); private $msg_uids = array(); private $open_mbox; function init(){ /* Filters parameters initialization. See readme.txt */ $this->load_config(); /* ***************************************************** */ $rcmail = rcmail::get_instance(); $this->rc = &$rcmail; $this->autoAddSpamFilterRule = $this->rc->config->get('autoAddSpamFilterRule',TRUE); $this->spam_subject = $this->rc->config->get('spam_subject','[SPAM]'); $this->caseInsensitiveSearch = $this->rc->config->get('caseInsensitiveSearch',TRUE); $this->decodeBase64Msg = $this->rc->config->get('decodeBase64Msg',FALSE); if($this->rc->task == 'mail' && !isset($_GET["_q"])) $this->add_hook('messages_list', array($this, 'filters_checkmsg')); else if ($this->rc->task == 'settings'){ $this->register_action('plugin.filters', array($this, 'filters_init')); $this->register_action('plugin.filters-save', array($this, 'filters_save')); $this->register_action('plugin.filters-delete', array($this, 'filters_delete')); $this->add_texts('localization/', array('filters','nosearchstring')); $this->rc->output->add_label('filters'); $this->include_script('filters.js'); } else if ($this->rc->task == 'login'){ if ($this->autoAddSpamFilterRule) $this->add_hook('login_after', array($this, 'filters_addMoveSpamRule')); } } function filters_checkmsg($mlist){ $user = $this->rc->user; if (method_exists($this->rc->imap,'get_mailbox_name')) { $imap = $this->rc->imap; $open_mbox = $imap->get_mailbox_name(); } else { $imap = $this->rc->storage; $open_mbox = $imap->get_folder(); } $this->open_mbox=$open_mbox; // does not consider the messages already in the trash if ($open_mbox == $this->rc->config->get('trash_mbox')) return; //load filters $arr_prefs = $this->rc->config->get('filters', array()); foreach ($arr_prefs as $key => $saved_filter){ // if saved destination folder exists and current folder is INBOX if (method_exists($imap,'mailbox_exists')){ if ($imap->mailbox_exists($saved_filter['destfolder']) && 'INBOX'==$open_mbox){ $saved_filter['searchstring'] = html_entity_decode($saved_filter['searchstring']); // if (!isset($saved_filter['filterpriority'])) $saved_filter['filterpriority'] = ''; // destfolder#messages#filterpriority#markread $this->searchstring[ $saved_filter['whatfilter'] ][ $saved_filter['searchstring'] ] = $saved_filter['destfolder']."#".$saved_filter['messages']."#".$saved_filter['filterpriority']."#".$saved_filter['markread']; } } if (!method_exists($imap,'mailbox_exists')){ if ($imap->folder_exists($saved_filter['destfolder']) && 'INBOX'==$open_mbox){ $saved_filter['searchstring'] = html_entity_decode($saved_filter['searchstring']); // if (!isset($saved_filter['filterpriority'])) $saved_filter['filterpriority'] = ''; // destfolder#messages#filterpriority#markread $this->searchstring[ $saved_filter['whatfilter'] ][ $saved_filter['searchstring'] ] = $saved_filter['destfolder']."#".$saved_filter['messages']."#".$saved_filter['filterpriority']."#".$saved_filter['markread']; } } } // if there aren't filters return if(!count($arr_prefs) || !count($this->searchstring) || !isset($mlist['messages']) || !is_array($mlist['messages'])) return; // scan the messages foreach($mlist["messages"] as $message){ $this->filters_search($message); } // move the filtered messages if (count($this->destfolder) > 0){ foreach ($this->destfolder as $dfolder){ $uids = array(); foreach ($this->msg_uids[$dfolder] as $muids){ $uids[] = $muids; } if (count($uids)){ $imap->move_message($uids, $dfolder, $open_mbox); // refresh $unseen = $this->rc->storage->count($dfolder, 'UNSEEN'); $this->api->output->command('set_unread_count',$dfolder, $unseen); $this->api->output->command('list_mailbox'); $this->api->output->send(); } } } } function filters_init(){ $this->add_texts('localization/'); $this->register_handler('plugin.body', array($this, 'filters_form')); $this->rc->output->set_pagetitle($this->gettext('filters')); $this->rc->output->send('plugin'); } function filters_save(){ $user = $this->rc->user; $this->add_texts('localization/'); $this->register_handler('plugin.body', array($this, 'filters_form')); $this->rc->output->set_pagetitle($this->gettext('filters')); $searchstring = trim(rcube_utils::get_input_value('_searchstring', RCUBE_INPUT_POST, true)); $destfolder = trim(rcube_utils::get_input_value('_folders', RCUBE_INPUT_POST, true)); $whatfilter = trim(rcube_utils::get_input_value('_whatfilter', RCUBE_INPUT_POST, true)); $messages = trim(rcube_utils::get_input_value('_messages', RCUBE_INPUT_POST, true)); $filterpriority = trim(rcube_utils::get_input_value('_checkbox', RCUBE_INPUT_POST, true)); $markread = trim(rcube_utils::get_input_value('_markread', RCUBE_INPUT_POST, true)); if ($searchstring == "") $this->rc->output->command('display_message', $this->gettext('nosearchstring'), 'error'); else{ $new_arr['whatfilter'] = $whatfilter; $new_arr['searchstring'] = htmlspecialchars(addslashes($searchstring)); $new_arr['destfolder'] = addslashes($destfolder); $new_arr['messages'] = $messages; $new_arr['filterpriority'] = $filterpriority; $new_arr['markread'] = $markread; $arr_prefs = $user->get_prefs(); $arr_prefs['filters'][] = $new_arr; if ($user->save_prefs($arr_prefs)) $this->rc->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation'); else $this->rc->output->command('display_message', $this->gettext('unsuccessfullysaved'), 'error'); } $this->rc->overwrite_action('plugin.filters'); $this->rc->output->send('plugin'); } function filters_delete(){ $user = $this->rc->user; $this->add_texts('localization/'); $this->register_handler('plugin.body', array($this, 'filters_form')); $this->rc->output->set_pagetitle($this->gettext('filters')); if (isset($_GET[filterid])){ $filter_id = $_GET[filterid]; $arr_prefs = $user->get_prefs(); $arr_prefs['filters'][$filter_id] = ''; $arr_prefs['filters'] = array_diff($arr_prefs['filters'], array('')); if ($user->save_prefs($arr_prefs)) $this->rc->output->command('display_message', $this->gettext('successfullydeleted'), 'confirmation'); else $this->rc->output->command('display_message', $this->gettext('unsuccessfullydeleted'), 'error'); } if (function_exists('rcmail::get_instance()->overwrite_action')) rcmail::get_instance()->overwrite_action('plugin.filters'); else $this->rc->overwrite_action('plugin.filters'); $this->rc->output->send('plugin'); } function filters_form(){ if (method_exists($this->rc,'imap_connect')) $this->rc->imap_connect(); else $this->rc->storage_connect(); $table = new html_table(array('cols' => 2)); $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('whatfilter').":", 'html')); $select = new html_select(array('name' => '_whatfilter', 'id' => 'whatfilter')); $select->add($this->gettext('from'), 'from'); $select->add($this->gettext('to'), 'to'); $select->add($this->gettext('cc'), 'cc'); $select->add($this->gettext('subject'), 'subject'); $table->add('', $select->show($this->gettext('from'))); $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('searchstring').":"), 'html'); $inputfield = new html_inputfield(array('name' => '_searchstring', 'id' => 'searchstring')); $table->add('', $inputfield->show("")); $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('moveto').":")); if (function_exists('rcmail::get_instance()->folder_selector')) $select = rcmail::get_instance()->folder_selector(array('name' => '_folders', 'id' => 'folders')); else $select = $this->rc->folder_selector(array('name' => '_folders', 'id' => 'folders')); $table->add('title', $select->show()); # new option: all, read and unread messages $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('messagecount').":"), 'html'); $select = new html_select(array('name' => '_messages', 'id' => 'messages')); $select->add($this->gettext('all'), 'all'); $select->add($this->gettext('unread'), 'unread'); $select->add($this->gettext('isread'), 'isread'); $table->add('', $select->show($this->gettext('all'))); # new option: markread or markunread messages $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('markmessages').":"), 'html'); $select = new html_select(array('name' => '_markread', 'id' => 'markread')); $select->add($this->gettext('none'), 'none'); $select->add($this->gettext('markunread'), 'markunread'); $select->add($this->gettext('markread'), 'markread'); $table->add('', $select->show($this->gettext('none'))); # new option: filter priority, "on" as enable and "" as disable $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('filterpriority').":"), 'html'); $checkbox = new html_checkbox(array('name' => '_checkbox', 'id' => 'checkbox')); $table->add('', $checkbox->show("0")); // load saved filters $user = $this->rc->user; $arr_prefs = $user->get_prefs(); $i = 1; $flag=false; $table2 = new html_table(array('cols' => 2)); foreach ($arr_prefs['filters'] as $key => $saved_filter){ $flag=true; if (empty($saved_filter['markread'])) $saved_filter['markread'] = 'none'; $folder_id = $saved_filter['destfolder']; if (function_exists('rcmail::get_instance()->localize_folderpath')) $folder_name = rcmail::get_instance()->localize_folderpath($folder_id); else $folder_name = $this->rc->localize_folderpath($folder_id); $messages = $saved_filter['messages']; $msg = $i." - ".$this->gettext('msg_if_field')." <b>".$this->gettext($saved_filter['whatfilter'])."</b> ".$this->gettext('msg_contains'). " <b>".stripslashes($saved_filter['searchstring'])."</b> ". $this->gettext('msg_move_msg_in')." <b>".$folder_name."</b> ". "(".$this->gettext('messagecount').": ".$this->gettext($saved_filter['messages']). ", ".$this->gettext('mark').": ".$this->gettext($saved_filter['markread']).")"; if ( !empty($saved_filter['filterpriority'])) $msg = "<font color='green'>".$msg."</font>"; $table2->add('title',$msg); $dlink = "<a href='./?_task=settings&_action=plugin.filters-delete&filterid=".$key."'>".$this->gettext('delete')."</a>"; $table2->add('title',$dlink); $i++; } if (!$flag){ $table2->add('title',rcube_utils::rep_specialchars_output($this->gettext('msg_no_stored_filters'), 'html')); } $out = html::div(array('class' => 'box'), html::div(array('id' => 'prefs-title', 'class' => 'boxtitle'), $this->gettext('filters')) . html::div(array('class' => 'boxcontent'), $table->show() . html::p(null, $this->rc->output->button(array( 'command' => 'plugin.filters-save', 'type' => 'input', 'class' => 'button mainaction', 'label' => 'save' ))))); $out.= html::div(array('id' => 'prefs-title','class' => 'boxtitle'), $this->gettext('storedfilters')). html::div(array('class' => 'uibox listbox scroller','style'=>'margin-top:250px;'), html::div(array('class' => 'boxcontent'), $table2->show() )); $this->rc->output->add_gui_object('filtersform', 'filters-form'); return $this->rc->output->form_tag(array( 'id' => 'filters-form', 'name' => 'filters-form', 'method' => 'post', 'class' => 'propform', 'action' => './?_task=settings&_action=plugin.filters-save', ), $out); } function filters_search($message){ // check if a message has been read if (isset($message->flags['SEEN']) && $message->flags['SEEN']) $msg_read = 1; $headers = array('from','to','cc','subject'); $destination_folder = ''; $filter_flag = ''; $mark_flag = ''; foreach($headers as $whatfilter){ if (isset($this->searchstring[$whatfilter])){ foreach ($this->searchstring[$whatfilter] as $from => $dest){ $arr = explode("#",$dest); $destination = $arr[0]; $msg_filter = $arr[1]; $filterpriority = $arr[2]; $markread = $arr[3]; switch ($whatfilter){ case 'from': $field = $message->from; break; case 'to': $field = $message->to; break; case 'cc': $field = $message->cc; break; case 'subject': $field = $message->subject; break; default: $field = ""; } if ($this->filters_searchString($field, $from) != false && $destination!=$this->open_mbox){ if (!empty($filterpriority)){ $destination_folder = $destination; $filter_flag = $msg_filter; $mark_flag = $markread; break 2; } if (empty($destination_folder)){ $destination_folder = $destination; $filter_flag = $msg_filter; $mark_flag = $markread; } } } } } if (!empty($destination_folder)){ // if message as read and need unread message, then exit from function // Если сообщение как прочитанное и нужно непрочитанное сообщение, то выход из функции if (!empty($msg_read) && $filter_flag == "unread") return; // if message as unread and need read message, then exit from function // Если сообщение как непрочитанное и нужно прочитанное сообщение, то выход из функции if (empty($msg_read) && $filter_flag == "isread") return; $this->msg_uids[$destination_folder][] = $message->uid; if (!in_array($destination_folder, $this->destfolder)) $this->destfolder[] = $destination_folder; // Mark message as read if need mark message as read // Отметить сообщение как прочитанное if ($mark_flag == "markread") $this->filters_markread($message); // Mark message as unread if need mark message as unread // Отметить сообщение как непрочитанное if ($mark_flag == "markunread") $this->filters_markread($message,'UNSEEN'); } } // Mark message as read (SEEN) or as unread (UNSEEN) function filters_markread($message,$markread='SEEN'){ $storage = $this->rc->storage; $storage->set_flag($message->uid, $markread, NULL); } function filters_searchString($msg,$stringToSearch){ $ret = FALSE; $ciSearch = $this->caseInsensitiveSearch; $decode_msg = rcube_mime::decode_header((string)$msg); $stringToSearch=stripslashes($stringToSearch); $decode_msg = addslashes($decode_msg); $stringToSearch = addslashes($stringToSearch); if ($ciSearch){ if (function_exists('mb_stripos')){ $tmp = mb_stripos($decode_msg, $stringToSearch); } else{ $tmp = stripos($decode_msg, $stringToSearch); } } else{ if (function_exists('mb_strpos')){ $tmp = mb_strpos($decode_msg, $stringToSearch); } else{ $tmp = strpos($decode_msg, $stringToSearch); } } if ($tmp !== FALSE){ $ret = TRUE; } else{ if ($this->decodeBase64Msg === TRUE){ // decode and search BASE64 msg $decode_msg = rcube_mime::decode_header(base64_decode($msg)); if ($decode_msg !== FALSE){ if ($ciSearch){ if (function_exists('mb_stripos')){ $tmp = mb_stripos($decode_msg, $stringToSearch); } else{ $tmp = stripos($decode_msg, $stringToSearch); } } else{ if (function_exists('mb_strpos')){ $tmp = mb_strpos($decode_msg, $stringToSearch); } else{ $tmp = strpos($decode_msg, $stringToSearch); } } if ($tmp !== FALSE){ $ret = TRUE; } } } } return $ret; } function filters_addMoveSpamRule(){ $user = $this->rc->user; $searchstring = $this->spam_subject; $destfolder = $this->rc->config->get('junk_mbox', null); $whatfilter = "subject"; $messages = "all"; //load filters $arr_prefs = $this->rc->config->get('filters', array()); // check if the rule is already enabled $found = false; foreach ($arr_prefs as $key => $saved_filter){ if ($saved_filter['searchstring'] == $searchstring && $saved_filter['whatfilter'] == $whatfilter){ $found = true; } } if (!$found && $destfolder !== null && $destfolder !== ""){ $new_arr['whatfilter'] = $whatfilter; $new_arr['searchstring'] = $searchstring; $new_arr['destfolder'] = $destfolder; $new_arr['messages'] = $messages; $arr_prefs = $user->get_prefs(); $arr_prefs['filters'][] = $new_arr; $user->save_prefs($arr_prefs); } } } ?>