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