1 /* -*- Mode: c++; -*- */
2 /* --------------------------------------------------------------------
3 * Filename:
4 * bincimap-up.cc
5 *
6 * Description:
7 * Implementation of the preauthenticated bincimap stub
8 *
9 * Authors:
10 * Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
11 *
12 * Bugs:
13 *
14 * ChangeLog:
15 *
16 * --------------------------------------------------------------------
17 * Copyright 2002-2005 Andreas Aardal Hanssen
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
32 * --------------------------------------------------------------------
33 */
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <string>
39
40 #include "broker.h"
41 #include "recursivedescent.h"
42 #include "io.h"
43 #ifdef WITH_SSL
44 #include "io-ssl.h"
45 #endif
46 #include "operators.h"
47 #include "session.h"
48
49 using namespace ::std;
50 using namespace Binc;
51
52 namespace Binc {
53 bool showGreeting(void);
54 }
55
56 //------------------------------------------------------------------------
main(int argc,char * argv[])57 int main(int argc, char *argv[])
58 {
59 Session &session = Session::getInstance();
60 if (!session.initialize(argc, argv)) {
61 if (session.getLastError() != "") {
62 IO &logger = IOFactory::getInstance().get(2);
63 logger << "error initializing Binc IMAP: " << session.getLastError()
64 << endl;
65 logger.flushContent();
66 }
67 return 111;
68 }
69
70 IO &com = IOFactory::getInstance().get(1);
71 IO &logger = IOFactory::getInstance().get(2);
72
73 logger << "connection from " << session.getIP() << endl;
74
75 // Show standard greeting
76 showGreeting();
77 bool recovery = false;
78 bool timedout = false;
79 bool disconnect = false;
80 bool abrt = false;
81
82 // Read commands and run functions
83 do {
84 com.enableInputLimit();
85
86 // recover from syntax error. There will be trash in the input
87 // buffer. We need to flush everything until we see an LF.
88 if (recovery) {
89 for (;;) {
90 int c = com.readChar(session.timeout());
91 if (c == '\n') break;
92 if (c == -1) {
93 disconnect = true;
94 abrt = true;
95 break;
96 } else if (c == -2) {
97 com << "* BYE Timeout after " << session.timeout()
98 << " seconds of inactivity." << endl;
99 timedout = true;
100 abrt = true;
101 break;
102 }
103 }
104
105 if (abrt)
106 break;
107 }
108
109 Request request;
110 recovery = false;
111
112 BrokerFactory &brokerFactory = BrokerFactory::getInstance();
113 Broker *broker = brokerFactory.getBroker(session.getState());
114 if (!broker) {
115 // will never happen
116 }
117
118 com.flushContent();
119 com.noFlushOnEndl();
120
121 switch (broker->parseStub(request)) {
122 case Operator::TIMEOUT:
123 com << "* BYE Timeout after " << session.timeout()
124 << " seconds of inactivity." << endl;
125 timedout = true;
126 abrt = true;
127 break;
128 case Operator::REJECT:
129 com << "* NO " << session.getLastError() << endl;
130 recovery = true;
131 continue;
132 case Operator::ERROR:
133 com << "* BAD " << session.getLastError() << endl;
134 recovery = true;
135 continue;
136 default:
137 break;
138 }
139
140 if (abrt)
141 break;
142
143 Operator *o = broker->get(request.getName());
144 if (!o) {
145 com << request.getTag() << " NO The command \""
146 << (request.getUidMode() ? "UID " : "")
147 << request.getName()
148 << "\" is unsupported in this state. "
149 << "Please authenticate." << endl;
150 recovery = true;
151 continue;
152 }
153
154 switch (o->parse(request)) {
155 case Operator::TIMEOUT:
156 com << "* BYE Timeout after " << session.timeout()
157 << " seconds of inactivity." << endl;
158 timedout = true;
159 abrt = true;
160 break;
161 case Operator::REJECT:
162 com << "* NO " << session.getLastError() << endl;
163 recovery = true;
164 continue;
165 case Operator::ERROR:
166 com << "* BAD " << session.getLastError() << endl;
167 recovery = true;
168 continue;
169 default:
170 break;
171 }
172
173 switch (o->process(*session.getDepot(), request)) {
174 case Operator::OK:
175 com << request.getTag() << " OK " << request.getName()
176 << " completed" << endl;
177 break;
178 case Operator::NO:
179 com << request.getTag() << " NO " << session.getResponseCode()
180 << request.getName() << " failed: " << session.getLastError() << endl;
181 session.clearResponseCode();
182 break;
183 case Operator::BAD:
184 com << request.getTag() << " BAD " << request.getName()
185 << " failed: " << session.getLastError() << endl;
186 recovery = true;
187 break;
188 case Operator::NOTHING:
189 break;
190 case Operator::ABORT:
191 session.setState(Session::LOGOUT);
192 abrt = true;
193 break;
194 }
195
196 if (abrt)
197 break;
198 } while (session.getState() != Session::LOGOUT);
199
200 logger << "shutting down ";
201 if (timedout)
202 logger << "(timeout " + toString(session.timeout()) + "s) ";
203 else if (disconnect)
204 logger << "(" << com.getLastError() << ") ";
205
206 logger << "- read:"
207 << session.getReadBytes()
208 << " bytes, wrote:" << session.getWriteBytes()
209 << " bytes." << endl;
210
211 com.flushContent();
212 }
213