nitoInstaller.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //
  2. // nitoInstaller.m
  3. // nitotvinstaller
  4. //
  5. // Created by Kevin Bradley on 1/31/18.
  6. // Copyright © 2018 Kevin Bradley. All rights reserved.
  7. //
  8. #include <objc/runtime.h>
  9. #include <libgen.h>
  10. #include <dlfcn.h>
  11. #include <CoreFoundation/CoreFoundation.h>
  12. #ifdef ARM
  13. #include <Foundation/Foundation.h> // NSObject
  14. #endif
  15. #import "nitoInstaller.h"
  16. #include<stdio.h>
  17. //#include<conio.h>
  18. #include<string.h>
  19. #define CORE_SERVICE_FRAMEWORK "/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices"
  20. NSObject * workspace; // Intentionally void * so as to NOT involve @interface files
  21. @interface LSApplicationWorkspace: NSObject
  22. - (id)allApplications;
  23. - (void)openApplicationWithBundleID:(NSString *)string;
  24. - (id)defaultWorkspace;
  25. @end
  26. void get_string(char *string);
  27. @implementation nitoInstaller
  28. - (NSString *)airPlayVersionNumber
  29. {
  30. NSDictionary *infoDictionary = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/PrivateFrameworks/AirPlaySupport.framework/Info.plist"];
  31. return infoDictionary[@"CFBundleVersion"];
  32. }
  33. + (NSString *)getTextWithPrompt:(NSString *)thePrompt
  34. {
  35. NSString *prompt = [NSString stringWithFormat:@"\n%@ ", thePrompt];
  36. fprintf(stdout, "%s", [prompt UTF8String]);
  37. NSString *thestring = [NSString.alloc initWithData:
  38. [NSFileHandle.fileHandleWithStandardInput availableData]
  39. encoding:NSUTF8StringEncoding];
  40. return [thestring stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  41. }
  42. - (NSString *)tarPathForCurrentMode
  43. {
  44. NSString *path = nil;
  45. switch (self.versionState) {
  46. case InstallVersionStateNine:
  47. path= @"/usr/bin/tar";
  48. break;
  49. case InstallVersionStateTenOne:
  50. path= @"/tmp/usr/bin/tar"; //need to verify
  51. break;
  52. case InstallVersionStateTenTwo:
  53. path= @"/usr/bin/tar";
  54. break;
  55. case InstallVersionStateEleven:
  56. path= @"/jb/usr/bin/tar";
  57. break;
  58. default:
  59. break;
  60. }
  61. return path;
  62. }
  63. - (NSString *)bootstrapPathForVersion:(NSString *)swVers
  64. {
  65. NSString *bootstrapPath = @"https://nitosoft.com/ATV4/bootstraps/";
  66. {
  67. OurLog(@"srcvers: %@", swVers);//352.18.1 == 11.0, 353.50 = 11.1
  68. if ([swVers compare:@"352.18.1" options:NSNumericSearch] != NSOrderedAscending)
  69. {
  70. OurLog(@"11.x or greater!");
  71. self.versionState = InstallVersionStateEleven;
  72. bootstrapPath = [bootstrapPath stringByAppendingString:@"bootstrap11.tar"];
  73. } else if([swVers compare:@"320.20.1" options:NSNumericSearch] != NSOrderedAscending)
  74. {
  75. OurLog(@"10.2.2 or greater!");
  76. self.versionState = InstallVersionStateTenTwo;
  77. bootstrapPath = [bootstrapPath stringByAppendingString:@"bootstrap11.tar"];
  78. } else if([swVers compare:@"301.44.3" options:NSNumericSearch] != NSOrderedAscending)
  79. {
  80. OurLog(@"10.0 or greater");
  81. self.versionState = InstallVersionStateTenOne;
  82. bootstrapPath = [bootstrapPath stringByAppendingString:@"bootstrap9.tar"];
  83. } else {
  84. OurLog(@"9.0 or greater?");
  85. self.versionState = InstallVersionStateNine;
  86. bootstrapPath = [bootstrapPath stringByAppendingString:@"bootstrap9.tar"];
  87. }
  88. }
  89. return bootstrapPath;
  90. }
  91. + (int)returnForProcess:(NSString *)call
  92. {
  93. if (call==nil)
  94. return 0;
  95. char line[200];
  96. FILE* fp = popen([call UTF8String], "r");
  97. //NSMutableArray *lines = [[NSMutableArray alloc]init];
  98. if (fp)
  99. {
  100. while (fgets(line, sizeof line, fp))
  101. {
  102. NSString *s = [NSString stringWithCString:line encoding:NSUTF8StringEncoding];
  103. s = [s stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  104. OurLog(@"%@",s);
  105. // [lines addObject:s];
  106. }
  107. }
  108. int returnStatus = pclose(fp);
  109. return returnStatus;
  110. }
  111. int main(int argc, const char * argv[]) {
  112. NSString *runPath = [[NSFileManager defaultManager] currentDirectoryPath];
  113. nitoInstaller *installer = [nitoInstaller new];
  114. //checking for dpkg status file might not be the most elegant check, but if its there we should have bootstrap installed
  115. NSString *fileCheck = @"/var/lib/dpkg/status";
  116. OurLog(@"\n\nWelcome to the nitoTV 2.0 & bootstrap installer script!");
  117. OurLog(@"\nWe will detect your tvOS version and install the compatible bootstrap nitoTV, upon completion nitoTV should appear on your AppleTV\n\n");
  118. if ([[NSFileManager defaultManager] fileExistsAtPath:fileCheck])
  119. {
  120. char c;
  121. printf("\nIt appears you have already installed nitoTV and the bootstrap, it is NOT recommended to do this again, are you sure you want to continue? [y/n]?");
  122. c=getchar();
  123. while(c!='y' && c!='n')
  124. {
  125. if (c!='\n'){
  126. printf("[y/n]");
  127. }
  128. c=getchar();
  129. }
  130. if (c == 'n')
  131. {
  132. OurLog(@"\nsmart move... exiting\n");
  133. return 0;
  134. } else if (c == 'y') {
  135. OurLog(@"\nits your funeral....\n");
  136. }
  137. }
  138. [installer installPackageInPath:runPath];
  139. CFRunLoopRun();
  140. return 0;
  141. }
  142. - (void)openApp:(NSString *)bundleID;
  143. {
  144. Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace"); if (!LSApplicationWorkspace_class) {fprintf(stderr,"Unable to get Workspace class\n"); } workspace = [LSApplicationWorkspace_class performSelector:@selector (defaultWorkspace)]; if (!workspace) {fprintf(stderr,"Unable to get Workspace\n"); }
  145. void *CS_handle = dlopen (CORE_SERVICE_FRAMEWORK, RTLD_NOW); if (!CS_handle) {
  146. fprintf(stderr,"Can't find %s!\n", CORE_SERVICE_FRAMEWORK);
  147. return;
  148. }
  149. if (workspace){
  150. [workspace performSelector:@selector(openApplicationWithBundleID:) withObject:(id) bundleID ];
  151. }
  152. }
  153. - (void)installPackageInPath:(NSString *)thePath
  154. {
  155. NSString *bootstrapPath = [self bootstrapPathForVersion:[self airPlayVersionNumber]];
  156. NSURL *url = [NSURL URLWithString:bootstrapPath];
  157. OurLog(@"Downloading file: %@", bootstrapPath);
  158. NSString *downloadLocation = [thePath stringByAppendingPathComponent:bootstrapPath.lastPathComponent];
  159. self.downloader = [URLDownloader new];
  160. [self.downloader downloadFileWithURL:url toLocation:downloadLocation withCredential:nil completed:^(NSString *downloadedFile) {
  161. OurLog(@"Download complete: %@", downloadedFile);
  162. OurLog(@"Installing...");
  163. NSString *tarPath = [self tarPathForCurrentMode];
  164. NSString *installString = [NSString stringWithFormat:@"%@ fxpv %@ -C / ; /usr/libexec/substrate ; /usr/bin/uicache ; /bin/bash /usr/libexec/nito/firmware.sh ; rm /var/mobile/Library/Preferences/Featured.plist", tarPath, downloadedFile];
  165. OurLog(@"install string: %@", installString);
  166. [nitoInstaller returnForProcess:installString];
  167. if (self.versionState == InstallVersionStateNine)
  168. {
  169. [nitoInstaller returnForProcess:@"/usr/bin/killall -9 PineBoard HeadBoard lsd nitoTV"];
  170. sleep(35);
  171. } else {
  172. sleep(10);
  173. }
  174. [self openApp:@"com.nito.nitoTV4"];
  175. CFRunLoopStop(CFRunLoopGetCurrent());
  176. }];
  177. }
  178. @end