/app/utils/CLI.m
Objective C | 201 lines | 170 code | 30 blank | 1 comment | 30 complexity | 92213dc68d2dd1d5a55f2916de6697e5 MD5 | raw file
1#import "CLI.h" 2 3@implementation CLI 4 5static id sharedCLI = nil; 6 7+ (id)sharedInstance{ 8 if (sharedCLI == nil) { 9 sharedCLI = [[CLI alloc] init]; 10 } 11 return sharedCLI; 12} 13 14@synthesize appDelegate, pathToCLI; 15 16- (id)init { 17 if ((self = [super init])) { 18 authorizationRef = NULL; 19 } 20 return self; 21} 22 23- (NSMutableArray *)listApplications { 24 NSArray *result; 25 Application *application; 26 NSDictionary *attributes; 27 NSMutableArray *applications; 28 29 NSLog(@"Retrieving a list of configured applications"); 30 result = [self execute:[NSArray arrayWithObjects:@"list", @"-m", nil] elevated:NO]; 31 applications = [NSMutableArray arrayWithCapacity:[result count]]; 32 33 if ([result count] > 0) { 34 for (attributes in result) { 35 application = [[Application alloc] initWithAttributes:attributes]; 36 [application setDelegate:appDelegate]; 37 [applications addObject:application]; 38 } 39 } 40 41 return applications; 42} 43 44- (void) add:(Application *)application { 45 NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"add", application.path, nil]; 46 [arguments addObjectsFromArray:[application toArgumentArray]]; 47 NSLog(@"Adding application with hostname %@ using %@", application.host, arguments); 48 [self execute:arguments elevated:YES]; 49 [application didApplyChanges]; 50} 51 52- (void) update:(Application *)application { 53 NSDictionary *beforeChanges = [application beforeChanges]; 54 NSString *currentHost = [beforeChanges valueForKey:@"host"]; 55 NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"update", currentHost, nil]; 56 [arguments addObjectsFromArray:[application toArgumentArray]]; 57 NSLog(@"Updating application with hostname %@ using %@", application.host, arguments); 58 [self execute:arguments elevated:YES]; 59 [application didApplyChanges]; 60} 61 62- (void) delete:(Application *)application { 63 NSLog(@"Deleting application with hostname: %@", application.host); 64 [self execute:[NSArray arrayWithObjects:@"delete", application.host, nil] elevated:YES]; 65} 66 67- (void) restart:(Application *)application { 68 NSLog(@"Restarting application with hostname: %@", application.host); 69 [self execute:[NSArray arrayWithObjects:@"restart", application.host, nil] elevated:NO]; 70} 71 72- (void) restart { 73 NSLog(@"Restarting Apache"); 74 [self execute:[NSArray arrayWithObject:@"restart"] elevated:YES]; 75} 76 77- (BOOL) isPassengerModuleInstalled { 78 NSLog(@"Checking if the Passenger module is installed"); 79 NSDictionary *info = [self execute:[NSArray arrayWithObjects:@"info", @"-m", nil] elevated:NO]; 80 if (info) { 81 NSNumber *isInstalled = [info objectForKey:@"passenger_module_installed"]; 82 return [isInstalled boolValue]; 83 } else { 84 NSLog(@"Failed to read info, assuming Passenger module isn't installed."); 85 return NO; 86 } 87} 88 89// Inspired by: http://svn.kismac-ng.org/kmng/trunk/Subprojects/BIGeneric/BLAuthentication.m 90- (id) execute:(NSArray *)arguments elevated:(BOOL)elevated { 91 OSStatus status; 92 char **argumentsAsCArray = NULL; 93 unsigned int index; 94 95 FILE *communicationPipe; 96 NSFileHandle *file; 97 NSData *data; 98 NSError *error = nil; 99 id result = nil; 100 101 if (elevated) { 102 if ([self isAuthorized]) { 103 if ([arguments count] > 0) { 104 index = 0; 105 argumentsAsCArray = NSAllocateCollectable(sizeof(char*)*([arguments count]+1), 0); 106 while(index < [arguments count]) { 107 argumentsAsCArray[index++] = (char*)[[arguments objectAtIndex:index] UTF8String]; 108 } 109 argumentsAsCArray[index] = NULL; 110 } 111 112 status = AuthorizationExecuteWithPrivileges(authorizationRef, [pathToCLI UTF8String], 113 kAuthorizationFlagDefaults, argumentsAsCArray, 114 &communicationPipe); 115 116 if (status == PPANE_SUCCESS) { 117 if (communicationPipe) { 118 file = [[NSFileHandle alloc] initWithFileDescriptor:fileno(communicationPipe)]; 119 data = [file readDataToEndOfFile]; 120 [file closeFile]; 121 if ([data length] > 0) { 122 result = [[CJSONDeserializer deserializer] deserialize:data error:&error]; 123 if (error) { 124 NSLog(@"ppane returned invalid JSON: %@", [error description]); 125 } else { 126 return result; 127 } 128 } else { 129 NSLog(@"ppane didn't return any information"); 130 } 131 } 132 } else { 133 NSLog(@"AuthorizationExecuteWithPrivileges failed to execute ppane (%d)", status); 134 } 135 } else { 136 NSLog(@"Ignoring a privileged command because the pane isn't authorized"); 137 } 138 return [NSDictionary dictionary]; 139 } else { 140 return [self execute:arguments]; 141 } 142} 143 144- (id)execute:(NSArray *)arguments { 145 NSData *data; 146 NSError *error = nil; 147 id result = nil; 148 149 NSPipe *stdout = [NSPipe pipe]; 150 NSTask *ppane; 151 152 ppane = [[NSTask alloc] init]; 153 [ppane setLaunchPath:pathToCLI]; 154 [ppane setArguments:arguments]; 155 [ppane setStandardOutput:stdout]; 156 [ppane launch]; 157 [ppane waitUntilExit]; 158 159 if ([ppane terminationStatus] == PPANE_SUCCESS) { 160 data = [[stdout fileHandleForReading] readDataToEndOfFile]; 161 if ([data length] > 0) { 162 result = [[CJSONDeserializer deserializer] deserialize:data error:&error]; 163 if (error) { 164 NSLog(@"ppane returned invalid JSON: %@", [error description]); 165 } else { 166 return result; 167 } 168 } else { 169 NSLog(@"ppane didn't return any data"); 170 } 171 } else { 172 NSLog(@"NSTask failed to execute the command"); 173 } 174 return [NSDictionary dictionary]; 175} 176 177- (AuthorizationRef) authorizationRef { 178 return authorizationRef; 179} 180 181- (void) setAuthorizationRef:(AuthorizationRef)ref { 182 authorizationRef = ref; 183} 184 185- (void) deauthorize { 186 authorizationRef = NULL; 187} 188 189- (BOOL) isAuthorized { 190 if (authorizationRef == NULL) { 191 return NO; 192 } else { 193 return YES; 194 } 195} 196 197- (void) fakeAuthorize { 198 AuthorizationCreate(nil, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); 199} 200 201@end