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

Diff of /imapfilter/response.c

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

revision 1.23.2.9 by lefcha, Fri Mar 28 16:57:52 2003 UTC revision 1.53 by lefcha, Sun Feb 15 15:31:54 2004 UTC
# Line 1  Line 1 
1  #include <stdio.h>  #include <stdio.h>
 #include <unistd.h>  
2  #include <stdlib.h>  #include <stdlib.h>
 #include <ctype.h>  
 #include <errno.h>  
3  #include <string.h>  #include <string.h>
4  #include <sys/time.h>  #include <strings.h>
5  #include <sys/types.h>  #include <ctype.h>
6    #include <sys/types.h>          /* For POSIX.1-2001 non-conformant systems. */
7  #include <regex.h>  #include <regex.h>
8  #include <setjmp.h>  #include <setjmp.h>
9    
10  #include "config.h"  #include "config.h"
11  #include "imapfilter.h"  #include "imapfilter.h"
12    #include "buffer.h"
13    
14    
15  extern int sockpri;  extern connection_t connpri, connaux;
16  extern unsigned int capabilities;  extern options_t opts;
17  extern jmp_buf acctloop;  extern jmp_buf acctloop;
18    
19  static char *vbuf = NULL;       /* Virtual buffer. */  buffer_t ibuf;                  /* Input buffer. */
20  static size_t vbufs = 0;        /* Virtual buffer size. */  
21    
22    void receive_response(connection_t * conn, char *buf);
23    void response_bye(char *buf);
24    int analyze_response(connection_t * conn, char *buf);
25    
26    
27  /*  /*
28   * Read one packet of data that the server sent.   * Read one packet of data that the server sent.
29   */   */
30  void receive_response(int *sock, char *buf)  void
31    receive_response(connection_t * conn, char *buf)
32  {  {
     if (socket_read(sock, buf) == ERROR_NETWORK)  
         longjmp(acctloop, -1);  
33    
34  #ifdef DEBUG          if (socket_read(conn, buf) == ERROR_NETWORK)
35      printf("\n%s\n", buf);                  longjmp(acctloop, -1);
 #endif  
36    
37            debug("getting response (%s):\n\n%s\n",
38                (conn == &connpri ? "primary" : "auxiliary"), buf);
39  }  }
40    
41    
42  /*  /*
43   * Get server response to client's request.   * Get server response to client's request.
44   */   */
45  int server_response(int *sock, unsigned int tag)  int
46    response_generic(connection_t * conn, unsigned int tag)
47  {  {
     char buf[RESPONSE_BUF + 1];  
48    
49      reset_vbuf();          buffer_reset(&ibuf);
50    
51      do {          do {
52          receive_response(sock, buf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
53          bye_response(buf);                  receive_response(conn, ibuf.data + strlen(ibuf.data));
54          check_vbuf(strlen(buf));                  response_bye(ibuf.data);
55          strncat(vbuf, buf, vbufs - strlen(vbuf));          } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
     } while (tag && !strcasestr(buf, ultostr(tag, 16)));  
56    
57      return analyze_response(buf);          return analyze_response(conn, ibuf.data);
58  }  }
59    
60    
61  /*  /*
62   * Check if server sent a BYE response (connection is closed immediately).   * Check if server sent a BYE response (connection is closed immediately).
63   */   */
64  void bye_response(char *buf)  void
65    response_bye(char *buf)
66  {  {
67      if (strcasestr(buf, "* BYE"))  
68          longjmp(acctloop, -1);          if (strcasestr(buf, "* BYE"))
69                    longjmp(acctloop, -1);
70  }  }
71    
72    
73  /*  /*
74   * Process the greeting that server sends during connection.   * Process the greeting that server sends during connection.
75   */   */
76  int greeting_response(int *sock)  int
77    response_greeting(connection_t * conn)
78  {  {
     char buf[RESPONSE_BUF + 1];  
79    
80      receive_response(sock, buf);          buffer_reset(&ibuf);
81      bye_response(buf);  
82            receive_response(conn, ibuf.data);
83    
84            verbose("%s: %s", (conn == &connpri ? "S" : "s"), ibuf);
85    
86      if (strcasestr(buf, "* PREAUTH"))          response_bye(ibuf.data);
         return RESPONSE_PREAUTH;  
87    
88      return RESPONSE_OK;          if (strcasestr(ibuf.data, "* PREAUTH"))
89                    return RESPONSE_PREAUTH;
90    
91            return RESPONSE_OK;
92  }  }
93    
94    
95  /*  /*
96   * Process the data that server sent due to IMAP LOGOUT client request.   * Process the data that server sent due to IMAP LOGOUT client request.
97   */   */
98  int logout_response(int *sock, unsigned int tag)  int
99    response_logout(connection_t * conn, unsigned int tag)
100  {  {
     char buf[RESPONSE_BUF + 1];  
101    
102      reset_vbuf();          buffer_reset(&ibuf);
103    
104      do {          do {
105          receive_response(sock, buf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
106          check_vbuf(strlen(buf));                  receive_response(conn, ibuf.data + strlen(ibuf.data));
107          strncat(vbuf, buf, vbufs - strlen(vbuf));          } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
     } while (!strcasestr(buf, ultostr(tag, 16)));  
108    
109      return analyze_response(buf);          return analyze_response(conn, ibuf.data);
110  }  }
111    
112    
113  /*  /*
114   * Process the data that server sent due to IMAP CAPABILITY client request.   * Process the data that server sent due to IMAP CAPABILITY client request.
115   */   */
116  int capability_response(int *sock, unsigned int tag)  int
117    response_capability(connection_t * conn, unsigned int tag)
118  {  {
     char buf[RESPONSE_BUF + 1];  
   
     reset_vbuf();  
119    
120      do {          buffer_reset(&ibuf);
         receive_response(sock, buf);  
         bye_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
   
     if (!strcasestr(vbuf, "IMAP4rev1")) {  
         error("imapfilter: server does not support IMAP4rev1 protocol\n");  
         return -2;  
     }  
     if (strcasestr(vbuf, "NAMESPACE"))  
         capabilities |= CAPABILITY_NAMESPACE;  
121    
122      return analyze_response(buf);          do {
123                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
124                    receive_response(conn, ibuf.data + strlen(ibuf.data));
125                    response_bye(ibuf.data);
126            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
127    
128            if (opts.force_protocol == PROTOCOL_NONE) {
129                    if (strcasestr(ibuf.data, "IMAP4rev1"))
130                            conn->proto = PROTOCOL_IMAP4REV1;
131                    else if (strcasestr(ibuf.data, "IMAP4"))
132                            conn->proto = PROTOCOL_IMAP4;
133                    else {
134                            error("server supports neither the IMAP4rev1 nor the "
135                                "IMAP4 protocol\n");
136                            return -2;
137                    }
138            } else
139                    conn->proto = opts.force_protocol;
140    
141            if (strcasestr(ibuf.data, "NAMESPACE"))
142                    conn->caps |= CAPABILITY_NAMESPACE;
143    #ifdef CRAM_MD5
144            if (strcasestr(ibuf.data, "AUTH=CRAM-MD5"))
145                    conn->caps |= CAPABILITY_CRAMMD5;
146    #endif
147    #ifdef SSL_TLS
148            if (strcasestr(ibuf.data, "STARTTLS"))
149                    conn->caps |= CAPABILITY_STARTTLS;
150    #endif
151            return analyze_response(conn, ibuf.data);
152  }  }
153    
154    
155    #ifdef CRAM_MD5
156  /*  /*
157   * Process the data that server sent due to IMAP NAMESPACE client request.   * Process the data that server sent due to IMAP AUTHENTICATE client request.
158   */   */
159  int namespace_response(int *sock, unsigned int tag, namesp_t * nsp)  int
160    response_authenticate(connection_t * conn, unsigned int tag, unsigned char **cont)
161  {  {
162      char buf[RESPONSE_BUF + 1];          int i;
163      char *c, *d;          char *c;
164    
165      reset_vbuf();          buffer_reset(&ibuf);
166    
167      do {          do {
168          receive_response(sock, buf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
169          bye_response(buf);                  receive_response(conn, ibuf.data + strlen(ibuf.data));
170          check_vbuf(strlen(buf));                  response_bye(ibuf.data);
171          strncat(vbuf, buf, vbufs - strlen(vbuf));          } while (strlen(ibuf.data) == RESPONSE_BUF &&
172      } while (!strcasestr(buf, ultostr(tag, 16)));              !strcasestr(ibuf.data, ultostr(tag, 16)));
   
     if ((c = strcasestr(vbuf, "* NAMESPACE"))) {  
         c += 12;  
         if (strncasecmp(c, "NIL", 3)) {  
             c = strchr(c, '"') + 1;  
             d = strchr(c, '"') + 1;  
   
             strncat(nsp->prefix, c, d - c - 1);  
             nsp->delim = *(strchr(d, '"') + 1);  
         }  
     }  
 #ifdef DEBUG  
     printf("debug: namespace: '%s' '%c'\n", nsp->prefix, nsp->delim);  
 #endif  
     return analyze_response(buf);  
 }  
173    
174            if (cont != NULL && ibuf.data[0] == '+' && ibuf.data[1] == ' ') {
175                    c = *cont = (unsigned char *)xmalloc(strlen(ibuf.data) + 1);
176    
177  /*                  for (i = 2; ibuf.data[i] != '\r'; i++)
178   * Process the data that server sent due to IMAP STATUS client request.                          *c++ = ibuf.data[i];
  */  
 int status_response(int *sock, unsigned int tag, char *mbox)  
 {  
     int r;  
     char buf[RESPONSE_BUF + 1];  
     unsigned int exist, recent, unseen;  
     char *c;  
   
     exist = recent = unseen = 0;  
   
     reset_vbuf();  
   
     do {  
         receive_response(sock, buf);  
         bye_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
   
     r = analyze_response(buf);  
   
     if (r == RESPONSE_NO)  
         return -2;  
   
     if ((c = strcasestr(vbuf, "MESSAGES"))) {  
         c += 9;  
         exist = strtoul(c, NULL, 10);  
     }  
     if ((c = strcasestr(vbuf, "RECENT"))) {  
         c += 7;  
         recent = strtoul(c, NULL, 10);  
     }  
     if ((c = strcasestr(vbuf, "UNSEEN"))) {  
         c += 7;  
         unseen = strtoul(c, NULL, 10);  
     }  
     if (!exist) {  
         info("No messages in mailbox \"%s\".\n", mbox);  
         return -2;  
     }  
     info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n", exist,  
          plural(exist), recent, unseen, mbox);  
179    
180      return r;                  *c = '\0';
181            }
182            return analyze_response(conn, ibuf.data);
183  }  }
184    #endif
185    
186    
187  /*  /*
188   * Process the data that server sent due to IMAP SELECT client request.   * Process the data that server sent due to IMAP NAMESPACE client request.
189   */   */
190  int select_response(int *sock, unsigned int tag)  int
191    response_namespace(connection_t * conn, unsigned int tag)
192  {  {
193      char buf[RESPONSE_BUF + 1];          char *c, *d;
   
     reset_vbuf();  
194    
195      do {          buffer_reset(&ibuf);
         receive_response(sock, buf);  
         bye_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
196    
197      if (strcasestr(vbuf, "[READ-ONLY]"))          do {
198          return RESPONSE_READONLY;                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
199                    receive_response(conn, ibuf.data + strlen(ibuf.data));
200      return analyze_response(buf);                  response_bye(ibuf.data);
201            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
202    
203            if ((c = strcasestr(ibuf.data, "* NAMESPACE"))) {
204                    c += 12;
205                    if (strncasecmp(c, "NIL", 3)) {
206                            c = strchr(c, '"') + 1;
207                            d = strchr(c, '"') + 1;
208    
209                            strncat(conn->ns.prefix, c, d - c - 1);
210                            conn->ns.delim = *(strchr(d, '"') + 1);
211                    }
212            }
213            debug("namespace (%s): '%s' '%c'\n",
214                (conn == &connpri ? "primary" : "auxiliary"), conn->ns.prefix,
215                conn->ns.delim);
216            return analyze_response(conn, ibuf.data);
217  }  }
218    
219    
220  /*  /*
221   * Process the data that server sent due to IMAP SEARCH client request.   * Process the data that server sent due to IMAP STATUS client request.
222   */   */
223  int search_response(int *sock, unsigned int tag, char **mesgs)  int
224    response_status(connection_t * conn, unsigned int tag, char *mbox)
225  {  {
226      char buf[RESPONSE_BUF + 1];          int r;
227      char *c, *m;          unsigned int exists, recent, unseen;
228      unsigned int blen;          char *c;
229    
230      reset_vbuf();          exists = recent = unseen = 0;
231    
232      do {          buffer_reset(&ibuf);
         receive_response(sock, buf);  
         bye_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
233    
234      if ((c = strcasestr(vbuf, "* SEARCH "))) {          do {
235          blen = strlen(vbuf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
236                    receive_response(conn, ibuf.data + strlen(ibuf.data));
237                    response_bye(ibuf.data);
238            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
239    
240          m = *mesgs = (char *)xmalloc(blen + 1);          r = analyze_response(conn, ibuf.data);
241    
242          c += 9;          if (r == RESPONSE_NO)
243                    return -2;
244    
245          while (*c && (isdigit((unsigned char)(*c)) || *c == ' '))          if ((c = strcasestr(ibuf.data, "MESSAGES"))) {
246              *(m++) = *(c++);                  c += 9;
247                    exists = strtoul(c, NULL, 10);
248            }
249            if (exists == 0) {
250                    info("No messages in mailbox \"%s\".\n", mbox);
251                    return -2;
252            }
253            if ((c = strcasestr(ibuf.data, "RECENT"))) {
254                    c += 7;
255                    recent = strtoul(c, NULL, 10);
256            }
257            if ((c = strcasestr(ibuf.data, "UNSEEN"))) {
258                    c += 7;
259                    unseen = strtoul(c, NULL, 10);
260            }
261            info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n",
262                exists, plural(exists), recent, unseen, mbox);
263    
264          *m = 0;          return r;
     }  
     return analyze_response(buf);  
265  }  }
266    
267    
268  /*  /*
269   * Process the data that server sent due to IMAP FETCH client request.   * Process the data that server sent due to IMAP EXAMINE client request.
270   */   */
271  int fetch_response(int *sock, unsigned int tag, int reset, char *fetch)  int
272    response_examine(connection_t * conn, unsigned int tag, char *mbox)
273  {  {
274      char buf[RESPONSE_BUF + 1];          int r;
275      unsigned int i;          unsigned int exists, recent, unseen;
276      static unsigned int s;          char *c;
     char *b;  
277    
278      if (reset) {          exists = recent = unseen = 0;
         s = 0;  
         return 0;  
     }  
     i = 0;  
279    
280      reset_vbuf();          buffer_reset(&ibuf);
281    
282      do {          do {
283          receive_response(sock, buf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
284          bye_response(buf);                  receive_response(conn, ibuf.data + strlen(ibuf.data));
285          check_vbuf(strlen(buf));                  response_bye(ibuf.data);
286          strncat(vbuf, buf, vbufs - strlen(vbuf));          } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
     } while (strlen(vbuf) < RESPONSE_BUF &&  
              !strcasestr(buf, ultostr(tag, 16)));  
287    
288      b = vbuf;          r = analyze_response(conn, ibuf.data);
289    
290      if (!s) {          if (r == RESPONSE_NO)
291          if ((b = strstr(b, "}\r\n"))) {                  return -2;
             while (b - vbuf > 0)  
                 if (*--b == '{')  
                     break;  
             s = atoi(++b) - 2;  
             b = strchr(b, '}');  
             b += 3;  
         } else {  
             return RESPONSE_NULLBODY;   /* Null body. */  
         }  
     }  
     while (*b && s--)  
         fetch[i++] = *(b++);  
292    
293      fetch[i] = 0;          if ((c = strcasestr(ibuf.data, "EXISTS"))) {
294                    while (--c >= ibuf.data && *c != '*');
295                    c++;
296                    exists = strtoul(c, NULL, 10);
297            }
298            if (exists == 0) {
299                    info("No messages in mailbox \"%s\".\n", mbox);
300                    return -2;
301            }
302            if ((c = strcasestr(ibuf.data, "RECENT"))) {
303                    while (--c >= ibuf.data && *c != '*');
304                    c++;
305                    recent = strtoul(c, NULL, 10);
306            }
307            if ((c = strcasestr(ibuf.data, "UNSEEN"))) {
308                    c += 7;
309                    unseen = strtoul(c, NULL, 10);
310                    info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n",
311                        exists, plural(exists), recent, unseen, mbox);
312            } else
313                    info("%d message%s, %d recent, in mailbox \"%s\".\n", exists,
314                        plural(exists), recent, mbox);
315    
316      return analyze_response(buf);          return r;
317  }  }
318    
319    
320  /*  /*
321   * Process the data that server sent due to IMAP FETCH RFC822.SIZE client   * Process the data that server sent due to IMAP SELECT client request.
  * request.  
322   */   */
323  int fetchsize_response(int *sock, unsigned int *size, unsigned int tag)  int
324    response_select(connection_t * conn, unsigned int tag)
325  {  {
     char buf[RESPONSE_BUF + 1];  
     char *c;  
326    
327      *size = 0;          buffer_reset(&ibuf);
328    
329      reset_vbuf();          do {
330                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
331                    receive_response(conn, ibuf.data + strlen(ibuf.data));
332                    response_bye(ibuf.data);
333            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
334    
335      do {          if (strcasestr(ibuf.data, "[READ-ONLY]"))
336          receive_response(sock, buf);                  return RESPONSE_READONLY;
         bye_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
337    
338      if ((c = strcasestr(vbuf, "FETCH (RFC822.SIZE "))) {          return analyze_response(conn, ibuf.data);
         c += 19;  
         *size = strtoul(c, NULL, 10);  
     }  
     return analyze_response(buf);  
339  }  }
340    
341    
342  /*  /*
343   * Process the data that server sent due to IMAP APPEND client request.   * Process the data that server sent due to IMAP SEARCH client request.
344   */   */
345  int append_response(int *sock, unsigned int tag)  int
346    response_search(connection_t * conn, unsigned int tag, char **mesgs)
347  {  {
348      int r = RESPONSE_OK;          char *c, *m;
349      char buf[RESPONSE_BUF + 1];          unsigned int blen;
350    
351            buffer_reset(&ibuf);
352    
353            do {
354                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
355                    receive_response(conn, ibuf.data + strlen(ibuf.data));
356                    response_bye(ibuf.data);
357            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
358    
359      reset_vbuf();          if ((c = strcasestr(ibuf.data, "* SEARCH "))) {
360                    blen = strlen(ibuf.data);
361    
362      do {                  m = *mesgs = (char *)xmalloc(blen + 1);
         receive_response(sock, buf);  
         bye_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
363    
364      if ((r = analyze_response(buf)) == RESPONSE_NO &&                  c += 9;
         strcasestr(vbuf, "[TRYCREATE]"))  
         return RESPONSE_TRYCREATE;  
365    
366      return r;                  while (*c != '\0' && (isdigit(*c) || *c == ' '))
367                            *(m++) = *(c++);
368    
369                    *m = 0;
370            }
371            return analyze_response(conn, ibuf.data);
372  }  }
373    
374    
375  /*  /*
376   * Process the data that server sent due to IMAP COPY client request.   * Process the data that server sent due to IMAP FETCH client request.
377   */   */
378  int copy_response(int *sock, unsigned int tag)  int
379    response_fetch(connection_t * conn, unsigned int tag, int reset, char *fetch)
380  {  {
381      int r = RESPONSE_OK;          unsigned int i;
382      char buf[RESPONSE_BUF + 1];          static unsigned int s;
383            char *b;
384    
385            if (reset) {
386                    s = 0;
387                    return 0;
388            }
389            i = 0;
390    
391      reset_vbuf();          buffer_reset(&ibuf);
392    
393      do {          do {
394          receive_response(sock, buf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
395          bye_response(buf);                  receive_response(conn, ibuf.data + strlen(ibuf.data));
396          check_vbuf(strlen(buf));                  response_bye(ibuf.data);
397          strncat(vbuf, buf, vbufs - strlen(vbuf));          } while (strlen(ibuf.data) < RESPONSE_BUF &&
398      } while (!strcasestr(buf, ultostr(tag, 16)));              !strcasestr(ibuf.data, ultostr(tag, 16)));
399    
400            b = ibuf.data;
401    
402            if (s == 0) {
403                    if ((b = strstr(b, "}\r\n"))) {
404                            while (b - ibuf.data > 0)
405                                    if (*--b == '{')
406                                            break;
407                            s = atoi(++b) - 2;
408                            b = strchr(b, '}');
409                            b += 3;
410                    } else {
411                            return RESPONSE_NULLBODY;       /* Null body. */
412                    }
413            }
414            while (*b != '\0' && s-- != 0)
415                    fetch[i++] = *(b++);
416    
417      if ((r = analyze_response(buf)) == RESPONSE_NO &&          fetch[i] = '\0';
         strcasestr(vbuf, "[TRYCREATE]"))  
         return RESPONSE_TRYCREATE;  
418    
419      return r;          return analyze_response(conn, ibuf.data);
420  }  }
421    
422    
423  /*  /*
424   * Check if response of server to client's request was succesfully   * Process the data that server sent due to IMAP FETCH FAST client request.
  * delivered or there was some kind of error.  
425   */   */
426  int analyze_response(char *buf)  int
427    response_fetchfast(connection_t * conn, char **flags, char **date,
428        unsigned int *size, unsigned int tag)
429  {  {
430      int r = RESPONSE_OK;          char *c, *m;
431      regex_t creg;          unsigned int blen;
432      regmatch_t match[3];  
433      const char *reg = "[[:xdigit:]]{6,6} ((OK|NO|BAD)[[:print:]]*)\r\n";          *size = 0;
434      char result[RESULT_BUF];  
435            buffer_reset(&ibuf);
436    
437      result[0] = 0;          do {
438                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
439                    receive_response(conn, ibuf.data + strlen(ibuf.data));
440                    response_bye(ibuf.data);
441            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
442    
443      regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);          if ((c = strcasestr(ibuf.data, "FETCH (FLAGS ("))) {
444                    blen = strlen(ibuf.data);
445    
446      if (!regexec(&creg, buf, 3, match, 0)) {                  m = *flags = (char *)xmalloc(blen + 1);
447          strncat(result, buf + match[1].rm_so,  
448                  min(match[1].rm_eo - match[1].rm_so, RESULT_BUF - 1));                  c += 14;
449    
450                    while (*c != '\0' && *c != ')') {
451                            /* The \Recent flag can not be altered by the client. */
452                            if (*c == '\\') {
453                                    if (strcasestr(c - 1, "(\\Recent)") ||
454                                        strcasestr(c - 1, " \\Recent)"))
455                                            break;
456                                    else if (strcasestr(c, "\\Recent "))
457                                            c += 8;
458                            }
459                            *(m++) = *(c++);
460                    }
461    
462                    *m = 0;
463            }
464            if ((c = strcasestr(ibuf.data, " INTERNALDATE \""))) {
465                    blen = strlen(ibuf.data);
466    
467          if (!strncasecmp(buf + match[2].rm_so, "NO", 2))                  m = *date = (char *)xmalloc(blen + 1);
             r = RESPONSE_NO;  
         else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))  
             r = RESPONSE_BAD;  
468    
469          verbose("Server response: %s\n", result);                  c += 15;
     } else  
         r = RESPONSE_NONE;  
470    
471      regfree(&creg);                  while (*c != '\0' && *c != '"')
472                            *(m++) = *(c++);
473    
474      return r;                  *m = 0;
475            }
476            if ((c = strcasestr(ibuf.data, " RFC822.SIZE "))) {
477                    c += 13;
478                    *size = strtoul(c, NULL, 10);
479            }
480            return analyze_response(conn, ibuf.data);
481  }  }
482    
483    
484  /*  /*
485   * Initialize virtual buffer.   * Process the data that server sent due to IMAP APPEND client request.
486   */   */
487  void init_vbuf(void)  int
488    response_append(connection_t * conn, unsigned int tag)
489  {  {
490      vbuf = xmalloc(VIRTUAL_BUF);          int r;
491      *vbuf = 0;  
492      vbufs = VIRTUAL_BUF;          r = RESPONSE_OK;
493    
494            buffer_reset(&ibuf);
495    
496            do {
497                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
498                    receive_response(conn, ibuf.data + strlen(ibuf.data));
499                    response_bye(ibuf.data);
500            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
501    
502            if ((r = analyze_response(conn, ibuf.data)) == RESPONSE_NO &&
503                strcasestr(ibuf.data, "[TRYCREATE]"))
504                    return RESPONSE_TRYCREATE;
505    
506            return r;
507  }  }
508    
509    
510  /*  /*
511   * Reset virtual buffer.   * Process the data that server sent due to IMAP COPY client request.
512   */   */
513  void reset_vbuf(void)  int
514    response_copy(connection_t * conn, unsigned int tag)
515  {  {
516      *vbuf = 0;          int r;
517    
518            r = RESPONSE_OK;
519    
520            buffer_reset(&ibuf);
521    
522            do {
523                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
524                    receive_response(conn, ibuf.data + strlen(ibuf.data));
525                    response_bye(ibuf.data);
526            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
527    
528            if ((r = analyze_response(conn, ibuf.data)) == RESPONSE_NO &&
529                strcasestr(ibuf.data, "[TRYCREATE]"))
530                    return RESPONSE_TRYCREATE;
531    
532            return r;
533  }  }
534    
535    
536  /*  /*
537   * Check if virtual buffer is full and make it bigger.   * Check if response of server to client's request was succesfully
538     * delivered or there was some kind of error.
539   */   */
540  void check_vbuf(size_t n)  int
541    analyze_response(connection_t * conn, char *buf)
542  {  {
543      if (n + strlen(vbuf) >= vbufs) {          int r;
544          vbufs += VIRTUAL_BUF;          regex_t creg;
545          vbuf = xrealloc(vbuf, vbufs);          regmatch_t match[3];
546      }          const char *reg;
547            char result[RESULT_BUF];
548    
549            r = RESPONSE_OK;
550            reg = "[[:xdigit:]]{4,4} ((OK|NO|BAD)[[:print:]]*)\r\n";
551            result[0] = '\0';
552    
553            regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
554    
555            if (!regexec(&creg, buf, 3, match, 0)) {
556                    strncat(result, buf + match[1].rm_so,
557                        min(match[1].rm_eo - match[1].rm_so, RESULT_BUF - 1));
558    
559                    if (!strncasecmp(buf + match[2].rm_so, "NO", 2))
560                            r = RESPONSE_NO;
561                    else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))
562                            r = RESPONSE_BAD;
563    
564                    verbose("%s: %s", (conn == &connpri ? "S" : "s"),
565                        buf + match[0].rm_so);
566            } else
567                    r = RESPONSE_NONE;
568    
569            regfree(&creg);
570    
571            return r;
572  }  }

Legend:
Removed from v.1.23.2.9  
changed lines
  Added in v.1.53

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26