2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
36 #include "mailmbox_parse.h"
40 #include <sys/types.h>
45 #define UID_HEADER "X-LibEtPan-UID:"
63 /* begin extracted from imf/mailimf.c */
65 static int mailimf_char_parse(char * message, size_t length,
66 size_t * index, char token)
72 if (cur_token >= length)
73 return MAILIMF_ERROR_PARSE;
75 if (message[cur_token] == token) {
78 return MAILIMF_NO_ERROR;
81 return MAILIMF_ERROR_PARSE;
84 int mailimf_crlf_parse(char * message, size_t length, size_t * index)
91 r = mailimf_char_parse(message, length, &cur_token, '\r');
92 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
95 r = mailimf_char_parse(message, length, &cur_token, '\n');
96 if (r != MAILIMF_NO_ERROR)
100 return MAILIMF_NO_ERROR;
104 int mailimf_ignore_field_parse(char * message, size_t length,
115 terminal = cur_token;
116 state = UNSTRUCTURED_START;
118 /* check if this is not a beginning CRLF */
120 if (cur_token >= length)
121 return MAILIMF_ERROR_PARSE;
123 switch (message[cur_token]) {
125 return MAILIMF_ERROR_PARSE;
127 return MAILIMF_ERROR_PARSE;
130 while (state != UNSTRUCTURED_OUT) {
133 case UNSTRUCTURED_START:
134 if (cur_token >= length)
135 return MAILIMF_ERROR_PARSE;
137 switch(message[cur_token]) {
139 state = UNSTRUCTURED_CR;
142 state = UNSTRUCTURED_LF;
146 state = UNSTRUCTURED_START;
149 state = UNSTRUCTURED_START;
153 case UNSTRUCTURED_CR:
154 if (cur_token >= length)
155 return MAILIMF_ERROR_PARSE;
157 switch(message[cur_token]) {
159 state = UNSTRUCTURED_LF;
163 state = UNSTRUCTURED_START;
166 state = UNSTRUCTURED_START;
170 case UNSTRUCTURED_LF:
171 if (cur_token >= length) {
172 terminal = cur_token;
173 state = UNSTRUCTURED_OUT;
177 switch(message[cur_token]) {
180 state = UNSTRUCTURED_WSP;
183 terminal = cur_token;
184 state = UNSTRUCTURED_OUT;
188 case UNSTRUCTURED_WSP:
189 if (cur_token >= length)
190 return MAILIMF_ERROR_PARSE;
192 switch(message[cur_token]) {
194 state = UNSTRUCTURED_CR;
197 state = UNSTRUCTURED_LF;
201 state = UNSTRUCTURED_START;
204 state = UNSTRUCTURED_START;
214 return MAILIMF_ERROR_PARSE;
218 return MAILIMF_NO_ERROR;
221 /* end - extracted from imf/mailimf.c */
224 mailmbox_fields_parse(char * str, size_t length,
244 r = mailimf_ignore_field_parse(str, length, &cur_token);
246 case MAILIMF_NO_ERROR:
247 if (str[begin] == 'X') {
249 if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) {
250 begin += strlen(UID_HEADER);
252 while (str[begin] == ' ')
255 uid = strtoul(str + begin, NULL, 10);
260 case MAILIMF_ERROR_PARSE:
267 hlen = cur_token - * index;
273 return MAILMBOX_NO_ERROR;
293 mailmbox_single_parse(char * str, size_t length,
298 size_t * pheaders_len,
313 size_t message_length;
327 if (cur_token >= length)
328 return MAILMBOX_ERROR_PARSE;
334 if (cur_token + 5 < length) {
335 if (strncmp(str + cur_token, "From ", 5) == 0) {
337 while (str[cur_token] != '\n') {
339 if (cur_token >= length)
342 if (cur_token < length) {
345 start_len = headers - start;
352 r = mailmbox_fields_parse(str, length, &cur_token,
354 if (r != MAILMBOX_NO_ERROR)
362 mailimf_crlf_parse(str, length, &cur_token);
365 if (str[cur_token] == 'F') {
367 printf("%50.50s\n", str + cur_token);
374 /* restore position */
375 /* cur_token = begin; */
384 while (state != OUT_MAIL) {
386 if (cur_token >= length) {
387 if (state == IN_MAIL)
395 switch(str[cur_token]) {
403 if (cur_token == body) {
419 switch(str[cur_token]) {
437 switch(str[cur_token]) {
454 switch(str[cur_token]) {
475 switch(str[cur_token]) {
496 switch(str[cur_token]) {
510 switch(str[cur_token]) {
524 switch(str[cur_token]) {
538 switch(str[cur_token]) {
552 message_length = end - start;
555 * pstart_len = start_len;
556 * pheaders = headers;
557 * pheaders_len = headers_len;
559 * pbody_len = end - body;
560 * psize = message_length;
561 * ppadding = next - end;
566 return MAILMBOX_NO_ERROR;
571 mailmbox_parse_additionnal(struct mailmbox_folder * folder,
595 /* remove temporary UID that we will parse */
597 first_index = folder->tab->len;
599 for(i = 0 ; i < folder->tab->len ; i++) {
600 struct mailmbox_msg_info * info;
602 info = carray_get(folder->tab, i);
604 if (info->start < cur_token) {
608 if (!info->written_uid) {
611 key.data = (char *) &info->uid;
612 key.len = sizeof(info->uid);
614 chash_delete(folder->hash, &key, NULL);
615 carray_delete_fast(folder->tab, i);
616 mailmbox_msg_info_free(info);
622 /* make a sequence in the table */
624 max_uid = folder->written_uid;
628 while (i < folder->tab->len) {
629 struct mailmbox_msg_info * info;
631 info = carray_get(folder->tab, i);
633 carray_set(folder->tab, j, info);
635 if (info->uid > max_uid)
643 carray_set_size(folder->tab, j);
650 struct mailmbox_msg_info * info;
654 r = mailmbox_single_parse(folder->mapping, folder->mapping_size,
657 &headers, &headers_len,
659 &size, &padding, &uid);
660 if (r == MAILMBOX_NO_ERROR) {
663 else if (r == MAILMBOX_ERROR_PARSE)
670 key.data = (char *) &uid;
671 key.len = sizeof(uid);
673 r = chash_get(folder->hash, &key, &data);
675 info = (struct mailmbox_msg_info *) data.data;
677 if (!info->written_uid) {
678 /* some new mail has been written and override an
679 existing temporary UID */
681 chash_delete(folder->hash, &key, NULL);
684 if (info->index < first_index)
685 first_index = info->index;
694 r = mailmbox_msg_info_update(folder,
695 start, start_len, headers, headers_len,
696 body, body_len, size, padding, uid);
697 if (r != MAILMBOX_NO_ERROR) {
705 folder->written_uid = max_uid;
709 for(i = first_index ; i < folder->tab->len ; i ++) {
710 struct mailmbox_msg_info * info;
714 info = carray_get(folder->tab, i);
716 if (info->uid != 0) {
723 key.data = (char *) &info->uid;
724 key.len = sizeof(info->uid);
725 data.data = (char *) info;
728 r = chash_set(folder->hash, &key, &data, NULL);
730 res = MAILMBOX_ERROR_MEMORY;
735 folder->max_uid = max_uid;
737 return MAILMBOX_NO_ERROR;
743 static void flush_uid(struct mailmbox_folder * folder)
747 for(i = 0 ; i < folder->tab->len ; i++) {
748 struct mailmbox_msg_info * info;
750 info = carray_get(folder->tab, i);
752 mailmbox_msg_info_free(info);
755 chash_clear(folder->hash);
756 carray_set_size(folder->tab, 0);
759 int mailmbox_parse(struct mailmbox_folder * folder)
769 r = mailmbox_parse_additionnal(folder, &cur_token);
771 if (r != MAILMBOX_NO_ERROR) {
776 return MAILMBOX_NO_ERROR;