*/
static enum threestate is_falted(FILE *);
static size_t copyname(char *, char *);
+static int is_separator(char *);
/*
-** For the states FLD2, BODY2 and FMTERR2 memory is allocated for f->value.
-** For the states LENERR2, ERR2 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)
ssize_t nchars;
enum threestate falted;
- nchars = getline(&tmpline, &len, msg);
- if (nchars == -1) {
- if (feof(msg)) {
- return FILEEOF2;
- } else {
- return ERR2;
+ switch (s) {
+ case FLD2:
+ nchars = getline(&tmpline, &len, msg);
+ if (nchars < 1) {
+ if (feof(msg)) {
+ return FILEEOF2;
+ } else {
+ return IOERR2;
+ }
}
- }
- if (nchars >= NAMESZ) {
- free(tmpline);
- return LENERR2;
- }
+ *f->name = '\0';
+ f->namelen = 0;
- *f->name = '\0';
- f->namelen = 0;
+ if (nchars >= NAMESZ) {
+ if (f->value) {
+ free(f->value);
+ }
+ f->value = tmpline;
+ f->valuelen = nchars;
+ return LENERR2;
+ }
- switch (s) {
- case FLD2:
if (*(tmpline + nchars - 1) != '\n') {
if (f->value) {
free(f->value);
return FMTERR2;
}
- if (nchars > 0 && (*tmpline == '\n' || *tmpline == '-')) {
+ if (is_separator(tmpline)) {
/* header/body separator found */
free(tmpline);
return m_getfld2(BODY2, f, msg);
nchars = getline(&tmpline, &len, msg);
if (nchars <= 0) {
free(tmpline);
- return ERR2;
+ return IOERR2;
}
if (nchars >= NAMESZ) {
- free(tmpline);
+ if (f->value) {
+ free(f->value);
+ }
+ f->value = tmpline;
+ f->valuelen = nchars;
return LENERR2;
}
if (falted == FAIL) {
free(tmpline);
- return ERR2;
+ return IOERR2;
}
free(tmpline);
return FLD2;
case BODY2:
+ nchars = getline(&tmpline, &len, msg);
+ if (nchars < 1) {
+ if (feof(msg)) {
+ return FILEEOF2;
+ } else {
+ return IOERR2;
+ }
+ }
+
+ *f->name = '\0';
+ f->namelen = 0;
+
+ if (nchars >= NAMESZ) {
+ if (f->value) {
+ free(f->value);
+ }
+ f->value = tmpline;
+ f->valuelen = nchars;
+ return LENERR2;
+ }
if (f->value) {
free(f->value);
}
copyname(char *dst, char *src)
{
size_t len;
- char *sep = strchr(src, ':');
+ char *cp, *sep;
- if (!sep) {
+ if (!(sep = strchr(src, ':'))) {
return 0;
}
+ /* whitespace is forbidden in name */
+ for (cp=src; cp<sep; cp++) {
+ if (isspace(*cp)) {
+ return 0;
+ }
+ }
len = sep - src;
if (len >= NAMESZ) {
return strlen(dst);
}
+
+static int
+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) {
+ return 1;
+ }
+ return 0;
+}