Viewing file: mbox_subs.c (6.75 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* File: mbox_subs.c * */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include <assert.h> #include "mbox_subs.h"
/* Test for an empty string. * * Check for a string that consists only of \\n or \\r\\n * * Parameter: * p - the string. * * Returns: 1 if empty, 0 otherwise. */ static int isempty(char* p) { char c; while((c = *p++)) { if ((c != '\r') && (c != '\n')) return 0; } return 1; }
/* * Returns: an initialized mail_t */ mail_t *new_mail() { return calloc(sizeof(struct rfc822_mail), 1); }
/* * Append a line to a mail being accumlated. If line * is empty, and is the first empty line seen, save * the offset of the end of it as the body offset. * * Parameters: * mail - The mail_t being accumulater * line - The line to append. */ static void accumulate_mail(mail_t* mail, char *line) { size_t linesize = strlen(line); mail->mail_text = realloc(mail->mail_text, mail->mail_size+linesize+1); assert(mail->mail_text); strcpy(mail->mail_text + mail->mail_size, line); mail->mail_size += linesize; if (isempty(line) && (!mail->body_offset)) mail->body_offset = mail->mail_size; }
/* * Parameter: * mail - The mail_t to be released. */ void free_mail(mail_t *mail) { if (mail) { free(mail->mail_text); free(mail->from); free(mail); } }
/* * * Open the specified mbox file and then associate it * with a newly allocated mbox_t. * * Parameter: * mbox_path - The path to the mbox file * * Returns: The mbox_t corresponding the the fill, or NULL if the file could not be opened. */ mbox_t *new_mbox(char *mbox_path) { mbox_t *box = NULL; FILE *f = fopen(mbox_path, "r"); if (f) { box = calloc(sizeof(struct mbox), 1); box->file = f; } return box; }
/* * Deallocate an mbox_t allocated by new_mbox(). * * Parameter: * box - The mbox_t to be deallocated */
void free_mbox(mbox_t *box) { fclose(box->file); free(box->from_line); free(box); }
/* * Read in the next piece of mail from the mbox file. * * Parameter: * mbox - The file to read from. * * Returns: The next mail as a mail_t, or NULL if no more mail. */ mail_t *next_mail(mbox_t *mbox) { char buf[1024]; mail_t *mail = NULL; /* If we've finished the file, just return NULL */ if (mbox->done) return NULL;
/* If we haven't seen a From line yet, which will be the * case on the first call, read lines until we find one, * then save a copy. */ if (!mbox->from_line) { do { if(NULL == fgets(buf, sizeof(buf), mbox->file)) { /* If we get here, we've exhausted the file. Flag * that and return NULL */ mbox->done = 1; return NULL; } if(!strncmp(buf, "From ", 5)) { /* Found a From line. Copy it */ mbox->from_line = strdup(buf); } }while(!mbox->from_line); }
/* Get a fresh mail_t */ mail = new_mail();
/* Accumulate lines until we encounter the next From line, or hit EOF */ do { /* Read a line */ if(fgets(buf, sizeof(buf), mbox->file)) { /* If it is a From line it means we're done. Save a copy * of the line and return the mail we've accumulated */ if (mbox->last_line_empty && !strncmp(buf, "From ", 5)) { mail->from = mbox->from_line; mbox->from_line = strdup(buf); return mail; } /* If not a from line, check to see if it is empty, then * append the line to the mail. */ mbox->last_line_empty = isempty(buf); accumulate_mail(mail, buf); } else { /* If we get here, we've seen EOF */ mbox->done = 1; if (mail->mail_size) { /* If we've accumulated something, return the mail */ mail->from = mbox->from_line; mbox->from_line = NULL; return mail; } else { /* otherwise, return NULL */ free_mail(mail); return NULL; } } } while(1); }
/* * Search for the specified header in a mail, and if found, * return a copy of it. (Note the the copy is malloc'd, so the * caller is responsible for freeing if). If the header is not * found, return NULL. If the header is wrapped, it will be unwrapped * prior to being returned. * * Note: In the case of multiple headers with the same name, * this will just return the first one. * * Parameters: * mail - The mail to be searched. * header - The header searched for. * * Returns: A copy of the header, or NULL */ char *get_header(mail_t *mail, char *header) { char *hdr = NULL; char *beg = NULL; char *text = NULL;
text = mail->mail_text; do { /* find a occurance */ beg = strstr(text, header); /* If not found, of it occurance is after headers, give up */ if (!beg || (beg - mail->mail_text > mail->body_offset)) return NULL;
/* Must be at the beginning of a line */ if ( (beg == mail->mail_text || *(beg-1) == '\n') ) { /* Now, search for the end of the header. Note that the header might be wrapped */ char *end; char *p = beg; do { /* get the end of the current line */ end = strchr(p, '\n'); if (end){ /* look ahead to see if next line is a continuation, and if so * keep going, else break */ ++end; if (!isspace(*end)) break; else p = end; } else { end = p + strlen(p); break; } }while(*p);
{ char *q0, *q1; size_t len = end-beg; /* Duplicate our header */ hdr = malloc(len+1); strncpy(hdr,beg,len); hdr[len] = '\0'; /* Then 'unwrap' it by deleting \r and \n chars. */ q0 = hdr; q1 = hdr; char c; for (c = *q0++; c; c = *q0++){ if ((c != '\r') && (c != '\n')) *q1++ = c; } /* then add a terminator to make it a C-string */ *q1 = '\0'; }
} else { /* Found one, but not a begin of line. Keep trying */ text = beg+1; } } while (!hdr); return hdr; }
|