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 |
* more information on http://herewe.servebeer.com/libspopc/ |
8 |
* |
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 |
DLLIMPORT 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 |
DLLIMPORT 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 |
DLLIMPORT void freemsg(char* msg){ |
79 |
free(msg); |
80 |
} |
81 |
|
82 |
DLLIMPORT int* list2array(char* poplist){ |
83 |
/* returns an int array of sizes of messages from a LIST pop query */ |
84 |
/* array[0] holds id of the array's element */ |
85 |
/* should only be called on data received by a pop3_list() request */ |
86 |
int* array=NULL; |
87 |
int len,size; |
88 |
int id=0; |
89 |
char* cur; |
90 |
|
91 |
if((!poplist)||pop3_error(poplist)){ |
92 |
return(NULL); /* any suggestions ? */ |
93 |
} |
94 |
if(!dotline(poplist)){/* if simple element list */ |
95 |
/* one should't use this function for simple element... */ |
96 |
/* one should better use listi2size() */ |
97 |
/* skip '+OK ': look for first mail int id */ |
98 |
for(cur=poplist;(*cur<'0')||(*cur>'9');cur++); |
99 |
/* not dot line here */ |
100 |
sscanf(cur,"%d %d\n",&id,&size); |
101 |
array=(int*)malloc((id+1)*sizeof(int)); |
102 |
memset(array,0,(id+1)*sizeof(int)); |
103 |
array[0]=id; |
104 |
array[id]=size; |
105 |
return(array); |
106 |
} |
107 |
/* else this is a true list */ |
108 |
/* skip '+OK\r\n' :*/ |
109 |
for(cur=poplist;(*cur!='.')&&(*cur!='\n'); cur++); |
110 |
cur ++; /* one more time to get behind '\n' */ |
111 |
len=1; /* array len */ |
112 |
while((*cur)!='.'){ |
113 |
sscanf(cur,"%d %d\n",&id,&size); |
114 |
while(id > len){ /* pad array while id > len */ |
115 |
len++; |
116 |
array=(int*)realloc(array,len*sizeof(int)); |
117 |
array[len-1]=0; /* no mail */ |
118 |
} |
119 |
len++; |
120 |
array=(int*)realloc(array,len*sizeof(int)); |
121 |
array[id]=size; |
122 |
cur=nextline(cur); |
123 |
} |
124 |
if(id){ |
125 |
array[0]=id; /* last id */ |
126 |
}else{ /* no mail */ |
127 |
array=(int*)realloc(array, 1*sizeof(int)); |
128 |
array[0]=0; |
129 |
} |
130 |
return(array); |
131 |
} |
132 |
|
133 |
DLLIMPORT void freelistarray(int* array){ |
134 |
/* free array allocated by list2array() */ |
135 |
free(array); |
136 |
} |
137 |
|
138 |
DLLIMPORT int listi2size(char* resp){ |
139 |
/* grep the given size (in bytes) in resp after a pop3_list(sock,ID) request */ |
140 |
int i; |
141 |
int r; |
142 |
|
143 |
if(pop3_error(resp)){ |
144 |
return(0); /* no message ! */ |
145 |
} |
146 |
r=sscanf(resp+5,"%d\n",&i);/* skip '+OK ' should be safer FIXME */ |
147 |
if(!r){ /* special case when no messages on server */ |
148 |
return(0); |
149 |
} |
150 |
return(i); |
151 |
} |
152 |
|
153 |
DLLIMPORT int stat2num(char* resp){ |
154 |
/* returns the num of retrievable (non-deleted) messages */ |
155 |
/* should only be called just after a pop3_stat() request */ |
156 |
int n,s,r; |
157 |
|
158 |
if((!resp)||pop3_error(resp)){ |
159 |
return(-1); |
160 |
} |
161 |
r=sscanf(resp+4,"%d %d\n",&n,&s); /* with skip '+OK ' */ |
162 |
if (r == 2) |
163 |
return n; |
164 |
else |
165 |
return -1; |
166 |
} |
167 |
|
168 |
DLLIMPORT int stat2bytes(char* resp){ |
169 |
/* returns the sumsize in bytes of all stored messages on server */ |
170 |
/* should only be called just after a pop3_stat() request */ |
171 |
int n,s,r; |
172 |
|
173 |
if((!resp)||pop3_error(resp)){ |
174 |
return(-1); |
175 |
} |
176 |
r=sscanf(resp+4,"%d %d\n",&n,&s); /* skip '+OK ' */ |
177 |
if (r == 2) |
178 |
return(s); |
179 |
else |
180 |
return -1; |
181 |
} |
182 |
|
183 |
DLLIMPORT char** uidl2array(char* resp){ |
184 |
/* returns an array of unique strings for each message id */ |
185 |
/* array[0] gives array's last id */ |
186 |
/* should only be called just after a pop3_uidl() request */ |
187 |
char** array=NULL; |
188 |
int l,i=0; /* l is array lenth, i is id of msg */ |
189 |
char s[POPBUF]; /* temp signature string : sig theorically <=512B */ |
190 |
char* cur; |
191 |
|
192 |
if((!resp)||pop3_error(resp)){ |
193 |
return(NULL); /* any suggestions ? */ |
194 |
} |
195 |
if(!dotline(resp)){ /* simple element uidl */ |
196 |
/* one should not use this function for simple element */ |
197 |
/* one would better use uidli2sig() */ |
198 |
/* skip '+OK ': look for first mail int id */ |
199 |
for(cur=resp;(*cur<'0')||(*cur>'9');cur++); |
200 |
/* no dot line here */ |
201 |
sscanf(cur,"%d %s\n",&i,s); |
202 |
array=(char**)malloc((i+1)*sizeof(char*)); |
203 |
memset(array,0,(i+1)*sizeof(char*)); |
204 |
array[0]=(char*)malloc(POPBUF); /* up to 512B */ |
205 |
snprintf(array[0],POPBUF,"%d",i); |
206 |
array[i]=strdup(s); |
207 |
return(array); |
208 |
} |
209 |
/* else this is a true uid list */ |
210 |
/* skip '+OK\r\n : look for first mail integer id */ |
211 |
for(cur=resp;(*cur!='.')&&(*cur!='\n'); cur++); |
212 |
cur ++; /* one more time to get behind '\n' */ |
213 |
l=1; /* array len */ |
214 |
while((*cur)!='.'){ |
215 |
sscanf(cur,"%d %s\n",&i,s); |
216 |
while(i > l){ /* pad array while id > len */ |
217 |
l++; |
218 |
array=(char**)realloc(array,l*sizeof(char*)); |
219 |
#if 0 |
220 |
array[l-1]=(char*)malloc(sizeof(char)); |
221 |
array[l-1]='\0'; |
222 |
#else |
223 |
array[l-1]=NULL; /* for consitency with popchkmsg() */ |
224 |
#endif |
225 |
|
226 |
} |
227 |
l++; |
228 |
array=(char**)realloc(array,l*sizeof(char*)); |
229 |
array[i]=(char*)malloc(POPBUF); /* up to 512B */ |
230 |
array[i]=strncpy(array[i],s,POPBUF); |
231 |
cur=nextline(cur); |
232 |
} |
233 |
if(i){ /* i is now the last message id met in this session */ |
234 |
array[0]=(char*)malloc(9); /* up to 99999999 msg uids FIXME */ |
235 |
snprintf(array[0],9,"%d",i); |
236 |
/* contains the id of the last msg (char*) (also tab length) */ |
237 |
}else{ /* zero message */ |
238 |
array=(char**)malloc(1*sizeof(char*)); |
239 |
array[0]=(char*)malloc(2*sizeof(char)); /* 2 because of '\0' */ |
240 |
snprintf(array[0],2,"%d",0); |
241 |
} |
242 |
return(array); |
243 |
} |
244 |
|
245 |
DLLIMPORT void freeuidlarray(char** array){ |
246 |
/* free the array allocated by uidl2array() */ |
247 |
int i,last; |
248 |
|
249 |
last= atoi(array[0]); |
250 |
for (i=1;i<=last;i++){ |
251 |
free(array[i]); |
252 |
} |
253 |
free(array[0]); |
254 |
free(array); |
255 |
} |
256 |
|
257 |
DLLIMPORT char* uidli2sig(char* resp){ |
258 |
/* greps signature from server resp */ |
259 |
/* should only be called after a pop3_uidl(sock,ID) */ |
260 |
char* sig=NULL; |
261 |
|
262 |
if(pop3_error(resp)){ |
263 |
return(NULL);/* no message ! */ |
264 |
} |
265 |
sig=strdup(resp+5); /* skip '+OK ID' should be safer, FIXME */ |
266 |
if(sig[1]=='.'){/* special case when no messages on the server */ |
267 |
free(sig); |
268 |
return(NULL); |
269 |
} |
270 |
return(sig); |
271 |
} |
272 |
|