# Pantera - Web Pen-Test Proxy
#
# FILENAME      : requestandresponse.py
# CODER         : Simon Roses Femerling
# DATE          : 9/23/2004
# LAST UPDATE   : 9/04/2006
# ABSTRACT      : Python Web Pen-Test Proxy :)
#                 Pantera Request and Response.
#
# - Roses Labs Innovations (RL+I)
# Roses Labs
# http://www.roseslabs.com
#
# Copyright (c) 2003-2006 Roses Labs.
#
# You may not distribute, transmit, repost this software for commercial 
# purposes without Roses Labs written permission. 
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, publish,
# distribute the Software, and to permit persons to whom the Software 
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

'''
@author:       Simon Roses Femerling
@license:      GNU General Public License 2.0 or later
@contact:      pantera.proxy@gmail.com
@organization: OWASP / Roses Labs
'''

import panterautils
import cgi
import gzip
import StringIO

#############################################################################################
# Our Functions
#############################################################################################

#############################################################################################
# FUNC     : class RequestAndResponse
# PARAMS   : ...
# RETURN   : ...
# ABSTRACT : Pantera Request and Response class
class RequestAndResponse:
    ''' 
    Pantera Request and Response Class 
    '''
    
    #############################################################################################
    # FUNC     : def __init__
    # PARAMS   : clientheader,clientbody,serverheader,serverbody
    # RETURN   : ...
    # ABSTRACT : Init
    def __init__(self,clientheader,clientbody,serverheader,serverbody):
        ''' 
        init class.
        
        @type  clientheader: class
        @param clientheader: Contains a HTTP header class.
        @type  clientbody: class
        @param clientbody: Contains a HTTP body class.
        @type  serverheader: class
        @param serverheader: Contains a HTTP body class.
        '''
        self.clientheader=clientheader
        self.clientbody=clientbody
        self.serverheader=serverheader
        self.serverbody=serverbody
    # EOF: def __init__

    #############################################################################################
    # FUNC     : def issame
    # PARAMS   : other
    # RETURN   : returns true if we are the same
    # ABSTRACT : Compare func
    def issame(self,other):
        '''
        Check if 2 request/response are the same.
        
        @type  other: class
        @param other: Contains a class.
        @return: Return 1 if is the same, otherwise 0. 
        '''
        if self.clientheader.issame(other.clientheader) and \
           self.clientbody.issame(other.clientbody) and \
           self.serverheader.issame(other.serverheader) and \
           self.serverbody.issame(other.serverbody):
            return 1
        return 0
    # EOF: def issame
        
    #############################################################################################
    # FUNC     : def printme
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Prints details about site
    def printme(self):
        ''' 
        Print information about a site.
        
        @return: Return string.
        '''
        site=self.clientheader.connectHost
        result=""
        result+="Site: %s<br>" % site
        result+="Port: %s<br>" % str(self.clientheader.connectPort)
        result+="SSL: "
        if self.clientheader.clientisSSL:
            result+="Yes"
        else:
            result+="No"
            
        result+="<br><br>"
        #constructRequest stolen out of spkproxy
        result+=cgi.escape(panterautils.constructRequest(self.clientheader,self.clientbody))
        result=result.replace("\n","<br>")
        return result
    # EOF: def printme
    
    #############################################################################################
    # FUNC     : def getResponse
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Get response    
    def getResponse(self):
        ''' 
        Get response.
        
        @return: Return string with HTTP response.
        '''
        result=""
        result+=panterautils.constructResponse(self.serverheader,self.serverbody)
        return result
    # EOF: def getResponse

    #############################################################################################
    # FUNC     : def getResponseHeader
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Get response header
    def getResponseHeader(self):
        ''' 
        Get response header.
        
        @return: Return string with HTTP response ready to use in JS.
        '''
        result=""
        result+=panterautils.constructResponseJS(self.serverheader,self.serverbody)
        return result
    # EOF: def getResponseHeader

    #############################################################################################
    # FUNC     : def printBody
    # PARAMS   : int
    # RETURN   : string
    # ABSTRACT : Print body
    def printBody(self, decode=0):
        ''' 
        Print body.
        
        @type decode: int
        @param decode: Default is 0 for no decoding. If 1 data will be decoding using gzip. 
        @return: Return string with the HTTP response body.
        '''
        res = "".join(self.serverbody.data)
        if decode==1: # do gzip decode
            ce_data = self.GetServerHeader('Content-Encoding')
            if ce_data != '' and ce_data.find("gzip")>=0:
                compressedstream = StringIO.StringIO(res)   
                gzipper = gzip.GzipFile(fileobj=compressedstream)      
                data = gzipper.read()
                return data                                  
        return res
    # EOF: def printBody
    
    #############################################################################################
    # FUNC     : def ReturnServerFirstLine 
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Return server first line
    def ReturnServerFirstLine(self):
        ''' 
        Return first line of HTTP response. 
        
        @return: Return string.
        '''
        if self.serverheader.firstline=="":
            return "Serious error: response's first line is empty!"
        else:
            return self.serverheader.firstline
    # EOF: def ReturnServerFirstLine

    #############################################################################################
    # FUNC     : def JustResponseHeader
    # PARAMS   : ...
    # RETURN   : string 
    # ABSTRACT : Return server header
    def JustResponseHeader(self):
        '''
        Return HTTP response header.
        
        @return: Return string with HTTP response.
        '''
        result=""
        result+=panterautils.JustConstructResponse(self.serverheader,self.serverbody)
        return result
    # EOF: def JustResponseHeader

    #############################################################################################
    # FUNC     : def GetServerHeader
    # PARAMS   : string
    # RETURN   : string
    # ABSTRACT : Return server header value
    def GetServerHeader(self, h):
        '''
        Get a value from the server HTTP header response.
        
        @type h: string
        @param h: Header to look for.
        @return: Return empty string if header not found, else string.
        '''
        if self.serverheader.headerValuesDict.has_key(h):
            return self.serverheader.headerValuesDict[h][0]
        else:
            return ""
    # EOF: def GetServerHeader

    #############################################################################################
    # FUNC     : def GetClientHeader
    # PARAMS   : string
    # RETURN   : string
    # ABSTRACT : Return client header value
    def GetClientHeader(self, h):
        '''
        Get a value from a client HTTP header request.
        
        @type h: string
        @param h: Header to look for.
        @return: Return empty string if headre not found, else string.
        '''
        if self.clientheader.headerValuesDict.has_key(h):
            return self.clientheader.headerValuesDict[h][0]
        else:
            return ""
    # EOF: GetClientHeader

# RL+I EOF