def http_client_continue (self, request):
         # push one string and maybe a producer in the output fifo ...
         http_request = '%s %s HTTP/%s\r\n' % (
                 request.http_method, 
                 request.http_url, 
                 self.http_version
                 )
         if request.producer_body == None: # GET, HEAD and DELETE
                 lines = mime_headers.lines (request.producer_headers)
                 lines.insert (0, http_request)
                 self.output_fifo.append (''.join (lines))
         else: # POST and PUT
                 if self.http_version == '1.1':
                         request.producer_body = \
                                 http_reactor.Chunk_producer (
                                         request.producer_body
                                         )
                         request.producer_headers[
                                 'transfer-encoding'
                                 ] = 'chunked'
                 lines = mime_headers.lines (request.producer_headers)
                 lines.insert (0, http_request)
                 self.output_fifo.append (''.join (lines))
                 self.output_fifo.append (request.producer_body)
         # append the reactor to the queue of responses expected ...
         self.pipeline_responses.append (request)
         self.pipelined_requests += 1
    def found_terminator(self):
        if self.smtp_response[3] == '-':
            # rest of a multi-line response, drop it!
            self.smtp_response = ''
            return

        response = self.smtp_response[:3]
        self.smtp_response = ''
        if not response in SMTP_RESPONSE_CONTINUE:
            if response in SMTP_RESPONSE_CLOSE:
                self.handle_close()
                return True

            elif response in SMTP_RESPONSE_ABORT:
                self.pipeline_responses.popleft()
            return

        if response == '220':
            self.output_fifo.append('HELO %s\r\n' % HOSTNAME)
            return

        if not self.pipeline_responses:
            # no response expected. if there is a pending reactor,
            # pipelined pop it from the requests queue, send MAIL
            # FROM command and push the reactor on the responses
            # queue. otherwise keep the connection alive or QUIT.
            #
            if self.pipeline_requests:
                reactor = self.pipeline_requests.popleft()
                self.output_fifo.append('MAIL FROM: <%s>\r\n'
                                        '' % reactor.smtp_mail_from)
                reactor.smtp_recipient = 0
                self.pipeline_responses.append(reactor)
            elif not self.pipeline_keep_alive:
                self.output_fifo.append('QUIT\r\n')
                self.output_fifo.append(None)
            return

        # response expected ...
        reactor = self.pipeline_responses[0]
        if reactor.smtp_rcpt_to:
            # RCPT TO command for next recipient
            self.output_fifo.append('RCPT TO: <%s>\r\n'
                                    '' % reactor.smtp_rcpt_to.pop(0))
        elif reactor.smtp_responses[-1] != '354':
            # send DATA command or mail input
            if response == '354':
                push = self.output_fifo.append
                # start mail input, end with <CRLF>.<CRLF>
                push(''.join(mime_headers.lines(reactor.producer_headers)))
                push(mime_reactor.Escaping_producer(reactor.producer_body))
                push('\r\n.\r\n')
                self.handle_write()
            else:
                self.output_fifo.append('DATA\r\n')
        else:
            # reactor completed,
            self.pipeline_responses.popleft()
            self.output_fifo.append('RSET\r\n')
        reactor.smtp_responses.append(response)
def multipart_producer(parts, headers=None, glob=1 << 14):
    boundary = "%x" % id(self)
    if headers == None:
        head = "MIME-Version: 1.0\r\n" "Content-Type: multipart/mixed;" ' boundary="%s"\r\n\r\n' % boundary
    else:
        headers["content-type"] = 'multipart/mixed; boundary="%s"' % boundary
        head = "".join(mime_headers.lines(headers))
    return producer.Composite(head, multipart_generator(parts, "\r\n--%s" % boundary), glob)
 def _response (reactor, response, head):
         return _RESPONSE % (
                 reactor.request[2], response, RESPONSES[response],
                 head, '\r\n'.join (mime_headers.lines (
                         reactor.producer_headers
                         )),
                 ' '.join (reactor.request),
                 '\r\n'.join (reactor.collector_lines)
                 )
 def __call__ (self, response, headers=(), body=None):
         self.response = response
         head = (
                 '%s %d %s\r\n' 
                 'Date: %s\r\n' 
                 'Server: Allegra\r\n' % (
                         self.request[2], 
                         response,
                         RESPONSES[response],
                         self.time or strftime (
                                 '%a, %d %b %Y %H:%M:%S GMT', 
                                 gmtime (time ())
                                 )
                         ) # supports async HTTP formated time
                 )
         # Complete the HTTP response producer
         self.producer_headers.update (headers)
         if body == None and (
                 self.request[0] in ('GET', 'POST') # and
                 # response != 204 # No content
                 ):
                 # Supply a response entity if one is required for the
                 # request's method and that none has been assigned.
                 self.producer_body = producer.Simple (
                         _response (self, response, head)
                         )
         else:
                 self.producer_body = body # Use the given body.
         if self.request[2] == 'HTTP/1.1':
                 # Allways use Chunked Transfer-Encoding for HTTP/1.1!
                 if self.producer_body != None:
                         self.producer_headers[
                                 'Transfer-Encoding'
                                 ] = 'chunked'
                         self.producer_body = \
                                 http_reactor.Chunk_producer (
                                         self.producer_body
                                         )
         else:
                 # Do not keep-alive without chunk-encoding!
                 self.producer_headers['Connection'] = 'close'
         # Build the response head with the reactor's MIME headers, 
         # the channel's HTTP version the reactor's HTTP response.
         self.producer_lines = mime_headers.lines (
                 self.producer_headers
                 ) # TODO: Revise the MIME_producer API as generator ?
         self.producer_lines.insert (0, head)
         if self.producer_headers.get ('Connection') == 'close':
                 # close socket when done ...
                 self.dispatcher.output_fifo.append (None)
                 return True # ... stall input now!
         
         return False # let the http_server.Dispatcher continue ...
 def http_client_continue(self, request):
     # push one string and maybe a producer in the output fifo ...
     http_request = '%s %s HTTP/%s\r\n' % (
         request.http_method, request.http_url, self.http_version)
     if request.producer_body == None:  # GET, HEAD and DELETE
         lines = mime_headers.lines(request.producer_headers)
         lines.insert(0, http_request)
         self.output_fifo.append(''.join(lines))
     else:  # POST and PUT
         if self.http_version == '1.1':
             request.producer_body = \
                     http_reactor.Chunk_producer (
                             request.producer_body
                             )
             request.producer_headers['transfer-encoding'] = 'chunked'
         lines = mime_headers.lines(request.producer_headers)
         lines.insert(0, http_request)
         self.output_fifo.append(''.join(lines))
         self.output_fifo.append(request.producer_body)
     # append the reactor to the queue of responses expected ...
     self.pipeline_responses.append(request)
     self.pipelined_requests += 1
Example #7
0
def multipart_producer (parts, headers=None, glob=1<<14):
        boundary = '%x' % id (self)
        if headers == None:
                head = (
                        'MIME-Version: 1.0\r\n'
                        'Content-Type: multipart/mixed;'
                        ' boundary="%s"\r\n\r\n' % boundary
                        )
        else:
                headers['content-type'] = (
                        'multipart/mixed; boundary="%s"' % boundary
                        )
                head = ''.join (mime_headers.lines (headers))
        return producer.Composite (
                head, multipart_generator (
                        parts, '\r\n--%s' % boundary
                        ), glob
                )
    def __call__(self, response, headers=(), body=None):
        self.response = response
        head = (
            '%s %d %s\r\n'
            'Date: %s\r\n'
            'Server: Allegra\r\n' %
            (self.request[2], response, RESPONSES[response], self.time
             or strftime('%a, %d %b %Y %H:%M:%S GMT', gmtime(time()))
             )  # supports async HTTP formated time
        )
        # Complete the HTTP response producer
        self.producer_headers.update(headers)
        if body == None and (self.request[0] in ('GET', 'POST')  # and
                             # response != 204 # No content
                             ):
            # Supply a response entity if one is required for the
            # request's method and that none has been assigned.
            self.producer_body = producer.Simple(
                _response(self, response, head))
        else:
            self.producer_body = body  # Use the given body.
        if self.request[2] == 'HTTP/1.1':
            # Allways use Chunked Transfer-Encoding for HTTP/1.1!
            if self.producer_body != None:
                self.producer_headers['Transfer-Encoding'] = 'chunked'
                self.producer_body = \
                        http_reactor.Chunk_producer (
                                self.producer_body
                                )
        else:
            # Do not keep-alive without chunk-encoding!
            self.producer_headers['Connection'] = 'close'
        # Build the response head with the reactor's MIME headers,
        # the channel's HTTP version the reactor's HTTP response.
        self.producer_lines = mime_headers.lines(
            self.producer_headers
        )  # TODO: Revise the MIME_producer API as generator ?
        self.producer_lines.insert(0, head)
        if self.producer_headers.get('Connection') == 'close':
            # close socket when done ...
            self.dispatcher.output_fifo.append(None)
            return True  # ... stall input now!

        return False  # let the http_server.Dispatcher continue ...
 def found_terminator (self):
         if self.smtp_response[3] == '-':
                 # rest of a multi-line response, drop it!
                 self.smtp_response = ''
                 return
         
         response = self.smtp_response[:3]
         self.smtp_response = ''
         if not response in SMTP_RESPONSE_CONTINUE:
                 if response in SMTP_RESPONSE_CLOSE:
                         self.handle_close ()
                         return True
                 
                 elif response in SMTP_RESPONSE_ABORT:
                         self.pipeline_responses.popleft ()
                 return
                 
         if response == '220':
                 self.output_fifo.append ('HELO %s\r\n' % HOSTNAME)
                 return
         
         if not self.pipeline_responses:
                 # no response expected. if there is a pending reactor,
                 # pipelined pop it from the requests queue, send MAIL 
                 # FROM command and push the reactor on the responses 
                 # queue. otherwise keep the connection alive or QUIT.
                 #
                 if self.pipeline_requests:
                         reactor = self.pipeline_requests.popleft ()
                         self.output_fifo.append (
                                 'MAIL FROM: <%s>\r\n'
                                 '' % reactor.smtp_mail_from
                                 )
                         reactor.smtp_recipient = 0
                         self.pipeline_responses.append (reactor)
                 elif not self.pipeline_keep_alive:
                         self.output_fifo.append ('QUIT\r\n')
                         self.output_fifo.append (None)
                 return
         
         # response expected ...
         reactor = self.pipeline_responses[0]
         if reactor.smtp_rcpt_to:
                 # RCPT TO command for next recipient
                 self.output_fifo.append (
                         'RCPT TO: <%s>\r\n'
                         '' % reactor.smtp_rcpt_to.pop (0)
                         )
         elif reactor.smtp_responses[-1] != '354':
                 # send DATA command or mail input
                 if response == '354':
                         push = self.output_fifo.append 
                         # start mail input, end with <CRLF>.<CRLF>
                         push (''.join (mime_headers.lines (
                                 reactor.producer_headers
                                 )))
                         push (mime_reactor.Escaping_producer (
                                 reactor.producer_body
                                 ))
                         push ('\r\n.\r\n')
                         self.handle_write ()
                 else:
                         self.output_fifo.append ('DATA\r\n')
         else:
                 # reactor completed, 
                 self.pipeline_responses.popleft ()
                 self.output_fifo.append ('RSET\r\n')
         reactor.smtp_responses.append (response)
 def _response(reactor, response, head):
     return _RESPONSE % (
         reactor.request[2], response, RESPONSES[response], head,
         '\r\n'.join(mime_headers.lines(reactor.producer_headers)),
         ' '.join(reactor.request), '\r\n'.join(reactor.collector_lines))