mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-31 04:44:14 -04:00 
			
		
		
		
	added files via upload
This commit is contained in:
		| @@ -0,0 +1,293 @@ | ||||
| // | ||||
| //  FLEXSystemLogViewController.m | ||||
| //  FLEX | ||||
| // | ||||
| //  Created by Ryan Olson on 1/19/15. | ||||
| //  Copyright (c) 2020 FLEX Team. All rights reserved. | ||||
| // | ||||
|  | ||||
| #import "FLEXSystemLogViewController.h" | ||||
| #import "FLEXASLLogController.h" | ||||
| #import "FLEXOSLogController.h" | ||||
| #import "FLEXSystemLogCell.h" | ||||
| #import "FLEXMutableListSection.h" | ||||
| #import "FLEXUtility.h" | ||||
| #import "FLEXColor.h" | ||||
| #import "FLEXResources.h" | ||||
| #import "UIBarButtonItem+FLEX.h" | ||||
| #import "NSUserDefaults+FLEX.h" | ||||
| #import "flex_fishhook.h" | ||||
| #import <dlfcn.h> | ||||
|  | ||||
| @interface FLEXSystemLogViewController () | ||||
|  | ||||
| @property (nonatomic, readonly) FLEXMutableListSection<FLEXSystemLogMessage *> *logMessages; | ||||
| @property (nonatomic, readonly) id<FLEXLogController> logController; | ||||
|  | ||||
| @end | ||||
|  | ||||
| static void (*MSHookFunction)(void *symbol, void *replace, void **result); | ||||
|  | ||||
| static BOOL FLEXDidHookNSLog = NO; | ||||
| static BOOL FLEXNSLogHookWorks = NO; | ||||
|  | ||||
| BOOL (*os_log_shim_enabled)(void *addr) = nil; | ||||
| BOOL (*orig_os_log_shim_enabled)(void *addr) = nil; | ||||
| static BOOL my_os_log_shim_enabled(void *addr) { | ||||
|     return NO; | ||||
| } | ||||
|  | ||||
| @implementation FLEXSystemLogViewController | ||||
|  | ||||
| #pragma mark - Initialization | ||||
|  | ||||
| + (void)load { | ||||
|     // User must opt-into disabling os_log | ||||
|     if (!NSUserDefaults.standardUserDefaults.flex_disableOSLog) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Thanks to @Ram4096 on GitHub for telling me that | ||||
|     // os_log is conditionally enabled by the SDK version | ||||
|     void *addr = __builtin_return_address(0); | ||||
|     void *libsystem_trace = dlopen("/usr/lib/system/libsystem_trace.dylib", RTLD_LAZY); | ||||
|     os_log_shim_enabled = dlsym(libsystem_trace, "os_log_shim_enabled"); | ||||
|     if (!os_log_shim_enabled) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     FLEXDidHookNSLog = flex_rebind_symbols((struct rebinding[1]) {{ | ||||
|         "os_log_shim_enabled", | ||||
|         (void *)my_os_log_shim_enabled, | ||||
|         (void **)&orig_os_log_shim_enabled | ||||
|     }}, 1) == 0; | ||||
|  | ||||
|     if (FLEXDidHookNSLog && orig_os_log_shim_enabled != nil) { | ||||
|         // Check if our rebinding worked | ||||
|         FLEXNSLogHookWorks = my_os_log_shim_enabled(addr) == NO; | ||||
|     } | ||||
|  | ||||
|     // So, just because we rebind the lazily loaded symbol for | ||||
|     // this function doesn't mean it's even going to be used. | ||||
|     // While it seems to be sufficient for the simulator, for | ||||
|     // whatever reason it is not sufficient on-device. We need | ||||
|     // to actually hook the function with something like Substrate. | ||||
|  | ||||
|     // Check if we have substrate, and if so use that instead | ||||
|     void *handle = dlopen("/usr/lib/libsubstrate.dylib", RTLD_LAZY); | ||||
|     if (handle) { | ||||
|         MSHookFunction = dlsym(handle, "MSHookFunction"); | ||||
|  | ||||
|         if (MSHookFunction) { | ||||
|             // Set the hook and check if it worked | ||||
|             void *unused; | ||||
|             MSHookFunction(os_log_shim_enabled, my_os_log_shim_enabled, &unused); | ||||
|             FLEXNSLogHookWorks = os_log_shim_enabled(addr) == NO; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| - (id)init { | ||||
|     return [super initWithStyle:UITableViewStylePlain]; | ||||
| } | ||||
|  | ||||
|  | ||||
| #pragma mark - Overrides | ||||
|  | ||||
| - (void)viewDidLoad { | ||||
|     [super viewDidLoad]; | ||||
|  | ||||
|     self.showsSearchBar = YES; | ||||
|     self.pinSearchBar = YES; | ||||
|  | ||||
|     weakify(self) | ||||
|     id logHandler = ^(NSArray<FLEXSystemLogMessage *> *newMessages) { strongify(self) | ||||
|         [self handleUpdateWithNewMessages:newMessages]; | ||||
|     }; | ||||
|  | ||||
|     if (FLEXOSLogAvailable() && !FLEXNSLogHookWorks) { | ||||
|         _logController = [FLEXOSLogController withUpdateHandler:logHandler]; | ||||
|     } else { | ||||
|         _logController = [FLEXASLLogController withUpdateHandler:logHandler]; | ||||
|     } | ||||
|  | ||||
|     self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; | ||||
|     self.title = @"Waiting for Logs..."; | ||||
|  | ||||
|     // Toolbar buttons // | ||||
|  | ||||
|     UIBarButtonItem *scrollDown = [UIBarButtonItem | ||||
|         flex_itemWithImage:FLEXResources.scrollToBottomIcon | ||||
|         target:self | ||||
|         action:@selector(scrollToLastRow) | ||||
|     ]; | ||||
|     UIBarButtonItem *settings = [UIBarButtonItem | ||||
|         flex_itemWithImage:FLEXResources.gearIcon | ||||
|         target:self | ||||
|         action:@selector(showLogSettings) | ||||
|     ]; | ||||
|  | ||||
|     [self addToolbarItems:@[scrollDown, settings]]; | ||||
| } | ||||
|  | ||||
| - (void)viewWillAppear:(BOOL)animated { | ||||
|     [super viewWillAppear:animated]; | ||||
|  | ||||
|     [self.logController startMonitoring]; | ||||
| } | ||||
|  | ||||
| - (NSArray<FLEXTableViewSection *> *)makeSections { weakify(self) | ||||
|     _logMessages = [FLEXMutableListSection list:@[] | ||||
|         cellConfiguration:^(FLEXSystemLogCell *cell, FLEXSystemLogMessage *message, NSInteger row) { | ||||
|             strongify(self) | ||||
|          | ||||
|             cell.logMessage = message; | ||||
|             cell.highlightedText = self.filterText; | ||||
|  | ||||
|             if (row % 2 == 0) { | ||||
|                 cell.backgroundColor = FLEXColor.primaryBackgroundColor; | ||||
|             } else { | ||||
|                 cell.backgroundColor = FLEXColor.secondaryBackgroundColor; | ||||
|             } | ||||
|         } filterMatcher:^BOOL(NSString *filterText, FLEXSystemLogMessage *message) { | ||||
|             NSString *displayedText = [FLEXSystemLogCell displayedTextForLogMessage:message]; | ||||
|             return [displayedText localizedCaseInsensitiveContainsString:filterText]; | ||||
|         } | ||||
|     ]; | ||||
|  | ||||
|     self.logMessages.cellRegistrationMapping = @{ | ||||
|         kFLEXSystemLogCellIdentifier : [FLEXSystemLogCell class] | ||||
|     }; | ||||
|  | ||||
|     return @[self.logMessages]; | ||||
| } | ||||
|  | ||||
| - (NSArray<FLEXTableViewSection *> *)nonemptySections { | ||||
|     return @[self.logMessages]; | ||||
| } | ||||
|  | ||||
|  | ||||
| #pragma mark - Private | ||||
|  | ||||
| - (void)handleUpdateWithNewMessages:(NSArray<FLEXSystemLogMessage *> *)newMessages { | ||||
|     self.title = [self.class globalsEntryTitle:FLEXGlobalsRowSystemLog]; | ||||
|  | ||||
|     [self.logMessages mutate:^(NSMutableArray *list) { | ||||
|         [list addObjectsFromArray:newMessages]; | ||||
|     }]; | ||||
|      | ||||
|     // Re-filter messages to filter against new messages | ||||
|     if (self.filterText.length) { | ||||
|         [self updateSearchResults:self.filterText]; | ||||
|     } | ||||
|  | ||||
|     // "Follow" the log as new messages stream in if we were previously near the bottom. | ||||
|     UITableView *tv = self.tableView; | ||||
|     BOOL wasNearBottom = tv.contentOffset.y >= tv.contentSize.height - tv.frame.size.height - 100.0; | ||||
|     [self reloadData]; | ||||
|     if (wasNearBottom) { | ||||
|         [self scrollToLastRow]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| - (void)scrollToLastRow { | ||||
|     NSInteger numberOfRows = [self.tableView numberOfRowsInSection:0]; | ||||
|     if (numberOfRows > 0) { | ||||
|         NSIndexPath *last = [NSIndexPath indexPathForRow:numberOfRows - 1 inSection:0]; | ||||
|         [self.tableView scrollToRowAtIndexPath:last atScrollPosition:UITableViewScrollPositionBottom animated:YES]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| - (void)showLogSettings { | ||||
|     NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; | ||||
|     BOOL disableOSLog = defaults.flex_disableOSLog; | ||||
|     BOOL persistent = defaults.flex_cacheOSLogMessages; | ||||
|  | ||||
|     NSString *aslToggle = disableOSLog ? @"Enable os_log (default)" : @"Disable os_log"; | ||||
|     NSString *persistence = persistent ? @"Disable persistent logging" : @"Enable persistent logging"; | ||||
|  | ||||
|     NSString *title = @"System Log Settings"; | ||||
|     NSString *body = @"In iOS 10 and up, ASL has been replaced by os_log. " | ||||
|     "The os_log API is much more limited. Below, you can opt-into the old behavior " | ||||
|     "if you want cleaner, more reliable logs within FLEX, but this will break " | ||||
|     "anything that expects os_log to be working, such as Console.app. " | ||||
|     "This setting requires the app to restart to take effect. \n\n" | ||||
|  | ||||
|     "To get as close to the old behavior as possible with os_log enabled, logs must " | ||||
|     "be collected manually at launch and stored. This setting has no effect " | ||||
|     "on iOS 9 and below, or if os_log is disabled. " | ||||
|     "You should only enable persistent logging when you need it."; | ||||
|  | ||||
|     FLEXOSLogController *logController = (FLEXOSLogController *)self.logController; | ||||
|  | ||||
|     [FLEXAlert makeAlert:^(FLEXAlert *make) { | ||||
|         make.title(title).message(body); | ||||
|         make.button(aslToggle).destructiveStyle().handler(^(NSArray<NSString *> *strings) { | ||||
|             [defaults flex_toggleBoolForKey:kFLEXDefaultsDisableOSLogForceASLKey]; | ||||
|         }); | ||||
|  | ||||
|         make.button(persistence).handler(^(NSArray<NSString *> *strings) { | ||||
|             [defaults flex_toggleBoolForKey:kFLEXDefaultsiOSPersistentOSLogKey]; | ||||
|             logController.persistent = !persistent; | ||||
|             [logController.messages addObjectsFromArray:self.logMessages.list]; | ||||
|         }); | ||||
|         make.button(@"Dismiss").cancelStyle(); | ||||
|     } showFrom:self]; | ||||
| } | ||||
|  | ||||
|  | ||||
| #pragma mark - FLEXGlobalsEntry | ||||
|  | ||||
| + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row { | ||||
|     return @"⚠️  System Log"; | ||||
| } | ||||
|  | ||||
| + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row { | ||||
|     return [self new]; | ||||
| } | ||||
|  | ||||
|  | ||||
| #pragma mark - Table view data source | ||||
|  | ||||
| - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { | ||||
|     FLEXSystemLogMessage *logMessage = self.logMessages.filteredList[indexPath.row]; | ||||
|     return [FLEXSystemLogCell preferredHeightForLogMessage:logMessage inWidth:self.tableView.bounds.size.width]; | ||||
| } | ||||
|  | ||||
|  | ||||
| #pragma mark - Copy on long press | ||||
|  | ||||
| - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { | ||||
|     return YES; | ||||
| } | ||||
|  | ||||
| - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { | ||||
|     return action == @selector(copy:); | ||||
| } | ||||
|  | ||||
| - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { | ||||
|     if (action == @selector(copy:)) { | ||||
|         // We usually only want to copy the log message itself, not any metadata associated with it. | ||||
|         UIPasteboard.generalPasteboard.string = self.logMessages.filteredList[indexPath.row].messageText ?: @""; | ||||
|     } | ||||
| } | ||||
|  | ||||
| - (UIContextMenuConfiguration *)tableView:(UITableView *)tableView | ||||
| contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath | ||||
|                                     point:(CGPoint)point __IOS_AVAILABLE(13.0) { | ||||
|     weakify(self) | ||||
|     return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil | ||||
|         actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) { | ||||
|             UIAction *copy = [UIAction actionWithTitle:@"Copy" | ||||
|                                                  image:nil | ||||
|                                             identifier:@"Copy" | ||||
|                                                handler:^(UIAction *action) { strongify(self) | ||||
|                 // We usually only want to copy the log message itself, not any metadata associated with it. | ||||
|                 UIPasteboard.generalPasteboard.string = self.logMessages.filteredList[indexPath.row].messageText ?: @""; | ||||
|             }]; | ||||
|             return [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[copy]]; | ||||
|         } | ||||
|     ]; | ||||
| } | ||||
|  | ||||
| @end | ||||
		Reference in New Issue
	
	Block a user
	 Balackburn
					Balackburn