/* elmo - ELectronic Mail Operator Copyright (C) 2002, 2003, 2004 rzyjontko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------- This is very simple module used to get full list of messages from file in mbox format. */ #define _GNU_SOURCE 1 /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "mail.h" #include "mbox.h" #include "hash.h" #include "mlex.h" #include "file.h" #include "error.h" #include "gettext.h" #include "clock.h" #include "maildir.h" #include "misc.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ #ifndef P_tmpdir # define P_tmpdir "/tmp" #endif #define MAIL_BEG_RE "^From " /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ int mbox_may_be_valid (const char *fname) { struct stat st; if (stat (fname, &st)){ error_ (errno, "%s", fname); return 0; } if (S_ISREG (st.st_mode)) return 1; return 0; } int mbox_mail_size (mail_t *mail) { mime_t *mime = mail->mime->mime; return mime->off_bound - mime->off_header; } mail_array_t * mbox_read_file (const char *file) { struct stat st; int ret = 0; mail_array_t *result; if (stat (file, &st)){ error_ (errno, "%s", file); return NULL; } if (! S_ISREG (st.st_mode) || st.st_size == 0) return NULL; yyin = fopen (file, "r"); if (!yyin){ error_ (errno, "%s", file); return NULL; } /* first invocation of mbox_scan tells us only if we are reading a mailbox; it does not bring any information yet */ if (mlex_mbox_scan_start () != NEXT_MAIL){ fclose (yyin); return NULL; } result = mail_array_create (BOX_MBOX, file); while (ret != END_OF_FILE){ ret = mlex_scan (); switch (ret){ case NEXT_MAIL: newmail->type = BOX_MBOX; newmail->mime->file = result->path; mail_array_insert (result, newmail); break; case BROKEN_MAIL: fclose (yyin); mail_array_destroy (result); return NULL; } } fclose (yyin); return result; } int mbox_mail_header (mail_t *mail, char **place, const char *fname) { mime_t *mime = mail->mime->mime; if (file_part (fname, mime->off_header, mime->off_start, place)){ *place = NULL; return 1; } return 0; } int mbox_mail_body (mail_t *mail, char **place, mime_t *mime, const char *fname) { if (file_part (fname, mime->off_start, mime->off_end, place)){ *place = NULL; return 1; } return 0; } char * mbox_fetch_single (const char *mbox, mail_t *mail) { int size; char *dir = P_tmpdir; char *path; char *fname; char *body; mime_t *mime; FILE *fp; if (mbox == NULL || mail == NULL || mail->mime == NULL) return NULL; mime = mail->mime->mime; size = mime->off_bound - mail->place.offset_header; if (file_part (mbox, mail->place.offset_header, mime->off_bound, & body)) return NULL; fname = maildir_valid_file_name (); path = file_with_dir (dir, fname); xfree (fname); fp = file_open (path, "w", O_WRONLY | O_CREAT | O_EXCL, 0600); if (fp == NULL){ xfree (body); xfree (path); return NULL; } if (fwrite (body, 1, size, fp) != size){ fclose (fp); xfree (body); xfree (path); return NULL; } fclose (fp); xfree (body); return path; } int mbox_box_mail_count (const char *box, int *unread) { FILE *fp; int ret; int size; int count; char *body; char *seek; regmatch_t matches[1]; if (! mbox_may_be_valid (box)) return -1; fp = fopen (box, "r"); if (fp == NULL) return -1; if (file_whole (fp, & body, & size)){ fclose (fp); return -1; } fclose (fp); if (unread) *unread = 0; count = 0; seek = body; while (1){ ret = misc_regex (MAIL_BEG_RE, seek, matches); if (ret == 0) break; seek = seek + matches[0].rm_eo; count++; } xfree (body); return count; } void mbox_free_resources (void) { } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE mbox.c * ****************************************************************************/