summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/data-types/mailstream_helper.c11
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.c8
-rw-r--r--libetpan/src/low-level/imap/mailimap_parser.c22
-rw-r--r--libetpan/src/low-level/maildir/maildir.c17
-rw-r--r--libetpan/src/low-level/mh/mailmh.c3
-rw-r--r--libetpan/src/low-level/pop3/mailpop3.c7
6 files changed, 59 insertions, 9 deletions
diff --git a/libetpan/src/data-types/mailstream_helper.c b/libetpan/src/data-types/mailstream_helper.c
index 2f0b9ae..f0ddf51 100644
--- a/libetpan/src/data-types/mailstream_helper.c
+++ b/libetpan/src/data-types/mailstream_helper.c
@@ -1,515 +1,522 @@
1/* 1/*
2 * libEtPan! -- a mail stuff library 2 * libEtPan! -- a mail stuff library
3 * 3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa 4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its 15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived 16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * $Id$ 33 * $Id$
34 */ 34 */
35 35
36#include "mailstream_helper.h" 36#include "mailstream_helper.h"
37#include <string.h> 37#include <string.h>
38#include <stdio.h> 38#include <stdio.h>
39#include "mail.h" 39#include "mail.h"
40 40
41static void remove_trailing_eol(MMAPString * mmapstr) 41static void remove_trailing_eol(MMAPString * mmapstr)
42{ 42{
43 if (mmapstr->str[mmapstr->len - 1] == '\n') { 43 if (mmapstr->str[mmapstr->len - 1] == '\n') {
44 mmapstr->len --; 44 mmapstr->len --;
45 mmapstr->str[mmapstr->len] = '\0'; 45 mmapstr->str[mmapstr->len] = '\0';
46 } 46 }
47 if (mmapstr->str[mmapstr->len - 1] == '\r') { 47 if (mmapstr->str[mmapstr->len - 1] == '\r') {
48 mmapstr->len --; 48 mmapstr->len --;
49 mmapstr->str[mmapstr->len] = '\0'; 49 mmapstr->str[mmapstr->len] = '\0';
50 } 50 }
51} 51}
52 52
53char * mailstream_read_line(mailstream * stream, MMAPString * line) 53char * mailstream_read_line(mailstream * stream, MMAPString * line)
54{ 54{
55 if (mmap_string_assign(line, "") == NULL) 55 if (mmap_string_assign(line, "") == NULL)
56 return NULL; 56 return NULL;
57 57
58 return mailstream_read_line_append(stream, line); 58 return mailstream_read_line_append(stream, line);
59} 59}
60 60
61static char * mailstream_read_len_append(mailstream * stream, 61static char * mailstream_read_len_append(mailstream * stream,
62 MMAPString * line, 62 MMAPString * line,
63 size_t i) 63 size_t i)
64{ 64{
65 size_t cur_size; 65 size_t cur_size;
66 66
67 cur_size = line->len; 67 cur_size = line->len;
68 if (mmap_string_set_size(line, line->len + i) == NULL) 68 if (mmap_string_set_size(line, line->len + i) == NULL)
69 return NULL; 69 return NULL;
70 if (mailstream_read(stream, line->str + cur_size, i) < 0) 70 if (mailstream_read(stream, line->str + cur_size, i) < 0)
71 return NULL; 71 return NULL;
72 return line->str; 72 return line->str;
73} 73}
74 74
75char * mailstream_read_line_append(mailstream * stream, MMAPString * line) 75char * mailstream_read_line_append(mailstream * stream, MMAPString * line)
76{ 76{
77 if (stream == NULL) 77 if (stream == NULL)
78 return NULL; 78 return NULL;
79 79
80 do { 80 do {
81 if (stream->read_buffer_len > 0) { 81 if (stream->read_buffer_len > 0) {
82 size_t i; 82 size_t i;
83 83
84 i = 0; 84 i = 0;
85 while (i < stream->read_buffer_len) { 85 while (i < stream->read_buffer_len) {
86 if (stream->read_buffer[i] == '\n') 86 if (stream->read_buffer[i] == '\n')
87 return mailstream_read_len_append(stream, line, i + 1); 87 return mailstream_read_len_append(stream, line, i + 1);
88 i++; 88 i++;
89 } 89 }
90 if (mailstream_read_len_append(stream, line, 90 if (mailstream_read_len_append(stream, line,
91 stream->read_buffer_len) == NULL) 91 stream->read_buffer_len) == NULL)
92 return NULL; 92 return NULL;
93 } 93 }
94 else { 94 else {
95 ssize_t r; 95 ssize_t r;
96 96
97 r = mailstream_feed_read_buffer(stream); 97 r = mailstream_feed_read_buffer(stream);
98 if (r == -1) 98 if (r == -1)
99 return NULL; 99 return NULL;
100 100
101 if (r == 0) 101 if (r == 0) {
102 break; 102 // LR
103 // this avoids a memory access violation later when trying
104 // to remove_trailing_eol from a null string
105 if ( line->len == 0 )
106 return NULL;
107 else
108 break;
109 }
103 } 110 }
104 } 111 }
105 while (1); 112 while (1);
106 113
107 return line->str; 114 return line->str;
108} 115}
109 116
110char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line) 117char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line)
111{ 118{
112 if (!mailstream_read_line(stream, line)) 119 if (!mailstream_read_line(stream, line))
113 return NULL; 120 return NULL;
114 121
115 remove_trailing_eol(line); 122 remove_trailing_eol(line);
116 123
117 return line->str; 124 return line->str;
118} 125}
119 126
120int mailstream_is_end_multiline(const char * line) 127int mailstream_is_end_multiline(const char * line)
121{ 128{
122 if (line[0] != '.') 129 if (line[0] != '.')
123 return FALSE; 130 return FALSE;
124 if (line[1] != 0) 131 if (line[1] != 0)
125 return FALSE; 132 return FALSE;
126 return TRUE; 133 return TRUE;
127} 134}
128 135
129#if 1 136#if 1
130char * mailstream_read_multiline(mailstream * s, size_t size, 137char * mailstream_read_multiline(mailstream * s, size_t size,
131 MMAPString * stream_buffer, 138 MMAPString * stream_buffer,
132 MMAPString * multiline_buffer, 139 MMAPString * multiline_buffer,
133 size_t progr_rate, 140 size_t progr_rate,
134 progress_function * progr_fun) 141 progress_function * progr_fun)
135{ 142{
136 size_t count; 143 size_t count;
137 char * line; 144 char * line;
138 size_t last; 145 size_t last;
139 146
140 if (mmap_string_assign(multiline_buffer, "") == NULL) 147 if (mmap_string_assign(multiline_buffer, "") == NULL)
141 return NULL; 148 return NULL;
142 149
143 count = 0; 150 count = 0;
144 last = 0; 151 last = 0;
145 152
146 while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) { 153 while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) {
147 if (mailstream_is_end_multiline(line)) 154 if (mailstream_is_end_multiline(line))
148 return multiline_buffer->str; 155 return multiline_buffer->str;
149 156
150 if (line[0] == '.') { 157 if (line[0] == '.') {
151 if (mmap_string_append(multiline_buffer, line + 1) == NULL) 158 if (mmap_string_append(multiline_buffer, line + 1) == NULL)
152 return NULL; 159 return NULL;
153 } 160 }
154 else { 161 else {
155 if (mmap_string_append(multiline_buffer, line) == NULL) 162 if (mmap_string_append(multiline_buffer, line) == NULL)
156 return NULL; 163 return NULL;
157 } 164 }
158 if (mmap_string_append(multiline_buffer, "\r\n") == NULL) 165 if (mmap_string_append(multiline_buffer, "\r\n") == NULL)
159 return NULL; 166 return NULL;
160 167
161 count += strlen(line); 168 count += strlen(line);
162 if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL)) 169 if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL))
163 if (count - last >= progr_rate) { 170 if (count - last >= progr_rate) {
164 (* progr_fun)(count, size); 171 (* progr_fun)(count, size);
165 last = count; 172 last = count;
166 } 173 }
167 } 174 }
168 175
169 return NULL; 176 return NULL;
170} 177}
171 178
172#else 179#else
173 180
174/* 181/*
175 high speed but don't replace the line break with '\n' and neither 182 high speed but don't replace the line break with '\n' and neither
176 remove the '.' 183 remove the '.'
177*/ 184*/
178 185
179static gboolean end_of_multiline(const char * str, gint len) 186static gboolean end_of_multiline(const char * str, gint len)
180{ 187{
181 gint index; 188 gint index;
182 189
183 index = len - 1; 190 index = len - 1;
184 191
185 if (str[index] != '\n') 192 if (str[index] != '\n')
186 return FALSE; 193 return FALSE;
187 if (index == 0) 194 if (index == 0)
188 return FALSE; 195 return FALSE;
189 196
190 index --; 197 index --;
191 198
192 if (str[index] == '\r') { 199 if (str[index] == '\r') {
193 index --; 200 index --;
194 if (index == 0) 201 if (index == 0)
195 return FALSE; 202 return FALSE;
196 } 203 }
197 204
198 if (str[index] != '.') 205 if (str[index] != '.')
199 return FALSE; 206 return FALSE;
200 if (index == 0) 207 if (index == 0)
201 return FALSE; 208 return FALSE;
202 209
203 index--; 210 index--;
204 211
205 if (str[index] != '\n') 212 if (str[index] != '\n')
206 return FALSE; 213 return FALSE;
207 214
208 return TRUE; 215 return TRUE;
209} 216}
210 217
211char * mailstream_read_multiline(mailstream * stream, size_t size, 218char * mailstream_read_multiline(mailstream * stream, size_t size,
212 MMAPString * stream_buffer, 219 MMAPString * stream_buffer,
213 MMAPString * line, 220 MMAPString * line,
214 size_t progr_rate, 221 size_t progr_rate,
215 progress_function * progr_fun) 222 progress_function * progr_fun)
216{ 223{
217 if (stream == NULL) 224 if (stream == NULL)
218 return NULL; 225 return NULL;
219 226
220 mmap_string_assign(line, ""); 227 mmap_string_assign(line, "");
221 228
222 do { 229 do {
223 if (stream->read_buffer_len > 0) { 230 if (stream->read_buffer_len > 0) {
224 size_t i; 231 size_t i;
225 232
226 i = 0; 233 i = 0;
227 while (i < stream->read_buffer_len) { 234 while (i < stream->read_buffer_len) {
228 if (end_of_multiline(stream->read_buffer, i + 1)) 235 if (end_of_multiline(stream->read_buffer, i + 1))
229 return mailstream_read_len_append(stream, line, i + 1); 236 return mailstream_read_len_append(stream, line, i + 1);
230 i++; 237 i++;
231 } 238 }
232 if (mailstream_read_len_append(stream, line, 239 if (mailstream_read_len_append(stream, line,
233 stream->read_buffer_len) == NULL) 240 stream->read_buffer_len) == NULL)
234 return NULL; 241 return NULL;
235 if (end_of_multiline(line->str, line->len)) 242 if (end_of_multiline(line->str, line->len))
236 return line->str; 243 return line->str;
237 } 244 }
238 else 245 else
239 if (mailstream_feed_read_buffer(stream) == -1) 246 if (mailstream_feed_read_buffer(stream) == -1)
240 return NULL; 247 return NULL;
241 } 248 }
242 while (1); 249 while (1);
243 250
244 return line->str; 251 return line->str;
245} 252}
246#endif 253#endif
247 254
248 255
249 256
250static inline ssize_t send_data_line(mailstream * s, 257static inline ssize_t send_data_line(mailstream * s,
251 const char * line, size_t length) 258 const char * line, size_t length)
252{ 259{
253 int fix_eol; 260 int fix_eol;
254 const char * start; 261 const char * start;
255 size_t count; 262 size_t count;
256 263
257 start = line; 264 start = line;
258 265
259 fix_eol = 0; 266 fix_eol = 0;
260 count = 0; 267 count = 0;
261 268
262 while (1) { 269 while (1) {
263 if (length == 0) 270 if (length == 0)
264 break; 271 break;
265 272
266 if (* line == '\r') { 273 if (* line == '\r') {
267 line ++; 274 line ++;
268 275
269 count ++; 276 count ++;
270 length --; 277 length --;
271 278
272 if (length == 0) { 279 if (length == 0) {
273 fix_eol = 1; 280 fix_eol = 1;
274 break; 281 break;
275 } 282 }
276 283
277 if (* line == '\n') { 284 if (* line == '\n') {
278 line ++; 285 line ++;
279 286
280 count ++; 287 count ++;
281 length --; 288 length --;
282 289
283 break; 290 break;
284 } 291 }
285 else { 292 else {
286 fix_eol = 1; 293 fix_eol = 1;
287 break; 294 break;
288 } 295 }
289 } 296 }
290 else if (* line == '\n') { 297 else if (* line == '\n') {
291 line ++; 298 line ++;
292 299
293 count ++; 300 count ++;
294 length --; 301 length --;
295 302
296 fix_eol = 1; 303 fix_eol = 1;
297 break; 304 break;
298 } 305 }
299 306
300 line ++; 307 line ++;
301 length --; 308 length --;
302 count ++; 309 count ++;
303 } 310 }
304 311
305 if (fix_eol) { 312 if (fix_eol) {
306 if (mailstream_write(s, start, count - 1) == -1) 313 if (mailstream_write(s, start, count - 1) == -1)
307 goto err; 314 goto err;
308 if (mailstream_write(s, "\r\n", 2) == -1) 315 if (mailstream_write(s, "\r\n", 2) == -1)
309 goto err; 316 goto err;
310 } 317 }
311 else { 318 else {
312 if (mailstream_write(s, start, count) == -1) 319 if (mailstream_write(s, start, count) == -1)
313 goto err; 320 goto err;
314 } 321 }
315 322
316 323
317#if 0 324#if 0
318 while (* line != '\n') { 325 while (* line != '\n') {
319 if (* line == '\r') 326 if (* line == '\r')
320 pos = line; 327 pos = line;
321 if (* line == '\0') 328 if (* line == '\0')
322 return line; 329 return line;
323 if (mailstream_write(s, line, 1) == -1) 330 if (mailstream_write(s, line, 1) == -1)
324 goto err; 331 goto err;
325 line ++; 332 line ++;
326 } 333 }
327 if (pos + 1 == line) { 334 if (pos + 1 == line) {
328 if (mailstream_write(s, line, 1) == -1) 335 if (mailstream_write(s, line, 1) == -1)
329 goto err; 336 goto err;
330 } 337 }
331 else { 338 else {
332 if (mailstream_write(s, "\r\n", 2) == -1) 339 if (mailstream_write(s, "\r\n", 2) == -1)
333 goto err; 340 goto err;
334 } 341 }
335 line ++; 342 line ++;
336#endif 343#endif
337 344
338 return count; 345 return count;
339 346
340 err: 347 err:
341 return -1; 348 return -1;
342} 349}
343 350
344static inline int send_data_crlf(mailstream * s, const char * message, 351static inline int send_data_crlf(mailstream * s, const char * message,
345 size_t size, 352 size_t size,
346 int quoted, 353 int quoted,
347 size_t progr_rate, 354 size_t progr_rate,
348 progress_function * progr_fun) 355 progress_function * progr_fun)
349{ 356{
350 const char * current; 357 const char * current;
351 size_t count; 358 size_t count;
352 size_t last; 359 size_t last;
353 size_t remaining; 360 size_t remaining;
354 361
355 count = 0; 362 count = 0;
356 last = 0; 363 last = 0;
357 364
358 current = message; 365 current = message;
359 remaining = size; 366 remaining = size;
360 367
361 while (remaining > 0) { 368 while (remaining > 0) {
362 ssize_t length; 369 ssize_t length;
363 370
364 if (quoted) { 371 if (quoted) {
365 if (current[0] == '.') 372 if (current[0] == '.')
366 if (mailstream_write(s, ".", 1) == -1) 373 if (mailstream_write(s, ".", 1) == -1)
367 goto err; 374 goto err;
368 } 375 }
369 376
370 length = send_data_line(s, current, remaining); 377 length = send_data_line(s, current, remaining);
371 if (length < 0) 378 if (length < 0)
372 goto err; 379 goto err;
373 380
374 current += length; 381 current += length;
375 382
376 count += length; 383 count += length;
377 if ((progr_rate != 0) && (progr_fun != NULL)) 384 if ((progr_rate != 0) && (progr_fun != NULL))
378 if (count - last >= progr_rate) { 385 if (count - last >= progr_rate) {
379 (* progr_fun)(count, size); 386 (* progr_fun)(count, size);
380 last = count; 387 last = count;
381 } 388 }
382 389
383 remaining -= length; 390 remaining -= length;
384 } 391 }
385 392
386 return 0; 393 return 0;
387 394
388 err: 395 err:
389 return -1; 396 return -1;
390} 397}
391 398
392int mailstream_send_data_crlf(mailstream * s, const char * message, 399int mailstream_send_data_crlf(mailstream * s, const char * message,
393 size_t size, 400 size_t size,
394 size_t progr_rate, 401 size_t progr_rate,
395 progress_function * progr_fun) 402 progress_function * progr_fun)
396{ 403{
397 return send_data_crlf(s, message, size, 0, progr_rate, progr_fun); 404 return send_data_crlf(s, message, size, 0, progr_rate, progr_fun);
398} 405}
399 406
400int mailstream_send_data(mailstream * s, const char * message, 407int mailstream_send_data(mailstream * s, const char * message,
401 size_t size, 408 size_t size,
402 size_t progr_rate, 409 size_t progr_rate,
403 progress_function * progr_fun) 410 progress_function * progr_fun)
404{ 411{
405 if (send_data_crlf(s, message, size, 1, progr_rate, progr_fun) == -1) 412 if (send_data_crlf(s, message, size, 1, progr_rate, progr_fun) == -1)
406 goto err; 413 goto err;
407 414
408 if (mailstream_write(s, "\r\n.\r\n", 5) == -1) 415 if (mailstream_write(s, "\r\n.\r\n", 5) == -1)
409 goto err; 416 goto err;
410 417
411 if (mailstream_flush(s) == -1) 418 if (mailstream_flush(s) == -1)
412 goto err; 419 goto err;
413 420
414 return 0; 421 return 0;
415 422
416 err: 423 err:
417 return -1; 424 return -1;
418} 425}
419 426
420static inline ssize_t get_data_size(const char * line, size_t length, 427static inline ssize_t get_data_size(const char * line, size_t length,
421 size_t * result) 428 size_t * result)
422{ 429{
423 int fix_eol; 430 int fix_eol;
424 const char * start; 431 const char * start;
425 size_t count; 432 size_t count;
426 size_t fixed_count; 433 size_t fixed_count;
427 434
428 start = line; 435 start = line;
429 436
430 fix_eol = 0; 437 fix_eol = 0;
431 count = 0; 438 count = 0;
432 fixed_count = 0; 439 fixed_count = 0;
433 440
434 while (1) { 441 while (1) {
435 if (length == 0) 442 if (length == 0)
436 break; 443 break;
437 444
438 if (* line == '\r') { 445 if (* line == '\r') {
439 line ++; 446 line ++;
440 447
441 count ++; 448 count ++;
442 length --; 449 length --;
443 450
444 if (length == 0) { 451 if (length == 0) {
445 fix_eol = 1; 452 fix_eol = 1;
446 fixed_count ++; 453 fixed_count ++;
447 break; 454 break;
448 } 455 }
449 456
450 if (* line == '\n') { 457 if (* line == '\n') {
451 line ++; 458 line ++;
452 459
453 count ++; 460 count ++;
454 length --; 461 length --;
455 462
456 break; 463 break;
457 } 464 }
458 else { 465 else {
459 fix_eol = 1; 466 fix_eol = 1;
460 fixed_count ++; 467 fixed_count ++;
461 break; 468 break;
462 } 469 }
463 } 470 }
464 else if (* line == '\n') { 471 else if (* line == '\n') {
465 line ++; 472 line ++;
466 473
467 count ++; 474 count ++;
468 length --; 475 length --;
469 476
470 fix_eol = 1; 477 fix_eol = 1;
471 fixed_count ++; 478 fixed_count ++;
472 break; 479 break;
473 } 480 }
474 481
475 line ++; 482 line ++;
476 length --; 483 length --;
477 count ++; 484 count ++;
478 } 485 }
479 486
480 * result = count + fixed_count; 487 * result = count + fixed_count;
481 488
482 return count; 489 return count;
483} 490}
484 491
485size_t mailstream_get_data_crlf_size(const char * message, size_t size) 492size_t mailstream_get_data_crlf_size(const char * message, size_t size)
486{ 493{
487 const char * current; 494 const char * current;
488 size_t count; 495 size_t count;
489 size_t last; 496 size_t last;
490 size_t remaining; 497 size_t remaining;
491 size_t fixed_count; 498 size_t fixed_count;
492 499
493 count = 0; 500 count = 0;
494 last = 0; 501 last = 0;
495 fixed_count = 0; 502 fixed_count = 0;
496 503
497 current = message; 504 current = message;
498 remaining = size; 505 remaining = size;
499 506
500 while (remaining > 0) { 507 while (remaining > 0) {
501 ssize_t length; 508 ssize_t length;
502 size_t line_count; 509 size_t line_count;
503 510
504 length = get_data_size(current, remaining, &line_count); 511 length = get_data_size(current, remaining, &line_count);
505 512
506 fixed_count += line_count; 513 fixed_count += line_count;
507 current += length; 514 current += length;
508 515
509 count += length; 516 count += length;
510 517
511 remaining -= length; 518 remaining -= length;
512 } 519 }
513 520
514 return fixed_count; 521 return fixed_count;
515} 522}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver.c b/libetpan/src/driver/implementation/pop3/pop3driver.c
index ea69923..6cc6a9a 100644
--- a/libetpan/src/driver/implementation/pop3/pop3driver.c
+++ b/libetpan/src/driver/implementation/pop3/pop3driver.c
@@ -1,388 +1,394 @@
1/* 1/*
2 * libEtPan! -- a mail stuff library 2 * libEtPan! -- a mail stuff library
3 * 3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa 4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its 15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived 16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * $Id$ 33 * $Id$
34 */ 34 */
35 35
36#include "pop3driver.h" 36#include "pop3driver.h"
37 37
38#include <string.h> 38#include <string.h>
39#include <stdlib.h> 39#include <stdlib.h>
40 40
41#include "pop3driver_message.h" 41#include "pop3driver_message.h"
42#include "maildriver_tools.h" 42#include "maildriver_tools.h"
43#include "pop3driver_tools.h" 43#include "pop3driver_tools.h"
44#include "mailmessage.h" 44#include "mailmessage.h"
45 45
46static int pop3driver_initialize(mailsession * session); 46static int pop3driver_initialize(mailsession * session);
47 47
48static void pop3driver_uninitialize(mailsession * session); 48static void pop3driver_uninitialize(mailsession * session);
49 49
50static int pop3driver_parameters(mailsession * session, 50static int pop3driver_parameters(mailsession * session,
51 int id, void * value); 51 int id, void * value);
52 52
53static int pop3driver_connect_stream(mailsession * session, mailstream * s); 53static int pop3driver_connect_stream(mailsession * session, mailstream * s);
54 54
55static int pop3driver_starttls(mailsession * session); 55static int pop3driver_starttls(mailsession * session);
56 56
57static int pop3driver_login(mailsession * session, 57static int pop3driver_login(mailsession * session,
58 char * userid, char * password); 58 char * userid, char * password);
59 59
60static int pop3driver_logout(mailsession * session); 60static int pop3driver_logout(mailsession * session);
61 61
62static int pop3driver_noop(mailsession * session); 62static int pop3driver_noop(mailsession * session);
63 63
64static int pop3driver_status_folder(mailsession * session, char * mb, 64static int pop3driver_status_folder(mailsession * session, char * mb,
65 uint32_t * result_messages, uint32_t * result_recent, 65 uint32_t * result_messages, uint32_t * result_recent,
66 uint32_t * result_unseen); 66 uint32_t * result_unseen);
67 67
68static int pop3driver_messages_number(mailsession * session, char * mb, 68static int pop3driver_messages_number(mailsession * session, char * mb,
69 uint32_t * result); 69 uint32_t * result);
70 70
71static int pop3driver_remove_message(mailsession * session, uint32_t num); 71static int pop3driver_remove_message(mailsession * session, uint32_t num);
72 72
73static int pop3driver_get_messages_list(mailsession * session, 73static int pop3driver_get_messages_list(mailsession * session,
74 struct mailmessage_list ** result); 74 struct mailmessage_list ** result);
75 75
76static int pop3driver_get_message(mailsession * session, 76static int pop3driver_get_message(mailsession * session,
77 uint32_t num, mailmessage ** result); 77 uint32_t num, mailmessage ** result);
78 78
79static mailsession_driver local_pop3_session_driver = { 79static mailsession_driver local_pop3_session_driver = {
80 .sess_name = "pop3", 80 .sess_name = "pop3",
81 81
82 .sess_initialize = pop3driver_initialize, 82 .sess_initialize = pop3driver_initialize,
83 .sess_uninitialize = pop3driver_uninitialize, 83 .sess_uninitialize = pop3driver_uninitialize,
84 84
85 .sess_parameters = pop3driver_parameters, 85 .sess_parameters = pop3driver_parameters,
86 86
87 .sess_connect_stream = pop3driver_connect_stream, 87 .sess_connect_stream = pop3driver_connect_stream,
88 .sess_connect_path = NULL, 88 .sess_connect_path = NULL,
89 .sess_starttls = pop3driver_starttls, 89 .sess_starttls = pop3driver_starttls,
90 .sess_login = pop3driver_login, 90 .sess_login = pop3driver_login,
91 .sess_logout = pop3driver_logout, 91 .sess_logout = pop3driver_logout,
92 .sess_noop = pop3driver_noop, 92 .sess_noop = pop3driver_noop,
93 93
94 .sess_build_folder_name = NULL, 94 .sess_build_folder_name = NULL,
95 .sess_create_folder = NULL, 95 .sess_create_folder = NULL,
96 .sess_delete_folder = NULL, 96 .sess_delete_folder = NULL,
97 .sess_rename_folder = NULL, 97 .sess_rename_folder = NULL,
98 .sess_check_folder = NULL, 98 .sess_check_folder = NULL,
99 .sess_examine_folder = NULL, 99 .sess_examine_folder = NULL,
100 .sess_select_folder = NULL, 100 .sess_select_folder = NULL,
101 .sess_expunge_folder = NULL, 101 .sess_expunge_folder = NULL,
102 .sess_status_folder = pop3driver_status_folder, 102 .sess_status_folder = pop3driver_status_folder,
103 .sess_messages_number = pop3driver_messages_number, 103 .sess_messages_number = pop3driver_messages_number,
104 .sess_recent_number = pop3driver_messages_number, 104 .sess_recent_number = pop3driver_messages_number,
105 .sess_unseen_number = pop3driver_messages_number, 105 .sess_unseen_number = pop3driver_messages_number,
106 .sess_list_folders = NULL, 106 .sess_list_folders = NULL,
107 .sess_lsub_folders = NULL, 107 .sess_lsub_folders = NULL,
108 .sess_subscribe_folder = NULL, 108 .sess_subscribe_folder = NULL,
109 .sess_unsubscribe_folder = NULL, 109 .sess_unsubscribe_folder = NULL,
110 110
111 .sess_append_message = NULL, 111 .sess_append_message = NULL,
112 .sess_append_message_flags = NULL, 112 .sess_append_message_flags = NULL,
113 .sess_copy_message = NULL, 113 .sess_copy_message = NULL,
114 .sess_move_message = NULL, 114 .sess_move_message = NULL,
115 115
116 .sess_get_messages_list = pop3driver_get_messages_list, 116 .sess_get_messages_list = pop3driver_get_messages_list,
117 .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, 117 .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
118 .sess_remove_message = pop3driver_remove_message, 118 .sess_remove_message = pop3driver_remove_message,
119#if 0 119#if 0
120 .sess_search_messages = maildriver_generic_search_messages, 120 .sess_search_messages = maildriver_generic_search_messages,
121#endif 121#endif
122 122
123 .sess_get_message = pop3driver_get_message, 123 .sess_get_message = pop3driver_get_message,
124 .sess_get_message_by_uid = NULL, 124 .sess_get_message_by_uid = NULL,
125}; 125};
126 126
127mailsession_driver * pop3_session_driver = &local_pop3_session_driver; 127mailsession_driver * pop3_session_driver = &local_pop3_session_driver;
128 128
129static inline struct pop3_session_state_data * 129static inline struct pop3_session_state_data *
130get_data(mailsession * session) 130get_data(mailsession * session)
131{ 131{
132 return session->sess_data; 132 return session->sess_data;
133} 133}
134 134
135static mailpop3 * get_pop3_session(mailsession * session) 135static mailpop3 * get_pop3_session(mailsession * session)
136{ 136{
137 return get_data(session)->pop3_session; 137 return get_data(session)->pop3_session;
138} 138}
139 139
140static int pop3driver_initialize(mailsession * session) 140static int pop3driver_initialize(mailsession * session)
141{ 141{
142 struct pop3_session_state_data * data; 142 struct pop3_session_state_data * data;
143 mailpop3 * pop3; 143 mailpop3 * pop3;
144 144
145 pop3 = mailpop3_new(0, NULL); 145 pop3 = mailpop3_new(0, NULL);
146 if (session == NULL) 146 if (session == NULL)
147 goto err; 147 goto err;
148 148
149 data = malloc(sizeof(* data)); 149 data = malloc(sizeof(* data));
150 if (data == NULL) 150 if (data == NULL)
151 goto free; 151 goto free;
152 152
153 data->pop3_session = pop3; 153 data->pop3_session = pop3;
154 data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; 154 data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
155 155
156 session->sess_data = data; 156 session->sess_data = data;
157 157
158 return MAIL_NO_ERROR; 158 return MAIL_NO_ERROR;
159 159
160 free: 160 free:
161 mailpop3_free(pop3); 161 mailpop3_free(pop3);
162 err: 162 err:
163 return MAIL_ERROR_MEMORY; 163 return MAIL_ERROR_MEMORY;
164} 164}
165 165
166static void pop3driver_uninitialize(mailsession * session) 166static void pop3driver_uninitialize(mailsession * session)
167{ 167{
168 struct pop3_session_state_data * data; 168 struct pop3_session_state_data * data;
169 169
170 data = get_data(session); 170 data = get_data(session);
171 171
172 mailpop3_free(data->pop3_session); 172 mailpop3_free(data->pop3_session);
173 free(data); 173 free(data);
174 174
175 session->sess_data = data; 175 session->sess_data = data;
176} 176}
177 177
178static int pop3driver_connect_stream(mailsession * session, mailstream * s) 178static int pop3driver_connect_stream(mailsession * session, mailstream * s)
179{ 179{
180 int r; 180 int r;
181 181
182 r = mailpop3_connect(get_pop3_session(session), s); 182 r = mailpop3_connect(get_pop3_session(session), s);
183 183
184 switch (r) { 184 switch (r) {
185 case MAILPOP3_NO_ERROR: 185 case MAILPOP3_NO_ERROR:
186 return MAIL_NO_ERROR_NON_AUTHENTICATED; 186 return MAIL_NO_ERROR_NON_AUTHENTICATED;
187 187
188 default: 188 default:
189 return pop3driver_pop3_error_to_mail_error(r); 189 return pop3driver_pop3_error_to_mail_error(r);
190 } 190 }
191} 191}
192 192
193static int pop3driver_starttls(mailsession * session) 193static int pop3driver_starttls(mailsession * session)
194{ 194{
195 int r; 195 int r;
196 int fd; 196 int fd;
197 mailstream_low * low; 197 mailstream_low * low;
198 mailstream_low * new_low; 198 mailstream_low * new_low;
199 mailpop3 * pop3; 199 mailpop3 * pop3;
200 200
201 pop3 = get_pop3_session(session); 201 pop3 = get_pop3_session(session);
202 202
203 r = mailpop3_stls(pop3); 203 r = mailpop3_stls(pop3);
204 204
205 switch (r) { 205 switch (r) {
206 case MAILPOP3_NO_ERROR: 206 case MAILPOP3_NO_ERROR:
207 break; 207 break;
208 default: 208 default:
209 return pop3driver_pop3_error_to_mail_error(r); 209 return pop3driver_pop3_error_to_mail_error(r);
210 } 210 }
211 211
212 low = mailstream_get_low(pop3->pop3_stream); 212 low = mailstream_get_low(pop3->pop3_stream);
213 fd = mailstream_low_get_fd(low); 213 fd = mailstream_low_get_fd(low);
214 if (fd == -1) 214 if (fd == -1)
215 return MAIL_ERROR_STREAM; 215 return MAIL_ERROR_STREAM;
216 216
217 new_low = mailstream_low_ssl_open(fd); 217 new_low = mailstream_low_ssl_open(fd);
218 if (new_low == NULL) 218 if (new_low == NULL)
219 return MAIL_ERROR_STREAM; 219 return MAIL_ERROR_STREAM;
220 mailstream_low_free(low); 220 mailstream_low_free(low);
221 mailstream_set_low(pop3->pop3_stream, new_low); 221 mailstream_set_low(pop3->pop3_stream, new_low);
222 222
223 return MAIL_NO_ERROR; 223 return MAIL_NO_ERROR;
224} 224}
225 225
226static int pop3driver_parameters(mailsession * session, 226static int pop3driver_parameters(mailsession * session,
227 int id, void * value) 227 int id, void * value)
228{ 228{
229 struct pop3_session_state_data * data; 229 struct pop3_session_state_data * data;
230 230
231 data = get_data(session); 231 data = get_data(session);
232 232
233 switch (id) { 233 switch (id) {
234 case POP3DRIVER_SET_AUTH_TYPE: 234 case POP3DRIVER_SET_AUTH_TYPE:
235 { 235 {
236 int * param; 236 int * param;
237 237
238 param = value; 238 param = value;
239 239
240 data->pop3_auth_type = * param; 240 data->pop3_auth_type = * param;
241 return MAIL_NO_ERROR; 241 return MAIL_NO_ERROR;
242 } 242 }
243 } 243 }
244 244
245 return MAIL_ERROR_INVAL; 245 return MAIL_ERROR_INVAL;
246} 246}
247 247
248static int pop3driver_login(mailsession * session, 248static int pop3driver_login(mailsession * session,
249 char * userid, char * password) 249 char * userid, char * password)
250{ 250{
251 int r; 251 int r;
252 //LR
253 int ret;
252 carray * msg_tab; 254 carray * msg_tab;
253 struct pop3_session_state_data * data; 255 struct pop3_session_state_data * data;
254 256
255 data = get_data(session); 257 data = get_data(session);
256 258
257 switch (data->pop3_auth_type) { 259 switch (data->pop3_auth_type) {
258 case POP3DRIVER_AUTH_TYPE_TRY_APOP: 260 case POP3DRIVER_AUTH_TYPE_TRY_APOP:
259 r = mailpop3_login_apop(get_pop3_session(session), userid, password); 261 r = mailpop3_login_apop(get_pop3_session(session), userid, password);
260 if (r != MAILPOP3_NO_ERROR) 262 if (r != MAILPOP3_NO_ERROR)
261 r = mailpop3_login(get_pop3_session(session), userid, password); 263 r = mailpop3_login(get_pop3_session(session), userid, password);
262 break; 264 break;
263 265
264 case POP3DRIVER_AUTH_TYPE_APOP: 266 case POP3DRIVER_AUTH_TYPE_APOP:
265 r = mailpop3_login_apop(get_pop3_session(session), userid, password); 267 r = mailpop3_login_apop(get_pop3_session(session), userid, password);
266 break; 268 break;
267 269
268 default: 270 default:
269 case POP3DRIVER_AUTH_TYPE_PLAIN: 271 case POP3DRIVER_AUTH_TYPE_PLAIN:
270 r = mailpop3_login(get_pop3_session(session), userid, password); 272 r = mailpop3_login(get_pop3_session(session), userid, password);
271 break; 273 break;
272 } 274 }
273 275
274 mailpop3_list(get_pop3_session(session), &msg_tab); 276 // LR 2 lines
277 ret = pop3driver_pop3_error_to_mail_error(r);
278 if ( ret == MAIL_NO_ERROR )
279 mailpop3_list(get_pop3_session(session), &msg_tab);
280 // LR
275 281
276 return pop3driver_pop3_error_to_mail_error(r); 282 return pop3driver_pop3_error_to_mail_error(r);
277} 283}
278 284
279static int pop3driver_logout(mailsession * session) 285static int pop3driver_logout(mailsession * session)
280{ 286{
281 int r; 287 int r;
282 288
283 r = mailpop3_quit(get_pop3_session(session)); 289 r = mailpop3_quit(get_pop3_session(session));
284 290
285 return pop3driver_pop3_error_to_mail_error(r); 291 return pop3driver_pop3_error_to_mail_error(r);
286} 292}
287 293
288static int pop3driver_noop(mailsession * session) 294static int pop3driver_noop(mailsession * session)
289{ 295{
290 int r; 296 int r;
291 297
292 r = mailpop3_noop(get_pop3_session(session)); 298 r = mailpop3_noop(get_pop3_session(session));
293 299
294 return pop3driver_pop3_error_to_mail_error(r); 300 return pop3driver_pop3_error_to_mail_error(r);
295} 301}
296 302
297static int pop3driver_status_folder(mailsession * session, char * mb, 303static int pop3driver_status_folder(mailsession * session, char * mb,
298 uint32_t * result_messages, 304 uint32_t * result_messages,
299 uint32_t * result_recent, 305 uint32_t * result_recent,
300 uint32_t * result_unseen) 306 uint32_t * result_unseen)
301{ 307{
302 uint32_t count; 308 uint32_t count;
303 int r; 309 int r;
304 310
305 r = pop3driver_messages_number(session, mb, &count); 311 r = pop3driver_messages_number(session, mb, &count);
306 if (r != MAIL_NO_ERROR) 312 if (r != MAIL_NO_ERROR)
307 return r; 313 return r;
308 314
309 * result_messages = count; 315 * result_messages = count;
310 * result_recent = count; 316 * result_recent = count;
311 * result_unseen = count; 317 * result_unseen = count;
312 318
313 return MAIL_NO_ERROR; 319 return MAIL_NO_ERROR;
314} 320}
315 321
316static int pop3driver_messages_number(mailsession * session, char * mb, 322static int pop3driver_messages_number(mailsession * session, char * mb,
317 uint32_t * result) 323 uint32_t * result)
318{ 324{
319 carray * msg_tab; 325 carray * msg_tab;
320 326
321 mailpop3_list(get_pop3_session(session), &msg_tab); 327 mailpop3_list(get_pop3_session(session), &msg_tab);
322 328
323 * result = carray_count(msg_tab) - 329 * result = carray_count(msg_tab) -
324 get_pop3_session(session)->pop3_deleted_count; 330 get_pop3_session(session)->pop3_deleted_count;
325 331
326 return MAIL_NO_ERROR; 332 return MAIL_NO_ERROR;
327} 333}
328 334
329 335
330/* messages operations */ 336/* messages operations */
331 337
332static int pop3driver_remove_message(mailsession * session, uint32_t num) 338static int pop3driver_remove_message(mailsession * session, uint32_t num)
333{ 339{
334 mailpop3 * pop3; 340 mailpop3 * pop3;
335 int r; 341 int r;
336 342
337 pop3 = get_pop3_session(session); 343 pop3 = get_pop3_session(session);
338 344
339 r = mailpop3_dele(pop3, num); 345 r = mailpop3_dele(pop3, num);
340 switch (r) { 346 switch (r) {
341 case MAILPOP3_ERROR_BAD_STATE: 347 case MAILPOP3_ERROR_BAD_STATE:
342 return MAIL_ERROR_BAD_STATE; 348 return MAIL_ERROR_BAD_STATE;
343 349
344 case MAILPOP3_ERROR_NO_SUCH_MESSAGE: 350 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
345 return MAIL_ERROR_MSG_NOT_FOUND; 351 return MAIL_ERROR_MSG_NOT_FOUND;
346 352
347 case MAILPOP3_ERROR_STREAM: 353 case MAILPOP3_ERROR_STREAM:
348 return MAIL_ERROR_STREAM; 354 return MAIL_ERROR_STREAM;
349 355
350 case MAILPOP3_NO_ERROR: 356 case MAILPOP3_NO_ERROR:
351 return MAIL_NO_ERROR; 357 return MAIL_NO_ERROR;
352 358
353 default: 359 default:
354 return MAIL_ERROR_REMOVE; 360 return MAIL_ERROR_REMOVE;
355 } 361 }
356} 362}
357 363
358static int pop3driver_get_messages_list(mailsession * session, 364static int pop3driver_get_messages_list(mailsession * session,
359 struct mailmessage_list ** result) 365 struct mailmessage_list ** result)
360{ 366{
361 mailpop3 * pop3; 367 mailpop3 * pop3;
362 368
363 pop3 = get_pop3_session(session); 369 pop3 = get_pop3_session(session);
364 370
365 return pop3_get_messages_list(pop3, session, 371 return pop3_get_messages_list(pop3, session,
366 pop3_message_driver, result); 372 pop3_message_driver, result);
367} 373}
368 374
369static int pop3driver_get_message(mailsession * session, 375static int pop3driver_get_message(mailsession * session,
370 uint32_t num, mailmessage ** result) 376 uint32_t num, mailmessage ** result)
371{ 377{
372 mailmessage * msg_info; 378 mailmessage * msg_info;
373 int r; 379 int r;
374 380
375 msg_info = mailmessage_new(); 381 msg_info = mailmessage_new();
376 if (msg_info == NULL) 382 if (msg_info == NULL)
377 return MAIL_ERROR_MEMORY; 383 return MAIL_ERROR_MEMORY;
378 384
379 r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0); 385 r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0);
380 if (r != MAIL_NO_ERROR) { 386 if (r != MAIL_NO_ERROR) {
381 mailmessage_free(msg_info); 387 mailmessage_free(msg_info);
382 return r; 388 return r;
383 } 389 }
384 390
385 * result = msg_info; 391 * result = msg_info;
386 392
387 return MAIL_NO_ERROR; 393 return MAIL_NO_ERROR;
388} 394}
diff --git a/libetpan/src/low-level/imap/mailimap_parser.c b/libetpan/src/low-level/imap/mailimap_parser.c
index ab4db67..071891c 100644
--- a/libetpan/src/low-level/imap/mailimap_parser.c
+++ b/libetpan/src/low-level/imap/mailimap_parser.c
@@ -1634,1538 +1634,1556 @@ static int mailimap_body_parse(mailstream * fd, MMAPString * buffer,
1634 r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part, 1634 r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part,
1635 progr_rate, progr_fun); 1635 progr_rate, progr_fun);
1636 if (r == MAILIMAP_NO_ERROR) 1636 if (r == MAILIMAP_NO_ERROR)
1637 type = MAILIMAP_BODY_1PART; 1637 type = MAILIMAP_BODY_1PART;
1638 1638
1639 if (r == MAILIMAP_ERROR_PARSE) { 1639 if (r == MAILIMAP_ERROR_PARSE) {
1640 r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token, 1640 r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token,
1641 &body_type_mpart, 1641 &body_type_mpart,
1642 progr_rate, progr_fun); 1642 progr_rate, progr_fun);
1643 1643
1644 if (r == MAILIMAP_NO_ERROR) 1644 if (r == MAILIMAP_NO_ERROR)
1645 type = MAILIMAP_BODY_MPART; 1645 type = MAILIMAP_BODY_MPART;
1646 } 1646 }
1647 1647
1648 if (r != MAILIMAP_NO_ERROR) { 1648 if (r != MAILIMAP_NO_ERROR) {
1649 res = r; 1649 res = r;
1650 goto err; 1650 goto err;
1651 } 1651 }
1652 1652
1653 r = mailimap_cparenth_parse(fd, buffer, &cur_token); 1653 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1654 if (r != MAILIMAP_NO_ERROR) { 1654 if (r != MAILIMAP_NO_ERROR) {
1655 res = r; 1655 res = r;
1656 goto free; 1656 goto free;
1657 } 1657 }
1658 1658
1659 body = mailimap_body_new(type, body_type_1part, body_type_mpart); 1659 body = mailimap_body_new(type, body_type_1part, body_type_mpart);
1660 if (body == NULL) { 1660 if (body == NULL) {
1661 res = MAILIMAP_ERROR_MEMORY; 1661 res = MAILIMAP_ERROR_MEMORY;
1662 goto free; 1662 goto free;
1663 } 1663 }
1664 1664
1665 * result = body; 1665 * result = body;
1666 * index = cur_token; 1666 * index = cur_token;
1667 1667
1668 return MAILIMAP_NO_ERROR; 1668 return MAILIMAP_NO_ERROR;
1669 1669
1670 free: 1670 free:
1671 if (body_type_1part) 1671 if (body_type_1part)
1672 mailimap_body_type_1part_free(body_type_1part); 1672 mailimap_body_type_1part_free(body_type_1part);
1673 if (body_type_mpart) 1673 if (body_type_mpart)
1674 mailimap_body_type_mpart_free(body_type_mpart); 1674 mailimap_body_type_mpart_free(body_type_mpart);
1675 err: 1675 err:
1676 return res; 1676 return res;
1677} 1677}
1678 1678
1679/* 1679/*
1680 body-extension = nstring / number / 1680 body-extension = nstring / number /
1681 "(" body-extension *(SP body-extension) ")" 1681 "(" body-extension *(SP body-extension) ")"
1682 ; Future expansion. Client implementations 1682 ; Future expansion. Client implementations
1683 ; MUST accept body-extension fields. Server 1683 ; MUST accept body-extension fields. Server
1684 ; implementations MUST NOT generate 1684 ; implementations MUST NOT generate
1685 ; body-extension fields except as defined by 1685 ; body-extension fields except as defined by
1686 ; future standard or standards-track 1686 ; future standard or standards-track
1687 ; revisions of this specification. 1687 ; revisions of this specification.
1688*/ 1688*/
1689 1689
1690/* 1690/*
1691 "(" body-extension *(SP body-extension) ")" 1691 "(" body-extension *(SP body-extension) ")"
1692*/ 1692*/
1693 1693
1694static int 1694static int
1695mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer, 1695mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer,
1696 size_t * index, 1696 size_t * index,
1697 clist ** result, 1697 clist ** result,
1698 size_t progr_rate, 1698 size_t progr_rate,
1699 progress_function * progr_fun) 1699 progress_function * progr_fun)
1700{ 1700{
1701 size_t cur_token; 1701 size_t cur_token;
1702 clist * list; 1702 clist * list;
1703 int r; 1703 int r;
1704 int res; 1704 int res;
1705 1705
1706 cur_token = * index; 1706 cur_token = * index;
1707 1707
1708 r = mailimap_oparenth_parse(fd, buffer, &cur_token); 1708 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1709 if (r != MAILIMAP_NO_ERROR) { 1709 if (r != MAILIMAP_NO_ERROR) {
1710 res = r; 1710 res = r;
1711 goto err; 1711 goto err;
1712 } 1712 }
1713 1713
1714 r = mailimap_struct_spaced_list_parse(fd, buffer, 1714 r = mailimap_struct_spaced_list_parse(fd, buffer,
1715 &cur_token, &list, 1715 &cur_token, &list,
1716 (mailimap_struct_parser * ) 1716 (mailimap_struct_parser * )
1717 mailimap_body_extension_parse, 1717 mailimap_body_extension_parse,
1718 (mailimap_struct_destructor * ) 1718 (mailimap_struct_destructor * )
1719 mailimap_body_extension_free, 1719 mailimap_body_extension_free,
1720 progr_rate, progr_fun); 1720 progr_rate, progr_fun);
1721 if (r != MAILIMAP_NO_ERROR) { 1721 if (r != MAILIMAP_NO_ERROR) {
1722 res = r; 1722 res = r;
1723 goto err; 1723 goto err;
1724 } 1724 }
1725 1725
1726 r = mailimap_cparenth_parse(fd, buffer, &cur_token); 1726 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1727 if (r != MAILIMAP_NO_ERROR) { 1727 if (r != MAILIMAP_NO_ERROR) {
1728 res = r; 1728 res = r;
1729 goto free_list; 1729 goto free_list;
1730 } 1730 }
1731 1731
1732 * index = cur_token; 1732 * index = cur_token;
1733 * result = list; 1733 * result = list;
1734 1734
1735 return MAILIMAP_NO_ERROR; 1735 return MAILIMAP_NO_ERROR;
1736 1736
1737 free_list: 1737 free_list:
1738 clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL); 1738 clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL);
1739 clist_free(list); 1739 clist_free(list);
1740 err: 1740 err:
1741 return res; 1741 return res;
1742} 1742}
1743 1743
1744/* 1744/*
1745 body-extension = nstring / number / 1745 body-extension = nstring / number /
1746 "(" body-extension *(SP body-extension) ")" 1746 "(" body-extension *(SP body-extension) ")"
1747 ; Future expansion. Client implementations 1747 ; Future expansion. Client implementations
1748 ; MUST accept body-extension fields. Server 1748 ; MUST accept body-extension fields. Server
1749 ; implementations MUST NOT generate 1749 ; implementations MUST NOT generate
1750 ; body-extension fields except as defined by 1750 ; body-extension fields except as defined by
1751 ; future standard or standards-track 1751 ; future standard or standards-track
1752 ; revisions of this specification. 1752 ; revisions of this specification.
1753*/ 1753*/
1754 1754
1755static int 1755static int
1756mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, 1756mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer,
1757 size_t * index, 1757 size_t * index,
1758 struct mailimap_body_extension ** result, 1758 struct mailimap_body_extension ** result,
1759 size_t progr_rate, 1759 size_t progr_rate,
1760 progress_function * progr_fun) 1760 progress_function * progr_fun)
1761{ 1761{
1762 size_t cur_token; 1762 size_t cur_token;
1763 uint32_t number; 1763 uint32_t number;
1764 char * nstring; 1764 char * nstring;
1765 clist * body_extension_list; 1765 clist * body_extension_list;
1766 struct mailimap_body_extension * body_extension; 1766 struct mailimap_body_extension * body_extension;
1767 int type; 1767 int type;
1768 int r; 1768 int r;
1769 int res; 1769 int res;
1770 1770
1771 cur_token = * index; 1771 cur_token = * index;
1772 1772
1773 nstring = NULL; 1773 nstring = NULL;
1774 number = 0; 1774 number = 0;
1775 body_extension_list = NULL; 1775 body_extension_list = NULL;
1776 type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */ 1776 type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */
1777 1777
1778 r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL, 1778 r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL,
1779 progr_rate, progr_fun); 1779 progr_rate, progr_fun);
1780 if (r == MAILIMAP_NO_ERROR) 1780 if (r == MAILIMAP_NO_ERROR)
1781 type = MAILIMAP_BODY_EXTENSION_NSTRING; 1781 type = MAILIMAP_BODY_EXTENSION_NSTRING;
1782 1782
1783 if (r == MAILIMAP_ERROR_PARSE) { 1783 if (r == MAILIMAP_ERROR_PARSE) {
1784 r = mailimap_number_parse(fd, buffer, &cur_token, &number); 1784 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
1785 1785
1786 if (r == MAILIMAP_NO_ERROR) 1786 if (r == MAILIMAP_NO_ERROR)
1787 type = MAILIMAP_BODY_EXTENSION_NUMBER; 1787 type = MAILIMAP_BODY_EXTENSION_NUMBER;
1788 } 1788 }
1789 1789
1790 if (r == MAILIMAP_ERROR_PARSE) { 1790 if (r == MAILIMAP_ERROR_PARSE) {
1791 r = mailimap_body_ext_list_parse(fd, buffer, &cur_token, 1791 r = mailimap_body_ext_list_parse(fd, buffer, &cur_token,
1792 &body_extension_list, 1792 &body_extension_list,
1793 progr_rate, progr_fun); 1793 progr_rate, progr_fun);
1794 1794
1795 if (r == MAILIMAP_NO_ERROR) 1795 if (r == MAILIMAP_NO_ERROR)
1796 type = MAILIMAP_BODY_EXTENSION_LIST; 1796 type = MAILIMAP_BODY_EXTENSION_LIST;
1797 } 1797 }
1798 1798
1799 if (r != MAILIMAP_NO_ERROR) { 1799 if (r != MAILIMAP_NO_ERROR) {
1800 res = r; 1800 res = r;
1801 goto err; 1801 goto err;
1802 } 1802 }
1803 1803
1804 body_extension = mailimap_body_extension_new(type, nstring, number, 1804 body_extension = mailimap_body_extension_new(type, nstring, number,
1805 body_extension_list); 1805 body_extension_list);
1806 1806
1807 if (body_extension == NULL) { 1807 if (body_extension == NULL) {
1808 res = MAILIMAP_ERROR_MEMORY; 1808 res = MAILIMAP_ERROR_MEMORY;
1809 goto free; 1809 goto free;
1810 } 1810 }
1811 1811
1812 * result = body_extension; 1812 * result = body_extension;
1813 * index = cur_token; 1813 * index = cur_token;
1814 1814
1815 return MAILIMAP_NO_ERROR; 1815 return MAILIMAP_NO_ERROR;
1816 1816
1817 free: 1817 free:
1818 if (nstring != NULL) 1818 if (nstring != NULL)
1819 mailimap_nstring_free(nstring); 1819 mailimap_nstring_free(nstring);
1820 if (body_extension_list) { 1820 if (body_extension_list) {
1821 clist_foreach(body_extension_list, 1821 clist_foreach(body_extension_list,
1822 (clist_func) mailimap_body_extension_free, 1822 (clist_func) mailimap_body_extension_free,
1823 NULL); 1823 NULL);
1824 clist_free(body_extension_list); 1824 clist_free(body_extension_list);
1825 } 1825 }
1826 err: 1826 err:
1827 return res; 1827 return res;
1828} 1828}
1829 1829
1830/* 1830/*
1831 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang 1831 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1832 *(SP body-extension)]] 1832 *(SP body-extension)]]
1833 ; MUST NOT be returned on non-extensible 1833 ; MUST NOT be returned on non-extensible
1834 ; "BODY" fetch 1834 ; "BODY" fetch
1835*/ 1835*/
1836 1836
1837/* 1837/*
1838 *(SP body-extension) 1838 *(SP body-extension)
1839*/ 1839*/
1840 1840
1841static int 1841static int
1842mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer, 1842mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer,
1843 size_t * index, 1843 size_t * index,
1844 clist ** body_ext_list, 1844 clist ** body_ext_list,
1845 size_t progr_rate, 1845 size_t progr_rate,
1846 progress_function * progr_fun) 1846 progress_function * progr_fun)
1847{ 1847{
1848 size_t cur_token; 1848 size_t cur_token;
1849 int r; 1849 int r;
1850 1850
1851 cur_token = * index; 1851 cur_token = * index;
1852 * body_ext_list = NULL; 1852 * body_ext_list = NULL;
1853 1853
1854 r = mailimap_space_parse(fd, buffer, &cur_token); 1854 r = mailimap_space_parse(fd, buffer, &cur_token);
1855 if (r != MAILIMAP_NO_ERROR) 1855 if (r != MAILIMAP_NO_ERROR)
1856 return r; 1856 return r;
1857 1857
1858 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, 1858 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
1859 body_ext_list, 1859 body_ext_list,
1860 (mailimap_struct_parser *) 1860 (mailimap_struct_parser *)
1861 mailimap_body_extension_parse, 1861 mailimap_body_extension_parse,
1862 (mailimap_struct_destructor *) 1862 (mailimap_struct_destructor *)
1863 mailimap_body_extension_free, 1863 mailimap_body_extension_free,
1864 progr_rate, progr_fun); 1864 progr_rate, progr_fun);
1865 if (r != MAILIMAP_NO_ERROR) 1865 if (r != MAILIMAP_NO_ERROR)
1866 return r; 1866 return r;
1867 1867
1868 * index = cur_token; 1868 * index = cur_token;
1869 1869
1870 return MAILIMAP_NO_ERROR; 1870 return MAILIMAP_NO_ERROR;
1871} 1871}
1872 1872
1873 1873
1874/* 1874/*
1875 [SP body-fld-lang 1875 [SP body-fld-lang
1876 *(SP body-extension)]] 1876 *(SP body-extension)]]
1877*/ 1877*/
1878 1878
1879static int 1879static int
1880mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer, 1880mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer,
1881 size_t * index, 1881 size_t * index,
1882 struct mailimap_body_fld_lang ** fld_lang, 1882 struct mailimap_body_fld_lang ** fld_lang,
1883 clist ** body_ext_list, 1883 clist ** body_ext_list,
1884 size_t progr_rate, 1884 size_t progr_rate,
1885 progress_function * progr_fun) 1885 progress_function * progr_fun)
1886{ 1886{
1887 size_t cur_token; 1887 size_t cur_token;
1888 int r; 1888 int r;
1889 1889
1890 cur_token = * index; 1890 cur_token = * index;
1891 * fld_lang = NULL; 1891 * fld_lang = NULL;
1892 * body_ext_list = NULL; 1892 * body_ext_list = NULL;
1893 1893
1894 r = mailimap_space_parse(fd, buffer, &cur_token); 1894 r = mailimap_space_parse(fd, buffer, &cur_token);
1895 if (r != MAILIMAP_NO_ERROR) 1895 if (r != MAILIMAP_NO_ERROR)
1896 return r; 1896 return r;
1897 1897
1898 r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang, 1898 r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang,
1899 progr_rate, progr_fun); 1899 progr_rate, progr_fun);
1900 if (r != MAILIMAP_NO_ERROR) 1900 if (r != MAILIMAP_NO_ERROR)
1901 return r; 1901 return r;
1902 1902
1903 r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token, 1903 r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token,
1904 body_ext_list, progr_rate, progr_fun); 1904 body_ext_list, progr_rate, progr_fun);
1905 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) 1905 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
1906 return r; 1906 return r;
1907 1907
1908 * index = cur_token; 1908 * index = cur_token;
1909 1909
1910 return MAILIMAP_NO_ERROR; 1910 return MAILIMAP_NO_ERROR;
1911} 1911}
1912 1912
1913 1913
1914/* 1914/*
1915 SP body-fld-dsp [SP body-fld-lang 1915 SP body-fld-dsp [SP body-fld-lang
1916 *(SP body-extension)]] 1916 *(SP body-extension)]]
1917*/ 1917*/
1918 1918
1919static int 1919static int
1920mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer, 1920mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer,
1921 size_t * index, 1921 size_t * index,
1922 struct mailimap_body_fld_dsp ** fld_dsp, 1922 struct mailimap_body_fld_dsp ** fld_dsp,
1923 struct mailimap_body_fld_lang ** fld_lang, 1923 struct mailimap_body_fld_lang ** fld_lang,
1924 clist ** body_ext_list, 1924 clist ** body_ext_list,
1925 size_t progr_rate, 1925 size_t progr_rate,
1926 progress_function * progr_fun) 1926 progress_function * progr_fun)
1927{ 1927{
1928 size_t cur_token; 1928 size_t cur_token;
1929 int r; 1929 int r;
1930 1930
1931 cur_token = * index; 1931 cur_token = * index;
1932 * fld_dsp = NULL; 1932 * fld_dsp = NULL;
1933 * fld_lang = NULL; 1933 * fld_lang = NULL;
1934 * body_ext_list = NULL; 1934 * body_ext_list = NULL;
1935 1935
1936 r = mailimap_space_parse(fd, buffer, &cur_token); 1936 r = mailimap_space_parse(fd, buffer, &cur_token);
1937 if (r != MAILIMAP_NO_ERROR) 1937 if (r != MAILIMAP_NO_ERROR)
1938 return r; 1938 return r;
1939 1939
1940 r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp, 1940 r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp,
1941 progr_rate, progr_fun); 1941 progr_rate, progr_fun);
1942 if (r != MAILIMAP_NO_ERROR) 1942 if (r != MAILIMAP_NO_ERROR)
1943 return r; 1943 return r;
1944 1944
1945 r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token, 1945 r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token,
1946 fld_lang, body_ext_list, 1946 fld_lang, body_ext_list,
1947 progr_rate, progr_fun); 1947 progr_rate, progr_fun);
1948 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) 1948 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
1949 return r; 1949 return r;
1950 1950
1951 * index = cur_token; 1951 * index = cur_token;
1952 1952
1953 return MAILIMAP_NO_ERROR; 1953 return MAILIMAP_NO_ERROR;
1954} 1954}
1955 1955
1956/* 1956/*
1957 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang 1957 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1958 *(SP body-extension)]] 1958 *(SP body-extension)]]
1959 ; MUST NOT be returned on non-extensible 1959 ; MUST NOT be returned on non-extensible
1960 ; "BODY" fetch 1960 ; "BODY" fetch
1961*/ 1961*/
1962 1962
1963static int 1963static int
1964mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, 1964mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer,
1965 size_t * index, 1965 size_t * index,
1966 struct mailimap_body_ext_1part ** result, 1966 struct mailimap_body_ext_1part ** result,
1967 size_t progr_rate, 1967 size_t progr_rate,
1968 progress_function * progr_fun) 1968 progress_function * progr_fun)
1969{ 1969{
1970 size_t cur_token; 1970 size_t cur_token;
1971 1971
1972 char * fld_md5; 1972 char * fld_md5;
1973 struct mailimap_body_fld_dsp * fld_dsp; 1973 struct mailimap_body_fld_dsp * fld_dsp;
1974 struct mailimap_body_fld_lang * fld_lang; 1974 struct mailimap_body_fld_lang * fld_lang;
1975 clist * body_ext_list; 1975 clist * body_ext_list;
1976 int r; 1976 int r;
1977 int res; 1977 int res;
1978 1978
1979 struct mailimap_body_ext_1part * ext_1part; 1979 struct mailimap_body_ext_1part * ext_1part;
1980 1980
1981 cur_token = * index; 1981 cur_token = * index;
1982 1982
1983 fld_md5 = NULL; 1983 fld_md5 = NULL;
1984 fld_dsp = NULL; 1984 fld_dsp = NULL;
1985 fld_lang = NULL; 1985 fld_lang = NULL;
1986 body_ext_list = NULL; 1986 body_ext_list = NULL;
1987 1987
1988 r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5, 1988 r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5,
1989 progr_rate, progr_fun); 1989 progr_rate, progr_fun);
1990 if (r != MAILIMAP_NO_ERROR) { 1990 if (r != MAILIMAP_NO_ERROR) {
1991 res = r; 1991 res = r;
1992 goto err; 1992 goto err;
1993 } 1993 }
1994 1994
1995 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, 1995 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token,
1996 &fld_dsp, 1996 &fld_dsp,
1997 &fld_lang, 1997 &fld_lang,
1998 &body_ext_list, 1998 &body_ext_list,
1999 progr_rate, progr_fun); 1999 progr_rate, progr_fun);
2000 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { 2000 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
2001 res = r; 2001 res = r;
2002 goto free; 2002 goto free;
2003 } 2003 }
2004 2004
2005 ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang, 2005 ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang,
2006 body_ext_list); 2006 body_ext_list);
2007 2007
2008 if (ext_1part == NULL) { 2008 if (ext_1part == NULL) {
2009 res = MAILIMAP_ERROR_MEMORY; 2009 res = MAILIMAP_ERROR_MEMORY;
2010 goto free; 2010 goto free;
2011 } 2011 }
2012 2012
2013 * result = ext_1part; 2013 * result = ext_1part;
2014 * index = cur_token; 2014 * index = cur_token;
2015 2015
2016 return MAILIMAP_NO_ERROR; 2016 return MAILIMAP_NO_ERROR;
2017 2017
2018 free: 2018 free:
2019 if (body_ext_list) { 2019 if (body_ext_list) {
2020 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, 2020 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
2021 NULL); 2021 NULL);
2022 clist_free(body_ext_list); 2022 clist_free(body_ext_list);
2023 } 2023 }
2024 if (fld_lang) 2024 if (fld_lang)
2025 mailimap_body_fld_lang_free(fld_lang); 2025 mailimap_body_fld_lang_free(fld_lang);
2026 if (fld_dsp) 2026 if (fld_dsp)
2027 mailimap_body_fld_dsp_free(fld_dsp); 2027 mailimap_body_fld_dsp_free(fld_dsp);
2028 mailimap_body_fld_md5_free(fld_md5); 2028 mailimap_body_fld_md5_free(fld_md5);
2029 err: 2029 err:
2030 return res; 2030 return res;
2031} 2031}
2032 2032
2033 2033
2034/* 2034/*
2035 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang 2035 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
2036 *(SP body-extension)]] 2036 *(SP body-extension)]]
2037 ; MUST NOT be returned on non-extensible 2037 ; MUST NOT be returned on non-extensible
2038 ; "BODY" fetch 2038 ; "BODY" fetch
2039*/ 2039*/
2040 2040
2041static int 2041static int
2042mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, 2042mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer,
2043 size_t * index, 2043 size_t * index,
2044 struct mailimap_body_ext_mpart ** result, 2044 struct mailimap_body_ext_mpart ** result,
2045 size_t progr_rate, 2045 size_t progr_rate,
2046 progress_function * progr_fun) 2046 progress_function * progr_fun)
2047{ 2047{
2048 size_t cur_token; 2048 size_t cur_token;
2049 2049
2050 struct mailimap_body_fld_dsp * fld_dsp; 2050 struct mailimap_body_fld_dsp * fld_dsp;
2051 struct mailimap_body_fld_lang * fld_lang; 2051 struct mailimap_body_fld_lang * fld_lang;
2052 struct mailimap_body_fld_param * fld_param; 2052 struct mailimap_body_fld_param * fld_param;
2053 clist * body_ext_list; 2053 clist * body_ext_list;
2054 2054
2055 struct mailimap_body_ext_mpart * ext_mpart; 2055 struct mailimap_body_ext_mpart * ext_mpart;
2056 int r; 2056 int r;
2057 int res; 2057 int res;
2058 2058
2059 cur_token = * index; 2059 cur_token = * index;
2060 2060
2061 fld_param = NULL; 2061 fld_param = NULL;
2062 fld_dsp = NULL; 2062 fld_dsp = NULL;
2063 fld_lang = NULL; 2063 fld_lang = NULL;
2064 body_ext_list = NULL; 2064 body_ext_list = NULL;
2065 2065
2066 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param, 2066 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param,
2067 progr_rate, progr_fun); 2067 progr_rate, progr_fun);
2068 if (r != MAILIMAP_NO_ERROR) { 2068 if (r != MAILIMAP_NO_ERROR) {
2069 res = r; 2069 res = r;
2070 goto err; 2070 goto err;
2071 } 2071 }
2072 2072
2073 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, 2073 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token,
2074 &fld_dsp, 2074 &fld_dsp,
2075 &fld_lang, 2075 &fld_lang,
2076 &body_ext_list, 2076 &body_ext_list,
2077 progr_rate, progr_fun); 2077 progr_rate, progr_fun);
2078 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { 2078 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
2079 res = r; 2079 res = r;
2080 goto free; 2080 goto free;
2081 } 2081 }
2082 2082
2083 ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang, 2083 ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang,
2084 body_ext_list); 2084 body_ext_list);
2085 if (ext_mpart == NULL) { 2085 if (ext_mpart == NULL) {
2086 res = MAILIMAP_ERROR_MEMORY; 2086 res = MAILIMAP_ERROR_MEMORY;
2087 goto free; 2087 goto free;
2088 } 2088 }
2089 2089
2090 * result = ext_mpart; 2090 * result = ext_mpart;
2091 * index = cur_token; 2091 * index = cur_token;
2092 2092
2093 return MAILIMAP_NO_ERROR; 2093 return MAILIMAP_NO_ERROR;
2094 2094
2095 free: 2095 free:
2096 if (body_ext_list) { 2096 if (body_ext_list) {
2097 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, 2097 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
2098 NULL); 2098 NULL);
2099 clist_free(body_ext_list); 2099 clist_free(body_ext_list);
2100 } 2100 }
2101 if (fld_lang) 2101 if (fld_lang)
2102 mailimap_body_fld_lang_free(fld_lang); 2102 mailimap_body_fld_lang_free(fld_lang);
2103 if (fld_dsp) 2103 if (fld_dsp)
2104 mailimap_body_fld_dsp_free(fld_dsp); 2104 mailimap_body_fld_dsp_free(fld_dsp);
2105 if (fld_param != NULL) 2105 if (fld_param != NULL)
2106 mailimap_body_fld_param_free(fld_param); 2106 mailimap_body_fld_param_free(fld_param);
2107 err: 2107 err:
2108 return res; 2108 return res;
2109} 2109}
2110 2110
2111/* 2111/*
2112 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP 2112 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
2113 body-fld-enc SP body-fld-octets 2113 body-fld-enc SP body-fld-octets
2114*/ 2114*/
2115 2115
2116static int 2116static int
2117mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, 2117mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer,
2118 size_t * index, 2118 size_t * index,
2119 struct mailimap_body_fields ** result, 2119 struct mailimap_body_fields ** result,
2120 size_t progr_rate, 2120 size_t progr_rate,
2121 progress_function * progr_fun) 2121 progress_function * progr_fun)
2122{ 2122{
2123 struct mailimap_body_fields * body_fields; 2123 struct mailimap_body_fields * body_fields;
2124 size_t cur_token; 2124 size_t cur_token;
2125 struct mailimap_body_fld_param * body_fld_param; 2125 struct mailimap_body_fld_param * body_fld_param;
2126 char * body_fld_id; 2126 char * body_fld_id;
2127 char * body_fld_desc; 2127 char * body_fld_desc;
2128 struct mailimap_body_fld_enc * body_fld_enc; 2128 struct mailimap_body_fld_enc * body_fld_enc;
2129 uint32_t body_fld_octets; 2129 uint32_t body_fld_octets;
2130 int r; 2130 int r;
2131 int res; 2131 int res;
2132 2132
2133 body_fld_param = NULL; 2133 body_fld_param = NULL;
2134 body_fld_id = NULL; 2134 body_fld_id = NULL;
2135 body_fld_desc = NULL; 2135 body_fld_desc = NULL;
2136 body_fld_enc = NULL; 2136 body_fld_enc = NULL;
2137 body_fld_octets = 0; 2137 body_fld_octets = 0;
2138 2138
2139 cur_token = * index; 2139 cur_token = * index;
2140 2140
2141 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param, 2141 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param,
2142 progr_rate, progr_fun); 2142 progr_rate, progr_fun);
2143 if (r != MAILIMAP_NO_ERROR) { 2143 if (r != MAILIMAP_NO_ERROR) {
2144 res = r; 2144 res = r;
2145 goto err; 2145 goto err;
2146 } 2146 }
2147 2147
2148 r = mailimap_space_parse(fd, buffer, &cur_token); 2148 r = mailimap_space_parse(fd, buffer, &cur_token);
2149 if (r != MAILIMAP_NO_ERROR) { 2149 if (r != MAILIMAP_NO_ERROR) {
2150 res = r; 2150 res = r;
2151 goto fld_param_free; 2151 goto fld_param_free;
2152 } 2152 }
2153 2153
2154 r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id, 2154 r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id,
2155 progr_rate, progr_fun); 2155 progr_rate, progr_fun);
2156 if (r != MAILIMAP_NO_ERROR) { 2156 if (r != MAILIMAP_NO_ERROR) {
2157 res = r; 2157 res = r;
2158 goto fld_param_free; 2158 goto fld_param_free;
2159 } 2159 }
2160 2160
2161 r = mailimap_space_parse(fd, buffer, &cur_token); 2161 r = mailimap_space_parse(fd, buffer, &cur_token);
2162 if (r != MAILIMAP_NO_ERROR) { 2162 if (r != MAILIMAP_NO_ERROR) {
2163 res = r; 2163 res = r;
2164 goto fld_id_free; 2164 goto fld_id_free;
2165 } 2165 }
2166 2166
2167 r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc, 2167 r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc,
2168 progr_rate, progr_fun); 2168 progr_rate, progr_fun);
2169 if (r != MAILIMAP_NO_ERROR) { 2169 if (r != MAILIMAP_NO_ERROR) {
2170 res = r; 2170 res = r;
2171 goto fld_id_free; 2171 goto fld_id_free;
2172 } 2172 }
2173 2173
2174 r = mailimap_space_parse(fd, buffer, &cur_token); 2174 r = mailimap_space_parse(fd, buffer, &cur_token);
2175 if (r != MAILIMAP_NO_ERROR) { 2175 if (r != MAILIMAP_NO_ERROR) {
2176 res = r; 2176 res = r;
2177 goto fld_desc_free; 2177 goto fld_desc_free;
2178 } 2178 }
2179 2179
2180 r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc, 2180 r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc,
2181 progr_rate, progr_fun); 2181 progr_rate, progr_fun);
2182 if (r != MAILIMAP_NO_ERROR) { 2182 if (r != MAILIMAP_NO_ERROR) {
2183 res = r; 2183 res = r;
2184 goto fld_desc_free; 2184 goto fld_desc_free;
2185 } 2185 }
2186 2186
2187 r = mailimap_space_parse(fd, buffer, &cur_token); 2187 r = mailimap_space_parse(fd, buffer, &cur_token);
2188 if (r != MAILIMAP_NO_ERROR) { 2188 if (r != MAILIMAP_NO_ERROR) {
2189 res = r; 2189 res = r;
2190 goto fld_enc_free; 2190 goto fld_enc_free;
2191 } 2191 }
2192 2192
2193 r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token, 2193 r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token,
2194 &body_fld_octets); 2194 &body_fld_octets);
2195 if (r != MAILIMAP_NO_ERROR) { 2195 if (r != MAILIMAP_NO_ERROR) {
2196 res = r; 2196 res = r;
2197 goto fld_enc_free; 2197 goto fld_enc_free;
2198 } 2198 }
2199 2199
2200 body_fields = mailimap_body_fields_new(body_fld_param, 2200 body_fields = mailimap_body_fields_new(body_fld_param,
2201 body_fld_id, 2201 body_fld_id,
2202 body_fld_desc, 2202 body_fld_desc,
2203 body_fld_enc, 2203 body_fld_enc,
2204 body_fld_octets); 2204 body_fld_octets);
2205 if (body_fields == NULL) { 2205 if (body_fields == NULL) {
2206 res = MAILIMAP_ERROR_MEMORY; 2206 res = MAILIMAP_ERROR_MEMORY;
2207 goto fld_enc_free; 2207 goto fld_enc_free;
2208 } 2208 }
2209 2209
2210 * result = body_fields; 2210 * result = body_fields;
2211 * index = cur_token; 2211 * index = cur_token;
2212 2212
2213 return MAILIMAP_NO_ERROR; 2213 return MAILIMAP_NO_ERROR;
2214 2214
2215 fld_enc_free: 2215 fld_enc_free:
2216 mailimap_body_fld_enc_free(body_fld_enc); 2216 mailimap_body_fld_enc_free(body_fld_enc);
2217 fld_desc_free: 2217 fld_desc_free:
2218 mailimap_body_fld_desc_free(body_fld_desc); 2218 mailimap_body_fld_desc_free(body_fld_desc);
2219 fld_id_free: 2219 fld_id_free:
2220 mailimap_body_fld_id_free(body_fld_id); 2220 mailimap_body_fld_id_free(body_fld_id);
2221 fld_param_free: 2221 fld_param_free:
2222 if (body_fld_param != NULL) 2222 if (body_fld_param != NULL)
2223 mailimap_body_fld_param_free(body_fld_param); 2223 mailimap_body_fld_param_free(body_fld_param);
2224 err: 2224 err:
2225 return res; 2225 return res;
2226} 2226}
2227 2227
2228/* 2228/*
2229 body-fld-desc = nstring 2229 body-fld-desc = nstring
2230*/ 2230*/
2231 2231
2232static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, 2232static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer,
2233 size_t * index, char ** result, 2233 size_t * index, char ** result,
2234 size_t progr_rate, 2234 size_t progr_rate,
2235 progress_function * progr_fun) 2235 progress_function * progr_fun)
2236{ 2236{
2237 return mailimap_nstring_parse(fd, buffer, index, result, NULL, 2237 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2238 progr_rate, progr_fun); 2238 progr_rate, progr_fun);
2239} 2239}
2240 2240
2241/* 2241/*
2242 body-fld-dsp = "(" string SP body-fld-param ")" / nil 2242 body-fld-dsp = "(" string SP body-fld-param ")" / nil
2243*/ 2243*/
2244 2244
2245static int 2245static int
2246mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, 2246mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer,
2247 size_t * index, 2247 size_t * index,
2248 struct mailimap_body_fld_dsp ** result, 2248 struct mailimap_body_fld_dsp ** result,
2249 size_t progr_rate, 2249 size_t progr_rate,
2250 progress_function * progr_fun) 2250 progress_function * progr_fun)
2251{ 2251{
2252 size_t cur_token; 2252 size_t cur_token;
2253 char * name; 2253 char * name;
2254 struct mailimap_body_fld_param * body_fld_param; 2254 struct mailimap_body_fld_param * body_fld_param;
2255 struct mailimap_body_fld_dsp * body_fld_dsp; 2255 struct mailimap_body_fld_dsp * body_fld_dsp;
2256 int res; 2256 int res;
2257 int r; 2257 int r;
2258 2258
2259 cur_token = * index; 2259 cur_token = * index;
2260 name = NULL; 2260 name = NULL;
2261 body_fld_param = NULL; 2261 body_fld_param = NULL;
2262 2262
2263 r = mailimap_nil_parse(fd, buffer, &cur_token); 2263 r = mailimap_nil_parse(fd, buffer, &cur_token);
2264 if (r == MAILIMAP_NO_ERROR) { 2264 if (r == MAILIMAP_NO_ERROR) {
2265 * result = NULL; 2265 * result = NULL;
2266 * index = cur_token; 2266 * index = cur_token;
2267 return MAILIMAP_NO_ERROR; 2267 return MAILIMAP_NO_ERROR;
2268 } 2268 }
2269 2269
2270 if (r != MAILIMAP_ERROR_PARSE) { 2270 if (r != MAILIMAP_ERROR_PARSE) {
2271 res = r; 2271 res = r;
2272 goto err; 2272 goto err;
2273 } 2273 }
2274 2274
2275 r = mailimap_oparenth_parse(fd, buffer, &cur_token); 2275 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2276 if (r != MAILIMAP_NO_ERROR) { 2276 if (r != MAILIMAP_NO_ERROR) {
2277 res = r; 2277 res = r;
2278 goto err; 2278 goto err;
2279 } 2279 }
2280 2280
2281 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, 2281 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL,
2282 progr_rate, progr_fun); 2282 progr_rate, progr_fun);
2283 if (r != MAILIMAP_NO_ERROR) { 2283 if (r != MAILIMAP_NO_ERROR) {
2284 res = r; 2284 res = r;
2285 goto err; 2285 goto err;
2286 } 2286 }
2287 2287
2288 r = mailimap_space_parse(fd, buffer, &cur_token); 2288 r = mailimap_space_parse(fd, buffer, &cur_token);
2289 if (r != MAILIMAP_NO_ERROR) { 2289 if (r != MAILIMAP_NO_ERROR) {
2290 res = r; 2290 res = r;
2291 goto string_free; 2291 goto string_free;
2292 } 2292 }
2293 2293
2294 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, 2294 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token,
2295 &body_fld_param, 2295 &body_fld_param,
2296 progr_rate, progr_fun); 2296 progr_rate, progr_fun);
2297 if (r != MAILIMAP_NO_ERROR) { 2297 if (r != MAILIMAP_NO_ERROR) {
2298 res = r; 2298 res = r;
2299 goto string_free; 2299 goto string_free;
2300 } 2300 }
2301 2301
2302 r = mailimap_cparenth_parse(fd, buffer, &cur_token); 2302 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2303 if (r != MAILIMAP_NO_ERROR) { 2303 if (r != MAILIMAP_NO_ERROR) {
2304 res = r; 2304 res = r;
2305 goto string_free; 2305 goto string_free;
2306 } 2306 }
2307 2307
2308 body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param); 2308 body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param);
2309 if (body_fld_dsp == NULL) { 2309 if (body_fld_dsp == NULL) {
2310 res = MAILIMAP_ERROR_MEMORY; 2310 res = MAILIMAP_ERROR_MEMORY;
2311 goto fld_param_free; 2311 goto fld_param_free;
2312 } 2312 }
2313 2313
2314 * index = cur_token; 2314 * index = cur_token;
2315 * result = body_fld_dsp; 2315 * result = body_fld_dsp;
2316 2316
2317 return MAILIMAP_NO_ERROR; 2317 return MAILIMAP_NO_ERROR;
2318 2318
2319 fld_param_free: 2319 fld_param_free:
2320 if (body_fld_param != NULL) 2320 if (body_fld_param != NULL)
2321 mailimap_body_fld_param_free(body_fld_param); 2321 mailimap_body_fld_param_free(body_fld_param);
2322 string_free: 2322 string_free:
2323 mailimap_string_free(name); 2323 mailimap_string_free(name);
2324 err: 2324 err:
2325 return res; 2325 return res;
2326} 2326}
2327 2327
2328/* 2328/*
2329 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ 2329 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
2330 "QUOTED-PRINTABLE") DQUOTE) / string 2330 "QUOTED-PRINTABLE") DQUOTE) / string
2331*/ 2331*/
2332 2332
2333static inline int 2333static inline int
2334mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer, 2334mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer,
2335 size_t * index, 2335 size_t * index,
2336 int * result, 2336 int * result,
2337 size_t progr_rate, 2337 size_t progr_rate,
2338 progress_function * progr_fun) 2338 progress_function * progr_fun)
2339{ 2339{
2340 size_t cur_token; 2340 size_t cur_token;
2341 int type; 2341 int type;
2342 int r; 2342 int r;
2343 int res; 2343 int res;
2344 2344
2345 cur_token = * index; 2345 cur_token = * index;
2346 2346
2347 r = mailimap_dquote_parse(fd, buffer, &cur_token); 2347 r = mailimap_dquote_parse(fd, buffer, &cur_token);
2348 if (r != MAILIMAP_NO_ERROR) { 2348 if (r != MAILIMAP_NO_ERROR) {
2349 res = r; 2349 res = r;
2350 goto err; 2350 goto err;
2351 } 2351 }
2352 2352
2353 type = mailimap_encoding_get_token_value(fd, buffer, &cur_token); 2353 type = mailimap_encoding_get_token_value(fd, buffer, &cur_token);
2354 2354
2355 if (type == -1) { 2355 if (type == -1) {
2356 res = MAILIMAP_ERROR_PARSE; 2356 res = MAILIMAP_ERROR_PARSE;
2357 goto err; 2357 goto err;
2358 } 2358 }
2359 2359
2360 r = mailimap_dquote_parse(fd, buffer, &cur_token); 2360 r = mailimap_dquote_parse(fd, buffer, &cur_token);
2361 if (r != MAILIMAP_NO_ERROR) { 2361 if (r != MAILIMAP_NO_ERROR) {
2362 res = r; 2362 res = r;
2363 goto err; 2363 goto err;
2364 } 2364 }
2365 2365
2366 * result = type; 2366 * result = type;
2367 * index = cur_token; 2367 * index = cur_token;
2368 2368
2369 return MAILIMAP_NO_ERROR; 2369 return MAILIMAP_NO_ERROR;
2370 2370
2371 err: 2371 err:
2372 return res; 2372 return res;
2373} 2373}
2374 2374
2375static int 2375static int
2376mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, 2376mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer,
2377 size_t * index, 2377 size_t * index,
2378 struct mailimap_body_fld_enc ** result, 2378 struct mailimap_body_fld_enc ** result,
2379 size_t progr_rate, 2379 size_t progr_rate,
2380 progress_function * progr_fun) 2380 progress_function * progr_fun)
2381{ 2381{
2382 size_t cur_token; 2382 size_t cur_token;
2383 int type; 2383 int type;
2384 char * value; 2384 char * value;
2385 struct mailimap_body_fld_enc * body_fld_enc; 2385 struct mailimap_body_fld_enc * body_fld_enc;
2386 int r; 2386 int r;
2387 int res; 2387 int res;
2388 2388
2389 cur_token = * index; 2389 cur_token = * index;
2390 2390
2391 r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token, 2391 r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token,
2392 &type, progr_rate, progr_fun); 2392 &type, progr_rate, progr_fun);
2393 if (r == MAILIMAP_NO_ERROR) { 2393 if (r == MAILIMAP_NO_ERROR) {
2394 value = NULL; 2394 value = NULL;
2395 } 2395 }
2396 else if (r == MAILIMAP_ERROR_PARSE) { 2396 else if (r == MAILIMAP_ERROR_PARSE) {
2397 type = MAILIMAP_BODY_FLD_ENC_OTHER; 2397 type = MAILIMAP_BODY_FLD_ENC_OTHER;
2398 2398
2399 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, 2399 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL,
2400 progr_rate, progr_fun); 2400 progr_rate, progr_fun);
2401 if (r != MAILIMAP_NO_ERROR) { 2401 if (r != MAILIMAP_NO_ERROR) {
2402 res = r; 2402 // LR start
2403 goto err; 2403 // accept NIL and set type to utf8
2404 int ret = r;
2405 r = mailimap_char_parse(fd, buffer, &cur_token, 'N');
2406 if (r == MAILIMAP_NO_ERROR) {
2407 r = mailimap_char_parse(fd, buffer, &cur_token, 'I');
2408 if (r == MAILIMAP_NO_ERROR) {
2409 r = mailimap_char_parse(fd, buffer, &cur_token, 'L');
2410 if (r == MAILIMAP_NO_ERROR) {
2411 type = 4;
2412 ret = MAILIMAP_NO_ERROR;
2413 value = NULL;
2414 }
2415 }
2416 }
2417 if ( ret != MAILIMAP_NO_ERROR ) {
2418 res = ret;
2419 goto err;
2420 }
2421 // LR end
2404 } 2422 }
2405 } 2423 }
2406 else { 2424 else {
2407 res = r; 2425 res = r;
2408 goto err; 2426 goto err;
2409 } 2427 }
2410 2428
2411 body_fld_enc = mailimap_body_fld_enc_new(type, value); 2429 body_fld_enc = mailimap_body_fld_enc_new(type, value);
2412 if (body_fld_enc == NULL) { 2430 if (body_fld_enc == NULL) {
2413 res = MAILIMAP_ERROR_MEMORY; 2431 res = MAILIMAP_ERROR_MEMORY;
2414 goto value_free; 2432 goto value_free;
2415 } 2433 }
2416 2434
2417 * result = body_fld_enc; 2435 * result = body_fld_enc;
2418 * index = cur_token; 2436 * index = cur_token;
2419 2437
2420 return MAILIMAP_NO_ERROR; 2438 return MAILIMAP_NO_ERROR;
2421 2439
2422 value_free: 2440 value_free:
2423 if (value) 2441 if (value)
2424 mailimap_string_free(value); 2442 mailimap_string_free(value);
2425 err: 2443 err:
2426 return res; 2444 return res;
2427} 2445}
2428 2446
2429/* 2447/*
2430 body-fld-id = nstring 2448 body-fld-id = nstring
2431*/ 2449*/
2432 2450
2433static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, 2451static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer,
2434 size_t * index, char ** result, 2452 size_t * index, char ** result,
2435 size_t progr_rate, 2453 size_t progr_rate,
2436 progress_function * progr_fun) 2454 progress_function * progr_fun)
2437{ 2455{
2438 return mailimap_nstring_parse(fd, buffer, index, result, NULL, 2456 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2439 progr_rate, progr_fun); 2457 progr_rate, progr_fun);
2440} 2458}
2441 2459
2442 2460
2443/* 2461/*
2444 body-fld-lang = nstring / "(" string *(SP string) ")" 2462 body-fld-lang = nstring / "(" string *(SP string) ")"
2445*/ 2463*/
2446 2464
2447/* 2465/*
2448"(" string *(SP string) ")" 2466"(" string *(SP string) ")"
2449*/ 2467*/
2450 2468
2451static int 2469static int
2452mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer, 2470mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer,
2453 size_t * index, clist ** result, 2471 size_t * index, clist ** result,
2454 size_t progr_rate, 2472 size_t progr_rate,
2455 progress_function * progr_fun) 2473 progress_function * progr_fun)
2456{ 2474{
2457 size_t cur_token; 2475 size_t cur_token;
2458 clist * list; 2476 clist * list;
2459 int r; 2477 int r;
2460 int res; 2478 int res;
2461 2479
2462 cur_token = * index; 2480 cur_token = * index;
2463 2481
2464 r = mailimap_oparenth_parse(fd, buffer, &cur_token); 2482 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2465 if (r != MAILIMAP_NO_ERROR) { 2483 if (r != MAILIMAP_NO_ERROR) {
2466 res = r; 2484 res = r;
2467 goto err; 2485 goto err;
2468 } 2486 }
2469 2487
2470 list = clist_new(); 2488 list = clist_new();
2471 if (list == NULL) { 2489 if (list == NULL) {
2472 res = MAILIMAP_ERROR_MEMORY; 2490 res = MAILIMAP_ERROR_MEMORY;
2473 goto err; 2491 goto err;
2474 } 2492 }
2475 2493
2476 while (1) { 2494 while (1) {
2477 char * elt; 2495 char * elt;
2478 2496
2479 r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL, 2497 r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL,
2480 progr_rate, progr_fun); 2498 progr_rate, progr_fun);
2481 if (r != MAILIMAP_ERROR_PARSE) 2499 if (r != MAILIMAP_ERROR_PARSE)
2482 break; 2500 break;
2483 else if (r == MAILIMAP_NO_ERROR) { 2501 else if (r == MAILIMAP_NO_ERROR) {
2484 r = clist_append(list, elt); 2502 r = clist_append(list, elt);
2485 if (r < 0) { 2503 if (r < 0) {
2486 mailimap_string_free(elt); 2504 mailimap_string_free(elt);
2487 res = r; 2505 res = r;
2488 goto list_free; 2506 goto list_free;
2489 } 2507 }
2490 } 2508 }
2491 else { 2509 else {
2492 res = r; 2510 res = r;
2493 goto list_free; 2511 goto list_free;
2494 } 2512 }
2495 } 2513 }
2496 2514
2497 r = mailimap_cparenth_parse(fd, buffer, &cur_token); 2515 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2498 if (r != MAILIMAP_NO_ERROR) { 2516 if (r != MAILIMAP_NO_ERROR) {
2499 res = r; 2517 res = r;
2500 goto list_free; 2518 goto list_free;
2501 } 2519 }
2502 2520
2503 * index = cur_token; 2521 * index = cur_token;
2504 * result = list; 2522 * result = list;
2505 2523
2506 return MAILIMAP_NO_ERROR; 2524 return MAILIMAP_NO_ERROR;
2507 2525
2508 list_free: 2526 list_free:
2509 clist_foreach(list, (clist_func) mailimap_string_free, NULL); 2527 clist_foreach(list, (clist_func) mailimap_string_free, NULL);
2510 clist_free(list); 2528 clist_free(list);
2511 err: 2529 err:
2512 return res; 2530 return res;
2513} 2531}
2514 2532
2515/* 2533/*
2516 body-fld-lang = nstring / "(" string *(SP string) ")" 2534 body-fld-lang = nstring / "(" string *(SP string) ")"
2517*/ 2535*/
2518 2536
2519static int 2537static int
2520mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, 2538mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer,
2521 size_t * index, 2539 size_t * index,
2522 struct mailimap_body_fld_lang ** result, 2540 struct mailimap_body_fld_lang ** result,
2523 size_t progr_rate, 2541 size_t progr_rate,
2524 progress_function * progr_fun) 2542 progress_function * progr_fun)
2525{ 2543{
2526 char * value; 2544 char * value;
2527 clist * list; 2545 clist * list;
2528 struct mailimap_body_fld_lang * fld_lang; 2546 struct mailimap_body_fld_lang * fld_lang;
2529 int type; 2547 int type;
2530 int r; 2548 int r;
2531 int res; 2549 int res;
2532 2550
2533 size_t cur_token; 2551 size_t cur_token;
2534 2552
2535 cur_token = * index; 2553 cur_token = * index;
2536 2554
2537 value = NULL; 2555 value = NULL;
2538 list = NULL; 2556 list = NULL;
2539 type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */ 2557 type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */
2540 2558
2541 r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL, 2559 r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL,
2542 progr_rate, progr_fun); 2560 progr_rate, progr_fun);
2543 if (r == MAILIMAP_NO_ERROR) 2561 if (r == MAILIMAP_NO_ERROR)
2544 type = MAILIMAP_BODY_FLD_LANG_SINGLE; 2562 type = MAILIMAP_BODY_FLD_LANG_SINGLE;
2545 2563
2546 if (r == MAILIMAP_ERROR_PARSE) { 2564 if (r == MAILIMAP_ERROR_PARSE) {
2547 r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list, 2565 r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list,
2548 progr_rate, progr_fun); 2566 progr_rate, progr_fun);
2549 if (r == MAILIMAP_NO_ERROR) 2567 if (r == MAILIMAP_NO_ERROR)
2550 type = MAILIMAP_BODY_FLD_LANG_LIST; 2568 type = MAILIMAP_BODY_FLD_LANG_LIST;
2551 } 2569 }
2552 2570
2553 if (r != MAILIMAP_NO_ERROR) { 2571 if (r != MAILIMAP_NO_ERROR) {
2554 res = r; 2572 res = r;
2555 goto err; 2573 goto err;
2556 } 2574 }
2557 2575
2558 fld_lang = mailimap_body_fld_lang_new(type, value, list); 2576 fld_lang = mailimap_body_fld_lang_new(type, value, list);
2559 if (fld_lang == NULL) { 2577 if (fld_lang == NULL) {
2560 res = MAILIMAP_ERROR_MEMORY; 2578 res = MAILIMAP_ERROR_MEMORY;
2561 goto free; 2579 goto free;
2562 } 2580 }
2563 2581
2564 * index = cur_token; 2582 * index = cur_token;
2565 * result = fld_lang; 2583 * result = fld_lang;
2566 2584
2567 return MAILIMAP_NO_ERROR; 2585 return MAILIMAP_NO_ERROR;
2568 2586
2569 free: 2587 free:
2570 if (value) 2588 if (value)
2571 mailimap_nstring_free(value); 2589 mailimap_nstring_free(value);
2572 if (list) { 2590 if (list) {
2573 clist_foreach(list, (clist_func) mailimap_string_free, NULL); 2591 clist_foreach(list, (clist_func) mailimap_string_free, NULL);
2574 clist_free(list); 2592 clist_free(list);
2575 } 2593 }
2576 err: 2594 err:
2577 return res; 2595 return res;
2578} 2596}
2579 2597
2580/* 2598/*
2581 body-fld-lines = number 2599 body-fld-lines = number
2582*/ 2600*/
2583 2601
2584static int mailimap_body_fld_lines_parse(mailstream * fd, 2602static int mailimap_body_fld_lines_parse(mailstream * fd,
2585 MMAPString * buffer, size_t * index, 2603 MMAPString * buffer, size_t * index,
2586 uint32_t * result) 2604 uint32_t * result)
2587{ 2605{
2588 return mailimap_number_parse(fd, buffer, index, result); 2606 return mailimap_number_parse(fd, buffer, index, result);
2589} 2607}
2590 2608
2591/* 2609/*
2592 body-fld-md5 = nstring 2610 body-fld-md5 = nstring
2593*/ 2611*/
2594 2612
2595static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, 2613static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer,
2596 size_t * index, char ** result, 2614 size_t * index, char ** result,
2597 size_t progr_rate, 2615 size_t progr_rate,
2598 progress_function * progr_fun) 2616 progress_function * progr_fun)
2599{ 2617{
2600 return mailimap_nstring_parse(fd, buffer, index, result, NULL, 2618 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2601 progr_rate, progr_fun); 2619 progr_rate, progr_fun);
2602} 2620}
2603 2621
2604/* 2622/*
2605 body-fld-octets = number 2623 body-fld-octets = number
2606*/ 2624*/
2607 2625
2608static int mailimap_body_fld_octets_parse(mailstream * fd, 2626static int mailimap_body_fld_octets_parse(mailstream * fd,
2609 MMAPString * buffer, size_t * index, 2627 MMAPString * buffer, size_t * index,
2610 uint32_t * result) 2628 uint32_t * result)
2611{ 2629{
2612 return mailimap_number_parse(fd, buffer, index, result); 2630 return mailimap_number_parse(fd, buffer, index, result);
2613} 2631}
2614 2632
2615/* 2633/*
2616 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil 2634 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
2617*/ 2635*/
2618 2636
2619/* 2637/*
2620 string SP string 2638 string SP string
2621*/ 2639*/
2622 2640
2623static int 2641static int
2624mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer, 2642mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer,
2625 size_t * index, 2643 size_t * index,
2626 struct mailimap_single_body_fld_param ** 2644 struct mailimap_single_body_fld_param **
2627 result, 2645 result,
2628 size_t progr_rate, 2646 size_t progr_rate,
2629 progress_function * progr_fun) 2647 progress_function * progr_fun)
2630{ 2648{
2631 struct mailimap_single_body_fld_param * param; 2649 struct mailimap_single_body_fld_param * param;
2632 char * name; 2650 char * name;
2633 char * value; 2651 char * value;
2634 size_t cur_token; 2652 size_t cur_token;
2635 int r; 2653 int r;
2636 int res; 2654 int res;
2637 2655
2638 cur_token = * index; 2656 cur_token = * index;
2639 2657
2640 name = NULL; 2658 name = NULL;
2641 value = NULL; 2659 value = NULL;
2642 2660
2643 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, 2661 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL,
2644 progr_rate, progr_fun); 2662 progr_rate, progr_fun);
2645 if (r != MAILIMAP_NO_ERROR) { 2663 if (r != MAILIMAP_NO_ERROR) {
2646 res = r; 2664 res = r;
2647 goto err; 2665 goto err;
2648 } 2666 }
2649 2667
2650 r = mailimap_space_parse(fd, buffer, &cur_token); 2668 r = mailimap_space_parse(fd, buffer, &cur_token);
2651 if (r != MAILIMAP_NO_ERROR) { 2669 if (r != MAILIMAP_NO_ERROR) {
2652 res = r; 2670 res = r;
2653 goto free_name; 2671 goto free_name;
2654 } 2672 }
2655 2673
2656 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, 2674 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL,
2657 progr_rate, progr_fun); 2675 progr_rate, progr_fun);
2658 if (r != MAILIMAP_NO_ERROR) { 2676 if (r != MAILIMAP_NO_ERROR) {
2659 res = r; 2677 res = r;
2660 goto free_name; 2678 goto free_name;
2661 } 2679 }
2662 2680
2663 param = mailimap_single_body_fld_param_new(name, value); 2681 param = mailimap_single_body_fld_param_new(name, value);
2664 if (param == NULL) { 2682 if (param == NULL) {
2665 res = MAILIMAP_ERROR_MEMORY; 2683 res = MAILIMAP_ERROR_MEMORY;
2666 goto free_value; 2684 goto free_value;
2667 } 2685 }
2668 2686
2669 * result = param; 2687 * result = param;
2670 * index = cur_token; 2688 * index = cur_token;
2671 2689
2672 return MAILIMAP_NO_ERROR; 2690 return MAILIMAP_NO_ERROR;
2673 2691
2674 free_value: 2692 free_value:
2675 mailimap_string_free(name); 2693 mailimap_string_free(name);
2676 free_name: 2694 free_name:
2677 mailimap_string_free(value); 2695 mailimap_string_free(value);
2678 err: 2696 err:
2679 return res; 2697 return res;
2680} 2698}
2681 2699
2682/* 2700/*
2683 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil 2701 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
2684*/ 2702*/
2685 2703
2686static int 2704static int
2687mailimap_body_fld_param_parse(mailstream * fd, 2705mailimap_body_fld_param_parse(mailstream * fd,
2688 MMAPString * buffer, size_t * index, 2706 MMAPString * buffer, size_t * index,
2689 struct mailimap_body_fld_param ** result, 2707 struct mailimap_body_fld_param ** result,
2690 size_t progr_rate, 2708 size_t progr_rate,
2691 progress_function * progr_fun) 2709 progress_function * progr_fun)
2692{ 2710{
2693 size_t cur_token; 2711 size_t cur_token;
2694 clist * param_list; 2712 clist * param_list;
2695 struct mailimap_body_fld_param * fld_param; 2713 struct mailimap_body_fld_param * fld_param;
2696 int r; 2714 int r;
2697 int res; 2715 int res;
2698 2716
2699 param_list = NULL; 2717 param_list = NULL;
2700 cur_token = * index; 2718 cur_token = * index;
2701 2719
2702 r = mailimap_nil_parse(fd, buffer, &cur_token); 2720 r = mailimap_nil_parse(fd, buffer, &cur_token);
2703 if (r == MAILIMAP_NO_ERROR) { 2721 if (r == MAILIMAP_NO_ERROR) {
2704 * result = NULL; 2722 * result = NULL;
2705 * index = cur_token; 2723 * index = cur_token;
2706 return MAILIMAP_NO_ERROR; 2724 return MAILIMAP_NO_ERROR;
2707 } 2725 }
2708 2726
2709 if (r != MAILIMAP_ERROR_PARSE) { 2727 if (r != MAILIMAP_ERROR_PARSE) {
2710 res = r; 2728 res = r;
2711 goto err; 2729 goto err;
2712 } 2730 }
2713 2731
2714 r = mailimap_oparenth_parse(fd, buffer, &cur_token); 2732 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2715 if (r != MAILIMAP_NO_ERROR) { 2733 if (r != MAILIMAP_NO_ERROR) {
2716 res = r; 2734 res = r;
2717 goto err; 2735 goto err;
2718 } 2736 }
2719 2737
2720 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &param_list, 2738 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &param_list,
2721 (mailimap_struct_parser *) 2739 (mailimap_struct_parser *)
2722 mailimap_single_body_fld_param_parse, 2740 mailimap_single_body_fld_param_parse,
2723 (mailimap_struct_destructor *) 2741 (mailimap_struct_destructor *)
2724 mailimap_single_body_fld_param_free, 2742 mailimap_single_body_fld_param_free,
2725 progr_rate, progr_fun); 2743 progr_rate, progr_fun);
2726 if (r != MAILIMAP_NO_ERROR) { 2744 if (r != MAILIMAP_NO_ERROR) {
2727 res = r; 2745 res = r;
2728 goto err; 2746 goto err;
2729 } 2747 }
2730 2748
2731 r = mailimap_cparenth_parse(fd, buffer, &cur_token); 2749 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2732 if (r != MAILIMAP_NO_ERROR) { 2750 if (r != MAILIMAP_NO_ERROR) {
2733 res = r; 2751 res = r;
2734 goto free; 2752 goto free;
2735 } 2753 }
2736 2754
2737 fld_param = mailimap_body_fld_param_new(param_list); 2755 fld_param = mailimap_body_fld_param_new(param_list);
2738 if (fld_param == NULL) { 2756 if (fld_param == NULL) {
2739 res = MAILIMAP_ERROR_MEMORY; 2757 res = MAILIMAP_ERROR_MEMORY;
2740 goto free; 2758 goto free;
2741 } 2759 }
2742 2760
2743 * index = cur_token; 2761 * index = cur_token;
2744 * result = fld_param; 2762 * result = fld_param;
2745 2763
2746 return MAILIMAP_NO_ERROR; 2764 return MAILIMAP_NO_ERROR;
2747 2765
2748 free: 2766 free:
2749 clist_foreach(param_list, 2767 clist_foreach(param_list,
2750 (clist_func) mailimap_single_body_fld_param_free, 2768 (clist_func) mailimap_single_body_fld_param_free,
2751 NULL); 2769 NULL);
2752 clist_free(param_list); 2770 clist_free(param_list);
2753 err: 2771 err:
2754 return res; 2772 return res;
2755} 2773}
2756 2774
2757/* 2775/*
2758 body-type-1part = (body-type-basic / body-type-msg / body-type-text) 2776 body-type-1part = (body-type-basic / body-type-msg / body-type-text)
2759 [SP body-ext-1part] 2777 [SP body-ext-1part]
2760*/ 2778*/
2761 2779
2762static int 2780static int
2763mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, 2781mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer,
2764 size_t * index, 2782 size_t * index,
2765 struct mailimap_body_type_1part ** result, 2783 struct mailimap_body_type_1part ** result,
2766 size_t progr_rate, 2784 size_t progr_rate,
2767 progress_function * progr_fun) 2785 progress_function * progr_fun)
2768{ 2786{
2769 size_t cur_token; 2787 size_t cur_token;
2770 struct mailimap_body_type_1part * body_type_1part; 2788 struct mailimap_body_type_1part * body_type_1part;
2771 struct mailimap_body_type_basic * body_type_basic; 2789 struct mailimap_body_type_basic * body_type_basic;
2772 struct mailimap_body_type_msg * body_type_msg; 2790 struct mailimap_body_type_msg * body_type_msg;
2773 struct mailimap_body_type_text * body_type_text; 2791 struct mailimap_body_type_text * body_type_text;
2774 struct mailimap_body_ext_1part * body_ext_1part; 2792 struct mailimap_body_ext_1part * body_ext_1part;
2775 int type; 2793 int type;
2776 size_t final_token; 2794 size_t final_token;
2777 int r; 2795 int r;
2778 int res; 2796 int res;
2779 2797
2780 cur_token = * index; 2798 cur_token = * index;
2781 2799
2782 body_type_basic = NULL; 2800 body_type_basic = NULL;
2783 body_type_msg = NULL; 2801 body_type_msg = NULL;
2784 body_type_text = NULL; 2802 body_type_text = NULL;
2785 body_ext_1part = NULL; 2803 body_ext_1part = NULL;
2786 2804
2787 type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */ 2805 type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */
2788 2806
2789 r = mailimap_body_type_msg_parse(fd, buffer, &cur_token, 2807 r = mailimap_body_type_msg_parse(fd, buffer, &cur_token,
2790 &body_type_msg, 2808 &body_type_msg,
2791 progr_rate, progr_fun); 2809 progr_rate, progr_fun);
2792 if (r == MAILIMAP_NO_ERROR) 2810 if (r == MAILIMAP_NO_ERROR)
2793 type = MAILIMAP_BODY_TYPE_1PART_MSG; 2811 type = MAILIMAP_BODY_TYPE_1PART_MSG;
2794 2812
2795 if (r == MAILIMAP_ERROR_PARSE) { 2813 if (r == MAILIMAP_ERROR_PARSE) {
2796 r = mailimap_body_type_text_parse(fd, buffer, &cur_token, 2814 r = mailimap_body_type_text_parse(fd, buffer, &cur_token,
2797 &body_type_text, 2815 &body_type_text,
2798 progr_rate, progr_fun); 2816 progr_rate, progr_fun);
2799 if (r == MAILIMAP_NO_ERROR) 2817 if (r == MAILIMAP_NO_ERROR)
2800 type = MAILIMAP_BODY_TYPE_1PART_TEXT; 2818 type = MAILIMAP_BODY_TYPE_1PART_TEXT;
2801 } 2819 }
2802 2820
2803 if (r == MAILIMAP_ERROR_PARSE) { 2821 if (r == MAILIMAP_ERROR_PARSE) {
2804 r = mailimap_body_type_basic_parse(fd, buffer, &cur_token, 2822 r = mailimap_body_type_basic_parse(fd, buffer, &cur_token,
2805 &body_type_basic, 2823 &body_type_basic,
2806 progr_rate, progr_fun); 2824 progr_rate, progr_fun);
2807 if (r == MAILIMAP_NO_ERROR) 2825 if (r == MAILIMAP_NO_ERROR)
2808 type = MAILIMAP_BODY_TYPE_1PART_BASIC; 2826 type = MAILIMAP_BODY_TYPE_1PART_BASIC;
2809 } 2827 }
2810 2828
2811 if (r != MAILIMAP_NO_ERROR) { 2829 if (r != MAILIMAP_NO_ERROR) {
2812 res = r; 2830 res = r;
2813 goto err; 2831 goto err;
2814 } 2832 }
2815 2833
2816 final_token = cur_token; 2834 final_token = cur_token;
2817 body_ext_1part = NULL; 2835 body_ext_1part = NULL;
2818 2836
2819 r = mailimap_space_parse(fd, buffer, &cur_token); 2837 r = mailimap_space_parse(fd, buffer, &cur_token);
2820 2838
2821 if (r == MAILIMAP_NO_ERROR) { 2839 if (r == MAILIMAP_NO_ERROR) {
2822 r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part, 2840 r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part,
2823 progr_rate, progr_fun); 2841 progr_rate, progr_fun);
2824 if (r == MAILIMAP_NO_ERROR) 2842 if (r == MAILIMAP_NO_ERROR)
2825 final_token = cur_token; 2843 final_token = cur_token;
2826 else if (r == MAILIMAP_ERROR_PARSE) { 2844 else if (r == MAILIMAP_ERROR_PARSE) {
2827 /* do nothing */ 2845 /* do nothing */
2828 } 2846 }
2829 else { 2847 else {
2830 res = r; 2848 res = r;
2831 goto free; 2849 goto free;
2832 } 2850 }
2833 } 2851 }
2834 else if (r == MAILIMAP_ERROR_PARSE) { 2852 else if (r == MAILIMAP_ERROR_PARSE) {
2835 /* do nothing */ 2853 /* do nothing */
2836 } 2854 }
2837 else { 2855 else {
2838 res = r; 2856 res = r;
2839 goto free; 2857 goto free;
2840 } 2858 }
2841 2859
2842 body_type_1part = mailimap_body_type_1part_new(type, body_type_basic, 2860 body_type_1part = mailimap_body_type_1part_new(type, body_type_basic,
2843 body_type_msg, body_type_text, 2861 body_type_msg, body_type_text,
2844 body_ext_1part); 2862 body_ext_1part);
2845 if (body_type_1part == NULL) { 2863 if (body_type_1part == NULL) {
2846 res = MAILIMAP_ERROR_MEMORY; 2864 res = MAILIMAP_ERROR_MEMORY;
2847 goto free; 2865 goto free;
2848 } 2866 }
2849 2867
2850 * index = final_token; 2868 * index = final_token;
2851 * result = body_type_1part; 2869 * result = body_type_1part;
2852 2870
2853 return MAILIMAP_NO_ERROR; 2871 return MAILIMAP_NO_ERROR;
2854 2872
2855 free: 2873 free:
2856 if (body_type_basic) 2874 if (body_type_basic)
2857 mailimap_body_type_basic_free(body_type_basic); 2875 mailimap_body_type_basic_free(body_type_basic);
2858 if (body_type_msg) 2876 if (body_type_msg)
2859 mailimap_body_type_msg_free(body_type_msg); 2877 mailimap_body_type_msg_free(body_type_msg);
2860 if (body_type_text) 2878 if (body_type_text)
2861 mailimap_body_type_text_free(body_type_text); 2879 mailimap_body_type_text_free(body_type_text);
2862 if (body_ext_1part) 2880 if (body_ext_1part)
2863 mailimap_body_ext_1part_free(body_ext_1part); 2881 mailimap_body_ext_1part_free(body_ext_1part);
2864 err: 2882 err:
2865 return res; 2883 return res;
2866} 2884}
2867 2885
2868/* 2886/*
2869 body-type-basic = media-basic SP body-fields 2887 body-type-basic = media-basic SP body-fields
2870 ; MESSAGE subtype MUST NOT be "RFC822" 2888 ; MESSAGE subtype MUST NOT be "RFC822"
2871*/ 2889*/
2872 2890
2873static int 2891static int
2874mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, 2892mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer,
2875 size_t * index, 2893 size_t * index,
2876 struct mailimap_body_type_basic ** result, 2894 struct mailimap_body_type_basic ** result,
2877 size_t progr_rate, 2895 size_t progr_rate,
2878 progress_function * progr_fun) 2896 progress_function * progr_fun)
2879{ 2897{
2880 size_t cur_token; 2898 size_t cur_token;
2881 struct mailimap_body_type_basic * body_type_basic; 2899 struct mailimap_body_type_basic * body_type_basic;
2882 struct mailimap_media_basic * media_basic; 2900 struct mailimap_media_basic * media_basic;
2883 struct mailimap_body_fields * body_fields; 2901 struct mailimap_body_fields * body_fields;
2884 int r; 2902 int r;
2885 int res; 2903 int res;
2886 2904
2887 cur_token = * index; 2905 cur_token = * index;
2888 2906
2889 media_basic = NULL; 2907 media_basic = NULL;
2890 body_fields = NULL; 2908 body_fields = NULL;
2891 2909
2892 r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic, 2910 r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic,
2893 progr_rate, progr_fun); 2911 progr_rate, progr_fun);
2894 if (r != MAILIMAP_NO_ERROR) { 2912 if (r != MAILIMAP_NO_ERROR) {
2895 res = r; 2913 res = r;
2896 goto err; 2914 goto err;
2897 } 2915 }
2898 2916
2899 r = mailimap_space_parse(fd, buffer, &cur_token); 2917 r = mailimap_space_parse(fd, buffer, &cur_token);
2900 if (r != MAILIMAP_NO_ERROR) { 2918 if (r != MAILIMAP_NO_ERROR) {
2901 res = r; 2919 res = r;
2902 goto free_media_basic; 2920 goto free_media_basic;
2903 } 2921 }
2904 2922
2905 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, 2923 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
2906 progr_rate, progr_fun); 2924 progr_rate, progr_fun);
2907 if (r != MAILIMAP_NO_ERROR) { 2925 if (r != MAILIMAP_NO_ERROR) {
2908 res = r; 2926 res = r;
2909 goto free_media_basic; 2927 goto free_media_basic;
2910 } 2928 }
2911 2929
2912 body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields); 2930 body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields);
2913 if (body_type_basic == NULL) { 2931 if (body_type_basic == NULL) {
2914 res = MAILIMAP_ERROR_MEMORY; 2932 res = MAILIMAP_ERROR_MEMORY;
2915 goto free_body_fields; 2933 goto free_body_fields;
2916 } 2934 }
2917 2935
2918 * index = cur_token; 2936 * index = cur_token;
2919 * result = body_type_basic; 2937 * result = body_type_basic;
2920 2938
2921 return MAILIMAP_NO_ERROR; 2939 return MAILIMAP_NO_ERROR;
2922 2940
2923 free_body_fields: 2941 free_body_fields:
2924 mailimap_body_fields_free(body_fields); 2942 mailimap_body_fields_free(body_fields);
2925 free_media_basic: 2943 free_media_basic:
2926 mailimap_media_basic_free(media_basic); 2944 mailimap_media_basic_free(media_basic);
2927 err: 2945 err:
2928 return res; 2946 return res;
2929} 2947}
2930 2948
2931/* 2949/*
2932 body-type-mpart = 1*body SP media-subtype 2950 body-type-mpart = 1*body SP media-subtype
2933 [SP body-ext-mpart] 2951 [SP body-ext-mpart]
2934*/ 2952*/
2935 2953
2936static int 2954static int
2937mailimap_body_type_mpart_parse(mailstream * fd, 2955mailimap_body_type_mpart_parse(mailstream * fd,
2938 MMAPString * buffer, 2956 MMAPString * buffer,
2939 size_t * index, 2957 size_t * index,
2940 struct mailimap_body_type_mpart ** result, 2958 struct mailimap_body_type_mpart ** result,
2941 size_t progr_rate, 2959 size_t progr_rate,
2942 progress_function * progr_fun) 2960 progress_function * progr_fun)
2943{ 2961{
2944 struct mailimap_body_type_mpart * body_type_mpart; 2962 struct mailimap_body_type_mpart * body_type_mpart;
2945 clist * body_list; 2963 clist * body_list;
2946 size_t cur_token; 2964 size_t cur_token;
2947 size_t final_token; 2965 size_t final_token;
2948 char * media_subtype; 2966 char * media_subtype;
2949 struct mailimap_body_ext_mpart * body_ext_mpart; 2967 struct mailimap_body_ext_mpart * body_ext_mpart;
2950 int r; 2968 int r;
2951 int res; 2969 int res;
2952 2970
2953 cur_token = * index; 2971 cur_token = * index;
2954 2972
2955 body_list = NULL; 2973 body_list = NULL;
2956 media_subtype = NULL; 2974 media_subtype = NULL;
2957 body_ext_mpart = NULL; 2975 body_ext_mpart = NULL;
2958 2976
2959 r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, 2977 r = mailimap_struct_multiple_parse(fd, buffer, &cur_token,
2960 &body_list, 2978 &body_list,
2961 (mailimap_struct_parser *) 2979 (mailimap_struct_parser *)
2962 mailimap_body_parse, 2980 mailimap_body_parse,
2963 (mailimap_struct_destructor *) 2981 (mailimap_struct_destructor *)
2964 mailimap_body_free, 2982 mailimap_body_free,
2965 progr_rate, progr_fun); 2983 progr_rate, progr_fun);
2966 if (r != MAILIMAP_NO_ERROR) { 2984 if (r != MAILIMAP_NO_ERROR) {
2967 res = r; 2985 res = r;
2968 goto err; 2986 goto err;
2969 } 2987 }
2970 2988
2971 r = mailimap_space_parse(fd, buffer, &cur_token); 2989 r = mailimap_space_parse(fd, buffer, &cur_token);
2972 if (r != MAILIMAP_NO_ERROR) { 2990 if (r != MAILIMAP_NO_ERROR) {
2973 res = r; 2991 res = r;
2974 goto free_body_list; 2992 goto free_body_list;
2975 } 2993 }
2976 2994
2977 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, 2995 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype,
2978 progr_rate, progr_fun); 2996 progr_rate, progr_fun);
2979 if (r != MAILIMAP_NO_ERROR) { 2997 if (r != MAILIMAP_NO_ERROR) {
2980 res = r; 2998 res = r;
2981 goto free_body_list; 2999 goto free_body_list;
2982 } 3000 }
2983 3001
2984 final_token = cur_token; 3002 final_token = cur_token;
2985 3003
2986 body_ext_mpart = NULL; 3004 body_ext_mpart = NULL;
2987 3005
2988 r = mailimap_space_parse(fd, buffer, &cur_token); 3006 r = mailimap_space_parse(fd, buffer, &cur_token);
2989 if (r == MAILIMAP_NO_ERROR) { 3007 if (r == MAILIMAP_NO_ERROR) {
2990 r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart, 3008 r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart,
2991 progr_rate, progr_fun); 3009 progr_rate, progr_fun);
2992 if (r == MAILIMAP_NO_ERROR) 3010 if (r == MAILIMAP_NO_ERROR)
2993 final_token = cur_token; 3011 final_token = cur_token;
2994 else if (r == MAILIMAP_ERROR_PARSE) { 3012 else if (r == MAILIMAP_ERROR_PARSE) {
2995 /* do nothing */ 3013 /* do nothing */
2996 } 3014 }
2997 else { 3015 else {
2998 res = r; 3016 res = r;
2999 goto free_body_list; 3017 goto free_body_list;
3000 } 3018 }
3001 } 3019 }
3002 else if (r == MAILIMAP_ERROR_PARSE) { 3020 else if (r == MAILIMAP_ERROR_PARSE) {
3003 /* do nothing */ 3021 /* do nothing */
3004 } 3022 }
3005 else { 3023 else {
3006 res = r; 3024 res = r;
3007 goto free_body_list; 3025 goto free_body_list;
3008 } 3026 }
3009 3027
3010 body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype, 3028 body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype,
3011 body_ext_mpart); 3029 body_ext_mpart);
3012 if (body_type_mpart == NULL) { 3030 if (body_type_mpart == NULL) {
3013 res = MAILIMAP_ERROR_MEMORY; 3031 res = MAILIMAP_ERROR_MEMORY;
3014 goto free_body_ext_mpart; 3032 goto free_body_ext_mpart;
3015 } 3033 }
3016 3034
3017 * result = body_type_mpart; 3035 * result = body_type_mpart;
3018 * index = final_token; 3036 * index = final_token;
3019 3037
3020 return MAILIMAP_NO_ERROR; 3038 return MAILIMAP_NO_ERROR;
3021 3039
3022 free_body_ext_mpart: 3040 free_body_ext_mpart:
3023 if (body_ext_mpart) 3041 if (body_ext_mpart)
3024 mailimap_body_ext_mpart_free(body_ext_mpart); 3042 mailimap_body_ext_mpart_free(body_ext_mpart);
3025 mailimap_media_subtype_free(media_subtype); 3043 mailimap_media_subtype_free(media_subtype);
3026 free_body_list: 3044 free_body_list:
3027 clist_foreach(body_list, (clist_func) mailimap_body_free, NULL); 3045 clist_foreach(body_list, (clist_func) mailimap_body_free, NULL);
3028 clist_free(body_list); 3046 clist_free(body_list);
3029 err: 3047 err:
3030 return res; 3048 return res;
3031} 3049}
3032 3050
3033/* 3051/*
3034 body-type-msg = media-message SP body-fields SP envelope 3052 body-type-msg = media-message SP body-fields SP envelope
3035 SP body SP body-fld-lines 3053 SP body SP body-fld-lines
3036*/ 3054*/
3037 3055
3038static int 3056static int
3039mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, 3057mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer,
3040 size_t * index, 3058 size_t * index,
3041 struct mailimap_body_type_msg ** result, 3059 struct mailimap_body_type_msg ** result,
3042 size_t progr_rate, 3060 size_t progr_rate,
3043 progress_function * progr_fun) 3061 progress_function * progr_fun)
3044{ 3062{
3045 struct mailimap_body_fields * body_fields; 3063 struct mailimap_body_fields * body_fields;
3046 struct mailimap_envelope * envelope; 3064 struct mailimap_envelope * envelope;
3047 struct mailimap_body * body; 3065 struct mailimap_body * body;
3048 uint32_t body_fld_lines; 3066 uint32_t body_fld_lines;
3049 struct mailimap_body_type_msg * body_type_msg; 3067 struct mailimap_body_type_msg * body_type_msg;
3050 size_t cur_token; 3068 size_t cur_token;
3051 int r; 3069 int r;
3052 int res; 3070 int res;
3053 3071
3054 cur_token = * index; 3072 cur_token = * index;
3055 3073
3056 body_fields = NULL; 3074 body_fields = NULL;
3057 envelope = NULL; 3075 envelope = NULL;
3058 body = NULL; 3076 body = NULL;
3059 body_fld_lines = 0; 3077 body_fld_lines = 0;
3060 3078
3061 r = mailimap_media_message_parse(fd, buffer, &cur_token); 3079 r = mailimap_media_message_parse(fd, buffer, &cur_token);
3062 if (r != MAILIMAP_NO_ERROR) { 3080 if (r != MAILIMAP_NO_ERROR) {
3063 res = r; 3081 res = r;
3064 goto err; 3082 goto err;
3065 } 3083 }
3066 3084
3067 r = mailimap_space_parse(fd, buffer, &cur_token); 3085 r = mailimap_space_parse(fd, buffer, &cur_token);
3068 if (r != MAILIMAP_NO_ERROR) { 3086 if (r != MAILIMAP_NO_ERROR) {
3069 res = r; 3087 res = r;
3070 goto err; 3088 goto err;
3071 } 3089 }
3072 3090
3073 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, 3091 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
3074 progr_rate, progr_fun); 3092 progr_rate, progr_fun);
3075 if (r != MAILIMAP_NO_ERROR) { 3093 if (r != MAILIMAP_NO_ERROR) {
3076 res = r; 3094 res = r;
3077 goto err; 3095 goto err;
3078 } 3096 }
3079 3097
3080 r = mailimap_space_parse(fd, buffer, &cur_token); 3098 r = mailimap_space_parse(fd, buffer, &cur_token);
3081 if (r != MAILIMAP_NO_ERROR) { 3099 if (r != MAILIMAP_NO_ERROR) {
3082 res = r; 3100 res = r;
3083 goto body_fields; 3101 goto body_fields;
3084 } 3102 }
3085 3103
3086 r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope, 3104 r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope,
3087 progr_rate, progr_fun); 3105 progr_rate, progr_fun);
3088 if (r != MAILIMAP_NO_ERROR) { 3106 if (r != MAILIMAP_NO_ERROR) {
3089 res = r; 3107 res = r;
3090 goto body_fields; 3108 goto body_fields;
3091 } 3109 }
3092 3110
3093 r = mailimap_space_parse(fd, buffer, &cur_token); 3111 r = mailimap_space_parse(fd, buffer, &cur_token);
3094 if (r != MAILIMAP_NO_ERROR) { 3112 if (r != MAILIMAP_NO_ERROR) {
3095 res = r; 3113 res = r;
3096 goto envelope; 3114 goto envelope;
3097 } 3115 }
3098 3116
3099 r = mailimap_body_parse(fd, buffer, &cur_token, &body, 3117 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
3100 progr_rate, progr_fun); 3118 progr_rate, progr_fun);
3101 if (r != MAILIMAP_NO_ERROR) { 3119 if (r != MAILIMAP_NO_ERROR) {
3102 res = r; 3120 res = r;
3103 goto envelope; 3121 goto envelope;
3104 } 3122 }
3105 3123
3106 r = mailimap_space_parse(fd, buffer, &cur_token); 3124 r = mailimap_space_parse(fd, buffer, &cur_token);
3107 if (r != MAILIMAP_NO_ERROR) { 3125 if (r != MAILIMAP_NO_ERROR) {
3108 res = r; 3126 res = r;
3109 goto body; 3127 goto body;
3110 } 3128 }
3111 3129
3112 r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, 3130 r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token,
3113 &body_fld_lines); 3131 &body_fld_lines);
3114 if (r != MAILIMAP_NO_ERROR) { 3132 if (r != MAILIMAP_NO_ERROR) {
3115 res = r; 3133 res = r;
3116 goto body; 3134 goto body;
3117 } 3135 }
3118 3136
3119 body_type_msg = mailimap_body_type_msg_new(body_fields, envelope, 3137 body_type_msg = mailimap_body_type_msg_new(body_fields, envelope,
3120 body, body_fld_lines); 3138 body, body_fld_lines);
3121 if (body_type_msg == NULL) { 3139 if (body_type_msg == NULL) {
3122 res = MAILIMAP_ERROR_MEMORY; 3140 res = MAILIMAP_ERROR_MEMORY;
3123 goto body; 3141 goto body;
3124 } 3142 }
3125 3143
3126 * result = body_type_msg; 3144 * result = body_type_msg;
3127 * index = cur_token; 3145 * index = cur_token;
3128 3146
3129 return MAILIMAP_NO_ERROR; 3147 return MAILIMAP_NO_ERROR;
3130 3148
3131 body: 3149 body:
3132 mailimap_body_free(body); 3150 mailimap_body_free(body);
3133 envelope: 3151 envelope:
3134 mailimap_envelope_free(envelope); 3152 mailimap_envelope_free(envelope);
3135 body_fields: 3153 body_fields:
3136 mailimap_body_fields_free(body_fields); 3154 mailimap_body_fields_free(body_fields);
3137 err: 3155 err:
3138 return res; 3156 return res;
3139} 3157}
3140 3158
3141/* 3159/*
3142 body-type-text = media-text SP body-fields SP body-fld-lines 3160 body-type-text = media-text SP body-fields SP body-fld-lines
3143*/ 3161*/
3144 3162
3145static int 3163static int
3146mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, 3164mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer,
3147 size_t * index, 3165 size_t * index,
3148 struct mailimap_body_type_text ** 3166 struct mailimap_body_type_text **
3149 result, 3167 result,
3150 size_t progr_rate, 3168 size_t progr_rate,
3151 progress_function * progr_fun) 3169 progress_function * progr_fun)
3152{ 3170{
3153 char * media_text; 3171 char * media_text;
3154 struct mailimap_body_fields * body_fields; 3172 struct mailimap_body_fields * body_fields;
3155 uint32_t body_fld_lines; 3173 uint32_t body_fld_lines;
3156 struct mailimap_body_type_text * body_type_text; 3174 struct mailimap_body_type_text * body_type_text;
3157 size_t cur_token; 3175 size_t cur_token;
3158 int r; 3176 int r;
3159 int res; 3177 int res;
3160 3178
3161 media_text = NULL; 3179 media_text = NULL;
3162 body_fields = NULL; 3180 body_fields = NULL;
3163 body_fld_lines = 0; 3181 body_fld_lines = 0;
3164 3182
3165 cur_token = * index; 3183 cur_token = * index;
3166 3184
3167 r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text, 3185 r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text,
3168 progr_rate, progr_fun); 3186 progr_rate, progr_fun);
3169 if (r != MAILIMAP_NO_ERROR) { 3187 if (r != MAILIMAP_NO_ERROR) {
3170 res = r; 3188 res = r;
3171 goto err; 3189 goto err;
diff --git a/libetpan/src/low-level/maildir/maildir.c b/libetpan/src/low-level/maildir/maildir.c
index 98b9f87..e81625d 100644
--- a/libetpan/src/low-level/maildir/maildir.c
+++ b/libetpan/src/low-level/maildir/maildir.c
@@ -1,798 +1,811 @@
1/* 1/*
2 * libEtPan! -- a mail stuff library 2 * libEtPan! -- a mail stuff library
3 * 3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa 4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its 15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived 16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * $Id$ 33 * $Id$
34 */ 34 */
35 35
36#include "maildir.h" 36#include "maildir.h"
37 37
38#include <string.h> 38#include <string.h>
39#include <stdlib.h> 39#include <stdlib.h>
40#include <stdio.h> 40#include <stdio.h>
41#include <unistd.h> 41#include <unistd.h>
42#include <sys/types.h> 42#include <sys/types.h>
43#include <dirent.h> 43#include <dirent.h>
44#include <time.h> 44#include <time.h>
45#include <sys/stat.h> 45#include <sys/stat.h>
46#include <sys/mman.h> 46#include <sys/mman.h>
47#include <errno.h> 47#include <errno.h>
48#include <fcntl.h> 48#include <fcntl.h>
49 49
50#ifdef LIBETPAN_SYSTEM_BASENAME 50#ifdef LIBETPAN_SYSTEM_BASENAME
51#include <libgen.h> 51#include <libgen.h>
52#endif 52#endif
53 53
54/* 54/*
55 We suppose the maildir mailbox remains on one unique filesystem. 55 We suppose the maildir mailbox remains on one unique filesystem.
56*/ 56*/
57 57
58struct maildir * maildir_new(const char * path) 58struct maildir * maildir_new(const char * path)
59{ 59{
60 struct maildir * md; 60 struct maildir * md;
61 61
62 md = malloc(sizeof(* md)); 62 md = malloc(sizeof(* md));
63 if (md == NULL) 63 if (md == NULL)
64 goto err; 64 goto err;
65 65
66 md->mdir_counter = 0; 66 md->mdir_counter = 0;
67 md->mdir_mtime_new = (time_t) -1; 67 md->mdir_mtime_new = (time_t) -1;
68 md->mdir_mtime_cur = (time_t) -1; 68 md->mdir_mtime_cur = (time_t) -1;
69 69
70 md->mdir_pid = getpid(); 70 md->mdir_pid = getpid();
71 gethostname(md->mdir_hostname, sizeof(md->mdir_hostname)); 71 gethostname(md->mdir_hostname, sizeof(md->mdir_hostname));
72 strncpy(md->mdir_path, path, sizeof(md->mdir_path)); 72 strncpy(md->mdir_path, path, sizeof(md->mdir_path));
73 md->mdir_path[PATH_MAX - 1] = '\0'; 73 md->mdir_path[PATH_MAX - 1] = '\0';
74 74
75 md->mdir_msg_list = carray_new(128); 75 md->mdir_msg_list = carray_new(128);
76 if (md->mdir_msg_list == NULL) 76 if (md->mdir_msg_list == NULL)
77 goto free; 77 goto free;
78 78
79 md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); 79 md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE);
80 if (md->mdir_msg_hash == NULL) 80 if (md->mdir_msg_hash == NULL)
81 goto free_msg_list; 81 goto free_msg_list;
82 82
83 return md; 83 return md;
84 84
85 free_msg_list: 85 free_msg_list:
86 carray_free(md->mdir_msg_list); 86 carray_free(md->mdir_msg_list);
87 free: 87 free:
88 free(md); 88 free(md);
89 err: 89 err:
90 return NULL; 90 return NULL;
91} 91}
92 92
93static void maildir_flush(struct maildir * md, int msg_new); 93static void maildir_flush(struct maildir * md, int msg_new);
94 94
95void maildir_free(struct maildir * md) 95void maildir_free(struct maildir * md)
96{ 96{
97 maildir_flush(md, 0); 97 maildir_flush(md, 0);
98 maildir_flush(md, 1); 98 maildir_flush(md, 1);
99 chash_free(md->mdir_msg_hash); 99 chash_free(md->mdir_msg_hash);
100 carray_free(md->mdir_msg_list); 100 carray_free(md->mdir_msg_list);
101 free(md); 101 free(md);
102} 102}
103 103
104#define MAX_TRY_ALLOC 32 104#define MAX_TRY_ALLOC 32
105 105
106static char * maildir_get_new_message_filename(struct maildir * md, 106static char * maildir_get_new_message_filename(struct maildir * md,
107 char * tmpfile) 107 char * tmpfile)
108{ 108{
109 char filename[PATH_MAX]; 109 char filename[PATH_MAX];
110 char basename[PATH_MAX]; 110 char basename[PATH_MAX];
111 int k; 111 int k;
112 time_t now; 112 time_t now;
113 //LR
114 struct stat f_stat;
113 int got_file; 115 int got_file;
114 int r; 116 int r;
115 117
116 got_file = 0; 118 got_file = 0;
117 now = time(NULL); 119 now = time(NULL);
118 k = 0; 120 k = 0;
119 while (k < MAX_TRY_ALLOC) { 121 while (k < MAX_TRY_ALLOC) {
120 snprintf(basename, sizeof(basename), "%lu.%u_%u.%s", 122 snprintf(basename, sizeof(basename), "%lu.%u_%u.%s",
121 (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname); 123 (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname);
122 snprintf(filename, sizeof(filename), "%s/tmp/%s", 124 snprintf(filename, sizeof(filename), "%s/tmp/%s",
123 md->mdir_path, basename); 125 md->mdir_path, basename);
124 126
127 // LR changed following lines
128 if ( stat( filename, &f_stat ) == -1 ) {
129 char * dup_filename;
130
131 dup_filename = strdup(filename);
132 if (dup_filename == NULL) {
133 //unlink(filename);
134 return NULL;
135 }
136 rename (tmpfile,dup_filename );
137#if 0
125 if (link(tmpfile, filename) == 0) { 138 if (link(tmpfile, filename) == 0) {
126 got_file = 1; 139 got_file = 1;
127 unlink(tmpfile); 140 unlink(tmpfile);
128 } 141 }
129 else if (errno == EXDEV) { 142 else if (errno == EXDEV) {
130 unlink(tmpfile); 143 unlink(tmpfile);
131 return NULL; 144 return NULL;
132 } 145 }
133 else if (errno == EPERM) { 146 else if (errno == EPERM) {
134 r = rename(tmpfile, filename); 147 r = rename(tmpfile, filename);
135 if (r < 0) { 148 if (r < 0) {
136 unlink(tmpfile); 149 unlink(tmpfile);
137 return NULL; 150 return NULL;
138 } 151 }
139 got_file = 1; 152 got_file = 1;
140 } 153 }
141 154
142 if (got_file) { 155 if (got_file) {
143 char * dup_filename; 156 char * dup_filename;
144 157
145 dup_filename = strdup(filename); 158 dup_filename = strdup(filename);
146 if (dup_filename == NULL) { 159 if (dup_filename == NULL) {
147 unlink(filename); 160 unlink(filename);
148 return NULL; 161 return NULL;
149 } 162 }
150 163#endif
151 md->mdir_counter ++; 164 md->mdir_counter ++;
152 165
153 return dup_filename; 166 return dup_filename;
154 } 167 }
155 168
156 md->mdir_counter ++; 169 md->mdir_counter ++;
157 k ++; 170 k ++;
158 } 171 }
159 172
160 return NULL; 173 return NULL;
161} 174}
162 175
163 176
164static void msg_free(struct maildir_msg * msg) 177static void msg_free(struct maildir_msg * msg)
165{ 178{
166 free(msg->msg_uid); 179 free(msg->msg_uid);
167 free(msg->msg_filename); 180 free(msg->msg_filename);
168 free(msg); 181 free(msg);
169} 182}
170 183
171/* 184/*
172 msg_new() 185 msg_new()
173 186
174 filename is given without path 187 filename is given without path
175*/ 188*/
176 189
177static struct maildir_msg * msg_new(char * filename, int new_msg) 190static struct maildir_msg * msg_new(char * filename, int new_msg)
178{ 191{
179 struct maildir_msg * msg; 192 struct maildir_msg * msg;
180 char * p; 193 char * p;
181 int flags; 194 int flags;
182 size_t uid_len; 195 size_t uid_len;
183 char * begin_uid; 196 char * begin_uid;
184 197
185 /* name of file : xxx-xxx_xxx-xxx:2,SRFT */ 198 /* name of file : xxx-xxx_xxx-xxx:2,SRFT */
186 199
187 msg = malloc(sizeof(* msg)); 200 msg = malloc(sizeof(* msg));
188 if (msg == NULL) 201 if (msg == NULL)
189 goto err; 202 goto err;
190 203
191 msg->msg_filename = strdup(filename); 204 msg->msg_filename = strdup(filename);
192 if (msg->msg_filename == NULL) 205 if (msg->msg_filename == NULL)
193 goto free; 206 goto free;
194 207
195 begin_uid = filename; 208 begin_uid = filename;
196 209
197 uid_len = strlen(begin_uid); 210 uid_len = strlen(begin_uid);
198 211
199 flags = 0; 212 flags = 0;
200 p = strstr(filename, ":2,"); 213 p = strstr(filename, ":2,");
201 if (p != NULL) { 214 if (p != NULL) {
202 uid_len = p - begin_uid; 215 uid_len = p - begin_uid;
203 216
204 p += 3; 217 p += 3;
205 218
206 /* parse flags */ 219 /* parse flags */
207 while (* p != '\0') { 220 while (* p != '\0') {
208 switch (* p) { 221 switch (* p) {
209 case 'S': 222 case 'S':
210 flags |= MAILDIR_FLAG_SEEN; 223 flags |= MAILDIR_FLAG_SEEN;
211 break; 224 break;
212 case 'R': 225 case 'R':
213 flags |= MAILDIR_FLAG_REPLIED; 226 flags |= MAILDIR_FLAG_REPLIED;
214 break; 227 break;
215 case 'F': 228 case 'F':
216 flags |= MAILDIR_FLAG_FLAGGED; 229 flags |= MAILDIR_FLAG_FLAGGED;
217 break; 230 break;
218 case 'T': 231 case 'T':
219 flags |= MAILDIR_FLAG_TRASHED; 232 flags |= MAILDIR_FLAG_TRASHED;
220 break; 233 break;
221 } 234 }
222 p ++; 235 p ++;
223 } 236 }
224 } 237 }
225 238
226 if (new_msg) 239 if (new_msg)
227 flags |= MAILDIR_FLAG_NEW; 240 flags |= MAILDIR_FLAG_NEW;
228 241
229 msg->msg_flags = flags; 242 msg->msg_flags = flags;
230 243
231 msg->msg_uid = malloc(uid_len + 1); 244 msg->msg_uid = malloc(uid_len + 1);
232 if (msg->msg_uid == NULL) 245 if (msg->msg_uid == NULL)
233 goto free_filename; 246 goto free_filename;
234 247
235 strncpy(msg->msg_uid, begin_uid, uid_len); 248 strncpy(msg->msg_uid, begin_uid, uid_len);
236 msg->msg_uid[uid_len] = '\0'; 249 msg->msg_uid[uid_len] = '\0';
237 250
238 return msg; 251 return msg;
239 252
240 free_filename: 253 free_filename:
241 free(msg->msg_filename); 254 free(msg->msg_filename);
242 free: 255 free:
243 free(msg); 256 free(msg);
244 err: 257 err:
245 return NULL; 258 return NULL;
246} 259}
247 260
248static void maildir_flush(struct maildir * md, int msg_new) 261static void maildir_flush(struct maildir * md, int msg_new)
249{ 262{
250 unsigned int i; 263 unsigned int i;
251 264
252 i = 0; 265 i = 0;
253 while (i < carray_count(md->mdir_msg_list)) { 266 while (i < carray_count(md->mdir_msg_list)) {
254 struct maildir_msg * msg; 267 struct maildir_msg * msg;
255 int delete; 268 int delete;
256 269
257 msg = carray_get(md->mdir_msg_list, i); 270 msg = carray_get(md->mdir_msg_list, i);
258 271
259 if (msg_new) { 272 if (msg_new) {
260 delete = 0; 273 delete = 0;
261 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 274 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
262 delete = 1; 275 delete = 1;
263 } 276 }
264 else { 277 else {
265 delete = 1; 278 delete = 1;
266 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 279 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
267 delete = 0; 280 delete = 0;
268 } 281 }
269 282
270 if (delete) { 283 if (delete) {
271 chashdatum key; 284 chashdatum key;
272 285
273 key.data = msg->msg_uid; 286 key.data = msg->msg_uid;
274 key.len = strlen(msg->msg_uid); 287 key.len = strlen(msg->msg_uid);
275 chash_delete(md->mdir_msg_hash, &key, NULL); 288 chash_delete(md->mdir_msg_hash, &key, NULL);
276 289
277 carray_delete(md->mdir_msg_list, i); 290 carray_delete(md->mdir_msg_list, i);
278 msg_free(msg); 291 msg_free(msg);
279 } 292 }
280 else { 293 else {
281 i ++; 294 i ++;
282 } 295 }
283 } 296 }
284} 297}
285 298
286static int add_message(struct maildir * md, 299static int add_message(struct maildir * md,
287 char * filename, int is_new) 300 char * filename, int is_new)
288{ 301{
289 struct maildir_msg * msg; 302 struct maildir_msg * msg;
290 chashdatum key; 303 chashdatum key;
291 chashdatum value; 304 chashdatum value;
292 unsigned int i; 305 unsigned int i;
293 int res; 306 int res;
294 int r; 307 int r;
295 308
296 msg = msg_new(filename, is_new); 309 msg = msg_new(filename, is_new);
297 if (msg == NULL) { 310 if (msg == NULL) {
298 res = MAILDIR_ERROR_MEMORY; 311 res = MAILDIR_ERROR_MEMORY;
299 goto err; 312 goto err;
300 } 313 }
301 314
302 r = carray_add(md->mdir_msg_list, msg, &i); 315 r = carray_add(md->mdir_msg_list, msg, &i);
303 if (r < 0) { 316 if (r < 0) {
304 res = MAILDIR_ERROR_MEMORY; 317 res = MAILDIR_ERROR_MEMORY;
305 goto free_msg; 318 goto free_msg;
306 } 319 }
307 320
308 key.data = msg->msg_uid; 321 key.data = msg->msg_uid;
309 key.len = strlen(msg->msg_uid); 322 key.len = strlen(msg->msg_uid);
310 value.data = msg; 323 value.data = msg;
311 value.len = 0; 324 value.len = 0;
312 325
313 r = chash_set(md->mdir_msg_hash, &key, &value, NULL); 326 r = chash_set(md->mdir_msg_hash, &key, &value, NULL);
314 if (r < 0) { 327 if (r < 0) {
315 res = MAILDIR_ERROR_MEMORY; 328 res = MAILDIR_ERROR_MEMORY;
316 goto delete; 329 goto delete;
317 } 330 }
318 331
319 return MAILDIR_NO_ERROR; 332 return MAILDIR_NO_ERROR;
320 333
321 delete: 334 delete:
322 carray_delete(md->mdir_msg_list, i); 335 carray_delete(md->mdir_msg_list, i);
323 free_msg: 336 free_msg:
324 msg_free(msg); 337 msg_free(msg);
325 err: 338 err:
326 return res; 339 return res;
327} 340}
328 341
329static int add_directory(struct maildir * md, char * path, int is_new) 342static int add_directory(struct maildir * md, char * path, int is_new)
330{ 343{
331 DIR * d; 344 DIR * d;
332 struct dirent * entry; 345 struct dirent * entry;
333 int res; 346 int res;
334 int r; 347 int r;
335#if 0 348#if 0
336 char filename[PATH_MAX]; 349 char filename[PATH_MAX];
337#endif 350#endif
338 351
339 d = opendir(path); 352 d = opendir(path);
340 if (d == NULL) { 353 if (d == NULL) {
341 res = MAILDIR_ERROR_DIRECTORY; 354 res = MAILDIR_ERROR_DIRECTORY;
342 goto err; 355 goto err;
343 } 356 }
344 357
345 while ((entry = readdir(d)) != NULL) { 358 while ((entry = readdir(d)) != NULL) {
346#if 0 359#if 0
347 struct stat stat_info; 360 struct stat stat_info;
348 361
349 snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); 362 snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
350 363
351 r = stat(filename, &stat_info); 364 r = stat(filename, &stat_info);
352 if (r < 0) 365 if (r < 0)
353 continue; 366 continue;
354 367
355 if (S_ISDIR(stat_info.st_mode)) 368 if (S_ISDIR(stat_info.st_mode))
356 continue; 369 continue;
357#endif 370#endif
358 371
359 if (entry->d_name[0] == '.') 372 if (entry->d_name[0] == '.')
360 continue; 373 continue;
361 374
362 r = add_message(md, entry->d_name, is_new); 375 r = add_message(md, entry->d_name, is_new);
363 if (r != MAILDIR_NO_ERROR) { 376 if (r != MAILDIR_NO_ERROR) {
364 /* ignore errors */ 377 /* ignore errors */
365 } 378 }
366 } 379 }
367 380
368 closedir(d); 381 closedir(d);
369 382
370 return MAILDIR_NO_ERROR; 383 return MAILDIR_NO_ERROR;
371 384
372 err: 385 err:
373 return res; 386 return res;
374} 387}
375 388
376int maildir_update(struct maildir * md) 389int maildir_update(struct maildir * md)
377{ 390{
378 struct stat stat_info; 391 struct stat stat_info;
379 char path_new[PATH_MAX]; 392 char path_new[PATH_MAX];
380 char path_cur[PATH_MAX]; 393 char path_cur[PATH_MAX];
381 char path_maildirfolder[PATH_MAX]; 394 char path_maildirfolder[PATH_MAX];
382 int r; 395 int r;
383 int res; 396 int res;
384 int changed; 397 int changed;
385 398
386 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); 399 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path);
387 snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path); 400 snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path);
388 401
389 changed = 0; 402 changed = 0;
390 403
391 /* did new/ changed ? */ 404 /* did new/ changed ? */
392 405
393 r = stat(path_new, &stat_info); 406 r = stat(path_new, &stat_info);
394 if (r < 0) { 407 if (r < 0) {
395 res = MAILDIR_ERROR_DIRECTORY; 408 res = MAILDIR_ERROR_DIRECTORY;
396 goto free; 409 goto free;
397 } 410 }
398 411
399 if (md->mdir_mtime_new != stat_info.st_mtime) { 412 if (md->mdir_mtime_new != stat_info.st_mtime) {
400 md->mdir_mtime_new = stat_info.st_mtime; 413 md->mdir_mtime_new = stat_info.st_mtime;
401 changed = 1; 414 changed = 1;
402 } 415 }
403 416
404 /* did cur/ changed ? */ 417 /* did cur/ changed ? */
405 418
406 r = stat(path_cur, &stat_info); 419 r = stat(path_cur, &stat_info);
407 if (r < 0) { 420 if (r < 0) {
408 res = MAILDIR_ERROR_DIRECTORY; 421 res = MAILDIR_ERROR_DIRECTORY;
409 goto free; 422 goto free;
410 } 423 }
411 424
412 if (md->mdir_mtime_cur != stat_info.st_mtime) { 425 if (md->mdir_mtime_cur != stat_info.st_mtime) {
413 md->mdir_mtime_cur = stat_info.st_mtime; 426 md->mdir_mtime_cur = stat_info.st_mtime;
414 changed = 1; 427 changed = 1;
415 } 428 }
416 429
417 if (changed) { 430 if (changed) {
418 431
419 carray_set_size(md->mdir_msg_list, 0); 432 carray_set_size(md->mdir_msg_list, 0);
420 chash_clear(md->mdir_msg_hash); 433 chash_clear(md->mdir_msg_hash);
421 434
422 maildir_flush(md, 1); 435 maildir_flush(md, 1);
423 436
424 /* messages in new */ 437 /* messages in new */
425 r = add_directory(md, path_new, 1); 438 r = add_directory(md, path_new, 1);
426 if (r != MAILDIR_NO_ERROR) { 439 if (r != MAILDIR_NO_ERROR) {
427 res = r; 440 res = r;
428 goto free; 441 goto free;
429 } 442 }
430 443
431 maildir_flush(md, 0); 444 maildir_flush(md, 0);
432 445
433 /* messages in cur */ 446 /* messages in cur */
434 r = add_directory(md, path_cur, 0); 447 r = add_directory(md, path_cur, 0);
435 if (r != MAILDIR_NO_ERROR) { 448 if (r != MAILDIR_NO_ERROR) {
436 res = r; 449 res = r;
437 goto free; 450 goto free;
438 } 451 }
439 } 452 }
440 453
441 snprintf(path_maildirfolder, sizeof(path_maildirfolder), 454 snprintf(path_maildirfolder, sizeof(path_maildirfolder),
442 "%s/maildirfolder", md->mdir_path); 455 "%s/maildirfolder", md->mdir_path);
443 456
444 if (stat(path_maildirfolder, &stat_info) == -1) { 457 if (stat(path_maildirfolder, &stat_info) == -1) {
445 int fd; 458 int fd;
446 459
447 fd = creat(path_maildirfolder, S_IRUSR | S_IWUSR); 460 fd = creat(path_maildirfolder, S_IRUSR | S_IWUSR);
448 if (fd != -1) 461 if (fd != -1)
449 close(fd); 462 close(fd);
450 } 463 }
451 464
452 return MAILDIR_NO_ERROR; 465 return MAILDIR_NO_ERROR;
453 466
454 free: 467 free:
455 maildir_flush(md, 0); 468 maildir_flush(md, 0);
456 maildir_flush(md, 1); 469 maildir_flush(md, 1);
457 md->mdir_mtime_cur = (time_t) -1; 470 md->mdir_mtime_cur = (time_t) -1;
458 md->mdir_mtime_new = (time_t) -1; 471 md->mdir_mtime_new = (time_t) -1;
459 return res; 472 return res;
460} 473}
461 474
462#ifndef LIBETPAN_SYSTEM_BASENAME 475#ifndef LIBETPAN_SYSTEM_BASENAME
463static char * libetpan_basename(char * filename) 476static char * libetpan_basename(char * filename)
464{ 477{
465 char * next; 478 char * next;
466 char * p; 479 char * p;
467 480
468 p = filename; 481 p = filename;
469 next = strchr(p, '/'); 482 next = strchr(p, '/');
470 483
471 while (next != NULL) { 484 while (next != NULL) {
472 p = next; 485 p = next;
473 next = strchr(p + 1, '/'); 486 next = strchr(p + 1, '/');
474 } 487 }
475 488
476 if (p == filename) 489 if (p == filename)
477 return filename; 490 return filename;
478 else 491 else
479 return p + 1; 492 return p + 1;
480} 493}
481#else 494#else
482#define libetpan_basename(a) basename(a) 495#define libetpan_basename(a) basename(a)
483#endif 496#endif
484 497
485int maildir_message_add_uid(struct maildir * md, 498int maildir_message_add_uid(struct maildir * md,
486 const char * message, size_t size, 499 const char * message, size_t size,
487 char * uid, size_t max_uid_len) 500 char * uid, size_t max_uid_len)
488{ 501{
489 char path_new[PATH_MAX]; 502 char path_new[PATH_MAX];
490 char tmpname[PATH_MAX]; 503 char tmpname[PATH_MAX];
491 int fd; 504 int fd;
492 int r; 505 int r;
493 char * mapping; 506 char * mapping;
494 char * delivery_tmp_name; 507 char * delivery_tmp_name;
495 char * delivery_tmp_basename; 508 char * delivery_tmp_basename;
496 char delivery_new_name[PATH_MAX]; 509 char delivery_new_name[PATH_MAX];
497 char * delivery_new_basename; 510 char * delivery_new_basename;
498 int res; 511 int res;
499 struct stat stat_info; 512 struct stat stat_info;
500 513
501 r = maildir_update(md); 514 r = maildir_update(md);
502 if (r != MAILDIR_NO_ERROR) { 515 if (r != MAILDIR_NO_ERROR) {
503 res = r; 516 res = r;
504 goto err; 517 goto err;
505 } 518 }
506 519
507 /* write to tmp/ with a classic temporary file */ 520 /* write to tmp/ with a classic temporary file */
508 521
509 snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX", 522 snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX",
510 md->mdir_path); 523 md->mdir_path);
511 fd = mkstemp(tmpname); 524 fd = mkstemp(tmpname);
512 if (fd < 0) { 525 if (fd < 0) {
513 res = MAILDIR_ERROR_FILE; 526 res = MAILDIR_ERROR_FILE;
514 goto err; 527 goto err;
515 } 528 }
516 529
517 r = ftruncate(fd, size); 530 r = ftruncate(fd, size);
518 if (r < 0) { 531 if (r < 0) {
519 res = MAILDIR_ERROR_FILE; 532 res = MAILDIR_ERROR_FILE;
520 goto close; 533 goto close;
521 } 534 }
522 535
523 mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 536 mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
524 if (mapping == MAP_FAILED) { 537 if (mapping == MAP_FAILED) {
525 res = MAILDIR_ERROR_FILE; 538 res = MAILDIR_ERROR_FILE;
526 goto close; 539 goto close;
527 } 540 }
528 541
529 memcpy(mapping, message, size); 542 memcpy(mapping, message, size);
530 543
531 msync(mapping, size, MS_SYNC); 544 msync(mapping, size, MS_SYNC);
532 munmap(mapping, size); 545 munmap(mapping, size);
533 546
534 close(fd); 547 close(fd);
535 548
536 /* write to tmp/ with maildir standard name */ 549 /* write to tmp/ with maildir standard name */
537 550
538 delivery_tmp_name = maildir_get_new_message_filename(md, tmpname); 551 delivery_tmp_name = maildir_get_new_message_filename(md, tmpname);
539 if (delivery_tmp_name == NULL) { 552 if (delivery_tmp_name == NULL) {
540 res = MAILDIR_ERROR_FILE; 553 res = MAILDIR_ERROR_FILE;
541 goto unlink; 554 goto unlink;
542 } 555 }
543 556
544 /* write to new/ with maildir standard name */ 557 /* write to new/ with maildir standard name */
545 558
546 strncpy(tmpname, delivery_tmp_name, sizeof(tmpname)); 559 strncpy(tmpname, delivery_tmp_name, sizeof(tmpname));
547 tmpname[sizeof(tmpname) - 1] = '\0'; 560 tmpname[sizeof(tmpname) - 1] = '\0';
548 561
549 delivery_tmp_basename = libetpan_basename(tmpname); 562 delivery_tmp_basename = libetpan_basename(tmpname);
550 563
551 snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s", 564 snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s",
552 md->mdir_path, delivery_tmp_basename); 565 md->mdir_path, delivery_tmp_basename);
553 566
554 r = link(delivery_tmp_name, delivery_new_name); 567 r = link(delivery_tmp_name, delivery_new_name);
555 if (r == 0) { 568 if (r == 0) {
556 unlink(delivery_tmp_name); 569 unlink(delivery_tmp_name);
557 } 570 }
558 else if (errno == EXDEV) { 571 else if (errno == EXDEV) {
559 res = MAILDIR_ERROR_FOLDER; 572 res = MAILDIR_ERROR_FOLDER;
560 goto unlink_tmp; 573 goto unlink_tmp;
561 } 574 }
562 else if (errno == EPERM) { 575 else if (errno == EPERM) {
563 r = rename(delivery_tmp_name, delivery_new_name); 576 r = rename(delivery_tmp_name, delivery_new_name);
564 if (r < 0) { 577 if (r < 0) {
565 res = MAILDIR_ERROR_FILE; 578 res = MAILDIR_ERROR_FILE;
566 goto unlink_tmp; 579 goto unlink_tmp;
567 } 580 }
568 } 581 }
569 582
570 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); 583 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path);
571 r = stat(path_new, &stat_info); 584 r = stat(path_new, &stat_info);
572 if (r < 0) { 585 if (r < 0) {
573 unlink(delivery_new_name); 586 unlink(delivery_new_name);
574 res = MAILDIR_ERROR_FILE; 587 res = MAILDIR_ERROR_FILE;
575 goto unlink_tmp; 588 goto unlink_tmp;
576 } 589 }
577 590
578 md->mdir_mtime_new = stat_info.st_mtime; 591 md->mdir_mtime_new = stat_info.st_mtime;
579 592
580 delivery_new_basename = libetpan_basename(delivery_new_name); 593 delivery_new_basename = libetpan_basename(delivery_new_name);
581 594
582 r = add_message(md, delivery_new_basename, 1); 595 r = add_message(md, delivery_new_basename, 1);
583 if (r != MAILDIR_NO_ERROR) { 596 if (r != MAILDIR_NO_ERROR) {
584 unlink(delivery_new_name); 597 unlink(delivery_new_name);
585 res = MAILDIR_ERROR_FILE; 598 res = MAILDIR_ERROR_FILE;
586 goto unlink_tmp; 599 goto unlink_tmp;
587 } 600 }
588 601
589 if (uid != NULL) 602 if (uid != NULL)
590 strncpy(uid, delivery_new_basename, max_uid_len); 603 strncpy(uid, delivery_new_basename, max_uid_len);
591 604
592 free(delivery_tmp_name); 605 free(delivery_tmp_name);
593 606
594 return MAILDIR_NO_ERROR; 607 return MAILDIR_NO_ERROR;
595 608
596 unlink_tmp: 609 unlink_tmp:
597 unlink(delivery_tmp_name); 610 unlink(delivery_tmp_name);
598 free(delivery_tmp_name); 611 free(delivery_tmp_name);
599 goto err; 612 goto err;
600 close: 613 close:
601 close(fd); 614 close(fd);
602 unlink: 615 unlink:
603 unlink(tmpname); 616 unlink(tmpname);
604 err: 617 err:
605 return res; 618 return res;
606} 619}
607 620
608int maildir_message_add(struct maildir * md, 621int maildir_message_add(struct maildir * md,
609 const char * message, size_t size) 622 const char * message, size_t size)
610{ 623{
611 return maildir_message_add_uid(md, message, size, 624 return maildir_message_add_uid(md, message, size,
612 NULL, 0); 625 NULL, 0);
613} 626}
614 627
615int maildir_message_add_file_uid(struct maildir * md, int fd, 628int maildir_message_add_file_uid(struct maildir * md, int fd,
616 char * uid, size_t max_uid_len) 629 char * uid, size_t max_uid_len)
617{ 630{
618 char * message; 631 char * message;
619 struct stat buf; 632 struct stat buf;
620 int r; 633 int r;
621 634
622 if (fstat(fd, &buf) == -1) 635 if (fstat(fd, &buf) == -1)
623 return MAILDIR_ERROR_FILE; 636 return MAILDIR_ERROR_FILE;
624 637
625 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 638 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
626 if (message == MAP_FAILED) 639 if (message == MAP_FAILED)
627 return MAILDIR_ERROR_FILE; 640 return MAILDIR_ERROR_FILE;
628 641
629 r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len); 642 r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len);
630 643
631 munmap(message, buf.st_size); 644 munmap(message, buf.st_size);
632 645
633 return r; 646 return r;
634} 647}
635 648
636int maildir_message_add_file(struct maildir * md, int fd) 649int maildir_message_add_file(struct maildir * md, int fd)
637{ 650{
638 return maildir_message_add_file_uid(md, fd, 651 return maildir_message_add_file_uid(md, fd,
639 NULL, 0); 652 NULL, 0);
640} 653}
641 654
642char * maildir_message_get(struct maildir * md, const char * uid) 655char * maildir_message_get(struct maildir * md, const char * uid)
643{ 656{
644 chashdatum key; 657 chashdatum key;
645 chashdatum value; 658 chashdatum value;
646 char filename[PATH_MAX]; 659 char filename[PATH_MAX];
647 char * dup_filename; 660 char * dup_filename;
648 struct maildir_msg * msg; 661 struct maildir_msg * msg;
649 char * dir; 662 char * dir;
650 int r; 663 int r;
651 664
652 key.data = (void *) uid; 665 key.data = (void *) uid;
653 key.len = strlen(uid); 666 key.len = strlen(uid);
654 r = chash_get(md->mdir_msg_hash, &key, &value); 667 r = chash_get(md->mdir_msg_hash, &key, &value);
655 if (r < 0) 668 if (r < 0)
656 return NULL; 669 return NULL;
657 670
658 msg = value.data; 671 msg = value.data;
659 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 672 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
660 dir = "new"; 673 dir = "new";
661 else 674 else
662 dir = "cur"; 675 dir = "cur";
663 676
664 snprintf(filename, sizeof(filename), "%s/%s/%s", 677 snprintf(filename, sizeof(filename), "%s/%s/%s",
665 md->mdir_path, dir, msg->msg_filename); 678 md->mdir_path, dir, msg->msg_filename);
666 679
667 dup_filename = strdup(filename); 680 dup_filename = strdup(filename);
668 if (dup_filename == NULL) 681 if (dup_filename == NULL)
669 return NULL; 682 return NULL;
670 683
671 return dup_filename; 684 return dup_filename;
672} 685}
673 686
674int maildir_message_remove(struct maildir * md, const char * uid) 687int maildir_message_remove(struct maildir * md, const char * uid)
675{ 688{
676 chashdatum key; 689 chashdatum key;
677 chashdatum value; 690 chashdatum value;
678 char filename[PATH_MAX]; 691 char filename[PATH_MAX];
679 struct maildir_msg * msg; 692 struct maildir_msg * msg;
680 char * dir; 693 char * dir;
681 int r; 694 int r;
682 int res; 695 int res;
683 696
684 key.data = (void *) uid; 697 key.data = (void *) uid;
685 key.len = strlen(uid); 698 key.len = strlen(uid);
686 r = chash_get(md->mdir_msg_hash, &key, &value); 699 r = chash_get(md->mdir_msg_hash, &key, &value);
687 if (r < 0) { 700 if (r < 0) {
688 res = MAILDIR_ERROR_NOT_FOUND; 701 res = MAILDIR_ERROR_NOT_FOUND;
689 goto err; 702 goto err;
690 } 703 }
691 704
692 msg = value.data; 705 msg = value.data;
693 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 706 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
694 dir = "new"; 707 dir = "new";
695 else 708 else
696 dir = "cur"; 709 dir = "cur";
697 710
698 snprintf(filename, sizeof(filename), "%s/%s/%s", 711 snprintf(filename, sizeof(filename), "%s/%s/%s",
699 md->mdir_path, dir, msg->msg_filename); 712 md->mdir_path, dir, msg->msg_filename);
700 713
701 r = unlink(filename); 714 r = unlink(filename);
702 if (r < 0) { 715 if (r < 0) {
703 res = MAILDIR_ERROR_FILE; 716 res = MAILDIR_ERROR_FILE;
704 goto err; 717 goto err;
705 } 718 }
706 719
707 return MAILDIR_NO_ERROR; 720 return MAILDIR_NO_ERROR;
708 721
709 err: 722 err:
710 return res; 723 return res;
711} 724}
712 725
713int maildir_message_change_flags(struct maildir * md, 726int maildir_message_change_flags(struct maildir * md,
714 const char * uid, int new_flags) 727 const char * uid, int new_flags)
715{ 728{
716 chashdatum key; 729 chashdatum key;
717 chashdatum value; 730 chashdatum value;
718 char filename[PATH_MAX]; 731 char filename[PATH_MAX];
719 struct maildir_msg * msg; 732 struct maildir_msg * msg;
720 char * dir; 733 char * dir;
721 int r; 734 int r;
722 char new_filename[PATH_MAX]; 735 char new_filename[PATH_MAX];
723 char flag_str[5]; 736 char flag_str[5];
724 size_t i; 737 size_t i;
725 int res; 738 int res;
726 739
727 key.data = (void *) uid; 740 key.data = (void *) uid;
728 key.len = strlen(uid); 741 key.len = strlen(uid);
729 r = chash_get(md->mdir_msg_hash, &key, &value); 742 r = chash_get(md->mdir_msg_hash, &key, &value);
730 if (r < 0) { 743 if (r < 0) {
731 res = MAILDIR_ERROR_NOT_FOUND; 744 res = MAILDIR_ERROR_NOT_FOUND;
732 goto err; 745 goto err;
733 } 746 }
734 747
735 msg = value.data; 748 msg = value.data;
736 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 749 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
737 dir = "new"; 750 dir = "new";
738 else 751 else
739 dir = "cur"; 752 dir = "cur";
740 753
741 snprintf(filename, sizeof(filename), "%s/%s/%s", 754 snprintf(filename, sizeof(filename), "%s/%s/%s",
742 md->mdir_path, dir, msg->msg_filename); 755 md->mdir_path, dir, msg->msg_filename);
743 756
744 if ((new_flags & MAILDIR_FLAG_NEW) != 0) 757 if ((new_flags & MAILDIR_FLAG_NEW) != 0)
745 dir = "new"; 758 dir = "new";
746 else 759 else
747 dir = "cur"; 760 dir = "cur";
748 761
749 i = 0; 762 i = 0;
750 if ((new_flags & MAILDIR_FLAG_SEEN) != 0) { 763 if ((new_flags & MAILDIR_FLAG_SEEN) != 0) {
751 flag_str[i] = 'S'; 764 flag_str[i] = 'S';
752 i ++; 765 i ++;
753 } 766 }
754 if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) { 767 if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) {
755 flag_str[i] = 'R'; 768 flag_str[i] = 'R';
756 i ++; 769 i ++;
757 } 770 }
758 if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) { 771 if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) {
759 flag_str[i] = 'F'; 772 flag_str[i] = 'F';
760 i ++; 773 i ++;
761 } 774 }
762 if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) { 775 if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) {
763 flag_str[i] = 'T'; 776 flag_str[i] = 'T';
764 i ++; 777 i ++;
765 } 778 }
766 flag_str[i] = 0; 779 flag_str[i] = 0;
767 780
768 if (flag_str[0] == '\0') 781 if (flag_str[0] == '\0')
769 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s", 782 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s",
770 md->mdir_path, dir, msg->msg_uid); 783 md->mdir_path, dir, msg->msg_uid);
771 else 784 else
772 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s", 785 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s",
773 md->mdir_path, dir, msg->msg_uid, flag_str); 786 md->mdir_path, dir, msg->msg_uid, flag_str);
774 787
775 if (strcmp(filename, new_filename) == 0) 788 if (strcmp(filename, new_filename) == 0)
776 return MAILDIR_NO_ERROR; 789 return MAILDIR_NO_ERROR;
777 790
778 r = link(filename, new_filename); 791 r = link(filename, new_filename);
779 if (r == 0) { 792 if (r == 0) {
780 unlink(filename); 793 unlink(filename);
781 } 794 }
782 else if (errno == EXDEV) { 795 else if (errno == EXDEV) {
783 res = MAILDIR_ERROR_FOLDER; 796 res = MAILDIR_ERROR_FOLDER;
784 goto err; 797 goto err;
785 } 798 }
786 else if (errno == EPERM) { 799 else if (errno == EPERM) {
787 r = rename(filename, new_filename); 800 r = rename(filename, new_filename);
788 if (r < 0) { 801 if (r < 0) {
789 res = MAILDIR_ERROR_FOLDER; 802 res = MAILDIR_ERROR_FOLDER;
790 goto err; 803 goto err;
791 } 804 }
792 } 805 }
793 806
794 return MAILDIR_NO_ERROR; 807 return MAILDIR_NO_ERROR;
795 808
796 err: 809 err:
797 return res; 810 return res;
798} 811}
diff --git a/libetpan/src/low-level/mh/mailmh.c b/libetpan/src/low-level/mh/mailmh.c
index 42cab9d..f8c694d 100644
--- a/libetpan/src/low-level/mh/mailmh.c
+++ b/libetpan/src/low-level/mh/mailmh.c
@@ -155,835 +155,838 @@ struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent,
155 folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); 155 folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
156 if (folder->fl_msgs_hash == NULL) 156 if (folder->fl_msgs_hash == NULL)
157 goto free_msgs_tab; 157 goto free_msgs_tab;
158 158
159 folder->fl_subfolders_tab = carray_new(128); 159 folder->fl_subfolders_tab = carray_new(128);
160 if (folder->fl_subfolders_tab == NULL) 160 if (folder->fl_subfolders_tab == NULL)
161 goto free_msgs_hash; 161 goto free_msgs_hash;
162 162
163 folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE); 163 folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE);
164 if (folder->fl_subfolders_hash == NULL) 164 if (folder->fl_subfolders_hash == NULL)
165 goto free_subfolders_tab; 165 goto free_subfolders_tab;
166 166
167 folder->fl_mtime = 0; 167 folder->fl_mtime = 0;
168 folder->fl_parent = parent; 168 folder->fl_parent = parent;
169 folder->fl_max_index = 0; 169 folder->fl_max_index = 0;
170 170
171 return folder; 171 return folder;
172 172
173 free_subfolders_tab: 173 free_subfolders_tab:
174 carray_free(folder->fl_subfolders_tab); 174 carray_free(folder->fl_subfolders_tab);
175 free_msgs_hash: 175 free_msgs_hash:
176#if 0 176#if 0
177 cinthash_free(folder->fl_msgs_hash); 177 cinthash_free(folder->fl_msgs_hash);
178#endif 178#endif
179 chash_free(folder->fl_msgs_hash); 179 chash_free(folder->fl_msgs_hash);
180 free_msgs_tab: 180 free_msgs_tab:
181 carray_free(folder->fl_msgs_tab); 181 carray_free(folder->fl_msgs_tab);
182 free_name: 182 free_name:
183 free(folder->fl_name); 183 free(folder->fl_name);
184 free_filename: 184 free_filename:
185 free(folder->fl_filename); 185 free(folder->fl_filename);
186 free_folder: 186 free_folder:
187 free(folder); 187 free(folder);
188 err: 188 err:
189 return NULL; 189 return NULL;
190} 190}
191 191
192void mailmh_folder_free(struct mailmh_folder * folder) 192void mailmh_folder_free(struct mailmh_folder * folder)
193{ 193{
194 unsigned int i; 194 unsigned int i;
195 195
196 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { 196 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) {
197 struct mailmh_folder * subfolder; 197 struct mailmh_folder * subfolder;
198 198
199 subfolder = carray_get(folder->fl_subfolders_tab, i); 199 subfolder = carray_get(folder->fl_subfolders_tab, i);
200 if (subfolder != NULL) 200 if (subfolder != NULL)
201 mailmh_folder_free(subfolder); 201 mailmh_folder_free(subfolder);
202 } 202 }
203 carray_free(folder->fl_subfolders_tab); 203 carray_free(folder->fl_subfolders_tab);
204 chash_free(folder->fl_subfolders_hash); 204 chash_free(folder->fl_subfolders_hash);
205 205
206 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { 206 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
207 struct mailmh_msg_info * msg_info; 207 struct mailmh_msg_info * msg_info;
208 208
209 msg_info = carray_get(folder->fl_msgs_tab, i); 209 msg_info = carray_get(folder->fl_msgs_tab, i);
210 if (msg_info != NULL) 210 if (msg_info != NULL)
211 mailmh_msg_info_free(msg_info); 211 mailmh_msg_info_free(msg_info);
212 } 212 }
213 carray_free(folder->fl_msgs_tab); 213 carray_free(folder->fl_msgs_tab);
214 chash_free(folder->fl_msgs_hash); 214 chash_free(folder->fl_msgs_hash);
215#if 0 215#if 0
216 cinthash_free(folder->fl_msgs_hash); 216 cinthash_free(folder->fl_msgs_hash);
217#endif 217#endif
218 218
219 free(folder->fl_filename); 219 free(folder->fl_filename);
220 free(folder->fl_name); 220 free(folder->fl_name);
221 221
222 free(folder); 222 free(folder);
223} 223}
224 224
225struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, 225struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root,
226 const char * filename) 226 const char * filename)
227{ 227{
228 int r; 228 int r;
229 char pathname[PATH_MAX]; 229 char pathname[PATH_MAX];
230 char * p; 230 char * p;
231 chashdatum key; 231 chashdatum key;
232 chashdatum data; 232 chashdatum data;
233 struct mailmh_folder * folder; 233 struct mailmh_folder * folder;
234 char * start; 234 char * start;
235 235
236 if (strcmp(root->fl_filename, filename) == 0) 236 if (strcmp(root->fl_filename, filename) == 0)
237 return root; 237 return root;
238 238
239#if 0 239#if 0
240 r = mailmh_folder_update(root); 240 r = mailmh_folder_update(root);
241 if (r != MAILMH_NO_ERROR) 241 if (r != MAILMH_NO_ERROR)
242 return NULL; 242 return NULL;
243#endif 243#endif
244 244
245#if 0 245#if 0
246 for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) { 246 for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) {
247 struct mailmh_folder * subfolder; 247 struct mailmh_folder * subfolder;
248 248
249 subfolder = carray_get(root->fl_subfolders_tab, i); 249 subfolder = carray_get(root->fl_subfolders_tab, i);
250 if (subfolder != NULL) 250 if (subfolder != NULL)
251 if (strncmp(subfolder->fl_filename, filename, 251 if (strncmp(subfolder->fl_filename, filename,
252 strlen(subfolder->fl_filename)) == 0) 252 strlen(subfolder->fl_filename)) == 0)
253 return mailmh_folder_find(subfolder, filename); 253 return mailmh_folder_find(subfolder, filename);
254 } 254 }
255#endif 255#endif
256 strncpy(pathname, filename, PATH_MAX); 256 strncpy(pathname, filename, PATH_MAX);
257 pathname[PATH_MAX - 1] = 0; 257 pathname[PATH_MAX - 1] = 0;
258 start = pathname + strlen(root->fl_filename) + 1; 258 start = pathname + strlen(root->fl_filename) + 1;
259 259
260 p = strchr(start, MAIL_DIR_SEPARATOR); 260 p = strchr(start, MAIL_DIR_SEPARATOR);
261 if (p != NULL) { 261 if (p != NULL) {
262 * p = 0; 262 * p = 0;
263 263
264 root = mailmh_folder_find(root, pathname); 264 root = mailmh_folder_find(root, pathname);
265 if (root != NULL) { 265 if (root != NULL) {
266 folder = mailmh_folder_find(root, filename); 266 folder = mailmh_folder_find(root, filename);
267 if (folder == NULL) 267 if (folder == NULL)
268 return NULL; 268 return NULL;
269 return folder; 269 return folder;
270 } 270 }
271 271
272 return NULL; 272 return NULL;
273 } 273 }
274 else { 274 else {
275 key.data = pathname; 275 key.data = pathname;
276 key.len = strlen(pathname); 276 key.len = strlen(pathname);
277 r = chash_get(root->fl_subfolders_hash, &key, &data); 277 r = chash_get(root->fl_subfolders_hash, &key, &data);
278 if (r < 0) 278 if (r < 0)
279 return NULL; 279 return NULL;
280 280
281 return data.data; 281 return data.data;
282 } 282 }
283} 283}
284 284
285int mailmh_folder_update(struct mailmh_folder * folder) 285int mailmh_folder_update(struct mailmh_folder * folder)
286{ 286{
287 DIR * d; 287 DIR * d;
288 struct dirent * ent; 288 struct dirent * ent;
289 struct stat buf; 289 struct stat buf;
290 char * mh_seq; 290 char * mh_seq;
291 char filename[PATH_MAX]; 291 char filename[PATH_MAX];
292 int res; 292 int res;
293 int r; 293 int r;
294 uint32_t max_index; 294 uint32_t max_index;
295#if 0 295#if 0
296 int add_folder; 296 int add_folder;
297#endif 297#endif
298 unsigned int i; 298 unsigned int i;
299 299
300 if (stat(folder->fl_filename, &buf) == -1) { 300 if (stat(folder->fl_filename, &buf) == -1) {
301 res = MAILMH_ERROR_FOLDER; 301 res = MAILMH_ERROR_FOLDER;
302 goto err; 302 goto err;
303 } 303 }
304 304
305 if (folder->fl_mtime == buf.st_mtime) { 305 if (folder->fl_mtime == buf.st_mtime) {
306 res = MAILMH_NO_ERROR; 306 res = MAILMH_NO_ERROR;
307 goto err; 307 goto err;
308 } 308 }
309 309
310 folder->fl_mtime = buf.st_mtime; 310 folder->fl_mtime = buf.st_mtime;
311 311
312 d = opendir(folder->fl_filename); 312 d = opendir(folder->fl_filename);
313 if (d == NULL) { 313 if (d == NULL) {
314 res = MAILMH_ERROR_FOLDER; 314 res = MAILMH_ERROR_FOLDER;
315 goto err; 315 goto err;
316 } 316 }
317 317
318 max_index = 0; 318 max_index = 0;
319 319
320#if 0 320#if 0
321 if (folder->fl_subfolders_tab->len == 0) 321 if (folder->fl_subfolders_tab->len == 0)
322 add_folder = 1; 322 add_folder = 1;
323 else 323 else
324 add_folder = 0; 324 add_folder = 0;
325#endif 325#endif
326 326
327 /* clear the message list */ 327 /* clear the message list */
328 328
329 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { 329 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) {
330 struct mailmh_msg_info * msg_info; 330 struct mailmh_msg_info * msg_info;
331 chashdatum key; 331 chashdatum key;
332 332
333 msg_info = carray_get(folder->fl_msgs_tab, i); 333 msg_info = carray_get(folder->fl_msgs_tab, i);
334 if (msg_info == NULL) 334 if (msg_info == NULL)
335 continue; 335 continue;
336 336
337#if 0 337#if 0
338 cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index); 338 cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index);
339#endif 339#endif
340 key.data = &msg_info->msg_index; 340 key.data = &msg_info->msg_index;
341 key.len = sizeof(msg_info->msg_index); 341 key.len = sizeof(msg_info->msg_index);
342 chash_delete(folder->fl_msgs_hash, &key, NULL); 342 chash_delete(folder->fl_msgs_hash, &key, NULL);
343 343
344 mailmh_msg_info_free(msg_info); 344 mailmh_msg_info_free(msg_info);
345 } 345 }
346 346
347 carray_set_size(folder->fl_msgs_tab, 0); 347 carray_set_size(folder->fl_msgs_tab, 0);
348 348
349 do { 349 do {
350 uint32_t index; 350 uint32_t index;
351 351
352 ent = readdir(d); 352 ent = readdir(d);
353 353
354 if (ent != NULL) { 354 if (ent != NULL) {
355 355
356 snprintf(filename, PATH_MAX, 356 snprintf(filename, PATH_MAX,
357 "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); 357 "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name);
358 358
359 if (stat(filename, &buf) == -1) 359 if (stat(filename, &buf) == -1)
360 continue; 360 continue;
361 361
362 if (S_ISREG(buf.st_mode)) { 362 if (S_ISREG(buf.st_mode)) {
363 index = strtoul(ent->d_name, NULL, 10); 363 index = strtoul(ent->d_name, NULL, 10);
364 if (index != 0) { 364 if (index != 0) {
365 struct mailmh_msg_info * msg_info; 365 struct mailmh_msg_info * msg_info;
366 unsigned int array_index; 366 unsigned int array_index;
367 chashdatum key; 367 chashdatum key;
368 chashdatum data; 368 chashdatum data;
369 369
370 msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime); 370 msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime);
371 if (msg_info == NULL) { 371 if (msg_info == NULL) {
372 res = MAILMH_ERROR_MEMORY; 372 res = MAILMH_ERROR_MEMORY;
373 goto closedir; 373 goto closedir;
374 } 374 }
375 375
376 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); 376 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
377 if (r < 0) { 377 if (r < 0) {
378 mailmh_msg_info_free(msg_info); 378 mailmh_msg_info_free(msg_info);
379 res = MAILMH_ERROR_MEMORY; 379 res = MAILMH_ERROR_MEMORY;
380 goto closedir; 380 goto closedir;
381 } 381 }
382 msg_info->msg_array_index = array_index; 382 msg_info->msg_array_index = array_index;
383 383
384 if (index > max_index) 384 if (index > max_index)
385 max_index = index; 385 max_index = index;
386 386
387#if 0 387#if 0
388 r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info); 388 r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info);
389#endif 389#endif
390 key.data = &msg_info->msg_index; 390 key.data = &msg_info->msg_index;
391 key.len = sizeof(msg_info->msg_index); 391 key.len = sizeof(msg_info->msg_index);
392 data.data = msg_info; 392 data.data = msg_info;
393 data.len = 0; 393 data.len = 0;
394 394
395 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); 395 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
396 if (r < 0) { 396 if (r < 0) {
397 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 397 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
398 mailmh_msg_info_free(msg_info); 398 mailmh_msg_info_free(msg_info);
399 res = MAILMH_ERROR_MEMORY; 399 res = MAILMH_ERROR_MEMORY;
400 goto closedir; 400 goto closedir;
401 } 401 }
402 } 402 }
403 } 403 }
404 else if (S_ISDIR(buf.st_mode)) { 404 else if (S_ISDIR(buf.st_mode)) {
405 struct mailmh_folder * subfolder; 405 struct mailmh_folder * subfolder;
406 unsigned int array_index; 406 unsigned int array_index;
407 chashdatum key; 407 chashdatum key;
408 chashdatum data; 408 chashdatum data;
409 409
410 if (ent->d_name[0] == '.') { 410 if (ent->d_name[0] == '.') {
411 if (ent->d_name[1] == 0) 411 if (ent->d_name[1] == 0)
412 continue; 412 continue;
413 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) 413 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))
414 continue; 414 continue;
415 } 415 }
416 416
417 key.data = ent->d_name; 417 key.data = ent->d_name;
418 key.len = strlen(ent->d_name); 418 key.len = strlen(ent->d_name);
419 r = chash_get(folder->fl_subfolders_hash, &key, &data); 419 r = chash_get(folder->fl_subfolders_hash, &key, &data);
420 if (r < 0) { 420 if (r < 0) {
421 subfolder = mailmh_folder_new(folder, ent->d_name); 421 subfolder = mailmh_folder_new(folder, ent->d_name);
422 if (subfolder == NULL) { 422 if (subfolder == NULL) {
423 res = MAILMH_ERROR_MEMORY; 423 res = MAILMH_ERROR_MEMORY;
424 goto closedir; 424 goto closedir;
425 } 425 }
426 426
427 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); 427 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index);
428 if (r < 0) { 428 if (r < 0) {
429 mailmh_folder_free(subfolder); 429 mailmh_folder_free(subfolder);
430 res = MAILMH_ERROR_MEMORY; 430 res = MAILMH_ERROR_MEMORY;
431 goto closedir; 431 goto closedir;
432 } 432 }
433 subfolder->fl_array_index = array_index; 433 subfolder->fl_array_index = array_index;
434 434
435 key.data = subfolder->fl_filename; 435 key.data = subfolder->fl_filename;
436 key.len = strlen(subfolder->fl_filename); 436 key.len = strlen(subfolder->fl_filename);
437 data.data = subfolder; 437 data.data = subfolder;
438 data.len = 0; 438 data.len = 0;
439 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); 439 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL);
440 if (r < 0) { 440 if (r < 0) {
441 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); 441 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index);
442 mailmh_folder_free(subfolder); 442 mailmh_folder_free(subfolder);
443 res = MAILMH_ERROR_MEMORY; 443 res = MAILMH_ERROR_MEMORY;
444 goto closedir; 444 goto closedir;
445 } 445 }
446 } 446 }
447 } 447 }
448 } 448 }
449 } 449 }
450 while (ent != NULL); 450 while (ent != NULL);
451 451
452 folder->fl_max_index = max_index; 452 folder->fl_max_index = max_index;
453 453
454 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); 454 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences"));
455 if (mh_seq == NULL) { 455 if (mh_seq == NULL) {
456 res = MAILMH_ERROR_MEMORY; 456 res = MAILMH_ERROR_MEMORY;
457 goto closedir; 457 goto closedir;
458 } 458 }
459 strcpy(mh_seq, folder->fl_filename); 459 strcpy(mh_seq, folder->fl_filename);
460 strcat(mh_seq, MAIL_DIR_SEPARATOR_S); 460 strcat(mh_seq, MAIL_DIR_SEPARATOR_S);
461 strcat(mh_seq, ".mh_sequences"); 461 strcat(mh_seq, ".mh_sequences");
462 462
463 if (stat(mh_seq, &buf) == -1) { 463 if (stat(mh_seq, &buf) == -1) {
464 int fd; 464 int fd;
465 465
466 fd = creat(mh_seq, S_IRUSR | S_IWUSR); 466 fd = creat(mh_seq, S_IRUSR | S_IWUSR);
467 if (fd != -1) 467 if (fd != -1)
468 close(fd); 468 close(fd);
469 } 469 }
470 free(mh_seq); 470 free(mh_seq);
471 471
472 closedir(d); 472 closedir(d);
473 473
474 return MAILMH_NO_ERROR; 474 return MAILMH_NO_ERROR;
475 475
476 closedir: 476 closedir:
477 closedir(d); 477 closedir(d);
478 err: 478 err:
479 return res; 479 return res;
480} 480}
481 481
482int mailmh_folder_add_subfolder(struct mailmh_folder * parent, 482int mailmh_folder_add_subfolder(struct mailmh_folder * parent,
483 const char * name) 483 const char * name)
484{ 484{
485 char * foldername; 485 char * foldername;
486 int r; 486 int r;
487 struct mailmh_folder * folder; 487 struct mailmh_folder * folder;
488 unsigned int array_index; 488 unsigned int array_index;
489 chashdatum key; 489 chashdatum key;
490 chashdatum data; 490 chashdatum data;
491 491
492 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); 492 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2);
493 if (foldername == NULL) 493 if (foldername == NULL)
494 return MAILMH_ERROR_MEMORY; 494 return MAILMH_ERROR_MEMORY;
495 strcpy(foldername, parent->fl_filename); 495 strcpy(foldername, parent->fl_filename);
496 strcat(foldername, MAIL_DIR_SEPARATOR_S); 496 strcat(foldername, MAIL_DIR_SEPARATOR_S);
497 strcat(foldername, name); 497 strcat(foldername, name);
498 498
499 r = mkdir(foldername, 0700); 499 r = mkdir(foldername, 0700);
500 free(foldername); 500 free(foldername);
501 501
502 if (r < 0) 502 if (r < 0)
503 return MAILMH_ERROR_FOLDER; 503 return MAILMH_ERROR_FOLDER;
504 504
505 folder = mailmh_folder_new(parent, name); 505 folder = mailmh_folder_new(parent, name);
506 if (folder == NULL) 506 if (folder == NULL)
507 return MAILMH_ERROR_MEMORY; 507 return MAILMH_ERROR_MEMORY;
508 508
509 r = carray_add(parent->fl_subfolders_tab, folder, &array_index); 509 r = carray_add(parent->fl_subfolders_tab, folder, &array_index);
510 if (r < 0) { 510 if (r < 0) {
511 mailmh_folder_free(folder); 511 mailmh_folder_free(folder);
512 return MAILMH_ERROR_MEMORY; 512 return MAILMH_ERROR_MEMORY;
513 } 513 }
514 folder->fl_array_index = array_index; 514 folder->fl_array_index = array_index;
515 515
516 key.data = folder->fl_filename; 516 key.data = folder->fl_filename;
517 key.len = strlen(folder->fl_filename); 517 key.len = strlen(folder->fl_filename);
518 data.data = folder; 518 data.data = folder;
519 data.len = 0; 519 data.len = 0;
520 520
521 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); 521 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL);
522 if (r < 0) { 522 if (r < 0) {
523 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); 523 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index);
524 mailmh_folder_free(folder); 524 mailmh_folder_free(folder);
525 return MAILMH_ERROR_MEMORY; 525 return MAILMH_ERROR_MEMORY;
526 } 526 }
527 527
528 return MAILMH_NO_ERROR; 528 return MAILMH_NO_ERROR;
529} 529}
530 530
531int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) 531int mailmh_folder_remove_subfolder(struct mailmh_folder * folder)
532{ 532{
533 struct mailmh_folder * parent; 533 struct mailmh_folder * parent;
534 chashdatum key; 534 chashdatum key;
535 chashdatum data; 535 chashdatum data;
536 int r; 536 int r;
537 537
538 parent = folder->fl_parent; 538 parent = folder->fl_parent;
539 539
540 key.data = folder->fl_filename; 540 key.data = folder->fl_filename;
541 key.len = strlen(folder->fl_filename); 541 key.len = strlen(folder->fl_filename);
542 542
543 r = chash_get(parent->fl_subfolders_hash, &key, &data); 543 r = chash_get(parent->fl_subfolders_hash, &key, &data);
544 if (r < 0) 544 if (r < 0)
545 return MAILMH_ERROR_FOLDER; 545 return MAILMH_ERROR_FOLDER;
546 546
547 chash_delete(parent->fl_subfolders_hash, &key, NULL); 547 chash_delete(parent->fl_subfolders_hash, &key, NULL);
548 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); 548 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index);
549 549
550 mailmh_folder_free(folder); 550 mailmh_folder_free(folder);
551 551
552 return MAILMH_NO_ERROR; 552 return MAILMH_NO_ERROR;
553 553
554} 554}
555 555
556int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, 556int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder,
557 struct mailmh_folder * dst_folder, 557 struct mailmh_folder * dst_folder,
558 const char * new_name) 558 const char * new_name)
559{ 559{
560 int r; 560 int r;
561 struct mailmh_folder * folder; 561 struct mailmh_folder * folder;
562 struct mailmh_folder * parent; 562 struct mailmh_folder * parent;
563 char * new_foldername; 563 char * new_foldername;
564 564
565 parent = src_folder->fl_parent; 565 parent = src_folder->fl_parent;
566 if (parent == NULL) 566 if (parent == NULL)
567 return MAILMH_ERROR_RENAME; 567 return MAILMH_ERROR_RENAME;
568 568
569 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); 569 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name));
570 if (new_foldername == NULL) 570 if (new_foldername == NULL)
571 return MAILMH_ERROR_MEMORY; 571 return MAILMH_ERROR_MEMORY;
572 572
573 strcpy(new_foldername, dst_folder->fl_filename); 573 strcpy(new_foldername, dst_folder->fl_filename);
574 strcat(new_foldername, MAIL_DIR_SEPARATOR_S); 574 strcat(new_foldername, MAIL_DIR_SEPARATOR_S);
575 strcat(new_foldername, new_name); 575 strcat(new_foldername, new_name);
576 576
577 r = rename(src_folder->fl_filename, new_foldername); 577 r = rename(src_folder->fl_filename, new_foldername);
578 free(new_foldername); 578 free(new_foldername);
579 if (r < 0) 579 if (r < 0)
580 return MAILMH_ERROR_RENAME; 580 return MAILMH_ERROR_RENAME;
581 581
582 r = mailmh_folder_remove_subfolder(src_folder); 582 r = mailmh_folder_remove_subfolder(src_folder);
583 if (r != MAILMH_NO_ERROR) 583 if (r != MAILMH_NO_ERROR)
584 return r; 584 return r;
585 585
586 folder = mailmh_folder_new(dst_folder, new_name); 586 folder = mailmh_folder_new(dst_folder, new_name);
587 if (folder == NULL) 587 if (folder == NULL)
588 return MAILMH_ERROR_MEMORY; 588 return MAILMH_ERROR_MEMORY;
589 589
590 r = carray_add(parent->fl_subfolders_tab, folder, NULL); 590 r = carray_add(parent->fl_subfolders_tab, folder, NULL);
591 if (r < 0) { 591 if (r < 0) {
592 mailmh_folder_free(folder); 592 mailmh_folder_free(folder);
593 return MAILMH_ERROR_MEMORY; 593 return MAILMH_ERROR_MEMORY;
594 } 594 }
595 595
596 return MAILMH_NO_ERROR; 596 return MAILMH_NO_ERROR;
597} 597}
598 598
599#define MAX_TRY_ALLOC 32 599#define MAX_TRY_ALLOC 32
600 600
601/* initial file MUST be in the same directory */ 601/* initial file MUST be in the same directory */
602 602
603static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, 603static int mailmh_folder_alloc_msg(struct mailmh_folder * folder,
604 char * filename, uint32_t * result) 604 char * filename, uint32_t * result)
605{ 605{
606 uint32_t max; 606 uint32_t max;
607 uint32_t k; 607 uint32_t k;
608 char * new_filename; 608 char * new_filename;
609 size_t len; 609 size_t len;
610 int got_file; 610 int got_file;
611 int r; 611 int r;
612 612
613 len = strlen(folder->fl_filename) + 20; 613 len = strlen(folder->fl_filename) + 20;
614 new_filename = malloc(len); 614 new_filename = malloc(len);
615 if (new_filename == NULL) 615 if (new_filename == NULL)
616 return MAILMH_ERROR_MEMORY; 616 return MAILMH_ERROR_MEMORY;
617 617
618 max = folder->fl_max_index + 1; 618 max = folder->fl_max_index + 1;
619 619
620 got_file = 0; 620 got_file = 0;
621 k = 0; 621 k = 0;
622 while (k < MAX_TRY_ALLOC) { 622 while (k < MAX_TRY_ALLOC) {
623 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, 623 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename,
624 MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); 624 MAIL_DIR_SEPARATOR, (unsigned long) (max + k));
625 625
626 if (link(filename, new_filename) == 0) { 626 if (link(filename, new_filename) == 0) {
627 unlink(filename); 627 unlink(filename);
628 } 628 }
629 else if (errno == EXDEV) { 629 else if (errno == EXDEV) {
630 free(filename); 630 free(filename);
631 return MAILMH_ERROR_FOLDER; 631 return MAILMH_ERROR_FOLDER;
632 } 632 }
633 else if (errno == EPERM) { 633 else if (errno == EPERM) {
634 rename(filename, new_filename); 634 rename(filename, new_filename);
635 got_file = 1; 635 got_file = 1;
636 } 636 }
637 637
638 if (got_file) { 638 if (got_file) {
639 free(new_filename); 639 free(new_filename);
640 640
641 if (k > MAX_TRY_ALLOC / 2) { 641 if (k > MAX_TRY_ALLOC / 2) {
642 r = mailmh_folder_update(folder); 642 r = mailmh_folder_update(folder);
643 /* ignore errors */ 643 /* ignore errors */
644 } 644 }
645 645
646 * result = max + k; 646 * result = max + k;
647 647
648 folder->fl_max_index = max + k; 648 folder->fl_max_index = max + k;
649 649
650 return MAILMH_NO_ERROR; 650 return MAILMH_NO_ERROR;
651 } 651 }
652 k ++; 652 k ++;
653 } 653 }
654 654
655 free(new_filename); 655 free(new_filename);
656 656
657 return MAILMH_ERROR_FOLDER; 657 return MAILMH_ERROR_FOLDER;
658} 658}
659 659
660int mailmh_folder_get_message_filename(struct mailmh_folder * folder, 660int mailmh_folder_get_message_filename(struct mailmh_folder * folder,
661 uint32_t index, char ** result) 661 uint32_t index, char ** result)
662{ 662{
663 char * filename; 663 char * filename;
664 int len; 664 int len;
665 665
666#if 0 666#if 0
667 r = mailmh_folder_update(folder); 667 r = mailmh_folder_update(folder);
668 if (r != MAILMH_NO_ERROR) 668 if (r != MAILMH_NO_ERROR)
669 return r; 669 return r;
670#endif 670#endif
671 671
672 len = strlen(folder->fl_filename) + 20; 672 len = strlen(folder->fl_filename) + 20;
673 filename = malloc(len); 673 filename = malloc(len);
674 if (filename == NULL) 674 if (filename == NULL)
675 return MAILMH_ERROR_MEMORY; 675 return MAILMH_ERROR_MEMORY;
676 676
677 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, 677 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR,
678 (unsigned long) index); 678 (unsigned long) index);
679 679
680 * result = filename; 680 * result = filename;
681 681
682 return MAILMH_NO_ERROR;; 682 return MAILMH_NO_ERROR;;
683} 683}
684 684
685 685
686int mailmh_folder_get_message_fd(struct mailmh_folder * folder, 686int mailmh_folder_get_message_fd(struct mailmh_folder * folder,
687 uint32_t index, int flags, int * result) 687 uint32_t index, int flags, int * result)
688{ 688{
689 char * filename; 689 char * filename;
690 int fd; 690 int fd;
691 int r; 691 int r;
692 692
693#if 0 693#if 0
694 r = mailmh_folder_update(folder); 694 r = mailmh_folder_update(folder);
695 if (r != MAILMH_NO_ERROR) 695 if (r != MAILMH_NO_ERROR)
696 return r; 696 return r;
697#endif 697#endif
698 698
699 r = mailmh_folder_get_message_filename(folder, index, &filename); 699 r = mailmh_folder_get_message_filename(folder, index, &filename);
700 if (r != MAILMH_NO_ERROR) 700 if (r != MAILMH_NO_ERROR)
701 return r; 701 return r;
702 702
703 fd = open(filename, flags); 703 fd = open(filename, flags);
704 free(filename); 704 free(filename);
705 if (fd == -1) 705 if (fd == -1)
706 return MAILMH_ERROR_MSG_NOT_FOUND; 706 return MAILMH_ERROR_MSG_NOT_FOUND;
707 707
708 * result = fd; 708 * result = fd;
709 709
710 return MAILMH_NO_ERROR; 710 return MAILMH_NO_ERROR;
711} 711}
712 712
713int mailmh_folder_get_message_size(struct mailmh_folder * folder, 713int mailmh_folder_get_message_size(struct mailmh_folder * folder,
714 uint32_t index, size_t * result) 714 uint32_t index, size_t * result)
715{ 715{
716 int r; 716 int r;
717 char * filename; 717 char * filename;
718 struct stat buf; 718 struct stat buf;
719 719
720 r = mailmh_folder_get_message_filename(folder, index, &filename); 720 r = mailmh_folder_get_message_filename(folder, index, &filename);
721 if (r != MAILMH_NO_ERROR) 721 if (r != MAILMH_NO_ERROR)
722 return r; 722 return r;
723 723
724 r = stat(filename, &buf); 724 r = stat(filename, &buf);
725 free(filename); 725 free(filename);
726 if (r < 0) 726 if (r < 0)
727 return MAILMH_ERROR_FILE; 727 return MAILMH_ERROR_FILE;
728 728
729 * result = buf.st_size; 729 * result = buf.st_size;
730 730
731 return MAILMH_NO_ERROR; 731 return MAILMH_NO_ERROR;
732} 732}
733 733
734int mailmh_folder_add_message_uid(struct mailmh_folder * folder, 734int mailmh_folder_add_message_uid(struct mailmh_folder * folder,
735 const char * message, size_t size, 735 const char * message, size_t size,
736 uint32_t * pindex) 736 uint32_t * pindex)
737{ 737{
738 char * tmpname; 738 char * tmpname;
739 int fd; 739 int fd;
740 size_t namesize; 740 size_t namesize;
741 size_t left; 741 size_t left;
742 ssize_t res; 742 ssize_t res;
743 struct mailmh_msg_info * msg_info; 743 struct mailmh_msg_info * msg_info;
744 uint32_t index; 744 uint32_t index;
745 int error; 745 int error;
746 int r; 746 int r;
747 unsigned int array_index; 747 unsigned int array_index;
748 struct stat buf; 748 struct stat buf;
749 chashdatum key; 749 chashdatum key;
750 chashdatum data; 750 chashdatum data;
751 751
752#if 0 752#if 0
753 r = mailmh_folder_update(folder); 753 r = mailmh_folder_update(folder);
754 if (r != MAILMH_NO_ERROR) { 754 if (r != MAILMH_NO_ERROR) {
755 error = r; 755 error = r;
756 goto err; 756 goto err;
757 } 757 }
758#endif 758#endif
759 759
760 namesize = strlen(folder->fl_filename) + 20; 760 namesize = strlen(folder->fl_filename) + 20;
761 tmpname = malloc(namesize); 761 tmpname = malloc(namesize);
762 snprintf(tmpname, namesize, "%s%ctmpXXXXXX", 762 snprintf(tmpname, namesize, "%s%ctmpXXXXXX",
763 folder->fl_filename, MAIL_DIR_SEPARATOR); 763 folder->fl_filename, MAIL_DIR_SEPARATOR);
764 fd = mkstemp(tmpname); 764 fd = mkstemp(tmpname);
765 if (fd < 0) { 765 if (fd < 0) {
766 error = MAILMH_ERROR_FILE; 766 error = MAILMH_ERROR_FILE;
767 goto free; 767 goto free;
768 } 768 }
769 769
770 left = size; 770 left = size;
771 while (left > 0) { 771 while (left > 0) {
772 res = write(fd, message, left); 772 res = write(fd, message, left);
773 if (res == -1) { 773 if (res == -1) {
774 close(fd); 774 close(fd);
775 error = MAILMH_ERROR_FILE; 775 error = MAILMH_ERROR_FILE;
776 goto free; 776 goto free;
777 } 777 }
778 778
779 left -= res; 779 left -= res;
780 } 780 }
781 close(fd); 781 close(fd);
782 782
783 r = stat(tmpname, &buf); 783 r = stat(tmpname, &buf);
784 if (r < 0) { 784 if (r < 0) {
785 error = MAILMH_ERROR_FILE; 785 error = MAILMH_ERROR_FILE;
786 goto free; 786 goto free;
787 } 787 }
788 788
789 r = mailmh_folder_alloc_msg(folder, tmpname, &index); 789 r = mailmh_folder_alloc_msg(folder, tmpname, &index);
790 if (r != MAILMH_NO_ERROR) { 790 if (r != MAILMH_NO_ERROR) {
791 unlink(tmpname); 791 unlink(tmpname);
792 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; 792 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG;
793 goto free; 793 goto free;
794 } 794 }
795 free(tmpname); 795 free(tmpname);
796 796
797 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); 797 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime);
798 if (msg_info == NULL) { 798 if (msg_info == NULL) {
799 mailmh_folder_remove_message(folder, index); 799 mailmh_folder_remove_message(folder, index);
800 error = MAILMH_ERROR_MEMORY; 800 error = MAILMH_ERROR_MEMORY;
801 goto err; 801 goto err;
802 } 802 }
803 803
804 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); 804 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
805 if (r < 0) { 805 if (r < 0) {
806 mailmh_folder_remove_message(folder, index); 806 mailmh_folder_remove_message(folder, index);
807 mailmh_msg_info_free(msg_info); 807 mailmh_msg_info_free(msg_info);
808 error = MAILMH_ERROR_MEMORY; 808 error = MAILMH_ERROR_MEMORY;
809 goto err; 809 goto err;
810 } 810 }
811 msg_info->msg_array_index = array_index; 811 msg_info->msg_array_index = array_index;
812 812
813#if 0 813#if 0
814 r = cinthash_add(folder->fl_msgs_hash, index, msg_info); 814 r = cinthash_add(folder->fl_msgs_hash, index, msg_info);
815#endif 815#endif
816 key.data = &index; 816 key.data = &index;
817 key.len = sizeof(index); 817 key.len = sizeof(index);
818 data.data = msg_info; 818 data.data = msg_info;
819 data.len = 0; 819 data.len = 0;
820 820
821 if (pindex != NULL) 821 if (pindex != NULL)
822 * pindex = index; 822 * pindex = index;
823 823
824 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); 824 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
825 if (r < 0) { 825 if (r < 0) {
826 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 826 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
827 mailmh_msg_info_free(msg_info); 827 mailmh_msg_info_free(msg_info);
828 error = MAILMH_ERROR_MEMORY; 828 error = MAILMH_ERROR_MEMORY;
829 goto err; 829 goto err;
830 } 830 }
831 831
832 return MAILMH_NO_ERROR; 832 return MAILMH_NO_ERROR;
833 833
834 free: 834 free:
835 free(tmpname); 835 free(tmpname);
836 err: 836 err:
837 return error; 837 return error;
838} 838}
839 839
840int mailmh_folder_add_message(struct mailmh_folder * folder, 840int mailmh_folder_add_message(struct mailmh_folder * folder,
841 const char * message, size_t size) 841 const char * message, size_t size)
842{ 842{
843 return mailmh_folder_add_message_uid(folder, message, size, NULL); 843 return mailmh_folder_add_message_uid(folder, message, size, NULL);
844} 844}
845 845
846int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, 846int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder,
847 int fd, uint32_t * pindex) 847 int fd, uint32_t * pindex)
848{ 848{
849 char * message; 849 char * message;
850 struct stat buf; 850 struct stat buf;
851 int r; 851 int r;
852 852
853#if 0 853#if 0
854 r = mailmh_folder_update(folder); 854 r = mailmh_folder_update(folder);
855 if (r != MAILMH_NO_ERROR) 855 if (r != MAILMH_NO_ERROR)
856 return r; 856 return r;
857#endif 857#endif
858 858
859 if (fstat(fd, &buf) == -1) 859 if (fstat(fd, &buf) == -1)
860 return MAILMH_ERROR_FILE; 860 return MAILMH_ERROR_FILE;
861 861
862 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 862 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
863 if (message == MAP_FAILED) 863 if (message == MAP_FAILED)
864 return MAILMH_ERROR_FILE; 864 return MAILMH_ERROR_FILE;
865 865
866 r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex); 866 r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex);
867 867
868 munmap(message, buf.st_size); 868 munmap(message, buf.st_size);
869 869
870 return r; 870 return r;
871} 871}
872 872
873int mailmh_folder_add_message_file(struct mailmh_folder * folder, 873int mailmh_folder_add_message_file(struct mailmh_folder * folder,
874 int fd) 874 int fd)
875{ 875{
876 return mailmh_folder_add_message_file_uid(folder, fd, NULL); 876 return mailmh_folder_add_message_file_uid(folder, fd, NULL);
877} 877}
878 878
879int mailmh_folder_remove_message(struct mailmh_folder * folder, 879int mailmh_folder_remove_message(struct mailmh_folder * folder,
880 uint32_t index) 880 uint32_t index)
881{ 881{
882 char * filename; 882 char * filename;
883 struct mailmh_msg_info * msg_info; 883 struct mailmh_msg_info * msg_info;
884 int res; 884 int res;
885 int r; 885 int r;
886 chashdatum key; 886 chashdatum key;
887 chashdatum data; 887 chashdatum data;
888 888
889#if 0 889#if 0
890 r = mailmh_folder_update(folder); 890 r = mailmh_folder_update(folder);
891 if (r != MAILMH_NO_ERROR) { 891 if (r != MAILMH_NO_ERROR) {
892 res = r; 892 res = r;
893 goto err; 893 goto err;
894 } 894 }
895#endif 895#endif
896 896
897 r = mailmh_folder_get_message_filename(folder, index, &filename); 897 r = mailmh_folder_get_message_filename(folder, index, &filename);
898 if (filename == NULL) { 898 if (filename == NULL) {
899 res = r; 899 res = r;
900 goto err; 900 goto err;
901 } 901 }
902 902
903 if (unlink(filename) == -1) { 903 if (unlink(filename) == -1) {
904 res = MAILMH_ERROR_FILE; 904 res = MAILMH_ERROR_FILE;
905 goto free; 905 goto free;
906 } 906 }
907 907
908 key.data = &index; 908 key.data = &index;
909 key.len = sizeof(index); 909 key.len = sizeof(index);
910 r = chash_get(folder->fl_msgs_hash, &key, &data); 910 r = chash_get(folder->fl_msgs_hash, &key, &data);
911#if 0 911#if 0
912 msg_info = cinthash_find(folder->fl_msgs_hash, index); 912 msg_info = cinthash_find(folder->fl_msgs_hash, index);
913#endif 913#endif
914 if (r == 0) { 914 if (r == 0) {
915 msg_info = data.data; 915 msg_info = data.data;
916 916
917 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 917 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
918#if 0 918#if 0
919 cinthash_remove(folder->fl_msgs_hash, index); 919 cinthash_remove(folder->fl_msgs_hash, index);
920#endif 920#endif
921 chash_delete(folder->fl_msgs_hash, &key, NULL); 921 chash_delete(folder->fl_msgs_hash, &key, NULL);
922 } 922 }
923 // LR memory leak fixed
924 mailmh_msg_info_free( msg_info );
925 free(filename);
923 926
924 return MAILMH_NO_ERROR; 927 return MAILMH_NO_ERROR;
925 928
926 free: 929 free:
927 free(filename); 930 free(filename);
928 err: 931 err:
929 return res; 932 return res;
930} 933}
931 934
932 935
933int mailmh_folder_move_message(struct mailmh_folder * dest_folder, 936int mailmh_folder_move_message(struct mailmh_folder * dest_folder,
934 struct mailmh_folder * src_folder, 937 struct mailmh_folder * src_folder,
935 uint32_t index) 938 uint32_t index)
936{ 939{
937 int fd; 940 int fd;
938 char * filename; 941 char * filename;
939 int r; 942 int r;
940 943
941#if 0 944#if 0
942 r = mailmh_folder_update(dest_folder); 945 r = mailmh_folder_update(dest_folder);
943 if (r != MAILMH_NO_ERROR) 946 if (r != MAILMH_NO_ERROR)
944 return r; 947 return r;
945 r = mailmh_folder_update(src_folder); 948 r = mailmh_folder_update(src_folder);
946 if (r != MAILMH_NO_ERROR) 949 if (r != MAILMH_NO_ERROR)
947 return r; 950 return r;
948#endif 951#endif
949 952
950 /* move on the same filesystem */ 953 /* move on the same filesystem */
951 r = mailmh_folder_get_message_filename(src_folder, index, &filename); 954 r = mailmh_folder_get_message_filename(src_folder, index, &filename);
952 if (r != MAILMH_NO_ERROR) 955 if (r != MAILMH_NO_ERROR)
953 return r; 956 return r;
954 957
955 r = mailmh_folder_alloc_msg(dest_folder, filename, &index); 958 r = mailmh_folder_alloc_msg(dest_folder, filename, &index);
956 free(filename); 959 free(filename);
957 if (r == MAILMH_NO_ERROR) 960 if (r == MAILMH_NO_ERROR)
958 return MAILMH_NO_ERROR; 961 return MAILMH_NO_ERROR;
959 962
960 /* move on the different filesystems */ 963 /* move on the different filesystems */
961 r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd); 964 r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd);
962 if (r != MAILMH_NO_ERROR) 965 if (r != MAILMH_NO_ERROR)
963 return r; 966 return r;
964 967
965 r = mailmh_folder_add_message_file(dest_folder, fd); 968 r = mailmh_folder_add_message_file(dest_folder, fd);
966 if (r != MAILMH_NO_ERROR) { 969 if (r != MAILMH_NO_ERROR) {
967 close(fd); 970 close(fd);
968 return r; 971 return r;
969 } 972 }
970 973
971 close(fd); 974 close(fd);
972 975
973 r = mailmh_folder_remove_message(src_folder, index); 976 r = mailmh_folder_remove_message(src_folder, index);
974 977
975 return MAILMH_NO_ERROR; 978 return MAILMH_NO_ERROR;
976} 979}
977 980
978unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) 981unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder)
979{ 982{
980 unsigned int i; 983 unsigned int i;
981 unsigned int count; 984 unsigned int count;
982 985
983 count = 0; 986 count = 0;
984 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) 987 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++)
985 if (carray_get(folder->fl_msgs_tab, i) != NULL) 988 if (carray_get(folder->fl_msgs_tab, i) != NULL)
986 count ++; 989 count ++;
987 990
988 return count; 991 return count;
989} 992}
diff --git a/libetpan/src/low-level/pop3/mailpop3.c b/libetpan/src/low-level/pop3/mailpop3.c
index 6f77a3a..bca62d5 100644
--- a/libetpan/src/low-level/pop3/mailpop3.c
+++ b/libetpan/src/low-level/pop3/mailpop3.c
@@ -1,1230 +1,1233 @@
1/* 1/*
2 * libEtPan! -- a mail stuff library 2 * libEtPan! -- a mail stuff library
3 * 3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa 4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its 15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived 16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * $Id$ 33 * $Id$
34 */ 34 */
35 35
36/* 36/*
37 POP3 Protocol 37 POP3 Protocol
38 38
39 RFC 1734 39 RFC 1734
40 RFC 1939 40 RFC 1939
41 RFC 2449 41 RFC 2449
42 42
43 */ 43 */
44 44
45#include "mailpop3.h" 45#include "mailpop3.h"
46#include <stdio.h> 46#include <stdio.h>
47#include <string.h> 47#include <string.h>
48#include "md5.h" 48#include "md5.h"
49#include "mail.h" 49#include "mail.h"
50#include <stdlib.h> 50#include <stdlib.h>
51 51
52 52
53 53
54 54
55enum { 55enum {
56 POP3_STATE_DISCONNECTED, 56 POP3_STATE_DISCONNECTED,
57 POP3_STATE_AUTHORIZATION, 57 POP3_STATE_AUTHORIZATION,
58 POP3_STATE_TRANSACTION 58 POP3_STATE_TRANSACTION
59}; 59};
60 60
61 61
62 62
63/* 63/*
64 mailpop3_msg_info structure 64 mailpop3_msg_info structure
65*/ 65*/
66 66
67static struct mailpop3_msg_info * 67static struct mailpop3_msg_info *
68mailpop3_msg_info_new(unsigned int index, uint32_t size, char * uidl) 68mailpop3_msg_info_new(unsigned int index, uint32_t size, char * uidl)
69{ 69{
70 struct mailpop3_msg_info * msg; 70 struct mailpop3_msg_info * msg;
71 71
72 msg = malloc(sizeof(* msg)); 72 msg = malloc(sizeof(* msg));
73 if (msg == NULL) 73 if (msg == NULL)
74 return NULL; 74 return NULL;
75 msg->msg_index = index; 75 msg->msg_index = index;
76 msg->msg_size = size; 76 msg->msg_size = size;
77 msg->msg_deleted = FALSE; 77 msg->msg_deleted = FALSE;
78 msg->msg_uidl = uidl; 78 msg->msg_uidl = uidl;
79 79
80 return msg; 80 return msg;
81} 81}
82 82
83static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg) 83static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg)
84{ 84{
85 if (msg->msg_uidl != NULL) 85 if (msg->msg_uidl != NULL)
86 free(msg->msg_uidl); 86 free(msg->msg_uidl);
87 free(msg); 87 free(msg);
88} 88}
89 89
90static void mailpop3_msg_info_tab_free(carray * msg_tab) 90static void mailpop3_msg_info_tab_free(carray * msg_tab)
91{ 91{
92 unsigned int i; 92 unsigned int i;
93 93
94 for(i = 0 ; i < carray_count(msg_tab) ; i++) { 94 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
95 struct mailpop3_msg_info * msg; 95 struct mailpop3_msg_info * msg;
96 96
97 msg = carray_get(msg_tab, i); 97 msg = carray_get(msg_tab, i);
98 mailpop3_msg_info_free(msg); 98 mailpop3_msg_info_free(msg);
99 } 99 }
100 carray_free(msg_tab); 100 carray_free(msg_tab);
101} 101}
102 102
103static void mailpop3_msg_info_tab_reset(carray * msg_tab) 103static void mailpop3_msg_info_tab_reset(carray * msg_tab)
104{ 104{
105 unsigned int i; 105 unsigned int i;
106 106
107 for(i = 0 ; i < carray_count(msg_tab) ; i++) { 107 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
108 struct mailpop3_msg_info * msg; 108 struct mailpop3_msg_info * msg;
109 msg = carray_get(msg_tab, i); 109 msg = carray_get(msg_tab, i);
110 msg->msg_deleted = FALSE; 110 msg->msg_deleted = FALSE;
111 } 111 }
112} 112}
113 113
114static inline struct mailpop3_msg_info * 114static inline struct mailpop3_msg_info *
115mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index) 115mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index)
116{ 116{
117 struct mailpop3_msg_info * msg; 117 struct mailpop3_msg_info * msg;
118 118
119 if (index == 0) 119 if (index == 0)
120 return NULL; 120 return NULL;
121 121
122 if (index > carray_count(msg_tab)) 122 if (index > carray_count(msg_tab))
123 return NULL; 123 return NULL;
124 124
125 msg = carray_get(msg_tab, index - 1); 125 msg = carray_get(msg_tab, index - 1);
126 126
127 return msg; 127 return msg;
128} 128}
129 129
130 130
131 131
132int mailpop3_get_msg_info(mailpop3 * f, unsigned int index, 132int mailpop3_get_msg_info(mailpop3 * f, unsigned int index,
133 struct mailpop3_msg_info ** result) 133 struct mailpop3_msg_info ** result)
134{ 134{
135 carray * tab; 135 carray * tab;
136 struct mailpop3_msg_info * info; 136 struct mailpop3_msg_info * info;
137 137
138 mailpop3_list(f, &tab); 138 mailpop3_list(f, &tab);
139 139
140 if (tab == NULL) 140 if (tab == NULL)
141 return MAILPOP3_ERROR_BAD_STATE; 141 return MAILPOP3_ERROR_BAD_STATE;
142 142
143 info = mailpop3_msg_info_tab_find_msg(tab, index); 143 info = mailpop3_msg_info_tab_find_msg(tab, index);
144 if (info == NULL) 144 if (info == NULL)
145 return MAILPOP3_ERROR_NO_SUCH_MESSAGE; 145 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
146 146
147 * result = info; 147 * result = info;
148 148
149 return MAILPOP3_NO_ERROR; 149 return MAILPOP3_NO_ERROR;
150} 150}
151 151
152 152
153/* 153/*
154 mailpop3_capa 154 mailpop3_capa
155*/ 155*/
156 156
157struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param) 157struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param)
158{ 158{
159 struct mailpop3_capa * capa; 159 struct mailpop3_capa * capa;
160 160
161 capa = malloc(sizeof(* capa)); 161 capa = malloc(sizeof(* capa));
162 if (capa == NULL) 162 if (capa == NULL)
163 return NULL; 163 return NULL;
164 capa->cap_name = name; 164 capa->cap_name = name;
165 capa->cap_param = param; 165 capa->cap_param = param;
166 166
167 return capa; 167 return capa;
168} 168}
169 169
170 170
171void mailpop3_capa_free(struct mailpop3_capa * capa) 171void mailpop3_capa_free(struct mailpop3_capa * capa)
172{ 172{
173 clist_foreach(capa->cap_param, (clist_func) free, NULL); 173 clist_foreach(capa->cap_param, (clist_func) free, NULL);
174 clist_free(capa->cap_param); 174 clist_free(capa->cap_param);
175 free(capa->cap_name); 175 free(capa->cap_name);
176 free(capa); 176 free(capa);
177} 177}
178 178
179/* 179/*
180 mailpop3 structure 180 mailpop3 structure
181*/ 181*/
182 182
183mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun) 183mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun)
184{ 184{
185 mailpop3 * f; 185 mailpop3 * f;
186 186
187 f = malloc(sizeof(* f)); 187 f = malloc(sizeof(* f));
188 if (f == NULL) 188 if (f == NULL)
189 goto err; 189 goto err;
190 190
191 f->pop3_timestamp = NULL; 191 f->pop3_timestamp = NULL;
192 f->pop3_response = NULL; 192 f->pop3_response = NULL;
193 193
194 f->pop3_stream = NULL; 194 f->pop3_stream = NULL;
195 195
196 f->pop3_progr_rate = progr_rate; 196 f->pop3_progr_rate = progr_rate;
197 f->pop3_progr_fun = progr_fun; 197 f->pop3_progr_fun = progr_fun;
198 198
199 f->pop3_stream_buffer = mmap_string_new(""); 199 f->pop3_stream_buffer = mmap_string_new("");
200 if (f->pop3_stream_buffer == NULL) 200 if (f->pop3_stream_buffer == NULL)
201 goto free_f; 201 goto free_f;
202 202
203 f->pop3_response_buffer = mmap_string_new(""); 203 f->pop3_response_buffer = mmap_string_new("");
204 if (f->pop3_response_buffer == NULL) 204 if (f->pop3_response_buffer == NULL)
205 goto free_stream_buffer; 205 goto free_stream_buffer;
206 206
207 f->pop3_msg_tab = NULL; 207 f->pop3_msg_tab = NULL;
208 f->pop3_deleted_count = 0; 208 f->pop3_deleted_count = 0;
209 f->pop3_state = POP3_STATE_DISCONNECTED; 209 f->pop3_state = POP3_STATE_DISCONNECTED;
210 210
211 return f; 211 return f;
212 212
213 free_stream_buffer: 213 free_stream_buffer:
214 mmap_string_free(f->pop3_stream_buffer); 214 mmap_string_free(f->pop3_stream_buffer);
215 free_f: 215 free_f:
216 free(f); 216 free(f);
217 err: 217 err:
218 return NULL; 218 return NULL;
219} 219}
220 220
221 221
222 222
223void mailpop3_free(mailpop3 * f) 223void mailpop3_free(mailpop3 * f)
224{ 224{
225 if (f->pop3_stream) 225 if (f->pop3_stream)
226 mailpop3_quit(f); 226 mailpop3_quit(f);
227 227
228 mmap_string_free(f->pop3_response_buffer); 228 mmap_string_free(f->pop3_response_buffer);
229 mmap_string_free(f->pop3_stream_buffer); 229 mmap_string_free(f->pop3_stream_buffer);
230 230
231 free(f); 231 free(f);
232} 232}
233 233
234 234
235 235
236 236
237 237
238 238
239 239
240 240
241 241
242 242
243 243
244/* 244/*
245 operations on mailpop3 structure 245 operations on mailpop3 structure
246*/ 246*/
247 247
248#define RESPONSE_OK 0 248#define RESPONSE_OK 0
249#define RESPONSE_ERR -1 249#define RESPONSE_ERR -1
250 250
251static int send_command(mailpop3 * f, char * command); 251static int send_command(mailpop3 * f, char * command);
252 252
253static char * read_line(mailpop3 * f); 253static char * read_line(mailpop3 * f);
254 254
255static char * read_multiline(mailpop3 * f, size_t size, 255static char * read_multiline(mailpop3 * f, size_t size,
256 MMAPString * multiline_buffer); 256 MMAPString * multiline_buffer);
257 257
258static int parse_response(mailpop3 * f, char * response); 258static int parse_response(mailpop3 * f, char * response);
259 259
260 260
261/* get the timestamp in the connection response */ 261/* get the timestamp in the connection response */
262 262
263#define TIMESTAMP_START '<' 263#define TIMESTAMP_START '<'
264#define TIMESTAMP_END '>' 264#define TIMESTAMP_END '>'
265 265
266static char * mailpop3_get_timestamp(char * response) 266static char * mailpop3_get_timestamp(char * response)
267{ 267{
268 char * begin_timestamp; 268 char * begin_timestamp;
269 char * end_timestamp; 269 char * end_timestamp;
270 char * timestamp; 270 char * timestamp;
271 int len_timestamp; 271 int len_timestamp;
272 272
273 if (response == NULL) 273 if (response == NULL)
274 return NULL; 274 return NULL;
275 275
276 begin_timestamp = strchr(response, TIMESTAMP_START); 276 begin_timestamp = strchr(response, TIMESTAMP_START);
277 277
278 end_timestamp = NULL; 278 end_timestamp = NULL;
279 if (begin_timestamp != NULL) { 279 if (begin_timestamp != NULL) {
280 end_timestamp = strchr(begin_timestamp, TIMESTAMP_END); 280 end_timestamp = strchr(begin_timestamp, TIMESTAMP_END);
281 if (end_timestamp == NULL) 281 if (end_timestamp == NULL)
282 begin_timestamp = NULL; 282 begin_timestamp = NULL;
283 } 283 }
284 284
285 if (!begin_timestamp) 285 if (!begin_timestamp)
286 return NULL; 286 return NULL;
287 287
288 len_timestamp = end_timestamp - begin_timestamp + 1; 288 len_timestamp = end_timestamp - begin_timestamp + 1;
289 289
290 timestamp = malloc(len_timestamp + 1); 290 timestamp = malloc(len_timestamp + 1);
291 if (timestamp == NULL) 291 if (timestamp == NULL)
292 return NULL; 292 return NULL;
293 strncpy(timestamp, begin_timestamp, len_timestamp); 293 strncpy(timestamp, begin_timestamp, len_timestamp);
294 timestamp[len_timestamp] = '\0'; 294 timestamp[len_timestamp] = '\0';
295 295
296 return timestamp; 296 return timestamp;
297} 297}
298 298
299/* 299/*
300 connect a stream to the mailpop3 structure 300 connect a stream to the mailpop3 structure
301*/ 301*/
302 302
303int mailpop3_connect(mailpop3 * f, mailstream * s) 303int mailpop3_connect(mailpop3 * f, mailstream * s)
304{ 304{
305 char * response; 305 char * response;
306 int r; 306 int r;
307 char * timestamp; 307 char * timestamp;
308 308
309 if (f->pop3_state != POP3_STATE_DISCONNECTED) 309 if (f->pop3_state != POP3_STATE_DISCONNECTED)
310 return MAILPOP3_ERROR_BAD_STATE; 310 return MAILPOP3_ERROR_BAD_STATE;
311 311
312 f->pop3_stream = s; 312 f->pop3_stream = s;
313 313
314 response = read_line(f); 314 response = read_line(f);
315 315
316 r = parse_response(f, response); 316 r = parse_response(f, response);
317 if (r != RESPONSE_OK) 317 if (r != RESPONSE_OK)
318 return MAILPOP3_ERROR_UNAUTHORIZED; 318 return MAILPOP3_ERROR_UNAUTHORIZED;
319 319
320 f->pop3_state = POP3_STATE_AUTHORIZATION; 320 f->pop3_state = POP3_STATE_AUTHORIZATION;
321 321
322 timestamp = mailpop3_get_timestamp(f->pop3_response); 322 timestamp = mailpop3_get_timestamp(f->pop3_response);
323 if (timestamp != NULL) 323 if (timestamp != NULL)
324 f->pop3_timestamp = timestamp; 324 f->pop3_timestamp = timestamp;
325 325
326 return MAILPOP3_NO_ERROR; 326 return MAILPOP3_NO_ERROR;
327} 327}
328 328
329 329
330/* 330/*
331 disconnect from a pop3 server 331 disconnect from a pop3 server
332*/ 332*/
333 333
334int mailpop3_quit(mailpop3 * f) 334int mailpop3_quit(mailpop3 * f)
335{ 335{
336 char command[POP3_STRING_SIZE]; 336 char command[POP3_STRING_SIZE];
337 char * response; 337 char * response;
338 int r; 338 int r;
339 int res; 339 int res;
340 340
341 if ((f->pop3_state != POP3_STATE_AUTHORIZATION) 341 if ((f->pop3_state != POP3_STATE_AUTHORIZATION)
342 && (f->pop3_state != POP3_STATE_TRANSACTION)) { 342 && (f->pop3_state != POP3_STATE_TRANSACTION)) {
343 res = MAILPOP3_ERROR_BAD_STATE; 343 res = MAILPOP3_ERROR_BAD_STATE;
344 goto close; 344 goto close;
345 } 345 }
346 346
347 snprintf(command, POP3_STRING_SIZE, "QUIT\r\n"); 347 snprintf(command, POP3_STRING_SIZE, "QUIT\r\n");
348 r = send_command(f, command); 348 r = send_command(f, command);
349 if (r == -1) { 349 if (r == -1) {
350 res = MAILPOP3_ERROR_STREAM; 350 res = MAILPOP3_ERROR_STREAM;
351 goto close; 351 goto close;
352 } 352 }
353 353
354 response = read_line(f); 354 response = read_line(f);
355 if (response == NULL) { 355 if (response == NULL) {
356 res = MAILPOP3_ERROR_STREAM; 356 res = MAILPOP3_ERROR_STREAM;
357 goto close; 357 goto close;
358 } 358 }
359 parse_response(f, response); 359 parse_response(f, response);
360 360
361 res = MAILPOP3_NO_ERROR; 361 res = MAILPOP3_NO_ERROR;
362 362
363 close: 363 close:
364 mailstream_close(f->pop3_stream); 364 mailstream_close(f->pop3_stream);
365 365
366 if (f->pop3_timestamp != NULL) { 366 if (f->pop3_timestamp != NULL) {
367 free(f->pop3_timestamp); 367 free(f->pop3_timestamp);
368 f->pop3_timestamp = NULL; 368 f->pop3_timestamp = NULL;
369 } 369 }
370 370
371 f->pop3_stream = NULL; 371 f->pop3_stream = NULL;
372 if (f->pop3_msg_tab != NULL) { 372 if (f->pop3_msg_tab != NULL) {
373 mailpop3_msg_info_tab_free(f->pop3_msg_tab); 373 mailpop3_msg_info_tab_free(f->pop3_msg_tab);
374 f->pop3_msg_tab = NULL; 374 f->pop3_msg_tab = NULL;
375 } 375 }
376 376
377 f->pop3_state = POP3_STATE_DISCONNECTED; 377 f->pop3_state = POP3_STATE_DISCONNECTED;
378 378
379 return res; 379 return res;
380} 380}
381 381
382 382
383 383
384 384
385 385
386 386
387 387
388 388
389 389
390 390
391 391
392 392
393 393
394 394
395 395
396 396
397 397
398 398
399 399
400 400
401 401
402 402
403 403
404 404
405 405
406 406
407 407
408 408
409 409
410 410
411 411
412 412
413int mailpop3_apop(mailpop3 * f, 413int mailpop3_apop(mailpop3 * f,
414 const char * user, const char * password) 414 const char * user, const char * password)
415{ 415{
416 char command[POP3_STRING_SIZE]; 416 char command[POP3_STRING_SIZE];
417 MD5_CTX md5context; 417 MD5_CTX md5context;
418 unsigned char md5digest[16]; 418 unsigned char md5digest[16];
419 char md5string[33]; 419 char md5string[33];
420 char * cmd_ptr; 420 char * cmd_ptr;
421 int r; 421 int r;
422 int i; 422 int i;
423 char * response; 423 char * response;
424 424
425 if (f->pop3_state != POP3_STATE_AUTHORIZATION) 425 if (f->pop3_state != POP3_STATE_AUTHORIZATION)
426 return MAILPOP3_ERROR_BAD_STATE; 426 return MAILPOP3_ERROR_BAD_STATE;
427 427
428 if (f->pop3_timestamp == NULL) 428 if (f->pop3_timestamp == NULL)
429 return MAILPOP3_ERROR_APOP_NOT_SUPPORTED; 429 return MAILPOP3_ERROR_APOP_NOT_SUPPORTED;
430 430
431 /* calculate md5 sum */ 431 /* calculate md5 sum */
432 432
433 MD5Init(&md5context); 433 MD5Init(&md5context);
434 MD5Update(&md5context, f->pop3_timestamp, strlen (f->pop3_timestamp)); 434 MD5Update(&md5context, f->pop3_timestamp, strlen (f->pop3_timestamp));
435 MD5Update(&md5context, password, strlen (password)); 435 MD5Update(&md5context, password, strlen (password));
436 MD5Final(md5digest, &md5context); 436 MD5Final(md5digest, &md5context);
437 437
438 cmd_ptr = md5string; 438 cmd_ptr = md5string;
439 for(i = 0 ; i < 16 ; i++, cmd_ptr += 2) 439 for(i = 0 ; i < 16 ; i++, cmd_ptr += 2)
440 snprintf(cmd_ptr, 3, "%02x", md5digest[i]); 440 snprintf(cmd_ptr, 3, "%02x", md5digest[i]);
441 * cmd_ptr = 0; 441 * cmd_ptr = 0;
442 442
443 /* send apop command */ 443 /* send apop command */
444 444
445 snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string); 445 snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string);
446 r = send_command(f, command); 446 r = send_command(f, command);
447 if (r == -1) 447 if (r == -1)
448 return MAILPOP3_ERROR_STREAM; 448 return MAILPOP3_ERROR_STREAM;
449 449
450 response = read_line(f); 450 response = read_line(f);
451 451
452 if (response == NULL) 452 if (response == NULL)
453 return MAILPOP3_ERROR_STREAM; 453 return MAILPOP3_ERROR_STREAM;
454 r = parse_response(f, response); 454 r = parse_response(f, response);
455 if (r != RESPONSE_OK) 455 if (r != RESPONSE_OK)
456 return MAILPOP3_ERROR_DENIED; 456 return MAILPOP3_ERROR_DENIED;
457 457
458 f->pop3_state = POP3_STATE_TRANSACTION; 458 f->pop3_state = POP3_STATE_TRANSACTION;
459 459
460 return MAILPOP3_NO_ERROR; 460 return MAILPOP3_NO_ERROR;
461} 461}
462 462
463int mailpop3_user(mailpop3 * f, const char * user) 463int mailpop3_user(mailpop3 * f, const char * user)
464{ 464{
465 char command[POP3_STRING_SIZE]; 465 char command[POP3_STRING_SIZE];
466 int r; 466 int r;
467 char * response; 467 char * response;
468 468
469 if (f->pop3_state != POP3_STATE_AUTHORIZATION) 469 if (f->pop3_state != POP3_STATE_AUTHORIZATION)
470 return MAILPOP3_ERROR_BAD_STATE; 470 return MAILPOP3_ERROR_BAD_STATE;
471 471
472 /* send user command */ 472 /* send user command */
473 473
474 snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user); 474 snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user);
475 r = send_command(f, command); 475 r = send_command(f, command);
476 if (r == -1) 476 if (r == -1)
477 return MAILPOP3_ERROR_STREAM; 477 return MAILPOP3_ERROR_STREAM;
478 478
479 response = read_line(f); 479 response = read_line(f);
480 if (response == NULL) 480 if (response == NULL)
481 return MAILPOP3_ERROR_STREAM; 481 return MAILPOP3_ERROR_STREAM;
482 r = parse_response(f, response); 482 r = parse_response(f, response);
483 483
484 if (r != RESPONSE_OK) 484 if (r != RESPONSE_OK)
485 return MAILPOP3_ERROR_BAD_USER; 485 return MAILPOP3_ERROR_BAD_USER;
486 486
487 return MAILPOP3_NO_ERROR; 487 return MAILPOP3_NO_ERROR;
488} 488}
489 489
490int mailpop3_pass(mailpop3 * f, const char * password) 490int mailpop3_pass(mailpop3 * f, const char * password)
491{ 491{
492 char command[POP3_STRING_SIZE]; 492 char command[POP3_STRING_SIZE];
493 int r; 493 int r;
494 char * response; 494 char * response;
495 495
496 if (f->pop3_state != POP3_STATE_AUTHORIZATION) 496 if (f->pop3_state != POP3_STATE_AUTHORIZATION)
497 return MAILPOP3_ERROR_BAD_STATE; 497 return MAILPOP3_ERROR_BAD_STATE;
498 498
499 /* send password command */ 499 /* send password command */
500 500
501 snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password); 501 snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password);
502 r = send_command(f, command); 502 r = send_command(f, command);
503 if (r == -1) 503 if (r == -1)
504 return MAILPOP3_ERROR_STREAM; 504 return MAILPOP3_ERROR_STREAM;
505 505
506 response = read_line(f); 506 response = read_line(f);
507 if (response == NULL) 507 if (response == NULL)
508 return MAILPOP3_ERROR_STREAM; 508 return MAILPOP3_ERROR_STREAM;
509 r = parse_response(f, response); 509 r = parse_response(f, response);
510 510
511 if (r != RESPONSE_OK) 511 if (r != RESPONSE_OK) {
512 return MAILPOP3_ERROR_BAD_PASSWORD; 512 // LR
513 fprintf(stderr,"POP3 login error. Response from server:\n%s\n",response );
514 return MAILPOP3_ERROR_BAD_PASSWORD;
515 }
513 516
514 f->pop3_state = POP3_STATE_TRANSACTION; 517 f->pop3_state = POP3_STATE_TRANSACTION;
515 518
516 return MAILPOP3_NO_ERROR; 519 return MAILPOP3_NO_ERROR;
517} 520}
518 521
519static int read_list(mailpop3 * f, carray ** result); 522static int read_list(mailpop3 * f, carray ** result);
520 523
521 524
522 525
523static int read_uidl(mailpop3 * f, carray * msg_tab); 526static int read_uidl(mailpop3 * f, carray * msg_tab);
524 527
525 528
526 529
527static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab) 530static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab)
528{ 531{
529 char command[POP3_STRING_SIZE]; 532 char command[POP3_STRING_SIZE];
530 int r; 533 int r;
531 char * response; 534 char * response;
532 535
533 if (f->pop3_state != POP3_STATE_TRANSACTION) 536 if (f->pop3_state != POP3_STATE_TRANSACTION)
534 return MAILPOP3_ERROR_BAD_STATE; 537 return MAILPOP3_ERROR_BAD_STATE;
535 538
536 /* send list command */ 539 /* send list command */
537 540
538 snprintf(command, POP3_STRING_SIZE, "UIDL\r\n"); 541 snprintf(command, POP3_STRING_SIZE, "UIDL\r\n");
539 r = send_command(f, command); 542 r = send_command(f, command);
540 if (r == -1) 543 if (r == -1)
541 return MAILPOP3_ERROR_STREAM; 544 return MAILPOP3_ERROR_STREAM;
542 545
543 response = read_line(f); 546 response = read_line(f);
544 if (response == NULL) 547 if (response == NULL)
545 return MAILPOP3_ERROR_STREAM; 548 return MAILPOP3_ERROR_STREAM;
546 r = parse_response(f, response); 549 r = parse_response(f, response);
547 550
548 if (r != RESPONSE_OK) 551 if (r != RESPONSE_OK)
549 return MAILPOP3_ERROR_CANT_LIST; 552 return MAILPOP3_ERROR_CANT_LIST;
550 553
551 r = read_uidl(f, msg_tab); 554 r = read_uidl(f, msg_tab);
552 if (r != MAILPOP3_NO_ERROR) 555 if (r != MAILPOP3_NO_ERROR)
553 return r; 556 return r;
554 557
555 return MAILPOP3_NO_ERROR; 558 return MAILPOP3_NO_ERROR;
556} 559}
557 560
558 561
559 562
560static int mailpop3_do_list(mailpop3 * f) 563static int mailpop3_do_list(mailpop3 * f)
561{ 564{
562 char command[POP3_STRING_SIZE]; 565 char command[POP3_STRING_SIZE];
563 int r; 566 int r;
564 carray * msg_tab; 567 carray * msg_tab;
565 char * response; 568 char * response;
566 569
567 if (f->pop3_msg_tab != NULL) { 570 if (f->pop3_msg_tab != NULL) {
568 mailpop3_msg_info_tab_free(f->pop3_msg_tab); 571 mailpop3_msg_info_tab_free(f->pop3_msg_tab);
569 f->pop3_msg_tab = NULL; 572 f->pop3_msg_tab = NULL;
570 } 573 }
571 574
572 if (f->pop3_state != POP3_STATE_TRANSACTION) 575 if (f->pop3_state != POP3_STATE_TRANSACTION)
573 return MAILPOP3_ERROR_BAD_STATE; 576 return MAILPOP3_ERROR_BAD_STATE;
574 577
575 /* send list command */ 578 /* send list command */
576 579
577 snprintf(command, POP3_STRING_SIZE, "LIST\r\n"); 580 snprintf(command, POP3_STRING_SIZE, "LIST\r\n");
578 r = send_command(f, command); 581 r = send_command(f, command);
579 if (r == -1) 582 if (r == -1)
580 return MAILPOP3_ERROR_STREAM; 583 return MAILPOP3_ERROR_STREAM;
581 584
582 response = read_line(f); 585 response = read_line(f);
583 if (response == NULL) 586 if (response == NULL)
584 return MAILPOP3_ERROR_STREAM; 587 return MAILPOP3_ERROR_STREAM;
585 r = parse_response(f, response); 588 r = parse_response(f, response);
586 589
587 if (r != RESPONSE_OK) 590 if (r != RESPONSE_OK)
588 return MAILPOP3_ERROR_CANT_LIST; 591 return MAILPOP3_ERROR_CANT_LIST;
589 592
590 r = read_list(f, &msg_tab); 593 r = read_list(f, &msg_tab);
591 if (r != MAILPOP3_NO_ERROR) 594 if (r != MAILPOP3_NO_ERROR)
592 return r; 595 return r;
593 596
594 f->pop3_msg_tab = msg_tab; 597 f->pop3_msg_tab = msg_tab;
595 f->pop3_deleted_count = 0; 598 f->pop3_deleted_count = 0;
596 599
597 mailpop3_do_uidl(f, msg_tab); 600 mailpop3_do_uidl(f, msg_tab);
598 601
599 return MAILPOP3_NO_ERROR; 602 return MAILPOP3_NO_ERROR;
600} 603}
601 604
602 605
603 606
604static void mailpop3_list_if_needed(mailpop3 * f) 607static void mailpop3_list_if_needed(mailpop3 * f)
605{ 608{
606 if (f->pop3_msg_tab == NULL) 609 if (f->pop3_msg_tab == NULL)
607 mailpop3_do_list(f); 610 mailpop3_do_list(f);
608} 611}
609 612
610/* 613/*
611 mailpop3_list 614 mailpop3_list
612*/ 615*/
613 616
614void mailpop3_list(mailpop3 * f, carray ** result) 617void mailpop3_list(mailpop3 * f, carray ** result)
615{ 618{
616 mailpop3_list_if_needed(f); 619 mailpop3_list_if_needed(f);
617 * result = f->pop3_msg_tab; 620 * result = f->pop3_msg_tab;
618} 621}
619 622
620static inline struct mailpop3_msg_info * 623static inline struct mailpop3_msg_info *
621find_msg(mailpop3 * f, unsigned int index) 624find_msg(mailpop3 * f, unsigned int index)
622{ 625{
623 mailpop3_list_if_needed(f); 626 mailpop3_list_if_needed(f);
624 627
625 if (f->pop3_msg_tab == NULL) 628 if (f->pop3_msg_tab == NULL)
626 return NULL; 629 return NULL;
627 630
628 return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, index); 631 return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, index);
629} 632}
630 633
631 634
632 635
633 636
634 637
635 638
636 639
637 640
638static void mailpop3_multiline_response_free(char * str) 641static void mailpop3_multiline_response_free(char * str)
639{ 642{
640 mmap_string_unref(str); 643 mmap_string_unref(str);
641} 644}
642 645
643void mailpop3_top_free(char * str) 646void mailpop3_top_free(char * str)
644{ 647{
645 mailpop3_multiline_response_free(str); 648 mailpop3_multiline_response_free(str);
646} 649}
647 650
648void mailpop3_retr_free(char * str) 651void mailpop3_retr_free(char * str)
649{ 652{
650 mailpop3_multiline_response_free(str); 653 mailpop3_multiline_response_free(str);
651} 654}
652 655
653/* 656/*
654 mailpop3_retr 657 mailpop3_retr
655 658
656 message content in (* result) is still there until the 659 message content in (* result) is still there until the
657 next retrieve or top operation on the mailpop3 structure 660 next retrieve or top operation on the mailpop3 structure
658*/ 661*/
659 662
660static int 663static int
661mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo, 664mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo,
662 char ** result, size_t * result_len) 665 char ** result, size_t * result_len)
663{ 666{
664 char * response; 667 char * response;
665 char * result_multiline; 668 char * result_multiline;
666 MMAPString * buffer; 669 MMAPString * buffer;
667 int r; 670 int r;
668 671
669 response = read_line(f); 672 response = read_line(f);
670 if (response == NULL) 673 if (response == NULL)
671 return MAILPOP3_ERROR_STREAM; 674 return MAILPOP3_ERROR_STREAM;
672 r = parse_response(f, response); 675 r = parse_response(f, response);
673 if (r != RESPONSE_OK) 676 if (r != RESPONSE_OK)
674 return MAILPOP3_ERROR_NO_SUCH_MESSAGE; 677 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
675 678
676 buffer = mmap_string_new(""); 679 buffer = mmap_string_new("");
677 if (buffer == NULL) 680 if (buffer == NULL)
678 return MAILPOP3_ERROR_MEMORY; 681 return MAILPOP3_ERROR_MEMORY;
679 682
680 result_multiline = read_multiline(f, msginfo->msg_size, buffer); 683 result_multiline = read_multiline(f, msginfo->msg_size, buffer);
681 if (result_multiline == NULL) { 684 if (result_multiline == NULL) {
682 mmap_string_free(buffer); 685 mmap_string_free(buffer);
683 return MAILPOP3_ERROR_STREAM; 686 return MAILPOP3_ERROR_STREAM;
684 } 687 }
685 else { 688 else {
686 r = mmap_string_ref(buffer); 689 r = mmap_string_ref(buffer);
687 if (r < 0) { 690 if (r < 0) {
688 mmap_string_free(buffer); 691 mmap_string_free(buffer);
689 return MAILPOP3_ERROR_MEMORY; 692 return MAILPOP3_ERROR_MEMORY;
690 } 693 }
691 694
692 * result = result_multiline; 695 * result = result_multiline;
693 * result_len = buffer->len; 696 * result_len = buffer->len;
694 return MAILPOP3_NO_ERROR; 697 return MAILPOP3_NO_ERROR;
695 } 698 }
696} 699}
697 700
698int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result, 701int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result,
699 size_t * result_len) 702 size_t * result_len)
700{ 703{
701 char command[POP3_STRING_SIZE]; 704 char command[POP3_STRING_SIZE];
702 struct mailpop3_msg_info * msginfo; 705 struct mailpop3_msg_info * msginfo;
703 int r; 706 int r;
704 707
705 if (f->pop3_state != POP3_STATE_TRANSACTION) 708 if (f->pop3_state != POP3_STATE_TRANSACTION)
706 return MAILPOP3_ERROR_BAD_STATE; 709 return MAILPOP3_ERROR_BAD_STATE;
707 710
708 msginfo = find_msg(f, index); 711 msginfo = find_msg(f, index);
709 712
710 if (msginfo == NULL) { 713 if (msginfo == NULL) {
711 f->pop3_response = NULL; 714 f->pop3_response = NULL;
712 return MAILPOP3_ERROR_NO_SUCH_MESSAGE; 715 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
713 } 716 }
714 717
715 snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", index); 718 snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", index);
716 r = send_command(f, command); 719 r = send_command(f, command);
717 if (r == -1) 720 if (r == -1)
718 return MAILPOP3_ERROR_STREAM; 721 return MAILPOP3_ERROR_STREAM;
719 722
720 return mailpop3_get_content(f, msginfo, result, result_len); 723 return mailpop3_get_content(f, msginfo, result, result_len);
721} 724}
722 725
723int mailpop3_top(mailpop3 * f, unsigned int index, 726int mailpop3_top(mailpop3 * f, unsigned int index,
724 unsigned int count, char ** result, 727 unsigned int count, char ** result,
725 size_t * result_len) 728 size_t * result_len)
726{ 729{
727 char command[POP3_STRING_SIZE]; 730 char command[POP3_STRING_SIZE];
728 struct mailpop3_msg_info * msginfo; 731 struct mailpop3_msg_info * msginfo;
729 int r; 732 int r;
730 733
731 if (f->pop3_state != POP3_STATE_TRANSACTION) 734 if (f->pop3_state != POP3_STATE_TRANSACTION)
732 return MAILPOP3_ERROR_BAD_STATE; 735 return MAILPOP3_ERROR_BAD_STATE;
733 736
734 msginfo = find_msg(f, index); 737 msginfo = find_msg(f, index);
735 738
736 if (msginfo == NULL) { 739 if (msginfo == NULL) {
737 f->pop3_response = NULL; 740 f->pop3_response = NULL;
738 return MAILPOP3_ERROR_NO_SUCH_MESSAGE; 741 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
739 } 742 }
740 743
741 snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", index, count); 744 snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", index, count);
742 r = send_command(f, command); 745 r = send_command(f, command);
743 if (r == -1) 746 if (r == -1)
744 return MAILPOP3_ERROR_STREAM; 747 return MAILPOP3_ERROR_STREAM;
745 748
746 return mailpop3_get_content(f, msginfo, result, result_len); 749 return mailpop3_get_content(f, msginfo, result, result_len);
747} 750}
748 751
749int mailpop3_dele(mailpop3 * f, unsigned int index) 752int mailpop3_dele(mailpop3 * f, unsigned int index)
750{ 753{
751 char command[POP3_STRING_SIZE]; 754 char command[POP3_STRING_SIZE];
752 struct mailpop3_msg_info * msginfo; 755 struct mailpop3_msg_info * msginfo;
753 char * response; 756 char * response;
754 int r; 757 int r;
755 758
756 if (f->pop3_state != POP3_STATE_TRANSACTION) 759 if (f->pop3_state != POP3_STATE_TRANSACTION)
757 return MAILPOP3_ERROR_BAD_STATE; 760 return MAILPOP3_ERROR_BAD_STATE;
758 761
759 msginfo = find_msg(f, index); 762 msginfo = find_msg(f, index);
760 763
761 if (msginfo == NULL) { 764 if (msginfo == NULL) {
762 f->pop3_response = NULL; 765 f->pop3_response = NULL;
763 return MAILPOP3_ERROR_NO_SUCH_MESSAGE; 766 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
764 } 767 }
765 768
766 snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", index); 769 snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", index);
767 r = send_command(f, command); 770 r = send_command(f, command);
768 if (r == -1) 771 if (r == -1)
769 return MAILPOP3_ERROR_STREAM; 772 return MAILPOP3_ERROR_STREAM;
770 773
771 response = read_line(f); 774 response = read_line(f);
772 if (response == NULL) 775 if (response == NULL)
773 return MAILPOP3_ERROR_STREAM; 776 return MAILPOP3_ERROR_STREAM;
774 r = parse_response(f, response); 777 r = parse_response(f, response);
775 if (r != RESPONSE_OK) 778 if (r != RESPONSE_OK)
776 return MAILPOP3_ERROR_NO_SUCH_MESSAGE; 779 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
777 780
778 msginfo->msg_deleted = TRUE; 781 msginfo->msg_deleted = TRUE;
779 f->pop3_deleted_count ++; 782 f->pop3_deleted_count ++;
780 783
781 return MAILPOP3_NO_ERROR; 784 return MAILPOP3_NO_ERROR;
782} 785}
783 786
784int mailpop3_noop(mailpop3 * f) 787int mailpop3_noop(mailpop3 * f)
785{ 788{
786 char command[POP3_STRING_SIZE]; 789 char command[POP3_STRING_SIZE];
787 char * response; 790 char * response;
788 int r; 791 int r;
789 792
790 if (f->pop3_state != POP3_STATE_TRANSACTION) 793 if (f->pop3_state != POP3_STATE_TRANSACTION)
791 return MAILPOP3_ERROR_BAD_STATE; 794 return MAILPOP3_ERROR_BAD_STATE;
792 795
793 snprintf(command, POP3_STRING_SIZE, "NOOP\r\n"); 796 snprintf(command, POP3_STRING_SIZE, "NOOP\r\n");
794 r = send_command(f, command); 797 r = send_command(f, command);
795 if (r == -1) 798 if (r == -1)
796 return MAILPOP3_ERROR_STREAM; 799 return MAILPOP3_ERROR_STREAM;
797 800
798 response = read_line(f); 801 response = read_line(f);
799 if (response == NULL) 802 if (response == NULL)
800 return MAILPOP3_ERROR_STREAM; 803 return MAILPOP3_ERROR_STREAM;
801 parse_response(f, response); 804 parse_response(f, response);
802 805
803 return MAILPOP3_NO_ERROR; 806 return MAILPOP3_NO_ERROR;
804} 807}
805 808
806int mailpop3_rset(mailpop3 * f) 809int mailpop3_rset(mailpop3 * f)
807{ 810{
808 char command[POP3_STRING_SIZE]; 811 char command[POP3_STRING_SIZE];
809 char * response; 812 char * response;
810 int r; 813 int r;
811 814
812 if (f->pop3_state != POP3_STATE_TRANSACTION) 815 if (f->pop3_state != POP3_STATE_TRANSACTION)
813 return MAILPOP3_ERROR_BAD_STATE; 816 return MAILPOP3_ERROR_BAD_STATE;
814 817
815 snprintf(command, POP3_STRING_SIZE, "RSET\r\n"); 818 snprintf(command, POP3_STRING_SIZE, "RSET\r\n");
816 r = send_command(f, command); 819 r = send_command(f, command);
817 if (r == -1) 820 if (r == -1)
818 return MAILPOP3_ERROR_STREAM; 821 return MAILPOP3_ERROR_STREAM;
819 822
820 response = read_line(f); 823 response = read_line(f);
821 if (response == NULL) 824 if (response == NULL)
822 return MAILPOP3_ERROR_STREAM; 825 return MAILPOP3_ERROR_STREAM;
823 parse_response(f, response); 826 parse_response(f, response);
824 827
825 if (f->pop3_msg_tab != NULL) { 828 if (f->pop3_msg_tab != NULL) {
826 mailpop3_msg_info_tab_reset(f->pop3_msg_tab); 829 mailpop3_msg_info_tab_reset(f->pop3_msg_tab);
827 f->pop3_deleted_count = 0; 830 f->pop3_deleted_count = 0;
828 } 831 }
829 832
830 return MAILPOP3_NO_ERROR; 833 return MAILPOP3_NO_ERROR;
831} 834}
832 835
833 836
834 837
835static int read_capa_resp(mailpop3 * f, clist ** result); 838static int read_capa_resp(mailpop3 * f, clist ** result);
836 839
837int mailpop3_capa(mailpop3 * f, clist ** result) 840int mailpop3_capa(mailpop3 * f, clist ** result)
838{ 841{
839 clist * capa_list; 842 clist * capa_list;
840 char command[POP3_STRING_SIZE]; 843 char command[POP3_STRING_SIZE];
841 int r; 844 int r;
842 char * response; 845 char * response;
843 846
844 snprintf(command, POP3_STRING_SIZE, "CAPA\r\n"); 847 snprintf(command, POP3_STRING_SIZE, "CAPA\r\n");
845 r = send_command(f, command); 848 r = send_command(f, command);
846 if (r == -1) 849 if (r == -1)
847 return MAILPOP3_ERROR_STREAM; 850 return MAILPOP3_ERROR_STREAM;
848 851
849 response = read_line(f); 852 response = read_line(f);
850 if (response == NULL) 853 if (response == NULL)
851 return MAILPOP3_ERROR_STREAM; 854 return MAILPOP3_ERROR_STREAM;
852 r = parse_response(f, response); 855 r = parse_response(f, response);
853 856
854 if (r != RESPONSE_OK) 857 if (r != RESPONSE_OK)
855 return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED; 858 return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED;
856 859
857 r = read_capa_resp(f, &capa_list); 860 r = read_capa_resp(f, &capa_list);
858 if (r != MAILPOP3_NO_ERROR) 861 if (r != MAILPOP3_NO_ERROR)
859 return r; 862 return r;
860 863
861 * result = capa_list; 864 * result = capa_list;
862 865
863 return MAILPOP3_NO_ERROR; 866 return MAILPOP3_NO_ERROR;
864} 867}
865 868
866void mailpop3_capa_resp_free(clist * capa_list) 869void mailpop3_capa_resp_free(clist * capa_list)
867{ 870{
868 clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL); 871 clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL);
869 clist_free(capa_list); 872 clist_free(capa_list);
870} 873}
871 874
872int mailpop3_stls(mailpop3 * f) 875int mailpop3_stls(mailpop3 * f)
873{ 876{
874 char command[POP3_STRING_SIZE]; 877 char command[POP3_STRING_SIZE];
875 int r; 878 int r;
876 char * response; 879 char * response;
877 880
878 snprintf(command, POP3_STRING_SIZE, "STLS\r\n"); 881 snprintf(command, POP3_STRING_SIZE, "STLS\r\n");
879 r = send_command(f, command); 882 r = send_command(f, command);
880 if (r == -1) 883 if (r == -1)
881 return MAILPOP3_ERROR_STREAM; 884 return MAILPOP3_ERROR_STREAM;
882 885
883 response = read_line(f); 886 response = read_line(f);
884 if (response == NULL) 887 if (response == NULL)
885 return MAILPOP3_ERROR_STREAM; 888 return MAILPOP3_ERROR_STREAM;
886 r = parse_response(f, response); 889 r = parse_response(f, response);
887 890
888 if (r != RESPONSE_OK) 891 if (r != RESPONSE_OK)
889 return MAILPOP3_ERROR_STLS_NOT_SUPPORTED; 892 return MAILPOP3_ERROR_STLS_NOT_SUPPORTED;
890 893
891 return MAILPOP3_NO_ERROR; 894 return MAILPOP3_NO_ERROR;
892} 895}
893 896
894 897
895 898
896 899
897 900
898 901
899 902
900 903
901 904
902 905
903 906
904 907
905 908
906 909
907 910
908 911
909 912
910 913
911 914
912 915
913 916
914 917
915 918
916 919
917#define RESP_OK_STR "+OK" 920#define RESP_OK_STR "+OK"
918#define RESP_ERR_STR "-ERR" 921#define RESP_ERR_STR "-ERR"
919 922
920 923
921static int parse_space(char ** line) 924static int parse_space(char ** line)
922{ 925{
923 char * p; 926 char * p;
924 927
925 p = * line; 928 p = * line;
926 929
927 while ((* p == ' ') || (* p == '\t')) 930 while ((* p == ' ') || (* p == '\t'))
928 p ++; 931 p ++;
929 932
930 if (p != * line) { 933 if (p != * line) {
931 * line = p; 934 * line = p;
932 return TRUE; 935 return TRUE;
933 } 936 }
934 else 937 else
935 return FALSE; 938 return FALSE;
936} 939}
937 940
938static char * cut_token(char * line) 941static char * cut_token(char * line)
939{ 942{
940 char * p; 943 char * p;
941 char * p_tab; 944 char * p_tab;
942 char * p_space; 945 char * p_space;
943 946
944 p = line; 947 p = line;
945 948
946 p_space = strchr(line, ' '); 949 p_space = strchr(line, ' ');
947 p_tab = strchr(line, '\t'); 950 p_tab = strchr(line, '\t');
948 if (p_tab == NULL) 951 if (p_tab == NULL)
949 p = p_space; 952 p = p_space;
950 else if (p_space == NULL) 953 else if (p_space == NULL)
951 p = p_tab; 954 p = p_tab;
952 else { 955 else {
953 if (p_tab < p_space) 956 if (p_tab < p_space)
954 p = p_tab; 957 p = p_tab;
955 else 958 else
956 p = p_space; 959 p = p_space;
957 } 960 }
958 if (p == NULL) 961 if (p == NULL)
959 return NULL; 962 return NULL;
960 * p = 0; 963 * p = 0;
961 p ++; 964 p ++;
962 965
963 return p; 966 return p;
964} 967}
965 968
966 969
967static int parse_response(mailpop3 * f, char * response) 970static int parse_response(mailpop3 * f, char * response)
968{ 971{
969 char * msg; 972 char * msg;
970 973
971 if (response == NULL) { 974 if (response == NULL) {
972 f->pop3_response = NULL; 975 f->pop3_response = NULL;
973 return RESPONSE_ERR; 976 return RESPONSE_ERR;
974 } 977 }
975 978
976 if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) { 979 if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) {
977 980
978 if (response[strlen(RESP_OK_STR)] == ' ') 981 if (response[strlen(RESP_OK_STR)] == ' ')
979 msg = response + strlen(RESP_OK_STR) + 1; 982 msg = response + strlen(RESP_OK_STR) + 1;
980 else 983 else
981 msg = response + strlen(RESP_OK_STR); 984 msg = response + strlen(RESP_OK_STR);
982 985
983 if (mmap_string_assign(f->pop3_response_buffer, msg)) 986 if (mmap_string_assign(f->pop3_response_buffer, msg))
984 f->pop3_response = f->pop3_response_buffer->str; 987 f->pop3_response = f->pop3_response_buffer->str;
985 else 988 else
986 f->pop3_response = NULL; 989 f->pop3_response = NULL;
987 990
988 return RESPONSE_OK; 991 return RESPONSE_OK;
989 } 992 }
990 else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) { 993 else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) {
991 994
992 if (response[strlen(RESP_ERR_STR)] == ' ') 995 if (response[strlen(RESP_ERR_STR)] == ' ')
993 msg = response + strlen(RESP_ERR_STR) + 1; 996 msg = response + strlen(RESP_ERR_STR) + 1;
994 else 997 else
995 msg = response + strlen(RESP_ERR_STR); 998 msg = response + strlen(RESP_ERR_STR);
996 999
997 if (mmap_string_assign(f->pop3_response_buffer, msg)) 1000 if (mmap_string_assign(f->pop3_response_buffer, msg))
998 f->pop3_response = f->pop3_response_buffer->str; 1001 f->pop3_response = f->pop3_response_buffer->str;
999 else 1002 else
1000 f->pop3_response = NULL; 1003 f->pop3_response = NULL;
1001 } 1004 }
1002 1005
1003 f->pop3_response = NULL; 1006 f->pop3_response = NULL;
1004 return RESPONSE_ERR; 1007 return RESPONSE_ERR;
1005} 1008}
1006 1009
1007 1010
1008 1011
1009 1012
1010 1013
1011 1014
1012 1015
1013static int read_list(mailpop3 * f, carray ** result) 1016static int read_list(mailpop3 * f, carray ** result)
1014{ 1017{
1015 unsigned int index; 1018 unsigned int index;
1016 uint32_t size; 1019 uint32_t size;
1017 carray * msg_tab; 1020 carray * msg_tab;
1018 struct mailpop3_msg_info * msg; 1021 struct mailpop3_msg_info * msg;
1019 char * line; 1022 char * line;
1020 1023
1021 msg_tab = carray_new(128); 1024 msg_tab = carray_new(128);
1022 if (msg_tab == NULL) 1025 if (msg_tab == NULL)
1023 goto err; 1026 goto err;
1024 1027
1025 while (1) { 1028 while (1) {
1026 line = read_line(f); 1029 line = read_line(f);
1027 if (line == NULL) 1030 if (line == NULL)
1028 goto free_list; 1031 goto free_list;
1029 1032
1030 if (mailstream_is_end_multiline(line)) 1033 if (mailstream_is_end_multiline(line))
1031 break; 1034 break;
1032 1035
1033 index = strtol(line, &line, 10); 1036 index = strtol(line, &line, 10);
1034 1037
1035 if (!parse_space(&line)) 1038 if (!parse_space(&line))
1036 continue; 1039 continue;
1037 1040
1038 size = strtol(line, &line, 10); 1041 size = strtol(line, &line, 10);
1039 1042
1040 msg = mailpop3_msg_info_new(index, size, NULL); 1043 msg = mailpop3_msg_info_new(index, size, NULL);
1041 if (msg == NULL) 1044 if (msg == NULL)
1042 goto free_list; 1045 goto free_list;
1043 1046
1044 if (carray_count(msg_tab) < index) { 1047 if (carray_count(msg_tab) < index) {
1045 int r; 1048 int r;
1046 1049
1047 r = carray_set_size(msg_tab, index); 1050 r = carray_set_size(msg_tab, index);
1048 if (r == -1) 1051 if (r == -1)
1049 goto free_list; 1052 goto free_list;
1050 } 1053 }
1051 1054
1052 carray_set(msg_tab, index - 1, msg); 1055 carray_set(msg_tab, index - 1, msg);
1053 } 1056 }
1054 1057
1055 * result = msg_tab; 1058 * result = msg_tab;
1056 1059
1057 return MAILPOP3_NO_ERROR; 1060 return MAILPOP3_NO_ERROR;
1058 1061
1059 free_list: 1062 free_list:
1060 mailpop3_msg_info_tab_free(msg_tab); 1063 mailpop3_msg_info_tab_free(msg_tab);
1061 err: 1064 err:
1062 return MAILPOP3_ERROR_STREAM; 1065 return MAILPOP3_ERROR_STREAM;
1063} 1066}
1064 1067
1065 1068
1066 1069
1067static int read_uidl(mailpop3 * f, carray * msg_tab) 1070static int read_uidl(mailpop3 * f, carray * msg_tab)
1068{ 1071{
1069 unsigned int index; 1072 unsigned int index;
1070 struct mailpop3_msg_info * msg; 1073 struct mailpop3_msg_info * msg;
1071 char * line; 1074 char * line;
1072 1075
1073 while (1) { 1076 while (1) {
1074 char * uidl; 1077 char * uidl;
1075 1078
1076 line = read_line(f); 1079 line = read_line(f);
1077 if (line == NULL) 1080 if (line == NULL)
1078 goto err; 1081 goto err;
1079 1082
1080 if (mailstream_is_end_multiline(line)) 1083 if (mailstream_is_end_multiline(line))
1081 break; 1084 break;
1082 1085
1083 index = strtol(line, &line, 10); 1086 index = strtol(line, &line, 10);
1084 1087
1085 if (!parse_space(&line)) 1088 if (!parse_space(&line))
1086 continue; 1089 continue;
1087 1090
1088 uidl = strdup(line); 1091 uidl = strdup(line);
1089 if (uidl == NULL) 1092 if (uidl == NULL)
1090 continue; 1093 continue;
1091 1094
1092 if (index > carray_count(msg_tab)) { 1095 if (index > carray_count(msg_tab)) {
1093 free(uidl); 1096 free(uidl);
1094 continue; 1097 continue;
1095 } 1098 }
1096 1099
1097 msg = carray_get(msg_tab, index - 1); 1100 msg = carray_get(msg_tab, index - 1);
1098 if (msg == NULL) { 1101 if (msg == NULL) {
1099 free(uidl); 1102 free(uidl);
1100 continue; 1103 continue;
1101 } 1104 }
1102 1105
1103 msg->msg_uidl = uidl; 1106 msg->msg_uidl = uidl;
1104 } 1107 }
1105 1108
1106 return MAILPOP3_NO_ERROR; 1109 return MAILPOP3_NO_ERROR;
1107 1110
1108 err: 1111 err:
1109 return MAILPOP3_ERROR_STREAM; 1112 return MAILPOP3_ERROR_STREAM;
1110} 1113}
1111 1114
1112 1115
1113 1116
1114static int read_capa_resp(mailpop3 * f, clist ** result) 1117static int read_capa_resp(mailpop3 * f, clist ** result)
1115{ 1118{
1116 char * line; 1119 char * line;
1117 int res; 1120 int res;
1118 clist * list; 1121 clist * list;
1119 int r; 1122 int r;
1120 char * name; 1123 char * name;
1121 clist * param_list; 1124 clist * param_list;
1122 1125
1123 list = clist_new(); 1126 list = clist_new();
1124 if (list == NULL) { 1127 if (list == NULL) {
1125 res = MAILPOP3_NO_ERROR; 1128 res = MAILPOP3_NO_ERROR;
1126 goto err; 1129 goto err;
1127 } 1130 }
1128 1131
1129 while (1) { 1132 while (1) {
1130 char * next_token; 1133 char * next_token;
1131 char * param; 1134 char * param;
1132 struct mailpop3_capa * capa; 1135 struct mailpop3_capa * capa;
1133 1136
1134 line = read_line(f); 1137 line = read_line(f);
1135 if (line == NULL) { 1138 if (line == NULL) {
1136 res = MAILPOP3_ERROR_STREAM; 1139 res = MAILPOP3_ERROR_STREAM;
1137 goto free_list; 1140 goto free_list;
1138 } 1141 }
1139 1142
1140 if (mailstream_is_end_multiline(line)) 1143 if (mailstream_is_end_multiline(line))
1141 break; 1144 break;
1142 1145
1143 next_token = cut_token(line); 1146 next_token = cut_token(line);
1144 name = strdup(line); 1147 name = strdup(line);
1145 if (name == NULL) { 1148 if (name == NULL) {
1146 res = MAILPOP3_ERROR_MEMORY; 1149 res = MAILPOP3_ERROR_MEMORY;
1147 goto free_list; 1150 goto free_list;
1148 } 1151 }
1149 1152
1150 param_list = clist_new(); 1153 param_list = clist_new();
1151 if (param_list == NULL) { 1154 if (param_list == NULL) {
1152 res = MAILPOP3_ERROR_MEMORY; 1155 res = MAILPOP3_ERROR_MEMORY;
1153 goto free_capa_name; 1156 goto free_capa_name;
1154 } 1157 }
1155 1158
1156 while (next_token != NULL) { 1159 while (next_token != NULL) {
1157 line = next_token; 1160 line = next_token;
1158 next_token = cut_token(line); 1161 next_token = cut_token(line);
1159 param = strdup(line); 1162 param = strdup(line);
1160 if (param == NULL) { 1163 if (param == NULL) {
1161 res = MAILPOP3_ERROR_MEMORY; 1164 res = MAILPOP3_ERROR_MEMORY;
1162 goto free_param_list; 1165 goto free_param_list;
1163 } 1166 }
1164 r = clist_append(param_list, param); 1167 r = clist_append(param_list, param);
1165 if (r < 0) { 1168 if (r < 0) {
1166 free(param); 1169 free(param);
1167 res = MAILPOP3_ERROR_MEMORY; 1170 res = MAILPOP3_ERROR_MEMORY;
1168 goto free_param_list; 1171 goto free_param_list;
1169 } 1172 }
1170 } 1173 }
1171 1174
1172 capa = mailpop3_capa_new(name, param_list); 1175 capa = mailpop3_capa_new(name, param_list);
1173 if (capa == NULL) { 1176 if (capa == NULL) {
1174 res = MAILPOP3_ERROR_MEMORY; 1177 res = MAILPOP3_ERROR_MEMORY;
1175 goto free_param_list; 1178 goto free_param_list;
1176 } 1179 }
1177 1180
1178 r = clist_append(list, capa); 1181 r = clist_append(list, capa);
1179 if (r < 0) { 1182 if (r < 0) {
1180 mailpop3_capa_free(capa); 1183 mailpop3_capa_free(capa);
1181 res = MAILPOP3_ERROR_MEMORY; 1184 res = MAILPOP3_ERROR_MEMORY;
1182 goto free_list; 1185 goto free_list;
1183 } 1186 }
1184 } 1187 }
1185 1188
1186 * result = list; 1189 * result = list;
1187 1190
1188 return MAILPOP3_NO_ERROR; 1191 return MAILPOP3_NO_ERROR;
1189 1192
1190 free_param_list: 1193 free_param_list:
1191 clist_foreach(param_list, (clist_func) free, NULL); 1194 clist_foreach(param_list, (clist_func) free, NULL);
1192 clist_free(param_list); 1195 clist_free(param_list);
1193 free_capa_name: 1196 free_capa_name:
1194 free(name); 1197 free(name);
1195 free_list: 1198 free_list:
1196 clist_foreach(list, (clist_func) mailpop3_capa_free, NULL); 1199 clist_foreach(list, (clist_func) mailpop3_capa_free, NULL);
1197 clist_free(list); 1200 clist_free(list);
1198 err: 1201 err:
1199 return res; 1202 return res;
1200} 1203}
1201 1204
1202 1205
1203 1206
1204static char * read_line(mailpop3 * f) 1207static char * read_line(mailpop3 * f)
1205{ 1208{
1206 return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer); 1209 return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer);
1207} 1210}
1208 1211
1209static char * read_multiline(mailpop3 * f, size_t size, 1212static char * read_multiline(mailpop3 * f, size_t size,
1210 MMAPString * multiline_buffer) 1213 MMAPString * multiline_buffer)
1211{ 1214{
1212 return mailstream_read_multiline(f->pop3_stream, size, 1215 return mailstream_read_multiline(f->pop3_stream, size,
1213 f->pop3_stream_buffer, multiline_buffer, 1216 f->pop3_stream_buffer, multiline_buffer,
1214 f->pop3_progr_rate, f->pop3_progr_fun); 1217 f->pop3_progr_rate, f->pop3_progr_fun);
1215} 1218}
1216 1219
1217static int send_command(mailpop3 * f, char * command) 1220static int send_command(mailpop3 * f, char * command)
1218{ 1221{
1219 ssize_t r; 1222 ssize_t r;
1220 1223
1221 r = mailstream_write(f->pop3_stream, command, strlen(command)); 1224 r = mailstream_write(f->pop3_stream, command, strlen(command));
1222 if (r == -1) 1225 if (r == -1)
1223 return -1; 1226 return -1;
1224 1227
1225 r = mailstream_flush(f->pop3_stream); 1228 r = mailstream_flush(f->pop3_stream);
1226 if (r == -1) 1229 if (r == -1)
1227 return -1; 1230 return -1;
1228 1231
1229 return 0; 1232 return 0;
1230} 1233}