def found_terminator(self):
        """
        We have come across a message terminator from the IMAP client talking
        to us.

        This is invoked in two different states:

        1) we have hit LINE_TERMINATOR and we were waiting for it.  At this
           point the buffer should contain an integer as an ascii string. This
           integer is the length of the actual message.

        2) We are reading the message itself.. we read the appropriate number
           of bytes from the channel.

        If (2) then we exit the state where we are reading the IMAP message
        from the channel and set the terminator back to LINE_TERMINATOR so that
        we can read the rest of the message from the IMAP client.
        """
        if not self.reading_message:
            # We have hit our line terminator.. we should have an ascii
            # representation of an int in our buffer.. read that to determine
            # how many characters the actual IMAP message we need to read is.
            #
            try:
                msg_length = int("".join(self.ibuffer).strip())
                self.ibuffer = []
                self.reading_message = True
                self.set_terminator(msg_length)
            except ValueError, e:
                self.log.error("found_terminator(): %s expected an int, got: "
                               "'%s'" % (self.log_string(),
                                         "".join(self.ibuffer)))
            return

        # If we were reading a full IMAP message, then we switch back to
        # reading lines.
        #
        imap_msg = "".join(self.ibuffer)
        self.ibuffer = []
        self.reading_message = False
        self.set_terminator(self.LINE_TERMINATOR)

        # Parse the IMAP message. If we can not parse it hand back a 'BAD'
        # response to the IMAP client.
        #
        # We special case if the client is idling. In this state we look for
        # ONLY a 'DONE' non-tagged message and when we get that we call the
        # 'do_done()' method on the client command processor.
        #
        if self.cmd_processor.idling:
            if imap_msg.lower().strip() != "done":
                self.push("* BAD Expected 'DONE' not: %s\r\n" % imap_msg)
            else:
                self.cmd_processor.do_done(None)
            return

        try:
            imap_cmd = asimap.parse.IMAPClientCommand(imap_msg)
            imap_cmd.parse()

        except asimap.parse.BadCommand, e:
            # The command we got from the client was bad...  If we at least
            # managed to parse the TAG out of the command the client sent us we
            # use that when sending our response to the client so it knows what
            # message we had problems with.
            #
            if imap_cmd.tag is not None:
                self.push("%s BAD %s\r\n" % (imap_cmd.tag, str(e)))
            else:
                self.push("* BAD %s\r\n" % str(e))
            return

        # Pass the command on to the command processor to handle.
        #
        self.cmd_processor.command(imap_cmd)

        # If our state is "logged_out" after processing the command then the
        # client has logged out of the authenticated state. We need to close
        # our connection to the main server process.
        #
        if self.cmd_processor.state == "logged_out":
            self.log.info("Client %s has logged out of the subprocess" % \
                          self.log_string())
            self.cleanup()
            if self.socket is not None:
                self.close()
        return

    ##################################################################
    #
dataset/ETHPy150Open scanner/asimap/asimap/user_server.py/IMAPUserClientHandler.found_terminator/original