public int read()

in geronimo-mail_2.1_spec/src/main/java/jakarta/mail/internet/MimeMultipart.java [580:736]


        public int read() throws IOException {
            if (boundaryFound) {
                return -1;
            }

            // read the next value from stream
            final int firstChar = inStream.read();
            // premature end?  Handle it like a boundary located
            if (firstChar == -1) {
            	//DO NOT treat this a a boundary because if we do so we have no chance to detect missing end boundaries
                return -1;
            }

            // we first need to look for a line boundary.  If we find a boundary, it can be followed by the
            // boundary marker, so we need to remember what sort of thing we found, then read ahead looking
            // for the part boundary.

            // NB:, we only handle [\r]\n--boundary marker[--]
            // we need to at least accept what most mail servers would consider an
            // invalid format using just '\n'
            if (firstChar != '\r' && firstChar != '\n') {
                // not a \r, just return the byte as is
                return firstChar;
            }
            // we might need to rewind to this point.  The padding is to allow for
            // line terminators and linear whitespace on the boundary lines
            inStream.mark(boundary.length + 1000);
            // we need to keep track of the first read character in case we need to
            // rewind back to the mark point
            int value = firstChar;
            // if this is a '\r', then we require the '\n'
            if (value == '\r') {
                // now scan ahead for the second character
                value = inStream.read();
                if (value != '\n') {
                    // only a \r, so this can't be a boundary.  Return the
                    // \r as if it was data, after first resetting
                    inStream.reset();
                    return '\r';
                }
            }

            value = inStream.read();
            // if the next character is not a boundary start, we
            // need to handle this as a normal line end
            if ((byte) value != boundary[0]) {
                // just reset and return the first character as data
                inStream.reset();
                return firstChar;
            }

            // we're here because we found a "\r\n-" sequence, which is a potential
            // boundary marker.  Read the individual characters of the next line until
            // we have a mismatch

            // read value is the first byte of the boundary. Start matching the
            // next characters to find a boundary
            int boundaryIndex = 0;
            while ((boundaryIndex < boundary.length) && ((byte) value == boundary[boundaryIndex])) {
                value = inStream.read();
                boundaryIndex++;
            }
            // if we didn't match all the way, we need to push back what we've read and
            // return the EOL character
            if (boundaryIndex != boundary.length) {
                // Boundary not found. Restoring bytes skipped.
                // just reset and return the first character as data
                inStream.reset();
                return firstChar;
            }

            // The full boundary sequence should be \r\n--boundary string[--]\r\n
            // if the last character we read was a '-', check for the end terminator
            if (value == '-') {
                value = inStream.read();
                // crud, we have a bad boundary terminator.  We need to unwind this all the way
                // back to the lineend and pretend none of this ever happened
                if (value != '-') {
                    // Boundary not found. Restoring bytes skipped.
                    // just reset and return the first character as data
                    inStream.reset();
                    return firstChar;
                }
                // on the home stretch, but we need to verify the LWSP/EOL sequence
                value = inStream.read();
                // first skip over the linear whitespace
                while (value == ' ' || value == '\t') {
                    value = inStream.read();
                }

                // We've matched the final boundary, skipped any whitespace, but
                // we've hit the end of the stream.  This is highly likely when
                // we have nested multiparts, since the linend terminator for the
                // final boundary marker is eated up as the start of the outer
                // boundary marker.  No CRLF sequence here is ok.
                if (value == -1) {
                    // we've hit the end of times...
                    finalBoundaryFound = true;
                    // we have a boundary, so return this as an EOF condition
                    boundaryFound = true;
                    return -1;
                }

                // this must be a CR or a LF...which leaves us even more to push back and forget
                if (value != '\r' && value != '\n') {
                    // Boundary not found. Restoring bytes skipped.
                    // just reset and return the first character as data
                    inStream.reset();
                    return firstChar;
                }

                // if this is carriage return, check for a linefeed
                if (value == '\r') {
                    // last check, this must be a line feed
                    value = inStream.read();
                    if (value != '\n') {
                        // SO CLOSE!
                        // Boundary not found. Restoring bytes skipped.
                        // just reset and return the first character as data
                        inStream.reset();
                        return firstChar;
                    }
                }

                // we've hit the end of times...
                finalBoundaryFound = true;
            }
            else {
                // first skip over the linear whitespace
                while (value == ' ' || value == '\t') {
                    value = inStream.read();
                }
                // this must be a CR or a LF...which leaves us even more to push back and forget
                if (value != '\r' && value != '\n') {
                    // Boundary not found. Restoring bytes skipped.
                    // just reset and return the first character as data
                    inStream.reset();
                    return firstChar;
                }

                // if this is carriage return, check for a linefeed
                if (value == '\r') {
                    // last check, this must be a line feed
                    value = inStream.read();
                    if (value != '\n') {
                        // SO CLOSE!
                        // Boundary not found. Restoring bytes skipped.
                        // just reset and return the first character as data
                        inStream.reset();
                        return firstChar;
                    }
                }
            }
            // we have a boundary, so return this as an EOF condition
            boundaryFound = true;
            return -1;
        }