SMTP and POP3 servers are standalone only now, eliminated library loading function
[fmail.git] / backends / protocol / pop3.cpp
blob7e184a2f9353499b33a1d2802925bbd9c3842c9a
1 /*
2 POP3 Protocol Handler
4 Copyright (C) 2007 Carlos Daniel Ruvalcaba Valenzuela <clsdaniel@gmail.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <libfmail.h>
22 #include <pcrecpp.h>
24 char *demomsg = "From: Test John <testjohn@localhost>\n"
25 "To: test@localhost\n"
26 "Content-Type: text/plain\n"
27 "Date: Wed, 06 Jun 2007 15:21:21 -0700\n"
28 "Message-Id: <1181168481.15047.2.camel@localhost>\n"
29 "Mime-Version: 1.0\n"
30 "X-Mailer: Evolution 2.10.1 \n"
31 "Content-Transfer-Encoding: 7bit\n"
32 "\n"
33 "Test Mail!!";
35 const int POP3_PORT = 12001; //25;
36 const char CRLF[2] = {0x0D, 0x0A};
38 const int CMD_USER = 1;
39 const int CMD_PASS = 2;
40 const int CMD_STAT = 3;
41 const int CMD_LIST = 4;
42 const int CMD_RETR = 5;
43 const int CMD_DELE = 6;
44 const int CMD_NOOP = 7;
45 const int CMD_QUIT = 8;
46 const int CMD_RSET = 9;
47 const int CMD_TOP = 10;
48 const int CMD_CAPA = 10;
50 const char KEY_END_DATA[6] = {0x0D, 0x0A, '.', 0x0D, 0x0A, 0x00};
52 #define STATE_AUTH 1
53 #define STATE_AUTH2 2
54 #define STATE_TRANSACTION 3
55 #define STATE_UPDATE 4
57 int knhash(char v){
58 if ((v >= 65) && (v <= 90))
59 return v - 65;
61 if (v == 95)
62 return 26;
64 if ((v >= 97) && (v <= 122))
65 return v - 97;
67 if (v == ' ')
68 return -1;
70 if (v == 0x0D)
71 return -1;
73 return 255;
76 class POP3Handler : public ProtocolHandler{
77 SearchTree<int, 27, &knhash> cmdtree;
78 public:
79 POP3Handler(){
80 cmdtree.Insert("USER", 1);
81 cmdtree.Insert("PASS", 2);
82 cmdtree.Insert("STAT", 3);
83 cmdtree.Insert("LIST", 4);
84 cmdtree.Insert("RETR", 5);
85 cmdtree.Insert("DELE", 6);
86 cmdtree.Insert("NOOP", 7);
87 cmdtree.Insert("QUIT", 8);
88 cmdtree.Insert("RSET", 9);
89 cmdtree.Insert("TOP", 10);
90 cmdtree.Insert("CAPA", 11);
91 printf("SearchTree Memory Usage: %i bytes\n", cmdtree.getTreeSize());
93 int Handle(Socket *s){
94 char buffer[255];
95 char userbuff[255];
96 char outbuff[255];
97 int r, i, j;
98 int onrun, cmd, state;
99 IPC *ipc;
100 IPCMessage *msg;
101 string user, pass;
102 pcrecpp::RE reg("[\\w\\a]*\\s([\\w\\a]*)");
104 ipc = IPC::CreateIPC("socket://127.0.0.1:14000");
106 s->Write("+OK FancyMail v0.1", 18);
107 s->Write(CRLF, 2);
109 state = STATE_AUTH;
111 onrun = 1;
113 while (onrun){
114 memset(buffer, 0, 255);
115 r = s->Read(buffer, 255);
117 try{
118 cmd = cmdtree.Lookup(buffer);
119 }catch (SearchNotFound){
120 cmd = -1;
123 if (cmd == CMD_QUIT){
124 printf("Got QUIT\n");
125 s->Write( "+OK", 3);
126 s->Write( CRLF, 2);
127 state = STATE_UPDATE;
130 switch (state){
131 case STATE_AUTH:
132 if (cmd == CMD_USER){
133 reg.PartialMatch(buffer, &user);
134 printf("Got USERNAME: %s\n", user.c_str());
136 s->Write( "+OK", 3);
137 s->Write( CRLF, 2);
138 state = STATE_AUTH2;
139 }else{
140 printf("INVALID [AUTH]: %s\n", buffer);
141 s->Write( "-ERR", 4);
142 s->Write( CRLF, 2);
144 break;
145 case STATE_AUTH2:
146 if (cmd == CMD_PASS){
147 reg.PartialMatch(buffer, &pass);
149 printf("Got Password: %s\n", pass.c_str());
151 i = 0;
152 while (i < 10){
153 if (ipc->RequestIPC())
154 i = 10;
157 msg = new IPCMessage("auth");
158 msg->PushParam((char*)user.c_str());
159 msg->PushParam((char*)pass.c_str());
160 ipc->PushMessage(msg);
162 while(ipc->PeekMessage() == 0){
164 msg = ipc->PopMessage();
166 ipc->CloseIPC();
168 if (!strcmp(msg->GetMessageName(), "authok")){
169 s->Write( "+OK", 3);
170 s->Write( CRLF, 2);
171 state = STATE_TRANSACTION;
172 }else{
173 s->Write( "-ERR", 4);
174 s->Write(CRLF, 2);
175 state = STATE_AUTH;
178 }else{
179 printf("INVALID [AUTH2]: %s\n", buffer);
180 s->Write( "-ERR", 4);
181 s->Write(CRLF, 2);
182 state = STATE_AUTH;
184 break;
185 case STATE_TRANSACTION:
186 switch (cmd){
187 case CMD_STAT:
188 printf("Got STAT Command\n");
189 s->Write( "+OK 3 400", 9);
190 s->Write( CRLF, 2);
191 break;
192 case CMD_LIST:
193 printf("Got LIST Command: %s\n", buffer);
194 s->Write( "+OK", 3);
195 s->Write( CRLF, 2);
197 s->Write( "1 150", 5);
198 s->Write( CRLF, 2);
200 s->Write( "2 150", 5);
201 s->Write( CRLF, 2);
203 s->Write( "3 100", 5);
204 s->Write( CRLF, 2);
205 s->Write( ".", 1);
206 s->Write( CRLF, 2);
207 break;
208 case CMD_RETR:
209 printf("Got RETR Command: %s\n", buffer);
210 s->Write( "+OK 150 octets", 14);
211 s->Write( CRLF, 2);
213 s->Write( demomsg, strlen(demomsg));
215 s->Write( CRLF, 2);
216 s->Write( ".", 1);
217 s->Write( CRLF, 2);
218 break;
219 case CMD_DELE:
220 printf("Got DELE Command: %s\n", buffer);
221 s->Write( "+OK", 3);
222 s->Write( CRLF, 2);
223 break;
224 case CMD_NOOP:
225 printf("Got NOOP Command\n");
226 s->Write( "+OK", 3);
227 s->Write( CRLF, 2);
228 break;
229 case CMD_RSET:
230 printf("Got RSET Command\n");
231 s->Write( "+OK", 3);
232 s->Write( CRLF, 2);
233 case CMD_TOP:
234 printf("Got TOP Command: %s\n", buffer);
235 for (i = strlen(buffer); i > 0; i--){
236 if (buffer[i] == ' ')
237 break;
239 if (i >= 0){
240 i = atoi((char*)(buffer + i));
241 }else{
242 i = 0;
244 s->Write( "+OK", 3);
245 s->Write( CRLF, 2);
247 j =0;
248 for (r = 0; r < i; r++){
249 sscanf((char*)(demomsg+j), "%s", buffer);
250 j = j + strlen(buffer);
251 s->Write( buffer, strlen(buffer));
252 s->Write( CRLF, 2);
254 s->Write( ".", 1);
255 s->Write( CRLF, 2);
256 break;
257 default:
258 printf("INVALID [TRANS]: %s\n", buffer);
259 s->Write( "-ERR", 4);
260 s->Write( CRLF, 2);
262 break;
263 case STATE_UPDATE:
264 onrun = 0;
265 break;
268 printf("Closing Connection\n");
269 s->Close();
273 class SimpleLoad : public LoadHandler {
274 public:
275 int Dispatch(Socket *sock, ProtocolHandler *ph){
276 if (ph)
277 return ph->Handle(sock);
278 return 0;
282 int main(int argc, char **argv){
283 BaseServer *srv;
284 SimpleLoad *lh;
285 POP3Handler *pop3;
287 pop3 = new POP3Handler();
288 srv = new BaseServer(pop3, 12001);
289 lh = new SimpleLoad();
290 srv->SetLoadhandler(lh);
291 srv->Listen();
293 while(1){
294 srv->Accept();
297 return 0;