Ignore:
Timestamp:
03/17/13 22:26:27 (11 years ago)
Author:
tmorgan
Message:

Switched to python3 only, since supporting both 2.x and 3.x is such a pain

Added preliminary python-requests support to http2py

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bin/bletchley-http2py

    r39 r40  
    1 #!/usr/bin/env python
    2 
    3 # Requires Python 2.7+
     1#!/usr/bin/env python3
     2
     3# Requires Python 3+
    44
    55'''
    6 This script reads a raw HTTP request from stdin and writes to stdout
    7 a Python script.  The generated script sends the same (or a very similar)
    8 request using the httplib/http.client libraries.
     6This script reads a raw HTTP request and writes to stdout a Python
     7script.  The generated script sends the same (or a very similar)
     8request using the standard httplib/http.client library, or optionally
     9using the more user friendly python-requests library.
    910
    1011Certainly if you have a raw request, you could simply send it via TCP
     
    3435import sys
    3536import argparse
    36 try:
    37     from lxml import etree
    38 except:
    39     sys.stderr.write('ERROR: Could not import lxml module.  Ensure it is installed.\n')
    40     sys.stderr.write('       Under Debian, the package name is "python-lxml"\n.')
    41     sys.exit(1)
    4237
    4338parser = argparse.ArgumentParser(
     
    4843    ' For more information, see: http://code.google.com/p/bletchley/wiki/Overview')
    4944parser.add_argument(
    50     'requestfile', type=file, nargs='?', default=sys.stdin,
     45    'requestfile', type=open, nargs='?', default=sys.stdin,
    5146    help='A file containing an HTTP request.  Defaults to stdin if omitted.')
    5247parser.add_argument(
    53     '--burp', action='store_true', help='Input file is a XML export from Burp.'
    54     ' (First request in file is used.)')
     48    '--requests', action='store_true', help='Generate a script that uses the'
     49    ' python-requests module rather than httplib/http.client (experimental).')
     50
    5551args = parser.parse_args()
    56 
    57 if args.burp:
    58     safe_parser = etree.ETCompatXMLParser(resolve_entities=False)
    59     root = etree.parse(args.requestfile, parser=safe_parser)
    60     input_req = root.xpath('/items/item/request')[0].text
    61     root = None
    62 else:
    63     input_req = args.requestfile.read()
    64 
     52input_req = args.requestfile.read()
    6553
    6654
     
    7967port = 80
    8068use_ssl = False
     69protocol = 'http'
    8170
    8271headers = []
     
    8574        break
    8675    # Handle header line continuations
    87     if l[0] == '\t':
     76    if l[0] in ' \t':
    8877        if len(headers) == 0:
    8978            continue
     
    10897            if port == 443:
    10998                use_ssl = True
     99                protocol = 'https'
    110100        else:
    111101            host = value
    112102
    113103
    114 print('''#!/usr/bin/env python
     104formatted_body = '\n            '.join([repr(body[i:i+40].encode()) for i in range(0,len(body),40)])
     105if formatted_body == '':
     106    formatted_body = "b''"
     107
     108
     109if args.requests:
     110    print('''#!/usr/bin/env python3
    115111
    116112import sys
    117 # function with either Python 2.7 or 3.x
    118113try:
    119     import http.client as httpc
     114    import requests
    120115except:
    121     import httplib as httpc
     116    sys.stderr.write('ERROR: Could not import requests module.  Ensure it is installed.\\n')
     117    sys.stderr.write('       Under Debian, the package name is "python3-requests"\\n.')
     118    sys.exit(1)
     119
     120
     121# TODO: ensure the host, port, and SSL settings are correct.
     122host = %s
     123port = %s
     124protocol = %s
     125''' % (repr(host),repr(port),repr(protocol)))
     126
     127    headers = dict(headers)
     128    # XXX: We don't currently support exactly formatted header
     129    #      continuations with python requests, but this should be
     130    #      semantically equivalent.
     131    for h in headers.keys():
     132        headers[h] = ' '.join(headers[h])
     133
     134    print('''
     135session = requests.Session()
     136# TODO: use "data" to supply any parameters to be included in the request
     137def sendRequest(session, data=None):
     138    method = %s
     139    path = %s
     140    headers = %s
     141    url = "%%s://%%s:%%d%%s" %% (protocol,host,port,path)
     142    body = (%s)
     143
     144    return session.request(method, url, headers=headers, data=body)
     145    ''' % (repr(method), repr(path), repr(headers), formatted_body))
     146
     147    print('''   
     148
     149def fetch(data):
     150    global session
     151    ret_val = None
     152
     153    # TODO: customize code here to retrieve what you need from the response(s)
     154    # For information on the response object's interface, see:
     155    #   http://docs.python-requests.org/en/latest/api/#requests.Response
     156    response = sendRequest(session, data)
     157    print(response.headers)
     158    print(repr(response.content))
     159
     160    return ret_val
     161
     162data = ''
     163fetch(data)
    122164''')
    123165
    124166
    125 print('''
     167
     168else:
     169    print('''#!/usr/bin/env python3
     170
     171import sys
     172import http.client as httpc
     173
     174
    126175# TODO: ensure the host, port, and SSL settings are correct.
    127176host = %s
     
    130179''' % (repr(host),repr(port),repr(use_ssl)))
    131180
    132 chunked_body = '\n            '.join([repr(body[i:i+40]) for i in range(0,len(body),40)])
    133 if chunked_body == '':
    134     chunked_body = "''"
    135 
    136 print('''
     181    print('''
    137182# TODO: use "data" to supply any parameters to be included in the request
    138183def sendRequest(connection, data=None):
     
    142187   
    143188    connection.putrequest(method, path)
    144     ''' % (repr(method), repr(path), chunked_body))
    145 
    146 for name,values in headers:
    147     if len(values) > 1:
    148         continuations = ','.join([repr(v) for v in values[1:]])
    149         print('''    connection.putheader(%s, %s, %s)''' % (repr(name),repr(values[0]),continuations))
    150     else:
    151         print('''    connection.putheader(%s, %s)''' % (repr(name),repr(values[0])))
    152 
    153 print('''   
     189    ''' % (repr(method), repr(path), formatted_body))
     190
     191    for name,values in headers:
     192        if len(values) > 1:
     193            continuations = ','.join([repr(v) for v in values[1:]])
     194            print('''    connection.putheader(%s, %s, %s)''' % (repr(name),repr(values[0]),continuations))
     195        else:
     196            print('''    connection.putheader(%s, %s)''' % (repr(name),repr(values[0])))
     197
     198    print('''   
    154199    if len(body) > 0:
    155200        connection.putheader('Content-Length', len(body))
     
    161206
    162207def newConnection():
    163     connection = None
    164208    if use_ssl:
    165209        return httpc.HTTPSConnection(host, port)
Note: See TracChangeset for help on using the changeset viewer.