X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=sbr%2Fm_getfld2.c;h=6545d0f7539632b54a6f50d92b43f151b4c12d71;hp=59204252d7f8c5eec7305138825e097ca0e1c601;hb=a87df3543d3bc128ba4079d1f95638476ba5ca50;hpb=a3d849510ecad775e265ab7b6090e85576f48ef7 diff --git a/sbr/m_getfld2.c b/sbr/m_getfld2.c index 5920425..6545d0f 100644 --- a/sbr/m_getfld2.c +++ b/sbr/m_getfld2.c @@ -10,6 +10,7 @@ #include #include #include +#include enum threestate { @@ -23,11 +24,24 @@ enum threestate { */ static enum threestate is_falted(FILE *); static size_t copyname(char *, char *); +static bool is_separator(char *); + +struct field free_field = { "\0", 0, NULL, 0, 0 }; /* -** For the states FLD2, BODY2 and FMTERR2 memory is allocated for f->value. -** For the states LENERR2, IOERR2 and FILEEOF2 no memory is allocated. +** FLD2: We read a (complete) header field +** BODY2: We read a body line +** LENERR2: Line is too long (>998, as defined by RFC 822) +** FMTERR2: Header field invalid +** IOERR2: Failure to read +** FILEEOF2: We're at the end of the file +** +** f->name is only filled in FLD2. +** +** In FLD2, f->value contains the field's (complete) value only; +** in BODY2, LENERR2 and FMTERR2 f->value contains the whole line; +** in IOERR2 and FILEEOF2 f->value is not set. */ enum state m_getfld2(enum state s, struct field *f, FILE *msg) @@ -35,38 +49,31 @@ m_getfld2(enum state s, struct field *f, FILE *msg) char *tmpline = NULL; size_t len = 0; ssize_t nchars; - enum threestate falted; + enum threestate falted = B_FALSE; + enum state ret = s; - nchars = getline(&tmpline, &len, msg); - if (nchars == -1) { - if (feof(msg)) { - return FILEEOF2; - } else { - return IOERR2; + switch (s) { + case FLD2: + nchars = getline(&tmpline, &len, msg); + if (nchars < 1) { + free(f->value); + *f = free_field; + if (feof(msg)) { + return FILEEOF2; + } else { + return IOERR2; + } } - } - if (nchars >= NAMESZ) { - free(tmpline); - return LENERR2; - } - - *f->name = '\0'; - f->namelen = 0; + if (nchars >= NAMESZ) { + ret = LENERR2; + } - switch (s) { - case FLD2: if (*(tmpline + nchars - 1) != '\n') { - if (f->value) { - free(f->value); - } - f->value = tmpline; - f->valuelen = nchars; - f->alloclen = len; - return FMTERR2; + ret = FMTERR2; } - if (nchars > 0 && (*tmpline == '\n' || *tmpline == '-')) { + if (ret == FLD2 && is_separator(tmpline)) { /* header/body separator found */ free(tmpline); return m_getfld2(BODY2, f, msg); @@ -74,13 +81,9 @@ m_getfld2(enum state s, struct field *f, FILE *msg) f->namelen = copyname(f->name, tmpline); if (f->namelen < 1) { - if (f->value) { - free(f->value); - } - f->value = tmpline; - f->valuelen = nchars; - f->alloclen = len; - return FMTERR2; + *f->name = '\0'; + f->namelen = 0; + ret = FMTERR2; } /* copy the field's value */ @@ -88,10 +91,15 @@ m_getfld2(enum state s, struct field *f, FILE *msg) f->value = mh_xrealloc(f->value, f->alloclen + len); f->alloclen += len; } - strcpy(f->value, tmpline + f->namelen + 1); - f->valuelen = nchars - f->namelen - 1; + if (f->namelen != 0) { + strcpy(f->value, tmpline + f->namelen + 1); + f->valuelen = nchars - f->namelen - 1; + } else { + strcpy(f->value, tmpline); + f->valuelen = nchars; + } - while ((falted = is_falted(msg)) == B_TRUE) { + while (ret == FLD2 && (falted = is_falted(msg)) == B_TRUE) { nchars = getline(&tmpline, &len, msg); if (nchars <= 0) { free(tmpline); @@ -99,18 +107,11 @@ m_getfld2(enum state s, struct field *f, FILE *msg) } if (nchars >= NAMESZ) { - free(tmpline); - return LENERR2; + ret = LENERR2; } if (*(tmpline + nchars - 1) != '\n') { - if (f->value) { - free(f->value); - } - f->value = tmpline; - f->valuelen = nchars; - f->alloclen = len; - return FMTERR2; + ret = FMTERR2; } if (f->alloclen - f->valuelen <= nchars) { @@ -124,21 +125,34 @@ m_getfld2(enum state s, struct field *f, FILE *msg) } if (falted == FAIL) { - free(tmpline); - return IOERR2; + ret = IOERR2; } free(tmpline); - return FLD2; + return ret; case BODY2: - if (f->value) { - free(f->value); + free(f->value); + *f = free_field; + + nchars = getline(&tmpline, &len, msg); + if (nchars < 1) { + free(tmpline); + if (feof(msg)) { + return FILEEOF2; + } else { + return IOERR2; + } + } + + if (nchars >= NAMESZ) { + ret = LENERR2; } + f->value = tmpline; f->valuelen = nchars; f->alloclen = len; - return BODY2; + return ret; default: /* give error states back as received */ @@ -197,3 +211,19 @@ copyname(char *dst, char *src) return strlen(dst); } + +static bool +is_separator(char *line) +{ + /* + ** In MH, lines that are consists of dashes only are + ** separators as well ... not so in RFC 822. + */ + while (*line == '-') { + line++; + } + if (strcmp("\n", line) == 0 || strcmp("\r\n", line) == 0 ) { + return true; + } + return false; +}