comply with the THRID draft instead of using arnt's gmail hack
[aox:aox.git] / imap / handlers / capability.cpp
1 // Copyright 2009 The Archiveopteryx Developers <info@aox.org>
2
3 #include "capability.h"
4
5 #include "scope.h"
6 #include "configuration.h"
7 #include "imap.h"
8 #include "estringlist.h"
9 #include "log.h"
10 #include "mechanism.h"
11
12
13 /*! \class Capability capability.h
14     Announces supported features (RFC 3501 section 6.1.1).
15
16     We announce the following standard capabilities:
17
18     RFC 2087: QUOTA,
19     RFC 3501: IMAP4rev1, STARTTLS, LOGINDISABLED,
20     RFC 3502: MULTIAPPEND,
21     RFC 2086: ACL,
22     RFC 2088: LITERAL+,
23     RFC 2177: IDLE,
24     RFC 2971: ID,
25     RFC 2342: NAMESPACE,
26     RFC 2359: UIDPLUS,
27     RFC 3691: UNSELECT,
28     RFC 2245: AUTH=ANONYMOUS,
29     RFC 2595: AUTH=PLAIN,
30     RFC 2195: AUTH=CRAM-MD5,
31     RFC 2831: AUTH=DIGEST-MD5,
32     RFC 3348: CHILDREN,
33     RFC 3516: BINARY,
34     RFC 4469: CATENATE,
35     RFC 4551: CONDSTORE,
36     RFC 4467: URLAUTH,
37     RFC 4731: ESEARCH (also from RFC 4466),
38     RFC 4959: SASL-IR,
39     RFC 4978: COMPRESS=DEFLATE,
40     RFC 5032: WITHIN,
41     RFC 5255: I18NLEVEL=1,
42     RFC 5256: SORT,
43     RFC 5257: ANNOTATE-EXPERIMENT-1,
44     RFC 5258: LISTEXT,
45     RFC 5465: NOTIFY,
46     RFC 6855: UTF=ACCEPT,
47     RFC 7162: QRESYNC.
48 */
49
50 void Capability::execute()
51 {
52     respond( "CAPABILITY " + capabilities( imap(), true ) );
53     finish();
54 }
55
56
57 /*! Returns all capabilities that are applicable to \a i. If \a all is
58     specified and true, the list includes capabilities that are not
59     applicable to the current IMAP::state().
60 */
61
62 EString Capability::capabilities( IMAP * i, bool all )
63 {
64     EStringList c;
65
66     c.append( "IMAP4rev1" );
67
68     bool login = true;
69     if ( i->state() == IMAP::NotAuthenticated )
70         login = false;
71
72     // the remainder of the capabilities are kept sorted by name
73
74     // ugly X-... prefixes are disregarded when sorting by name
75
76     if ( all || ( !login && i->accessPermitted() ) )
77         c.append( SaslMechanism::allowedMechanisms( "AUTH=", i->hasTls() ) );
78
79     if ( all || login ) {
80         c.append( "ACL" );
81         c.append( "ANNOTATE-EXPERIMENT-1" );
82         c.append( "BINARY" );
83         c.append( "CATENATE" );
84         c.append( "CHILDREN" );
85     }
86     // should we advertise COMPRESS only if not compressed?
87     //c.append( "COMPRESS=DEFLATE" );
88     if ( all || login )
89         c.append( "CONDSTORE" );
90     c.append( "ENABLE" );
91     if ( all || login ) {
92         c.append( "ESEARCH" );
93         c.append( "I18NLEVEL=1" );
94     }
95     c.append( "ID" );
96     if ( all || login )
97         c.append( "IDLE" );
98     if ( all || login )
99         c.append( "LIST-EXTENDED" );
100     c.append( "LITERAL+" );
101     if ( ( all || !login ) &&
102          !SaslMechanism::allowed( SaslMechanism::Plain, i->hasTls() ) )
103         c.append( "LOGINDISABLED" );
104     if ( all || login ) {
105         c.append( "MOVE" );
106         c.append( "MULTIAPPEND" );
107         c.append( "NAMESPACE" );
108         //c.append( "NOTIFY" );
109     }
110     if ( all || login ) {
111         if ( Configuration::toggle( Configuration::UseImapQuota ) )
112             c.append( "QUOTA" );
113         c.append( "QRESYNC" );
114         c.append( "RIGHTS=ekntx" );
115     }
116     if ( all || !login )
117         c.append( "SASL-IR" );
118     if ( all || login ) {
119         c.append( "SORT" );
120         c.append( "SORT=DISPLAY" ); // draft-ietf-morg-sortdisplay
121     }
122     if ( Configuration::toggle( Configuration::UseTls ) && !i->hasTls() )
123         c.append( "STARTTLS" );
124     if ( all || login ) {
125         c.append( "THREAD=ORDEREDSUBJECT" );
126         c.append( "THREAD=REFS" );
127         c.append( "THREAD=REFERENCES" );
128         c.append( "THRID" );
129         c.append( "UIDPLUS" );
130         c.append( "UNSELECT" );
131         c.append( "URLAUTH" );
132         c.append( "UTF8=ACCEPT" );
133         c.append( "WITHIN" );
134     }
135
136     return c.join( " " );
137 }