OK found the reversal - the file timestamps were messed up. The
attached should be the right way round and easier to apply.
Jim
On 11/04/2015 21:32, NSS Ltd wrote:
> Hi Arnt,
>
> OK, I've attached a first draft patch set for the status return. I'm
> emphasizing draft/in-progress.
>
> This patch set also includes my previous patches and code for the
> annotate stuff which is probably redundant so it may be a good idea to
> look over and excise the annotation elements (the patch set may not be
> complete for those as there were some new files too).
>
> The patch set looks reversed to me, so careful using patch to apply it
> and using the reverse option looks necessary.
>
> I've done some basic tests but I don't have a full test set handy to
> properly validate this. I'm hoping by giving you the patch you can run
> it through your test/validation harness (with added cases) ?
>
> Rather than use the id directly, I opted to add a column to mailboxes of
> type uuid (called guid) and generate uuids via postgresql. This way the
> values are non-deterministic which I think may be better than allowing
> someone to predict the UUID for a mailbox and hence walk through them
> (i.e. my feeling is this approach is more secure).
>
> So mailboxes table is :
>
> Table "public.mailboxes"
> Column | Type |
> Modifiers
> --------------+---------+--------------------------------------------------------
> id | integer | not null default
> nextval('mailboxes_id_seq'::regclass)
> name | text | not null
> owner | integer |
> uidnext | integer | not null default 1
> nextmodseq | bigint | not null default 1
> first_recent | integer | not null default 1
> uidvalidity | integer | not null default 1
> deleted | boolean | not null default false
> guid | uuid | not null default uuid_generate_v4() <--- NEW
> COLUMN
>
> Later (>9.3) postresql has some different uuid generation functions but
> I'm using 9.3 here.
>
> This one is a work in progress.
>
> Of course, I also found SOGo uses additional extensions - VANISHED - for
> fetching a message, so looks like that also needs more patching :
>
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2/187 First line: 180 UID
> FETCH 1:* (UID) (CHANGEDSINCE 1 VANISHED)
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2 IMAP::runCommands, 1 commands
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2/187 Execution time 1ms
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2/187 Finished
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2 IMAP::runCommands, 1 commands
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2/187 Retired
> Apr 11 14:35:55 email Archiveopteryx: 663/2/2/187 180 BAD Unknown fetch
> modifier: vanished
>
> Jim
>
Only in aox-jim: AOX
Only in aox-jim/aox: buildinfo.inc
diff -wur aox-master/aox/db.cpp aox-jim/aox/db.cpp
--- aox-master/aox/db.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/aox/db.cpp 2015-04-11 08:50:12.579422000 -0400
@@ -723,6 +723,9 @@
case Column::Timestamp:
s.append( "(timestamptz)" );
break;
+ case Column::Uuid:
+ s.append( "(uuid)");
+ break;
case Column::Null:
s.append( "null" );
break;
Only in aox-jim: bin
Only in aox-jim: build
diff -wur aox-master/core/estring.h aox-jim/core/estring.h
--- aox-master/core/estring.h 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/core/estring.h 2014-07-06 12:35:16.379058000 -0400
@@ -40,6 +40,7 @@
EString & operator=( const EString & );
EString & operator=( const char * );
EString & operator+=( const EString & str ) { append( str ); return *this;
}
+ EString & operator+=( const int64 & num ) { appendNumber(num); return
*this; }
void operator delete( void * );
Only in aox-jim/db: downgrades.inc
diff -wur aox-master/db/pgmessage.cpp aox-jim/db/pgmessage.cpp
--- aox-master/db/pgmessage.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/db/pgmessage.cpp 2015-04-11 09:16:33.295422000 -0400
@@ -8,6 +8,7 @@
#include "buffer.h"
#include "query.h"
+#include "stdio.h"
static bool haveAskedForCitext;
static int citextOid;
@@ -189,6 +190,53 @@
return s;
}
+EString PgServerMessage::decodeUUID( uint x ) {
+ EString s = "";
+
+ if (16 != x) {
+ log("uuid decode should request 16 bytes but instead requested
" + x );
+ throw Syntax;
+ }
+
+ uint32 data1 = ( (*buf)[0] << 24 ) |
+ ( (*buf)[1] << 16 ) |
+ ( (*buf)[2] << 8 ) |
+ ( (*buf)[3] );
+ buf->remove( 4 );
+ n += 4;
+
+ uint32 data2 = ((*buf)[0] << 8) | (*buf)[1];
+ buf->remove( 2 );
+ n += 2;
+
+ uint32 data3 = ((*buf)[0] << 8) | (*buf)[1];
+ buf->remove( 2 );
+ n += 2;
+
+ uint32 data4 = ((*buf)[0] << 8) | (*buf)[1];
+ buf->remove( 2 );
+ n += 2;
+
+ uint32 data5 = ((*buf)[0] << 8) | (*buf)[1];
+ buf->remove( 2 );
+ n += 2;
+
+
+ uint32 data6 = ( (*buf)[0] << 24 ) |
+ ( (*buf)[1] << 16 ) |
+ ( (*buf)[2] << 8 ) |
+ ( (*buf)[3] );
+ buf->remove( 4 );
+ n += 4;
+
+ char result[37];
+ sprintf( result, "%08x-%04x-%04x-%04x-%04x%08x", data1, data2, data3,
data4, data5, data6);
+
+ s = result;
+
+ return s;
+}
+
/*! This function is used by subclasses to assert that they have decoded
the entire contents of the message. If the size of the decoded data
@@ -898,6 +946,9 @@
case 1184:
cv->type = Column::Timestamp;
break;
+ case 2950:
+ cv->type = Column::Uuid;
+ break;
default:
if ( it->type == ::citextOid ) { // CITEXT
cv->type = Column::Bytes;
@@ -978,6 +1029,9 @@
case Column::Timestamp:
cv->s = decodeByten( length );
break;
+ case Column::Uuid:
+ cv->s = decodeUUID( length );
+ break;
case Column::Null:
// nothing needed
break;
diff -wur aox-master/db/pgmessage.h aox-jim/db/pgmessage.h
--- aox-master/db/pgmessage.h 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/db/pgmessage.h 2015-04-11 07:50:20.871422000 -0400
@@ -33,6 +33,7 @@
char decodeByte();
EString decodeString();
EString decodeByten( uint );
+ EString decodeUUID(uint);
void end();
};
Only in aox-jim/db: privileges.inc
diff -wur aox-master/db/query.cpp aox-jim/db/query.cpp
--- aox-master/db/query.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/db/query.cpp 2015-04-11 09:20:29.359422000 -0400
@@ -855,6 +855,19 @@
return c->bi;
}
+/*! Returns the string value of the column named \a f i if it exists
+ and is NOT NULL, and an empty string otherwise.
+*/
+
+EString Row::getUUID( const char * f ) const
+{
+ const Column * c = fetch( f, Column::Uuid, true );
+ if ( !c )
+ return "";
+ if ( c->type != Column::Uuid )
+ return "";
+ return c->s;
+}
/*! Returns the string value of the column named \a f i if it exists
and is NOT NULL, and an empty string otherwise.
@@ -1009,6 +1022,9 @@
case Timestamp:
n = "timestamptz";
break;
+ case Uuid:
+ n = "uuid";
+ break;
case Null:
n = "null";
break;
diff -wur aox-master/db/query.h aox-jim/db/query.h
--- aox-master/db/query.h 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/db/query.h 2015-04-11 09:19:18.935422000 -0400
@@ -129,7 +129,7 @@
: public Garbage
{
public:
- enum Type { Unknown, Boolean, Integer, Bigint, Bytes, Timestamp, Null };
+ enum Type { Unknown, Boolean, Integer, Bigint, Bytes, Timestamp, Null,
Uuid };
Type type;
EString s;
@@ -153,6 +153,7 @@
bool getBoolean( const char * ) const;
EString getEString( const char * ) const;
UString getUString( const char * ) const;
+ EString getUUID( const char * ) const;
bool hasColumn( const char * ) const;
Column::Type columnType( const char * ) const;
Only in aox-jim/doc: man
diff -wur aox-master/imap/command.cpp aox-jim/imap/command.cpp
--- aox-master/imap/command.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/imap/command.cpp 2014-07-07 08:37:36.395058000 -0400
@@ -51,6 +51,7 @@
#include "handlers/thread.h"
#include "handlers/unselect.h"
#include "handlers/urlfetch.h"
+#include "handlers/folderannotation.h"
#include <sys/time.h> // gettimeofday, struct timeval
@@ -263,6 +264,7 @@
else if ( n == "setquotaroot" )
c = new SetQuotaRoot();
+
if ( c ) {
authenticated = true;
selected = true;
@@ -292,6 +294,10 @@
c = new Sort( uid );
else if ( n == "move" )
c = new Move( uid );
+ else if ( n == "getannotation" )
+ c = new GetAnnotation;
+ else if ( n == "setannotation" )
+ c = new SetAnnotation;
if ( c )
selected = true;
@@ -1223,6 +1229,11 @@
UString Command::mailboxName()
{
EString n = astring();
+ return mailboxName(n);
+}
+
+UString Command::mailboxName(const EString &source) {
+ EString n = source;
if ( n.endsWith( "/" ) )
n = n.mid( 0, n.length() - 1 );
diff -wur aox-master/imap/command.h aox-jim/imap/command.h
--- aox-master/imap/command.h 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/imap/command.h 2014-07-06 10:17:05.475058000 -0400
@@ -82,6 +82,7 @@
uint msn();
EString flag();
class Mailbox * mailbox();
+ UString mailboxName(const EString &);
UString mailboxName();
void end();
diff -wur aox-master/imap/handlers/capability.cpp
aox-jim/imap/handlers/capability.cpp
--- aox-master/imap/handlers/capability.cpp 2014-06-03 09:15:21.000000000
-0400
+++ aox-jim/imap/handlers/capability.cpp 2015-04-07 16:14:14.159422000
-0400
@@ -77,7 +77,7 @@
if ( all || login ) {
c.append( "ACL" );
- c.append( "ANNOTATE-EXPERIMENT-1" );
+ c.append( "ANNOTATE" );
c.append( "BINARY" );
c.append( "CATENATE" );
c.append( "CHILDREN" );
Only in aox-jim/imap/handlers: folderannotation.cpp
Only in aox-jim/imap/handlers: folderannotation.h
diff -wur aox-master/imap/handlers/Jamfile aox-jim/imap/handlers/Jamfile
--- aox-master/imap/handlers/Jamfile 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/imap/handlers/Jamfile 2014-07-06 06:46:05.047058000 -0400
@@ -37,4 +37,5 @@
thread.cpp
unselect.cpp
urlfetch.cpp
+ folderannotation.cpp
;
diff -wur aox-master/imap/handlers/listext.cpp aox-jim/imap/handlers/listext.cpp
--- aox-master/imap/handlers/listext.cpp 2014-06-03 09:15:21.000000000
-0400
+++ aox-jim/imap/handlers/listext.cpp 2015-04-11 15:58:14.047422000 -0400
@@ -19,19 +19,35 @@
: public Garbage
{
public:
+ class statusInfo : public Garbage {
+ public:
+ uint messages;
+ uint unseen;
+ uint recent;
+ int64 nextmodseq;
+ EString guid;
+
+ statusInfo() :
+ messages(0), unseen(0), recent(0), nextmodseq(0) {
+ // Empty
+ }
+ };
+
ListextData():
- selectQuery( 0 ), permissionsQuery( 0 ),
- reference( 0 ),
+ selectQuery( 0 ), permissionsQuery( 0 ), statusQuery( 0 ),
+ reference( 0 ), mailboxStatus (0),
state( 0 ),
extended( false ),
returnSubscribed( false ), returnChildren( false ),
selectSubscribed( false ), selectRemote( false ),
- selectRecursiveMatch( false )
+ selectRecursiveMatch( false ), returnStatus( false )
{}
Query * selectQuery;
Query * permissionsQuery;
+ Query * statusQuery;
Mailbox * reference;
+ statusInfo * mailboxStatus;
EString referenceName;
UStringList patterns;
uint state;
@@ -64,12 +80,38 @@
EString previousResponse;
List<Response> responses;
+ // Status Selection Object
+ class statusSelection : public Garbage {
+ public:
+ bool getRecent;
+ bool getMessages;
+ bool getUidNext;
+ bool getUidValidity;
+ bool getUnseen;
+ bool getHighestModSeq;
+ bool getXGuid;
+
+
+ statusSelection() :
+ getRecent(false), getMessages(false), getUidNext(false),
+ getUidValidity(false), getUnseen (false),
getHighestModSeq (false),
+ getXGuid ( false ) {
+ // Empty Constructor
+ }
+ };
+
+ statusSelection statusRequired;
+
+
+
+
bool extended;
bool returnSubscribed;
bool returnChildren;
bool selectSubscribed;
bool selectRemote;
bool selectRecursiveMatch;
+ bool returnStatus;
};
@@ -177,7 +219,7 @@
uint bn = 1;
EString sel;
if ( d->selectSubscribed && d->selectRecursiveMatch ) {
- sel = "select mb.id, mb.name, s.id as sid, "
+ sel = "with q1 as (select mb.id, mb.name, s.id as sid, "
"exists(select cmb.id from mailboxes cmb "
"join subscriptions cs on"
" (cmb.id=cs.mailbox and cs.owner=$1) "
@@ -192,14 +234,14 @@
bn = 2;
}
else if ( d->selectSubscribed ) {
- sel = "select mb.id, mb.name, s.id as sid from mailboxes mb "
+ sel = "with q1 as (select mb.id, mb.name, s.id as sid from
mailboxes mb "
"join subscriptions s on (mb.id=s.mailbox and s.owner=$1) "
"where ";
d->selectQuery->bind( 1, imap()->user()->id() );
bn = 2;
}
else {
- sel = "select mb.id, mb.name";
+ sel = "with q1 as (select mb.id, mb.name";
if ( d->returnSubscribed ) {
sel.append( ", s.id as sid from mailboxes mb "
"left join subscriptions s on"
@@ -261,6 +303,17 @@
++i;
}
sel.append( " order by lower(mb.name)||' '" );
+
+ // Complete Sub-Query And Add Our Own For Additional Status Info
+ sel.append( "), "
+ "q2 as (select q1.id, mb.guid,
uidnext-first_recent as recent from q1 join mailboxes mb using (id)), "
+ "q3 as (select q1.id, count(uid) as
unseen from q1 join mailbox_messages mm on (q1.id=mm.mailbox) where not seen
group by id), "
+ "q4 as (select q1.id, count(*) as
messages from q1 join mailbox_messages mm on (q1.id=mm.mailbox) group by id) ");
+
+ // Now Return All Of That As A Single Query Compatible With
+ // The makeResponse Call From Before We Added The Status Feature
+ sel.append( "select * from q1 JOIN q2 using (id) join q3 using
(id) join q4 using (id)");
+
d->selectQuery->setString( sel );
d->selectQuery->execute();
@@ -387,10 +440,46 @@
d->returnSubscribed = true;
else if ( option == "children" )
d->returnChildren = true;
- else
+ else if ( "status" == option ) {
+ // Status Return Takes A Number Of Status Attributes We Need To
Parse
+ d->returnStatus = true;
+
+ require(" ("); // Status Must Be Followed By A SPACE Then (
+
+ addStatusItem(atom().lower()); // First Status Item Is
Mandatory
+ while ( present( " " ) )
+ addStatusItem( atom().lower() ); // Handle Any Further Items
+
+ require(")"); // To Complete Status, A Closing Bracket Is
Mandatory
+
+ } else
error( Bad, "Unknown return option: " + option );
}
+void Listext::addStatusItem( const EString & statusSelected ) {
+ if ("x-guid" == statusSelected) {
+ // X-GUID
+ d->statusRequired.getXGuid = true;
+ } else if ("messages" == statusSelected) {
+ d->statusRequired.getMessages = true;
+ } else if ("recent" == statusSelected) {
+ d->statusRequired.getRecent = true;
+ } else if ("uidnext" == statusSelected) {
+ d->statusRequired.getUidNext = true;
+ } else if ("uidvalidity" == statusSelected) {
+ d->statusRequired.getUidValidity = true;
+ } else if ("unseen" == statusSelected) {
+ d->statusRequired.getUnseen = true;
+ } else if ("highestmodseq" == statusSelected) {
+ d->statusRequired.getHighestModSeq = true;
+ } else {
+ // Nothing Valid Left - May Just Be We Don't Handle It Rather
Than
+ // The RFC Stating It Is Illegal/Invalid. We Log It So, If
Debug Is
+ // Active, There Will Be A Record Of This Happening To Help
+ // Track It Down.
+ error( Bad, "Unknown status item: " + statusSelected );
+ }
+}
/*! Parses the selection \a option, or emits a suitable error. \a
option must be lower-cased. */
@@ -449,6 +538,68 @@
EString name = imapQuoted( mailbox );
+ // Need To Append Any Extended Attributes Status ?
+ if (d->returnStatus) {
+ // yes - add them to ext
+ ext.append(" (");
+ EString preAppend = "";
+
+ if (d->statusRequired.getXGuid && row->hasColumn("guid") &&
!row->isNull("guid")) {
+ // We want the guid and the column exists and is not
null, so it is good to retrieve
+ EString guid = row->getUUID("guid");
+ ext.append(preAppend + "X-GUID " + guid);
+ log("retrieved guid as " + guid);
+ preAppend = " ";
+ }
+
+ if (d->statusRequired.getRecent && row->hasColumn("recent") &&
!row->isNull("recent")) {
+ int recent = row->getInt("recent");
+ ext.append(preAppend + "RECENT ");
+ ext.appendNumber(recent);
+ preAppend = " ";
+ }
+
+ if (d->statusRequired.getUnseen && row->hasColumn("unseen") &&
!row->isNull("unseen")) {
+ int unseen = row->getInt("unseen");
+ ext.append(preAppend + "UNSEEN ");
+ ext.appendNumber(unseen);
+ preAppend = " ";
+ }
+
+ if (d->statusRequired.getMessages && row->hasColumn("messages")
&& !row->isNull("messages")) {
+ int messages = row->getInt("messages");
+ ext.append(preAppend + "MESSAGES ");
+ ext.appendNumber(messages);
+ preAppend = " ";
+ }
+
+ if (d->statusRequired.getUidNext) {
+ int uidnext = mailbox->uidnext();
+ ext.append(preAppend + "UIDNEXT ");
+ ext.appendNumber(uidnext);
+ preAppend = " ";
+ }
+
+ if (d->statusRequired.getUidValidity) {
+ int uidvalidity = mailbox->uidvalidity();
+ ext.append(preAppend + "UIDVALIDITY ");
+ ext.appendNumber(uidvalidity);
+ preAppend = " ";
+ }
+
+ if (d->statusRequired.getHighestModSeq) {
+ int64 highest = mailbox->nextModSeq();
+ if (highest > 1)
+ highest--;
+
+ ext.append(preAppend + "HIGHESTMODSEQ ");
+ ext.appendNumber(highest);
+ preAppend = " ";
+ }
+
+ ext.append(")");
+ }
+
EString r = "LIST (" + a.join( " " ) + ") \"/\" " + name + ext;
if ( r == d->previousResponse )
diff -wur aox-master/imap/handlers/listext.h aox-jim/imap/handlers/listext.h
--- aox-master/imap/handlers/listext.h 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/imap/handlers/listext.h 2015-04-10 16:23:50.459422000 -0400
@@ -20,6 +20,7 @@
private:
void addReturnOption( const EString & );
void addSelectOption( const EString & );
+ void addStatusItem( const EString & );
void makeResponse( class Row * );
diff -wur aox-master/imap/handlers/sort.cpp aox-jim/imap/handlers/sort.cpp
--- aox-master/imap/handlers/sort.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/imap/handlers/sort.cpp 2014-07-06 06:46:05.051058000 -0400
@@ -210,8 +210,8 @@
{
switch ( c->t ) {
case Arrival:
- addJoin( t, "join messages m on (m.id=mm.message) ",
- "m.idate", c->reverse );
+ addJoin( t, "join messages mardt on (mardt.id=mm.message) ",
+ "mardt.idate", c->reverse );
break;
case Cc:
addJoin( t,
diff -wur aox-master/imap/handlers/status.cpp aox-jim/imap/handlers/status.cpp
--- aox-master/imap/handlers/status.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/imap/handlers/status.cpp 2015-04-08 08:38:02.135422000 -0400
@@ -19,16 +19,17 @@
StatusData() :
messages( false ), uidnext( false ), uidvalidity( false ),
recent( false ), unseen( false ),
- modseq( false ),
+ modseq( false ), x_guid (false),
mailbox( 0 ),
unseenCount( 0 ), messageCount( 0 ), recentCount( 0 ),
cacheState( 0 )
{}
- bool messages, uidnext, uidvalidity, recent, unseen, modseq;
+ bool messages, uidnext, uidvalidity, recent, unseen, modseq, x_guid;
Mailbox * mailbox;
Query * unseenCount;
Query * messageCount;
Query * recentCount;
+ Query * mailbox_x_guid;
uint cacheState;
class CacheItem
@@ -37,16 +38,19 @@
public:
CacheItem():
hasMessages( false ), hasUnseen( false ), hasRecent( false ),
+ has_x_guid (false),
messages( 0 ), unseen( 0 ), recent( 0 ),
nextmodseq( 0 ), mailbox( 0 )
{}
bool hasMessages;
bool hasUnseen;
bool hasRecent;
+ bool has_x_guid;
uint messages;
uint unseen;
uint recent;
int64 nextmodseq;
+ EString x_guid;
Mailbox * mailbox;
};
@@ -73,6 +77,7 @@
i->hasMessages = false;
i->hasUnseen = false;
i->hasRecent = false;
+ i->has_x_guid = false;
}
return i;
}
@@ -154,6 +159,8 @@
d->unseen = true;
else if ( item == "highestmodseq" )
d->modseq = true;
+ else if ( "x-guid" == item )
+ d->x_guid = true;
else
error( Bad, "Unknown STATUS item: " + item );
@@ -189,13 +196,15 @@
// second part. see if anything has happened, and feed the cache if
// so. make sure we feed the cache at once.
- if ( d->unseenCount || d->recentCount || d->messageCount ) {
+ if ( d->unseenCount || d->recentCount || d->messageCount ||
d->mailbox_x_guid) {
if ( d->unseenCount && !d->unseenCount->done() )
return;
if ( d->messageCount && !d->messageCount->done() )
return;
if ( d->recentCount && !d->recentCount->done() )
return;
+ if ( d->mailbox_x_guid && !d->mailbox_x_guid->done() )
+ return;
}
if ( !::cache )
::cache = new StatusData::StatusCache;
@@ -233,7 +242,18 @@
}
}
}
-
+ if ( d->mailbox_x_guid ) {
+ // Retrieve Mailbox GUID Value And Place Into Cache Item
+ while ( d->mailbox_x_guid->hasResults() ) {
+ Row * r = d->mailbox_x_guid->nextRow();
+ StatusData::CacheItem * ci =
+ ::cache->find( r->getInt( "mailbox" ) );
+ if ( ci ) {
+ ci->has_x_guid = true;
+ ci->x_guid = r->getEString( "guid" );
+ }
+ }
+ }
// third part. are we processing the first command in a STATUS
// loop? if so, see if we ought to preload the cache.
if ( mailboxGroup() && d->cacheState < 3 ) {
@@ -244,9 +264,9 @@
while ( i ) {
StatusData::CacheItem * ci = ::cache->provide( i );
bool need = false;
- if ( d->unseen || d->recent || d->messages )
+ if ( d->unseen || d->recent || d->messages || d->x_guid )
need = true;
- if ( ci->hasUnseen || ci->hasRecent || ci->hasMessages )
+ if ( ci->hasUnseen || ci->hasRecent || ci->hasMessages ||
ci->has_x_guid )
need = false;
if ( need )
mailboxes.add( i->id() );
@@ -282,6 +302,16 @@
d->messageCount->bind( 1, mailboxes );
d->messageCount->execute();
}
+ if ( d->x_guid ) {
+ // Run Query To Get Mailbox GUID Value
+ d->mailbox_x_guid
+ = new Query( "select guid "
+ "from mailboxes where id=any($1) "
+ , this );
+ d->mailbox_x_guid->bind( 1, mailboxes );
+ d->mailbox_x_guid->execute();
+ }
+
d->cacheState = 2;
}
if ( d->cacheState == 2 ) {
@@ -296,6 +326,8 @@
ci->hasRecent = true;
if ( ci && d->messageCount )
ci->hasMessages = true;
+ if ( ci && d->mailbox_x_guid )
+ ci->has_x_guid = true;
++i;
}
// and drop the queries
@@ -303,6 +335,7 @@
d->unseenCount = 0;
d->recentCount = 0;
d->messageCount = 0;
+ d->mailbox_x_guid = NULL; // Null is surely
better than 0?
}
}
@@ -356,13 +389,26 @@
d->messageCount->execute();
}
- if ( d->unseenCount || d->recentCount || d->messageCount ) {
+ // Individual guid query ?
+ if ( d->x_guid && !d->mailbox_x_guid && !i->has_x_guid ) {
+ d->mailbox_x_guid
+ = new Query( "select guid "
+ "from mailboxes where id=$1 "
+ , this );
+ d->mailbox_x_guid->bind( 1, d->mailbox->id() );
+ d->mailbox_x_guid->execute();
+ }
+
+
+ if ( d->unseenCount || d->recentCount || d->messageCount ||
d->mailbox_x_guid ) {
if ( d->unseenCount && !d->unseenCount->done() )
return;
if ( d->messageCount && !d->messageCount->done() )
return;
if ( d->recentCount && !d->recentCount->done() )
return;
+ if ( d->mailbox_x_guid && !d->mailbox_x_guid->done() )
+ return;
}
// fifth part: return the payload.
@@ -396,6 +442,9 @@
status.append( "HIGHESTMODSEQ " + fn( hms ) );
}
+ if ( d->x_guid && i->has_x_guid )
+ status.append( "X-GUID " + i->x_guid );
+
respond( "STATUS " + imapQuoted( d->mailbox ) +
" (" + status.join( " " ) + ")" );
finish();
Only in aox-jim/message: tld.inc
Only in aox-jim: patchset
diff -wur aox-master/sasl/mechanism.cpp aox-jim/sasl/mechanism.cpp
--- aox-master/sasl/mechanism.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/sasl/mechanism.cpp 2015-04-07 14:19:38.519422000 -0400
@@ -167,7 +167,8 @@
d->state = newState;
switch ( newState ) {
case AwaitingInitialResponse:
- // no logging necessary
+ // no logging necessary - but being done anyway since it helps
debugging
+ log( "Awaiting initial response", Log::Debug );
break;
case IssuingChallenge:
log( "Issuing challenge", Log::Debug );
diff -wur aox-master/sasl/sasllogin.cpp aox-jim/sasl/sasllogin.cpp
--- aox-master/sasl/sasllogin.cpp 2014-06-03 09:15:21.000000000 -0400
+++ aox-jim/sasl/sasllogin.cpp 2015-04-07 12:52:10.983422000 -0400
@@ -22,11 +22,14 @@
SaslLogin::SaslLogin( EventHandler * c )
: SaslMechanism( c, SaslMechanism::Login )
{
+ log( "SASLLOGIN: Debug Info Commenced LOGIN", Log::Error );
+ setState( AwaitingInitialResponse );
}
EString SaslLogin::challenge()
{
+ log( "SASLLOGIN: In Challenge with login " + login().ascii().quoted(),
Log::Error );
if ( login().isEmpty() )
return "Username:";
else
@@ -36,6 +39,7 @@
void SaslLogin::parseResponse( const EString &s )
{
+ log( "SASLLOGIN: Debug Info " + s.quoted(), Log::Error );
if ( login().isEmpty() ) {
if ( s.isEmpty() ) {
setState( Failed );
Only in aox-master/sasl: sasllogin-fixed.cpp