1313#import < Security/Security.h>
1414#import < MapKit/MapKit.h>
1515
16- #define theSpan 0 .30f ;
1716static NSString *const kServerURIUser = @" /api/mdm/devices/search" ;
1817static NSString *const kServerURIDevices = @" /api/mdm/devices" ;
1918static NSString *const kServerURIGPS = @" /api/mdm/devices/gps" ;
2524static NSString *const kServerInternalApps = @" /api/mam/apps/public" ;
2625static NSString *const kServerPurchasedApps = @" /api/mam/apps/purchasedappsearch" ;
2726static NSString *const kServerAllApps = @" /api/mam/apps/search" ;
28- static NSString *const kServerURIInstallApp = @" /api/mam/apps/purchased/" ;
29-
27+ static NSString *const kServerURIInstallPurchasedApp = @" /api/mam/apps/purchased/" ;
3028
3129@interface AppDelegate ()
3230@property (weak ) IBOutlet NSWindow *window;
@@ -85,13 +83,13 @@ - (IBAction)closeSecWindow:(id)sender;
8583
8684// App Install Window
8785@property (weak ) IBOutlet NSWindow *availableApps;
88- @property (weak ) IBOutlet NSTableView *installAppsTable ;
86+ @property (weak ) IBOutlet NSTableView *installAppsTableView ;
8987@property NSArray *installAppsTableArray;
90- - (IBAction )installAppsTable : (id )sender ;
88+ - (IBAction )installAppsTableView : (id )sender ;
9189- (IBAction )installApp : (id )sender ;
9290@property NSDictionary *installAppDict;
9391
94-
92+ // Main Window
9593@property (weak ) IBOutlet NSTextField *searchValue;
9694@property (weak ) IBOutlet NSPopUpButtonCell *searchParamater;
9795@property (weak ) IBOutlet NSPopUpButton *maxDeviceSearch;
@@ -123,9 +121,13 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
123121 NSArray *creds = [self getCredsFromKeychainWithUserName: storedUsername serverURL: storedServerURL];
124122 if (storedServerURL) {
125123 self.serverURL .stringValue = storedServerURL;
124+ } else {
125+ [self changeCredentials: self ];
126126 }
127127 if (storedUsername) {
128128 self.userName .stringValue = storedUsername;
129+ } else {
130+ [self changeCredentials: self ];
129131 }
130132 if (creds.count == 2 ) {
131133 self.password .stringValue = creds.firstObject ;
@@ -139,7 +141,7 @@ - (void)setCredsToKeychainWithUserName:(NSString *)userName serverURL:(NSString
139141 void *passwordAndAPIKey = NULL ;
140142 UInt32 passwordandAPIKeyLength = 0 ;
141143 NSString *creds = [[password stringByAppendingString: @" \n " ] stringByAppendingString: awTenantCode];
142- SecKeychainItemRef * keychainRef = NULL ;
144+ SecKeychainItemRef keychainRef = NULL ;
143145 NSString *currentUserName = [[NSUserDefaults standardUserDefaults ] valueForKey: @" Username" ];
144146 NSString *currentServerURL = [[NSUserDefaults standardUserDefaults ] valueForKey: @" ServerURL" ];
145147 // Before trying to create or update the keychain, we need to try and find it, which allows us to set the keychainRef pointer properly
@@ -200,12 +202,9 @@ - (void)setCredsToKeychainWithUserName:(NSString *)userName serverURL:(NSString
200202 [[NSUserDefaults standardUserDefaults ] setValue: userName forKey: @" Username" ];
201203 [[NSUserDefaults standardUserDefaults ] setValue: serverURL forKey: @" ServerURL" ];
202204 }
203- // if ([serverURL isEqualToString:currentServerURL]) {
204- //
205- // OSStatus ret = SecKeychainItemModifyAttributesAndData(keychainRef, NULL, (UInt32)creds.length, (void *)creds.UTF8String);
206- // }
207205 } else {
208- OSStatus ret = SecKeychainAddGenericPassword (NULL , (UInt32)serverURL.length , serverURL.UTF8String , (UInt32)userName.length , userName.UTF8String , (UInt32)creds.length , (void *)creds.UTF8String , keychainRef);
206+ OSStatus ret = SecKeychainAddGenericPassword (NULL , (UInt32)serverURL.length , serverURL.UTF8String , (UInt32)userName.length , userName.UTF8String , (UInt32)creds.length , (void *)creds.UTF8String , &keychainRef);
207+
209208 // NSLog(@"The return code from trying to add the keychain entry: %d", ret);
210209 if (ret != errSecSuccess) {
211210 // Should show an NSAlert here about how it couldn't set a keychain
@@ -218,6 +217,7 @@ - (void)setCredsToKeychainWithUserName:(NSString *)userName serverURL:(NSString
218217 return ;
219218 }];
220219 }
220+ CFRelease (keychainRef);
221221
222222 [[NSUserDefaults standardUserDefaults ] setValue: userName forKey: @" Username" ];
223223 [[NSUserDefaults standardUserDefaults ] setValue: serverURL forKey: @" ServerURL" ];
@@ -1053,14 +1053,13 @@ - (IBAction)getSecurityInfo:(id)sender {
10531053// }
10541054
10551055
1056- - (NSDictionary *)makePostRequest : (NSString *)URIPath serialNumber : (NSString *)serialNumber postData : ( NSDictionary *) postData {
1056+ - (NSDictionary *)sendPostRequest : (NSString *)URIPath serialNumber : (NSString *)serialNumber {
10571057 // Create the URL request with the hostname and search URI's
10581058 NSURLComponents *airWatchURLComponents = [NSURLComponents componentsWithString: self .serverURL.stringValue];
1059- // NSString *serialNumberPlusGPS = [[@"/" stringByAppendingString:serialNumber] stringByAppendingString:@"/gps"];
10601059 airWatchURLComponents.path = URIPath;
1061- NSURLQueryItem *serialNumberParamater = [NSURLQueryItem queryItemWithName: @" searchby " value :@" serialnumber " ];
1062- NSURLQueryItem *serialNumberValue = [ NSURLQueryItem queryItemWithName: @" id " value: serialNumber] ;
1063- airWatchURLComponents. queryItems = @[ serialNumberParamater, serialNumberValue ];
1060+ NSDictionary *postData = [[ NSDictionary alloc ] initWithObjectsAndKeys :@" SerialNumber " , serialNumber , nil ];
1061+ NSError *error ;
1062+ NSData *JSONPostData = [ NSJSONSerialization dataWithJSONObject: postData options: 0 error: &error ];
10641063
10651064 // Create the base64 encoded authentication
10661065 NSString *authenticationString = [NSString stringWithFormat: @" %@ :%@ " , self .userName.stringValue, self .password.stringValue];
@@ -1074,6 +1073,7 @@ - (NSDictionary *)makePostRequest:(NSString *)URIPath serialNumber:(NSString *)s
10741073 [URLRequest addValue: self .awTenantCode.stringValue forHTTPHeaderField: @" aw-tenant-code" ];
10751074 [URLRequest addValue: @" application/json" forHTTPHeaderField: @" Accept" ];
10761075 [URLRequest addValue: totalAuthHeader forHTTPHeaderField: @" Authorization" ];
1076+ [URLRequest setHTTPBody: JSONPostData];
10771077 URLRequest.HTTPMethod = @" POST" ;
10781078
10791079 // Create the semaphore
@@ -1158,10 +1158,11 @@ - (IBAction)installPurchasedApplication:(id)sender {
11581158 // NSLog(@"%@", returnedJSON);
11591159 NSMutableArray *appsArray = [NSMutableArray array ];
11601160 appsArray = returnedJSON[@" Application" ];
1161+ NSLog (@" %@ " , appsArray);
11611162 NSArray *descriptor = [NSArray arrayWithObject: [NSSortDescriptor sortDescriptorWithKey: @" ApplicationName" ascending: YES ]];
11621163 NSArray *sortedApps = [appsArray sortedArrayUsingDescriptors: descriptor];
11631164 self.installAppsTableArray = sortedApps;
1164- [self .installAppsTable reloadData ];
1165+ [self .installAppsTableView reloadData ];
11651166 dispatch_semaphore_signal (sema);
11661167 }] resume ];
11671168
@@ -1228,8 +1229,77 @@ - (IBAction)closeNetworkWindow:(id)sender {
12281229 [self .window endSheet: self .networkWindow];
12291230}
12301231- (IBAction )installApp : (id )sender {
1231- // NSInteger selectedRow = [self.deviceTableView selectedRow];
1232- // [self makePostRequest:kServerURIInstallApp serialNumber:self.deviceTableArray[selectedRow][@"SerialNumber"] postData:self.installAppDict];
1232+ NSInteger deviceSelectedRow = [self .deviceTableView selectedRow ];
1233+ NSString *serialNumber = self.deviceTableArray [deviceSelectedRow][@" SerialNumber" ];
1234+ NSLog (@" Sending install command for serial: %@ " , serialNumber);
1235+
1236+ NSInteger appSelectedRow = [self .installAppsTableView selectedRow ];
1237+ NSNumber *appToInstall = self.installAppsTableArray [appSelectedRow][@" Id" ][@" Value" ];
1238+ NSLog (@" Installing app: %@ " , appToInstall);
1239+ // Create the URL request with the hostname and search URI's
1240+ NSURLComponents *airWatchURLComponents = [NSURLComponents componentsWithString: self .serverURL.stringValue];
1241+
1242+ airWatchURLComponents.path = [[kServerURIInstallPurchasedApp stringByAppendingString: appToInstall.stringValue] stringByAppendingString: @" /install" ];
1243+ NSDictionary *postData = [[NSDictionary alloc ] initWithObjectsAndKeys: serialNumber, @" SerialNumber" , nil ];
1244+ NSError *error;
1245+ NSData *JSONPostData = [NSJSONSerialization dataWithJSONObject: postData options: 0 error: &error];
1246+ if (JSONPostData) {
1247+ // process the data
1248+ } else {
1249+ NSLog (@" Unable to serialize the data %@ : %@ " , postData, error);
1250+ }
1251+
1252+ // Create the base64 encoded authentication
1253+ NSString *authenticationString = [NSString stringWithFormat: @" %@ :%@ " , self .userName.stringValue, self .password.stringValue];
1254+ NSData *authenticationData = [authenticationString dataUsingEncoding: NSASCIIStringEncoding];
1255+ NSString *b64AuthenticationString = [authenticationData base64EncodedStringWithOptions: 0 ];
1256+ NSString *totalAuthHeader = [@" Basic " stringByAppendingString: b64AuthenticationString];
1257+ // NSLog(@"Base64 Encoded Creds: %@", b64AuthenticationString);
1258+
1259+ // Complete the URL request and add-in headers
1260+ NSMutableURLRequest *URLRequest = [NSMutableURLRequest requestWithURL: airWatchURLComponents.URL];
1261+ [URLRequest addValue: self .awTenantCode.stringValue forHTTPHeaderField: @" aw-tenant-code" ];
1262+ [URLRequest addValue: @" application/json" forHTTPHeaderField: @" Content-Type" ];
1263+ [URLRequest addValue: totalAuthHeader forHTTPHeaderField: @" Authorization" ];
1264+ [URLRequest setHTTPBody: JSONPostData];
1265+ URLRequest.HTTPMethod = @" POST" ;
1266+
1267+ // Create the semaphore
1268+
1269+ dispatch_semaphore_t sema = dispatch_semaphore_create (0 );
1270+ // Run the query using the URL request and return the JSON
1271+ NSURLSession *session = [NSURLSession sharedSession ];
1272+ [[session dataTaskWithRequest: URLRequest completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
1273+
1274+ if (!data) return ;
1275+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
1276+ if ([httpResponse statusCode ] != 200 ) {
1277+ NSDictionary *returnedJSON = [NSJSONSerialization JSONObjectWithData: data options: 0 error: NULL ];
1278+ NSString *errorMessage;
1279+ if (!returnedJSON[@" Message" ]) {
1280+ errorMessage = @" Something went wrong." ;
1281+ } else {
1282+ errorMessage = returnedJSON[@" Message" ];
1283+ }
1284+ dispatch_async (dispatch_get_main_queue (), ^{
1285+ NSAlert *alert = [[NSAlert alloc ] init ];
1286+ [alert addButtonWithTitle: @" OK" ];
1287+ [alert setMessageText: @" Received a bad response from the server." ];
1288+ [alert setInformativeText: errorMessage];
1289+ [alert setAlertStyle: NSAlertStyleWarning];
1290+ [alert beginSheetModalForWindow: self .window completionHandler: ^(NSModalResponse returnCode) {
1291+ return ;
1292+ }];
1293+ });
1294+ return ;
1295+ }
1296+ dispatch_semaphore_signal (sema);
1297+
1298+ }] resume ];
1299+
1300+ if (dispatch_semaphore_wait (sema, dispatch_time (DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC))) {
1301+ NSLog (@" Timeout" );
1302+ }
12331303}
12341304
12351305- (IBAction )quit : (id )sender {
@@ -1240,6 +1310,6 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification {
12401310 // Insert code here to tear down your application
12411311}
12421312
1243- - (IBAction )installAppsTable : (id )sender {
1313+ - (IBAction )installAppsTableView : (id )sender {
12441314}
12451315@end
0 commit comments