2011-05-19 12:40:46 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type-aware folder management/listing for Kolab
|
|
|
|
*
|
2011-11-18 15:55:08 +01:00
|
|
|
* @version @package_version@
|
2011-05-19 12:40:46 +02:00
|
|
|
* @author Aleksander Machniak <machniak@kolabsys.com>
|
|
|
|
*
|
2011-10-27 10:20:46 +02:00
|
|
|
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
2011-05-19 12:40:46 +02:00
|
|
|
*
|
2011-10-27 10:20:46 +02:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
2011-05-19 12:40:46 +02:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2011-10-27 10:20:46 +02:00
|
|
|
* GNU Affero General Public License for more details.
|
2011-05-19 12:40:46 +02:00
|
|
|
*
|
2011-10-27 10:20:46 +02:00
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2011-05-19 12:40:46 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
class kolab_folders extends rcube_plugin
|
|
|
|
{
|
2011-07-07 15:52:29 +02:00
|
|
|
public $task = '?(?!login).*';
|
|
|
|
|
2011-10-04 13:19:46 +02:00
|
|
|
public $types = array('mail', 'event', 'journal', 'task', 'note', 'contact', 'configuration');
|
2011-10-27 18:24:04 +02:00
|
|
|
public $mail_types = array('inbox', 'drafts', 'sentitems', 'outbox', 'wastebasket', 'junkemail');
|
2011-05-19 12:40:46 +02:00
|
|
|
private $rc;
|
|
|
|
|
|
|
|
const CTYPE_KEY = '/shared/vendor/kolab/folder-type';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Plugin initialization.
|
|
|
|
*/
|
|
|
|
function init()
|
|
|
|
{
|
|
|
|
$this->rc = rcmail::get_instance();
|
|
|
|
|
|
|
|
// Folder listing hooks
|
|
|
|
$this->add_hook('mailboxes_list', array($this, 'mailboxes_list'));
|
|
|
|
|
|
|
|
// Folder manager hooks
|
|
|
|
$this->add_hook('folder_form', array($this, 'folder_form'));
|
|
|
|
$this->add_hook('folder_update', array($this, 'folder_save'));
|
|
|
|
$this->add_hook('folder_create', array($this, 'folder_save'));
|
2011-07-10 20:21:53 +02:00
|
|
|
$this->add_hook('folder_delete', array($this, 'folder_save'));
|
|
|
|
$this->add_hook('folder_rename', array($this, 'folder_save'));
|
2011-06-15 15:28:13 +02:00
|
|
|
$this->add_hook('folders_list', array($this, 'folders_list'));
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for mailboxes_list hook. Enables type-aware lists filtering.
|
|
|
|
*/
|
|
|
|
function mailboxes_list($args)
|
|
|
|
{
|
|
|
|
if (!$this->metadata_support()) {
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
$filter = $args['filter'];
|
|
|
|
|
|
|
|
// all-folders request, use core method
|
|
|
|
if (!$filter) {
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get folders types
|
2011-10-27 18:24:04 +02:00
|
|
|
$folderdata = $this->get_folder_type_list($args['root'].$args['name'], true);
|
2011-05-19 12:40:46 +02:00
|
|
|
|
|
|
|
if (!is_array($folderdata)) {
|
|
|
|
$args['folders'] = false;
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
$regexp = '/^' . preg_quote($filter, '/') . '(\..+)?$/';
|
|
|
|
|
|
|
|
// In some conditions we can skip LIST command (?)
|
|
|
|
if ($args['mode'] == 'LIST' && $filter != 'mail'
|
|
|
|
&& $args['root'] == '' && $args['name'] == '*'
|
|
|
|
) {
|
2011-10-27 18:24:04 +02:00
|
|
|
foreach ($folderdata as $folder => $type) {
|
|
|
|
if (!preg_match($regexp, $type)) {
|
|
|
|
unset($folderdata[$folder]);
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
$args['folders'] = array_keys($folderdata);
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get folders list
|
|
|
|
if ($args['mode'] == 'LIST') {
|
|
|
|
$args['folders'] = $this->rc->imap->conn->listMailboxes($args['root'], $args['name']);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$args['folders'] = $this->list_subscribed($args['root'], $args['name']);
|
|
|
|
}
|
|
|
|
|
|
|
|
// In case of an error, return empty list
|
|
|
|
if (!is_array($args['folders'])) {
|
|
|
|
$args['folders'] = array();
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Filter folders list
|
|
|
|
foreach ($args['folders'] as $idx => $folder) {
|
2011-10-27 18:24:04 +02:00
|
|
|
$type = $folderdata[$folder];
|
|
|
|
if ($filter == 'mail' && empty($type)) {
|
2011-05-19 12:40:46 +02:00
|
|
|
continue;
|
|
|
|
}
|
2011-10-27 18:24:04 +02:00
|
|
|
if (empty($type) || !preg_match($regexp, $type)) {
|
2011-05-19 12:40:46 +02:00
|
|
|
unset($args['folders'][$idx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
2011-06-15 15:28:13 +02:00
|
|
|
/**
|
|
|
|
* Handler for folders_list hook. Add css classes to folder rows.
|
|
|
|
*/
|
|
|
|
function folders_list($args)
|
|
|
|
{
|
|
|
|
if (!$this->metadata_support()) {
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = $args['table'];
|
|
|
|
|
|
|
|
// get folders types
|
|
|
|
$folderdata = $this->get_folder_type_list('*');
|
|
|
|
|
|
|
|
if (!is_array($folderdata)) {
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add type-based style for table rows
|
|
|
|
// See kolab_folders::folder_class_name()
|
2011-06-23 10:31:45 +02:00
|
|
|
for ($i=1, $cnt=$table->size(); $i<=$cnt; $i++) {
|
2011-06-15 15:28:13 +02:00
|
|
|
$attrib = $table->get_row_attribs($i);
|
|
|
|
$folder = $attrib['foldername']; // UTF7-IMAP
|
2011-10-27 18:24:04 +02:00
|
|
|
$type = $folderdata[$folder];
|
2011-06-15 15:42:58 +02:00
|
|
|
|
|
|
|
if (!$type)
|
|
|
|
$type = 'mail';
|
|
|
|
|
|
|
|
$class_name = self::folder_class_name($type);
|
|
|
|
|
|
|
|
$attrib['class'] = trim($attrib['class'] . ' ' . $class_name);
|
|
|
|
$table->set_row_attribs($attrib, $i);
|
2011-06-15 15:28:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
2011-05-19 12:40:46 +02:00
|
|
|
/**
|
|
|
|
* Handler for folder info/edit form (folder_form hook).
|
|
|
|
* Adds folder type selector.
|
|
|
|
*/
|
|
|
|
function folder_form($args)
|
|
|
|
{
|
|
|
|
if (!$this->metadata_support()) {
|
|
|
|
return $args;
|
|
|
|
}
|
2011-07-07 19:39:34 +02:00
|
|
|
// load translations
|
|
|
|
$this->add_texts('localization/', false);
|
|
|
|
|
|
|
|
// INBOX folder is of type mail.inbox and this cannot be changed
|
|
|
|
if ($args['name'] == 'INBOX') {
|
|
|
|
$args['form']['props']['fieldsets']['settings']['content']['foldertype'] = array(
|
|
|
|
'label' => $this->gettext('folderctype'),
|
|
|
|
'value' => sprintf('%s (%s)', $this->gettext('foldertypemail'), $this->gettext('inbox')),
|
|
|
|
);
|
|
|
|
|
|
|
|
return $args;
|
|
|
|
}
|
2011-05-19 12:40:46 +02:00
|
|
|
|
2011-10-04 13:19:46 +02:00
|
|
|
if ($args['options']['is_root']) {
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
2011-05-19 12:40:46 +02:00
|
|
|
$mbox = strlen($args['name']) ? $args['name'] : $args['parent_name'];
|
2011-07-07 19:39:34 +02:00
|
|
|
|
2011-05-19 12:40:46 +02:00
|
|
|
if (isset($_POST['_ctype'])) {
|
|
|
|
$new_ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST));
|
2011-07-07 19:39:34 +02:00
|
|
|
$new_subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST));
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get type of the folder or the parent
|
|
|
|
if (strlen($mbox)) {
|
|
|
|
list($ctype, $subtype) = $this->get_folder_type($mbox);
|
2011-07-07 15:50:50 +02:00
|
|
|
if (strlen($args['parent_name']) && $subtype == 'default')
|
|
|
|
$subtype = ''; // there can be only one
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$ctype) {
|
|
|
|
$ctype = 'mail';
|
|
|
|
}
|
|
|
|
|
2011-08-19 10:13:14 +02:00
|
|
|
// Don't allow changing type of shared folder, according to ACL
|
|
|
|
if (strlen($mbox)) {
|
|
|
|
$options = $this->rc->imap->mailbox_info($mbox);
|
|
|
|
if ($options['namespace'] != 'personal' && !in_array('a', $options['rights'])) {
|
|
|
|
if (in_array($ctype, $this->types))
|
|
|
|
$value = $this->gettext('foldertype'.$ctype);
|
|
|
|
else
|
|
|
|
$value = $ctype;
|
|
|
|
if ($subtype)
|
|
|
|
$value .= ' ('. ($subtype == 'default' ? $this->gettext('default') : $subtype) .')';
|
|
|
|
|
|
|
|
$args['form']['props']['fieldsets']['settings']['content']['foldertype'] = array(
|
|
|
|
'label' => $this->gettext('folderctype'),
|
|
|
|
'value' => $value,
|
|
|
|
);
|
|
|
|
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-07 19:39:34 +02:00
|
|
|
// Add javascript script to the client
|
2011-05-19 12:40:46 +02:00
|
|
|
$this->include_script('kolab_folders.js');
|
|
|
|
|
|
|
|
// build type SELECT fields
|
|
|
|
$type_select = new html_select(array('name' => '_ctype', 'id' => '_ctype'));
|
|
|
|
$sub_select = new html_select(array('name' => '_subtype', 'id' => '_subtype'));
|
|
|
|
|
|
|
|
foreach ($this->types as $type) {
|
|
|
|
$type_select->add($this->gettext('foldertype'.$type), $type);
|
|
|
|
}
|
|
|
|
// add non-supported type
|
|
|
|
if (!in_array($ctype, $this->types)) {
|
|
|
|
$type_select->add($ctype, $ctype);
|
|
|
|
}
|
|
|
|
|
|
|
|
$sub_select->add('', '');
|
|
|
|
$sub_select->add($this->gettext('default'), 'default');
|
|
|
|
foreach ($this->mail_types as $type) {
|
|
|
|
$sub_select->add($this->gettext($type), $type);
|
|
|
|
}
|
|
|
|
|
|
|
|
$args['form']['props']['fieldsets']['settings']['content']['foldertype'] = array(
|
|
|
|
'label' => $this->gettext('folderctype'),
|
|
|
|
'value' => $type_select->show(isset($new_ctype) ? $new_ctype : $ctype)
|
|
|
|
. $sub_select->show(isset($new_subtype) ? $new_subtype : $subtype),
|
|
|
|
);
|
|
|
|
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for folder update/create action (folder_update/folder_create hook).
|
|
|
|
*/
|
|
|
|
function folder_save($args)
|
|
|
|
{
|
2011-07-10 20:21:53 +02:00
|
|
|
// Folder actions from folders list
|
|
|
|
if (empty($args['record'])) {
|
|
|
|
// Just clear Horde folders cache and return
|
|
|
|
$this->clear_folders_cache();
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Folder create/update with form
|
2011-06-17 10:04:00 +02:00
|
|
|
$ctype = trim(get_input_value('_ctype', RCUBE_INPUT_POST));
|
|
|
|
$subtype = trim(get_input_value('_subtype', RCUBE_INPUT_POST));
|
2011-06-15 15:28:13 +02:00
|
|
|
$mbox = $args['record']['name'];
|
|
|
|
$old_mbox = $args['record']['oldname'];
|
|
|
|
$subscribe = $args['record']['subscribe'];
|
2011-05-19 12:40:46 +02:00
|
|
|
|
|
|
|
if (empty($ctype)) {
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
2011-07-07 15:50:50 +02:00
|
|
|
// load translations
|
|
|
|
$this->add_texts('localization/', false);
|
|
|
|
|
|
|
|
// Skip folder creation/rename in core
|
|
|
|
// @TODO: Maybe we should provide folder_create_after and folder_update_after hooks?
|
|
|
|
// Using create_mailbox/rename_mailbox here looks bad
|
|
|
|
$args['abort'] = true;
|
|
|
|
|
|
|
|
// There can be only one default folder of specified type
|
2011-05-19 12:40:46 +02:00
|
|
|
if ($subtype == 'default') {
|
2011-07-07 15:50:50 +02:00
|
|
|
$default = $this->get_default_folder($ctype);
|
|
|
|
|
|
|
|
if ($default !== null && $old_mbox != $default) {
|
|
|
|
$args['result'] = false;
|
|
|
|
$args['message'] = $this->gettext('defaultfolderexists');
|
|
|
|
return $args;
|
|
|
|
}
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
// Subtype sanity-checks
|
2011-06-15 15:28:13 +02:00
|
|
|
else if ($subtype && ($ctype != 'mail' || !in_array($subtype, $this->mail_types))) {
|
2011-05-19 12:40:46 +02:00
|
|
|
$subtype = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
$ctype .= $subtype ? '.'.$subtype : '';
|
|
|
|
|
|
|
|
// Create folder
|
|
|
|
if (!strlen($old_mbox)) {
|
2011-06-15 15:28:13 +02:00
|
|
|
// By default don't subscribe to non-mail folders
|
|
|
|
if ($subscribe)
|
2011-06-15 15:42:58 +02:00
|
|
|
$subscribe = (bool) preg_match('/^mail/', $ctype);
|
2011-06-15 15:28:13 +02:00
|
|
|
|
|
|
|
$result = $this->rc->imap->create_mailbox($mbox, $subscribe);
|
2011-05-19 12:40:46 +02:00
|
|
|
// Set folder type
|
|
|
|
if ($result) {
|
|
|
|
$this->set_folder_type($mbox, $ctype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Rename folder
|
|
|
|
else {
|
|
|
|
if ($old_mbox != $mbox) {
|
|
|
|
$result = $this->rc->imap->rename_mailbox($old_mbox, $mbox);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$result = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($result) {
|
|
|
|
list($oldtype, $oldsubtype) = $this->get_folder_type($mbox);
|
|
|
|
$oldtype .= $oldsubtype ? '.'.$oldsubtype : '';
|
|
|
|
|
|
|
|
if ($ctype != $oldtype) {
|
|
|
|
$this->set_folder_type($mbox, $ctype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-10 20:21:53 +02:00
|
|
|
// Clear Horde folders cache
|
|
|
|
if ($result) {
|
|
|
|
$this->clear_folders_cache();
|
|
|
|
}
|
|
|
|
|
2011-06-15 15:28:13 +02:00
|
|
|
$args['record']['class'] = self::folder_class_name($ctype);
|
|
|
|
$args['record']['subscribe'] = $subscribe;
|
2011-05-19 12:40:46 +02:00
|
|
|
$args['result'] = $result;
|
|
|
|
|
|
|
|
return $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
|
|
|
|
*
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
function metadata_support()
|
|
|
|
{
|
|
|
|
return $this->rc->imap->get_capability('METADATA') ||
|
|
|
|
$this->rc->imap->get_capability('ANNOTATEMORE') ||
|
|
|
|
$this->rc->imap->get_capability('ANNOTATEMORE2');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
|
|
|
|
*
|
|
|
|
* @param string $folder Folder name
|
|
|
|
*
|
|
|
|
* @return array Folder content-type
|
|
|
|
*/
|
|
|
|
function get_folder_type($folder)
|
|
|
|
{
|
|
|
|
$folderdata = $this->rc->imap->get_metadata($folder, array(kolab_folders::CTYPE_KEY));
|
|
|
|
|
|
|
|
return explode('.', $folderdata[$folder][kolab_folders::CTYPE_KEY]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets folder content-type.
|
|
|
|
*
|
|
|
|
* @param string $folder Folder name
|
|
|
|
* @param string $type Content type
|
|
|
|
*
|
|
|
|
* @return boolean True on success
|
|
|
|
*/
|
|
|
|
function set_folder_type($folder, $type='mail')
|
|
|
|
{
|
|
|
|
return $this->rc->imap->set_metadata($folder, array(kolab_folders::CTYPE_KEY => $type));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns list of subscribed folders (directly from IMAP server)
|
|
|
|
*
|
|
|
|
* @param string $root Optional root folder
|
|
|
|
* @param string $name Optional name pattern
|
|
|
|
*
|
|
|
|
* @return array List of mailboxes/folders
|
|
|
|
*/
|
|
|
|
private function list_subscribed($root='', $name='*')
|
|
|
|
{
|
|
|
|
$imap = $this->rc->imap;
|
|
|
|
|
|
|
|
// Code copied from rcube_imap::_list_mailboxes()
|
|
|
|
// Server supports LIST-EXTENDED, we can use selection options
|
|
|
|
// #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED
|
|
|
|
if (!$this->rc->config->get('imap_force_lsub') && $imap->get_capability('LIST-EXTENDED')) {
|
|
|
|
// This will also set mailbox options, LSUB doesn't do that
|
|
|
|
$a_folders = $imap->conn->listMailboxes($root, $name,
|
|
|
|
NULL, array('SUBSCRIBED'));
|
|
|
|
|
|
|
|
// remove non-existent folders
|
2011-08-18 11:37:28 +02:00
|
|
|
if (is_array($a_folders) && $name = '*') {
|
2011-05-19 12:40:46 +02:00
|
|
|
foreach ($a_folders as $idx => $folder) {
|
|
|
|
if ($imap->conn->data['LIST'] && ($opts = $imap->conn->data['LIST'][$folder])
|
|
|
|
&& in_array('\\NonExistent', $opts)
|
|
|
|
) {
|
2011-08-18 11:37:28 +02:00
|
|
|
$imap->conn->unsubscribe($folder);
|
2011-05-19 12:40:46 +02:00
|
|
|
unset($a_folders[$idx]);
|
2011-08-18 11:37:28 +02:00
|
|
|
}
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// retrieve list of folders from IMAP server using LSUB
|
|
|
|
else {
|
|
|
|
$a_folders = $imap->conn->listSubscribed($root, $name);
|
2011-08-18 11:37:28 +02:00
|
|
|
|
|
|
|
// unsubscribe non-existent folders, remove from the list
|
|
|
|
if (is_array($a_folders) && $name == '*') {
|
|
|
|
foreach ($a_folders as $idx => $folder) {
|
|
|
|
if ($imap->conn->data['LIST'] && ($opts = $imap->conn->data['LIST'][$folder])
|
|
|
|
&& in_array('\\Noselect', $opts)
|
|
|
|
) {
|
|
|
|
// Some servers returns \Noselect for existing folders
|
|
|
|
if (!$imap->mailbox_exists($folder)) {
|
|
|
|
$imap->conn->unsubscribe($folder);
|
|
|
|
unset($a_folders[$idx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-19 12:40:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $a_folders;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns list of folder(s) type(s)
|
|
|
|
*
|
2011-10-27 18:24:04 +02:00
|
|
|
* @param string $mbox Folder name or pattern
|
|
|
|
* @param bool $defaults Enables creation of configured default folders
|
2011-05-19 12:40:46 +02:00
|
|
|
*
|
|
|
|
* @return array List of folders data, indexed by folder name
|
|
|
|
*/
|
2011-10-27 18:24:04 +02:00
|
|
|
function get_folder_type_list($mbox, $create_defaults = false)
|
2011-05-19 12:40:46 +02:00
|
|
|
{
|
|
|
|
// Use mailboxes. prefix so the cache will be cleared by core
|
|
|
|
// together with other mailboxes-related cache data
|
2011-10-27 18:24:04 +02:00
|
|
|
$cache_key = 'mailboxes.folder-type.'.$mbox;
|
2011-05-19 12:40:46 +02:00
|
|
|
|
|
|
|
// get cached metadata
|
|
|
|
$metadata = $this->rc->imap->get_cache($cache_key);
|
|
|
|
|
2011-10-27 18:24:04 +02:00
|
|
|
if (!is_array($metadata)) {
|
|
|
|
$metadata = $this->rc->imap->get_metadata($mbox, kolab_folders::CTYPE_KEY);
|
|
|
|
$need_update = true;
|
|
|
|
}
|
2011-05-19 12:40:46 +02:00
|
|
|
|
|
|
|
if (!is_array($metadata)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-10-27 18:24:04 +02:00
|
|
|
// make the result more flat
|
|
|
|
if ($need_update) {
|
|
|
|
$metadata = array_map('implode', $metadata);
|
|
|
|
}
|
|
|
|
|
|
|
|
// create default folders if needed
|
|
|
|
if ($create_defaults) {
|
|
|
|
$this->create_default_folders($metadata, $cache_key);
|
|
|
|
}
|
|
|
|
|
2011-05-19 12:40:46 +02:00
|
|
|
// write mailboxlist to cache
|
2011-10-27 18:24:04 +02:00
|
|
|
if ($need_update) {
|
|
|
|
$this->rc->imap->update_cache($cache_key, $metadata);
|
|
|
|
}
|
2011-05-19 12:40:46 +02:00
|
|
|
|
|
|
|
return $metadata;
|
|
|
|
}
|
|
|
|
|
2011-07-07 15:50:50 +02:00
|
|
|
/**
|
|
|
|
* Returns the name of default folder
|
|
|
|
*
|
|
|
|
* @param string $type Folder type
|
|
|
|
*
|
|
|
|
* @return string Folder name
|
|
|
|
*/
|
|
|
|
function get_default_folder($type)
|
|
|
|
{
|
|
|
|
$folderdata = $this->get_folder_type_list('*');
|
|
|
|
|
|
|
|
if (!is_array($folderdata)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$type .= '.default';
|
|
|
|
$namespace = $this->rc->imap->get_namespace();
|
|
|
|
|
2011-10-27 18:24:04 +02:00
|
|
|
// get all folders of specified type
|
|
|
|
$folderdata = array_intersect($folderdata, array($type));
|
|
|
|
unset($folders[0]);
|
2011-07-07 15:50:50 +02:00
|
|
|
|
2011-10-27 18:24:04 +02:00
|
|
|
foreach ($folderdata as $folder => $data) {
|
|
|
|
// check if folder is in personal namespace
|
|
|
|
foreach (array('shared', 'other') as $nskey) {
|
|
|
|
if (!empty($namespace[$nskey])) {
|
|
|
|
foreach ($namespace[$nskey] as $ns) {
|
|
|
|
if ($ns[0] && substr($folder, 0, strlen($ns[0])) == $ns[0]) {
|
|
|
|
continue 3;
|
|
|
|
}
|
2011-07-07 15:50:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// There can be only one default folder of specified type
|
|
|
|
return $folder;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2011-06-15 15:28:13 +02:00
|
|
|
/**
|
|
|
|
* Returns CSS class name for specified folder type
|
|
|
|
*
|
|
|
|
* @param string $type Folder type
|
|
|
|
*
|
|
|
|
* @return string Class name
|
|
|
|
*/
|
|
|
|
static function folder_class_name($type)
|
|
|
|
{
|
|
|
|
list($ctype, $subtype) = explode('.', $type);
|
|
|
|
|
|
|
|
$class[] = 'type-' . ($ctype ? $ctype : 'mail');
|
|
|
|
|
2011-06-15 15:31:29 +02:00
|
|
|
if ($subtype)
|
|
|
|
$class[] = 'subtype-' . $subtype;
|
2011-06-15 15:28:13 +02:00
|
|
|
|
|
|
|
return implode(' ', $class);
|
|
|
|
}
|
2011-07-10 20:21:53 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Clear Horde's folder cache. See Kolab_List::singleton().
|
|
|
|
*/
|
|
|
|
private function clear_folders_cache()
|
|
|
|
{
|
|
|
|
unset($_SESSION['horde_session_objects']['kolab_folderlist']);
|
|
|
|
}
|
2011-10-27 18:24:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates default folders if they doesn't exist
|
|
|
|
*/
|
|
|
|
private function create_default_folders(&$folderdata, $cache_key = null)
|
|
|
|
{
|
|
|
|
$namespace = $this->rc->imap->get_namespace();
|
|
|
|
$defaults = array();
|
|
|
|
$need_update = false;
|
|
|
|
|
|
|
|
// Find personal namespace prefix
|
|
|
|
if (is_array($namespace['personal']) && count($namespace['personal']) == 1) {
|
|
|
|
$prefix = $namespace['personal'][0][0];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$prefix = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->load_config();
|
|
|
|
|
|
|
|
// get configured defaults
|
|
|
|
foreach ($this->types as $type) {
|
|
|
|
$subtypes = $type == 'mail' ? $this->mail_types : array('default');
|
|
|
|
foreach ($subtypes as $subtype) {
|
|
|
|
$opt_name = 'kolab_folders_' . $type . '_' . $subtype;
|
|
|
|
if ($folder = $this->rc->config->get($opt_name)) {
|
|
|
|
// convert configuration value to UTF7-IMAP charset
|
|
|
|
$folder = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP');
|
|
|
|
// and namespace prefix if needed
|
|
|
|
if ($prefix && strpos($folder, $prefix) === false && $folder != 'INBOX') {
|
|
|
|
$folder = $prefix . $folder;
|
|
|
|
}
|
|
|
|
$defaults[$type . '.' . $subtype] = $folder;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// find default folders
|
|
|
|
foreach ($defaults as $type => $foldername) {
|
|
|
|
// folder exists, do nothing
|
|
|
|
if (!empty($folderdata[$foldername])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// special case, need to set type only
|
|
|
|
if ($foldername == 'INBOX' || $type == 'mail.inbox') {
|
|
|
|
$this->set_folder_type($foldername, 'mail.inbox');
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get all folders of specified type
|
|
|
|
$folders = array_intersect($folderdata, array($type));
|
|
|
|
unset($folders[0]);
|
|
|
|
|
|
|
|
// find folders in personal namespace
|
|
|
|
foreach ($folders as $folder) {
|
|
|
|
if ($folder) {
|
|
|
|
foreach (array('shared', 'other') as $nskey) {
|
|
|
|
if (!empty($namespace[$nskey])) {
|
|
|
|
foreach ($namespace[$nskey] as $ns) {
|
|
|
|
if ($ns[0] && substr($folder, 0, strlen($ns[0])) == $ns[0]) {
|
|
|
|
continue 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// got folder in personal namespace
|
|
|
|
continue 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
list($type1, $type2) = explode('.', $type);
|
|
|
|
|
|
|
|
// create folder
|
|
|
|
if ($type1 != 'mail' || !$this->rc->imap->mailbox_exists($foldername)) {
|
|
|
|
$this->rc->imap->create_mailbox($foldername, $type1 == 'mail');
|
|
|
|
}
|
|
|
|
|
|
|
|
// set type
|
|
|
|
$result = $this->set_folder_type($foldername, $type);
|
|
|
|
|
|
|
|
// add new folder to the result
|
|
|
|
if ($result) {
|
|
|
|
$folderdata[$foldername] = $type;
|
|
|
|
$need_update = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// update cache
|
|
|
|
if ($need_update && $cache_key) {
|
|
|
|
$this->rc->imap->update_cache($cache_key, $folderdata);
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 15:28:13 +02:00
|
|
|
}
|