def _visualize(target): target = fb.evaluateInputExpression(target) if fb.evaluateBooleanExpression("(unsigned long)CFGetTypeID((CFTypeRef)" + target + ") == (unsigned long)CGImageGetTypeID()"): _showImage("(id)[UIImage imageWithCGImage:" + target + "]") elif fb.evaluateBooleanExpression( "(unsigned long)CFGetTypeID((CFTypeRef)" + target + ") == (unsigned long)CVPixelBufferGetTypeID()"): _showPixelBuffer(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 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 _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 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 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]" # noqa B950 % view)
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 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 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]" # noqa B950 % vc) else: raise Exception("Argument is already presented") else: raise Exception("Argument must be a UIViewController")
def run(self, arguments, options): object = fb.evaluateObjectExpression(arguments[0]) isHidden = fb.evaluateBooleanExpression("[" + object + " isHidden]") shouldHide = not isHidden for _ 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 forceStartAccessibilityServer(): # We try to start accessibility server only if we don't have needed method active if not fb.evaluateBooleanExpression( "[UIView instancesRespondToSelector:@selector(_accessibilityElementsInContainer:)]" # noqa B950 ): # Starting accessibility server is different for simulator and device if isRunningInSimulator(): fb.evaluateEffect( "[[UIApplication sharedApplication] accessibilityActivate]") else: fb.evaluateEffect( "[[[UIApplication sharedApplication] _accessibilityBundlePrincipalClass] _accessibilityStartServer]" # noqa B950 )
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 Exception: currentView = None if viewDescription: recursiveDescription.insert(0, viewDescription) if not len(viewDescription): return None currentPrefix = "" builder = "" for viewDescription in recursiveDescription: builder += currentPrefix + viewDescription + "\n" currentPrefix += " | " return builder
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]' # noqa B950 % (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]' # noqa B950 % (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): 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): 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]" # noqa B950 if isMac: arguments[ 0] = "(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:0] contentViewController]" # noqa B950 print(vcHelpers.viewControllerRecursiveDescription(arguments[0]))
def isFirstResponder(view): return fb.evaluateBooleanExpression("[%s isFirstResponder]" % view)
def isEqualToString(identifier, needle): return fb.evaluateBooleanExpression('[%s isEqualToString:@"%s"]' % (identifier, needle))
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( # noqa B950 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' # noqa B950 ) 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 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 class_isMetaClass(klass): command = "class_isMetaClass((Class){})".format(klass) return fb.evaluateBooleanExpression(command)
def isViewController(object): command = "[(id){} isKindOfClass:[UIViewController class]]".format( object) isVC = fb.evaluateBooleanExpression(command) return isVC