X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ham.c;h=e54ec5e3b099d191a5bd30464f16f6b5ed03c2a5;hb=6b3d60b53a72a491b6792e3bd08c7835297f8f7b;hp=f8f96bd007fb7994af99b4d5fc2779fac2700f84;hpb=f7469b506efca7aa155899a9398b7ce490dd4ba1;p=umpf.git diff --git a/ham.c b/ham.c index f8f96bd..e54ec5e 100644 --- a/ham.c +++ b/ham.c @@ -2,6 +2,7 @@ #include #include #include +#include #include @@ -14,7 +15,7 @@ char mbox_write_buf[BUFSIZE]; int mbox_write_pos; int mbox_write_err; -static void +void new_header(char* buf, struct list* h) { char* p; @@ -27,7 +28,10 @@ new_header(char* buf, struct list* h) new->value = xstrdup(""); else { *p = 0; - new->value = xstrdup(p+1); + if (*(p + 1) == ' ') + new->value = xstrdup(p + 2); + else + new->value = xstrdup(p + 1); p = strrchr(new->value, '\n'); if (p && !*(p+1)) *p = 0; @@ -37,8 +41,61 @@ new_header(char* buf, struct list* h) list_add_last(h, &new->car); } +int gmc_pos; +char gmc_buf[BUFSIZE]; +int gmc_init; +int gmc_read; +int gmc_unget; + +static int +give_me_char(int fd) +{ + if (! gmc_init) { + gmc_pos = 0; + gmc_read = read(fd, gmc_buf, BUFSIZE); + gmc_init = 1; + gmc_unget = EOF; + curr_email_len = 0; + } + + if (gmc_unget != EOF) { + int a = gmc_unget; + gmc_unget = EOF; + curr_email_len++; + return a; + } + + if (! gmc_read) { + gmc_init = 0; + return EOF; + } + + if (gmc_pos < gmc_read) { + curr_email_len++; + return gmc_buf[gmc_pos++]; + } else { + gmc_pos = 0; + gmc_read = read(fd, gmc_buf, BUFSIZE); + if (! gmc_read) { + gmc_init = 0; + return EOF; + } + else { + curr_email_len++; + return gmc_buf[gmc_pos++]; + } + } +} + +static void +unget_me(int c) +{ + gmc_unget = c; + curr_email_len--; +} + struct list* -make_hlist(void) +make_hlist(int fd) { struct list* l = xmalloc(sizeof(struct list)); char* buf; @@ -49,7 +106,7 @@ make_hlist(void) buf = xmalloc(BUFSIZE); curbufsize = BUFSIZE; - while ((c = getchar()) != EOF){ + while ((c = give_me_char(fd)) != EOF){ if (c == '\r') continue; @@ -60,9 +117,9 @@ make_hlist(void) if (c == '\n'){ if (last == '\n') break; - if ((c = getchar()) != ' ' && c != '\t'){ + if ((c = give_me_char(fd)) != ' ' && c != '\t'){ if (c != EOF) - ungetc(c, stdin); + unget_me(c); buf[i] = 0; new_header(buf, l); i = 0; @@ -76,7 +133,7 @@ make_hlist(void) } struct email* -get_body(void) +get_body(int rfd) { char* buf; struct email* b; @@ -94,14 +151,14 @@ get_body(void) b->fd = -1; /* read mail body, if it is too big, try to make tmp file */ - while ((c = getchar()) != EOF){ + while ((c = give_me_char(rfd)) != EOF){ buf[i++] = c; if (i >= curbufsize - 1) { tmpfile = xstrdup("/tmp/umpf.XXXXXX"); fd = mkstemp(tmpfile); /* cannot create tmpfile, try to continue reading */ if (fd < 0) - bye(EX_TEMPFAIL, "%m"); + bye(EX_TEMPFAIL, "Cannot create temporary file: %m"); else { will_save = 1; b->body = NULL; @@ -110,7 +167,7 @@ get_body(void) res = write(fd, buf, MAIL_LEN); if (res < MAIL_LEN) { unlink(b->tmpfile); - bye(EX_TEMPFAIL, "%m"); + bye(EX_TEMPFAIL, "Cannot write to remporary file: %m"); } break; } @@ -120,7 +177,7 @@ get_body(void) /* save rest of the body to the tmpfile */ if (will_save) { int j = 0; - while ((c = getchar()) != EOF){ + while ((c = give_me_char(rfd)) != EOF){ buf[j++] = c; b->body_len++; if (j >= MAIL_LEN) { @@ -128,14 +185,14 @@ get_body(void) res = write(fd, buf, MAIL_LEN); if (res < MAIL_LEN) { unlink(b->tmpfile); - bye(EX_TEMPFAIL, "%m"); + bye(EX_TEMPFAIL, "Cannot write to temporary file: %m"); } } } res = write(fd, buf, j); if (res < j) { unlink(b->tmpfile); - bye(EX_TEMPFAIL, "%m"); + bye(EX_TEMPFAIL, "Cannot write to temporary file: %m"); } } return b; @@ -178,6 +235,91 @@ write_char_to_mailbox(char c, int fd) mbox_write_buf[mbox_write_pos++] = c; } +int email_pos; +int headers_sent; +int email_opened; + +void +open_email(void) +{ + email_pos = 0; + headers_sent = 0; + email_opened = 1; +} + +char* +read_email(struct email* em) +{ + char* buf; + int r, pos; + + if (! email_opened) { + chars_written = 0; + return NULL; + } + + if (! headers_sent) { + struct hlist* ph; + int curbufsize = BUFSIZE; + buf = xmalloc(BUFSIZE); + pos = 0; + + LIST_FOREACH(ph, em->headers){ + int needed = strlen(ph->name) + strlen(ph->value) + 4; + if (curbufsize < pos + needed) + buf = xrealloc(buf, curbufsize*=2); + strcpy(buf + pos, ph->name); + pos += strlen(ph->name); + buf[pos++] = ':'; + buf[pos++] = ' '; + strcpy(buf + pos, ph->value); + pos += strlen(ph->value); + buf[pos++] = '\n'; + + } + buf[pos++] = '\n'; + headers_sent = 1; + chars_written = pos; + return buf; + } + + if (em->body) { + buf = xstrdup(em->body); + chars_written = em->body_len; + //printf("%d: %s\n", em->body_len, em->body); + email_opened = 0; + return buf; + } + + if (! email_pos) + lseek(em->fd, 0, SEEK_SET); + + buf = xmalloc(MAIL_LEN + 1); + r = read(em->fd, buf, MAIL_LEN); + if (r < MAIL_LEN) + email_opened = 0; + chars_written = r; + + return buf; +} + +int +write_email_to_fd(int fd, struct email* email) +{ + char* buf; + int wr; + + open_email(); + do { + buf = read_email(email); + wr = write(fd, buf, chars_written); + if (wr < chars_written) + return 1; + } while (chars_written); + + return 0; +} + /* try to copy e-mail to mailbox, if it fails, truncate mailbox to the original size */ static int @@ -193,21 +335,49 @@ copy_email(int fd, struct email* email) mbox_write_err = 0; mbox_write_pos = 0; - /* headers */ + /* From line */ struct hlist* ph; + int i, len; + char* fromline; + char* from = NULL; + time_t t; + time(&t); + char* date = ctime(&t); + int datelen = strlen(date); + + LIST_FOREACH(ph, email->headers) { + if (!strcasecmp(ph->name, "From")) { + from = ph->value; + break; + } + } + len = 5 + datelen + 1; + if (from) + len += strlen(from); + + fromline = xmalloc(len); + if (from) + sprintf(fromline, "From %s %s", from, date); + else + sprintf(fromline, "From %s", date); + + len = strlen(fromline); + for (i = 0; i < len; i++) + write_char_to_mailbox(fromline[i], fd); + + /* headers */ char* pc; LIST_FOREACH(ph, email->headers){ for (pc = ph->name; *pc; pc++) write_char_to_mailbox(*pc, fd); write_char_to_mailbox(':', fd); + write_char_to_mailbox(' ', fd); for (pc = ph->value; *pc; pc++) write_char_to_mailbox(*pc, fd); write_char_to_mailbox('\n', fd); } write_char_to_mailbox('\n', fd); - /* body */ - /* FIXME: do not forget change Content-Length */ if (email->body) { for (pc = email->body; pc < email->body + email->body_len; pc++){ write_char_to_mailbox(*pc, fd); @@ -252,51 +422,6 @@ copy_email(int fd, struct email* email) return 0; } -int -write_email_to_fd(int fd, struct email* email) -{ - int written; - - /* headers */ - struct hlist* ph; - LIST_FOREACH(ph, email->headers){ - written = write(fd, ph->name, strlen(ph->name)); - if (written < (ssize_t) strlen(ph->name)) - return 1; - written = write(fd, ":", 1); - if (written < 1) - return 1; - written = write(fd, ph->value, strlen(ph->value)); - if (written < (ssize_t) strlen(ph->value)) - return 1; - written = write(fd, "\n", 1); - if (written < 1) - return 1; - } - written = write(fd, "\n", 1); - if (written < 1) - return 1; - - /* body */ - if (email->body) { - written = write(fd, email->body, email->body_len); - if (written < email->body_len) - return 1; - } else { - char buf[MAIL_LEN]; - int i; - for(i = 0; i < email->body_len; i+=MAIL_LEN) { - int len = MAIL_LEN; - if (i >= email->body_len) - len = len - (i - email->body_len); - read(email->fd, buf, len); //FIXME: check it? - write(fd, buf, len); - } - } - - return 0; -} - int deliver_local_email(char* folder, struct email* email) {