1 // Copyright 2009 The Archiveopteryx Developers <info@aox.org>
2
3 #include "subscribe.h"
4
5 #include "imap.h"
6 #include "user.h"
7 #include "query.h"
8 #include "mailbox.h"
9
10
11 /*! \class Subscribe subscribe.h
12 Adds a mailbox to the subscription list (RFC 3501 section 6.3.6)
13 */
14
Subscribe()15 Subscribe::Subscribe()
16 : q( 0 ), m( 0 )
17 {}
18
19
20 /*! \class Unsubscribe subscribe.h
21 Removes a mailbox from the subscription list (RFC 3501 section 6.3.7)
22 */
23
Unsubscribe()24 Unsubscribe::Unsubscribe()
25 : Command(), q( 0 )
26 {
27 }
28
29
parse()30 void Subscribe::parse()
31 {
32 space();
33 m = mailbox();
34 end();
35 if ( ok() )
36 log( "Subscribe " + m->name().ascii() );
37 }
38
39
execute()40 void Subscribe::execute()
41 {
42 if ( state() != Executing )
43 return;
44
45 if ( m->deleted() )
46 error( No, "Cannot subscribe to deleted mailbox" );
47
48 requireRight( m, Permissions::Lookup );
49
50 if ( !ok() || !permitted() )
51 return;
52
53 if ( !q ) {
54 // this query has a race: the select can return an empty set
55 // while someone else is running the same query, then the
56 // insert fails because of the 'unique' constraint. the db is
57 // still valid, so the race only leads to an unnecessary error
58 // in the pg log file.
59 q = new Query( "insert into subscriptions (owner, mailbox) "
60 "select $1, $2 where not exists "
61 "(select owner, mailbox from subscriptions"
62 " where owner=$1 and mailbox=$2)", this );
63 q->bind( 1, imap()->user()->id() );
64 q->bind( 2, m->id() );
65 q->canFail();
66 q->execute();
67 }
68
69 if ( !q->done() )
70 return;
71
72 if ( q->failed() )
73 log( "Ignoring duplicate subscription" );
74 finish();
75 }
76
77
parse()78 void Unsubscribe::parse()
79 {
80 space();
81 n = mailboxName();
82 end();
83 if ( ok() )
84 log( "Unsubscribe " + n.ascii() );
85 }
86
87
execute()88 void Unsubscribe::execute()
89 {
90 if ( !q ) {
91 UString c = imap()->user()->mailboxName( n );
92 Mailbox * m = Mailbox::find( c, true );
93 if ( !m ) {
94 finish();
95 return;
96 }
97 else if ( !m->id() ) {
98 finish();
99 return;
100 }
101 q = new Query( "delete from subscriptions "
102 "where owner=$1 and mailbox=$2", this );
103 q->bind( 1, imap()->user()->id() );
104 q->bind( 2, m->id() );
105 q->execute();
106 }
107
108 if ( q && !q->done() )
109 return;
110
111 finish();
112 }
113