On Wed, 4 Jun 2003, Alexander Gr�fe wrote:
>Hi, Andy.
>I don't think the slowdown we experienced with Squirrelmail is caused by
>a slower MIME parser, because it happens early on, when listing all
>subscribed folders.
Alexander, this patch for 1.1.8 makes LSUB return all mailbox flags just
like LIST does. Please try it and see if it solves your problem. The patch
has not been extensively tested.
Andreas :-)
diff -u -r1.17 operator-lsub.cc
--- src/operator-lsub.cc 5 May 2003 18:18:30 -0000 1.17
+++ src/operator-lsub.cc 9 Jun 2003 14:45:29 -0000
@@ -43,14 +43,20 @@
#include "parsers/imap/recursivedescent/recursivedescent.h"
#include "io/io.h"
+#include "mailbox/mailbox.h"
#include "util/convert.h"
-
#include "util/regmatch.h"
#include "session.h"
#include "depot.h"
#include "operators.h"
+namespace {
+ const int DIR_SELECT = 0x01;
+ const int DIR_MARKED = 0x02;
+ const int DIR_NOINFERIORS = 0x04;
+}
+
using namespace ::std;
using namespace Binc;
@@ -81,26 +87,126 @@
{
Session &session = Session::getInstance();
IO &com = IOFactory::getInstance().get(1);
+ const char delim = depot.getDelimiter();
+ // remove leading or trailing delimiter in wildcard
string wildcard = command.getListMailbox();
- if (wildcard != "" && wildcard[0] == depot.getDelimiter())
- wildcard = wildcard.substr(1);
+ trim(wildcard, string(&delim, 1));
+ // convert wildcard to regular expression
const string ®ex = toRegex(wildcard, depot.getDelimiter());
+
+ // remove leading or trailing delimiter in reference
string ref = command.getMailbox();
- if (ref != "" && ref[0] == depot.getDelimiter())
- ref = ref.substr(1);
+ trim(ref, string(&delim, 1));
+
+ // a map from mailbox name to flags
+ map<string, int> mailboxes;
+
+ // read through all entries in depository.
+ for (Depot::iterator i = depot.begin("."); i != depot.end(); ++i) {
+ const string path = *i;
+ const string mpath = depot.filenameToMailbox(path);
+ Mailbox *m = 0;
+
+ // skip entries that are not identified as mailboxes
+ if ((m = depot.get(mpath)) == 0)
+ continue;
+
+ // convert file name to mailbox name. skip it if there is no
+ // corresponding mailbox name.
+ string tmp = toCanonMailbox(depot.filenameToMailbox(path));
+ trim(tmp, string(&delim, 1));
+ if (tmp == "") continue;
+ else {
+ // inherit flags that were already set for this mailbox.
+ int flags = DIR_SELECT;
+ if (m->isMarked(path)) flags |= DIR_MARKED;
+ if (mailboxes.find(tmp) != mailboxes.end()) flags |= mailboxes[tmp];
+ mailboxes[tmp] = flags;
+ }
+
+ // now add all superior mailboxes with no flags set if not
+ // added already.
+ string::size_type pos = tmp.rfind(delim);
+ while (pos != string::npos) {
+ tmp = tmp.substr(0, pos);
+ trim(tmp, string(&delim, 1));
+
+ if (mailboxes.find(tmp) == mailboxes.end())
+ mailboxes[tmp] = 0;
+
+ pos = tmp.rfind(delim);
+ }
+ }
+
+ // find leaf nodes O(N^2)
+ map<string, int>::iterator i;
+ for (i = mailboxes.begin(); i != mailboxes.end(); ++i) {
+ string mailbox = i->first;
+ mailbox += delim;
+
+ bool leaf = true;
+ map<string, int>::const_iterator j;
+ for (j = mailboxes.begin(); j != mailboxes.end(); ++j) {
+ string::size_type pos = j->first.rfind(delim);
+ if (pos == string::npos) continue;
+
+ string base = j->first.substr(0, pos + 1);
+
+ if (mailbox == base) {
+ leaf = false;
+ break;
+ }
+ }
+
+ if (leaf)
+ i->second |= DIR_NOINFERIORS;
+ }
vector<string> &subscribed = session.subscribed;
sort(subscribed.begin(), subscribed.end());
- for (vector<string>::const_iterator i = subscribed.begin();
- i != subscribed.end(); ++i) {
- if (ref == "" || ((ref.length() < (*i).length())
- && ((*i).substr(0, ref.length()) == ref)))
- if (regexMatch(*i, regex) == 0)
- com << "*" << " LSUB () \"" << depot.getDelimiter() << "\" "
- << toImapString(*i) << endl;
+ // finally, print all mailbox entries with flags.
+ for (i = mailboxes.begin(); i != mailboxes.end(); ++i) {
+ if (ref == "" || ((ref.length() <= i->first.length())
+ && (i->first.substr(0, ref.length()) == ref)))
+ if (regexMatch(i->first, regex) == 0) {
+ bool match = false;
+ for (vector<string>::const_iterator j = subscribed.begin();
+ j != subscribed.end(); ++j)
+ if (*j == i->first) {
+ match = true;
+ break;
+ }
+ if (!match)
+ continue;
+
+ com << "* LSUB (";
+ string sep = "";
+
+ int flags = i->second;
+ bool noselect = false;
+ if (!(flags & DIR_SELECT)) {
+ com << sep << "\\Noselect";
+ sep = " ";
+ noselect = true;
+ }
+
+ if (!noselect) {
+ if (flags & DIR_MARKED)
+ com << sep << "\\Marked";
+ else
+ com << sep << "\\UnMarked";
+ sep = " ";
+ }
+
+ if (flags & DIR_NOINFERIORS)
+ com << sep << "\\Noinferiors";
+
+ com << ") \"" << depot.getDelimiter() << "\" "
+ << toImapString(i->first) << endl;
+ }
}
}