/[imapfilter]/imapfilter/imap.c
ViewVC logotype

Diff of /imapfilter/imap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by lefcha, Sat Aug 11 15:52:52 2001 UTC revision 1.46 by lefcha, Sat Feb 14 22:48:04 2004 UTC
# Line 1  Line 1 
1  #include <stdio.h>  #include <stdio.h>
2  #include <string.h>  #include <string.h>
 #include <stdlib.h>  
 #include <unistd.h>  
 #include <errno.h>  
3    
4  #include "config.h"  #include "config.h"
5  #include "imapfilter.h"  #include "imapfilter.h"
6  #include "imap.h"  #include "filter.h"
7  #include "connect.h"  #include "buffer.h"
 #include "log.h"  
8    
9    
10  static int tag = 0xA000;        /* Every IMAP command is prefixed with a  extern options_t opts;
11                                     unique [:alnum:] string. */  extern connection_t connpri, connaux;
12  extern int sock;  
13  extern int fcnt;  buffer_t obuf;                  /* Output buffer. */
14  extern filter_entry **filters;  
15  extern account_data account;  static unsigned int tag = 0x1000;       /* Every IMAP command is prefixed with
16  extern int options;                                           * a unique [:alnum:] string. */
17    
18    
19    unsigned int send_command(connection_t * conn, char *cmd, char *alt);
20    void send_command_cont(connection_t * conn, char *cmd);
21    
22    
23  /*  /*
24   * Sends to server data; a command.   * Send to server data; a command.
25   */   */
26  int send_command(char *command)  unsigned int
27    send_command(connection_t * conn, char *cmd, char *alt)
28  {  {
29    
30  #ifdef DEBUG          debug("sending command (%s):\n\n%s\n",
31      printf("debug: sending command: %s", command);              (conn == &connpri ? "primary" : "auxiliary"),
32  #endif              (opts.debug == 1 && alt ? alt : cmd));
33    
34            verbose("%s: %s", (conn == &connpri ? "C" : "c"), (alt ? alt : cmd));
35    
36            socket_write(conn, cmd);
37    
38      if (write(sock, command, strlen(command)) == -1) {          if (tag == 0xFFFF)
39          error("imapfilter: error while sending command; %s",                  tag = 0x0FFF;
               strerror(errno));  
         return FAILURE;  
     }  
40    
41      return SUCCESS;          return tag++;
42  }  }
43    
44    
45    #ifdef CRAM_MD5
46  /*  /*
47   * Calls send_command() and get_response().   * Send to server data: a continuation command.
48   */   */
49  int send_command_get_response(char *command)  void
50    send_command_cont(connection_t * conn, char *cmd)
51  {  {
     char buf[RESPONSE_BUFFER_MAX];  
52    
53      if (!send_command(command)) {          debug("sending command (%s):\n\n%s\r\n\n",
54          get_response(buf);              (conn == &connpri ? "primary" : "auxiliary"), cmd);
55          return SUCCESS;  
56      } else          socket_write(conn, cmd);
57          return FAILURE;          socket_write(conn, "\r\n");
58  }  }
59    #endif
60    
61    
 #ifdef DEBUG  
62  /*  /*
63   * IMAP NOOP: does nothing always succeeds.   * IMAP NOOP: does nothing always succeeds.
64   */   */
65  int imap_noop(void)  int
66    imap_noop(connection_t * conn)
67  {  {
     char command[SMALL_COMMAND_MAX];  
68    
69      verbose("Client request:  NOOP\n");          buffer_reset(&obuf);
70            buffer_check(&obuf, strlen("NOOP") + 12);
71    
72            snprintf(obuf.data, obuf.size, "%04X NOOP\r\n", tag);
73    
74            return send_command(conn, obuf.data, NULL);
75    }
76    
77    
78      snprintf(command, SMALL_COMMAND_MAX, "%X NOOP\r\n", tag++);  /*
79     * IMAP CAPABILITY: requests listing of capabilities that the server supports.
80     */
81    int
82    imap_capability(connection_t * conn)
83    {
84    
85            buffer_reset(&obuf);
86            buffer_check(&obuf, strlen("CAPABILITY") + 12);
87    
88      return send_command_get_response(command);          snprintf(obuf.data, obuf.size, "%04X CAPABILITY\r\n", tag);
89    
90            return send_command(conn, obuf.data, NULL);
91    }
92    
93    
94    /*
95     * IMAP NAMESPACE: discovers the prefix and delimeter of namespaces used by the
96     * server for mailboxes (RFC 2342).
97     */
98    int
99    imap_namespace(connection_t * conn)
100    {
101    
102            buffer_reset(&obuf);
103            buffer_check(&obuf, strlen("NAMESPACE") + 12);
104    
105            snprintf(obuf.data, obuf.size, "%04X NAMESPACE\r\n", tag);
106    
107            return send_command(conn, obuf.data, NULL);
108  }  }
 #endif  
109    
110    
111  /*  /*
112   * IMAP LOGOUT: informs server that client is done.   * IMAP LOGOUT: informs server that client is done.
113   */   */
114  int imap_logout(void)  int
115    imap_logout(connection_t * conn)
116  {  {
     char command[SMALL_COMMAND_MAX];  
117    
118      verbose("Client request:  LOGOUT\n");          buffer_reset(&obuf);
119            buffer_check(&obuf, strlen("LOGOUT") + 12);
120    
121            snprintf(obuf.data, obuf.size, "%04X LOGOUT\r\n", tag);
122    
123            return send_command(conn, obuf.data, NULL);
124    }
125    
126    
127    /*
128     * IMAP STARTTLS: begin TLS negotiation.
129     */
130    int
131    imap_starttls(connection_t * conn)
132    {
133    
134            buffer_reset(&obuf);
135            buffer_check(&obuf, strlen("STARTTLS") + 12);
136    
137            snprintf(obuf.data, obuf.size, "%04X STARTTLS\r\n", tag);
138    
139            return send_command(conn, obuf.data, NULL);
140    }
141    
142    
143      snprintf(command, SMALL_COMMAND_MAX, "%X LOGOUT\r\n", tag++);  #ifdef CRAM_MD5
144    /*
145     * IMAP AUTHENTICATE: indicates authentication mechanism and performs an
146     * authentication protocol exchange.
147     */
148    int
149    imap_authenticate(connection_t * conn, char *auth, int cont)
150    {
151    
152      return send_command_get_response(command);          buffer_reset(&obuf);
153            buffer_check(&obuf, strlen("AUTHENTICATE") + 12);
154    
155            if (!cont) {
156                    snprintf(obuf.data, obuf.size, "%04X AUTHENTICATE %s\r\n",
157                        tag, auth);
158                    return send_command(conn, obuf.data, NULL);
159            } else {
160                    send_command_cont(conn, auth);
161                    return 0;
162            }
163  }  }
164    #endif
165    
166    
167  /*  /*
168   * IMAP LOGIN: identifies client to server.   * IMAP LOGIN: identifies client to server.
169   */   */
170  int imap_login(void)  int
171    imap_login(connection_t * conn, char *user, char *pass)
172  {  {
173      char command[MEDIUM_COMMAND_MAX];          int r, n;
174            char *sbuf;
175    
176      verbose("Client request:  LOGIN\n");          /* Command to send to server. */
177            n = strlen("LOGIN") + strlen(user) + strlen(pass) + 18;
178            sbuf = (char *)smalloc(n);
179            snprintf(sbuf, n, "%04X LOGIN \"%s\" \"%s\"\r\n", tag, user, pass);
180    
181      snprintf(command, MEDIUM_COMMAND_MAX, "%X LOGIN \"%s\" \"%s\"\r\n",          /* Alternate command with password shrouded for safe printing. */
182               tag++, account.username, account.password);          buffer_reset(&obuf);
183            buffer_check(&obuf, strlen("LOGIN") + strlen(user) + 18);
184            snprintf(obuf.data, obuf.size, "%04X LOGIN \"%s\" *\r\n", tag, user);
185    
186      return send_command_get_response(command);          r = send_command(conn, sbuf, obuf.data);
187    
188            sfree(sbuf);
189    
190            return r;
191  }  }
192    
193    
194  /*  /*
195   * IMAP SELECT: selects a mailbox in which messages can be accessed.   * IMAP LIST: returns a subset of names from the complete set of names
196     * available to the client.
197     *
198    int imap_list(connection_t *conn, char *refer, char *mbox)
199    {
200    
201            buffer_reset(&obuf);
202            buffer_check(&obuf, strlen("LIST") + strlen(refer) + strlen(mbox) + 18);
203            
204            snprintf(obuf.data, obuf.size, "%04X LIST \"%s\" \"%s\"\r\n", tag,
205                refer, mbox);
206    
207            return send_command(conn, obuf.data, NULL);
208    }*/
209    
210    
211    /*
212     * IMAP SUBSCRIBE: adds the specified mailbox name to the server's set of
213     * "active" or "subscribed" mailboxes.
214   */   */
215  int imap_select(void)  int
216    imap_subscribe(connection_t * conn, char *mbox)
217  {  {
     char command[SMALL_COMMAND_MAX];  
218    
219      verbose("Client request:  SELECT\n");          buffer_reset(&obuf);
220            buffer_check(&obuf, strlen("SUBSCRIBE") + strlen(mbox) + 15);
221    
222      snprintf(command, SMALL_COMMAND_MAX, "%X SELECT INBOX\r\n", tag++);          snprintf(obuf.data, obuf.size, "%04X SUBSCRIBE \"%s\"\r\n", tag, mbox);
223    
224      return send_command_get_response(command);          return send_command(conn, obuf.data, NULL);
225  }  }
226    
227    
228  /*  /*
229   * IMAP SEARCH: searches the mailbox for messages that match certain criteria.   * IMAP EXAMINE: access a mailbox in READ-ONLY mode.
230     */
231    int
232    imap_examine(connection_t * conn, char *mbox)
233    {
234    
235            buffer_reset(&obuf);
236            buffer_check(&obuf, strlen("EXAMINE") + strlen(mbox) + 15);
237    
238            snprintf(obuf.data, obuf.size, "%04X EXAMINE \"%s\"\r\n", tag, mbox);
239    
240            return send_command(conn, obuf.data, NULL);
241    }
242    
243    
244    /*
245     * IMAP SELECT: access a mailbox in READ-WRITE mode.
246   */   */
247  int imap_search(void)  int
248    imap_select(connection_t * conn, char *mbox)
249  {  {
     char command[BIG_COMMAND_MAX];  
250    
251      verbose("Client request:  SEARCH\n");          buffer_reset(&obuf);
252            buffer_check(&obuf, strlen("SELECT") + strlen(mbox) + 15);
253    
254      generate_search_filters(command);          snprintf(obuf.data, obuf.size, "%04X SELECT \"%s\"\r\n", tag, mbox);
255    
256      return send_command(command);          return send_command(conn, obuf.data, NULL);
257    }
258    
259    
260    /*
261     * IMAP STATUS: requests status of the indicated mailbox.
262     */
263    int
264    imap_status(connection_t * conn, char *mbox, char *items)
265    {
266    
267            buffer_reset(&obuf);
268            buffer_check(&obuf, strlen("STATUS") + strlen(mbox) +
269                strlen(items) + 18);
270    
271            snprintf(obuf.data, obuf.size, "%04X STATUS \"%s\" (%s)\r\n", tag,
272                mbox, items);
273    
274            return send_command(conn, obuf.data, NULL);
275    }
276    
277    
278    /*
279     * IMAP CREATE: create mailbox.
280     */
281    int
282    imap_create(connection_t * conn, char *mbox)
283    {
284    
285            buffer_reset(&obuf);
286            buffer_check(&obuf, strlen("CREATE") + strlen(mbox) + 14);
287    
288            snprintf(obuf.data, obuf.size, "%04X CREATE \"%s\"\r\n", tag, mbox);
289    
290            return send_command(conn, obuf.data, NULL);
291    }
292    
293    
294    /*
295     * IMAP SEARCH: searches the mailbox for messages that match certain criteria.
296     */
297    int
298    imap_search(connection_t * conn, char *charset, char *search)
299    {
300    
301            buffer_reset(&obuf);
302            buffer_check(&obuf, strlen("SEARCH CHARSET") + strlen(charset) +
303                strlen(search) + 15);
304    
305            if (*charset)
306                    snprintf(obuf.data, obuf.size,
307                        "%04X SEARCH CHARSET \"%s\" %s\r\n", tag, charset, search);
308            else
309                    snprintf(obuf.data, obuf.size, "%04X SEARCH %s\r\n", tag,
310                        search);
311    
312            return send_command(conn, obuf.data, NULL);
313  }  }
314    
315    
316  /*  /*
317   * IMAP FETCH: retrieves data associated with a message.   * IMAP FETCH: retrieves data associated with a message.
318   */   */
319  int imap_fetch(unsigned int m, char *results)  int
320    imap_fetch(connection_t * conn, char *mesg, char *items)
321  {  {
     char command[MEDIUM_COMMAND_MAX];  
322    
323      verbose("Client request:  FETCH\n");          buffer_reset(&obuf);
324            buffer_check(&obuf,
325                strlen("FETCH") + strlen(mesg) + strlen(items) + 14);
326    
327      snprintf(command, MEDIUM_COMMAND_MAX,          snprintf(obuf.data, obuf.size, "%04X FETCH %s %s\r\n", tag, mesg,
328               "%X FETCH %d BODY[HEADER.FIELDS (\"DATE\" \"FROM\" \"SUBJECT\")]\r\n",              items);
              tag++, m);  
329    
330      if (!send_command(command)) {          return send_command(conn, obuf.data, NULL);
         fetch_response(results);  
         return SUCCESS;  
     } else  
         return FAILURE;  
331  }  }
332    
333    
334  /*  /*
335   * IMAP STORE: alters data associated with a message.   * IMAP STORE: alters data associated with a message.
336   */   */
337  int imap_store(unsigned int m)  int
338    imap_store(connection_t * conn, char *mesg, unsigned int mode, char *flags)
339  {  {
     char command[MEDIUM_COMMAND_MAX];  
340    
341      verbose("Client request:  STORE\n");          buffer_reset(&obuf);
342            buffer_check(&obuf, strlen("STORE") + strlen(mesg) +
343                strlen("FLAGS.SILENT") + strlen(flags) + 18);
344    
345      snprintf(command, MEDIUM_COMMAND_MAX,          snprintf(obuf.data, obuf.size, "%04X STORE %s %sFLAGS.SILENT (%s)\r\n",
346               "%X STORE %d +FLAGS \\Deleted\r\n", tag++, m);              tag, mesg, (mode == ACTION_FLAG_REPLACE ? "" :
347                mode == ACTION_FLAG_ADD ? "+" : "-"), flags);
348    
349      return send_command_get_response(command);          return send_command(conn, obuf.data, NULL);
350  }  }
351    
352    
353  /*  /*
354   * IMAP EXPUNGE: premanently removes any messages with the \Deleted flag set.   * IMAP COPY: copy messages to mailbox.
355   */   */
356  int imap_expunge(void)  int
357    imap_copy(connection_t * conn, char *mesg, char *mbox)
358  {  {
     char command[SMALL_COMMAND_MAX];  
359    
360      verbose("Client request:  EXPUNGE\n");          buffer_reset(&obuf);
361            buffer_check(&obuf, strlen("COPY") + strlen(mesg) + strlen(mbox) + 16);
362    
363      snprintf(command, SMALL_COMMAND_MAX, "%X EXPUNGE\r\n", tag++);          snprintf(obuf.data, obuf.size, "%04X COPY %s \"%s\"\r\n", tag, mesg,
364                mbox);
365    
366      return send_command_get_response(command);          return send_command(conn, obuf.data, NULL);
367  }  }
368    
369    
370  /*  /*
371   * Prepare according to the filters defined by the user the IMAP SEARCH   * IMAP APPEND: append message to the end of a mailbox.
  * command that will be sent.  
372   */   */
373  void generate_search_filters(char *command)  int
374    imap_append(connection_t * conn, char *mbox, char *flags, char *date, unsigned int size)
375  {  {
     int f = 0;  
     int len;  
376    
377      snprintf(command, BIG_COMMAND_MAX, "%X SEARCH ", tag++);          buffer_reset(&obuf);
378            buffer_check(&obuf, strlen("APPEND") + strlen(mbox) + strlen(flags) +
379                strlen(date) + strlen(ultostr(size, 10)) + 24);
380    
381      while (f < (fcnt - 1)) {          snprintf(obuf.data, obuf.size,
382          len = strlen(command);              "%04X APPEND \"%s\" (%s) \"%s\" {%d}\r\n", tag, mbox, flags, date,
383          snprintf(command + len, BIG_COMMAND_MAX - len, "OR %s%s \"%s\" ",              size);
                  (filters[f]->explicit ? "HEADER " : ""), filters[f]->name,  
                  filters[f]->body);  
         f++;  
     }  
384    
385      len = strlen(command);          return send_command(conn, obuf.data, NULL);
     snprintf(command + len, BIG_COMMAND_MAX - len, "%s%s \"%s\"\r\n",  
              (filters[f]->explicit ? "HEADER " : ""), filters[f]->name,  
              filters[f]->body);  
386  }  }
387    
388    
389    
390  /*  /*
391   * Convert the string with the UID's of the messages to be deleted to   * IMAP CLOSE: delete messages and return to authenticated state.
  * integers, send the appropriate command and maybe print some headers  
  * of the "to be deleted" message.  
392   */   */
393  void delete_messages(char *unwanted)  int
394    imap_close(connection_t * conn)
395  {  {
     unsigned long int messg;  
     char headers[HEADERS_MAX];  
396    
397      do {          buffer_reset(&obuf);
398          messg = strtoul(unwanted, &unwanted, 0);          buffer_check(&obuf, strlen("CLOSE") + 12);
399    
400          imap_fetch(messg, headers);          snprintf(obuf.data, obuf.size, "%04X CLOSE\r\n", tag);
401    
402          if (!(options & OPTION_DETAILS_QUITE)) {          return send_command(conn, obuf.data, NULL);
403              printf("Deleting message:\n%s\n", headers);  }
         }  
404    
405          if (!(options & OPTION_TEST_MODE)) {  
406              log_info("%s\n", headers);  /*
407              imap_store(messg);   * IMAP EXPUNGE: permanently removes any messages with the \Deleted flag set.
408          }   */
409      } while (*unwanted);  int
410    imap_expunge(connection_t * conn)
411    {
412    
413            buffer_reset(&obuf);
414            buffer_check(&obuf, strlen("EXPUNGE") + 12);
415    
416            snprintf(obuf.data, obuf.size, "%04X EXPUNGE\r\n", tag);
417    
418            return send_command(conn, obuf.data, NULL);
419  }  }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.46

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26