Improve some sieve-related translations
[claws.git] / src / plugins / mailmbox / mailmbox_parse.c
blobafd964c7df576816f0c27082044003b506af77a5
1 /*
2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
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
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
29 * SUCH DAMAGE.
33 * $Id$
36 #include "config.h"
38 #include "mailmbox_parse.h"
40 #include "mailmbox.h"
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <string.h>
45 #include <stdlib.h>
47 #define UID_HEADER "X-LibEtPan-UID:"
49 #include "utils.h"
51 #ifndef TRUE
52 #define TRUE 1
53 #endif
55 #ifndef FALSE
56 #define FALSE 0
57 #endif
59 enum {
60 UNSTRUCTURED_START,
61 UNSTRUCTURED_CR,
62 UNSTRUCTURED_LF,
63 UNSTRUCTURED_WSP,
64 UNSTRUCTURED_OUT
67 static inline int
68 claws_mailmbox_fields_parse(char * str, size_t length,
69 size_t * index,
70 uint32_t * puid,
71 size_t * phlen)
73 size_t cur_token;
74 int r;
75 size_t hlen;
76 size_t uid;
77 int end;
79 cur_token = * index;
81 end = FALSE;
82 uid = 0;
83 while (!end) {
84 size_t begin;
86 begin = cur_token;
88 r = mailimf_ignore_field_parse(str, length, &cur_token);
89 switch (r) {
90 case MAILIMF_NO_ERROR:
91 if (str[begin] == 'X') {
93 if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) {
94 begin += strlen(UID_HEADER);
96 while (str[begin] == ' ')
97 begin ++;
99 uid = strtoul(str + begin, NULL, 10);
103 break;
104 case MAILIMF_ERROR_PARSE:
105 default:
106 end = TRUE;
107 break;
111 hlen = cur_token - * index;
113 * phlen = hlen;
114 * puid = uid;
115 * index = cur_token;
117 return MAILMBOX_NO_ERROR;
120 enum {
121 IN_MAIL,
122 FIRST_CR,
123 FIRST_LF,
124 SECOND_CR,
125 SECOND_LF,
126 PARSING_F,
127 PARSING_R,
128 PARSING_O,
129 PARSING_M,
130 OUT_MAIL
136 static inline int
137 claws_mailmbox_single_parse(char * str, size_t length,
138 size_t * index,
139 size_t * pstart,
140 size_t * pstart_len,
141 size_t * pheaders,
142 size_t * pheaders_len,
143 size_t * pbody,
144 size_t * pbody_len,
145 size_t * psize,
146 size_t * ppadding,
147 uint32_t * puid)
149 size_t cur_token;
150 size_t start;
151 size_t start_len;
152 size_t headers;
153 size_t headers_len;
154 size_t body;
155 size_t end;
156 size_t next;
157 size_t message_length;
158 uint32_t uid;
159 int r;
160 #if 0
161 int in_mail_data;
162 #endif
163 #if 0
164 size_t begin;
165 #endif
167 int state;
169 cur_token = * index;
171 if (cur_token >= length)
172 return MAILMBOX_ERROR_PARSE;
174 start = cur_token;
175 start_len = 0;
176 headers = cur_token;
178 if (cur_token + 5 < length) {
179 if (strncmp(str + cur_token, "From ", 5) == 0) {
180 cur_token += 5;
181 while (str[cur_token] != '\n') {
182 cur_token ++;
183 if (cur_token >= length)
184 break;
186 if (cur_token < length) {
187 cur_token ++;
188 headers = cur_token;
189 start_len = headers - start;
194 next = length;
196 r = claws_mailmbox_fields_parse(str, length, &cur_token,
197 &uid, &headers_len);
198 if (r != MAILMBOX_NO_ERROR)
199 return r;
201 /* save position */
202 #if 0
203 begin = cur_token;
204 #endif
206 mailimf_crlf_parse(str, length, &cur_token);
208 #if 0
209 if (str[cur_token] == 'F') {
210 printf("start !\n");
211 printf("%50.50s\n", str + cur_token);
212 getchar();
214 #endif
216 body = cur_token;
218 /* restore position */
219 /* cur_token = begin; */
221 state = FIRST_LF;
223 end = length;
225 #if 0
226 in_mail_data = 0;
227 #endif
228 while (state != OUT_MAIL) {
230 if (cur_token >= length) {
231 if (state == IN_MAIL)
232 end = length;
233 next = length;
234 break;
237 switch(state) {
238 case IN_MAIL:
239 switch(str[cur_token]) {
240 case '\r':
241 state = FIRST_CR;
242 break;
243 case '\n':
244 state = FIRST_LF;
245 break;
246 case 'F':
247 if (cur_token == body) {
248 end = cur_token;
249 next = cur_token;
250 state = PARSING_F;
252 break;
253 #if 0
254 default:
255 in_mail_data = 1;
256 break;
257 #endif
259 break;
261 case FIRST_CR:
262 end = cur_token;
263 switch(str[cur_token]) {
264 case '\r':
265 state = SECOND_CR;
266 break;
267 case '\n':
268 state = FIRST_LF;
269 break;
270 default:
271 state = IN_MAIL;
272 #if 0
273 in_mail_data = 1;
274 #endif
275 break;
277 break;
279 case FIRST_LF:
280 end = cur_token;
281 switch(str[cur_token]) {
282 case '\r':
283 state = SECOND_CR;
284 break;
285 case '\n':
286 state = SECOND_LF;
287 break;
288 default:
289 state = IN_MAIL;
290 #if 0
291 in_mail_data = 1;
292 #endif
293 break;
295 break;
297 case SECOND_CR:
298 switch(str[cur_token]) {
299 case '\r':
300 end = cur_token;
301 break;
302 case '\n':
303 state = SECOND_LF;
304 break;
305 case 'F':
306 next = cur_token;
307 state = PARSING_F;
308 break;
309 default:
310 state = IN_MAIL;
311 #if 0
312 in_mail_data = 1;
313 #endif
314 break;
316 break;
318 case SECOND_LF:
319 switch(str[cur_token]) {
320 case '\r':
321 state = SECOND_CR;
322 break;
323 case '\n':
324 end = cur_token;
325 break;
326 case 'F':
327 next = cur_token;
328 state = PARSING_F;
329 break;
330 default:
331 state = IN_MAIL;
332 #if 0
333 in_mail_data = 1;
334 #endif
335 break;
337 break;
339 case PARSING_F:
340 switch(str[cur_token]) {
341 case 'r':
342 state = PARSING_R;
343 break;
344 default:
345 state = IN_MAIL;
346 #if 0
347 in_mail_data = 1;
348 #endif
349 break;
351 break;
353 case PARSING_R:
354 switch(str[cur_token]) {
355 case 'o':
356 state = PARSING_O;
357 break;
358 default:
359 state = IN_MAIL;
360 #if 0
361 in_mail_data = 1;
362 #endif
363 break;
365 break;
367 case PARSING_O:
368 switch(str[cur_token]) {
369 case 'm':
370 state = PARSING_M;
371 break;
372 default:
373 state = IN_MAIL;
374 #if 0
375 in_mail_data = 1;
376 #endif
377 break;
379 break;
381 case PARSING_M:
382 switch(str[cur_token]) {
383 case ' ':
384 state = OUT_MAIL;
385 break;
386 default:
387 state = IN_MAIL;
388 break;
390 break;
393 cur_token ++;
396 message_length = end - start;
398 * pstart = start;
399 * pstart_len = start_len;
400 * pheaders = headers;
401 * pheaders_len = headers_len;
402 * pbody = body;
403 * pbody_len = end - body;
404 * psize = message_length;
405 * ppadding = next - end;
406 * puid = uid;
408 * index = next;
410 return MAILMBOX_NO_ERROR;
415 claws_mailmbox_parse_additionnal(struct claws_mailmbox_folder * folder,
416 size_t * index)
418 size_t cur_token;
420 size_t start;
421 size_t start_len;
422 size_t headers;
423 size_t headers_len;
424 size_t body;
425 size_t body_len;
426 size_t size;
427 size_t padding;
428 uint32_t uid;
429 int r;
430 int res;
432 uint32_t max_uid;
433 uint32_t first_index;
434 unsigned int i;
435 unsigned int j;
437 cur_token = * index;
439 /* remove temporary UID that we will parse */
441 first_index = carray_count(folder->mb_tab);
443 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
444 struct claws_mailmbox_msg_info * info;
446 info = carray_get(folder->mb_tab, i);
448 if (info->msg_start < cur_token) {
449 continue;
452 if (!info->msg_written_uid) {
453 chashdatum key;
455 key.data = &info->msg_uid;
456 key.len = sizeof(info->msg_uid);
458 chash_delete(folder->mb_hash, &key, NULL);
459 carray_delete_fast(folder->mb_tab, i);
460 claws_mailmbox_msg_info_free(info);
461 if (i < first_index)
462 first_index = i;
466 /* make a sequence in the table */
468 max_uid = folder->mb_written_uid;
470 i = 0;
471 j = 0;
472 while (i < carray_count(folder->mb_tab)) {
473 struct claws_mailmbox_msg_info * info;
475 info = carray_get(folder->mb_tab, i);
476 if (info != NULL) {
477 carray_set(folder->mb_tab, j, info);
479 if (info->msg_uid > max_uid)
480 max_uid = info->msg_uid;
482 info->msg_index = j;
483 j ++;
485 i ++;
487 carray_set_size(folder->mb_tab, j);
489 /* parse content */
491 first_index = j;
493 while (1) {
494 struct claws_mailmbox_msg_info * info;
495 chashdatum key;
496 chashdatum data;
498 r = claws_mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size,
499 &cur_token,
500 &start, &start_len,
501 &headers, &headers_len,
502 &body, &body_len,
503 &size, &padding, &uid);
504 if (r == MAILMBOX_NO_ERROR) {
505 /* do nothing */
507 else if (r == MAILMBOX_ERROR_PARSE) {
508 break;
509 } else {
510 res = r;
511 goto err;
514 key.data = &uid;
515 key.len = sizeof(uid);
517 r = chash_get(folder->mb_hash, &key, &data);
518 if (r == 0) {
519 info = data.data;
521 if (!info->msg_written_uid) {
522 /* some new mail has been written and override an
523 existing temporary UID */
525 chash_delete(folder->mb_hash, &key, NULL);
526 info->msg_uid = 0;
528 if (info->msg_index < first_index)
529 first_index = info->msg_index;
531 else
532 uid = 0;
535 if (uid > max_uid)
536 max_uid = uid;
538 r = claws_mailmbox_msg_info_update(folder,
539 start, start_len, headers, headers_len,
540 body, body_len, size, padding, uid);
541 if (r != MAILMBOX_NO_ERROR) {
542 debug_print("claws_mailmbox_msg_info_update failed with %d\n", r);
543 res = r;
544 goto err;
548 * index = cur_token;
550 folder->mb_written_uid = max_uid;
552 /* attribute uid */
554 for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) {
555 struct claws_mailmbox_msg_info * info;
556 chashdatum key;
557 chashdatum data;
559 info = carray_get(folder->mb_tab, i);
561 if (info->msg_uid != 0) {
562 continue;
565 max_uid ++;
566 info->msg_uid = max_uid;
568 key.data = &info->msg_uid;
569 key.len = sizeof(info->msg_uid);
570 data.data = info;
571 data.len = 0;
573 r = chash_set(folder->mb_hash, &key, &data, NULL);
574 if (r < 0) {
575 debug_print("chash_set failed with %d\n", r);
576 res = MAILMBOX_ERROR_MEMORY;
577 goto err;
581 folder->mb_max_uid = max_uid;
583 return MAILMBOX_NO_ERROR;
585 err:
586 return res;
589 static void flush_uid(struct claws_mailmbox_folder * folder)
591 unsigned int i;
593 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
594 struct claws_mailmbox_msg_info * info;
596 info = carray_get(folder->mb_tab, i);
597 if (info != NULL)
598 claws_mailmbox_msg_info_free(info);
601 chash_clear(folder->mb_hash);
602 carray_set_size(folder->mb_tab, 0);
605 int claws_mailmbox_parse(struct claws_mailmbox_folder * folder)
607 int r;
608 int res;
609 size_t cur_token;
611 flush_uid(folder);
613 cur_token = 0;
615 r = claws_mailmbox_parse_additionnal(folder, &cur_token);
617 if (r != MAILMBOX_NO_ERROR) {
618 res = r;
619 goto err;
622 return MAILMBOX_NO_ERROR;
624 err:
625 return res;