int rfc2045_decodemimesection(struct rfc2045src *src, struct rfc2045 *rfc, int (*handler)(const char *, size_t, void *), void *voidarg) { off_t start_pos, end_pos, start_body; char buf[BUFSIZ]; ssize_t cnt; off_t dummy; int rc; rfc2045_mimepos(rfc, &start_pos, &end_pos, &start_body, &dummy, &dummy); if (SRC_SEEK(src, start_body) == (off_t)-1) return (-1); rfc2045_cdecode_start(rfc, handler, voidarg); while (start_body < end_pos) { cnt=sizeof(buf); if (cnt > end_pos-start_body) cnt=end_pos-start_body; cnt=SRC_READ(src, buf, cnt); if (cnt <= 0) break; if ((rc=rfc2045_cdecode(rfc, buf, cnt)) != 0) return (rc); start_body += cnt; } return (rfc2045_cdecode_end(rfc)); }
static void do_print_section(struct rfc2045 *s, FILE *fp) { off_t start, end, body; off_t nlines; off_t nbodylines; rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines); if (fseek(stdin, body, SEEK_SET) == -1) { perror("fseek"); exit(1); } rfc2045_cdecode_start(s, &decode_to_file, fp); while (body < end) { char buf[BUFSIZ]; size_t n=sizeof(buf); if ((off_t)n > end-body) n=end-body; n=fread(buf, 1, n, stdin); if (n == 0) { perror("fread"); exit(1); } rfc2045_cdecode(s, buf, n); body += n; } rfc2045_cdecode_end(s); }
static void rfc822text(FILE *fp, struct fetchinfo *fi, struct imapscaninfo *info, unsigned long msgnum, struct rfc2045 *rfcp) { off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; unsigned long i; int c; char buf[BUFSIZ]; unsigned long l; writes("RFC822.TEXT {"); rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (fseek(fp, start_body, SEEK_SET) == -1) { fetcherror("fseek", fi, info, msgnum); writes("0}\r\n"); return; } i=end_pos - start_body + nbodylines; writen(i); writes("}\r\n"); l=0; while (i) { c=getc(fp); if (c == EOF) { fetcherror("unexpected EOF", fi, info, msgnum); _exit(1); } --i; if (l >= sizeof(BUFSIZ)) { writemem(buf, l); l=0; } if (c == '\n' && i) { --i; buf[l++]='\r'; if (l >= sizeof(BUFSIZ)) { writemem(buf, l); l=0; } } buf[l++]=c; ++body_count; } writemem(buf, l); }
static void rfc822size(FILE *fp, struct fetchinfo *fi, struct imapscaninfo *i, unsigned long msgnum, struct rfc2045 *mimep) { off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; writes("RFC822.SIZE "); rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); writen(end_pos - start_pos + nlines); }
static int search_spell(const char *filename, unsigned parnum, unsigned pos) { struct rfc2045 *rfcp, *textp; struct buf newtext, current_line; off_t start_pos, end_pos, start_body; int made_replacements, has_misspelling; char *new_line; unsigned paragraph; const char *ignoreword=""; const char *replacefrom=""; const char *replaceto=""; int checked=0; off_t dummy; FILE *fp=0; int x; x=maildir_safeopen(filename, O_RDONLY, 0); if (x >= 0) if ((fp=fdopen(x, "r")) == 0) close(x); if (!fp) return (0); rfcp=rfc2045_fromfp(fp); if (!rfcp) enomem(); textp=findtext(rfcp); if (!textp) { rfc2045_free(rfcp); fclose(fp); return (0); } buf_init(&newtext); buf_init(¤t_line); rfc2045_mimepos(textp, &start_pos, &end_pos, &start_body, &dummy, &dummy); if (fseek(fp, start_body, SEEK_SET) == -1) enomem(); made_replacements=0; has_misspelling=0; paragraph=0; for ( ; start_body < end_pos; start_body++) { int c=getc(fp); if (c < 0) enomem(); if (c != '\n') { buf_append(¤t_line, c); continue; } buf_append(¤t_line, '\0'); if (parnum) { --parnum; buf_cat(&newtext, current_line.ptr); buf_cat(&newtext, "\n"); current_line.cnt=0; ++paragraph; continue; } if (!checked) { int l; checked=1; if ((l=strlen(cgi("word"))) > 0) { /* Ok, what should we do? */ const char *newword=cgi("REPLACE"); if (!*newword || strcmp(newword, "#other") == 0) newword=cgi("OTHER"); /* ** Perhaps they entered the word without ** checking this checkmark. */ else if (*newword == '#') newword=""; if (*newword && pos + l <= strlen(current_line.ptr)) { struct buf tempbuf; buf_init(&tempbuf); buf_cpyn(&tempbuf, current_line.ptr, pos); buf_cat(&tempbuf, newword); buf_cat(&tempbuf, current_line.ptr+pos+l); pos += strlen(newword); if (*cgi("REPLACEALL")) { replacefrom=cgi("word"); replaceto=newword; } buf_append(&tempbuf, '\0'); buf_cpy(¤t_line, tempbuf.ptr); buf_append(¤t_line, '\0'); buf_free(&tempbuf); made_replacements=1; } else { pos += l; if (strcmp(cgi("REPLACE"), "#ignoreall") == 0) ignoreword=cgi("word"); } if (strcmp(cgi("REPLACE"), "#insert") == 0) { spelladd(cgi("word")); } } } if (*current_line.ptr == '>') { buf_cat(&newtext, current_line.ptr); buf_cat(&newtext, "\n"); pos=0; current_line.cnt=0; ++paragraph; continue; } if (!has_misspelling) { new_line=spell_check(current_line.ptr, paragraph, pos, ignoreword, replacefrom, replaceto, &has_misspelling); if (new_line) { buf_cat(&newtext, new_line); free(new_line); made_replacements=1; } else buf_cat(&newtext, current_line.ptr); } else buf_cat(&newtext, current_line.ptr); buf_cat(&newtext, "\n"); pos=0; current_line.cnt=0; ++paragraph; } if (current_line.cnt) buf_cat(&newtext, "\n"); rfc2045_free(rfcp); fclose(fp); if (made_replacements) { char *p=newmsg_createdraft_do(filename, newtext.ptr, NEWMSG_SQISPELL); if (p) free(p); if (*cgi("error")) { has_misspelling=0; /* Abort spell checking */ } } buf_free(&newtext); buf_free(¤t_line); if (*ignoreword) { static char *p=0; if (p) free(p); p=malloc(strlen(cgi("globignore")) + 2 + strlen(ignoreword)); if (!p) enomem(); strcpy(p, cgi("globignore")); if (*p) strcat(p, ":"); strcat(p, ignoreword); cgi_put("globignore", p); } if (*replacefrom) { static char *p=0; if (p) free(p); p=malloc(strlen(cgi("globreplace"))+3 +strlen(replacefrom)+strlen(replaceto)); if (!p) enomem(); strcpy(p, cgi("globreplace")); if (*p) strcat(p, ":"); strcat(strcat(strcat(p, replacefrom), ":"), replaceto); cgi_put("globreplace", p); free(p); } if (has_misspelling) return (1); return (0); }
void msgenvelope(void (*writefunc)(const char *, size_t), FILE *fp, struct rfc2045 *mimep) { char *date=0, *subject=0; char *from=0, *sender=0, *replyto=0, *to=0, *cc=0, *bcc=0; char *inreplyto=0, *msgid=0; off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; char *p, *q, *r; rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (fseek(fp, start_pos, SEEK_SET) < 0) { perror("fseek"); exit(0); } while ((p=read_header(fp, &start_pos, &start_body)) != 0) { char **hdrp=0; size_t oldl, newl; size_t c; if ((q=strchr(p, ':')) != 0) *q++=0; for (r=p; *r; r++) *r=tolower((int)(unsigned char)*r); if (strcmp(p, "date") == 0) hdrp= &date; if (strcmp(p, "subject") == 0) hdrp= &subject; if (strcmp(p, "from") == 0) hdrp= &from; if (strcmp(p, "sender") == 0) hdrp= &sender; if (strcmp(p, "reply-to") == 0) hdrp= &replyto; if (strcmp(p, "to") == 0) hdrp= &to; if (strcmp(p, "cc") == 0) hdrp= &cc; if (strcmp(p, "bcc") == 0) hdrp= &bcc; if (strcmp(p, "in-reply-to") == 0) hdrp= &inreplyto; if (strcmp(p, "message-id") == 0) hdrp= &msgid; if (!hdrp) continue; if (!q) q=""; oldl= *hdrp ? strlen(*hdrp):0; newl= strlen(q); c=oldl+newl+1; if (c > 8192) c=8192; r= (char *)(*hdrp ? realloc(*hdrp, c+1):malloc(c+1)); if (!r) { perror("malloc"); exit(1); } if (oldl && oldl < c) r[oldl++]=','; newl=c-oldl; if (newl) memcpy(r+oldl, q, newl); r[oldl+newl]=0; *hdrp= r; } #if 1 if (!replyto) replyto=strdup(from ? from:""); if (!sender) sender=strdup(from ? from:""); if (!replyto || !sender) { perror("malloc"); exit(1); } #endif (*writefunc)("(", 1); doenvs(writefunc, date); (*writefunc)(" ", 1); doenvs(writefunc, subject); (*writefunc)(" ", 1); doenva(writefunc, from); (*writefunc)(" ", 1); doenva(writefunc, sender); (*writefunc)(" ", 1); doenva(writefunc, replyto); (*writefunc)(" ", 1); doenva(writefunc, to); (*writefunc)(" ", 1); doenva(writefunc, cc); (*writefunc)(" ", 1); doenva(writefunc, bcc); (*writefunc)(" ", 1); doenvs(writefunc, inreplyto); (*writefunc)(" ", 1); doenvs(writefunc, msgid); (*writefunc)(")", 1); }
static void dsn(struct rfc2045 *p, int do_orig) { const char *content_type_s; const char *content_transfer_encoding_s; const char *charset_s; off_t start_pos, end_pos, start_body; off_t dummy; const char *q; char buf[BUFSIZ]; unsigned i; int ch; char *recip; char *action; char *orecip; rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s, &charset_s); if (strcasecmp(content_type_s, "multipart/report") || (q=rfc2045_getattr(p->content_type_attr, "report-type")) == 0 || strcasecmp(q, "delivery-status") || !p->firstpart || !p->firstpart->next || !p->firstpart->next->next) _exit(1); p=p->firstpart->next->next; rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s, &charset_s); rfc2045_mimepos(p, &start_pos, &end_pos, &start_body, &dummy, &dummy); if (strcasecmp(content_type_s, "message/delivery-status") || fseek(stdin, start_body, SEEK_SET) == -1) _exit(1); i=0; recip=0; orecip=0; action=0; while (start_body < end_pos) { if ((ch=getchar()) == EOF) break; ++start_body; if (i < sizeof(buf)-1) buf[i++]= ch; if (ch != '\n') continue; ch=getchar(); if (ch != EOF) ungetc(ch, stdin); if (ch != '\n' && isspace((int)(unsigned char)ch)) continue; buf[i-1]=0; if (buf[0] == 0) { if (orecip) { if (recip) free(recip); recip=orecip; orecip=0; } print_dsn_recip(recip, action); recip=0; action=0; } if (strncasecmp(buf, "Final-Recipient:", 16) == 0 && recip == 0) { recip=strdup(buf+16); if (!recip) { perror("strdup"); exit(2); } } if (strncasecmp(buf, "Original-Recipient:", 19) == 0 && orecip == 0 && do_orig) { orecip=strdup(buf+19); if (!orecip) { perror("strdup"); exit(2); } } if (strncasecmp(buf, "Action:", 7) == 0 && action == 0) { action=strdup(buf+7); if (!action) { perror("strdup"); exit(2); } } i=0; } if (orecip) { if (recip) free(recip); recip=orecip; orecip=0; } print_dsn_recip(recip, action); }
static void do_print_info(struct rfc2045 *s) { const char *content_type, *transfer_encoding, *charset; off_t start, end, body; const char *disposition; const char *disposition_name; const char *disposition_filename; const char *content_name; off_t nlines, nbodylines; const char *p; rfc2045_mimeinfo(s, &content_type, &transfer_encoding, &charset); rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines); rfc2045_dispositioninfo(s, &disposition, &disposition_name, &disposition_filename); content_name=rfc2045_contentname(s); printf("content-type: %s\n", content_type); if (content_name) { char *s=rfc2047_decode_simple(content_name); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-name: %s\n", s); free(s); } printf("content-transfer-encoding: %s\n", transfer_encoding); printf("charset: %s\n", charset); if (disposition && *disposition) printf("content-disposition: %s\n", disposition); if (disposition_name && *disposition_name) { char *s=rfc2047_decode_simple(disposition_name); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-disposition-name: %s\n", s); free(s); } if (disposition_filename && *disposition_filename) { char *s=rfc2047_decode_simple(disposition_filename); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-disposition-filename: %s\n", s); free(s); } if (*(p=rfc2045_content_id(s))) printf("content-id: <%s>\n", p); if (*(p=rfc2045_content_description(s))) { char *s=rfc2047_decode_simple(p); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-description: %s\n", s); free(s); } if (*(p=rfc2045_content_language(s))) printf("content-language: %s\n", p); if (*(p=rfc2045_content_md5(s))) printf("content-md5: %s\n", p); printf("starting-pos: %lu\n", (unsigned long)start); printf("starting-pos-body: %lu\n", (unsigned long)body); printf("ending-pos: %lu\n", (unsigned long)end); printf("line-count: %lu\n", (unsigned long)nlines); printf("body-line-count: %lu\n", (unsigned long)nbodylines); }
void msgbodystructure( void (*writefunc)(const char *, size_t), int dox, FILE *fp, struct rfc2045 *mimep) { const char *content_type_s; const char *content_transfer_encoding_s; const char *charset_s; off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; const char *disposition_s; char *p, *q; rfc2045_mimeinfo(mimep, &content_type_s, &content_transfer_encoding_s, &charset_s); rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); disposition_s=mimep->content_disposition; (*writefunc)("(", 1); if (mimep->firstpart && mimep->firstpart->isdummy && mimep->firstpart->next) /* MULTIPART */ { struct rfc2045 *childp; for (childp=mimep->firstpart; (childp=childp->next) != 0; ) msgbodystructure(writefunc, dox, fp, childp); (*writefunc)(" \"", 2); p=strchr(content_type_s, '/'); if (p) msgappends(writefunc, p+1, strlen(p+1)); (*writefunc)("\"", 1); if (dox) { (*writefunc)(" ", 1); do_param_list(writefunc, mimep->content_type_attr); (*writefunc)(" ", 1); do_disposition(writefunc, disposition_s, mimep->content_disposition_attr); (*writefunc)(" ", 1); contentstr(writefunc, rfc2045_content_language(mimep)); } } else { char *mybuf; char buf[40]; const char *cp; mybuf=my_strdup(content_type_s); q=strtok(mybuf, " /"); (*writefunc)("\"", 1); if (q) msgappends(writefunc, q, strlen(q)); (*writefunc)("\" \"", 3); if (q) q=strtok(0, " /"); if (q) msgappends(writefunc, q, strlen(q)); free(mybuf); (*writefunc)("\" ", 2); do_param_list(writefunc, mimep->content_type_attr); (*writefunc)(" ", 1); cp=rfc2045_content_id(mimep); if (!cp || !*cp) contentstr(writefunc, cp); else { (*writefunc)("\"<", 2); msgappends(writefunc, cp, strlen(cp)); (*writefunc)(">\"", 2); } (*writefunc)(" ", 1); contentstr(writefunc, rfc2045_content_description(mimep)); (*writefunc)(" \"", 2); msgappends(writefunc, content_transfer_encoding_s, strlen(content_transfer_encoding_s)); (*writefunc)("\" ", 2); sprintf(buf, "%lu", (unsigned long) (end_pos-start_body+nbodylines)); /* nbodylines added for CRs */ (*writefunc)(buf, strlen(buf)); if ( (content_type_s[0] == 't' || content_type_s[0] == 'T') && (content_type_s[1] == 'e' || content_type_s[1] == 'E') && (content_type_s[2] == 'x' || content_type_s[2] == 'X') && (content_type_s[3] == 't' || content_type_s[3] == 'T') && (content_type_s[4] == '/' || content_type_s[4] == 0)) { (*writefunc)(" ", 1); sprintf(buf, "%lu", (unsigned long)nbodylines); (*writefunc)(buf, strlen(buf)); } if (mimep->firstpart && !mimep->firstpart->isdummy) /* message/rfc822 */ { (*writefunc)(" ", 1); msgenvelope(writefunc, fp, mimep->firstpart); (*writefunc)(" ", 1); msgbodystructure(writefunc, dox, fp, mimep->firstpart); (*writefunc)(" ", 1); sprintf(buf, "%lu", (unsigned long)nbodylines); (*writefunc)(buf, strlen(buf)); } if (dox) { (*writefunc)(" ", 1); contentstr(writefunc, rfc2045_content_md5(mimep)); (*writefunc)(" ", 1); do_disposition(writefunc, disposition_s, mimep->content_disposition_attr); (*writefunc)(" NIL", 4); /* TODO Content-Language: */ } } (*writefunc)(")", 1); }
static void dofetchheadersbuf(FILE *fp, struct fetchinfo *fi, struct imapscaninfo *info, unsigned long msgnum, struct rfc2045 *mimep, int (*headerfunc)(struct fetchinfo *fi, const char *)) { off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; size_t i,j,k,l; char buf[BUFSIZ+2]; int goodheader; unsigned long skipping; unsigned long cnt; char *p; int ii; rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (fseek(fp, start_pos, SEEK_SET) == -1) { writes("{0}\r\n"); fetcherror("fseek", fi, info, msgnum); return; } ii=fread(buf, 1, start_body - start_pos, fp); if (ii < 0 || (i=ii) != start_body - start_pos) { fetcherror("unexpected EOF", fi, info, msgnum); exit(1); } goodheader= (*headerfunc)(fi, ""); l=0; for (j=0; j<i; ) { if (buf[j] != '\n' && buf[j] != '\r' && !isspace((int)(unsigned char)buf[j])) { goodheader= (*headerfunc)(fi, ""); for (k=j; k<i; k++) { if (buf[k] == '\n' || buf[k] == ':') break; } if (k < i && buf[k] == ':') { buf[k]=0; goodheader=(*headerfunc)(fi, buf+j); buf[k]=':'; } } else if (buf[j] == '\n') goodheader=0; for (k=j; k<i; k++) if (buf[k] == '\n') { ++k; break; } if (goodheader) { while (j<k) buf[l++]=buf[j++]; } j=k; } buf[l++]='\n'; /* Always append a blank line */ cnt=l; for (i=0; i<l; i++) if (buf[i] == '\n') ++cnt; skipping=0; if (fi->ispartial) { skipping=fi->partialstart; if (skipping > cnt) skipping=cnt; cnt -= skipping; if (fi->ispartial > 1 && cnt > fi->partialend) cnt=fi->partialend; } writes("{"); writen(cnt); writes("}\r\n"); p=buf; while (skipping) { if (*p == '\n') { --skipping; if (skipping == 0) { if (cnt) { writes("\n"); --cnt; } break; } } --skipping; ++p; } while (cnt) { if (*p == '\n') { writes("\r"); if (--cnt == 0) break; writes("\n"); --cnt; ++p; continue; } for (i=0; i<cnt; i++) if (p[i] == '\n') break; writemem(p, i); p += i; cnt -= i; header_count += i; } }
static void dofetchmsgbody(FILE *fp, struct fetchinfo *fi, struct imapscaninfo *i, unsigned long msgnum, struct rfc2045 *mimep) { const char *p=fi->bodysection; off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; unsigned long cnt; char buf[BUFSIZ]; char rbuf[BUFSIZ]; char *rbufptr; int rbufleft; unsigned long bufptr; unsigned long skipping; int ismsgrfc822=1; off_t start_seek_pos; struct rfc2045 *headermimep; /* ** To optimize consecutive FETCHes, we cache our virtual and physical ** position. What we do is that on the first fetch we count off the ** characters we read, and keep track of both the physical and the CRLF-based ** offset into the message. Then, on subsequent FETCHes, we attempt to ** use that information. */ off_t cnt_virtual_chars; off_t cnt_phys_chars; off_t cache_virtual_chars; off_t cache_phys_chars; headermimep=mimep; while (p && isdigit((int)(unsigned char)*p)) { unsigned long n=0; headermimep=mimep; do { n=n*10 + (*p++ - '0'); } while (isdigit((int)(unsigned char)*p)); if (mimep) { if (ismsgrfc822) { const char *ct, *dummy; if (mimep->firstpart == 0) { /* Not a multipart, n must be 1 */ if (n != 1) mimep=0; if (*p == '.') ++p; continue; } ismsgrfc822=0; rfc2045_mimeinfo(mimep, &ct, &dummy, &dummy); if (ct && strcasecmp(ct, "message/rfc822" ) == 0) ismsgrfc822=1; /* The content is another message/rfc822 */ } mimep=mimep->firstpart; while (mimep) { if (!mimep->isdummy && --n == 0) break; mimep=mimep->next; } headermimep=mimep; if (mimep && mimep->firstpart && !mimep->firstpart->isdummy) /* This is a message/rfc822 part */ { if (!*p) break; mimep=mimep->firstpart; ismsgrfc822=1; } } if (*p == '.') ++p; } if (p && strcmp(p, "MIME") == 0) mimep=headermimep; if (mimep == 0) { writes("{0}\r\n"); return; } rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (p && strcmp(p, "TEXT") == 0) { start_seek_pos=start_body; cnt=end_pos - start_body + nbodylines; } else if (p && strcmp(p, "HEADER") == 0) { start_seek_pos=start_pos; cnt= start_body - start_pos + (nlines - nbodylines); } else if (p && strcmp(p, "HEADER.FIELDS") == 0) { if (start_body - start_pos <= BUFSIZ) dofetchheadersbuf(fp, fi, i, msgnum, mimep, &dofetchheaderfields); else dofetchheadersfile(fp, fi, i, msgnum, mimep, &dofetchheaderfields); return; } else if (p && strcmp(p, "HEADER.FIELDS.NOT") == 0) { if (start_body - start_pos <= BUFSIZ) dofetchheadersbuf(fp, fi, i, msgnum, mimep, &dofetchheadernotfields); else dofetchheadersfile(fp, fi, i, msgnum, mimep, &dofetchheadernotfields); return; } else if (p && strcmp(p, "MIME") == 0) { if (start_body - start_pos <= BUFSIZ) dofetchheadersbuf(fp, fi, i, msgnum, mimep, &dofetchheadermime); else dofetchheadersfile(fp, fi, i, msgnum, mimep, &dofetchheadermime); return; } else if (*fi->bodysection == 0) { start_seek_pos=start_pos; cnt= end_pos - start_pos + nlines; } else /* Last possibility: entire body */ { start_seek_pos=start_body; cnt= end_pos - start_body + nbodylines; } skipping=0; if (fi->ispartial) { skipping=fi->partialstart; if (skipping > cnt) skipping=cnt; cnt -= skipping; if (fi->ispartial > 1 && cnt > fi->partialend) cnt=fi->partialend; } if (get_cached_offsets(start_seek_pos, &cnt_virtual_chars, &cnt_phys_chars) == 0 && cnt_virtual_chars <= skipping) /* Yeah - cache it, baby! */ { if (fseek(fp, start_seek_pos+cnt_phys_chars, SEEK_SET) == -1) { writes("{0}\r\n"); fetcherror("fseek", fi, i, msgnum); return; } skipping -= cnt_virtual_chars; } else { if (fseek(fp, start_seek_pos, SEEK_SET) == -1) { writes("{0}\r\n"); fetcherror("fseek", fi, i, msgnum); return; } cnt_virtual_chars=0; cnt_phys_chars=0; } cache_virtual_chars=cnt_virtual_chars; cache_phys_chars=cnt_phys_chars; writes("{"); writen(cnt); writes("}\r\n"); bufptr=0; writeflush(); rbufptr=0; rbufleft=0; while (cnt) { int c; if (!rbufleft) { rbufleft=fread(rbuf, 1, sizeof(rbuf), fp); if (rbufleft < 0) rbufleft=0; rbufptr=rbuf; } if (!rbufleft) { fetcherror("unexpected EOF", fi, i, msgnum); _exit(1); } --rbufleft; c=(int)(unsigned char)*rbufptr++; ++cnt_phys_chars; if (c == '\n') { ++cnt_virtual_chars; if (skipping) --skipping; else { if (bufptr >= sizeof(buf)) { writemem(buf, sizeof(buf)); bufptr=0; /*writeflush();*/ } buf[bufptr++]='\r'; --cnt; if (cnt == 0) break; } } ++cnt_virtual_chars; if (skipping) --skipping; else { ++body_count; if (bufptr >= sizeof(buf)) { writemem(buf, sizeof(buf)); bufptr=0; /*writeflush();*/ } buf[bufptr++]=c; --cnt; } cache_virtual_chars=cnt_virtual_chars; cache_phys_chars=cnt_phys_chars; } writemem(buf, bufptr); writeflush(); save_cached_offsets(start_seek_pos, cache_virtual_chars, cache_phys_chars); }
static void dofetchheadersfile(FILE *fp, struct fetchinfo *fi, struct imapscaninfo *info, unsigned long msgnum, struct rfc2045 *mimep, int (*headerfunc)(struct fetchinfo *fi, const char *)) { off_t start_pos, end_pos, start_body, left; off_t nlines, nbodylines; size_t i; int c, pass; char buf1[256]; int goodheader; struct fetchheaderinfo finfo; finfo.cnt=0; for (pass=0; pass<2; pass++) { void (*func)(struct fetchheaderinfo *, const char *, size_t)= pass ? printheader:countheader; rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (fseek(fp, start_pos, SEEK_SET) == -1) { writes("{0}\r\n"); fetcherror("fseek", fi, info, msgnum); return; } if (pass) { finfo.skipping=0; if (fi->ispartial) { finfo.skipping=fi->partialstart; if (finfo.skipping > finfo.cnt) finfo.skipping=finfo.cnt; finfo.cnt -= finfo.skipping; if (fi->ispartial > 1 && finfo.cnt > fi->partialend) finfo.cnt=fi->partialend; } writes("{"); writen(finfo.cnt+2); /* BUG */ writes("}\r\n"); } left=start_body - start_pos; goodheader= (*headerfunc)(fi, ""); while (left) { for (i=0; i<sizeof(buf1)-1 && i<left; i++) { c=getc(fp); if (c == EOF) { fetcherror("unexpected EOF", fi, info, msgnum); _exit(1); } if (c == '\n' || c == ':') { ungetc(c, fp); break; } buf1[i]=c; } buf1[i]=0; left -= i; if (buf1[0] != '\n' && buf1[0] != '\r' && !isspace((int)(unsigned char)buf1[0])) goodheader= (*headerfunc)(fi, buf1); else if (buf1[0] == '\n') goodheader=0; if (!goodheader) { while (left) { c=getc(fp); --left; if (c == EOF) { fetcherror("unexpected EOF", fi, info, msgnum); _exit(1); } if (c == '\n') break; } continue; } (*func)(&finfo, buf1, i); i=0; while (left) { c=getc(fp); if (c == EOF) { fetcherror("unexpected EOF", fi, info, msgnum); _exit(1); } --left; if (i >= sizeof(buf1)) { (*func)(&finfo, buf1, i); i=0; } if (c == '\n') { (*func)(&finfo, buf1, i); buf1[0]='\r'; i=1; } buf1[i++]=c; if (c == '\n') break; } (*func)(&finfo, buf1, i); if (pass && finfo.cnt == 0) break; } } writes("\r\n"); /* BUG */ }