/* * sz is size of 'line' buffer in bytes. Must be reasonably * long enough to hold one physical real-world e-mail line. */ static int read_one_header_line(char *line, int sz, FILE *in) { int len; /* * We will read at most (sz-1) bytes and then potentially * re-add NUL after it. Accessing line[sz] after this is safe * and we can allow len to grow up to and including sz. */ sz--; /* Get the first part of the line. */ if (!fgets(line, sz, in)) return 0; /* * Is it an empty line or not a valid rfc2822 header? * If so, stop here, and return false ("not a header") */ len = eatspace(line); if (!len || !is_rfc2822_header(line)) { /* Re-add the newline */ line[len] = '\n'; line[len + 1] = '\0'; return 0; } /* * Now we need to eat all the continuation lines.. * Yuck, 2822 header "folding" */ for (;;) { int peek, addlen; static char continuation[1000]; peek = fgetc(in); ungetc(peek, in); if (peek != ' ' && peek != '\t') break; if (!fgets(continuation, sizeof(continuation), in)) break; addlen = eatspace(continuation); if (len < sz - 1) { if (addlen >= sz - len) addlen = sz - len - 1; memcpy(line + len, continuation, addlen); line[len] = '\n'; len += addlen; } } line[len] = 0; return 1; }
static int read_one_header_line(struct strbuf *line, FILE *in) { struct strbuf continuation = STRBUF_INIT; /* Get the first part of the line. */ if (strbuf_getline_lf(line, in)) return 0; /* * Is it an empty line or not a valid rfc2822 header? * If so, stop here, and return false ("not a header") */ strbuf_rtrim(line); if (!line->len || !is_rfc2822_header(line)) { /* Re-add the newline */ strbuf_addch(line, '\n'); return 0; } /* * Now we need to eat all the continuation lines.. * Yuck, 2822 header "folding" */ for (;;) { int peek; peek = fgetc(in); if (peek == EOF) break; ungetc(peek, in); if (peek != ' ' && peek != '\t') break; if (strbuf_getline_lf(&continuation, in)) break; continuation.buf[0] = ' '; strbuf_rtrim(&continuation); strbuf_addbuf(line, &continuation); } strbuf_release(&continuation); return 1; }