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