pop3._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: pop3.pike,v 1.1 2008/03/31 13:39:57 exodusd Exp $
18  */
19 inherit "/net/coal/login";
20 inherit "/net/base/line";
21 #include <macros.h>
22 #include <config.h>
23 #include <database.h>
24 class pop3 : public login,line{
25 public:
26 
27 
28 
29 
30 
31 #define STATE_AUTHORIZATION 1
32 #define STATE_TRANSACTION 2
33 #define STATE_UPDATE 3
34 
35  int _state = STATE_AUTHORIZATION;
36  string sServer = _Server->query_config("server");
37  object oMailBox;
38 
39 protected:
40  void send_ok(string msg)
41 {
42  LOG("Sending ok ("+msg+")");
43  send_message("+OK " + msg + "\r\n");
44 }
45 
46 public:
47 
48 protected:
49  void send_err(string msg)
50 {
51  LOG("Sending error ("+msg+")");
52  send_message("-ERR " + msg + "\r\n");
53 }
54 
55 public:
56 
57 
58 protected:
59  mapping mCmd = ([
60  STATE_AUTHORIZATION: ([
61  "APOP": apop,
62  "USER": user,
63  "PASS": pass,
64  "AUTH": auth,
65  "QUIT": quit,
66  "CAPA": capa,
67  ]),
68  STATE_TRANSACTION: ([
69  "STAT": stat,
70  "LIST": list,
71  "RETR": retr,
72  "DELE": dele,
73  "QUIT": quit,
74  "UIDL": uidl,
75  "TOP": top,
76  "CAPA": capa,
77  ]),
78  ]);
79 
80 
81 protected:
82  string greeting()
83 {
84  return "<1234."+time()+"@"+sServer+">";
85 }
86 
87 public:
88 
89 void create(object f)
90 {
91  ::create(f);
92  send_ok("POP3 Server ready " + greeting());
93 }
94 
95 string tohex(string what)
96 {
97  int i = 0;
98  for ( int q = 0; q < strlen(what); q++ ) {
99  i <<= 8;
100  i |= what[strlen(what)-1-q];
101  }
102  return sprintf("%x", i);
103 }
104 
105 /**
106  * Authenticate to the pop server.
107  *
108  * @param string user - the current user.
109  * @param string auth - the authorization string.
110  */
111 protected:
112  void apop(string user, string auth)
113 {
114  if ( oUser->check_user_password_md5(greeting(), auth) )
115  send_ok("maildrop has 0 message (0 octets)");
116  else
117  send_err("authentification failed");
118 }
119 
120 public:
121 
122 protected:
123  void auth(string type)
124 {
125  LOG("auth("+type+")");
126  send_err("Unrecognized authentication type");
127 }
128 
129 public:
130 
131 protected:
132  void user(string u)
133 {
134  oUser = _Persistence->lookup_user(u);
135  if ( !objectp(oUser) )
136  send_err("no such user ("+u+")");
137  send_ok("user, now send pass");
138 }
139 
140 public:
141 
142 protected:
143  string status_mailbox()
144 {
145  return oUser->get_identifier()+"'s maildrop has " +
146  oMailBox->get_num_messages() + " messages ("+
147  oMailBox->get_size() + " octets)";
148 }
149 
150 public:
151 
152 protected:
153  void pass(string p)
154 {
155  if ( oUser->check_user_password(p) ) {
156  oMailBox = _Server->get_module("mailbox")->get_mailbox(oUser);
157  login_user(oUser);
158  send_ok(status_mailbox());
159  _state = STATE_TRANSACTION;
160  LOG("login ok..."+sprintf("%O", get_user_object()));
161  }
162  else
163  send_err("Password does not match");
164 }
165 
166 public:
167 
168 protected:
169  void stat()
170 {
171  send_ok(oMailBox->get_num_messages() + " " + oMailBox->get_size());
172 }
173 
174 public:
175 
176 protected:
177  void list(int num)
178 {
179  stat();
180  for ( int i = 0; i < oMailBox->get_num_messages(); i++ ) {
181  send_message((i+1) + " " + oMailBox->get_message_size(i) +"\r\n");
182  }
183  send_message(".\r\n");
184 }
185 
186 public:
187 
188 protected:
189  void retr(int num)
190 {
191  send_ok(oMailBox->get_message_size(num-1)+ " octets");
192  send_message(oMailBox->retrieve_message(num-1));
193  send_message("\r\n.\r\n");
194 }
195 
196 public:
197 
198 protected:
199  void dele(int num)
200 {
201  if ( oMailBox->delete_message(num-1) )
202  send_ok("message "+ num + " deleted");
203  else
204  send_err("failed to delete message");
205 }
206 
207 public:
208 
209 protected:
210  void capa()
211 {
212  send_ok("Capability list follows");
213  foreach(indices(mCmd[_state]), string idx) {
214  send_message(idx + "\r\n");
215  }
216  send_message(".\r\n");
217 }
218 
219 public:
220 
221 /**
222  * Returns the unique id for a message, (object-id)
223  *
224  * @param int num - the message to identify
225  */
226 protected:
227  void uidl(int num)
228 {
229  send_ok(num + " " + oMailBox->get_message_id(num-1));
230  send_message(".\r\n");
231 }
232 
233 public:
234 
235 protected:
236  void top(int num, int l)
237 {
238  send_ok("");
239  string message = oMailBox->retrieve_message(num-1);
240  string header, body;
241  int i = search(message, "\r\n");
242  header = message[..i-1];
243  send_message(header);
244  body = message[i+2..];
245  array lines = body / "\n";
246  if ( l >= sizeof(lines) )
247  send_message(body + "\r\n.\r\n");
248  else {
249  send_message((lines[..l-1]*"\n")+ "\r\n.\r\n");
250  }
251 }
252 
253 public:
254 
255 
256 protected:
257  void quit()
258 {
259  _state = STATE_AUTHORIZATION;
260  oMailBox->cleanup(); // remove all messages scheduled for deletion
261  int messages_left = (objectp(oMailBox) ? oMailBox->get_num_messages() : 0);
262  send_ok("steam POP3 server signing off (" + messages_left +
263  " messages left)");
264 
265  oUser->disconnect();
266  close_connection();
267 }
268 
269 public:
270 
271 protected:
272  void process_command(string cmd)
273 {
274  array commands;
275 
276  commands = cmd / " ";
277 
278  for ( int i = 0; i < sizeof(commands); i++ ) {
279  mixed token = commands[i];
280  int l = strlen(token);
281 
282  if ( sscanf(token, "%d", token) && strlen((string)token)==l)
283  commands[i] = token;
284  }
285  function f = mCmd[_state][commands[0]];
286  if ( functionp(f) ) {
287  if ( sizeof(commands) == 1 )
288  f();
289  else
290  f(@commands[1..]);
291  return;
292  }
293  send_err("command not recognized");
294 }
295 
296 public:
297 
298 string get_socket_name() { return "pop3"; }
299 
300 
301 };