From a5a4bf46bd2e579e828989563c120f9ab2b28a32 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Mon, 25 Oct 2010 08:39:36 -0400
Subject: [PATCH] - Add basic IMAP LIST's \Noselect option support (mark unselectable folders as virtual, etc.)

---
 CHANGELOG                                 |    1 
 program/include/main.inc                  |    8 ++++
 program/include/rcube_imap.php            |   25 ++++++++++++
 program/steps/settings/manage_folders.inc |   26 ++++++++----
 program/include/rcube_imap_generic.php    |   15 ++++++-
 5 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 48daaa1..30868f1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -48,6 +48,7 @@
 - Add support for IMAP proxy authentication (#1486690)
 - Add support for AUTH=DIGEST-MD5 in IMAP (RFC 2831)
 - Fix parent folder with unread subfolder not bold when message is open (#1487078)
+- Add basic IMAP LIST's \Noselect option support
 
 RELEASE 0.4.2
 -------------
diff --git a/program/include/main.inc b/program/include/main.inc
index 46e45f7..7e96233 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1332,6 +1332,8 @@
  */
 function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
 {
+  global $RCMAIL;
+
   $pos = strpos($folder, $delm);
 
   if ($pos !== false) {
@@ -1354,6 +1356,12 @@
 
   $path .= $currentFolder;
 
+  // Check \Noselect option
+  if (!$virtual) {
+    $opts = $RCMAIL->imap->mailbox_options($path);
+    $virtual = in_array('\\Noselect', $opts);
+  }
+
   if (!isset($arrFolders[$currentFolder])) {
     $arrFolders[$currentFolder] = array(
       'id' => $path,
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 7fbff37..46427d6 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -3121,6 +3121,31 @@
 
 
     /**
+     * Gets folder options from LIST/LSUB response, e.g. \Noselect, \Noinferiors
+     *
+     * @param string $mbox_name Folder name
+     *
+     * @return array Options list
+     */
+    function mailbox_options($mbox_name)
+    {
+        $mbox = $this->mod_mailbox($mbox_name);
+
+        if ($mbox == 'INBOX') {
+            return array();
+        }
+
+        if (!is_array($this->conn->data['LIST']) || !is_array($this->conn->data['LIST'][$mbox])) {
+            $this->conn->listMailboxes($this->mod_mailbox(''), $mbox_name);
+        }
+
+        $opts = $this->conn->data['LIST'][$mbox];
+
+        return is_array($opts) ? $opts : array();
+    }
+
+
+    /**
      * Get message header names for rcube_imap_generic::fetchHeader(s)
      *
      * @return string Space-separated list of header names
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 9009d12..d51b8cf 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -857,6 +857,12 @@
 		    return true;
 	    }
 
+        if (is_array($this->data['LIST']) && is_array($opts = $this->data['LIST'][$mailbox])) {
+            if (in_array('\\Noselect', $opts)) {
+                return false;
+            }
+        }
+
         list($code, $response) = $this->execute('SELECT', array($this->escape($mailbox)));
 
         if ($code == self::ERROR_OK) {
@@ -1861,11 +1867,11 @@
 		if (empty($mailbox)) {
 	        $mailbox = '*';
 	    }
-/*
+
 	    if (empty($ref) && $this->prefs['rootdir']) {
 	        $ref = $this->prefs['rootdir'];
 	    }
-*/
+
         $args = array($this->escape($ref), $this->escape($mailbox));
 
         if (!empty($status_opts) && $this->getCapability('LIST-STATUS')) {
@@ -1884,12 +1890,17 @@
                 // * LIST (<options>) <delimiter> <mailbox>
                 if (!$lstatus || $cmd == 'LIST' || $cmd == 'LSUB') {
                     list($opts, $delim, $folder) = $this->tokenizeResponse($response, 3);
+
                     if (!$lstatus) {
            			    $folders[] = $folder;
                     }
                     else {
                         $folders[$folder] = array();
                     }
+
+                    if ($cmd == 'LIST') {
+                        $this->data['LIST'][$folder] = $opts;
+                    }
                 }
                 // * STATUS <mailbox> (<result>)
                 else if ($cmd == 'STATUS') {
diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc
index 4a0bb69..1dd459a 100644
--- a/program/steps/settings/manage_folders.inc
+++ b/program/steps/settings/manage_folders.inc
@@ -221,7 +221,7 @@
   $a_subscribed = $IMAP->list_mailboxes();
   $a_threaded = $a_threaded_copy = $RCMAIL->config->get('message_threading', array()); 
   $delimiter = $IMAP->get_hierarchy_delimiter();
-  $a_js_folders = $seen_folders = $list_folders = array();
+  $a_js_folders = $seen = $list_folders = array();
 
   // pre-process folders list
   foreach ($a_unsubscribed as $i => $folder) {
@@ -233,11 +233,11 @@
     // add any necessary "virtual" parent folders
     if ($parent_folder && !$seen[$parent_folder]) {
       for ($i=1; $i<=$level; $i++) {
-	$ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
-	if ($ancestor_folder && !$seen[$ancestor_folder]++) {
-	  $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP');
-	  $list_folders[] = array('id' => $ancestor_folder, 'name' => $ancestor_name, 'level' => $i-1, 'virtual' => true);
-	}
+	    $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
+	    if ($ancestor_folder && !$seen[$ancestor_folder]++) {
+	      $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP');
+	      $list_folders[] = array('id' => $ancestor_folder, 'name' => $ancestor_name, 'level' => $i-1, 'virtual' => true);
+	    }
       }
     }
     
@@ -246,6 +246,8 @@
     $list_folders[] = array('id' => $folder, 'name' => $name, 'level' => $level);
     $seen[$folder]++;
   }
+
+  unset($seen);
 
   // remove 'message_threading' option for not existing folders
   if ($a_threaded_copy) {
@@ -285,15 +287,21 @@
     $display_folder = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $folder['level']) . ($protected ? rcmail_localize_foldername($folder['id']) : $folder['name']);
     $folder_utf8 = rcube_charset_convert($folder['id'], 'UTF7-IMAP');
     
-    if ($folder['virtual'])
+    if ($folder['virtual']) {
       $classes[] = 'virtual';
-    
+    }
+
+    if (!$protected) {
+      $opts = $IMAP->mailbox_options($folder['id']);
+      $noselect = in_array('\\Noselect', $opts);
+    }
+
     $table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes)));
     
     $table->add('name', Q($display_folder));
     $table->add('msgcount', ($folder['virtual'] ? '' : $IMAP->messagecount($folder['id'], 'ALL', false, false)));
     $table->add('subscribed', $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''),
-      array('value' => $folder_utf8, 'disabled' => $protected ? 'disabled' : '')));
+      array('value' => $folder_utf8, 'disabled' => ($protected || $noselect) ? 'disabled' : '')));
     if ($threading_supported) {
       $table->add('threaded', $folder['virtual'] ? '' :
             $checkbox_threaded->show(($threaded ? $folder_utf8 : ''), array('value' => $folder_utf8)));

--
Gitblit v1.9.1