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

Diff of /imapfilter/response.c

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

revision 1.17.2.4 by lefcha, Mon Jun 17 12:01:00 2002 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>
9    
10  #include "config.h"  #include "config.h"
11  #include "imapfilter.h"  #include "imapfilter.h"
12    #include "buffer.h"
13    
14    
15    extern connection_t connpri, connaux;
16    extern options_t opts;
17    extern jmp_buf acctloop;
18    
19    buffer_t ibuf;                  /* Input buffer. */
20    
 extern unsigned int options;  
 extern unsigned int capabilities;  
21    
22  char *vbuf = NULL;  void receive_response(connection_t * conn, char *buf);
23  size_t vbufs = 0;  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(char *buf)  void
31    receive_response(connection_t * conn, char *buf)
32  {  {
     socket_read(buf);  
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(unsigned int tag)  int
46    response_generic(connection_t * conn, unsigned int tag)
47    {
48    
49            buffer_reset(&ibuf);
50    
51            do {
52                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
53                    receive_response(conn, ibuf.data + strlen(ibuf.data));
54                    response_bye(ibuf.data);
55            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
56    
57            return analyze_response(conn, ibuf.data);
58    }
59    
60    
61    /*
62     * Check if server sent a BYE response (connection is closed immediately).
63     */
64    void
65    response_bye(char *buf)
66  {  {
     char buf[RESPONSE_BUF];  
       
     reset_vbuf();  
   
     do {  
         receive_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (tag && !strcasestr(buf, ultostr(tag, 16)));  
67    
68      return analyze_response(buf);          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(void)  int
77    response_greeting(connection_t * conn)
78  {  {
     char buf[RESPONSE_BUF];  
79    
80      receive_response(buf);          buffer_reset(&ibuf);
81    
82      if (strcasestr(buf, "BYE"))          receive_response(conn, ibuf.data);
         return RESPONSE_BYE;  
     else if (strcasestr(buf, "PREAUTH"))  
         return RESPONSE_PREAUTH;  
83    
84      return RESPONSE_OK;          verbose("%s: %s", (conn == &connpri ? "S" : "s"), ibuf);
85    
86            response_bye(ibuf.data);
87    
88            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.
97     */
98    int
99    response_logout(connection_t * conn, unsigned int tag)
100    {
101    
102            buffer_reset(&ibuf);
103    
104            do {
105                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
106                    receive_response(conn, ibuf.data + strlen(ibuf.data));
107            } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
108    
109            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(unsigned int tag)  int
117    response_capability(connection_t * conn, unsigned int tag)
118    {
119    
120            buffer_reset(&ibuf);
121    
122            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 AUTHENTICATE client request.
158     */
159    int
160    response_authenticate(connection_t * conn, unsigned int tag, unsigned char **cont)
161  {  {
162      char buf[RESPONSE_BUF];          int i;
163            char *c;
164    
165            buffer_reset(&ibuf);
166    
167            do {
168                    buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
169                    receive_response(conn, ibuf.data + strlen(ibuf.data));
170                    response_bye(ibuf.data);
171            } while (strlen(ibuf.data) == RESPONSE_BUF &&
172                !strcasestr(ibuf.data, ultostr(tag, 16)));
173    
174      reset_vbuf();          if (cont != NULL && ibuf.data[0] == '+' && ibuf.data[1] == ' ') {
175                    c = *cont = (unsigned char *)xmalloc(strlen(ibuf.data) + 1);
176    
177      do {                  for (i = 2; ibuf.data[i] != '\r'; i++)
178          receive_response(buf);                          *c++ = ibuf.data[i];
         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;  
179    
180      return analyze_response(vbuf);                  *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 NAMESPACE client request.   * Process the data that server sent due to IMAP NAMESPACE client request.
189   */   */
190  int namespace_response(unsigned int tag, struct namespace_t * namesp)  int
191    response_namespace(connection_t * conn, unsigned int tag)
192  {  {
193      char buf[RESPONSE_BUF];          char *c, *d;
194      char *c, *d;  
195                buffer_reset(&ibuf);
     reset_vbuf();  
   
     do {  
         receive_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
   
     if ((c = strcasestr(vbuf, "* NAMESPACE"))) {  
         c += 12;  
         if (strncasecmp(c, "NIL", 3)) {  
             c = strchr(c, '"') + 1;  
             d = strchr(c, '"') + 1;  
196    
197              strncat(namesp->prefix, c, d - c - 1);          do {
198              namesp->delim = *(strchr(d, '"') + 1);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
199                    receive_response(conn, ibuf.data + strlen(ibuf.data));
200                    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      return analyze_response(buf);              (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 STATUS client request.   * Process the data that server sent due to IMAP STATUS client request.
222   */   */
223  int status_response(unsigned int tag, char *mbox)  int
224    response_status(connection_t * conn, unsigned int tag, char *mbox)
225    {
226            int r;
227            unsigned int exists, recent, unseen;
228            char *c;
229    
230            exists = recent = unseen = 0;
231    
232            buffer_reset(&ibuf);
233    
234            do {
235                    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            r = analyze_response(conn, ibuf.data);
241    
242            if (r == RESPONSE_NO)
243                    return -2;
244    
245            if ((c = strcasestr(ibuf.data, "MESSAGES"))) {
246                    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            return r;
265    }
266    
267    
268    /*
269     * Process the data that server sent due to IMAP EXAMINE client request.
270     */
271    int
272    response_examine(connection_t * conn, unsigned int tag, char *mbox)
273  {  {
274      int r;          int r;
275      char buf[RESPONSE_BUF];          unsigned int exists, recent, unseen;
276      unsigned int exist, recent, unseen;          char *c;
277      char *c;  
278            exists = recent = unseen = 0;
279      exist = recent = unseen = 0;  
280            buffer_reset(&ibuf);
281      reset_vbuf();  
282                do {
283      do {                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
284          receive_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 (!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);  
287    
288      return r;          r = analyze_response(conn, ibuf.data);
289    
290            if (r == RESPONSE_NO)
291                    return -2;
292    
293            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 r;
317  }  }
318    
319    
320  /*  /*
321   * Process the data that server sent due to IMAP SELECT client request.   * Process the data that server sent due to IMAP SELECT client request.
322   */   */
323  int select_response(unsigned int tag)  int
324    response_select(connection_t * conn, unsigned int tag)
325  {  {
     char buf[RESPONSE_BUF];  
326    
327      reset_vbuf();          buffer_reset(&ibuf);
328        
329      do {          do {
330          receive_response(buf);                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
331          check_vbuf(strlen(buf));                  receive_response(conn, ibuf.data + strlen(ibuf.data));
332          strncat(vbuf, buf, vbufs - strlen(vbuf));                  response_bye(ibuf.data);
333      } while (!strcasestr(buf, ultostr(tag, 16)));          } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
334    
335      if (strcasestr(vbuf, "[READ-ONLY]"))          if (strcasestr(ibuf.data, "[READ-ONLY]"))
336          return RESPONSE_READONLY;                  return RESPONSE_READONLY;
337    
338      return analyze_response(buf);          return analyze_response(conn, ibuf.data);
339  }  }
340    
341    
342  /*  /*
343   * Process the data that server sent due to IMAP SEARCH client request.   * Process the data that server sent due to IMAP SEARCH client request.
344   */   */
345  int search_response(unsigned int tag, char **mesgs)  int
346    response_search(connection_t * conn, unsigned int tag, char **mesgs)
347  {  {
348     char buf[RESPONSE_BUF];          char *c, *m;
349      char *c, *m;          unsigned int blen;
     unsigned int blen;  
   
     reset_vbuf();  
       
     do {  
         receive_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
   
     if ((c = strcasestr(vbuf, "* SEARCH "))) {  
         blen = strlen(vbuf);  
           
         m = *mesgs = (char *) xmalloc(blen + 1);  
           
         c += 9;  
           
         while (*c && (isdigit(*c) || *c == ' '))  
             *(m++) = *(c++);  
350    
351          *m = 0;          buffer_reset(&ibuf);
     }  
352    
353      return analyze_response(buf);          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            if ((c = strcasestr(ibuf.data, "* SEARCH "))) {
360                    blen = strlen(ibuf.data);
361    
362                    m = *mesgs = (char *)xmalloc(blen + 1);
363    
364                    c += 9;
365    
366                    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 FETCH client request.   * Process the data that server sent due to IMAP FETCH client request.
377   */   */
378  int fetch_response(unsigned int tag)  int
379    response_fetch(connection_t * conn, unsigned int tag, int reset, char *fetch)
380  {  {
381      char buf[RESPONSE_BUF];          unsigned int i;
382      char hdrs[HEADERS_BUF];          static unsigned int s;
383      int f;          char *b;
384      unsigned int sa, sb, i, n;  
385      char s[8];          if (reset) {
386      char *b;                  s = 0;
387                    return 0;
388      hdrs[0] = 0;          }
389      sa = sb = i = f = 0;          i = 0;
     s[0] = 0;  
   
     do {  
         receive_response(buf);  
   
         b = buf;  
   
         while (f || (b = strchr(b, '{'))) {  
             /* Headers are continued from previous packet. */  
             if (f) {  
                 f = 0;  
                 for (; i < HEADERS_BUF - 1 && i < sa - 2; i++) {  
                     /* Continued in next packet. */  
                     if (!*b) {  
                         f = 1;  
                         break;  
                     }  
                     hdrs[i] = *(b++);  
                 }  
             } else {  
                 /* Left bracket is last byte of buffer. */  
                 if (b == buf + RESPONSE_BUF - 2) {  
                     receive_response(buf);  
                     b = buf;  
                 } else  
                     b++;  
   
                 sa = atoi(b);  
   
                 /* Headers length may be continued in next packet. */  
                 if (!(b = strchr(b, '}'))) {  
                     receive_response(buf);  
                     if (buf != (b = strchr(buf, '}'))) {  
                         sb = atoi(buf);  
                         strncat(s, ultostr(sa, 10), 7);  
                         strncat(s, ultostr(sb, 10), 7);  
                         sa = atoi(s);  
                         s[0] = 0;  
                     }  
                     b += 3;  
                 } else if ((n = RESPONSE_BUF - 1 - (b - buf)) < 3) {  
                     receive_response(buf);  
                     b = buf + 3 - n;  
                 } else {  
                     b += 3;  
                 }  
   
                 for (i = 0; i < HEADERS_BUF - 1 && i < sa - 2; i++) {  
                     if (!*b) {  
                         f = 1;  
                         break;  
                     }  
                     hdrs[i] = *(b++);  
                 }  
             }  
390    
391              if (!f) {          buffer_reset(&ibuf);
                 hdrs[i] = 0;  
392    
393                  if (*hdrs) {          do {
394                      if (options & OPTION_HEADERS)                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
395                          info("%s\n", hdrs);                  receive_response(conn, ibuf.data + strlen(ibuf.data));
396                      log_info(LOG_WRITE, hdrs);                  response_bye(ibuf.data);
397            } while (strlen(ibuf.data) < RESPONSE_BUF &&
398                !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 {                  } else {
411                      log_info(LOG_WRITE, NULL);                          return RESPONSE_NULLBODY;       /* Null body. */
412                  }                  }
             } else {  
                 break;  
             }  
413          }          }
414      } while (!strcasestr(buf, ultostr(tag, 16)));          while (*b != '\0' && s-- != 0)
415                    fetch[i++] = *(b++);
416    
417            fetch[i] = '\0';
418    
419      return analyze_response(buf);          return analyze_response(conn, ibuf.data);
420  }  }
421    
422    
423  /*  /*
424   * Process the data that server sent due to IMAP COPY client request.   * Process the data that server sent due to IMAP FETCH FAST client request.
425   */   */
426  int copy_response(unsigned int tag)  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      char buf[RESPONSE_BUF];          unsigned int blen;
432    
433      reset_vbuf();          *size = 0;
       
     do {  
         receive_response(buf);  
         check_vbuf(strlen(buf));  
         strncat(vbuf, buf, vbufs - strlen(vbuf));  
     } while (!strcasestr(buf, ultostr(tag, 16)));  
   
     if ((r = analyze_response(buf)) == RESPONSE_NO  
         && strcasestr(vbuf, "[TRYCREATE]"))  
         return RESPONSE_TRYCREATE;  
       
     return r;  
 }  
434    
435            buffer_reset(&ibuf);
436    
437  /*          do {
438   * Check if response of server to client's request was succesfully                  buffer_check(&ibuf, strlen(ibuf.data) + RESPONSE_BUF);
439   * delivered or there was some kind of error.                  receive_response(conn, ibuf.data + strlen(ibuf.data));
440   */                  response_bye(ibuf.data);
441  int analyze_response(char *buf)          } while (!strcasestr(ibuf.data, ultostr(tag, 16)));
 {  
     int r = RESPONSE_OK;  
     regex_t creg;  
     regmatch_t match[3];  
     const char *reg = "[[:xdigit:]]{6,6} ((OK|NO|BAD)[[:print:]]*)\r\n";  
     char result[RESULT_BUF];  
442    
443      result[0] = 0;          if ((c = strcasestr(ibuf.data, "FETCH (FLAGS ("))) {
444                    blen = strlen(ibuf.data);
445    
446      regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);                  m = *flags = (char *)xmalloc(blen + 1);
447    
448      if (!regexec(&creg, buf, 3, match, 0)) {                  c += 14;
         strncat(result, buf + match[1].rm_so,  
                 min(match[1].rm_eo - match[1].rm_so, RESULT_BUF - 1));  
449    
450          if (!strncasecmp(buf + match[2].rm_so, "NO", 2))                  while (*c != '\0' && *c != ')') {
451              r = RESPONSE_NO;                          /* The \Recent flag can not be altered by the client. */
452          else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))                          if (*c == '\\') {
453              r = RESPONSE_BAD;                                  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          verbose("Server response: %s\n", result);                  *m = 0;
463      }          }
464      regfree(&creg);          if ((c = strcasestr(ibuf.data, " INTERNALDATE \""))) {
465                    blen = strlen(ibuf.data);
466    
467      return r;                  m = *date = (char *)xmalloc(blen + 1);
468    
469                    c += 15;
470    
471                    while (*c != '\0' && *c != '"')
472                            *(m++) = *(c++);
473    
474                    *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(4096);          int r;
491      *vbuf = 0;  
492      vbufs = 4096;          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 s)  int
541    analyze_response(connection_t * conn, char *buf)
542  {  {
543      if (s + strlen(vbuf) >= vbufs) {          int r;
544          vbufs += 4096;          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.17.2.4  
changed lines
  Added in v.1.53

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26