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

Diff of /imapfilter/response.c

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

revision 1.19 by lefcha, Fri Jan 25 17:10:17 2002 UTC revision 1.20 by lefcha, Tue Jun 18 21:21:47 2002 UTC
# Line 12  Line 12 
12  #include "imapfilter.h"  #include "imapfilter.h"
13    
14    
15    extern int sockpri;
16  extern unsigned int options;  extern unsigned int options;
17  extern unsigned int capabilities;  extern unsigned int capabilities;
18    
19    static char *vbuf = NULL;       /* Virtual buffer. */
20    static size_t vbufs = 0;        /* Virtual buffer size. */
21    
22    
23  /*  /*
24   * Read one packet of data that the server sent.   * Read one packet of data that the server sent.
25   */   */
26  void receive_response(char *buf)  void receive_response(int *sock, char *buf)
27  {  {
28      socket_read(buf);      socket_read(sock, buf);
29    
30  #ifdef DEBUG  #ifdef DEBUG
31      printf("\n%s\n", buf);      printf("\n%s\n", buf);
# Line 33  void receive_response(char *buf) Line 37  void receive_response(char *buf)
37  /*  /*
38   * Get server response to client's request.   * Get server response to client's request.
39   */   */
40  int server_response(unsigned int tag)  int server_response(int *sock, unsigned int tag)
41  {  {
42      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
43    
44      do      reset_vbuf();
45          receive_response(buf);      
46      while (tag && !strcasestr(buf, ultostr(tag, 16)));      do {
47            receive_response(sock, buf);
48            check_vbuf(strlen(buf));
49            strncat(vbuf, buf, vbufs - strlen(vbuf));
50        } while (tag && !strcasestr(buf, ultostr(tag, 16)));
51    
52      return analyze_response(buf);      return analyze_response(buf);
53  }  }
# Line 48  int server_response(unsigned int tag) Line 56  int server_response(unsigned int tag)
56  /*  /*
57   * Process the greeting that server sends during connection.   * Process the greeting that server sends during connection.
58   */   */
59  int greeting_response(void)  int greeting_response(int *sock)
60  {  {
61      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
62    
63      receive_response(buf);      receive_response(sock, buf);
64    
65      if (strcasestr(buf, "BYE"))      if (strcasestr(buf, "BYE"))
66          return RESPONSE_BYE;          return RESPONSE_BYE;
# Line 66  int greeting_response(void) Line 74  int greeting_response(void)
74  /*  /*
75   * Process the data that server sent due to IMAP CAPABILITY client request.   * Process the data that server sent due to IMAP CAPABILITY client request.
76   */   */
77  int capability_response(unsigned int tag)  int capability_response(int *sock, unsigned int tag)
78  {  {
79      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
80        
81        reset_vbuf();
82    
83      do      do {
84          receive_response(buf);          receive_response(sock, buf);
85      while (!strcasestr(buf, ultostr(tag, 16)));          check_vbuf(strlen(buf));
86            strncat(vbuf, buf, vbufs - strlen(vbuf));
87        } while (!strcasestr(buf, ultostr(tag, 16)));
88    
89      if (!strcasestr(buf, "IMAP4rev1")) {      if (!strcasestr(vbuf, "IMAP4rev1")) {
90          error("imapfilter: server does not support IMAP4rev1 protocol\n");          error("imapfilter: server does not support IMAP4rev1 protocol\n");
91          return -2;          return -2;
92      }      }
93      if (strcasestr(buf, "NAMESPACE"))      if (strcasestr(vbuf, "NAMESPACE"))
94          capabilities |= CAPABILITY_NAMESPACE;          capabilities |= CAPABILITY_NAMESPACE;
95    
96      return analyze_response(buf);      return analyze_response(buf);
# Line 88  int capability_response(unsigned int tag Line 100  int capability_response(unsigned int tag
100  /*  /*
101   * Process the data that server sent due to IMAP NAMESPACE client request.   * Process the data that server sent due to IMAP NAMESPACE client request.
102   */   */
103  int namespace_response(unsigned int tag, char *prefix, char delim)  int namespace_response(int *sock, unsigned int tag, namesp_t *nsp)
104  {  {
105      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
106      char *c, *d;      char *c, *d;
107    
108      do      reset_vbuf();
109          receive_response(buf);      
110      while (!strcasestr(buf, ultostr(tag, 16)));      do {
111            check_vbuf(strlen(buf));
112            strncat(vbuf, buf, vbufs - strlen(vbuf));      
113            receive_response(sock, buf);
114        } while (!strcasestr(buf, ultostr(tag, 16)));
115    
116      if ((c = strcasestr(buf, "* NAMESPACE"))) {      if ((c = strcasestr(vbuf, "* NAMESPACE"))) {
117          c += 12;          c += 12;
118          if (strncasecmp(c, "NIL", 3)) {          if (strncasecmp(c, "NIL", 3)) {
119              c = strchr(c, '"') + 1;              c = strchr(c, '"') + 1;
120              d = strchr(c, '"') + 1;              d = strchr(c, '"') + 1;
121    
122              strncat(prefix, c, d - c - 1);              strncat(nsp->prefix, c, d - c - 1);
123              delim = *(strchr(d, '"') + 1);              nsp->delim = *(strchr(d, '"') + 1);
124          }          }
125      }      }
126    #ifdef DEBUG
127        printf("debug: namespace: '%s' '%c'\n", nsp->prefix, nsp->delim);
128    #endif
129      return analyze_response(buf);      return analyze_response(buf);
130  }  }
131    
# Line 114  int namespace_response(unsigned int tag, Line 133  int namespace_response(unsigned int tag,
133  /*  /*
134   * Process the data that server sent due to IMAP STATUS client request.   * Process the data that server sent due to IMAP STATUS client request.
135   */   */
136  int status_response(unsigned int tag, char *mbox)  int status_response(int *sock, unsigned int tag, char *mbox)
137  {  {
138      int r;      int r;
139      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
# Line 122  int status_response(unsigned int tag, ch Line 141  int status_response(unsigned int tag, ch
141      char *c;      char *c;
142    
143      exist = recent = unseen = 0;      exist = recent = unseen = 0;
144        
145        reset_vbuf();
146    
147      do      do {
148          receive_response(buf);          receive_response(sock, buf);
149      while (!strcasestr(buf, ultostr(tag, 16)));          check_vbuf(strlen(buf));
150            strncat(vbuf, buf, vbufs - strlen(vbuf));
151        } while (!strcasestr(buf, ultostr(tag, 16)));
152    
153      r = analyze_response(buf);      r = analyze_response(buf);
154    
155      if (r == RESPONSE_NO)      if (r == RESPONSE_NO)
156          return -2;          return -2;
157    
158      if ((c = strcasestr(buf, "MESSAGES"))) {      if ((c = strcasestr(vbuf, "MESSAGES"))) {
159          c += 9;          c += 9;
160          exist = strtoul(c, NULL, 10);          exist = strtoul(c, NULL, 10);
161      }      }
162      if ((c = strcasestr(buf, "RECENT"))) {      if ((c = strcasestr(vbuf, "RECENT"))) {
163          c += 7;          c += 7;
164          recent = strtoul(c, NULL, 10);          recent = strtoul(c, NULL, 10);
165      }      }
166      if ((c = strcasestr(buf, "UNSEEN"))) {      if ((c = strcasestr(vbuf, "UNSEEN"))) {
167          c += 7;          c += 7;
168          unseen = strtoul(c, NULL, 10);          unseen = strtoul(c, NULL, 10);
169      }      }
# Line 158  int status_response(unsigned int tag, ch Line 181  int status_response(unsigned int tag, ch
181  /*  /*
182   * Process the data that server sent due to IMAP SELECT client request.   * Process the data that server sent due to IMAP SELECT client request.
183   */   */
184  int select_response(unsigned int tag)  int select_response(int *sock, unsigned int tag)
185  {  {
186      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
187    
188      do      reset_vbuf();
189          receive_response(buf);      
190      while (!strcasestr(buf, ultostr(tag, 16)));      do {
191            receive_response(sock, buf);
192            check_vbuf(strlen(buf));
193            strncat(vbuf, buf, vbufs - strlen(vbuf));
194        } while (!strcasestr(buf, ultostr(tag, 16)));
195    
196      if (strcasestr(buf, "[READ-ONLY]"))      if (strcasestr(vbuf, "[READ-ONLY]"))
197          return RESPONSE_READONLY;          return RESPONSE_READONLY;
198    
199      return analyze_response(buf);      return analyze_response(buf);
# Line 176  int select_response(unsigned int tag) Line 203  int select_response(unsigned int tag)
203  /*  /*
204   * Process the data that server sent due to IMAP SEARCH client request.   * Process the data that server sent due to IMAP SEARCH client request.
205   */   */
206  int search_response(unsigned int tag, char **mesgs)  int search_response(int *sock, unsigned int tag, char **mesgs)
207  {  {
208      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
209      char *c, *m;      char *c, *m;
210      int f;      unsigned int blen;
     unsigned int blen, mlen;  
   
     f = blen = mlen = 0;  
211    
212        reset_vbuf();
213        
214      do {      do {
215          receive_response(buf);          receive_response(sock, buf);
216            check_vbuf(strlen(buf));
217          if (f) {                /* Search results are continued from          strncat(vbuf, buf, vbufs - strlen(vbuf));
                                    previous packet. */  
             c = buf;  
             blen = strlen(buf);  
             mlen = strlen(*mesgs);  
   
             *mesgs = (char *) xrealloc(*mesgs, mlen + blen + 1);  
             m = *mesgs + mlen;  
   
             while (*c && (isdigit(*c) || *c == ' '))  
                 *(m++) = *(c++);  
             *m = 0;  
         } else if ((c = strcasestr(buf, "* SEARCH "))) {  
             f = 1;  
             blen = strlen(buf);  
   
             m = *mesgs = (char *) xmalloc(blen + 1);  
             c += 9;  
   
             while (*c && (isdigit(*c) || *c == ' '))  
                 *(m++) = *(c++);  
             *m = 0;  
         }  
218      } while (!strcasestr(buf, ultostr(tag, 16)));      } while (!strcasestr(buf, ultostr(tag, 16)));
219    
220        if ((c = strcasestr(vbuf, "* SEARCH "))) {
221            blen = strlen(vbuf);
222            
223            m = *mesgs = (char *) xmalloc(blen + 1);
224            
225            c += 9;
226            
227            while (*c && (isdigit(*c) || *c == ' '))
228                *(m++) = *(c++);
229    
230            *m = 0;
231        }
232    
233      return analyze_response(buf);      return analyze_response(buf);
234  }  }
235    
# Line 220  int search_response(unsigned int tag, ch Line 237  int search_response(unsigned int tag, ch
237  /*  /*
238   * Process the data that server sent due to IMAP FETCH client request.   * Process the data that server sent due to IMAP FETCH client request.
239   */   */
240  int fetch_response(unsigned int tag)  int fetch_response(int *sock, int reset, char *fetch, unsigned int tag)
241  {  {
242      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
243      char hdrs[HEADERS_BUF];      unsigned int i;
244      int f;      static unsigned int s;
     unsigned int sa, sb, i, n;  
     char s[8];  
245      char *b;      char *b;
246    
247      hdrs[0] = 0;      if (reset) {
248      sa = sb = i = f = 0;          s = 0;
249      s[0] = 0;          return 0;
250        }
251        
252        i = 0;
253    
254        receive_response(sock, buf);
255    
256        b = buf;
257        
258        if (!s) {
259            b = strchr(b, '{');
260            b++;
261            s  = atoi(b) - 2;
262            b = strchr(b, '}');
263            b += 3;
264        }
265        
266        while (*b && s--)
267            fetch[i++] = *(b++);
268    
269        fetch[i] = 0;
270        
271        return analyze_response(buf);
272    }
273    
274    
275    /*
276     * Process the data that server sent due to IMAP FETCH RFC822.SIZE client
277     * request.
278     */
279    int fetchsize_response(int *sock, unsigned int *size, unsigned int tag)
280    {
281        char buf[RESPONSE_BUF];
282        char *c;
283        
284        *size = 0;
285        
286        reset_vbuf();
287        
288      do {      do {
289          receive_response(buf);          receive_response(sock, buf);
290            check_vbuf(strlen(buf));
291            strncat(vbuf, buf, vbufs - strlen(vbuf));
292        } while (!strcasestr(buf, ultostr(tag, 16)));
293        
294        if ((c = strcasestr(vbuf, "FETCH (RFC822.SIZE "))) {
295            c += 19;
296            *size = strtoul(c, NULL, 10);
297        }
298        
299        return analyze_response(buf);
300    }
301    
         b = buf;  
302    
303          while (f || (b = strchr(b, '{'))) {  /*
304              /* Headers are continued from previous packet. */   * Process the data that server sent due to IMAP APPEND client request.
305              if (f) {   */
306                  f = 0;  int append_response(int *sock, unsigned int tag)
307                  for (; i < HEADERS_BUF - 1 && i < sa - 2; i++) {  {
308                      /* Continued in next packet. */      int r = RESPONSE_OK;
309                      if (!*b) {      char buf[RESPONSE_BUF];
310                          f = 1;      
311                          break;      reset_vbuf();
312                      }      
313                      hdrs[i] = *(b++);      do {
314                  }          receive_response(sock, buf);
315              } else {          check_vbuf(strlen(buf));
316                  /* Left bracket is last byte of buffer. */          strncat(vbuf, buf, vbufs - strlen(vbuf));
                 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++);  
                 }  
             }  
   
             if (!f) {  
                 hdrs[i] = 0;  
   
                 if (*hdrs) {  
                     if (options & OPTION_HEADERS)  
                         info("%s\n", hdrs);  
                     log_info(LOG_WRITE, hdrs);  
                 } else {  
                     log_info(LOG_WRITE, NULL);  
                 }  
             } else {  
                 break;  
             }  
         }  
317      } while (!strcasestr(buf, ultostr(tag, 16)));      } while (!strcasestr(buf, ultostr(tag, 16)));
318        
319        if ((r = analyze_response(buf)) == RESPONSE_NO &&
320            strcasestr(vbuf, "[TRYCREATE]"))
321            return RESPONSE_TRYCREATE;
322    
323      return analyze_response(buf);      return r;
324  }  }
325    
326    
327  /*  /*
328   * Process the data that server sent due to IMAP COPY client request.   * Process the data that server sent due to IMAP COPY client request.
329   */   */
330  int copy_response(unsigned int tag)  int copy_response(int *sock, unsigned int tag)
331  {  {
332      int r = RESPONSE_OK;      int r = RESPONSE_OK;
       
333      char buf[RESPONSE_BUF];      char buf[RESPONSE_BUF];
334        
335        reset_vbuf();
336    
337      do      do {
338          receive_response(buf);          receive_response(sock, buf);
339      while (!strcasestr(buf, ultostr(tag, 16)));          check_vbuf(strlen(buf));
340            strncat(vbuf, buf, vbufs - strlen(vbuf));
341        } while (!strcasestr(buf, ultostr(tag, 16)));
342    
343      if ((r = analyze_response(buf)) == RESPONSE_NO &&      if ((r = analyze_response(buf)) == RESPONSE_NO &&
344          strcasestr(buf, "[TRYCREATE]"))          strcasestr(vbuf, "[TRYCREATE]"))
345          return RESPONSE_TRYCREATE;          return RESPONSE_TRYCREATE;
346    
347      return r;      return r;
# Line 354  int analyze_response(char *buf) Line 374  int analyze_response(char *buf)
374              r = RESPONSE_BAD;              r = RESPONSE_BAD;
375    
376          verbose("Server response: %s\n", result);          verbose("Server response: %s\n", result);
377      }      } else
378            r = RESPONSE_NONE;
379        
380      regfree(&creg);      regfree(&creg);
381    
382      return r;      return r;
383  }  }
384    
385    
386    /*
387     * Initialize virtual buffer.
388     */
389    void init_vbuf(void)
390    {
391        vbuf = xmalloc(4096);
392        *vbuf = 0;
393        vbufs = 4096;
394    }
395    
396    
397    /*
398     * Reset virtual buffer.
399     */
400    void reset_vbuf(void)
401    {
402        *vbuf = 0;
403    }
404    
405    
406    /*
407     * Check if virtual buffer is full and make it bigger.
408     */
409    void check_vbuf(size_t n)
410    {
411        if (n + strlen(vbuf) >= vbufs) {
412            vbufs += 4096;
413            vbuf = xrealloc(vbuf, vbufs);
414        }
415    }

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26