DELETED iOS/AboutController.h Index: iOS/AboutController.h ================================================================== --- iOS/AboutController.h +++ iOS/AboutController.h @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import UIKit; - -@interface AboutController: UIViewController -@property (nonatomic, retain) IBOutlet UIWebView *webView; -@end DELETED iOS/AboutController.m Index: iOS/AboutController.m ================================================================== --- iOS/AboutController.m +++ iOS/AboutController.m @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#import "AboutController.h" - -static NSString *aboutHTMLTemplate = - @"" - @"" - @"" - @"" - @"" - @"
" - @" scrypt-pwgen {version}" - @"
" - @"" - @"

" - @" scrypt-pwgen is free software and the source code is available at " - @" here." - @"

" - @"

" - @" It makes use of the ObjFW " - @"framework and also uses its scrypt implementation." - @"

" - @"" - @""; - -@implementation AboutController -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.automaticallyAdjustsScrollViewInsets = NO; - - NSDictionary *infoDictionary = NSBundle.mainBundle.infoDictionary; - NSString *version = infoDictionary[@"CFBundleShortVersionString"]; - NSString *aboutHTML = [aboutHTMLTemplate - stringByReplacingOccurrencesOfString: @"{version}" - withString: version]; - [self.webView loadHTMLString: aboutHTML - baseURL: nil]; -} - -- (void)dealloc -{ - [_webView release]; - - [super dealloc]; -} - -- (BOOL)webView: (UIWebView *)webView - shouldStartLoadWithRequest: (NSURLRequest *)request - navigationType: (UIWebViewNavigationType)navigationType -{ - if (navigationType == UIWebViewNavigationTypeLinkClicked) { - [UIApplication.sharedApplication openURL: request.URL - options: @{} - completionHandler: ^ (BOOL success) { - }]; - return NO; - } - - return YES; -} -@end ADDED iOS/AboutController.swift Index: iOS/AboutController.swift ================================================================== --- iOS/AboutController.swift +++ iOS/AboutController.swift @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class AboutController: UIViewController, UIWebViewDelegate { + @IBOutlet var webView: UIWebView? + + override func viewDidLoad() { + super.viewDidLoad() + + self.automaticallyAdjustsScrollViewInsets = false + + let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] + webView?.loadHTMLString( + "" + + "" + + "" + + "" + + "" + + "
" + + " scrypt-pwgen \(version ?? "")" + + "
" + + "" + + "

" + + " scrypt-pwgen is free software and the source code is available" + + " at here." + + "

" + + "

" + + " It makes use of the" + + " ObjFW framework and" + + " also uses its scrypt implementation." + + "

" + + "" + + "", baseURL: nil) + } + + func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, + navigationType: UIWebView.NavigationType) -> Bool { + if #available(iOS 10.0, *), + navigationType == UIWebView.NavigationType.linkClicked, + let url = request.url { + UIApplication.shared.open(url) + return false + } + + return true + } +} DELETED iOS/AddSiteController.h Index: iOS/AddSiteController.h ================================================================== --- iOS/AddSiteController.h +++ iOS/AddSiteController.h @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import UIKit; - -#import "MainViewController.h" - -@interface AddSiteController: UITableViewController -@property (nonatomic, retain) IBOutlet UITextField *nameField; -@property (nonatomic, retain) IBOutlet UITextField *lengthField; -@property (nonatomic, retain) IBOutlet UISwitch *legacySwitch; -@property (nonatomic, copy) NSString *keyFile; -@property (nonatomic, retain) IBOutlet UILabel *keyFileLabel; -@property (retain) MainViewController *mainViewController; - -- (IBAction)done: (id)sender; -- (IBAction)cancel: (id)sender; -@end DELETED iOS/AddSiteController.m Index: iOS/AddSiteController.m ================================================================== --- iOS/AddSiteController.m +++ iOS/AddSiteController.m @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW_Bridge; - -#import "AddSiteController.h" -#import "SelectKeyFileController.h" - -static void -showAlert(UIViewController *controller, NSString *title, NSString *message) -{ - UIAlertController *alert = [UIAlertController - alertControllerWithTitle: title - message: message - preferredStyle: UIAlertControllerStyleAlert]; - [alert addAction: - [UIAlertAction actionWithTitle: @"OK" - style: UIAlertActionStyleDefault - handler: nil]]; - - [controller presentViewController: alert - animated: YES - completion: nil]; -} - -@implementation AddSiteController -- (void)dealloc -{ - [_nameField release]; - [_lengthField release]; - [_legacySwitch release]; - [_keyFile release]; - [_keyFileLabel release]; - [_mainViewController release]; - - [super dealloc]; -} - -- (void)tableView: (UITableView *)tableView - didSelectRowAtIndexPath: (NSIndexPath *)indexPath -{ - [tableView deselectRowAtIndexPath: indexPath - animated: YES]; - - if (indexPath.section == 1 && indexPath.row == 1) - [self performSegueWithIdentifier: @"selectKeyFile" - sender: self]; -} - -- (NSIndexPath *)tableView: (UITableView *)tableView - willSelectRowAtIndexPath: (NSIndexPath *)indexPath -{ - if (indexPath.section == 1 && indexPath.row == 1) - return indexPath; - - return nil; -} - -- (IBAction)done: (id)sender -{ - OFString *name = self.nameField.text.OFObject; - OFString *lengthString = self.lengthField.text.OFObject; - bool lengthValid = true; - size_t length; - - if (name.length == 0) { - showAlert(self, @"Name missing", @"Please enter a name."); - return; - } - - @try { - length = (size_t)lengthString.decimalValue; - - if (length < 3 || length > 64) - lengthValid = false; - } @catch (OFInvalidFormatException *e) { - lengthValid = false; - } - - if (!lengthValid) { - showAlert(self, @"Invalid length", - @"Please enter a number between 3 and 64."); - return; - } - - if ([self.mainViewController.siteStorage hasSite: name]) { - showAlert(self, @"Site Already Exists", - @"Please pick a name that does not exist yet."); - return; - } - - [self.mainViewController.siteStorage setSite: name - length: length - legacy: self.legacySwitch.on - keyFile: self.keyFile.OFObject]; - [self.mainViewController reset]; - - [self.navigationController popViewControllerAnimated: YES]; -} - -- (IBAction)cancel: (id)sender -{ - [self.navigationController popViewControllerAnimated: YES]; -} - -- (void)prepareForSegue: (UIStoryboardSegue *)segue - sender: (id)sender -{ - if ([segue.identifier isEqual: @"selectKeyFile"]) - [segue.destinationViewController setAddSiteController: self]; -} -@end ADDED iOS/AddSiteController.swift Index: iOS/AddSiteController.swift ================================================================== --- iOS/AddSiteController.swift +++ iOS/AddSiteController.swift @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit +import ObjFW +import ObjFW_Bridge + +class AddSiteController: UITableViewController { + @IBOutlet var nameField: UITextField? + @IBOutlet var lengthField: UITextField? + @IBOutlet var legacySwitch: UISwitch? + public var keyFile: String? + @IBOutlet var keyFileLabel: UILabel? + public var mainViewController: MainViewController? + + override func tableView(_ tableView: UITableView, + didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + if indexPath.section == 1 && indexPath.row == 1 { + self.performSegue(withIdentifier: "selectKeyFile", sender: self) + } + } + + override func tableView( + _ tableView: UITableView, + willSelectRowAt indexPath: IndexPath + ) -> IndexPath? { + if indexPath.section == 1 && indexPath.row == 1 { + return indexPath + } + + return nil + } + + private func showAlert(controller: UIViewController, title: String, + message: String) { + let alert = UIAlertController(title: title, message: message, + preferredStyle: .alert) + alert.addAction( + UIAlertAction(title: "OK", style: .default, handler: nil)) + controller.present(alert, animated: true, completion: nil) + } + + @IBAction func done(_ sender: Any) { + guard let name = nameField?.text?.ofObject else { return } + guard let lengthString = lengthField?.text?.ofObject else { return } + + guard name.length > 0 else { + showAlert(controller: self, title: "Name missing", + message: "Please enter a name.") + return + } + + var lengthValid = true + var length: size_t = 0 + OFException.try({ + length = lengthString.decimalValue + + if length < 3 || length > 64 { + lengthValid = false + } + }, catch: { (OFException) in + lengthValid = false + }) + + guard lengthValid else { + showAlert(controller: self, title: "Invalid length", + message: "Please enter a number between 3 and 64.") + return + } + + guard let siteStorage = mainViewController?.siteStorage else { return } + + guard !siteStorage.hasSite(name) else { + showAlert(controller: self, title: "Site Already Exists", + message: "Please pick a name that does not exist yet.") + return + } + + let keyFile = self.keyFile?.ofObject + siteStorage.setSite(name, length: length, + legacy: legacySwitch?.isOn ?? false, + keyFile: keyFile) + mainViewController?.reset() + navigationController?.popViewController(animated: true) + } + + @IBAction func cancel(_ sender: Any) { + navigationController?.popViewController(animated: true) + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "selectKeyFile" { + let controller = segue.destination as? SelectKeyFileController + controller?.addSiteController = self + } + } +} DELETED iOS/AppDelegate.h Index: iOS/AppDelegate.h ================================================================== --- iOS/AppDelegate.h +++ iOS/AppDelegate.h @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import UIKit; - -@interface AppDelegate: UIResponder -@property (nonatomic, strong) UIWindow *window; -@end DELETED iOS/AppDelegate.m Index: iOS/AppDelegate.m ================================================================== --- iOS/AppDelegate.m +++ iOS/AppDelegate.m @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#import "AppDelegate.h" - -@implementation AppDelegate -- (void)dealloc -{ - [_window release]; - - [super dealloc]; -} -@end ADDED iOS/AppDelegate.swift Index: iOS/AppDelegate.swift ================================================================== --- iOS/AppDelegate.swift +++ iOS/AppDelegate.swift @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +@objc class AppDelegate: UIResponder, UIApplicationDelegate { + public var window: UIWindow? +} Index: iOS/Base.lproj/Main.storyboard ================================================================== --- iOS/Base.lproj/Main.storyboard +++ iOS/Base.lproj/Main.storyboard @@ -1,14 +1,13 @@ - + - - + @@ -30,11 +29,11 @@ - + @@ -91,11 +90,11 @@ - + @@ -128,11 +127,11 @@ - + @@ -240,11 +239,11 @@ - + @@ -342,11 +341,11 @@ - + DELETED iOS/HTTPServerDelegate.h Index: iOS/HTTPServerDelegate.h ================================================================== --- iOS/HTTPServerDelegate.h +++ iOS/HTTPServerDelegate.h @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW; - -@interface HTTPServerDelegate: OFObject -@end DELETED iOS/HTTPServerDelegate.m Index: iOS/HTTPServerDelegate.m ================================================================== --- iOS/HTTPServerDelegate.m +++ iOS/HTTPServerDelegate.m @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#import "HTTPServerDelegate.h" - -@implementation HTTPServerDelegate -- (void)server: (OFHTTPServer *)server - didReceiveRequest: (OFHTTPRequest *)request - response: (OFHTTPResponse *)response -{ - of_log(@"%@", request); -} -@end ADDED iOS/HTTPServerDelegate.swift Index: iOS/HTTPServerDelegate.swift ================================================================== --- iOS/HTTPServerDelegate.swift +++ iOS/HTTPServerDelegate.swift @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import ObjFW + +class HTTPServerDelegate: OFObject, OFHTTPServerDelegate { + func server(_ server: OFHTTPServer, didReceive request: OFHTTPRequest, + requestBody: OFStream?, response: OFHTTPResponse) { + print("\(request)") + } +} DELETED iOS/MainViewController.h Index: iOS/MainViewController.h ================================================================== --- iOS/MainViewController.h +++ iOS/MainViewController.h @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import UIKit; - -#import "SiteStorage.h" - -@interface MainViewController: UIViewController -@property (retain) OFArray *sites; -@property (retain) SiteStorage *siteStorage; -@property (nonatomic, retain) IBOutlet UISearchBar *searchBar; -@property (nonatomic, retain) IBOutlet UITableView *tableView; - -- (void)reset; -@end DELETED iOS/MainViewController.m Index: iOS/MainViewController.m ================================================================== --- iOS/MainViewController.m +++ iOS/MainViewController.m @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW_Bridge; - -#import "MainViewController.h" - -#import "AddSiteController.h" -#import "ShowDetailsController.h" - -@implementation MainViewController -- (void)viewDidLoad -{ - [super viewDidLoad]; - - _siteStorage = [[SiteStorage alloc] init]; - [self reset]; -} - -- (void)dealloc -{ - [_sites release]; - [_siteStorage release]; - [_searchBar release]; - [_tableView release]; - - [super dealloc]; -} - -- (void)reset -{ - void *pool = objc_autoreleasePoolPush(); - - _searchBar.text = @""; - self.sites = [_siteStorage sitesWithFilter: nil]; - [_tableView reloadData]; - - objc_autoreleasePoolPop(pool); -} - -- (NSInteger)tableView: (UITableView *)tableView - numberOfRowsInSection: (NSInteger)section -{ - return self.sites.count; -} - -- (UITableViewCell *)tableView: (UITableView *)tableView - cellForRowAtIndexPath: (NSIndexPath *)indexPath -{ - UITableViewCell *cell = [tableView - dequeueReusableCellWithIdentifier: @"site"]; - - if (cell == nil) - cell = [[[UITableViewCell alloc] - initWithStyle: UITableViewCellStyleDefault - reuseIdentifier: @"site"] autorelease]; - - cell.textLabel.text = self.sites[indexPath.row].NSObject; - - return cell; -} - -- (void)searchBar: (UISearchBar *)searchBar - textDidChange: (NSString *)searchText -{ - self.sites = [_siteStorage sitesWithFilter: _searchBar.text.OFObject]; - [_tableView reloadData]; -} - -- (void)tableView: (UITableView *)tableView - didSelectRowAtIndexPath: (NSIndexPath *)indexPath -{ - [self performSegueWithIdentifier: @"showDetails" - sender: self]; -} - -- (void)prepareForSegue: (UIStoryboardSegue *)segue - sender: (id)sender -{ - if ([segue.identifier isEqual: @"addSite"] || - [segue.identifier isEqual: @"showDetails"]) - [segue.destinationViewController setMainViewController: self]; -} -@end ADDED iOS/MainViewController.swift Index: iOS/MainViewController.swift ================================================================== --- iOS/MainViewController.swift +++ iOS/MainViewController.swift @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit +import ObjFW + +class MainViewController: UIViewController, UISearchBarDelegate, + UITableViewDelegate, UITableViewDataSource { + public var sites = OFArray() + public var siteStorage = SiteStorage() + @IBOutlet var searchBar: UISearchBar? + @IBOutlet var tableView: UITableView? + + override func viewDidLoad() { + super.viewDidLoad() + + self.reset() + } + + func reset() { + searchBar?.text = "" + sites = siteStorage.sites(withFilter: nil) + tableView?.reloadData() + } + + func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + return sites.count + } + + func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "site") ?? + UITableViewCell(style: .default, reuseIdentifier: "site") + cell.textLabel?.text = sites[indexPath.row].nsObject + return cell + } + + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + sites = siteStorage.sites(withFilter: searchBar.text?.ofObject) + tableView?.reloadData() + } + + func tableView(_ tableView: UITableView, + didSelectRowAt indexPath: IndexPath) { + self.performSegue(withIdentifier: "showDetails", sender: self) + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + switch segue.identifier { + case .some("addSite"): + let destination = segue.destination as? AddSiteController + destination?.mainViewController = self + case .some("showDetails"): + let destination = segue.destination as? ShowDetailsController + destination?.mainViewController = self + default: + break + } + } +} DELETED iOS/SelectKeyFileController.h Index: iOS/SelectKeyFileController.h ================================================================== --- iOS/SelectKeyFileController.h +++ iOS/SelectKeyFileController.h @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW; -@import UIKit; - -#import "AddSiteController.h" -#import "HTTPServerDelegate.h" - -@interface SelectKeyFileController: UITableViewController -{ - NSArray *_keyFiles; - OFHTTPServer *_HTTPServer; - HTTPServerDelegate *_HTTPServerDelegate; - OFThread *_HTTPServerThread; -} - -@property (retain) AddSiteController *addSiteController; - -- (IBAction)upload: (id)sender; -@end DELETED iOS/SelectKeyFileController.m Index: iOS/SelectKeyFileController.m ================================================================== --- iOS/SelectKeyFileController.m +++ iOS/SelectKeyFileController.m @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW_Bridge; - -#import "HTTPServerDelegate.h" -#import "SelectKeyFileController.h" - -@implementation SelectKeyFileController -- (void)viewDidLoad -{ - NSString *documentDirectory; - NSArray *keyFiles; - NSError *error; - - [super viewDidLoad]; - - if ((documentDirectory = NSSearchPathForDirectoriesInDomains( - NSDocumentDirectory, NSUserDomainMask, YES).firstObject) == nil) { - NSLog(@"Could not get key files: No documents directory"); - [self.navigationController popViewControllerAnimated: YES]; - return; - } - - keyFiles = [NSFileManager.defaultManager - contentsOfDirectoryAtPath: documentDirectory - error: &error]; - - if (keyFiles == nil) { - NSLog(@"Could not get key files: %@", error); - [self.navigationController popViewControllerAnimated: YES]; - return; - } - - _keyFiles = [[keyFiles sortedArrayUsingSelector: - @selector(compare:)] retain]; - - _HTTPServer = [[OFHTTPServer alloc] init]; - @autoreleasepool { - _HTTPServer.host = @"127.0.0.1".OFObject; - } - - _HTTPServerDelegate = [[HTTPServerDelegate alloc] init]; - _HTTPServer.delegate = _HTTPServerDelegate; - - _HTTPServerThread = [[OFThread alloc] init]; - [_HTTPServerThread start]; -} - -- (void)dealloc -{ - [_keyFiles release]; - - [_HTTPServerThread.runLoop stop]; - [_HTTPServerThread join]; - [_HTTPServerThread release]; - - [_HTTPServer release]; - - [_HTTPServerDelegate release]; - - [super dealloc]; -} - -- (NSInteger)tableView: (UITableView *)tableView - numberOfRowsInSection: (NSInteger)section -{ - return _keyFiles.count + 1; -} - -- (UITableViewCell *)tableView: (UITableView *)tableView - cellForRowAtIndexPath: (NSIndexPath *)indexPath -{ - UITableViewCell *cell = [tableView - dequeueReusableCellWithIdentifier: @"keyFile"]; - - if (cell == nil) - cell = [[[UITableViewCell alloc] - initWithStyle: UITableViewCellStyleDefault - reuseIdentifier: @"keyFile"] autorelease]; - - cell.textLabel.text = - (indexPath.row > 0 ? _keyFiles[indexPath.row - 1] : @"None"); - - return cell; -} - -- (void)tableView: (UITableView *)tableView - didSelectRowAtIndexPath: (NSIndexPath *)indexPath -{ - self.addSiteController.keyFile = - (indexPath.row > 0 ? _keyFiles[indexPath.row - 1] : nil); - self.addSiteController.keyFileLabel.text = - (indexPath.row > 0 ? _keyFiles[indexPath.row - 1] : @"None"); - - [self.navigationController popViewControllerAnimated: YES]; -} - -- (void)upload: (id)sender -{ - [_HTTPServerThread.runLoop addTimer: [OFTimer - scheduledTimerWithTimeInterval: 0 - repeats: false - block: ^ (OFTimer *timer) { - NSString *message; - UIAlertController *alert; - - _HTTPServer.port = 0; - [_HTTPServer start]; - - message = [NSString stringWithFormat: - @"Navigate to http://%@:%u/ with your browser.\n\n" - @"Press OK when done.", - _HTTPServer.host.NSObject, _HTTPServer.port]; - alert = [UIAlertController - alertControllerWithTitle: @"Server Running" - message: message - preferredStyle: UIAlertControllerStyleAlert]; - [alert addAction: - [UIAlertAction actionWithTitle: @"OK" - style: UIAlertActionStyleDefault - handler: nil]]; - - dispatch_sync(dispatch_get_main_queue(), ^ { - [self presentViewController: alert - animated: YES - completion: ^ { - [_HTTPServer stop]; - }]; - }); - }]]; -} -@end ADDED iOS/SelectKeyFileController.swift Index: iOS/SelectKeyFileController.swift ================================================================== --- iOS/SelectKeyFileController.swift +++ iOS/SelectKeyFileController.swift @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import ObjFW +import UIKit + +class SelectKeyFileController: UITableViewController { + public var addSiteController: AddSiteController? + + private var keyFiles: [String] = [] + private var httpServer: OFHTTPServer + private var httpServerDelegate: HTTPServerDelegate + private var httpServerThread: OFThread + + required init?(coder aDecoder: NSCoder) { + httpServer = OFHTTPServer() + httpServer.host = "127.0.0.1".ofObject + + httpServerDelegate = HTTPServerDelegate() + httpServer.delegate = self.httpServerDelegate + + httpServerThread = OFThread() + + super.init(coder: aDecoder) + } + + override func viewDidLoad() { + super.viewDidLoad() + + guard let documentDirectory = NSSearchPathForDirectoriesInDomains( + .documentDirectory, .userDomainMask, true).first + else { + print("Could not get key files: No documents directory") + navigationController?.popViewController(animated: true) + return + } + + do { + keyFiles = try FileManager.default.contentsOfDirectory( + atPath: documentDirectory).sorted() + } catch let error as NSError { + print("Could not get key files: \(error)") + navigationController?.popViewController(animated: true) + return + } + + httpServerThread.start() + } + + deinit { + httpServerThread.runLoop.stop() + httpServerThread.join() + } + + override func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + return keyFiles.count + 1 + } + + override func tableView( + _ tableView: UITableView, + cellForRowAt indexPath: IndexPath + ) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "keyFile") ?? + UITableViewCell(style: .default, reuseIdentifier: "keyFile") + cell.textLabel?.text = + indexPath.row > 0 ? keyFiles[indexPath.row - 1] : "None" + return cell + } + + override func tableView(_ tableView: UITableView, + didSelectRowAt indexPath: IndexPath) { + addSiteController?.keyFile = + indexPath.row > 0 ? keyFiles[indexPath.row - 1] : nil + addSiteController?.keyFileLabel?.text = + indexPath.row > 0 ? keyFiles[indexPath.row - 1] : "None" + + self.navigationController?.popViewController(animated: true) + } + + @IBAction func upload(_ sender: Any?) { + let timer = OFTimer.scheduledTimer(withTimeInterval: 0, + repeats: false) { (OFTimer) in + self.httpServer.port = 0 + self.httpServer.start() + + let message = + "Navigate to http://\(self.httpServer.host!.nsObject):" + + "\(self.httpServer.port)/ in your browser.\n\n" + + "Press OK when done." + let alert = UIAlertController(title: "Server Running", + message: message, + preferredStyle: .alert) + alert.addAction( + UIAlertAction(title: "OK", style: .default, handler: nil)) + + DispatchQueue.main.sync { + self.present(alert, animated: true) { + self.httpServer.stop() + } + } + } + httpServerThread.runLoop.add(timer) + } +} DELETED iOS/ShowDetailsController.h Index: iOS/ShowDetailsController.h ================================================================== --- iOS/ShowDetailsController.h +++ iOS/ShowDetailsController.h @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import UIKit; - -#import "MainViewController.h" - -@interface ShowDetailsController: UITableViewController -{ - OFString *_name; - size_t _length; - bool _legacy; - OFString *_keyFile; -} - -@property (retain, nonatomic) IBOutlet UITextField *nameField; -@property (retain, nonatomic) IBOutlet UITextField *lengthField; -@property (retain, nonatomic) IBOutlet UISwitch *legacySwitch; -@property (retain, nonatomic) IBOutlet UITextField *keyFileField; -@property (retain, nonatomic) IBOutlet UITextField *passphraseField; -@property (retain) MainViewController *mainViewController; - -- (IBAction)remove: (id)sender; -@end DELETED iOS/ShowDetailsController.m Index: iOS/ShowDetailsController.m ================================================================== --- iOS/ShowDetailsController.m +++ iOS/ShowDetailsController.m @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW_Bridge; - -#import "ShowDetailsController.h" - -#import "SiteStorage.h" -#import "PasswordGenerator.h" -#import "NewPasswordGenerator.h" -#import "LegacyPasswordGenerator.h" - -@interface ShowDetailsController () -- (void)_generateWithCallback: (void (^)(NSMutableString *))block; -- (void)_generateAndCopy; -- (void)_generateAndShow; -@end - -static void -clearNSMutableString(NSMutableString *string) -{ - /* - * NSMutableString does not offer a way to zero the string. - * This is in the hope that setting a single character at an index just - * replaces that character in memory, and thus allows us to zero the - * password. - */ - for (NSUInteger i = 0; i < string.length; i++) - [string replaceCharactersInRange: NSMakeRange(i, 1) - withString: @" "]; -} - -@implementation ShowDetailsController -- (void)dealloc -{ - [_name release]; - [_nameField release]; - [_lengthField release]; - [_legacySwitch release]; - [_keyFile release]; - [_keyFileField release]; - [_passphraseField release]; - [_mainViewController release]; - - [super dealloc]; -} - -- (void)viewWillAppear: (BOOL)animated -{ - SiteStorage *siteStorage; - NSIndexPath *indexPath; - - [super viewWillAppear: animated]; - - siteStorage = self.mainViewController.siteStorage; - indexPath = self.mainViewController.tableView.indexPathForSelectedRow; - - [_name release]; - _name = [self.mainViewController.sites[indexPath.row] copy]; - _length = [siteStorage lengthForSite: _name]; - _legacy = [siteStorage isSiteLegacy: _name]; - _keyFile = [[siteStorage keyFileForSite: _name] copy]; - - self.nameField.text = _name.NSObject; - self.lengthField.text = [NSString stringWithFormat: @"%zu", _length]; - self.legacySwitch.on = _legacy; - self.keyFileField.text = _keyFile.NSObject; - - [self.mainViewController.tableView deselectRowAtIndexPath: indexPath - animated: YES]; -} - -- (BOOL)textFieldShouldReturn: (UITextField *)textField -{ - [textField resignFirstResponder]; - return NO; -} - -- (void)tableView: (UITableView *)tableView - didSelectRowAtIndexPath: (NSIndexPath *)indexPath -{ - [self.passphraseField resignFirstResponder]; - [tableView deselectRowAtIndexPath: indexPath - animated: YES]; - - if (indexPath.section == 3) { - switch (indexPath.row) { - case 0: - [self _generateAndCopy]; - break; - case 1: - [self _generateAndShow]; - break; - } - } -} - -- (void)_generateAndCopy -{ - [self _generateWithCallback: ^ (NSMutableString *password) { - UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; - pasteBoard.string = password; - - clearNSMutableString(password); - - UIAlertController *alert = [UIAlertController - alertControllerWithTitle: @"Password Generated" - message: @"The password has been copied " - @"into the clipboard." - preferredStyle: UIAlertControllerStyleAlert]; - [alert addAction: - [UIAlertAction actionWithTitle: @"OK" - style: UIAlertActionStyleDefault - handler: ^ (UIAlertAction *action) { - [self.navigationController - popViewControllerAnimated: YES]; - }]]; - - [self presentViewController: alert - animated: YES - completion: nil]; - }]; -} - -- (void)_generateAndShow -{ - [self _generateWithCallback: ^ (NSMutableString *password) { - UIAlertController *alert = [UIAlertController - alertControllerWithTitle: @"Generated Passphrase" - message: password - preferredStyle: UIAlertControllerStyleAlert]; - [alert addAction: - [UIAlertAction actionWithTitle: @"OK" - style: UIAlertActionStyleDefault - handler: ^ (UIAlertAction *action) { - [self.navigationController - popViewControllerAnimated: YES]; - }]]; - - [self presentViewController: alert - animated: YES - completion: ^ { - clearNSMutableString(password); - }]; - }]; -} - -- (void)_generateWithCallback: (void (^)(NSMutableString *))block -{ - id generator; - char *passphrase; - UIStoryboard *mainStoryboard; - UIViewController *activityController; - - if (_legacy) - generator = [LegacyPasswordGenerator generator]; - else - generator = [NewPasswordGenerator generator]; - - generator.site = _name; - generator.length = _length; - - if (_keyFile != nil) { - NSString *documentDirectory; - OFString *keyFilePath; - - if ((documentDirectory = NSSearchPathForDirectoriesInDomains( - NSDocumentDirectory, NSUserDomainMask, YES).firstObject) == - nil) { - NSLog(@"Could not get key files: No documents " - @"directory"); - return; - } - - keyFilePath = [documentDirectory.OFObject - stringByAppendingPathComponent: _keyFile]; - generator.keyFile = [OFMutableData - dataWithContentsOfFile: keyFilePath]; - } - - passphrase = of_strdup(self.passphraseField.text.UTF8String); - generator.passphrase = passphrase; - - mainStoryboard = [UIStoryboard storyboardWithName: @"Main" - bundle: nil]; - activityController = [mainStoryboard - instantiateViewControllerWithIdentifier: @"activityIndicator"]; - [self.navigationController.view addSubview: activityController.view]; - - dispatch_async(dispatch_get_global_queue( - DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ { - @try { - [generator derivePassword]; - } @finally { - if (generator.keyFile != nil) - of_explicit_memset( - (void *)generator.keyFile.items, 0, - generator.keyFile.count); - - of_explicit_memset(passphrase, 0, strlen(passphrase)); - free(passphrase); - } - - NSMutableString *password = [[[NSMutableString alloc] - initWithBytes: (char *)generator.output - length: generator.length - encoding: NSUTF8StringEncoding] autorelease]; - of_explicit_memset(generator.output, 0, generator.length); - - dispatch_sync(dispatch_get_main_queue(), ^ { - activityController.view.hidden = YES; - block(password); - }); - }); -} - -- (IBAction)remove: (id)sender -{ - UIAlertController *alert = [UIAlertController - alertControllerWithTitle: @"Remove Site?" - message: @"Do you want to remove this site?" - preferredStyle: UIAlertControllerStyleAlert]; - [alert addAction: - [UIAlertAction actionWithTitle: @"No" - style: UIAlertActionStyleCancel - handler: nil]]; - [alert addAction: - [UIAlertAction actionWithTitle: @"Yes" - style: UIAlertActionStyleDestructive - handler: ^ (UIAlertAction *action) { - [self.mainViewController.siteStorage removeSite: _name]; - [self.mainViewController reset]; - - [self.navigationController popViewControllerAnimated: YES]; - }]]; - - [self presentViewController: alert - animated: YES - completion: nil]; -} -@end ADDED iOS/ShowDetailsController.swift Index: iOS/ShowDetailsController.swift ================================================================== --- iOS/ShowDetailsController.swift +++ iOS/ShowDetailsController.swift @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit +import ObjFW +import ObjFW_Bridge + +class ShowDetailsController: UITableViewController, UITextFieldDelegate { + @IBOutlet var nameField: UITextField? + @IBOutlet var lengthField: UITextField? + @IBOutlet var legacySwitch: UISwitch? + @IBOutlet var keyFileField: UITextField? + @IBOutlet var passphraseField: UITextField? + public var mainViewController: MainViewController? + + private var name: OFString = "".ofObject + private var length: size_t = 0 + private var isLegacy: Bool = false + private var keyFile: OFString? = nil + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + guard let mainViewController = self.mainViewController else { return } + guard let tableView = mainViewController.tableView else { return } + let siteStorage = mainViewController.siteStorage + guard let indexPath = tableView.indexPathForSelectedRow else { return } + + name = mainViewController.sites[indexPath.row] + length = siteStorage.length(forSite: name) + isLegacy = siteStorage.isLegacy(site: name) + keyFile = siteStorage.keyFile(forSite: name) + + nameField?.text = name.nsObject + lengthField?.text = "\(length)" + legacySwitch?.isOn = isLegacy + keyFileField?.text = keyFile?.nsObject + + tableView.deselectRow(at: indexPath, animated: true) + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return false + } + + static private func clearNSMutableString(_ string: NSMutableString) { + /* + * NSMutableString does not offer a way to zero the string. + * This is in the hope that setting a single character at an index just + * replaces that character in memory, and thus allows us to zero the + * password. + */ + for i in 0.. ()) { + let generator: PasswordGenerator = isLegacy ? + LegacyPasswordGenerator() : NewPasswordGenerator() + generator.site = name + generator.length = length + + if let keyFile = keyFile { + guard let documentDirectory = NSSearchPathForDirectoriesInDomains( + .documentDirectory, .userDomainMask, true).first + else { + print("Could not get key files: No documents directory") + return + } + + let keyFilePath = documentDirectory.ofObject.appending(keyFile) + generator.keyFile = OFMutableData(contentsOfFile: keyFilePath) + } + + let passphraseText = (passphraseField?.text ?? "") as NSString + let passphrase = of_strdup(passphraseText.utf8String!)! + generator.passphrase = UnsafePointer(passphrase) + + let mainStoryboard = UIStoryboard(name: "Main", bundle: nil) + let activityController = mainStoryboard.instantiateViewController( + withIdentifier: "activityIndicator") + navigationController?.view.addSubview(activityController.view) + + DispatchQueue.global(qos: .default).async { + OFException.try({ + generator.derivePassword() + }, finally: { + if let keyFile = generator.keyFile as? OFMutableData { + of_explicit_memset(keyFile.mutableItems, 0, keyFile.count) + } + + of_explicit_memset(passphrase, 0, strlen(passphrase)) + free(passphrase) + }) + } + + let password = NSMutableString(bytes: generator.output, + length: generator.length, + encoding: String.Encoding.utf8.rawValue)! + of_explicit_memset(generator.output, 0, generator.length) + + DispatchQueue.main.sync { + activityController.view.isHidden = true + block(password) + } + } + + @IBAction func remove(_ sender: Any?) { + let message = "Do you want to remove this site?" + let alert = UIAlertController(title: "Remove Site?", + message: message, + preferredStyle: .alert) + alert.addAction( + UIAlertAction(title: "No", style: .cancel, handler: nil)) + let yesAction = UIAlertAction(title: "Yes", style: .destructive) { + (UIAlertAction) in + self.mainViewController?.siteStorage.removeSite(self.name) + self.mainViewController?.reset() + + self.navigationController?.popViewController(animated: true) + } + alert.addAction(yesAction) + + self.present(alert, animated: true, completion: nil) + } +} DELETED iOS/SiteStorage.h Index: iOS/SiteStorage.h ================================================================== --- iOS/SiteStorage.h +++ iOS/SiteStorage.h @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW; - -@interface SiteStorage: OFObject -{ - OFString *_path; - OFMutableDictionary *> - *_storage; - OFArray *_sites; -} - -- (OFArray *)sitesWithFilter: (OFString *)filter; -- (bool)hasSite: (OFString *)name; -- (size_t)lengthForSite: (OFString *)name; -- (bool)isSiteLegacy: (OFString *)name; -- (OFString *)keyFileForSite: (OFString *)name; -- (void)setSite: (OFString *)site - length: (size_t)length - legacy: (bool)legacy - keyFile: (OFString *)keyFile; -- (void)removeSite: (OFString *)name; -@end DELETED iOS/SiteStorage.m Index: iOS/SiteStorage.m ================================================================== --- iOS/SiteStorage.m +++ iOS/SiteStorage.m @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2016 - 2019 Jonathan Schleifer - * - * https://heap.zone/git/scrypt-pwgen.git - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -@import ObjFW; - -#import "SiteStorage.h" - -@interface SiteStorage () -- (void)_update; -@end - -static OFNumber *lengthField, *legacyField, *keyFileField; - -@implementation SiteStorage -+ (void)initialize -{ - lengthField = [[OFNumber alloc] initWithUInt8: 0]; - legacyField = [[OFNumber alloc] initWithUInt8: 1]; - keyFileField = [[OFNumber alloc] initWithUInt8: 2]; -} - -- (instancetype)init -{ - self = [super init]; - - @try { - @autoreleasepool { - OFFileManager *fileManager = - OFFileManager.defaultManager; - OFString *userDataPath = OFSystemInfo.userDataPath; - - if (![fileManager directoryExistsAtPath: userDataPath]) - [fileManager - createDirectoryAtPath: userDataPath]; - - _path = [[userDataPath stringByAppendingPathComponent: - @"sites.msgpack"] copy]; - - @try { - _storage = [[OFData dataWithContentsOfFile: - _path].messagePackValue mutableCopy]; - } @catch (id e) { - _storage = [[OFMutableDictionary alloc] init]; - } - - _sites = [_storage.allKeys.sortedArray retain]; - } - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_path release]; - [_storage release]; - [_sites release]; - - [super dealloc]; -} - -- (OFArray *)sitesWithFilter: (OFString *)filter -{ - OFArray *sites; - - @autoreleasepool { - /* - * FIXME: We need case folding here, but there is no method for - * it yet. - */ - filter = filter.lowercaseString; - sites = [_storage.allKeys.sortedArray - filteredArrayUsingBlock: ^ (OFString *name, size_t index) { - if (filter == nil) - return true; - - return [name.lowercaseString containsString: filter]; - }]; - - [sites retain]; - } - - return [sites autorelease]; -} - -- (bool)hasSite: (OFString *)name -{ - return (_storage[name] != nil); -} - -- (size_t)lengthForSite: (OFString *)name -{ - OFDictionary *site = _storage[name]; - - if (site == nil) - @throw [OFInvalidArgumentException exception]; - - return [site[lengthField] sizeValue]; -} - -- (bool)isSiteLegacy: (OFString *)name -{ - OFDictionary *site = _storage[name]; - - if (site == nil) - @throw [OFInvalidArgumentException exception]; - - return [site[legacyField] boolValue]; -} - -- (OFString *)keyFileForSite: (OFString *)name -{ - OFDictionary *site = _storage[name]; - OFString *keyFile; - - if (site == nil) - @throw [OFInvalidArgumentException exception]; - - keyFile = site[keyFileField]; - - if ([keyFile isEqual: [OFNull null]]) - return nil; - - return keyFile; -} - -- (void)setSite: (OFString *)site - length: (size_t)length - legacy: (bool)legacy - keyFile: (OFString *)keyFile -{ - @autoreleasepool { - OFMutableDictionary *siteDictionary = - [OFMutableDictionary dictionary]; - - siteDictionary[lengthField] = [OFNumber numberWithSize: length]; - siteDictionary[legacyField] = [OFNumber numberWithBool: legacy]; - siteDictionary[keyFileField] = keyFile; - - [siteDictionary makeImmutable]; - - _storage[site] = siteDictionary; - - [self _update]; - } -} - -- (void)removeSite: (OFString *)name -{ - [_storage removeObjectForKey: name]; - [self _update]; -} - -- (void)_update -{ - @autoreleasepool { - [_storage.messagePackRepresentation writeToFile: _path]; - - [_sites release]; - _sites = [_storage.allKeys.sortedArray retain]; - } -} -@end ADDED iOS/SiteStorage.swift Index: iOS/SiteStorage.swift ================================================================== --- iOS/SiteStorage.swift +++ iOS/SiteStorage.swift @@ -0,0 +1,138 @@ +/* +* Copyright (c) 2016 - 2019 Jonathan Schleifer +* +* https://heap.zone/git/scrypt-pwgen.git +* +* Permission to use, copy, modify, and/or distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice is present in all copies. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +import ObjFW +import ObjFW_Bridge + +class SiteStorage: OFObject { + private typealias Storage = + OFMutableDictionary> + + private static let lengthField = OFNumber(uInt8: 0) + private static let legacyField = OFNumber(uInt8: 1) + private static let keyFileField = OFNumber(uInt8: 2) + + private var path: OFString + private var storage: Storage + private var sites: OFArray + + override init() { + let fileManager = OFFileManager.default + let userDataPath = OFSystemInfo.userDataPath! + + if !fileManager.directoryExists(atPath: userDataPath) { + fileManager.createDirectory(atPath: userDataPath) + } + + let path = userDataPath.appendingPathComponent( + OFString(utf8String: "sites.msgpack")) + var storage: Storage? = nil + OFException.try({ + storage = OFData(contentsOfFile: path).messagePackValue as? Storage + }, catch: { (OFException) in + storage = OFMutableDictionary() + }) + + self.path = path + self.storage = storage! + self.sites = self.storage.allKeys.sorted + } + + func sites(withFilter filter: OFString?) -> OFArray { + // FIXME: We need case folding here, but there is no method for it yet. + let filter = filter?.lowercase + + return storage.allKeys.sorted.filteredArray({ + (name: Any, index: size_t) -> Bool in + if filter == nil { + return true + } + + let name = name as! OFString + return name.lowercase.contains(filter!) + }) + } + + func hasSite(_ name: OFString) -> Bool { + return (storage[name] != nil) + } + + func length(forSite name: OFString) -> size_t { + guard let site = storage[name] else { + OFInvalidArgumentException().throw() + abort() + } + + return (site[SiteStorage.lengthField] as! OFNumber).sizeValue + } + + func isLegacy(site name: OFString) -> Bool { + guard let site = storage[name] else { + OFInvalidArgumentException().throw() + abort() + } + + return (site[SiteStorage.legacyField] as! OFNumber).boolValue + } + + func keyFile(forSite name: OFString) -> OFString? { + guard let site = storage[name] else { + OFInvalidArgumentException().throw() + abort() + } + + let keyFile = site[SiteStorage.keyFileField] + if keyFile is OFNull { + return nil + } + + return keyFile as? OFString + } + + func setSite(_ name: OFString, length: size_t, legacy: Bool, + keyFile: OFString?) { + let siteDictionary = OFMutableDictionary() + + siteDictionary.setObject(OFNumber(size: length), + forKey: SiteStorage.lengthField) + siteDictionary.setObject(OFNumber(bool: legacy), + forKey: SiteStorage.legacyField) + if keyFile != nil { + siteDictionary.setObject(keyFile!, forKey: SiteStorage.keyFileField) + } + + siteDictionary.makeImmutable() + storage.setObject(siteDictionary, forKey: name) + + self.update() + } + + func removeSite(_ name: OFString) { + self.storage.removeObject(forKey: name) + self.update() + } + + private func update() { + storage.messagePackRepresentation.write(toFile: path) + sites = storage.allKeys.sorted + } +} ADDED iOS/bridge.h Index: iOS/bridge.h ================================================================== --- iOS/bridge.h +++ iOS/bridge.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 - 2019 Jonathan Schleifer + * + * https://heap.zone/git/scrypt-pwgen.git + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#import "PasswordGenerator.h" +#import "NewPasswordGenerator.h" +#import "LegacyPasswordGenerator.h" Index: iOS/main.m ================================================================== --- iOS/main.m +++ iOS/main.m @@ -22,11 +22,11 @@ #import #import #import -#import "AppDelegate.h" +#import "scrypt_pwgen-Swift.h" @interface OFAppDelegate: OFObject @end OF_APPLICATION_DELEGATE(OFAppDelegate) Index: iOS/scrypt-pwgen.xcodeproj/project.pbxproj ================================================================== --- iOS/scrypt-pwgen.xcodeproj/project.pbxproj +++ iOS/scrypt-pwgen.xcodeproj/project.pbxproj @@ -5,30 +5,30 @@ }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ - 4B0719251DAA78D80065997A /* ShowDetailsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0719241DAA78D80065997A /* ShowDetailsController.m */; }; - 4B2E52E11DA942840040D091 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E52E01DA942840040D091 /* main.m */; }; - 4B2E52E41DA942840040D091 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E52E31DA942840040D091 /* AppDelegate.m */; }; - 4B2E52E71DA942840040D091 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2E52E61DA942840040D091 /* MainViewController.m */; }; 4B2E52EA1DA942840040D091 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52E81DA942840040D091 /* Main.storyboard */; }; 4B2E52EC1DA942840040D091 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52EB1DA942840040D091 /* Assets.xcassets */; }; 4B2E52EF1DA942840040D091 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52ED1DA942840040D091 /* LaunchScreen.storyboard */; }; - 4B82D1151DAAAFCE00F32B2F /* AboutController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B82D1141DAAAFCE00F32B2F /* AboutController.m */; }; + 4B31D80922B58F0F00494B15 /* SiteStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B31D80822B58F0F00494B15 /* SiteStorage.swift */; }; + 4B5BCEF922B5B94C00E551BD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5BCEF822B5B94C00E551BD /* AppDelegate.swift */; }; + 4B5BCEFB22B5CF3200E551BD /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5BCEFA22B5CF3200E551BD /* MainViewController.swift */; }; + 4B5BCEFD22B5D98800E551BD /* SelectKeyFileController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5BCEFC22B5D98800E551BD /* SelectKeyFileController.swift */; }; + 4B5BCEFF22B5E36900E551BD /* ShowDetailsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5BCEFE22B5E36900E551BD /* ShowDetailsController.swift */; }; + 4B93656E22B5ADA00099DD08 /* HTTPServerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B93656D22B5ADA00099DD08 /* HTTPServerDelegate.swift */; }; + 4B93657022B5AE2C0099DD08 /* AboutController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B93656F22B5AE2C0099DD08 /* AboutController.swift */; }; + 4B93657222B5B1FB0099DD08 /* AddSiteController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B93657122B5B1FB0099DD08 /* AddSiteController.swift */; }; 4B9525251F96BB900095F259 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9525231F96BB820095F259 /* ObjFW.framework */; }; 4B9525261F96BB900095F259 /* ObjFW_Bridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9525241F96BB820095F259 /* ObjFW_Bridge.framework */; }; 4B9525291F994CD30095F259 /* ObjFW.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9525231F96BB820095F259 /* ObjFW.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4B95252A1F9953350095F259 /* ObjFW_Bridge.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9525241F96BB820095F259 /* ObjFW_Bridge.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 4B9EB1152008167200EB66F2 /* HTTPServerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9EB1142008167200EB66F2 /* HTTPServerDelegate.m */; settings = {COMPILER_FLAGS = "-fconstant-string-class=OFConstantString -fno-constant-cfstrings"; }; }; 4BA115D21DA9432D007ED4EA /* LegacyPasswordGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BA115CE1DA9432D007ED4EA /* LegacyPasswordGenerator.m */; settings = {COMPILER_FLAGS = "-fconstant-string-class=OFConstantString -fno-constant-cfstrings"; }; }; 4BA115D31DA9432D007ED4EA /* NewPasswordGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BA115D01DA9432D007ED4EA /* NewPasswordGenerator.m */; settings = {COMPILER_FLAGS = "-fconstant-string-class=OFConstantString -fno-constant-cfstrings"; }; }; 4BA115D61DA94390007ED4EA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BA115D51DA94390007ED4EA /* UIKit.framework */; }; - 4BB3CDFD1DA9764300FEE5ED /* AddSiteController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB3CDFC1DA9764300FEE5ED /* AddSiteController.m */; }; - 4BC29DD51FCB5FAE00A1E786 /* SelectKeyFileController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC29DD41FCB5FAE00A1E786 /* SelectKeyFileController.m */; }; 4BF4ADEA1DA9A3DB0073B995 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BF4ADE91DA9A3DB0073B995 /* Foundation.framework */; }; - 4BF4ADED1DA9A6B00073B995 /* SiteStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF4ADEC1DA9A6B00073B995 /* SiteStorage.m */; settings = {COMPILER_FLAGS = "-fconstant-string-class=OFConstantString -fno-constant-cfstrings"; }; }; + 4BF4C3A022B602F50034FCED /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF4C39F22B602F50034FCED /* main.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 4BB3CDF61DA967C100FEE5ED /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -43,41 +43,34 @@ runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 4B0719231DAA78D80065997A /* ShowDetailsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowDetailsController.h; sourceTree = ""; }; - 4B0719241DAA78D80065997A /* ShowDetailsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowDetailsController.m; sourceTree = ""; }; 4B2E52DC1DA942840040D091 /* scrypt-pwgen.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "scrypt-pwgen.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B2E52E01DA942840040D091 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 4B2E52E21DA942840040D091 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 4B2E52E31DA942840040D091 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 4B2E52E51DA942840040D091 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; - 4B2E52E61DA942840040D091 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; 4B2E52E91DA942840040D091 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 4B2E52EB1DA942840040D091 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 4B2E52EE1DA942840040D091 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4B2E52F01DA942840040D091 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 4B82D1131DAAAFCE00F32B2F /* AboutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutController.h; sourceTree = ""; }; - 4B82D1141DAAAFCE00F32B2F /* AboutController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutController.m; sourceTree = ""; }; + 4B31D80822B58F0F00494B15 /* SiteStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteStorage.swift; sourceTree = ""; }; + 4B38148322B5ED01005C27B2 /* bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bridge.h; sourceTree = ""; }; + 4B5BCEF822B5B94C00E551BD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 4B5BCEFA22B5CF3200E551BD /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + 4B5BCEFC22B5D98800E551BD /* SelectKeyFileController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectKeyFileController.swift; sourceTree = ""; }; + 4B5BCEFE22B5E36900E551BD /* ShowDetailsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowDetailsController.swift; sourceTree = ""; }; + 4B93656D22B5ADA00099DD08 /* HTTPServerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPServerDelegate.swift; sourceTree = ""; }; + 4B93656F22B5AE2C0099DD08 /* AboutController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutController.swift; sourceTree = ""; }; + 4B93657122B5B1FB0099DD08 /* AddSiteController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSiteController.swift; sourceTree = ""; }; 4B9525231F96BB820095F259 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ObjFW/Frameworks/ObjFW.framework; sourceTree = ""; }; 4B9525241F96BB820095F259 /* ObjFW_Bridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW_Bridge.framework; path = ObjFW/Frameworks/ObjFW_Bridge.framework; sourceTree = ""; }; - 4B9EB1142008167200EB66F2 /* HTTPServerDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTTPServerDelegate.m; sourceTree = ""; }; - 4B9EB1162008168400EB66F2 /* HTTPServerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTTPServerDelegate.h; sourceTree = ""; }; 4BA115CD1DA9432D007ED4EA /* LegacyPasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LegacyPasswordGenerator.h; path = ../LegacyPasswordGenerator.h; sourceTree = ""; }; 4BA115CE1DA9432D007ED4EA /* LegacyPasswordGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LegacyPasswordGenerator.m; path = ../LegacyPasswordGenerator.m; sourceTree = ""; }; 4BA115CF1DA9432D007ED4EA /* NewPasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NewPasswordGenerator.h; path = ../NewPasswordGenerator.h; sourceTree = ""; }; 4BA115D01DA9432D007ED4EA /* NewPasswordGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NewPasswordGenerator.m; path = ../NewPasswordGenerator.m; sourceTree = ""; }; 4BA115D11DA9432D007ED4EA /* PasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PasswordGenerator.h; path = ../PasswordGenerator.h; sourceTree = ""; }; 4BA115D51DA94390007ED4EA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 4BB3CDFB1DA9764300FEE5ED /* AddSiteController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddSiteController.h; sourceTree = ""; }; - 4BB3CDFC1DA9764300FEE5ED /* AddSiteController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddSiteController.m; sourceTree = ""; }; - 4BC29DD41FCB5FAE00A1E786 /* SelectKeyFileController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SelectKeyFileController.m; sourceTree = ""; }; - 4BC29DD61FCB5FC400A1E786 /* SelectKeyFileController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SelectKeyFileController.h; sourceTree = ""; }; 4BF4ADE91DA9A3DB0073B995 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 4BF4ADEB1DA9A6B00073B995 /* SiteStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SiteStorage.h; sourceTree = ""; }; - 4BF4ADEC1DA9A6B00073B995 /* SiteStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SiteStorage.m; sourceTree = ""; }; + 4BF4C39F22B602F50034FCED /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 4B2E52D91DA942840040D091 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -113,30 +106,23 @@ }; 4B2E52DE1DA942840040D091 /* iOS */ = { isa = PBXGroup; children = ( 4B2E52EB1DA942840040D091 /* Assets.xcassets */, - 4B82D1131DAAAFCE00F32B2F /* AboutController.h */, - 4B82D1141DAAAFCE00F32B2F /* AboutController.m */, - 4BB3CDFB1DA9764300FEE5ED /* AddSiteController.h */, - 4BB3CDFC1DA9764300FEE5ED /* AddSiteController.m */, - 4B2E52E21DA942840040D091 /* AppDelegate.h */, - 4B2E52E31DA942840040D091 /* AppDelegate.m */, - 4B9EB1162008168400EB66F2 /* HTTPServerDelegate.h */, - 4B9EB1142008167200EB66F2 /* HTTPServerDelegate.m */, + 4B93656F22B5AE2C0099DD08 /* AboutController.swift */, + 4B93657122B5B1FB0099DD08 /* AddSiteController.swift */, + 4B5BCEF822B5B94C00E551BD /* AppDelegate.swift */, + 4B93656D22B5ADA00099DD08 /* HTTPServerDelegate.swift */, 4B2E52F01DA942840040D091 /* Info.plist */, 4B2E52ED1DA942840040D091 /* LaunchScreen.storyboard */, 4B2E52E81DA942840040D091 /* Main.storyboard */, - 4B2E52E51DA942840040D091 /* MainViewController.h */, - 4B2E52E61DA942840040D091 /* MainViewController.m */, - 4BC29DD61FCB5FC400A1E786 /* SelectKeyFileController.h */, - 4BC29DD41FCB5FAE00A1E786 /* SelectKeyFileController.m */, - 4B0719231DAA78D80065997A /* ShowDetailsController.h */, - 4B0719241DAA78D80065997A /* ShowDetailsController.m */, - 4BF4ADEB1DA9A6B00073B995 /* SiteStorage.h */, - 4BF4ADEC1DA9A6B00073B995 /* SiteStorage.m */, - 4B2E52E01DA942840040D091 /* main.m */, + 4B5BCEFA22B5CF3200E551BD /* MainViewController.swift */, + 4B5BCEFC22B5D98800E551BD /* SelectKeyFileController.swift */, + 4B5BCEFE22B5E36900E551BD /* ShowDetailsController.swift */, + 4B31D80822B58F0F00494B15 /* SiteStorage.swift */, + 4B38148322B5ED01005C27B2 /* bridge.h */, + 4BF4C39F22B602F50034FCED /* main.m */, ); name = iOS; sourceTree = ""; }; 4BA115CC1DA9431D007ED4EA /* scrypt-pwgen */ = { @@ -193,19 +179,21 @@ ORGANIZATIONNAME = "Jonathan Schleifer"; TargetAttributes = { 4B2E52DB1DA942840040D091 = { CreatedOnToolsVersion = 8.0; DevelopmentTeam = MXKNFCKFL6; + LastSwiftMigration = 1020; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 4B2E52D71DA942840040D091 /* Build configuration list for PBXProject "scrypt-pwgen" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); mainGroup = 4B2E52D31DA942840040D091; productRefGroup = 4B2E52DD1DA942840040D091 /* Products */; @@ -233,21 +221,21 @@ /* Begin PBXSourcesBuildPhase section */ 4B2E52D81DA942840040D091 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4B82D1151DAAAFCE00F32B2F /* AboutController.m in Sources */, - 4BC29DD51FCB5FAE00A1E786 /* SelectKeyFileController.m in Sources */, - 4BB3CDFD1DA9764300FEE5ED /* AddSiteController.m in Sources */, - 4B2E52E41DA942840040D091 /* AppDelegate.m in Sources */, - 4B9EB1152008167200EB66F2 /* HTTPServerDelegate.m in Sources */, + 4B5BCEF922B5B94C00E551BD /* AppDelegate.swift in Sources */, + 4B93656E22B5ADA00099DD08 /* HTTPServerDelegate.swift in Sources */, + 4B5BCEFB22B5CF3200E551BD /* MainViewController.swift in Sources */, + 4B93657222B5B1FB0099DD08 /* AddSiteController.swift in Sources */, 4BA115D21DA9432D007ED4EA /* LegacyPasswordGenerator.m in Sources */, - 4B2E52E71DA942840040D091 /* MainViewController.m in Sources */, 4BA115D31DA9432D007ED4EA /* NewPasswordGenerator.m in Sources */, - 4B0719251DAA78D80065997A /* ShowDetailsController.m in Sources */, - 4BF4ADED1DA9A6B00073B995 /* SiteStorage.m in Sources */, - 4B2E52E11DA942840040D091 /* main.m in Sources */, + 4B31D80922B58F0F00494B15 /* SiteStorage.swift in Sources */, + 4B5BCEFD22B5D98800E551BD /* SelectKeyFileController.swift in Sources */, + 4B5BCEFF22B5E36900E551BD /* ShowDetailsController.swift in Sources */, + 4BF4C3A022B602F50034FCED /* main.m in Sources */, + 4B93657022B5AE2C0099DD08 /* AboutController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ @@ -388,12 +376,16 @@ "$(inherited)", "$(PROJECT_DIR)/ObjFW/Frameworks", ); HEADER_SEARCH_PATHS = ObjFW/include; INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "zone.heap.scrypt-pwgen.ios"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = bridge.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 4B2E52F51DA942840040D091 /* Release */ = { @@ -409,12 +401,15 @@ "$(inherited)", "$(PROJECT_DIR)/ObjFW/Frameworks", ); HEADER_SEARCH_PATHS = ObjFW/include; INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "zone.heap.scrypt-pwgen.ios"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = bridge.h; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */