Version 0.2.7

This commit is contained in:
Rob Glew 2016-02-18 15:29:43 -06:00
parent fda0166e72
commit f4274e1e82
27 changed files with 2136 additions and 493 deletions

View file

@ -11,6 +11,7 @@ from pappyproxy.util import PappyException
from pappyproxy.requestcache import RequestCache
from pappyproxy.console import print_requests
from pappyproxy.pappy import heapstats, cons
from pappyproxy.plugin import require_modules
from twisted.internet import defer
def cache_info(line):
@ -23,19 +24,16 @@ def cache_info(line):
rs = sorted(rl, key=lambda r: Request.cache._last_used[r.reqid], reverse=True)
print_requests(rs)
@require_modules('psutil')
def memory_info(line):
try:
import psutil
except ImportError:
raise PappyException('This command requires the psutil package')
import psutil
proc = psutil.Process(os.getpid())
mem = proc.memory_info().rss
megabyte = (float(mem)/1024)/1024
print 'Memory usage: {0:.2f} Mb ({1} bytes)'.format(megabyte, mem)
@require_modules('guppy')
def heap_info(line):
if heapstats is None:
raise PappyException('Command requires the guppy library')
size = heapstats.heap().size
print 'Heap usage: {0:.2f} Mb'.format(size/(1024.0*1024.0))
print heapstats.heap()
@ -54,11 +52,9 @@ def limit_info(line):
print 'Soft limit is now:', soft
print 'Hard limit is now:', hard
@require_modules('objgraph')
def graph_randobj(line):
try:
import objgraph
except ImportError:
raise PappyException('This command requires the objgraph library')
import objgraph
args = shlex.split(line)
if len(args) > 1:
fname = args[1]

View file

@ -2,12 +2,13 @@ import HTMLParser
import StringIO
import base64
import clipboard
import datetime
import gzip
import shlex
import string
import urllib
from pappyproxy.util import PappyException, hexdump
from pappyproxy.util import PappyException, hexdump, printable_data
def print_maybe_bin(s):
binary = False
@ -231,6 +232,14 @@ def gzip_encode_raw(line):
to a file.
"""
print _code_helper(line, gzip_encode_helper, copy=False)
def unix_time_decode_helper(line):
unix_time = int(line.strip())
dtime = datetime.datetime.fromtimestamp(unix_time)
return dtime.strftime('%Y-%m-%d %H:%M:%S')
def unix_time_decode(line):
print _code_helper(line, unix_time_decode_helper)
def load_cmds(cmd):
cmd.set_cmds({
@ -254,6 +263,7 @@ def load_cmds(cmd):
'html_encode_raw': (html_encode_raw, None),
'gzip_decode_raw': (gzip_decode_raw, None),
'gzip_encode_raw': (gzip_encode_raw, None),
'unixtime_decode': (unix_time_decode, None),
})
cmd.add_aliases([
('base64_decode', 'b64d'),
@ -276,4 +286,5 @@ def load_cmds(cmd):
('html_encode_raw', 'htmler'),
('gzip_decode_raw', 'gzdr'),
('gzip_encode_raw', 'gzer'),
('unixtime_decode', 'uxtd'),
])

View file

@ -96,9 +96,13 @@ def run_int_macro(line):
if args[0] not in int_macro_dict:
raise PappyException('%s not a loaded intercepting macro' % line)
macro = int_macro_dict[args[0]]
macro.init(args[1:])
add_intercepting_macro(macro.name, macro)
print '"%s" started' % macro.name
try:
macro.init(args[1:])
add_intercepting_macro(macro.name, macro)
print '"%s" started' % macro.name
except Exception as e:
print 'Error initializing macro:'
raise e
def stop_int_macro(line):
"""

View file

@ -58,6 +58,7 @@ class MangleInterceptMacro(InterceptMacro):
defer.returnValue(None)
mangled_req = Request(text, update_content_length=True)
mangled_req._host = request.host
mangled_req.port = request.port
mangled_req.is_ssl = request.is_ssl
@ -126,7 +127,6 @@ def check_reqid(reqid):
def start_editor(reqid):
script_loc = os.path.join(config.PAPPY_DIR, "plugins", "vim_repeater", "repeater.vim")
#print "RepeaterSetup %d %d"%(reqid, comm_port)
subprocess.call(["vim", "-S", script_loc, "-c", "RepeaterSetup %s %d"%(reqid, comm.comm_port)])
####################

View file

@ -66,7 +66,10 @@ def clrmem(line):
"""
to_delete = list(pappyproxy.http.Request.cache.inmem_reqs)
for r in to_delete:
yield r.deep_delete()
try:
yield r.deep_delete()
except PappyException as e:
print str(e)
def gencerts(line):
"""

View file

@ -74,9 +74,10 @@ def print_request_extended(request):
print_pairs = []
print_pairs.append(('Made on', time_made_str))
print_pairs.append(('ID', request.reqid))
print_pairs.append(('Verb', verb))
print_pairs.append(('URL', request.url_color))
print_pairs.append(('Host', host))
print_pairs.append(('Path', path_formatter(request.full_path)))
print_pairs.append(('Verb', verb))
print_pairs.append(('Status Code', response_code))
print_pairs.append(('Request Length', reqlen))
print_pairs.append(('Response Length', rsplen))
@ -97,6 +98,14 @@ def print_tree(tree):
# Prints a tree. Takes in a sorted list of path tuples
_print_tree_helper(tree, 0, [])
def guess_pretty_print_fmt(msg):
if 'content-type' in msg.headers:
if 'json' in msg.headers['content-type']:
return 'json'
elif 'www-form' in msg.headers['content-type']:
return 'form'
return 'text'
def pretty_print_body(fmt, body):
try:
if fmt.lower() == 'json':
@ -111,6 +120,8 @@ def pretty_print_body(fmt, body):
s += Colors.ENDC
s += urllib.unquote(v)
print s
elif fmt.lower() == 'text':
print body
else:
raise PappyException('"%s" is not a valid format' % fmt)
except PappyException as e:
@ -165,8 +176,59 @@ def _print_tree_helper(tree, depth, print_bars):
curkey = '/'
print _get_tree_prefix(depth, print_bars, True) + curkey
_print_tree_helper(subtree, depth+1, print_bars + [False])
def print_params(req, params=None):
if not req.url_params.all_pairs() and not req.body:
print 'Request %s has no url or data parameters' % req.reqid
print ''
if req.url_params.all_pairs():
print Styles.TABLE_HEADER + "Url Params" + Colors.ENDC
for k, v in req.url_params.all_pairs():
if params is None or (params and k in params):
print Styles.KV_KEY+str(k)+': '+Styles.KV_VAL+str(v)
print ''
if req.body:
print Styles.TABLE_HEADER + "Body/POST Params" + Colors.ENDC
pretty_print_body(guess_pretty_print_fmt(req), req.body)
print ''
if req.cookies.all_pairs():
print Styles.TABLE_HEADER + "Cookies" + Colors.ENDC
for k, v in req.cookies.all_pairs():
if params is None or (params and k in params):
print Styles.KV_KEY+str(k)+': '+Styles.KV_VAL+str(v)
print ''
# multiform request when we support it
def add_param(found_params, kind, k, v, reqid):
if not k in found_params:
found_params[k] = {}
if kind in found_params[k]:
found_params[k][kind].append((reqid, v))
else:
found_params[k][kind] = [(reqid, v)]
def print_param_info(param_info):
for k, d in param_info.iteritems():
print Styles.TABLE_HEADER + k + Colors.ENDC
for param_type, valpairs in d.iteritems():
print param_type
value_ids = {}
for reqid, val in valpairs:
ids = value_ids.get(val, [])
ids.append(reqid)
value_ids[val] = ids
for val, ids in value_ids.iteritems():
if len(ids) <= 15:
idstr = ', '.join(ids)
else:
idstr = ', '.join(ids[:15]) + '...'
if val == '':
printstr = (Colors.RED + 'BLANK' + Colors.ENDC + 'x%d (%s)') % (len(ids), idstr)
else:
printstr = (Colors.GREEN + '%s' + Colors.ENDC + 'x%d (%s)') % (val, len(ids), idstr)
print printstr
print ''
####################
## Command functions
@ -359,6 +421,70 @@ def pretty_print_response(line):
else:
print 'No response associated with request %s' % req.reqid
@crochet.wait_for(timeout=None)
@defer.inlineCallbacks
def print_params_cmd(line):
"""
View the headers of the request
Usage: view_request_headers <reqid(s)>
"""
args = shlex.split(line)
reqid = args[0]
if len(args) > 1:
keys = args[1:]
else:
keys = None
reqs = yield load_reqlist(reqid)
for req in reqs:
if len(reqs) > 1:
print 'Request %s:' % req.reqid
print_params(req, keys)
if len(reqs) > 1:
print '-'*30
@crochet.wait_for(timeout=None)
@defer.inlineCallbacks
def get_param_info(line):
args = shlex.split(line)
if args and args[0] == 'ct':
contains = True
args = args[1:]
else:
contains = False
if args:
params = tuple(args)
else:
params = None
def check_key(k, params, contains):
if contains:
for p in params:
if p.lower() in k.lower():
return True
else:
if params is None or k in params:
return True
return False
found_params = {}
ids = yield main_context_ids()
for i in ids:
req = yield Request.load_request(i)
for k, v in req.url_params.all_pairs():
if check_key(k, params, contains):
add_param(found_params, 'Url Parameter', k, v, req.reqid)
for k, v in req.post_params.all_pairs():
if check_key(k, params, contains):
add_param(found_params, 'POST Parameter', k, v, req.reqid)
for k, v in req.cookies.all_pairs():
if check_key(k, params, contains):
add_param(found_params, 'Cookie', k, v, req.reqid)
print_param_info(found_params)
@crochet.wait_for(timeout=None)
@defer.inlineCallbacks
def dump_response(line):
@ -387,6 +513,11 @@ def site_map(line):
Print the site map. Only includes requests in the current context.
Usage: site_map
"""
args = shlex.split(line)
if len(args) > 0 and args[0] == 'p':
paths = True
else:
paths = False
ids = yield main_context_ids()
paths_set = set()
for reqid in ids:
@ -394,7 +525,11 @@ def site_map(line):
if req.response and req.response.response_code != 404:
paths_set.add(req.path_tuple)
tree = sorted(list(paths_set))
print_tree(tree)
if paths:
for p in tree:
print ('/'.join(list(p)))
else:
print_tree(tree)
###############
@ -412,6 +547,8 @@ def load_cmds(cmd):
'view_full_response': (view_full_response, None),
'view_response_bytes': (view_response_bytes, None),
'pretty_print_response': (pretty_print_response, None),
'print_params': (print_params_cmd, None),
'param_info': (get_param_info, None),
'site_map': (site_map, None),
'dump_response': (dump_response, None),
})
@ -420,12 +557,16 @@ def load_cmds(cmd):
('view_request_info', 'viq'),
('view_request_headers', 'vhq'),
('view_full_request', 'vfq'),
('view_full_request', 'kjq'),
('view_request_bytes', 'vbq'),
('pretty_print_request', 'ppq'),
('view_response_headers', 'vhs'),
('view_full_response', 'vfs'),
('view_full_response', 'kjs'),
('view_response_bytes', 'vbs'),
('pretty_print_response', 'pps'),
('print_params', 'pprm'),
('param_info', 'pri'),
('site_map', 'sm'),
#('dump_response', 'dr'),
])

View file

@ -119,7 +119,7 @@ def submit_current_buffer():
full_request = '\n'.join(curbuf)
commdata = {'action': 'submit',
'full_message': base64.b64encode(full_request),
'tags': {'repeater'},
'tags': ['repeater'],
'port': int(vim.eval("s:repport")),
'host': vim.eval("s:rephost")}
if vim.eval("s:repisssl") == '1':