rc = rcmail::get_instance();
$this->load_config();
$this->add_texts('localization/', false);
$this->setCustomLabels();
if ($this->rc->task == 'mail')
{
# -- disable plugin when printing message
if ($this->rc->action == 'print')
return;
if (!$this->rc->config->get('tb_label_enable'))
// disable plugin according to prefs
return;
// pass 'tb_label_enable_shortcuts' and 'tb_label_style' prefs to JS
$this->rc->output->set_env('tb_label_enable_shortcuts', $this->rc->config->get('tb_label_enable_shortcuts'));
$this->rc->output->set_env('tb_label_style', $this->rc->config->get('tb_label_style'));
$this->include_script('tb_label.js');
$this->add_hook('messages_list', array($this, 'read_flags'));
$this->add_hook('message_load', array($this, 'read_single_flags'));
$this->add_hook('template_object_messageheaders', array($this, 'color_headers'));
$this->add_hook('render_page', array($this, 'tb_label_popup'));
$this->add_hook('check_recent', array($this, 'check_recent_flags'));
$this->include_stylesheet($this->local_skin_path() . '/tb_label.css');
#$this->include_stylesheet($this->local_skin_path() . '/tb_label.php');
$this->name = get_class($this);
# -- additional TB flags
$this->add_tb_flags = array(
/*'LABEL1' => '$Label1',
'LABEL2' => '$Label2',
'LABEL3' => '$Label3',
'LABEL4' => '$Label4',
'LABEL5' => '$Label5',*/
);
$this->message_tb_labels = array();
$html = $this->template_file2html('toolbar');
if ($html)
$this->api->add_content($html, 'toolbar');
// JS function "set_flags" => PHP function "set_flags"
$this->register_action('plugin.thunderbird_labels.set_flags', array($this, 'set_flags'));
if (method_exists($this, 'require_plugin')
&& in_array('contextmenu', $this->rc->config->get('plugins'))
&& $this->require_plugin('contextmenu')
&& $this->rc->config->get('tb_label_enable_contextmenu'))
{
if ($this->rc->action == '')
$this->add_hook('render_mailboxlist', array($this, 'show_tb_label_contextmenu'));
}
}
elseif ($this->rc->task == 'settings')
{
$this->include_stylesheet($this->local_skin_path() . '/tb_label.css');
$this->add_hook('preferences_list', array($this, 'prefs_list'));
$this->add_hook('preferences_sections_list', array($this, 'prefs_section'));
$this->add_hook('preferences_save', array($this, 'prefs_save'));
}
}
private function setCustomLabels()
{
$c = $this->rc->config->get('tb_label_custom_labels');
if (empty($c) || isset($c[3]))
{
// if no user specific labels, use localized strings by default
$this->rc->config->set('tb_label_custom_labels', array(
'LABEL0' => $this->getText('label0'),
'LABEL1' => $this->getText('label1'),
'LABEL2' => $this->getText('label2'),
'LABEL3' => $this->getText('label3'),
'LABEL4' => $this->getText('label4'),
'LABEL5' => $this->getText('label5')
));
}
// pass label strings to JS
$this->rc->output->set_env('tb_label_custom_labels', $this->rc->config->get('tb_label_custom_labels'));
}
// create a section for the tb-labels Settings
public function prefs_section($args)
{
$args['list']['thunderbird_labels'] = array(
'id' => 'thunderbird_labels',
'section' => rcube::Q($this->gettext('tb_label_options'))
);
return $args;
}
// display thunderbird-labels prefs in Roundcube Settings
public function prefs_list($args)
{
if ($args['section'] != 'thunderbird_labels')
return $args;
$this->load_config();
$dont_override = (array) $this->rc->config->get('dont_override', array());
$args['blocks']['tb_label'] = array();
$args['blocks']['tb_label']['name'] = $this->gettext('tb_label_options');
$key = 'tb_label_enable';
if (!in_array($key, $dont_override))
{
$input = new html_checkbox(array(
'name' => $key,
'id' => $key,
'value' => 1
));
$content = $input->show($this->rc->config->get($key));
$args['blocks']['tb_label']['options'][$key] = array(
'title' => $this->gettext('tb_label_enable_option'),
'content' => $content
);
}
$key = 'tb_label_enable_shortcuts';
if (!in_array($key, $dont_override))
{
$input = new html_checkbox(array(
'name' => $key,
'id' => $key,
'value' => 1
));
$content = $input->show($this->rc->config->get($key));
$args['blocks']['tb_label']['options'][$key] = array(
'title' => $this->gettext('tb_label_enable_shortcuts_option'),
'content' => $content
);
}
$key = 'tb_label_style';
if (!in_array($key, $dont_override))
{
$select = new html_select(array(
'name' => $key,
'id' => $key
));
$select->add([$this->gettext('thunderbird'), $this->gettext('bullets'), $this->gettext('badges')], self::LABEL_STYLES);
$content = $select->show($this->rc->config->get($key));
$args['blocks']['tb_label']['options'][$key] = array(
'title' => $this->gettext('tb_label_style_option'),
'content' => $content
);
}
if (!in_array('tb_label_custom_labels', $dont_override)
&& $this->rc->config->get('tb_label_modify_labels'))
{
$custom_labels = $this->rc->config->get('tb_label_custom_labels');
foreach ($custom_labels as $key => $value)
{
$input = new html_inputfield(array(
'name' => "custom_$key",
'id' => "custom_$key",
'type' => 'text',
'autocomplete' => 'off',
'title' => $this->getText(strtolower($key)), # shows default value on hover
'value' => $value));
$args['blocks']['tb_label']['options']["option_$key"] = array(
'title' => $key,
'content' => $input->show()
);
}
}
return $args;
}
// save prefs after modified in UI
public function prefs_save($args)
{
if ($args['section'] != 'thunderbird_labels')
return $args;
$this->load_config();
$dont_override = (array) $this->rc->config->get('dont_override', array());
if (!in_array('tb_label_enable', $dont_override))
$args['prefs']['tb_label_enable'] = rcube_utils::get_input_value('tb_label_enable', rcube_utils::INPUT_POST) ? true : false;
if (!in_array('tb_label_enable_shortcuts', $dont_override))
$args['prefs']['tb_label_enable_shortcuts'] = rcube_utils::get_input_value('tb_label_enable_shortcuts', rcube_utils::INPUT_POST) ? true : false;
if (!in_array('tb_label_style', $dont_override))
{
$tb_label_style = rcube_utils::get_input_value('tb_label_style', rcube_utils::INPUT_POST);
if (in_array($tb_label_style, self::LABEL_STYLES))
{
$args['prefs']['tb_label_style'] = $tb_label_style;
}
}
if (!in_array('tb_label_custom_labels', $dont_override)
&& $this->rc->config->get('tb_label_modify_labels'))
{
$args['prefs']['tb_label_custom_labels'] = array(
'LABEL0' => $this->gettext('label0'),
'LABEL1' => rcube_utils::get_input_value('custom_LABEL1', rcube_utils::INPUT_POST),
'LABEL2' => rcube_utils::get_input_value('custom_LABEL2', rcube_utils::INPUT_POST),
'LABEL3' => rcube_utils::get_input_value('custom_LABEL3', rcube_utils::INPUT_POST),
'LABEL4' => rcube_utils::get_input_value('custom_LABEL4', rcube_utils::INPUT_POST),
'LABEL5' => rcube_utils::get_input_value('custom_LABEL5', rcube_utils::INPUT_POST)
);
}
return $args;
}
public function show_tb_label_contextmenu($args)
{
# no longer needed
#$this->include_script('tb_label_contextmenu.js');
return null;
}
private function _gen_label_submenu($args, $id)
{
$out = '';
$custom_labels = $this->rc->config->get('tb_label_custom_labels');
for ($i = 0; $i < 6; $i++)
{
$separator = ($i == 0)? ' separator_below' :'';
$out .= html::tag('li',
null,
$this->api->output->button(array(
'label' => rcube::Q($i.' '.$custom_labels["LABEL$i"]),
'command' => 'test.comm.and',
'type' => 'link',
'class' => 'label'.$i.$separator,
'aria-disabled' => 'true'
)
)
);
/*$out .= '
'.
$i.' '.$custom_labels[$i].
'';*/
}
$out = html::tag('ul', array('id' => $id, 'role' => 'menu'), $out);
return $out;
}
public function read_single_flags($args)
{
#rcube::write_log($this->name, print_r(($args['object']), true));
if (!isset($args['object'])) {
return;
}
if (is_array($args['object']->headers->flags))
{
$this->message_tb_labels = $this->custom_flags(array_keys($args['object']->headers->flags));
}
# -- no return value for this hook
}
/**
* Writes labelnumbers for single message display
* Coloring of Message header table happens via Javascript
*/
public function color_headers($p)
{
#rcube::write_log($this->name, print_r($p, true));
# -- always write array, even when empty
$p['content'] .= '';
return $p;
}
public function read_flags($args)
{
#rcube::write_log($this->name, print_r($args, true));
// add color information for all messages
// dont loop over all messages if we dont have any highlights or no msgs
if (!isset($args['messages']) or !is_array($args['messages'])) {
return $args;
}
// loop over all messages and add $LabelX info to the extra_flags
foreach($args['messages'] as $message)
{
#rcube::write_log($this->name, print_r($message->flags, true));
$message->list_flags['extra_flags']['tb_labels'] = array(); # always set extra_flags, needed for javascript later!
if (is_array($message->flags))
$message->list_flags['extra_flags']['tb_labels'] = $this->custom_flags(array_keys($message->flags));
}
return($args);
}
// set flags in IMAP server
function set_flags()
{
#rcube::write_log($this->name, print_r($_GET, true));
$imap = $this->rc->storage;
$cbox = rcube_utils::get_input_value('_cur', rcube_utils::INPUT_GET);
$mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GET);
$toggle_label = rcube_utils::get_input_value('_toggle_label', rcube_utils::INPUT_GET);
$flag_uids = rcube_utils::get_input_value('_flag_uids', rcube_utils::INPUT_GET);
$flag_uids = explode(',', $flag_uids);
$unflag_uids = rcube_utils::get_input_value('_unflag_uids', rcube_utils::INPUT_GET);
$unflag_uids = explode(',', $unflag_uids);
$imap->conn->flags = array_merge($imap->conn->flags, $this->add_tb_flags);
#rcube::write_log($this->name, print_r($flag_uids, true));
#rcube::write_log($this->name, print_r($unflag_uids, true));
if (!is_array($unflag_uids)
|| !is_array($flag_uids))
return false;
# FIXME: there is no reliable way to know if roundcube mangled a label of different client
# here is just a workaround for the known Thunderbird labels
if (preg_match("/^LABEL[1-5]$/", $toggle_label)) # only for Thunderbird labels
{
$imap->set_flag($flag_uids, "UN$toggle_label", $mbox); # quickhack to remove non-$ labels
$imap->set_flag($unflag_uids, "UN$toggle_label", $mbox); # quickhack to remove non-$ labels
# prepend $ again to be compatible to Thunderbird (roundcube removes $ from labels)
$imap->set_flag($flag_uids, "\$$toggle_label", $mbox);
$imap->set_flag($unflag_uids, "UN\$$toggle_label", $mbox);
}
else
{
$imap->set_flag($flag_uids, "$toggle_label", $mbox);
$imap->set_flag($unflag_uids, "UN$toggle_label", $mbox);
}
$this->api->output->send();
}
function template_include_markup($tpl_name)
{
$path = '/' . $this->local_skin_path() . '/includes/' . $tpl_name . '.html';
$filepath = slashify($this->home) . $path;
if (is_file($filepath) && is_readable($filepath))
return "";
return null;
}
function template_file2html($tpl_name)
{
$tpl_cmd = $this->template_include_markup($tpl_name);
if ($tpl_cmd)
return $this->template2html($tpl_cmd);
return null;
}
function template2html($tpl_code)
{
if ($this->api->output->type == 'html')
{
if ($tpl_code)
{
$this->add_texts('localization/');
return $this->rc->output->just_parse($tpl_code);
}
}
return null;
}
function tb_label_popup($args)
{
// Other plugins may use template parsing method, this causes more than one render_page execution.
// We have to make sure the menu is added only once (when content is going to be written to client).
// roundcube < 1.4 does not send 'write' key
if (array_key_exists('write', $args) && !$args['write'])
return;
$html = $this->template_file2html($this->rc->task);
if ($html)
$this->rc->output->add_footer($html);
# create a RC template for the popup-menu of tb-labels, make html from it and inject
$tpl = '
';
$tpl_menu = '';
$custom_labels = $this->rc->config->get('tb_label_custom_labels');
$i = 0;
foreach ($custom_labels as $label_name => $human_readable)
{
$tpl_menu .= '';
$i++;
}
$html = $this->template2html($tpl.$tpl_menu.$tpl_end);
if ($html)
$this->rc->output->add_footer($html);
}
/* Bastardised hook, actually supposed to modify the list of folders for refresh
* what we do here is fetching the imap-label changes using GPC variables!
*/
function check_recent_flags($params)
{
$mbox_name = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC); // appears to be the current one
$uids = rcube_utils::get_input_value('_uids', rcube_utils::INPUT_GPC);
if ($uids && $mbox_name)
{
$mbox_name = $params['folders'][0];
$RCMAIL = $this->rc;
# -- from here it's from check_recent.inc
$data = $RCMAIL->storage->folder_data($mbox_name);
if (empty($_SESSION['list_mod_seq']) || $_SESSION['list_mod_seq'] != $data['HIGHESTMODSEQ']) {
$flags = $RCMAIL->storage->list_flags($mbox_name, explode(',', $uids), $_SESSION['list_mod_seq']);
foreach ($flags as $idx => $row) {
$flags[$idx] = array_change_key_case(array_map('intval', $row));
}
// remember last HIGHESTMODSEQ value (if supported)
if (!empty($data['HIGHESTMODSEQ'])) {
$_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
}
$RCMAIL->output->set_env('recent_flags', $flags);
}
# -- end of code copy from check_recent.inc
if (isset($data['PERMANENTFLAGS']))
{
//rcube::write_log($this->name, "data:".print_r($data['PERMANENTFLAGS'], true));
$RCMAIL->output->set_env('custom_flags', $this->custom_flags($data['PERMANENTFLAGS']));
}
}
return $params;
}
/**
* Checks if the IMAP Server has support for custom flags
* According to RFC the server must respond with a '\*' within PERMANENTFLAGS
*/
function custom_flags_allowed($permanent_flags)
{
if (!is_null($this->_custom_flags_allowed)) // primitive caching
return $this->_custom_flags_allowed;
$this->_custom_flags_allowed = false;
foreach ($permanent_flags as $pf)
{
if ($pf == '\*')
$this->_custom_flags_allowed = true;
}
return $this->_custom_flags_allowed;
}
/**
* creates a list of custom flags besides the RFC default ones
*/
function custom_flags($permanent_flags)
{
$default_flags = [
'\Seen', '\Answered', // RFC3501
'\Flagged', '\Deleted', // RFC3501
'\Draft', '\Recent', // RFC3501
'SEEN', 'ANSWERED', // RFC3501 roundcubed
'FLAGGED', 'DELETED', // RFC3501 roundcubed
'DRAFT', 'RECENT', // RFC3501 roundcubed
'$MDNSent', // Message Disposition Notification, not of interest
'MDNSENT', // Message Disposition Notification, not of interest roundcubed
'Junk', // not a useful flag for the user?
'JUNK', // not a useful flag for the user? roundcubed
'NonJunk', // not a useful flag for the user?
'NONJUNK', // not a useful flag for the user? roundcubed
'\\*', // means labels allowed
'*', // means labels allowed roundcubed
];
$default_flags = array_unique(array_merge($default_flags, $this->rc->config->get('tb_label_hidden_flags', [])));
/* TODO: flagnames contain $ sign, or umlauts (imap-utf-7 encoded meanging & will be in the name)
* smart way to recode those characters and create valid variable names?
* Valid CSS classname is easy, just escape everything outside of [a-zA-Z0-9_] using backslash
*/
$custom_flags = array();
foreach ($permanent_flags as $pf)
{
$pf = $this->roundcube_flag($pf);
if (!in_array($pf, $default_flags))
$custom_flags[] = $pf;
}
return $custom_flags;
}
/**
* Roundcube mangles the flagnames for some reason to uppercase and removes backslash and $
*/
function roundcube_flag($flag)
{
return ltrim(strtoupper($flag), '$\\');
}
}