Moved pop3 to new SearchTree
[fmail.git] / backends / protocol / pop3.cpp
blob2700363e326ff640016abe39415d9962e8474a04
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 <odkutils.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;
49 const char KEY_END_DATA[6] = {0x0D, 0x0A, '.', 0x0D, 0x0A, 0x00};
51 #define STATE_AUTH 1
52 #define STATE_AUTH2 2
53 #define STATE_TRANSACTION 3
54 #define STATE_UPDATE 4
56 int knhash(char v){
57 if ((v >= 65) && (v <= 90))
58 return v - 65;
60 if (v == 95)
61 return 26;
63 if ((v >= 97) && (v <= 122))
64 return v - 97;
66 if (v == ' ')
67 return -1;
69 if (v == 0x0D)
70 return -1;
72 return 255;
75 class POP3Handler : public ProtocolHandler{
76 SearchTree<int, 27, &knhash> cmdtree;
77 public:
78 POP3Handler(){
79 cmdtree.Insert("USER", 1);
80 cmdtree.Insert("PASS", 2);
81 cmdtree.Insert("STAT", 3);
82 cmdtree.Insert("LIST", 4);
83 cmdtree.Insert("RETR", 5);
84 cmdtree.Insert("DELE", 6);
85 cmdtree.Insert("NOOP", 7);
86 cmdtree.Insert("QUIT", 8);
87 cmdtree.Insert("RSET", 9);
88 cmdtree.Insert("TOP", 10);
90 int Handle(Socket *s){
91 char buffer[255];
92 char userbuff[255];
93 char outbuff[255];
94 int r, i, j;
95 int onrun, cmd, state;
96 odkRegex *reg;
97 odkRegMatch *m;
99 reg = odk_regex_new("[\\w\\a]*\\s([\\w\\a]*)", 0, 0);
100 s->Write("+OK FancyMail v0.1", 18);
101 s->Write(CRLF, 2);
103 state = STATE_AUTH;
105 onrun = 1;
107 while (onrun){
108 memset(buffer, 0, 255);
109 r = s->Read(buffer, 255);
111 try{
112 cmd = cmdtree.Lookup(buffer);
113 }catch (SearchNotFound){
114 cmd = -1;
117 if (cmd == CMD_QUIT){
118 printf("Got QUIT\n");
119 s->Write( "+OK", 3);
120 s->Write( CRLF, 2);
121 state = STATE_UPDATE;
124 switch (state){
125 case STATE_AUTH:
126 if (cmd == CMD_USER){
128 m = odk_regex_match(reg, buffer, 0);
130 memset(userbuff, 0, 255);
131 memcpy(userbuff, (char*)((int)buffer + m->submatch[0].start), m->submatch[0].end - m->submatch[0].start);
132 printf("Got USERNAME: %s\n", userbuff);
133 odk_match_free(m);
134 s->Write( "+OK", 3);
135 s->Write( CRLF, 2);
136 state = STATE_AUTH2;
137 }else{
138 printf("INVALID [AUTH]: %s\n", buffer);
139 s->Write( "-ERR", 4);
140 s->Write( CRLF, 2);
142 break;
143 case STATE_AUTH2:
144 if (cmd == CMD_PASS){
145 m = odk_regex_match(reg, buffer, 0);
147 memset(outbuff, 0, 255);
148 memcpy(outbuff, (char*)((int)buffer + m->submatch[0].start), m->submatch[0].end - m->submatch[0].start);
149 printf("Got Password: %s\n", outbuff);
151 s->Write( "+OK", 3);
152 s->Write( CRLF, 2);
153 state = STATE_TRANSACTION;
154 }else{
155 printf("INVALID [AUTH2]: %s\n", buffer);
156 s->Write( "-ERR", 4);
157 s->Write(CRLF, 2);
158 state = STATE_AUTH;
160 break;
161 case STATE_TRANSACTION:
162 switch (cmd){
163 case CMD_STAT:
164 printf("Got STAT Command\n");
165 s->Write( "+OK 3 400", 9);
166 s->Write( CRLF, 2);
167 break;
168 case CMD_LIST:
169 printf("Got LIST Command: %s\n", buffer);
170 s->Write( "+OK", 3);
171 s->Write( CRLF, 2);
173 s->Write( "1 150", 5);
174 s->Write( CRLF, 2);
176 s->Write( "2 150", 5);
177 s->Write( CRLF, 2);
179 s->Write( "3 100", 5);
180 s->Write( CRLF, 2);
181 s->Write( ".", 1);
182 s->Write( CRLF, 2);
183 break;
184 case CMD_RETR:
185 printf("Got RETR Command: %s\n", buffer);
186 s->Write( "+OK 150 octets", 14);
187 s->Write( CRLF, 2);
189 s->Write( demomsg, strlen(demomsg));
191 s->Write( CRLF, 2);
192 s->Write( ".", 1);
193 s->Write( CRLF, 2);
194 break;
195 case CMD_DELE:
196 printf("Got DELE Command: %s\n", buffer);
197 s->Write( "+OK", 3);
198 s->Write( CRLF, 2);
199 break;
200 case CMD_NOOP:
201 printf("Got NOOP Command\n");
202 s->Write( "+OK", 3);
203 s->Write( CRLF, 2);
204 break;
205 case CMD_RSET:
206 printf("Got RSET Command\n");
207 s->Write( "+OK", 3);
208 s->Write( CRLF, 2);
209 case CMD_TOP:
210 printf("Got TOP Command: %s\n", buffer);
211 for (i = strlen(buffer); i > 0; i--){
212 if (buffer[i] == ' ')
213 break;
215 if (i >= 0){
216 i = atoi((char*)(buffer + i));
217 }else{
218 i = 0;
220 s->Write( "+OK", 3);
221 s->Write( CRLF, 2);
223 j =0;
224 for (r = 0; r < i; r++){
225 sscanf((char*)(demomsg+j), "%s", buffer);
226 j = j + strlen(buffer);
227 s->Write( buffer, strlen(buffer));
228 s->Write( CRLF, 2);
230 s->Write( ".", 1);
231 s->Write( CRLF, 2);
232 break;
233 default:
234 printf("INVALID [TRANS]: %s\n", buffer);
235 s->Write( "-ERR", 4);
236 s->Write( CRLF, 2);
238 break;
239 case STATE_UPDATE:
240 onrun = 0;
241 break;
244 printf("Closing Connection\n");
245 s->Close();
249 extern "C"{
250 ProtocolHandler *plugin_protocol_load(){
251 return new POP3Handler();