1 |
ben |
1 |
/* this is format.c file, part of the libspopc library sources |
2 |
|
|
* copyright © 2002- Benoit Rouits <brouits@free.fr> |
3 |
|
|
* released under the terms of the GNU Lesser General Public Licence. |
4 |
|
|
* |
5 |
|
|
* libspopc offers simple API for a pop3 client. |
6 |
|
|
* See RFC 1725 for pop3 specifications. |
7 |
ben |
2 |
* more information on http://herewe.servebeer.com/libspopc/ |
8 |
ben |
1 |
* |
9 |
|
|
* This library is free software; you can redistribute it and/or |
10 |
|
|
* modify it under the terms of the GNU Lesser General Public |
11 |
|
|
* License as published by the Free Software Foundation; either |
12 |
|
|
* version 2.1 of the License, or (at your option) any later version. |
13 |
|
|
* |
14 |
|
|
* This library is distributed in the hope that it will be useful, |
15 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 |
|
|
* Lesser General Public License for more details. |
18 |
|
|
* |
19 |
|
|
* You should have received a copy of the GNU Lesser General Public |
20 |
|
|
* License along with this library; if not, write to the Free Software |
21 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include <stdlib.h> |
25 |
|
|
#include <string.h> |
26 |
|
|
#include <stdio.h> |
27 |
|
|
#include "libspopc.h" |
28 |
|
|
|
29 |
|
|
/************************************************************ |
30 |
|
|
* libspopc functions to format pop data returned by server * |
31 |
|
|
************************************************************/ |
32 |
|
|
|
33 |
|
|
char* nextline(char* string){ |
34 |
|
|
/* returns a pointer to the next line of given string */ |
35 |
|
|
while(((*string) != '\n')&&((*string) != '\0')){ |
36 |
|
|
string++; |
37 |
|
|
} |
38 |
|
|
if(!(*string)){ |
39 |
|
|
return (NULL); |
40 |
|
|
} |
41 |
|
|
return(string+1); |
42 |
|
|
} |
43 |
|
|
|
44 |
|
|
char* retr2msg(char* data){ |
45 |
|
|
/* retruns formatted mail from a pop RETR X query */ |
46 |
|
|
/* should only be called on data returned by pop3_retr() */ |
47 |
|
|
char* msg=NULL; |
48 |
|
|
char* cur; |
49 |
|
|
|
50 |
|
|
if((!data)||pop3_error(data)){ |
51 |
|
|
return(NULL);/* any suggestions ? */ |
52 |
|
|
} |
53 |
|
|
while (( data != NULL ) && (strncmp("+OK", data, 3) != 0)){ |
54 |
|
|
data=nextline(data); /* skip ...\n before +OK */ |
55 |
|
|
} |
56 |
|
|
if(( data != NULL ) && (strncmp("+OK", data, 3) == 0)) { |
57 |
|
|
data=nextline(data); /* skip +OK ...\n */ |
58 |
|
|
} |
59 |
|
|
msg=data?(char*)malloc(strlen(data)):NULL; |
60 |
|
|
if(!msg){ |
61 |
|
|
return(NULL); |
62 |
|
|
} |
63 |
|
|
cur=msg; |
64 |
|
|
while(*data){ |
65 |
|
|
if(DOTBEGIN(data)){ |
66 |
|
|
(*cur)=(*data); /* keep \n */ |
67 |
|
|
data+=2; /* skip first dot */ |
68 |
|
|
cur++; |
69 |
|
|
}else{ |
70 |
|
|
(*cur)=(*data); |
71 |
|
|
cur++;data++; |
72 |
|
|
} |
73 |
|
|
} |
74 |
|
|
(*(cur-2))='\0'; /* erase \r\n */ |
75 |
|
|
return(msg); |
76 |
|
|
} |
77 |
|
|
|
78 |
|
|
void freemsg(char* msg){ |
79 |
|
|
free(msg); |
80 |
|
|
msg=NULL; |
81 |
|
|
} |
82 |
|
|
|
83 |
|
|
int* list2array(char* poplist){ |
84 |
|
|
/* returns an int array of sizes of messages from a LIST pop query */ |
85 |
|
|
/* array[0] holds id of the array's element */ |
86 |
|
|
/* should only be called on data received by a pop3_list() request */ |
87 |
|
|
int* array=NULL; |
88 |
|
|
int len,size; |
89 |
|
|
int id=0; |
90 |
|
|
char* cur; |
91 |
|
|
|
92 |
|
|
if((!poplist)||pop3_error(poplist)){ |
93 |
|
|
return(NULL); /* any suggestions ? */ |
94 |
|
|
} |
95 |
|
|
if(!dotline(poplist)){/* if simple element list */ |
96 |
|
|
/* one should't use this function for simple element... */ |
97 |
|
|
/* one should better use listi2size() */ |
98 |
|
|
/* skip '+OK ': look for first mail int id */ |
99 |
|
|
for(cur=poplist;(*cur<'0')||(*cur>'9');cur++); |
100 |
|
|
/* not dot line here */ |
101 |
|
|
sscanf(cur,"%d %d\n",&id,&size); |
102 |
|
|
array=(int*)malloc((id+1)*sizeof(int)); |
103 |
|
|
memset(array,0,(id+1)*sizeof(int)); |
104 |
|
|
array[0]=id; |
105 |
|
|
array[id]=size; |
106 |
|
|
return(array); |
107 |
|
|
} |
108 |
|
|
/* else this is a true list */ |
109 |
|
|
/* skip '+OK\r\n' :*/ |
110 |
|
|
for(cur=poplist;(*cur!='.')&&(*cur!='\n'); cur++); |
111 |
|
|
cur ++; /* one more time to get behind '\n' */ |
112 |
|
|
len=1; /* array len */ |
113 |
|
|
while((*cur)!='.'){ |
114 |
|
|
sscanf(cur,"%d %d\n",&id,&size); |
115 |
|
|
while(id > len){ /* pad array while id > len */ |
116 |
|
|
len++; |
117 |
|
|
array=(int*)realloc(array,len*sizeof(int)); |
118 |
|
|
array[len-1]=0; /* no mail */ |
119 |
|
|
} |
120 |
|
|
len++; |
121 |
|
|
array=(int*)realloc(array,len*sizeof(int)); |
122 |
|
|
array[id]=size; |
123 |
|
|
cur=nextline(cur); |
124 |
|
|
} |
125 |
|
|
if(id){ |
126 |
|
|
array[0]=id; /* last id */ |
127 |
|
|
}else{ /* no mail */ |
128 |
|
|
array=(int*)realloc(array, 1*sizeof(int)); |
129 |
|
|
array[0]=0; |
130 |
|
|
} |
131 |
|
|
return(array); |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
void freelistarray(int* array){ |
135 |
|
|
/* free array allocated by list2array() */ |
136 |
|
|
free(array); |
137 |
|
|
} |
138 |
|
|
|
139 |
|
|
int listi2size(char* resp){ |
140 |
|
|
/* grep the given size (in bytes) in resp after a pop3_list(sock,ID) request */ |
141 |
|
|
int i; |
142 |
|
|
int r; |
143 |
|
|
|
144 |
|
|
if(pop3_error(resp)){ |
145 |
|
|
return(0); /* no message ! */ |
146 |
|
|
} |
147 |
|
|
r=sscanf(resp+5,"%d\n",&i);/* skip '+OK ' should be safer FIXME */ |
148 |
|
|
if(!r){ /* special case when no messages on server */ |
149 |
|
|
return(0); |
150 |
|
|
} |
151 |
|
|
return(i); |
152 |
|
|
} |
153 |
|
|
|
154 |
|
|
int stat2num(char* resp){ |
155 |
|
|
/* returns the num of retrievable (non-deleted) messages */ |
156 |
|
|
/* should only be called just after a pop3_stat() request */ |
157 |
|
|
int n,s,r; |
158 |
|
|
|
159 |
|
|
if((!resp)||pop3_error(resp)){ |
160 |
|
|
return(-1); |
161 |
|
|
} |
162 |
|
|
r=sscanf(resp+4,"%d %d\n",&n,&s); /* with skip '+OK ' */ |
163 |
|
|
if (r == 2) |
164 |
|
|
return n; |
165 |
|
|
else |
166 |
|
|
return -1; |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
int stat2bytes(char* resp){ |
170 |
|
|
/* returns the sumsize in bytes of all stored messages on server */ |
171 |
|
|
/* should only be called just after a pop3_stat() request */ |
172 |
|
|
int n,s,r; |
173 |
|
|
|
174 |
|
|
if((!resp)||pop3_error(resp)){ |
175 |
|
|
return(-1); |
176 |
|
|
} |
177 |
|
|
r=sscanf(resp+4,"%d %d\n",&n,&s); /* skip '+OK ' */ |
178 |
|
|
if (r == 2) |
179 |
|
|
return(s); |
180 |
|
|
else |
181 |
|
|
return -1; |
182 |
|
|
} |
183 |
|
|
|
184 |
|
|
char** uidl2array(char* resp){ |
185 |
|
|
/* returns an array of unique strings for each message id */ |
186 |
|
|
/* array[0] gives array's last id */ |
187 |
|
|
/* should only be called just after a pop3_uidl() request */ |
188 |
|
|
char** array=NULL; |
189 |
|
|
int l,i=0; /* l is array lenth, i is id of msg */ |
190 |
|
|
char s[POPBUF]; /* temp signature string : sig theorically <=512B */ |
191 |
|
|
char* cur; |
192 |
|
|
|
193 |
|
|
if((!resp)||pop3_error(resp)){ |
194 |
|
|
return(NULL); /* any suggestions ? */ |
195 |
|
|
} |
196 |
|
|
if(!dotline(resp)){ /* simple element uidl */ |
197 |
|
|
/* one should not use this function for simple element */ |
198 |
|
|
/* one would better use uidli2sig() */ |
199 |
|
|
/* skip '+OK ': look for first mail int id */ |
200 |
|
|
for(cur=resp;(*cur<'0')||(*cur>'9');cur++); |
201 |
|
|
/* no dot line here */ |
202 |
|
|
sscanf(cur,"%d %s\n",&i,s); |
203 |
|
|
array=(char**)malloc((i+1)*sizeof(char*)); |
204 |
|
|
memset(array,0,(i+1)*sizeof(char*)); |
205 |
|
|
array[0]=(char*)malloc(POPBUF); /* up to 512B */ |
206 |
|
|
snprintf(array[0],POPBUF,"%d",i); |
207 |
|
|
array[i]=strdup(s); |
208 |
|
|
return(array); |
209 |
|
|
} |
210 |
|
|
/* else this is a true uid list */ |
211 |
|
|
/* skip '+OK\r\n : look for first mail integer id */ |
212 |
|
|
for(cur=resp;(*cur!='.')&&(*cur!='\n'); cur++); |
213 |
|
|
cur ++; /* one more time to get behind '\n' */ |
214 |
|
|
l=1; /* array len */ |
215 |
|
|
while((*cur)!='.'){ |
216 |
|
|
sscanf(cur,"%d %s\n",&i,s); |
217 |
|
|
while(i > l){ /* pad array while id > len */ |
218 |
|
|
l++; |
219 |
|
|
array=(char**)realloc(array,l*sizeof(char*)); |
220 |
|
|
#if 0 |
221 |
|
|
array[l-1]=(char*)malloc(sizeof(char)); |
222 |
|
|
array[l-1]='\0'; |
223 |
|
|
#else |
224 |
|
|
array[l-1]=NULL; /* for consitency with popchkmsg() */ |
225 |
|
|
#endif |
226 |
|
|
|
227 |
|
|
} |
228 |
|
|
l++; |
229 |
|
|
array=(char**)realloc(array,l*sizeof(char*)); |
230 |
|
|
array[i]=(char*)malloc(POPBUF); /* up to 512B */ |
231 |
|
|
array[i]=strncpy(array[i],s,POPBUF); |
232 |
|
|
cur=nextline(cur); |
233 |
|
|
} |
234 |
|
|
if(i){ /* i is now the last message id met in this session */ |
235 |
|
|
array[0]=(char*)malloc(9); /* up to 99999999 msg uids FIXME */ |
236 |
|
|
snprintf(array[0],9,"%d",i); |
237 |
|
|
/* contains the id of the last msg (char*) (also tab length) */ |
238 |
|
|
}else{ /* zero message */ |
239 |
|
|
array=(char**)malloc(1*sizeof(char*)); |
240 |
|
|
array[0]=(char*)malloc(2*sizeof(char)); /* 2 because of '\0' */ |
241 |
|
|
snprintf(array[0],2,"%d",0); |
242 |
|
|
} |
243 |
|
|
return(array); |
244 |
|
|
} |
245 |
|
|
|
246 |
|
|
void freeuidlarray(char** array){ |
247 |
|
|
/* free the array allocated by uidl2array() */ |
248 |
|
|
int i,last; |
249 |
|
|
|
250 |
|
|
last= atoi(array[0]); |
251 |
|
|
for (i=1;i<=last;i++){ |
252 |
|
|
free(array[i]); |
253 |
|
|
} |
254 |
|
|
free(array[0]); |
255 |
|
|
free(array); |
256 |
|
|
} |
257 |
|
|
|
258 |
|
|
char* uidli2sig(char* resp){ |
259 |
|
|
/* greps signature from server resp */ |
260 |
|
|
/* should only be called after a pop3_uidl(sock,ID) */ |
261 |
|
|
char* sig=NULL; |
262 |
|
|
|
263 |
|
|
if(pop3_error(resp)){ |
264 |
|
|
return(NULL);/* no message ! */ |
265 |
|
|
} |
266 |
|
|
sig=strdup(resp+5); /* skip '+OK ID' should be safer, FIXME */ |
267 |
|
|
if(sig[1]=='.'){/* special case when no messages on the server */ |
268 |
|
|
free(sig); |
269 |
|
|
return(NULL); |
270 |
|
|
} |
271 |
|
|
return(sig); |
272 |
|
|
} |
273 |
|
|
|