Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pcurl command #109

Merged
merged 15 commits into from
Sep 28, 2015
2 changes: 1 addition & 1 deletion commands/FBFindCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def run(self, arguments, options):

def printMatchesInViewOutputStringAndCopyFirstToClipboard(needle, haystack):
first = None
for match in re.finditer('.*<.*(' + needle + ').*: (0x[0-9a-fA-F]*);.*', haystack, re.IGNORECASE):
for match in re.finditer('.*<.*(' + needle + ')\\S*: (0x[0-9a-fA-F]*);.*', haystack, re.IGNORECASE):
view = match.groups()[-1]
className = fb.evaluateExpressionValue('(id)[(' + view + ') class]').GetObjectDescription()
print('{} {}'.format(view, className))
Expand Down
66 changes: 66 additions & 0 deletions commands/FBPrintCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def lldbcommands():
FBPrintData(),
FBPrintTargetActions(),
FBPrintJSON(),
FBPrintAsCurl(),
]

class FBPrintViewHierarchyCommand(fb.FBCommand):
Expand Down Expand Up @@ -450,3 +451,68 @@ def run(self, arguments, options):

print jsonString

class FBPrintAsCurl(fb.FBCommand):
def name(self):
return 'pcurl'

def description(self):
return 'Print the NSURLRequest (HTTP) as curl command.'

def options(self):
return [
fb.FBCommandArgument(short='-e', long='--embed-data', arg='embed', boolean=True, default=False, help='Embed request data as base64.'),
]

def args(self):
return [ fb.FBCommandArgument(arg='request', type='NSURLRequest*/NSMutableURLRequest*', help='The request to convert to the curl command.') ]

def generateTmpFilePath(self):
return '/tmp/curl_data_{}'.format(fb.evaluateExpression('(NSTimeInterval)[NSDate timeIntervalSinceReferenceDate]'))

def run(self, arguments, options):
request = arguments[0]
HTTPHeaderSring = ''
HTTPMethod = fb.evaluateExpressionValue('(id)[{} HTTPMethod]'.format(request)).GetObjectDescription()
URL = fb.evaluateExpressionValue('(id)[{} URL]'.format(request)).GetObjectDescription()
timeout = fb.evaluateExpression('(NSTimeInterval)[{} timeoutInterval]'.format(request))
HTTPHeaders = fb.evaluateObjectExpression('(id)[{} allHTTPHeaderFields]'.format(request))
HTTPHeadersCount = fb.evaluateIntegerExpression('[{} count]'.format(HTTPHeaders))
allHTTPKeys = fb.evaluateObjectExpression('[{} allKeys]'.format(HTTPHeaders))
for index in range(0, HTTPHeadersCount):
key = fb.evaluateObjectExpression('[{} objectAtIndex:{}]'.format(allHTTPKeys, index))
keyDescription = fb.evaluateExpressionValue('(id){}'.format(key)).GetObjectDescription()
value = fb.evaluateExpressionValue('(id)[(id){} objectForKey:{}]'.format(HTTPHeaders, key)).GetObjectDescription()
if len(HTTPHeaderSring) > 0:
HTTPHeaderSring += ' '
HTTPHeaderSring += '-H "{}: {}"'.format(keyDescription, value)
HTTPData = fb.evaluateObjectExpression('[{} HTTPBody]'.format(request))
dataFile = None
dataAsString = None
if fb.evaluateIntegerExpression('[{} length]'.format(HTTPData)) > 0:
if options.embed:
if fb.evaluateIntegerExpression('[{} respondsToSelector:@selector(base64EncodedStringWithOptions:)]'.format(HTTPData)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably no need to do this, since it's available in iOS 7 and I don't think we support <iOS 7. Although I can't remember for sure. @kastiglione?

And if we do supper <iOS 7 I would prefer in the else case here to print an error, and include an option to skip the data part of this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we state an official iOS version support. If we don't, this is as good a time to start. So yeah, let's say iOS 7+.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This command works on OS X as well, but this method available only for 10.9+

dataAsString = fb.evaluateExpressionValue('(id)[(id){} base64EncodedStringWithOptions:0]'.format(HTTPData)).GetObjectDescription()
else :
print 'This version of OS doesn\'t supports base64 data encoding'
return False
elif not runtimeHelpers.isIOSDevice():
dataFile = self.generateTmpFilePath()
if not fb.evaluateBooleanExpression('(BOOL)[{} writeToFile:@"{}" atomically:NO]'.format(HTTPData, dataFile)):
print 'Can\'t write data to file {}'.format(dataFile)
return False
else:
print 'HTTPBody data for iOS Device is supported only with "--embed-data" flag'
return False

commandString = ''
if dataAsString is not None and len(dataAsString) > 0:
dataFile = self.generateTmpFilePath()
commandString += 'echo "{}" | base64 -D -o "{}" && '.format(dataAsString, dataFile)
commandString += 'curl -X {} --connect-timeout {}'.format(HTTPMethod, timeout)
if len(HTTPHeaderSring) > 0:
commandString += ' ' + HTTPHeaderSring
if dataFile is not None:
commandString += ' --data-binary @"{}"'.format(dataFile)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattjgalloway actually same file are used in two cases:

  1. To embed data
  2. To write data to file

If I will place name generation under the not runtimeHelpers.isIOSDevice(): condition, then it will be not available here with --embed-data option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh whoops sorry!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kastiglione do you think it's ready for merge?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a couple comments. Primarily needs a fix for the location of dataFile.


commandString += ' "{}"'.format(URL)
print commandString
6 changes: 6 additions & 0 deletions fblldbobjcruntimehelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,9 @@ def isMacintoshArch():
command = '(void*)objc_getClass("{}")'.format(nsClassName)

return (fb.evaluateBooleanExpression(command + '!= nil'))

def isIOSSimulator():
return fb.evaluateExpressionValue('(id)[[UIDevice currentDevice] model]').GetObjectDescription().lower().find('simulator') >= 0

def isIOSDevice():
return not isMacintoshArch() and not isIOSSimulator()