iOS web browser with a focus on security and privacy
at master 175 lines 5.3 kB view raw
1/* 2 * Endless 3 * Copyright (c) 2015 joshua stein <jcs@jcs.org> 4 * 5 * See LICENSE file for redistribution terms. 6 */ 7 8#import "AppDelegate.h" 9#import "Bookmark.h" 10 11@implementation Bookmark 12 13static AppDelegate *appDelegate; 14static NSMutableArray *_list; 15 16NSString * const BOOKMARK_KEY_NAME = @"name"; 17NSString * const BOOKMARK_KEY_URL = @"url"; 18 19NSString * const BOOKMARK_KEY_VERSION = @"version"; 20NSString * const BOOKMARK_KEY_LIST = @"bookmarks"; 21 22const int BOOKMARK_FILE_VERSION = 1; 23 24+ (NSString *)bookmarksPath 25{ 26 NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 27 return [path stringByAppendingPathComponent:@"bookmarks.plist"]; 28} 29 30+ (void)retrieveList 31{ 32 appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 33 _list = nil; 34 35 NSFileManager *fileManager = [NSFileManager defaultManager]; 36 if ([fileManager fileExistsAtPath:[self bookmarksPath]]) { 37 NSDictionary *bookmarks = [[NSDictionary alloc] initWithContentsOfFile:[self bookmarksPath]]; 38 39 NSNumber *v = [bookmarks objectForKey:BOOKMARK_KEY_VERSION]; 40 if (v != nil) { 41 if ([v intValue] != BOOKMARK_FILE_VERSION) 42 NSLog(@"need to handle bookmark list migration from version %d to %d", [v intValue], BOOKMARK_FILE_VERSION); 43 44 NSArray *tlist = [bookmarks objectForKey:BOOKMARK_KEY_LIST]; 45 _list = [[NSMutableArray alloc] initWithCapacity:MIN(tlist.count, 5)]; 46 for (int i = 0; i < [tlist count]; i++) 47 [_list addObject:[self unmarshall:tlist[i]]]; 48 } 49 } 50 51 if (_list == nil) 52 _list = [[NSMutableArray alloc] initWithCapacity:5]; 53} 54 55+ (NSMutableArray *)list 56{ 57 return _list; 58} 59 60+ (void)persistList 61{ 62 NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; 63 64 NSMutableArray *t = [[NSMutableArray alloc] initWithCapacity:[_list count]]; 65 for (int i = 0; i < [_list count]; i++) 66 [t addObject:((Bookmark *)_list[i]).marshallable]; 67 68 [d setObject:t forKey:BOOKMARK_KEY_LIST]; 69 [d setObject:[NSNumber numberWithInt:BOOKMARK_FILE_VERSION] forKey:BOOKMARK_KEY_VERSION]; 70 71 if ([d writeToFile:[self bookmarksPath] atomically:YES] == false) 72 NSLog(@"failed writing bookmarks to %@", [self bookmarksPath]); 73} 74 75+ (Bookmark *)unmarshall:(NSDictionary *)marshalled 76{ 77 Bookmark *b = [[Bookmark alloc] init]; 78 b.name = [marshalled objectForKey:BOOKMARK_KEY_NAME]; 79 b.url = [NSURL URLWithString:[marshalled objectForKey:BOOKMARK_KEY_URL]]; 80 return b; 81} 82 83+ (void)addBookmarkForURLString:(NSString *)urls withName:(NSString *)name; 84{ 85 Bookmark *b = [[Bookmark alloc] init]; 86 87 NSURL *furl = [NSURL URLWithString:urls]; 88 if (![furl scheme] || [[furl scheme] isEqualToString:@""]) 89 furl = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@", urls]]; 90 91 if (![furl path] || [[furl path] isEqualToString:@""]) 92 furl = [NSURL URLWithString:[NSString stringWithFormat:@"%@/", [furl absoluteString]]]; 93 94 b.url = furl; 95 96 if (name && ![name isEqualToString:@""]) 97 b.name = name; 98 else 99 b.name = [NSString stringWithFormat:@"%@%@", [furl host], [[furl path] isEqualToString:@"/"] ? @"" : [furl path]]; 100 101 [[self list] addObject:b]; 102 [self persistList]; 103} 104 105+ (BOOL)isURLBookmarked:(NSURL *)url 106{ 107 for (int i = 0; i < [[Bookmark list] count]; i++) { 108 Bookmark *b = [Bookmark list][i]; 109 110 if ([[[[b url] absoluteString] lowercaseString] isEqualToString:[[url absoluteString] lowercaseString]]) 111 return YES; 112 } 113 114 return NO; 115} 116 117+ (UIAlertController *)addBookmarkDialogWithOkCallback:(void (^)(void))callback 118{ 119 WebViewTab *wvt = [[appDelegate webViewController] curWebViewTab]; 120 121 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Add Bookmark", nil) message:NSLocalizedString(@"Enter the details of the URL to bookmark:", nil) preferredStyle:UIAlertControllerStyleAlert]; 122 [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 123 textField.placeholder = NSLocalizedString(@"URL", nil); 124 125 if (wvt && [wvt url]) 126 textField.text = [[wvt url] absoluteString]; 127 }]; 128 [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { 129 textField.placeholder = NSLocalizedString(@"Page Name (leave blank to use URL)", nil); 130 131 if (wvt && [wvt url]) 132 textField.text = [[wvt title] text]; 133 }]; 134 135 UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK action") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 136 UITextField *url = alertController.textFields[0]; 137 UITextField *name = alertController.textFields[1]; 138 139 if (url && ![[url text] isEqualToString:@""]) { 140 [Bookmark addBookmarkForURLString:[url text] withName:[name text]]; 141 142 if (callback != nil) 143 callback(); 144 } 145 }]; 146 147 UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel action") style:UIAlertActionStyleCancel handler:nil]; 148 [alertController addAction:cancelAction]; 149 [alertController addAction:okAction]; 150 151 return alertController; 152} 153 154 155- (NSDictionary *)marshallable 156{ 157 /* can only have basic things like NSArray, NSString, etc. or writing will fail */ 158 159 return @{ 160 BOOKMARK_KEY_NAME: self.name, 161 BOOKMARK_KEY_URL: self.url.absoluteString, 162 }; 163} 164 165- (NSString *)urlString 166{ 167 return [self.url absoluteString]; 168} 169 170- (void)setUrlString:(NSString *)urls 171{ 172 self.url = [NSURL URLWithString:urls]; 173} 174 175@end