]> Pileus Git - ~andy/fetchmail/blob - imap.c
gcc -Wall cleanup.
[~andy/fetchmail] / imap.c
1 /*
2  * imap.c -- IMAP2bis protocol methods
3  *
4  * Copyright 1996 by Eric S. Raymond
5  * All rights reserved.
6  * For license terms, see the file COPYING in this directory.
7  */
8
9 #include  <config.h>
10 #include  <stdio.h>
11 #include  <string.h>
12 #include  <ctype.h>
13 #if defined(STDC_HEADERS)
14 #include  <stdlib.h>
15 #endif
16 #include  "socket.h"
17 #include  "fetchmail.h"
18
19 static int count, seen, recent, unseen;
20
21 int imap_ok (socket, argbuf)
22 /* parse command response */
23 char *argbuf;
24 int socket;
25 {
26     char buf [POPBUFSIZE+1];
27
28     seen = 0;
29     do {
30         if (SockGets(socket, buf, sizeof(buf)) < 0)
31             return(PS_SOCKET);
32
33         if (outlevel == O_VERBOSE)
34             fprintf(stderr,"%s\n",buf);
35
36         /* interpret untagged status responses */
37         if (strstr(buf, "EXISTS"))
38             count = atoi(buf+2);
39         if (strstr(buf, "RECENT"))
40             recent = atoi(buf+2);
41         if (strstr(buf, "UNSEEN"))
42             unseen = atoi(buf+2);
43         if (strstr(buf, "FLAGS"))
44             seen = (strstr(buf, "Seen") != (char *)NULL);
45     } while
46         (tag[0] != '\0' && strncmp(buf, tag, strlen(tag)));
47
48     if (tag[0] == '\0')
49     {
50         strcpy(argbuf, buf);
51         return(0); 
52     }
53     else
54     {
55         char    *cp;
56
57         /* skip the tag */
58         for (cp = buf; !isspace(*cp); cp++)
59             continue;
60         while (isspace(*cp))
61             cp++;
62
63         if (strncmp(cp, "OK", 2) == 0)
64         {
65             strcpy(argbuf, cp);
66             return(0);
67         }
68         else if (strncmp(cp, "BAD", 2) == 0)
69             return(PS_ERROR);
70         else
71             return(PS_PROTOCOL);
72     }
73 }
74
75 int imap_getauth(socket, ctl, buf)
76 /* apply for connection authorization */
77 int socket;
78 struct query *ctl;
79 char *buf;
80 {
81     /* try to get authorized */
82     return(gen_transact(socket,
83                   "LOGIN %s \"%s\"",
84                   ctl->remotename, ctl->password));
85 }
86
87 static int imap_getrange(socket, ctl, countp, newp)
88 /* get range of messages to be fetched */
89 int socket;
90 struct query *ctl;
91 int *countp, *newp;
92 {
93     int ok;
94
95     /* find out how many messages are waiting */
96     recent = unseen = 0;
97     ok = gen_transact(socket,
98                   "SELECT %s",
99                   ctl->mailbox[0] ? ctl->mailbox : "INBOX");
100     if (ok != 0)
101         return(ok);
102
103     *countp = count;
104
105     if (unseen)         /* optional response, but better if we see it */
106         *newp = unseen;
107     else if (recent)    /* mandatory */
108         *newp = recent;
109     else
110         *newp = -1;     /* should never happen, RECENT is mandatory */ 
111
112     return(0);
113 }
114
115 static int imap_getsizes(socket, count, sizes)
116 /* capture the sizes of all messages */
117 int     socket;
118 int     count;
119 int     *sizes;
120 {
121     char buf [POPBUFSIZE+1];
122
123     gen_send(socket, "FETCH 1:%d RFC822.SIZE", count);
124     while (SockGets(socket, buf, sizeof(buf)) >= 0)
125     {
126         int num, size;
127
128         if (outlevel == O_VERBOSE)
129             fprintf(stderr,"%s\n",buf);
130         if (strstr(buf, "OK"))
131             break;
132         else if (sscanf(buf, "* %d FETCH (RFC822.SIZE %d)", &num, &size) == 2)
133             sizes[num - 1] = size;
134         else
135             sizes[num - 1] = -1;
136     }
137
138     return(0);
139 }
140
141 static int imap_is_old(socket, ctl, num)
142 /* is the given message old? */
143 int socket;
144 struct query *ctl;
145 int num;
146 {
147     int ok;
148
149     if ((ok = gen_transact(socket, "FETCH %d FLAGS", num)) != 0)
150         exit(PS_ERROR);
151
152     return(seen);
153 }
154
155 static int imap_fetch(socket, number, lenp)
156 /* request nth message */
157 int socket;
158 int number;
159 int *lenp; 
160 {
161     char buf [POPBUFSIZE+1];
162     int num;
163
164     gen_send(socket, "FETCH %d RFC822", number);
165
166     /* looking for FETCH response */
167     do {
168         if (SockGets(socket, buf,sizeof(buf)) < 0)
169             return(PS_SOCKET);
170     } while
171             (sscanf(buf+2, "%d FETCH (RFC822 {%d}", &num, lenp) != 2);
172
173     if (num != number)
174         return(PS_ERROR);
175     else
176         return(0);
177 }
178
179 static int imap_trail(socket, ctl, number)
180 /* discard tail of FETCH response after reading message text */
181 int socket;
182 struct query *ctl;
183 int number;
184 {
185     char buf [POPBUFSIZE+1];
186
187     if (SockGets(socket, buf,sizeof(buf)) < 0)
188         return(PS_SOCKET);
189     else
190         return(0);
191 }
192
193 static int imap_delete(socket, ctl, number)
194 /* set delete flag for given message */
195 int socket;
196 struct query *ctl;
197 int number;
198 {
199     return(gen_transact(socket, "STORE %d +FLAGS (\\Deleted)", number));
200 }
201
202 const static struct method imap =
203 {
204     "IMAP",             /* Internet Message Access Protocol */
205     143,                /* standard IMAP2bis/IMAP4 port */
206     1,                  /* this is a tagged protocol */
207     0,                  /* no message delimiter */
208     imap_ok,            /* parse command response */
209     imap_getauth,       /* get authorization */
210     imap_getrange,      /* query range of messages */
211     imap_getsizes,      /* grab message sizes */
212     imap_is_old,        /* no UID check */
213     imap_fetch,         /* request given message */
214     imap_trail,         /* eat message trailer */
215     imap_delete,        /* set IMAP delete flag */
216     "EXPUNGE",          /* the IMAP expunge command */
217     "LOGOUT",           /* the IMAP exit command */
218 };
219
220 int doIMAP(ctl)
221 /* retrieve messages using IMAP Version 2bis or Version 4 */
222 struct query *ctl;
223 {
224     return(do_protocol(ctl, &imap));
225 }
226
227 /* imap.c ends here */