--- src/greeting.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/greeting.cc 5 Sep 2003 07:44:16 -0000 1.2 @@ -65,7 +65,7 @@ char mytime[ISO8601SIZE]; unsigned int size = strftime(mytime, sizeof(mytime), - "%Y-%m-%d %I:%M:%S %Z", mytm); + "%Y-%m-%d %H:%M:%S %Z", mytm); if (size >= sizeof(mytime)) mytime[0] = 0; --- src/maildirmessage.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/maildirmessage.cc 5 Sep 2003 22:08:55 -0000 1.3 @@ -403,9 +403,9 @@ // CONTENT-LOCATION io << " "; printOneHeader(io, message, "content-location"); - - io << ")"; } + + io << ")"; } } } @@ -731,8 +731,6 @@ if (fd == -1) return false; - rewind(); - // FIXME: parse errors if (!doc) doc = new MimeDocument; @@ -756,8 +754,6 @@ if (fd == -1) return false; - rewind(); - // FIXME: parse errors if (!doc) doc = new MimeDocument; @@ -795,7 +791,8 @@ std::vector headers, bool includeHeaders, unsigned int startOffset, - unsigned int length) const + unsigned int length, + bool mime) const { IO &com = IOFactory::getInstance().get(1); com << storage; @@ -808,7 +805,8 @@ std::vector headers, bool includeHeaders, unsigned int startOffset, - unsigned int length) const + unsigned int length, + bool mime) const { IO &com = IOFactory::getInstance().get(1); @@ -818,7 +816,7 @@ } else if (!parseFull()) return false; - const MimePart *part = doc->getPart(section, ""); + const MimePart *part = doc->getPart(section, "", mime ? MimePart::FetchMime : MimePart::FetchHeader); if (!part) { storage = ""; return 0; @@ -828,8 +826,6 @@ if (fd == -1) return false; - rewind(); - storage = ""; unsigned int size = part->printHeader(fd, com, headers, includeHeaders, startOffset, @@ -869,8 +865,6 @@ if (fd == -1) return false; - rewind(); - storage = ""; unsigned int size = part->printBody(fd, com, startOffset, length, storage, /* store */ true, @@ -908,8 +902,6 @@ if (fd == -1) return false; - rewind(); - storage = ""; unsigned int size = part->printDoc(fd, com, startOffset, length, storage, /* store = */ true, @@ -947,13 +939,11 @@ if (fd == -1) return false; - rewind(); - crlffile = fd; crlfReset(); char c; - for (int i = 0; i < doc->getBodyStartOffset(); ++i) + for (unsigned int i = 0; i < doc->getBodyStartOffset(); ++i) if (!crlfGetChar(c)) break; @@ -982,8 +972,6 @@ int fd = getFile(); if (fd == -1) return false; - - rewind(); crlffile = fd; crlfReset(); --- src/maildirmessage.h 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/maildirmessage.h 5 Sep 2003 21:11:46 -0000 1.2 @@ -100,12 +100,14 @@ std::vector headers, bool includeHeaders = false, unsigned int startOffset = 0, - unsigned int length = UINTMAX) const; + unsigned int length = UINTMAX, + bool mime = false) const; unsigned int getHeaderSize(const std::string §ion, std::vector headers, bool includeHeaders = false, unsigned int startOffset = 0, - unsigned int length = UINTMAX) const; + unsigned int length = UINTMAX, + bool mime = false) const; bool printBody(const std::string §ion = "", unsigned int startOffset = 0, --- src/message.h 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/message.h 5 Sep 2003 21:11:46 -0000 1.2 @@ -103,12 +103,14 @@ std::vector headers, bool includeHeaders = false, unsigned int startOffset = 0, - unsigned int length = UINTMAX) const = 0; + unsigned int length = UINTMAX, + bool mime = false) const = 0; virtual unsigned int getHeaderSize(const std::string §ion, std::vector headers, bool includeHeaders = false, unsigned int startOffset = 0, - unsigned int length = UINTMAX) const = 0; + unsigned int length = UINTMAX, + bool mime = false) const = 0; virtual bool printBody(const std::string §ion, unsigned int startOffset = 0, --- src/mime-getpart.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-getpart.cc 5 Sep 2003 21:11:46 -0000 1.2 @@ -53,7 +53,7 @@ //------------------------------------------------------------------------ const Binc::MimePart *Binc::MimePart::getPart(const string &findpart, - string genpart) const + string genpart, FetchType fetchType) const { if (findpart == genpart) return this; @@ -71,8 +71,13 @@ ss << part; const MimePart *m; - if ((m = (*i).getPart(findpart, ss.str())) != 0) + if ((m = (*i).getPart(findpart, ss.str())) != 0) { + + if (fetchType == FetchHeader && m->isMessageRFC822()) + m = &m->members[0]; + return m; + } ++i; ++part; @@ -83,7 +88,7 @@ const MimePart *m = members[0].getPart(findpart, genpart); return m; } else { - // error in doc. skip part. + return 0; } } else { // Singlepart --- src/mime-parsefull.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-parsefull.cc 6 Sep 2003 08:57:49 -0000 1.4 @@ -54,8 +54,9 @@ int crlffile = 0; char crlfdata[4096]; -int crlftail = 0; -int crlfhead = 0; +unsigned int crlftail = 0; +unsigned int crlfhead = 0; +unsigned int crlfoffset = 0; char lastchar = '\0'; //------------------------------------------------------------------------ @@ -63,10 +64,10 @@ { char raw[1024]; - size_t nbytes; + ssize_t nbytes; for (;;) { - nbytes = read(crlffile, raw, sizeof(raw)); - if (nbytes == 0) { + nbytes = read(crlffile, raw, sizeof(raw) - 1); + if (nbytes <= 0) { // FIXME: If ferror(crlffile) we should log this. return false; } @@ -81,6 +82,7 @@ crlfdata[crlftail++ & 0xfff] = '\r'; crlfdata[crlftail++ & 0xfff] = '\n'; } + break; case '\n': crlfdata[crlftail++ & 0xfff] = '\r'; crlfdata[crlftail++ & 0xfff] = '\n'; @@ -113,62 +115,48 @@ crlffile = fd; crlfReset(); - headerstartoffset = 0; + headerstartoffsetcrlf = 0; headerlength = 0; - bodystartoffset = 0; + bodystartoffsetcrlf = 0; bodylength = 0; - size = -1; + size = 0; messagerfc822 = false; multipart = false; - int crlfnr = 0; - int bytenr = 0; - MimePart::parseFull(fd, "", bytenr, crlfnr); + int bsize = 0; + MimePart::parseFull("", bsize); - size = crlfnr; + size = crlfoffset; } //------------------------------------------------------------------------ -int Binc::MimePart::parseFull(int fd, const string &toboundary, int &bytenr, int &crlfnr) const +int Binc::MimePart::parseFull(const string &toboundary, int &boundarysize) const { - static int level = 0; - string name; string content; char cqueue[4]; memset(cqueue, 0, sizeof(cqueue)); - headerstartoffset = bytenr; - int headerstartoffsetcrlf = crlfnr; - - bool breakheader = false; bool quit = false; char c; bool eof = false; + headerstartoffsetcrlf = crlfoffset; + while (!quit) { // read name while (1) { if (!crlfGetChar(c)) { - eof = true; quit = true; break; } - ++crlfnr; if (c == '\n') ++nlines; - if (c != '\r') ++bytenr; if (c == ':') break; if (c == '\n') { - --bytenr; - for (int i = name.length() - 1; i >= 0; --i) { + for (int i = name.length() - 1; i >= 0; --i) crlfUnGetChar(); - --crlfnr; - if (name[i] != '\r') --bytenr; - } - quit = true; - breakheader = true; name = ""; break; } @@ -187,18 +175,15 @@ break; } - if (eof) break; + if (quit) break; while (!quit) { if (!crlfGetChar(c)) { - eof = true; quit = true; break; } - ++crlfnr; if (c == '\n') ++nlines; - if (c != '\r') ++bytenr; for (int i = 0; i < 3; ++i) cqueue[i] = cqueue[i + 1]; @@ -219,7 +204,7 @@ trim(content); h.add(name, content); - + name = c; content = ""; break; @@ -230,15 +215,25 @@ } } - if (eof) - return 1; - if (name != "") { if (content.length() > 2) content.resize(content.length() - 2); h.add(name, content); } - + + // Headerlength includes the seperating CRLF. Body starts after the + // CRLF. + headerlength = crlfoffset - headerstartoffsetcrlf; + bodystartoffsetcrlf = crlfoffset; + + // If we encounter the end of file, we return 1 as if we found our + // parent's terminal boundary. This will cause a safe exit, and + // whatever we parsed until now will be available. + if (eof) + return 1; + + // Do simple parsing of headers to determine the + // type of message (multipart,messagerfc822 etc) HeaderItem ctype; if (h.getFirstHeader("content-type", ctype)) { vector types; @@ -286,146 +281,132 @@ } bool foundendofpart = false; - headerlength = crlfnr - headerstartoffsetcrlf; - if (headerlength < 0) headerlength = 0; - - int bodystartoffsetcrlf = crlfnr; - bodystartoffset = bytenr; - if (messagerfc822) { // message rfc822 means a completely enclosed mime document. we // call the parser recursively, and pass on the boundary string // that we got. when parse() finds this boundary, it returns. MimePart m; - level += 3; - int n = m.parseFull(fd, toboundary, bytenr, crlfnr); + + // parsefull returns the number of bytes that need to be removed + // from the body because of the terminating boundary string. + int bsize; + if (m.parseFull(toboundary, bsize)) + foundendofpart = true; + bodylength = crlfoffset - bodystartoffsetcrlf - bsize; nbodylines += m.getNofLines(); members.push_back(m); - level -= 3; - - // if the enclosed doc ended with _our_ boundary string - if (n == 1) - foundendofpart = true; - else - foundendofpart = false; } else if (multipart) { // multipart parsing starts with skipping to the first // boundary. then we call parse() for all parts. the last parse() // command will return a code indicating that it found the last // boundary of this multipart. - string _boundary = "--"; _boundary += boundary; + string _boundary = "\r\n--"; _boundary += boundary; char *boundaryqueue = 0; int endpos = _boundary.length(); boundaryqueue = new char[endpos]; int boundarypos = 0; bool eof = false; - - // first, skip to the first _boundary string - while (1) { + + // first, skip to the first boundary string. Anything between the + // header and the first boundary string is simply ignored (it's + // usually a text message intended for non-mime clients) + do { if (!crlfGetChar(c)) { eof = true; break; } - ++crlfnr; - if (c == '\n') { ++nbodylines; ++nlines; } - if (c != '\r') ++bytenr; + + if (c == '\n') + ++nlines; boundaryqueue[boundarypos++ % endpos] = c; - - if (compareStringToQueue(_boundary, boundaryqueue, boundarypos, endpos)) { - boundaryqueue[0] = '\0'; - - char a; - if (!crlfGetChar(a)) { - eof = true; - quit = true; - break; - } - ++crlfnr; - if (a == '\n') { /* ++nbodylines; ++nlines; */ } - if (a != '\r') ++bytenr; + // Fixme: Must also check for all parents' boundary. + } while (!compareStringToQueue(_boundary, boundaryqueue, boundarypos, endpos)); - char b; - if (!crlfGetChar(b)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines;*/ } - if (b != '\r') ++bytenr; - - if (a == '-' && b == '-') { - if (!crlfGetChar(a)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines; */ } - if (a != '\r') ++bytenr; - - if (a == '\r') { - if (!crlfGetChar(b)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines; */ } - if (b != '\r') ++bytenr; - - if (b != '\n') { - // FIXME: barf! - } - } else { - // FIXME: barf!! - } - - foundendofpart = true; - } - - break; - } + delete boundaryqueue; + + // Read two more characters. This may be CRLF, it may be "--" and + // it may be any other two characters. + char a; + if (!crlfGetChar(a)) + eof = true; + + if (a == '\n') + ++nlines; + + char b; + if (!crlfGetChar(b)) + eof = true; + + if (b == '\n') + ++nlines; + + // If we find two dashes after the boundary, then this is the end + // of boundary marker. + if (!eof && (a == '-' && b == '-')) { + foundendofpart = true; + + if (!crlfGetChar(a)) + eof = true; + + if (a == '\n') + ++nlines; + + if (!crlfGetChar(b)) + eof = true; + + if (b == '\n') + ++nlines; } - if (boundaryqueue != 0) - delete boundaryqueue; + // This is really a special case: If the first boundary marker for + // some reason was the end of boundary, then return. + if (foundendofpart) { + bodylength = crlfoffset - bodystartoffsetcrlf; + boundarysize = 0; + return 1; + } + + // If the boundary is not followed by CRLF or "--", then leave + // those two bytes and immediately start parsing the mime part. + if (!eof && !(a == '\r' && b == '\n')) { + crlfUnGetChar(); + crlfUnGetChar(); + } - // at this point, we found the first boundary and we ate it. the next - // consecutive calls to parse() will all have given that the start of - // the input is the start of the part, straight after the boundary. + // read all mime parts. if (!eof && !foundendofpart) { + // then, parse all the parts bool quit = false; - while (!quit) { + do { MimePart m; - level += 3; - if (m.parseFull(fd, boundary, bytenr, crlfnr) == 1) + // If parseFull returns != 0, then it encountered the multipart's + // final boundary. + int bsize = 0; + if (m.parseFull(boundary, bsize)) { quit = true; + foundendofpart = true; + } members.push_back(m); - level -= 3; - } + + } while (!quit); } - // we mustn't forget to eat our own parent's boundary, if it's non-empty. + unsigned int crlfoffsetbeforeboundary = crlfoffset; + // eat our parent's boundary. this is actually quite painful to + // do, since it's an exact duplicate of the code used by the + // parsing of a singlepart message. if (!eof && toboundary != "") { - string _toboundary; - - if (toboundary != "") { - _toboundary = "--"; - _toboundary += toboundary; - } + string _toboundary = "\r\n--"; + _toboundary += toboundary + "--"; char *boundaryqueue = 0; int endpos = _toboundary.length(); @@ -435,185 +416,139 @@ string line; int nchars = 0; - while (crlfGetChar(c)) { - ++crlfnr; - if (c != '\r') ++bytenr; - if (c == '\n') { ++nbodylines; ++nlines; } + do { + if (!crlfGetChar(c)) { + eof = true; + break; + } + + if (c == '\n') + ++nlines; nchars++; - if (toboundary != "") { - // find boundary - boundaryqueue[boundarypos++ % endpos] = c; - - if (compareStringToQueue(_toboundary, boundaryqueue, boundarypos, endpos)) { - boundaryqueue[0] = '\0'; - char a; - if (!crlfGetChar(a)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (a == '\n') { /* ++nbodylines; ++nlines; */ } - if (a != '\r') ++bytenr; - - char b; - if (!crlfGetChar(b)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines; */ } - if (b != '\r') ++bytenr; - - if (a == '-' && b == '-') { - if (crlfGetChar(a)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (a == '\n') { /* ++nbodylines; ++nlines; */ } - if (a != '\r') ++bytenr; - - if (a == '\r') { - if (!crlfGetChar(b)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines; */ } - if (b != '\r') ++bytenr; - if (b != '\n') { - // FIXME: barf! - } - } else { - // FIXME: barf!! - } - - foundendofpart = true; - } + // find boundary + boundaryqueue[boundarypos++ % endpos] = c; - break; - } - } + } while (compareStringToQueue(_toboundary, boundaryqueue, boundarypos, endpos)); + + // Don't care if it's EOF or if we actually found the boundary. + foundendofpart = true; + + delete boundaryqueue; + + char a; + if (!crlfGetChar(a)) { + eof = true; + quit = true; } - if (boundaryqueue != 0) - delete boundaryqueue; + if (a == '\n') + ++nlines; + + char b; + if (!crlfGetChar(b)) { + eof = true; + quit = true; + } + + if (b == '\n') + ++nlines; + + if (a == '\r' && b == '\n') { + crlfUnGetChar(); + crlfUnGetChar(); + } } + boundarysize = crlfoffset - crlfoffsetbeforeboundary; + bodylength = crlfoffset - bodystartoffsetcrlf; } else { - string _toboundary; - + // If toboundary is empty, then we read until the end of the + // file. Otherwise we will read until we encounter toboundary. + string _toboundary; if (toboundary != "") { - _toboundary = "--"; + _toboundary = "\r\n--"; _toboundary += toboundary; } char *boundaryqueue = 0; int endpos = _toboundary.length(); - if (_toboundary != "") + if (toboundary != "") boundaryqueue = new char[endpos]; int boundarypos = 0; string line; int nchars = 0; while (crlfGetChar(c)) { - crlfnr++; - if (c != '\r') ++bytenr; if (c == '\n') { ++nbodylines; ++nlines; } nchars++; - if (toboundary != "") { - // find boundary - boundaryqueue[boundarypos++ % endpos] = c; - - if (compareStringToQueue(_toboundary, boundaryqueue, boundarypos, endpos)) { - boundaryqueue[0] = '\0'; - char a; - if (!crlfGetChar(a)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (a == '\n') { /* ++nbodylines; ++nlines; */ } - if (a != '\r') ++bytenr; - - char b; - if (!crlfGetChar(b)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines; */ } - if (b != '\r') ++bytenr; - - if (a == '-' && b == '-') { - char a; - if (!crlfGetChar(a)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (a == '\n') { /* ++nbodylines; ++nlines; */ } - if (a != '\r') ++bytenr; - - if (a == '\r') { - char b; - if (!crlfGetChar(b)) { - eof = true; - quit = true; - break; - } - - ++crlfnr; - if (b == '\n') { /* ++nbodylines; ++nlines; */ } - if (b != '\r') ++bytenr; - if (b != '\n') { - // FIXME: barf! - } - } else { - // FIXME: barf!! - } + if (toboundary == "") + continue; - foundendofpart = true; - } - - break; - } + // find boundary + boundaryqueue[boundarypos++ % endpos] = c; + + if (!compareStringToQueue(_toboundary, boundaryqueue, boundarypos, endpos)) + continue; + else { + boundarysize = _toboundary.length(); + break; } } - if (boundaryqueue != 0) + if (toboundary != "") delete boundaryqueue; - } - bodylength = crlfnr - bodystartoffsetcrlf; + if (toboundary != "") { + char a; + if (!crlfGetChar(a)) { + eof = true; + quit = true; + } - // FIXME: is this crap? - if (toboundary != "") { - bodylength -= toboundary.length() + 4; - if (foundendofpart) - bodylength -= 4; - } + if (a == '\n') + ++nlines; + char b; + if (!crlfGetChar(b)) { + eof = true; + quit = true; + } - if (bodylength < 0) bodylength = 0; + if (b == '\n') + ++nlines; - if (foundendofpart) - return 1; - else - return 0; + if (a == '-' && b == '-') { + boundarysize += 2; + foundendofpart = true; + char a; + if (!crlfGetChar(a)) { + eof = true; + quit = true; + } + + if (a == '\n') + ++nlines; + + char b; + if (!crlfGetChar(b)) { + eof = true; + quit = true; + } + + if (b == '\n') + ++nlines; + + if (!(a == '\r' && b == '\n')) { + crlfUnGetChar(); + crlfUnGetChar(); + } else + boundarysize += 2; + } + } + + bodylength = crlfoffset - bodystartoffsetcrlf - boundarysize; + } + + return (eof || foundendofpart) ? 1 : 0; } --- src/mime-parseonlyheader.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-parseonlyheader.cc 5 Sep 2003 21:11:46 -0000 1.2 @@ -63,32 +63,28 @@ crlffile = fd; crlfReset(); - headerstartoffset = 0; + headerstartoffsetcrlf = 0; headerlength = 0; - bodystartoffset = 0; + bodystartoffsetcrlf = 0; bodylength = 0; - // size = -1; messagerfc822 = false; multipart = false; nlines = 0; nbodylines = 0; - int crlfnr = 0; - int bytenr = 0; - MimePart::parseOnlyHeader(fd, "", bytenr, crlfnr); + MimePart::parseOnlyHeader(""); } //------------------------------------------------------------------------ -int Binc::MimePart::parseOnlyHeader(int fd, const string &toboundary, int &bytenr, int &crlfnr) const +int Binc::MimePart::parseOnlyHeader(const string &toboundary) const { string name; string content; char cqueue[4]; memset(cqueue, 0, sizeof(cqueue)); - headerstartoffset = bytenr; - int headerstartoffsetcrlf = crlfnr; + headerstartoffsetcrlf = crlfoffset; bool quit = false; char c = '\0'; @@ -101,17 +97,12 @@ break; } - ++crlfnr; if (c == '\n') ++nlines; - if (c != '\r') ++bytenr; if (c == ':') break; if (c == '\n') { - --bytenr; - for (int i = name.length() - 1; i >= 0; --i) { + for (int i = name.length() - 1; i >= 0; --i) crlfUnGetChar(); - --crlfnr; - if (name[i] != '\r') --bytenr; - } + quit = true; name = ""; break; @@ -139,9 +130,7 @@ break; } - ++crlfnr; if (c == '\n') ++nlines; - if (c != '\r') ++bytenr; for (int i = 0; i < 3; ++i) cqueue[i] = cqueue[i + 1]; @@ -179,8 +168,7 @@ h.add(name, content); } - headerlength = crlfnr - headerstartoffsetcrlf; - if (headerlength < 0) headerlength = 0; + headerlength = crlfoffset - headerstartoffsetcrlf; return 1; } --- src/mime-printbody.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-printbody.cc 6 Sep 2003 09:25:30 -0000 1.3 @@ -53,26 +53,19 @@ using namespace ::std; //------------------------------------------------------------------------ -int Binc::MimePart::printBody(int fd, IO &output, int startoffset, - int length, string &storage, bool store, - bool doprint) const +int Binc::MimePart::printBody(int fd, IO &output, unsigned int startoffset, + unsigned int length, string &storage, + bool store, bool doprint) const { - char c = '\0'; - lseek(fd, bodystartoffset, SEEK_SET); - crlffile = fd; - crlfReset(); + crlfSeek(bodystartoffsetcrlf + startoffset); - if (length == -1) length = bodylength; if (startoffset + length > bodylength) - length = bodylength - startoffset + 1; - - for (int i = 0; i < startoffset; ++i) - if (!crlfGetChar(c)) - break; + length = bodylength - startoffset; int wrotebytes = 0; - for (int i = 0; i < length; ++i) + char c = '\0'; + for (unsigned int i = 0; i < length; ++i) if (!crlfGetChar(c)) break; else { --- src/mime-printdoc.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-printdoc.cc 5 Sep 2003 21:11:46 -0000 1.2 @@ -53,23 +53,16 @@ using namespace ::std; //------------------------------------------------------------------------ -int Binc::MimePart::printDoc(int fd, IO &output, int startoffset, - int length, string &storage, bool store, - bool doprint) const +int Binc::MimePart::printDoc(int fd, IO &output, unsigned int startoffset, + unsigned int length, string &storage, + bool store, bool doprint) const { - char c; - - lseek(fd, 0, SEEK_SET); - crlffile = fd; - crlfReset(); + crlfSeek(startoffset); - for (int i = 0; i < startoffset; ++i) - if (!crlfGetChar(c)) - break; - - int wrotebytes = 0; - for (int i = 0; i < length || length == -1; ++i) + unsigned int wrotebytes = 0; + char c; + for (unsigned int i = 0; i < length; ++i) if (!crlfGetChar(c)) break; else { --- src/mime-printheader.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-printheader.cc 5 Sep 2003 21:11:46 -0000 1.2 @@ -55,61 +55,47 @@ //------------------------------------------------------------------------ int Binc::MimePart::printHeader(int fd, IO &output, vector headers, bool includeheaders, - int startoffset, int length, + unsigned int startoffset, unsigned int length, bool doprint, bool dostore, string &store) const { IO &com = IOFactory::getInstance().get(1); - - char c = '\0'; - lseek(fd, headerstartoffset, SEEK_SET); + IO &logger = IOFactory::getInstance().get(2); crlffile = fd; - crlfReset(); - - if (length == -1) length = headerlength; - if (startoffset + length > headerlength) - length = headerlength - startoffset + 1; + crlfSeek(headerstartoffsetcrlf); - int wrotebytes = 0; - int processedbytes = 0; - - int crlfnr = 0; string name; string content; + char cqueue[4]; + memset(cqueue, 0, sizeof(cqueue)); + bool quit = false; + char c = '\0'; - bool breakheader = false; + unsigned int printstartoffset = crlfoffset; + unsigned int wrotebytes = 0; + unsigned int processedbytes = 0; while (!quit) { - - // 1) read all characters to but not including ':' - string name; - if (crlfnr >= headerlength) { - quit = true; - break; - } - + // read name while (1) { if (!crlfGetChar(c)) { quit = true; break; } - ++crlfnr; + if (c == '\n') ++nlines; if (c == ':') break; if (c == '\n') { - for (int i = name.length() - 1; i >= 0; --i) { + for (int i = name.length() - 1; i >= 0; --i) crlfUnGetChar(); - --crlfnr; - } + quit = true; - breakheader = true; name = ""; break; } - if (c != '\r') - name += c; + name += c; if (name.length() == 2 && name.substr(0, 2) == "\r\n") { name = ""; @@ -117,120 +103,72 @@ break; } } - if (quit) - break; - // 2) check if we want to print this header - string tmp = name; - lowercase(tmp); - bool match = false; - if (headers.size() == 0) { - match = true; - } else { - for (vector::const_iterator i = headers.begin(); i != headers.end(); ++i) { - string t2 = *i; lowercase(t2); - - if (t2 == tmp) { - match = true; - break; - } - } - if (!includeheaders) - if (match) match = false; - else if (!match) match = true; + if (name.length() == 1 && name[0] == '\r') { + name = ""; + break; } - // 3) if we did not want to print this header, skip to the next header - if (!match) { - char cq[3]; - do { - if (crlfnr >= headerlength) { - quit = true; - break; - } + if (quit) break; - if (!crlfGetChar(c)) { - quit = true; - break; - } + while (!quit) { + if (!crlfGetChar(c)) { + quit = true; + break; + } - crlfnr++; + if (c == '\n') ++nlines; - for (int i = 0; i < 2; ++i) cq[i] = cq[i + 1]; - cq[2] = c; - if (strncmp(cq, "\r\n", 2) == 0) { - if (!isspace(c)) { - crlfUnGetChar(); - --crlfnr; - break; - } - } - } while (1); + for (int i = 0; i < 3; ++i) + cqueue[i] = cqueue[i + 1]; + cqueue[3] = c; - if (quit) + if (strncmp(cqueue, "\r\n\r\n", 4) == 0) { + quit = true; break; + } - } else { - // don't forget the colon - name += ":"; - - // 3.1) print what we have already - for (string::const_iterator i = name.begin(); i != name.end(); ++i) - if (processedbytes >= startoffset) { - if (doprint) - com << *i; - if (dostore) - store += *i; - ++wrotebytes; - } else - ++processedbytes; - - // 3.2) print the rest of this header - char cq[4]; - cq[2] = ':'; - do { - if (crlfnr >= headerlength) { - quit = true; - break; - } - - if (!crlfGetChar(c)) { - quit = true; - break; - } + if (cqueue[2] == '\n') { - crlfnr++; + // guess the mime rfc says what can not appear on the beginning + // of a line. + if (!isspace(cqueue[3])) { + if (content.length() > 2) + content.resize(content.length() - 2); + + trim(content); + string out = name + ": " + content + "\r\n"; + for (string::const_iterator i = out.begin(); i != out.end(); ++i) + if (processedbytes >= startoffset && wrotebytes < length) { + if (processedbytes >= startoffset) { + if (doprint) + com << *i; + if (dostore) + store += *i; + ++wrotebytes; + } + } else + ++processedbytes; - for (int i = 0; i < 2; ++i) cq[i] = cq[i + 1]; - cq[2] = c; - if (strncmp(cq, "\r\n", 2) == 0) { - if (!isspace(c)) { - crlfUnGetChar(); - --crlfnr; - break; - } + name = c; + content = ""; + break; } + } - if (processedbytes >= startoffset) { - if (doprint) - com << (char)c; - if (dostore) - store += (char)c; - ++wrotebytes; - } else - ++processedbytes; - } while (1); - if (quit) - break; + content += c; } - - name = ""; } - if (breakheader || headers.size() != 0) { - name = "\r\n"; - for (string::const_iterator i = name.begin(); i != name.end(); ++i) - if (processedbytes >= startoffset) { + if (name != "") { + if (content.length() > 2) + content.resize(content.length() - 2); + + trim(content); + + string out = name + ": " + content + "\r\n"; + for (string::const_iterator i = out.begin(); i != out.end(); ++i) + if (processedbytes >= startoffset && wrotebytes < length) { if (doprint) com << *i; if (dostore) @@ -239,6 +177,17 @@ } else ++processedbytes; } + + name = "\r\n"; + for (string::const_iterator i = name.begin(); i != name.end(); ++i) + if (processedbytes >= startoffset && wrotebytes < length) { + if (doprint) + com << *i; + if (dostore) + store += *i; + ++wrotebytes; + } else + ++processedbytes; return wrotebytes; } diff -u -r1.1.1.1 -r1.2 --- src/mime-utils.h 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime-utils.h 5 Sep 2003 21:11:46 -0000 1.2 @@ -43,6 +43,8 @@ #include #include +#include "io.h" + using namespace ::std; inline bool compareStringToQueue(const std::string &s_in, @@ -59,8 +61,9 @@ extern int crlffile; extern char crlfdata[]; -extern int crlftail; -extern int crlfhead; +extern unsigned int crlfoffset; +extern unsigned int crlftail; +extern unsigned int crlfhead; extern char lastchar; bool fillInputBuffer(void); @@ -71,18 +74,37 @@ return false; c = crlfdata[crlfhead++ & 0xfff]; + ++crlfoffset; return true; } inline void crlfUnGetChar(void) { - crlfhead--; + --crlfhead; + --crlfoffset; } inline void crlfReset(void) { - crlfhead = crlftail = 0; - lastchar = '\0'; + if (crlfoffset != 0) { + crlfoffset = 0; + crlfhead = crlftail = 0; + lastchar = '\0'; + lseek(crlffile, 0, SEEK_SET); + } } +inline void crlfSeek(unsigned int offset) +{ + if (crlfoffset > offset) + crlfReset(); + + char c; + int n = 0; + while (offset > crlfoffset) { + if (!crlfGetChar(c)) + break; + ++n; + } +} #endif --- src/mime.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime.cc 5 Sep 2003 21:11:46 -0000 1.2 @@ -82,7 +82,7 @@ //------------------------------------------------------------------------ Binc::MimePart::MimePart(void) { - size = -1; + size = 0; messagerfc822 = false; multipart = false; --- src/mime.h 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/mime.h 5 Sep 2003 21:11:46 -0000 1.2 @@ -86,17 +86,22 @@ mutable std::string subtype; mutable std::string boundary; - mutable int headerstartoffset; - mutable int headerlength; + mutable unsigned int headerstartoffsetcrlf; + mutable unsigned int headerlength; - mutable int bodystartoffset; - mutable int bodystartoffsetcrlf; - mutable int bodylength; - mutable int nlines; - mutable int nbodylines; - mutable int size; + mutable unsigned int bodystartoffsetcrlf; + mutable unsigned int bodylength; + mutable unsigned int nlines; + mutable unsigned int nbodylines; + mutable unsigned int size; public: + enum FetchType { + FetchBody, + FetchHeader, + FetchMime + }; + mutable Header h; mutable std::vector members; @@ -104,21 +109,21 @@ inline const std::string &getSubType(void) const { return subtype; } inline bool isMultipart(void) const { return multipart; } inline bool isMessageRFC822(void) const { return messagerfc822; } - inline int getSize(void) const { return bodylength; } - inline int getNofLines(void) const { return nlines; } - inline int getNofBodyLines(void) const { return nbodylines; } - inline int getBodyLength(void) const { return bodylength; } - inline int getBodyStartOffset(void) const { return bodystartoffset; } - - int printBody(int fd, Binc::IO &output, int startoffset, int length, std::string &storage, bool store, bool doprint) const; - int printHeader(int fd, Binc::IO &output, std::vector headers, bool includeheaders, int startoffset, int length, bool doprint, bool dostore, std::string &storage) const; - int printDoc(int fd, Binc::IO &output, int startoffset, int length, std::string &storage, bool store, bool doprint) const; + inline unsigned int getSize(void) const { return bodylength; } + inline unsigned int getNofLines(void) const { return nlines; } + inline unsigned int getNofBodyLines(void) const { return nbodylines; } + inline unsigned int getBodyLength(void) const { return bodylength; } + inline unsigned int getBodyStartOffset(void) const { return bodystartoffsetcrlf; } + + int printBody(int fd, Binc::IO &output, unsigned int startoffset, unsigned int length, std::string &storage, bool store, bool doprint) const; + int printHeader(int fd, Binc::IO &output, std::vector headers, bool includeheaders, unsigned int startoffset, unsigned int length, bool doprint, bool dostore, std::string &storage) const; + int printDoc(int fd, Binc::IO &output, unsigned int startoffset, unsigned int length, std::string &storage, bool store, bool doprint) const; void printStruct(std::string s = "") const; virtual void clear(void) const; - const MimePart *getPart(const std::string &findpart, std::string genpart) const; - virtual int parseOnlyHeader(int fd, const std::string &toboundary, int &bytenr, int &crlfnr) const; - virtual int parseFull(int fd, const std::string &toboundary, int &bytenr, int &crlfnr) const; + const MimePart *getPart(const std::string &findpart, std::string genpart, FetchType fetchType = FetchBody) const; + virtual int parseOnlyHeader(const std::string &toboundary) const; + virtual int parseFull(const std::string &toboundary, int &boundarysize) const; MimePart(void); virtual ~MimePart(void); --- src/operator-fetch.cc 18 Aug 2003 18:06:05 -0000 1.1.1.1 +++ src/operator-fetch.cc 5 Sep 2003 21:11:46 -0000 1.2 @@ -240,11 +240,11 @@ ? message.getHeaderSize(fatt.section, v, true, fatt.offsetstart, - fatt.offsetlength) + fatt.offsetlength, fatt.sectiontext == "MIME") : message.getHeaderSize(fatt.section, fatt.headerlist, includeheaders, fatt.offsetstart, - fatt.offsetlength); + fatt.offsetlength, fatt.sectiontext == "MIME"); com << "{" << size << "}\r\n"; @@ -252,12 +252,12 @@ message.printHeader(fatt.section, v, true, fatt.offsetstart, - fatt.offsetlength); + fatt.offsetlength, fatt.sectiontext == "MIME"); } else { message.printHeader(fatt.section, fatt.headerlist, includeheaders, fatt.offsetstart, - fatt.offsetlength); + fatt.offsetlength, fatt.sectiontext == "MIME"); } } else { unsigned int size;