11#import "BookmarkListController.h"
13#import "BookmarkEditorController.h"
14#import "RDPSessionViewController.h"
15#import "Toast+UIView.h"
16#import "Reachability.h"
17#import "GlobalDefaults.h"
19#define SECTION_SESSIONS 0
20#define SECTION_BOOKMARKS 1
23@interface BookmarkListController (Private)
24#pragma mark misc functions
25- (UIButton *)disclosureButtonWithImage:(UIImage *)image;
26- (void)performSearch:(NSString *)searchText;
27#pragma mark Persisting bookmarks
28- (void)scheduleWriteBookmarksToDataStore;
29- (void)writeBookmarksToDataStore;
30- (void)scheduleWriteManualBookmarksToDataStore;
31- (void)writeManualBookmarksToDataStore;
32- (void)readManualBookmarksFromDataStore;
33- (void)writeArray:(NSArray *)bookmarks toDataStoreURL:(NSURL *)url;
34- (NSMutableArray *)arrayFromDataStoreURL:(NSURL *)url;
35- (NSURL *)manualBookmarksDataStoreURL;
36- (NSURL *)connectionHistoryDataStoreURL;
41@synthesize searchBar = _searchBar, tableView = _tableView, bmTableCell = _bmTableCell,
42 sessTableCell = _sessTableCell;
46- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
48 if ((
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]))
51 [
self readManualBookmarksFromDataStore];
54 [
self readConnectionHistoryFromDataStore];
57 _manual_search_result = nil;
60 [[NSNotificationCenter defaultCenter] addObserver:self
61 selector:@selector(sessionDisconnected:)
62 name:TSXSessionDidDisconnectNotification
64 [[NSNotificationCenter defaultCenter] addObserver:self
65 selector:@selector(sessionFailedToConnect:)
66 name:TSXSessionDidFailToConnectNotification
70 [
self setTitle:NSLocalizedString(@"Connections",
71 @"'Connections': bookmark controller title")];
72 [
self setTabBarItem:[[[UITabBarItem alloc]
73 initWithTabBarSystemItem:UITabBarSystemItemBookmarks
77 _star_on_img = [[UIImage
78 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"icon_accessory_star_on"
79 ofType:@"png"]] retain];
81 [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
82 pathForResource:@"icon_accessory_star_off"
83 ofType:@"png"]] retain];
86 [[NSNotificationCenter defaultCenter] addObserver:self
87 selector:@selector(reachabilityChanged:)
88 name:kReachabilityChangedNotification
92 _active_sessions = [[NSMutableArray alloc] init];
93 _temporary_bookmark = nil;
109 [[
self navigationItem] setRightBarButtonItem:[
self editButtonItem]];
112- (void)viewWillAppear:(BOOL)animated
114 [
super viewWillAppear:animated];
117 if ([[_searchBar text] length] > 0)
118 [
self performSearch:[_searchBar text]];
121 [_tableView reloadData];
125- (void)viewSafeAreaInsetsDidChange
127 [
super viewSafeAreaInsetsDidChange];
128 [[
self view] setNeedsLayout];
131- (void)viewDidLayoutSubviews
133 [
super viewDidLayoutSubviews];
135 const CGRect bounds = [[
self view] bounds];
136 const UIEdgeInsets safe = [[
self view] safeAreaInsets];
137 const CGFloat x = safe.left;
138 const CGFloat w = bounds.size.width - safe.left - safe.right;
139 CGFloat searchH = CGRectGetHeight([_searchBar frame]);
141 [_searchBar setFrame:CGRectMake(x, safe.top, w, searchH)];
143 setFrame:CGRectMake(x, safe.top + searchH, w, bounds.size.height - safe.top - searchH)];
146- (void)viewWillDisappear:(BOOL)animated
148 [
super viewWillDisappear:animated];
151 [_searchBar setText:@""];
152 [_searchBar resignFirstResponder];
153 [
self performSearch:@""];
157- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
163- (void)didReceiveMemoryWarning
166 [
super didReceiveMemoryWarning];
173 [
super viewDidUnload];
180 [[NSNotificationCenter defaultCenter] removeObserver:self];
182 [_temporary_bookmark release];
183 [_connection_history release];
184 [_active_sessions release];
185 [_manual_search_result release];
186 [_manual_bookmarks release];
188 [_star_on_img release];
189 [_star_off_img release];
195#pragma mark Table view data source
197- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
203- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
208 case SECTION_SESSIONS:
212 case SECTION_BOOKMARKS:
215 if (_manual_search_result != nil)
216 return ([_manual_search_result count] + [_history_search_result count] + 1);
217 return ([_manual_bookmarks count] + 1);
227- (UITableViewCell *)cellForGenericListEntry
229 static NSString *CellIdentifier =
@"BookmarkListCell";
230 UITableViewCell *cell = [[
self tableView] dequeueReusableCellWithIdentifier:CellIdentifier];
233 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
234 reuseIdentifier:CellIdentifier];
235 [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
236 [cell setAccessoryView:[
self disclosureButtonWithImage:_star_off_img]];
244 static NSString *BookmarkCellIdentifier =
@"BookmarkCell";
246 dequeueReusableCellWithIdentifier:BookmarkCellIdentifier];
249 [[NSBundle mainBundle] loadNibNamed:@"BookmarkTableViewCell" owner:self options:nil];
250 [_bmTableCell setAccessoryView:[
self disclosureButtonWithImage:_star_on_img]];
259- (UITableViewCell *)tableView:(UITableView *)tableView
260 cellForRowAtIndexPath:(NSIndexPath *)indexPath
263 switch ([indexPath section])
265 case SECTION_SESSIONS:
268 static NSString *SessionCellIdentifier =
@"SessionCell";
270 dequeueReusableCellWithIdentifier:SessionCellIdentifier];
273 [[NSBundle mainBundle] loadNibNamed:@"SessionTableViewCell" owner:self options:nil];
274 cell = _sessTableCell;
275 _sessTableCell = nil;
279 RDPSession *session = [_active_sessions objectAtIndex:[indexPath row]];
280 [[cell title] setText:[session sessionName]];
281 [[cell server] setText:[[session params] StringForKey:@"hostname"]];
282 [[cell username] setText:[[session params] StringForKey:@"username"]];
284 setImage:[session getScreenshotWithSize:[[cell screenshot] bounds].size]];
285 [[cell disconnectButton] setTag:[indexPath row]];
289 case SECTION_BOOKMARKS:
292 if ([indexPath row] == 0)
296 UITableViewCell *cell = [
self cellForGenericListEntry];
297 if ([[_searchBar text] length] == 0)
300 setText:[@" " stringByAppendingString:
301 NSLocalizedString(@"Add Connection",
302 @"'Add Connection': button label")]];
303 [((UIButton *)[cell accessoryView]) setHidden:YES];
307 [[cell textLabel] setText:[@" " stringByAppendingString:[_searchBar text]]];
308 [((UIButton *)[cell accessoryView]) setHidden:NO];
316 if ([
self isIndexPathToHistoryItem:indexPath])
318 UITableViewCell *cell = [
self cellForGenericListEntry];
320 setText:[@" " stringByAppendingString:
321 [_history_search_result
323 [
self historyIndexFromIndexPath:indexPath]]]];
324 [((UIButton *)[cell accessoryView]) setHidden:NO];
332 if (_manual_search_result == nil)
333 entry = [_manual_bookmarks
334 objectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]];
336 entry = [[_manual_search_result
337 objectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]]
338 valueForKey:@"bookmark"];
340 [[cell title] setText:[entry label]];
341 [[cell subTitle] setText:[[entry params] StringForKey:@"hostname"]];
351 NSAssert(0,
@"Failed to create cell");
356- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
359 if ([indexPath section] == SECTION_SESSIONS)
361 if ([indexPath section] == SECTION_BOOKMARKS && [indexPath row] == 0)
367- (void)tableView:(UITableView *)tableView
368 commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
369 forRowAtIndexPath:(NSIndexPath *)indexPath
371 if (editingStyle == UITableViewCellEditingStyleDelete)
374 switch ([indexPath section])
376 case SECTION_BOOKMARKS:
378 if (_manual_search_result == nil)
380 removeObjectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]];
384 if ([
self isIndexPathToHistoryItem:indexPath])
388 [_history_search_result
389 objectAtIndex:[
self historyIndexFromIndexPath:indexPath]]];
390 [_history_search_result
391 removeObjectAtIndex:[
self historyIndexFromIndexPath:indexPath]];
397 [[_manual_search_result
398 objectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]]
399 valueForKey:@"bookmark"]];
400 [_manual_search_result
401 removeObjectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]];
404 [
self scheduleWriteManualBookmarksToDataStore];
409 [tableView reloadSections:[NSIndexSet indexSetWithIndex:[indexPath section]]
410 withRowAnimation:UITableViewRowAnimationNone];
415- (void)tableView:(UITableView *)tableView
416 moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
417 toIndexPath:(NSIndexPath *)toIndexPath
419 if ([fromIndexPath compare:toIndexPath] != NSOrderedSame)
421 switch ([fromIndexPath section])
423 case SECTION_BOOKMARKS:
425 NSInteger fromIdx = [
self bookmarkIndexFromIndexPath:fromIndexPath];
426 NSInteger toIdx = [
self bookmarkIndexFromIndexPath:toIndexPath];
428 [[_manual_bookmarks objectAtIndex:fromIdx] retain];
429 [_manual_bookmarks removeObjectAtIndex:fromIdx];
430 if (toIdx >= [_manual_bookmarks count])
431 [_manual_bookmarks addObject:temp_bookmark];
433 [_manual_bookmarks insertObject:temp_bookmark atIndex:toIdx];
434 [temp_bookmark release];
436 [
self scheduleWriteManualBookmarksToDataStore];
444- (NSIndexPath *)tableView:(UITableView *)tableView
445 targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
446 toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
452 if ([proposedDestinationIndexPath row] == 0 ||
453 ([sourceIndexPath section] != [proposedDestinationIndexPath section]) ||
454 _manual_search_result != nil)
456 return sourceIndexPath;
460 return proposedDestinationIndexPath;
465- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
468 if ([indexPath section] == SECTION_BOOKMARKS && [indexPath row] == 0)
473- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
475 if (section == SECTION_SESSIONS && [_active_sessions count] > 0)
476 return NSLocalizedString(
@"My Sessions",
@"'My Session': section sessions header");
477 if (section == SECTION_BOOKMARKS)
478 return NSLocalizedString(
@"Manual Connections",
479 @"'Manual Connections': section manual bookmarks header");
483- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
488- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
490 if ([indexPath section] == SECTION_SESSIONS)
492 return [tableView rowHeight];
496#pragma mark Table view delegate
498- (void)setEditing:(BOOL)editing animated:(BOOL)animated
500 [
super setEditing:editing animated:animated];
501 [[
self tableView] setEditing:editing animated:animated];
504- (void)accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event
507 NSIndexPath *indexPath =
508 [[
self tableView] indexPathForRowAtPoint:[[[event touchesForView:button] anyObject]
509 locationInView:[
self tableView]]];
510 if (indexPath == nil)
513 [[[
self tableView] delegate] tableView:[
self tableView]
514 accessoryButtonTappedForRowWithIndexPath:indexPath];
517- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
519 if ([indexPath section] == SECTION_SESSIONS)
522 RDPSession *session = [_active_sessions objectAtIndex:[indexPath row]];
523 UIViewController *ctrl =
526 session:session] autorelease];
527 [ctrl setHidesBottomBarWhenPushed:YES];
528 [[
self navigationController] pushViewController:ctrl animated:YES];
533 if ([indexPath section] == SECTION_BOOKMARKS)
536 if ([indexPath row] == 0)
538 if ([[_searchBar text] length] == 0)
545 [bookmarkEditorController
546 setTitle:NSLocalizedString(@"Add Connection", @"Add Connection title")];
547 [bookmarkEditorController setDelegate:self];
548 [bookmarkEditorController setHidesBottomBarWhenPushed:YES];
549 [[
self navigationController] pushViewController:bookmarkEditorController
556 bookmark = [
self bookmarkForQuickConnectTo:[_searchBar text]];
557 if (![_connection_history containsObject:[_searchBar text]])
559 [_connection_history addObject:[_searchBar text]];
560 [
self scheduleWriteConnectionHistoryToDataStore];
566 if (_manual_search_result != nil)
568 if ([
self isIndexPathToHistoryItem:indexPath])
571 NSString *item = [_history_search_result
572 objectAtIndex:[
self historyIndexFromIndexPath:indexPath]];
573 bookmark = [
self bookmarkForQuickConnectTo:item];
576 bookmark = [[_manual_search_result
577 objectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]]
578 valueForKey:@"bookmark"];
581 bookmark = [_manual_bookmarks
582 objectAtIndex:[
self bookmarkIndexFromIndexPath:
589 reachabilityWithHostName:[[bookmark params]
590 StringForKey:@"hostname"]]
591 currentReachabilityStatus] == ReachableViaWiFi];
598 UIViewController *ctrl =
601 session:session] autorelease];
602 [ctrl setHidesBottomBarWhenPushed:YES];
603 [[
self navigationController] pushViewController:ctrl animated:YES];
604 [_active_sessions addObject:session];
609- (void)tableView:(UITableView *)tableView
610 accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
613 NSString *bookmark_editor_title =
614 NSLocalizedString(
@"Edit Connection",
@"Edit Connection title");
616 if ([indexPath section] == SECTION_BOOKMARKS)
618 if ([indexPath row] == 0)
621 bookmark = [
self bookmarkForQuickConnectTo:[_searchBar text]];
622 bookmark_editor_title = NSLocalizedString(
@"Add Connection",
@"Add Connection title");
626 if (_manual_search_result != nil)
628 if ([
self isIndexPathToHistoryItem:indexPath])
631 NSString *item = [_history_search_result
632 objectAtIndex:[
self historyIndexFromIndexPath:indexPath]];
633 bookmark = [
self bookmarkForQuickConnectTo:item];
634 bookmark_editor_title =
635 NSLocalizedString(
@"Add Connection",
@"Add Connection title");
638 bookmark = [[_manual_search_result
639 objectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]]
640 valueForKey:@"bookmark"];
643 bookmark = [_manual_bookmarks
644 objectAtIndex:[
self bookmarkIndexFromIndexPath:indexPath]];
654 [editBookmarkController setHidesBottomBarWhenPushed:YES];
655 [editBookmarkController setTitle:bookmark_editor_title];
656 [editBookmarkController setDelegate:self];
657 [[
self navigationController] pushViewController:editBookmarkController animated:YES];
662#pragma mark Search Bar Delegates
664- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
667 [searchBar setShowsCancelButton:YES animated:YES];
671- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
674 [_manual_search_result release];
675 _manual_search_result = nil;
678 [searchBar setText:@""];
679 [searchBar resignFirstResponder];
682- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
684 [searchBar setShowsCancelButton:NO animated:YES];
687 [_tableView setAllowsSelection:YES];
692- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
694 [_searchBar resignFirstResponder];
697- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
699 [
self performSearch:searchText];
700 [_tableView reloadData];
703#pragma mark - Session handling
706- (void)sessionDisconnected:(NSNotification *)notification
710 [_active_sessions removeObject:session];
713 if ([[
self navigationController] visibleViewController] ==
self)
714 [_tableView reloadSections:[NSIndexSet indexSetWithIndex:SECTION_SESSIONS]
715 withRowAnimation:UITableViewRowAnimationNone];
719 if (![_manual_bookmarks containsObject:[session bookmark]])
722 _temporary_bookmark = [[session bookmark] retain];
726 NSLocalizedString(
@"Save Connection Settings?",
@"Save connection settings title");
727 NSString *message = NSLocalizedString(
728 @"Your Connection Settings have not been saved. Do you want to save them?",
729 @"Save connection settings message");
730 UIAlertController *alert =
731 [UIAlertController alertControllerWithTitle:title
733 preferredStyle:UIAlertControllerStyleAlert];
734 [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"No", @"No Button")
735 style:UIAlertActionStyleCancel
737 [alert addAction:[UIAlertAction
738 actionWithTitle:NSLocalizedString(@"Yes", @"Yes Button")
739 style:UIAlertActionStyleDefault
740 handler:^(UIAlertAction *action) {
741 if (_temporary_bookmark)
743 [_manual_bookmarks addObject:_temporary_bookmark];
745 reloadSections:[NSIndexSet indexSetWithIndex:
747 withRowAnimation:UITableViewRowAnimationNone];
748 [_temporary_bookmark autorelease];
749 _temporary_bookmark = nil;
752 [
self presentViewController:alert animated:YES completion:nil];
756- (void)sessionFailedToConnect:(NSNotification *)notification
760 [_active_sessions removeObject:session];
763 [[
self view] makeToast:NSLocalizedString(@"Failed to connect to session!",
764 @"Failed to connect error message")
765 duration:ToastDurationNormal
769#pragma mark - Reachability notification
770- (void)reachabilityChanged:(NSNotification *)notification
774 if ([_active_sessions count] > 0)
776 RDPSession *session = [_active_sessions objectAtIndex:0];
777 [session disconnect];
781#pragma mark - BookmarkEditorController delegate
787 for (
int idx = 0; idx < [_manual_bookmarks count]; ++idx)
789 if ([[bookmark uuid] isEqualToString:[[_manual_bookmarks objectAtIndex:idx] uuid]])
791 [_manual_bookmarks replaceObjectAtIndex:idx withObject:bookmark];
797 [_manual_bookmarks addObject:bookmark];
800 NSString *hostname = [[bookmark params] StringForKey:@"hostname"];
801 if ([_connection_history containsObject:hostname])
803 [_connection_history removeObject:hostname];
804 [
self scheduleWriteConnectionHistoryToDataStore];
807 [
self scheduleWriteManualBookmarksToDataStore];
810- (IBAction)disconnectButtonPressed:(
id)sender
813 RDPSession *session = [_active_sessions objectAtIndex:[sender tag]];
814 [session disconnect];
817#pragma mark - Misc functions
819- (BOOL)hasNoBookmarks
821 return ([_manual_bookmarks count] == 0);
824- (UIButton *)disclosureButtonWithImage:(UIImage *)image
828 UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
829 [button setFrame:CGRectMake(0, 0, [image size].width * 2, [image size].height + 10)];
830 [button setImage:image forState:UIControlStateNormal];
831 [button addTarget:self
832 action:@selector(accessoryButtonTapped:withEvent:)
833 forControlEvents:UIControlEventTouchUpInside];
834 [button setUserInteractionEnabled:YES];
838- (void)performSearch:(NSString *)searchText
840 [_manual_search_result autorelease];
842 if ([searchText length] > 0)
844 _manual_search_result = [FilterBookmarks(
846 [searchText componentsSeparatedByCharactersInSet:[NSCharacterSet
847 whitespaceAndNewlineCharacterSet]])
849 _history_search_result = [FilterHistory(_connection_history, searchText) retain];
853 _history_search_result = nil;
854 _manual_search_result = nil;
858- (NSInteger)bookmarkIndexFromIndexPath:(NSIndexPath *)indexPath
860 return [indexPath row] -
861 ((_history_search_result != nil) ? [_history_search_result count] : 0) - 1;
864- (NSInteger)historyIndexFromIndexPath:(NSIndexPath *)indexPath
866 return [indexPath row] - 1;
869- (BOOL)isIndexPathToHistoryItem:(NSIndexPath *)indexPath
871 return (([indexPath row] - 1) < [_history_search_result count]);
878 [bookmark setLabel:host];
879 [[bookmark params] setValue:host forKey:@"hostname"];
883#pragma mark - Persisting bookmarks
885- (void)scheduleWriteBookmarksToDataStore
887 [[NSOperationQueue mainQueue] addOperationWithBlock:^{
888 [
self writeBookmarksToDataStore];
892- (void)writeBookmarksToDataStore
894 [
self writeManualBookmarksToDataStore];
897- (void)scheduleWriteManualBookmarksToDataStore
899 [[NSOperationQueue mainQueue]
900 addOperation:[[[NSInvocationOperation alloc]
902 selector:@selector(writeManualBookmarksToDataStore)
903 object:nil] autorelease]];
906- (void)writeManualBookmarksToDataStore
908 [
self writeArray:_manual_bookmarks toDataStoreURL:[
self manualBookmarksDataStoreURL]];
911- (void)scheduleWriteConnectionHistoryToDataStore
913 [[NSOperationQueue mainQueue]
914 addOperation:[[[NSInvocationOperation alloc]
916 selector:@selector(writeConnectionHistoryToDataStore)
917 object:nil] autorelease]];
920- (void)writeConnectionHistoryToDataStore
922 [
self writeArray:_connection_history toDataStoreURL:[
self connectionHistoryDataStoreURL]];
925- (void)writeArray:(NSArray *)bookmarks toDataStoreURL:(NSURL *)url
927 NSError *error = nil;
928 NSData *archived_data = [NSKeyedArchiver archivedDataWithRootObject:bookmarks
929 requiringSecureCoding:YES
935 NSLog(
@"%s: failed to archive %@: %@", __func__, [url lastPathComponent], error);
939 [archived_data writeToURL:url atomically:YES];
942- (void)readManualBookmarksFromDataStore
944 [_manual_bookmarks autorelease];
945 _manual_bookmarks = [
self arrayFromDataStoreURL:[
self manualBookmarksDataStoreURL]];
947 if (_manual_bookmarks == nil)
949 _manual_bookmarks = [[NSMutableArray alloc] init];
953- (void)readConnectionHistoryFromDataStore
955 [_connection_history autorelease];
956 _connection_history = [
self arrayFromDataStoreURL:[
self connectionHistoryDataStoreURL]];
958 if (_connection_history == nil)
959 _connection_history = [[NSMutableArray alloc] init];
962- (NSMutableArray *)arrayFromDataStoreURL:(NSURL *)url
964 NSData *archived_data = [NSData dataWithContentsOfURL:url];
970 NSSet *classes = [NSSet setWithObjects:[NSArray class], [
ComputerBookmark class],
972 [NSString class], [NSNumber class], [NSData class], nil];
973 NSError *error = nil;
974 NSArray *decoded = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes
975 fromData:archived_data
980 NSLog(
@"%s: failed to unarchive %@: %@", __func__, [url lastPathComponent], error);
985 return [[NSMutableArray alloc] initWithArray:decoded];
988- (NSURL *)manualBookmarksDataStoreURL
991 fileURLWithPath:[NSString stringWithFormat:@"%@/%@",
992 [NSSearchPathForDirectoriesInDomains(
993 NSDocumentDirectory, NSUserDomainMask, YES)
995 @"com.freerdp.ifreerdp.bookmarks.plist"]];
998- (NSURL *)connectionHistoryDataStoreURL
1001 fileURLWithPath:[NSString
1002 stringWithFormat:@"%@/%@",
1003 [NSSearchPathForDirectoriesInDomains(
1004 NSDocumentDirectory, NSUserDomainMask, YES)
1006 @"com.freerdp.ifreerdp.connection_history.plist"]];