def convertToLayer(viewOrLayer): if fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[CALayer class]]' % viewOrLayer): return viewOrLayer elif fb.evaluateBooleanExpression('[(id)%s respondsToSelector:(SEL)@selector(layer)]' % viewOrLayer): return fb.evaluateExpression('(CALayer *)[%s layer]' % viewOrLayer) else: raise Exception('Argument must be a CALayer, UIView, or NSView.')
def accessibilityElements(view): if fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(accessibilityElements)]'): a11yElements = fb.evaluateExpression('(id)[%s accessibilityElements]' % view, False) if int(a11yElements, 16) != 0: return a11yElements if fb.evaluateBooleanExpression('[%s respondsToSelector:@selector(_accessibleSubviews)]' % view): return fb.evaluateExpression('(id)[%s _accessibleSubviews]' % (view), False) else: return fb.evaluateObjectExpression('[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]' % view)
def run(self, arguments, options): startResponder = arguments[0] if not fb.evaluateBooleanExpression( "(BOOL)[(id)" + startResponder + " isKindOfClass:[UIResponder class]]" ) and not fb.evaluateBooleanExpression("(BOOL)[(id)" + startResponder + " isKindOfClass:[NSResponder class]]"): print "Whoa, " + startResponder + " is not a UI/NSResponder. =(" return _printIterative(startResponder, _responderChain)
def dismissViewController(viewController): vc = '(%s)' % (viewController) if fb.evaluateBooleanExpression('%s != nil && ((BOOL)[(id)%s isKindOfClass:(Class)[UIViewController class]])' % (vc, vc)): isPresented = fb.evaluateBooleanExpression('[%s presentingViewController] != nil' % vc) if isPresented: lldb.debugger.HandleCommand('expr (void)[(UIViewController *)%s dismissViewControllerAnimated:YES completion:nil]' % vc) else: raise Exception('Argument must be presented') else: raise Exception('Argument must be a UIViewController')
def presentViewController(viewController): vc = '(%s)' % (viewController) if fb.evaluateBooleanExpression('%s != nil && ((BOOL)[(id)%s isKindOfClass:(Class)[UIViewController class]])' % (vc, vc)): notPresented = fb.evaluateBooleanExpression('[%s presentingViewController] == nil' % vc) if notPresented: lldb.debugger.HandleCommand('expr (void)[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:%s animated:YES completion:nil]' % vc) else: raise Exception('Argument is already presented') else: raise Exception('Argument must be a UIViewController')
def presentViewController(viewController): vc = '(%s)' % (viewController) if fb.evaluateBooleanExpression('%s != nil && ((BOOL)[(id)%s isKindOfClass:(Class)[UIViewController class]])' % (vc, vc)): notPresented = fb.evaluateBooleanExpression('[%s presentingViewController] == nil' % vc) if notPresented: fb.evaluateEffect('[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:%s animated:YES completion:nil]' % vc) else: raise Exception('Argument is already presented') else: raise Exception('Argument must be a UIViewController')
def setBorderOnAmbiguousViewRecursive(view, width, color): if not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[UIView class]]' % view): return isAmbiguous = fb.evaluateBooleanExpression('(BOOL)[%s hasAmbiguousLayout]' % view) if isAmbiguous: layer = viewHelpers.convertToLayer(view) fb.evaluateEffect('[%s setBorderWidth:(CGFloat)%s]' % (layer, width)) fb.evaluateEffect('[%s setBorderColor:(CGColorRef)[(id)[UIColor %sColor] CGColor]]' % (layer, color)) subviews = fb.evaluateExpression('(id)[%s subviews]' % view) subviewsCount = int(fb.evaluateExpression('(int)[(id)%s count]' % subviews)) if subviewsCount > 0: for i in range(0, subviewsCount): subview = fb.evaluateExpression('(id)[%s objectAtIndex:%i]' % (subviews, i)) setBorderOnAmbiguousViewRecursive(subview, width, color)
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( vc, string, prefix, childPrefix): isMac = runtimeHelpers.isMacintoshArch() s = "%s%s%s\n" % ( prefix, "" if prefix == "" else " ", _viewControllerDescription(vc), ) nextPrefix = childPrefix + " |" numChildViewControllers = fb.evaluateIntegerExpression( "(int)[(id)[%s childViewControllers] count]" % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression( "(id)[(id)[%s childViewControllers] objectAtIndex:%d]" % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( viewController, string, nextPrefix, nextPrefix) if not isMac: isModal = fb.evaluateBooleanExpression( "%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s" # noqa B950 % (vc, vc, vc)) if isModal: modalVC = fb.evaluateObjectExpression( "(id)[(id)%s presentedViewController]" % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( modalVC, string, childPrefix + " *M", nextPrefix) s += "\n// '*M' means the view controller is presented modally." return string + s
def tableViewInHierarchy(): viewDescription = fb.evaluateExpressionValue( "(id)[(id)[[UIApplication sharedApplication] keyWindow] recursiveDescription]" ).GetObjectDescription() searchView = None # Try to find an instance of classPattern = re.compile(r"UITableView: (0x[0-9a-fA-F]+);") for match in re.finditer(classPattern, viewDescription): searchView = match.group(1) break # Try to find a direct subclass if not searchView: subclassPattern = re.compile(r"(0x[0-9a-fA-F]+); baseClass = UITableView;") for match in re.finditer(subclassPattern, viewDescription): searchView = match.group(1) break # SLOW: check every pointer in town if not searchView: pattern = re.compile(r"(0x[0-9a-fA-F]+)[;>]") for view in re.findall(pattern, viewDescription): if fb.evaluateBooleanExpression("[" + view + " isKindOfClass:(id)[UITableView class]]"): searchView = view break return searchView
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(vc, string, prefix, childPrefix): isMac = runtimeHelpers.isMacintoshArch() s = "%s%s%s\n" % (prefix, "" if prefix == "" else " ", _viewControllerDescription(vc)) nextPrefix = childPrefix + " |" numChildViewControllers = fb.evaluateIntegerExpression("(int)[(id)[%s childViewControllers] count]" % (vc)) childViewControllers = fb.evaluateExpression("(id)[%s childViewControllers]" % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression("(id)[(id)[%s childViewControllers] objectAtIndex:%d]" % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(viewController, string, nextPrefix, nextPrefix) if not isMac: isModal = fb.evaluateBooleanExpression( "%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s" % (vc, vc, vc) ) if isModal: modalVC = fb.evaluateObjectExpression("(id)[(id)%s presentedViewController]" % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( modalVC, string, childPrefix + " *M", nextPrefix ) s += "\n// '*M' means the view controller is presented modally." return string + s
def upwardsRecursiveDescription(view): if not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[UIView class]]' % view): return None currentView = view recursiveDescription = [] while currentView: viewDescription = fb.evaluateExpressionValue('(id)[%s debugDescription]' % (currentView)).GetObjectDescription() currentView = fb.evaluateExpression('(void*)[%s superview]' % (currentView)) try: if int(currentView, 0) == 0: currentView = None except: currentView = None if viewDescription: recursiveDescription.insert(0, viewDescription) if len(viewDescription) == 0: return None currentPrefix = "" builder = "" for viewDescription in recursiveDescription: builder += currentPrefix + viewDescription + "\n" currentPrefix += " | " return builder
def accessibilityGrepHierarchy(self, view, needle): a11yLabel = accessibilityLabel(view) # if we don't have any accessibility string - we should have some children if int(a11yLabel.GetValue(), 16) == 0: # We call private method that gives back all visible accessibility children # for view iOS 10 and higher if fb.evaluateBooleanExpression( "[UIView respondsToSelector:@selector(_accessibilityElementsAndContainersDescendingFromViews:options:sorted:)]" # noqa B950 ): accessibilityElements = fb.evaluateObjectExpression( "[UIView _accessibilityElementsAndContainersDescendingFromViews:@[(id)%s] options:0 sorted:NO]" # noqa B950 % view) else: accessibilityElements = fb.evaluateObjectExpression( "[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]" # noqa B950 % view) accessibilityElementsCount = fb.evaluateIntegerExpression( "[%s count]" % accessibilityElements) for index in range(0, accessibilityElementsCount): subview = fb.evaluateObjectExpression( "[%s objectAtIndex:%i]" % (accessibilityElements, index)) self.accessibilityGrepHierarchy(subview, needle) elif re.match(r".*" + needle + ".*", a11yLabel.GetObjectDescription(), re.IGNORECASE): classDesc = objHelpers.className(view) print("({} {}) {}".format(classDesc, view, a11yLabel.GetObjectDescription())) # First element that is found is copied to clipboard if not self.foundElement: self.foundElement = True cmd = 'echo %s | tr -d "\n" | pbcopy' % view os.system(cmd)
def run(self, arguments, options): view = fb.evaluateInputExpression(arguments[0]) opt = fb.evaluateBooleanExpression( "[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]" # noqa B950 ) traceCall = "_autolayoutTraceRecursively:1" if opt else "_autolayoutTrace" print(fb.describeObject("[{} {}]".format(view, traceCall)))
def run(self, arguments, options): view = fb.evaluateInputExpression(arguments[0]) opt = fb.evaluateBooleanExpression( '[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]' ) traceCall = '_autolayoutTraceRecursively:1' if opt else '_autolayoutTrace' print(fb.describeObject('[{} {}]'.format(view, traceCall)))
def tableViewInHierarchy(): viewDescription = fb.evaluateExpressionValue('(id)[(id)[[UIApplication sharedApplication] keyWindow] recursiveDescription]').GetObjectDescription() searchView = None # Try to find an instance of classPattern = re.compile(r'UITableView: (0x[0-9a-fA-F]+);') for match in re.finditer(classPattern, viewDescription): searchView = match.group(1) break # Try to find a direct subclass if not searchView: subclassPattern = re.compile(r'(0x[0-9a-fA-F]+); baseClass = UITableView;') for match in re.finditer(subclassPattern, viewDescription): searchView = match.group(1) break # SLOW: check every pointer in town if not searchView: pattern = re.compile(r'(0x[0-9a-fA-F]+)[;>]') for (view) in re.findall(pattern, viewDescription): if fb.evaluateBooleanExpression('[' + view + ' isKindOfClass:(id)[UITableView class]]'): searchView = view break return searchView
def upwardsRecursiveDescription(view, maxDepth=0): if not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[UIView class]]' % view) and not fb.evaluateBooleanExpression('[(id)%s isKindOfClass:(Class)[NSView class]]' % view): return None currentView = view recursiveDescription = [] depth = 0 while currentView and (maxDepth <= 0 or depth <= maxDepth): depth += 1 viewDescription = fb.evaluateExpressionValue('(id)[%s debugDescription]' % (currentView)).GetObjectDescription() currentView = fb.evaluateExpression('(void*)[%s superview]' % (currentView)) try: if int(currentView, 0) == 0: currentView = None except: currentView = None if viewDescription: recursiveDescription.insert(0, viewDescription) if len(viewDescription) == 0: return None currentPrefix = "" builder = "" for viewDescription in recursiveDescription: builder += currentPrefix + viewDescription + "\n" currentPrefix += " | " return builder
def run(self, arguments, options): startResponder = arguments[0] if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[UIResponder class]]') and not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[NSResponder class]]'): print 'Whoa, ' + startResponder + ' is not a UI/NSResponder. =(' return _printIterative(startResponder, _responderChain)
def _visualize(target): target = fb.evaluateInputExpression(target) if fb.evaluateBooleanExpression("(unsigned long)CFGetTypeID((CFTypeRef)" + target + ") == (unsigned long)CGImageGetTypeID()"): _showImage("(id)[UIImage imageWithCGImage:" + target + "]") else: if objectHelpers.isKindOfClass(target, "UIImage"): _showImage(target) elif objectHelpers.isKindOfClass(target, "UIView"): _showLayer("[(id)" + target + " layer]") elif objectHelpers.isKindOfClass(target, "CALayer"): _showLayer(target) elif (objectHelpers.isKindOfClass(target, "UIColor") or objectHelpers.isKindOfClass(target, "CIColor") or _colorIsCGColorRef(target)): _showColor(target) elif objectHelpers.isKindOfClass(target, "NSData"): if _dataIsImage(target): _showImage("(id)[UIImage imageWithData:" + target + "]") elif _dataIsString(target): print( fb.describeObject("[[NSString alloc] initWithData:" + target + " encoding:4]")) else: print("Data isn't an image and isn't a string.") else: print( "{} isn't supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef." .format( # noqa B950 objectHelpers.className(target)))
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( vc, string, prefix, childPrefix): s = '%s%s%s\n' % (prefix, '' if prefix == '' else ' ', _viewControllerDescription(vc)) nextPrefix = childPrefix + ' |' numChildViewControllers = fb.evaluateIntegerExpression( '(int)[(id)[%s childViewControllers] count]' % (vc)) childViewControllers = fb.evaluateExpression( '(id)[%s childViewControllers]' % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression( '(id)[(id)[%s childViewControllers] objectAtIndex:%d]' % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( viewController, string, nextPrefix, nextPrefix) isModal = fb.evaluateBooleanExpression( '%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s' % (vc, vc, vc)) if isModal: modalVC = fb.evaluateObjectExpression( '(id)[(id)%s presentedViewController]' % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix( modalVC, string, childPrefix + ' *M', nextPrefix) s += '\n// \'*M\' means the view controller is presented modally.' return string + s
def _visualize(target): target = fb.evaluateInputExpression(target) if fb.evaluateBooleanExpression('(unsigned long)CFGetTypeID((CFTypeRef)' + target + ') == (unsigned long)CGImageGetTypeID()'): _showImage('(id)[UIImage imageWithCGImage:' + target + ']') else: if objectHelpers.isKindOfClass(target, 'UIImage'): _showImage(target) elif objectHelpers.isKindOfClass(target, 'UIView'): _showLayer('[(id)' + target + ' layer]') elif objectHelpers.isKindOfClass(target, 'CALayer'): _showLayer(target) elif objectHelpers.isKindOfClass( target, 'UIColor') or objectHelpers.isKindOfClass( target, 'CIColor') or _colorIsCGColorRef(target): _showColor(target) elif objectHelpers.isKindOfClass(target, 'NSData'): if _dataIsImage(target): _showImage('(id)[UIImage imageWithData:' + target + ']') elif _dataIsString(target): print( fb.describeObject('[[NSString alloc] initWithData:' + target + ' encoding:4]')) else: print('Data isn\'t an image and isn\'t a string.') else: print( '{} isn\'t supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef.' .format(objectHelpers.className(target)))
def _visualize(target): target = '(' + target + ')' if fb.evaluateBooleanExpression('(unsigned long)CFGetTypeID((CFTypeRef)' + target + ') == (unsigned long)CGImageGetTypeID()'): _showImage('(id)[UIImage imageWithCGImage:' + target + ']') else: if objectHelpers.isKindOfClass(target, 'UIImage'): _showImage(target) elif objectHelpers.isKindOfClass(target, 'UIView'): _showLayer('[(id)' + target + ' layer]') elif objectHelpers.isKindOfClass(target, 'CALayer'): _showLayer(target) elif objectHelpers.isKindOfClass(target, 'NSData'): if _dataIsImage(target): _showImage('(id)[UIImage imageWithData:' + target + ']') elif _dataIsString(target): lldb.debugger.HandleCommand( 'po (NSString*)[[NSString alloc] initWithData:' + target + ' encoding:4]') else: print 'Data isn\'t an image and isn\'t a string.' else: print '{} isn\'t supported. You can visualize UIImage, CGImageRef, UIView, CALayer or NSData.'.format( objectHelpers.className(target))
def tableViewInHierarchy(): viewDescription = fb.evaluateExpressionValue( '(id)[(id)[UIWindow keyWindow] recursiveDescription]').GetObjectDescription() searchView = None # Try to find an instance of classPattern = re.compile(r'UITableView: (0x[0-9a-fA-F]+);') for match in re.finditer(classPattern, viewDescription): searchView = match.group(1) break # Try to find a direct subclass if not searchView: subclassPattern = re.compile(r'(0x[0-9a-fA-F]+); baseClass = UITableView;') for match in re.finditer(subclassPattern, viewDescription): searchView = match.group(1) break # SLOW: check every pointer in town if not searchView: pattern = re.compile(r'(0x[0-9a-fA-F]+)[;>]') for (view) in re.findall(pattern, viewDescription): if fb.evaluateBooleanExpression('[' + view + ' isKindOfClass:(id)[UITableView class]]'): searchView = view break return searchView
def run(self, arguments, options): startResponder = arguments[0] if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[UIResponder class]]'): print 'Whoa, ' + startResponder + ' is not a UIResponder. =(' return _printIterative(startResponder, _responderChain)
def accessibilityElements(view): if fb.evaluateBooleanExpression( '[UIView instancesRespondToSelector:@selector(accessibilityElements)]' ): a11yElements = fb.evaluateExpression( '(id)[%s accessibilityElements]' % view, False) if int(a11yElements, 16) != 0: return a11yElements if fb.evaluateBooleanExpression( '[%s respondsToSelector:@selector(_accessibleSubviews)]' % view): return fb.evaluateExpression('(id)[%s _accessibleSubviews]' % (view), False) else: return fb.evaluateObjectExpression( '[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]' % view)
def forceStartAccessibilityServer(): #We try to start accessibility server only if we don't have needed method active if not fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_accessibilityElementsInContainer:)]'): #Starting accessibility server is different for simulator and device if isRunningInSimulator(): fb.evaluateEffect('[[UIApplication sharedApplication] accessibilityActivate]') else: fb.evaluateEffect('[[[UIApplication sharedApplication] _accessibilityBundlePrincipalClass] _accessibilityStartServer]')
def forceStartAccessibilityServer(): #We try to start accessibility server only if we don't have needed method active if not fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_accessibilityElementsInContainer:)]'): #Starting accessibility server is different for simulator and device if fb.evaluateExpressionValue('(id)[[UIDevice currentDevice] model]').GetObjectDescription().lower().find('simulator') >= 0: lldb.debugger.HandleCommand('expr -l objc++ -- (void)[[UIApplication sharedApplication] accessibilityActivate]') else: lldb.debugger.HandleCommand('expr -l objc++ -- (void)[[[UIApplication sharedApplication] _accessibilityBundlePrincipalClass] _accessibilityStartServer]')
def forceStartAccessibilityServer(): #We try to start accessibility server only if we don't have needed method active if not fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_accessibilityElementsInContainer:)]'): #Starting accessibility server is different for simulator and device if fb.evaluateExpressionValue('(id)[[UIDevice currentDevice] model]').GetObjectDescription().lower().find('simulator') >= 0: lldb.debugger.HandleCommand('expr (void)[[UIApplication sharedApplication] accessibilityActivate]') else: lldb.debugger.HandleCommand('expr (void)[[[UIApplication sharedApplication] _accessibilityBundlePrincipalClass] _accessibilityStartServer]')
def dismissViewController(viewController): vc = "(%s)" % (viewController) if fb.evaluateBooleanExpression( "%s != nil && ((BOOL)[(id)%s isKindOfClass:(Class)[UIViewController class]])" % (vc, vc)): isPresented = fb.evaluateBooleanExpression( "[%s presentingViewController] != nil" % vc) if isPresented: fb.evaluateEffect( "[(UIViewController *)%s dismissViewControllerAnimated:YES completion:nil]" # noqa B950 % vc) else: raise Exception("Argument must be presented") else: raise Exception("Argument must be a UIViewController")
def forceStartAccessibilityServer(): #We try to start accessibility server only if we don't have needed method active if not fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_accessibilityElementsInContainer:)]'): #Starting accessibility server is different for simulator and device if isRunningInSimulator(): lldb.debugger.HandleCommand('eobjc (void)[[UIApplication sharedApplication] accessibilityActivate]') else: lldb.debugger.HandleCommand('eobjc (void)[[[UIApplication sharedApplication] _accessibilityBundlePrincipalClass] _accessibilityStartServer]')
def run(self, arguments, options): object = fb.evaluateObjectExpression(arguments[0]) isHidden = fb.evaluateBooleanExpression('[' + object + ' isHidden]') shouldHide = not isHidden for x in range(0, 2): viewHelpers.setViewHidden(object, shouldHide) viewHelpers.setViewHidden(object, isHidden)
def isMacintoshArch(): arch = currentArch() if not arch == 'x86_64': return False nsClassName = 'NSApplication' command = '(void*)objc_getClass("{}")'.format(nsClassName) return (fb.evaluateBooleanExpression(command + '!= nil'))
def isMacintoshArch(): arch = currentArch() if not arch == "x86_64": return False nsClassName = "NSApplication" command = '(void*)objc_getClass("{}")'.format(nsClassName) return fb.evaluateBooleanExpression(command + "!= nil")
def run(self, arguments, options): object = fb.evaluateObjectExpression(arguments[0]) if options.appleWay: if fb.evaluateBooleanExpression('[{} respondsToSelector:@selector(_ivarDescription)]'.format(object)): command = 'po [{} _ivarDescription]'.format(object) else: print 'Sorry, but it seems Apple dumped the _ivarDescription method' return else: objectClass = fb.evaluateExpressionValue('(id)[(id)(' + object + ') class]').GetObjectDescription() command = 'p *(({} *)((id){}))'.format(objectClass, object) lldb.debugger.HandleCommand(command)
def _viewControllerDescription(viewController): vc = '(%s)' % (viewController) if fb.evaluateBooleanExpression('[(id)%s isViewLoaded]' % (vc)): result = fb.evaluateExpressionValue('(id)[[NSString alloc] initWithFormat:@"<%%@: %%p; view = <%%@; %%p>; frame = (%%g, %%g; %%g, %%g)>", (id)NSStringFromClass((id)[(id)%s class]), %s, (id)[(id)[(id)%s view] class], (id)[(id)%s view], ((CGRect)[(id)[(id)%s view] frame]).origin.x, ((CGRect)[(id)[(id)%s view] frame]).origin.y, ((CGRect)[(id)[(id)%s view] frame]).size.width, ((CGRect)[(id)[(id)%s view] frame]).size.height]' % (vc, vc, vc, vc, vc, vc, vc, vc)) else: result = fb.evaluateExpressionValue('(id)[[NSString alloc] initWithFormat:@"<%%@: %%p; view not loaded>", (id)NSStringFromClass((id)[(id)%s class]), %s]' % (vc, vc)) if result.GetError() is not None and str(result.GetError()) != 'success': return '[Error getting description.]' else: return result.GetObjectDescription()
def run(self, arguments, options): isMac = runtimeHelpers.isMacintoshArch() if arguments[0] == '__keyWindow_rootVC_dynamic__': if fb.evaluateBooleanExpression('[UIViewController respondsToSelector:@selector(_printHierarchy)]'): lldb.debugger.HandleCommand('po [UIViewController _printHierarchy]') return arguments[0] = '(id)[(id)[[UIApplication sharedApplication] keyWindow] rootViewController]' if isMac: arguments[0] = '(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:0] contentViewController]' print vcHelpers.viewControllerRecursiveDescription(arguments[0])
def run(self, arguments, options): startResponder = fb.evaluateInputExpression(arguments[0]) isMac = runtimeHelpers.isMacintoshArch() responderClass = 'UIResponder' if isMac: responderClass = 'NSResponder' if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[' + responderClass + ' class]]'): print 'Whoa, ' + startResponder + ' is not a ' + responderClass + '. =(' return _printIterative(startResponder, _responderChain)
def run(self, arguments, options): startResponder = arguments[0] isMac = runtimeHelpers.isMacintoshArch() responderClass = 'UIResponder' if isMac: responderClass = 'NSResponder' if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[' + responderClass + ' class]]'): print('Whoa, ' + startResponder + ' is not a ' + responderClass + '. =(') return _printIterative(startResponder, _responderChain)
def run(self, arguments, options): isMac = runtimeHelpers.isMacintoshArch() if arguments[0] == '__keyWindow_rootVC_dynamic__': if fb.evaluateBooleanExpression('[UIViewController respondsToSelector:@selector(_printHierarchy)]'): print fb.describeObject('[UIViewController _printHierarchy]') return arguments[0] = '(id)[(id)[[UIApplication sharedApplication] keyWindow] rootViewController]' if isMac: arguments[0] = '(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:0] contentViewController]' print vcHelpers.viewControllerRecursiveDescription(arguments[0])
def _visualize(target): target = '(' + target + ')' if fb.evaluateBooleanExpression('(unsigned long)CFGetTypeID((CFTypeRef)' + target + ') == (unsigned long)CGImageGetTypeID()'): _showImage('(id)[UIImage imageWithCGImage:' + target + ']') else: if objectHelpers.isKindOfClass(target, 'UIImage'): _showImage(target) elif objectHelpers.isKindOfClass(target, 'UIView'): _showLayer('[(id)' + target + ' layer]') elif objectHelpers.isKindOfClass(target, 'CALayer'): _showLayer(target) else: print '{} is not supported. You can visualize UIImage, CGImageRef, UIView, or CALayer.'.format(objectHelpers.className(target))
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)): 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) commandString += ' "{}"'.format(URL) print(commandString)
def run(self, arguments, options): request = fb.evaluateInputExpression(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)): 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) commandString += ' "{}"'.format(URL) print commandString
def run(self, arguments, options): startResponder = fb.evaluateInputExpression(arguments[0]) isMac = runtimeHelpers.isMacintoshArch() responderClass = "UIResponder" if isMac: responderClass = "NSResponder" if not fb.evaluateBooleanExpression( "(BOOL)[(id)" + startResponder + " isKindOfClass:[" + responderClass + " class]]" ): print("Whoa, " + startResponder + " is not a " + responderClass + ". =(") return _printIterative(startResponder, _responderChain)
def _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(vc, string, prefix, childPrefix): s = '%s%s%s\n' % (prefix, '' if prefix == '' else ' ', _viewControllerDescription(vc)) nextPrefix = childPrefix + ' |' numChildViewControllers = fb.evaluateIntegerExpression('(int)[(id)[%s childViewControllers] count]' % (vc)) childViewControllers = fb.evaluateExpression('(id)[%s childViewControllers]' % (vc)) for i in range(0, numChildViewControllers): viewController = fb.evaluateExpression('(id)[(id)[%s childViewControllers] objectAtIndex:%d]' % (vc, i)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(viewController, string, nextPrefix, nextPrefix) isModal = fb.evaluateBooleanExpression('((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s' % (vc, vc)) if isModal: modalVC = fb.evaluateObjectExpression('(id)[(id)%s presentedViewController]' % (vc)) s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(modalVC, string, childPrefix + ' *M' , nextPrefix) s += '\n// \'*M\' means the view controller is presented modally.' return string + s
def _visualize(target): target = '(' + target + ')' if fb.evaluateBooleanExpression('(unsigned long)CFGetTypeID((CFTypeRef)' + target + ') == (unsigned long)CGImageGetTypeID()'): _showImage('(id)[UIImage imageWithCGImage:' + target + ']') else: if objectHelpers.isKindOfClass(target, 'UIImage'): _showImage(target) elif objectHelpers.isKindOfClass(target, 'UIView'): _showLayer('[(id)' + target + ' layer]') elif objectHelpers.isKindOfClass(target, 'CALayer'): _showLayer(target) elif objectHelpers.isKindOfClass(target, 'NSData'): if _dataIsImage(target): _showImage('(id)[UIImage imageWithData:' + target + ']'); elif _dataIsString(target): lldb.debugger.HandleCommand('po (NSString*)[[NSString alloc] initWithData:' + target + ' encoding:4]') else: print 'Data isn\'t an image and isn\'t a string'; else: print '{} is not supported. You can visualize UIImage, CGImageRef, UIView, CALayer or NSData.'.format(objectHelpers.className(target))
def _visualize(target): target = '(' + target + ')' if fb.evaluateBooleanExpression('(unsigned long)CFGetTypeID((CFTypeRef)' + target + ') == (unsigned long)CGImageGetTypeID()'): _showImage('(id)[UIImage imageWithCGImage:' + target + ']') else: if objectHelpers.isKindOfClass(target, 'UIImage'): _showImage(target) elif objectHelpers.isKindOfClass(target, 'UIView'): _showLayer('[(id)' + target + ' layer]') elif objectHelpers.isKindOfClass(target, 'CALayer'): _showLayer(target) elif objectHelpers.isKindOfClass(target, 'UIColor') or objectHelpers.isKindOfClass(target, 'CIColor') or _colorIsCGColorRef(target): _showColor(target) elif objectHelpers.isKindOfClass(target, 'NSData'): if _dataIsImage(target): _showImage('(id)[UIImage imageWithData:' + target + ']') elif _dataIsString(target): print fb.describeObject('[[NSString alloc] initWithData:' + target + ' encoding:4]') else: print 'Data isn\'t an image and isn\'t a string.' else: print '{} isn\'t supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef.'.format(objectHelpers.className(target))
def accessibilityGrepHierarchy(self, view, needle): a11yLabel = accessibilityLabel(view) #if we don't have any accessibility string - we should have some children if int(a11yLabel.GetValue(), 16) == 0: #We call private method that gives back all visible accessibility children for view # iOS 10 and higher if fb.evaluateBooleanExpression('[UIView respondsToSelector:@selector(_accessibilityElementsAndContainersDescendingFromViews:options:sorted:)]'): accessibilityElements = fb.evaluateObjectExpression('[UIView _accessibilityElementsAndContainersDescendingFromViews:@[(id)%s] options:0 sorted:NO]' % view) else: accessibilityElements = fb.evaluateObjectExpression('[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]' % view) accessibilityElementsCount = fb.evaluateIntegerExpression('[%s count]' % accessibilityElements) for index in range(0, accessibilityElementsCount): subview = fb.evaluateObjectExpression('[%s objectAtIndex:%i]' % (accessibilityElements, index)) self.accessibilityGrepHierarchy(subview, needle) elif re.match(r'.*' + needle + '.*', a11yLabel.GetObjectDescription(), re.IGNORECASE): classDesc = objHelpers.className(view) print('({} {}) {}'.format(classDesc, view, a11yLabel.GetObjectDescription())) #First element that is found is copied to clipboard if not self.foundElement: self.foundElement = True cmd = 'echo %s | tr -d "\n" | pbcopy' % view os.system(cmd)
def isEqualToString(identifier, needle): return fb.evaluateBooleanExpression('[%s isEqualToString:@"%s"]' % (identifier, needle))
def class_isMetaClass(klass): command = 'class_isMetaClass((Class){})'.format(klass) return fb.evaluateBooleanExpression(command)
def isFirstResponder(view): return fb.evaluateBooleanExpression('[%s isFirstResponder]' % view)
def isViewController(object): command = '[(id){} isKindOfClass:[UIViewController class]]'.format(object) isVC = fb.evaluateBooleanExpression(command) return isVC
def isKindOfClass(obj, className): isKindOfClassStr = '[' + obj + 'isKindOfClass:[{} class]]' return fb.evaluateBooleanExpression(isKindOfClassStr.format(className))
def isNSView(obj): return runtimeHelpers.isMacintoshArch() and fb.evaluateBooleanExpression( '[(id)%s isKindOfClass:(Class)[NSView class]]' % obj)
def isKindOfClass(obj, className): isKindOfClassStr = '[(id)' + obj + ' isKindOfClass:[{} class]]' return fb.evaluateBooleanExpression(isKindOfClassStr.format(className))
def isFirstResponder(view): return fb.evaluateBooleanExpression("[%s isFirstResponder]" % view)