iOS: Migrate to Swift
This is in preparation for moving to SwiftUI at some point.
This commit is contained in:
parent
e039b7d5f5
commit
83b21ee89e
25 changed files with 816 additions and 1266 deletions
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <UIWebViewDelegate>
|
|
||||||
@property (nonatomic, retain) IBOutlet UIWebView *webView;
|
|
||||||
@end
|
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 =
|
|
||||||
@"<html>"
|
|
||||||
@"<head>"
|
|
||||||
@"<style type='text/css'>"
|
|
||||||
@"body {"
|
|
||||||
@" font-family: sans-serif;"
|
|
||||||
@"}"
|
|
||||||
@""
|
|
||||||
@"#title {"
|
|
||||||
@" font-size: 2.5em;"
|
|
||||||
@" font-weight: bold;"
|
|
||||||
@"}"
|
|
||||||
@""
|
|
||||||
@"#copyright {"
|
|
||||||
@" font-size: 0.9em;"
|
|
||||||
@" font-weight: bold;"
|
|
||||||
@"}"
|
|
||||||
@"</style>"
|
|
||||||
@"</head>"
|
|
||||||
@"<body>"
|
|
||||||
@"<div id='title'>"
|
|
||||||
@" scrypt-pwgen {version}"
|
|
||||||
@"</div>"
|
|
||||||
@"<div id='copyright'>"
|
|
||||||
@" Copyright © 2016 - 2019 Jonathan Schleifer"
|
|
||||||
@"</div>"
|
|
||||||
@"<p name='free_software'>"
|
|
||||||
@" scrypt-pwgen is free software and the source code is available at "
|
|
||||||
@" <a href='https://heap.zone/scrypt-pwgen/'>here</a>."
|
|
||||||
@"</p>"
|
|
||||||
@"<p name='objfw'>"
|
|
||||||
@" It makes use of the <a href='https://heap.zone/objfw/'>ObjFW</a> "
|
|
||||||
@"framework and also uses its scrypt implementation."
|
|
||||||
@"</p>"
|
|
||||||
@"</body>"
|
|
||||||
@"</html>";
|
|
||||||
|
|
||||||
@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
|
|
84
iOS/AboutController.swift
Normal file
84
iOS/AboutController.swift
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
||||||
|
*
|
||||||
|
* 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(
|
||||||
|
"<html>" +
|
||||||
|
"<head>" +
|
||||||
|
"<style type='text/css'>" +
|
||||||
|
"body {" +
|
||||||
|
" font-family: sans-serif;" +
|
||||||
|
"}" +
|
||||||
|
"" +
|
||||||
|
"#title {" +
|
||||||
|
" font-size: 2.5em;" +
|
||||||
|
" font-weight: bold;" +
|
||||||
|
"}" +
|
||||||
|
"" +
|
||||||
|
"#copyright {" +
|
||||||
|
" font-size: 0.9em;" +
|
||||||
|
" font-weight: bold;" +
|
||||||
|
"}" +
|
||||||
|
"</style>" +
|
||||||
|
"</head>" +
|
||||||
|
"<body>" +
|
||||||
|
"<div id='title'>" +
|
||||||
|
" scrypt-pwgen \(version ?? "")" +
|
||||||
|
"</div>" +
|
||||||
|
"<div id='copyright'>" +
|
||||||
|
" Copyright © 2016 - 2019 Jonathan Schleifer" +
|
||||||
|
"</div>" +
|
||||||
|
"<p name='free_software'>" +
|
||||||
|
" scrypt-pwgen is free software and the source code is available" +
|
||||||
|
" at <a href='https://heap.zone/scrypt-pwgen/'>here</a>." +
|
||||||
|
"</p>" +
|
||||||
|
"<p name='objfw'>" +
|
||||||
|
" It makes use of the" +
|
||||||
|
" <a href='https://heap.zone/objfw/'>ObjFW</a> framework and" +
|
||||||
|
" also uses its scrypt implementation." +
|
||||||
|
"</p>" +
|
||||||
|
"</body>" +
|
||||||
|
"</html>", 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <UITableViewDelegate>
|
|
||||||
@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
|
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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
|
|
118
iOS/AddSiteController.swift
Normal file
118
iOS/AddSiteController.swift
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <UIApplicationDelegate>
|
|
||||||
@property (nonatomic, strong) UIWindow *window;
|
|
||||||
@end
|
|
|
@ -20,13 +20,8 @@
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
import UIKit
|
||||||
|
|
||||||
@implementation AppDelegate
|
@objc class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
- (void)dealloc
|
public var window: UIWindow?
|
||||||
{
|
|
||||||
[_window release];
|
|
||||||
|
|
||||||
[super dealloc];
|
|
||||||
}
|
}
|
||||||
@end
|
|
|
@ -1,12 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BN3-Y7-zvx">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BN3-Y7-zvx">
|
||||||
<device id="retina4_7" orientation="portrait">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
|
@ -32,7 +31,7 @@
|
||||||
<!--Sites-->
|
<!--Sites-->
|
||||||
<scene sceneID="raj-gx-00d">
|
<scene sceneID="raj-gx-00d">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="P19-6i-fpd" customClass="MainViewController" sceneMemberID="viewController">
|
<viewController id="P19-6i-fpd" customClass="MainViewController" customModule="scrypt_pwgen" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="XVy-9K-Bul"/>
|
<viewControllerLayoutGuide type="top" id="XVy-9K-Bul"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="TZK-mv-9Bn"/>
|
<viewControllerLayoutGuide type="bottom" id="TZK-mv-9Bn"/>
|
||||||
|
@ -93,7 +92,7 @@
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<scene sceneID="rga-fS-ski">
|
<scene sceneID="rga-fS-ski">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController title="About" id="MZ3-iZ-Dsf" customClass="AboutController" sceneMemberID="viewController">
|
<viewController title="About" id="MZ3-iZ-Dsf" customClass="AboutController" customModule="scrypt_pwgen" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="8k0-QJ-gsC"/>
|
<viewControllerLayoutGuide type="top" id="8k0-QJ-gsC"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="NSX-G5-c03"/>
|
<viewControllerLayoutGuide type="bottom" id="NSX-G5-c03"/>
|
||||||
|
@ -130,7 +129,7 @@
|
||||||
<!--Add Site Controller-->
|
<!--Add Site Controller-->
|
||||||
<scene sceneID="IxZ-dn-p6h">
|
<scene sceneID="IxZ-dn-p6h">
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="mTn-Td-fIF" customClass="AddSiteController" sceneMemberID="viewController">
|
<tableViewController id="mTn-Td-fIF" customClass="AddSiteController" customModule="scrypt_pwgen" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="cum-L6-K1B">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="cum-L6-K1B">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
@ -242,7 +241,7 @@
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Key file" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Uyw-CW-atj">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Key file" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Uyw-CW-atj">
|
||||||
<rect key="frame" x="16" y="12" width="100" height="21"/>
|
<rect key="frame" x="16" y="11.5" width="100" height="21"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="100" id="5d9-re-aJA"/>
|
<constraint firstAttribute="width" constant="100" id="5d9-re-aJA"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
@ -306,7 +305,7 @@
|
||||||
<!--Select Key File Controller-->
|
<!--Select Key File Controller-->
|
||||||
<scene sceneID="fKq-Aa-JNA">
|
<scene sceneID="fKq-Aa-JNA">
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="4bs-rP-TxE" customClass="SelectKeyFileController" sceneMemberID="viewController">
|
<tableViewController id="4bs-rP-TxE" customClass="SelectKeyFileController" customModule="scrypt_pwgen" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="SYH-wm-J8Z">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="SYH-wm-J8Z">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
@ -344,7 +343,7 @@
|
||||||
<!--Show Details Controller-->
|
<!--Show Details Controller-->
|
||||||
<scene sceneID="rn9-fJ-mg7">
|
<scene sceneID="rn9-fJ-mg7">
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="ayJ-fs-aIU" customClass="ShowDetailsController" sceneMemberID="viewController">
|
<tableViewController id="ayJ-fs-aIU" customClass="ShowDetailsController" customModule="scrypt_pwgen" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="vWS-Yc-qQ5">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="vWS-Yc-qQ5">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
|
|
@ -20,13 +20,12 @@
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "HTTPServerDelegate.h"
|
import Foundation
|
||||||
|
import ObjFW
|
||||||
|
|
||||||
@implementation HTTPServerDelegate
|
class HTTPServerDelegate: OFObject, OFHTTPServerDelegate {
|
||||||
- (void)server: (OFHTTPServer *)server
|
func server(_ server: OFHTTPServer, didReceive request: OFHTTPRequest,
|
||||||
didReceiveRequest: (OFHTTPRequest *)request
|
requestBody: OFStream?, response: OFHTTPResponse) {
|
||||||
response: (OFHTTPResponse *)response
|
print("\(request)")
|
||||||
{
|
}
|
||||||
of_log(@"%@", request);
|
|
||||||
}
|
}
|
||||||
@end
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <UISearchBarDelegate,
|
|
||||||
UITableViewDelegate, UITableViewDataSource>
|
|
||||||
@property (retain) OFArray<OFString *> *sites;
|
|
||||||
@property (retain) SiteStorage *siteStorage;
|
|
||||||
@property (nonatomic, retain) IBOutlet UISearchBar *searchBar;
|
|
||||||
@property (nonatomic, retain) IBOutlet UITableView *tableView;
|
|
||||||
|
|
||||||
- (void)reset;
|
|
||||||
@end
|
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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
|
|
80
iOS/MainViewController.swift
Normal file
80
iOS/MainViewController.swift
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
||||||
|
*
|
||||||
|
* 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<OFString>()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <UITableViewDelegate,
|
|
||||||
UITableViewDataSource>
|
|
||||||
{
|
|
||||||
NSArray<NSString *> *_keyFiles;
|
|
||||||
OFHTTPServer *_HTTPServer;
|
|
||||||
HTTPServerDelegate *_HTTPServerDelegate;
|
|
||||||
OFThread *_HTTPServerThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (retain) AddSiteController *addSiteController;
|
|
||||||
|
|
||||||
- (IBAction)upload: (id)sender;
|
|
||||||
@end
|
|
|
@ -1,152 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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<NSString *> *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
|
|
124
iOS/SelectKeyFileController.swift
Normal file
124
iOS/SelectKeyFileController.swift
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <UITableViewDelegate,
|
|
||||||
UITextFieldDelegate>
|
|
||||||
{
|
|
||||||
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
|
|
|
@ -1,260 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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 <PasswordGenerator> 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
|
|
203
iOS/ShowDetailsController.swift
Normal file
203
iOS/ShowDetailsController.swift
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
||||||
|
*
|
||||||
|
* 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..<string.length {
|
||||||
|
string.replaceCharacters(in: NSRange(location: i, length: 1),
|
||||||
|
with: " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView,
|
||||||
|
didSelectRowAt indexPath: IndexPath) {
|
||||||
|
passphraseField?.resignFirstResponder()
|
||||||
|
tableView.deselectRow(at: indexPath, animated: true)
|
||||||
|
|
||||||
|
if indexPath.section == 3 {
|
||||||
|
switch indexPath.row {
|
||||||
|
case 0:
|
||||||
|
self.generateAndCopy()
|
||||||
|
case 1:
|
||||||
|
self.generateAndShow()
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func generateAndCopy() {
|
||||||
|
self.generateWithCallback { (password: NSMutableString) in
|
||||||
|
let pasteboard = UIPasteboard.general
|
||||||
|
pasteboard.string = password as String
|
||||||
|
|
||||||
|
ShowDetailsController.clearNSMutableString(password)
|
||||||
|
|
||||||
|
let message = "The password has been copied into the clipboard."
|
||||||
|
let alert = UIAlertController(title: "Password Generated",
|
||||||
|
message: message,
|
||||||
|
preferredStyle: .alert)
|
||||||
|
let action = UIAlertAction(title: "OK", style: .default) {
|
||||||
|
(UIAlertAction) in
|
||||||
|
self.navigationController?.popViewController(animated: true)
|
||||||
|
}
|
||||||
|
alert.addAction(action)
|
||||||
|
|
||||||
|
self.present(alert, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func generateAndShow() {
|
||||||
|
self.generateWithCallback { (password: NSMutableString) in
|
||||||
|
let alert = UIAlertController(title: "Generated Passphrase",
|
||||||
|
message: password as String,
|
||||||
|
preferredStyle: .alert)
|
||||||
|
let action = UIAlertAction(title: "OK", style: .default) {
|
||||||
|
(UIAlertAction) in
|
||||||
|
self.navigationController?.popViewController(animated: true)
|
||||||
|
}
|
||||||
|
alert.addAction(action)
|
||||||
|
|
||||||
|
self.present(alert, animated: true) {
|
||||||
|
ShowDetailsController.clearNSMutableString(password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func generateWithCallback(_ block: (_: NSMutableString) -> ()) {
|
||||||
|
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<CChar>(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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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<OFString *, OFDictionary<OFNumber *, id> *>
|
|
||||||
*_storage;
|
|
||||||
OFArray *_sites;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (OFArray<OFString *> *)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
|
|
|
@ -1,185 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
|
||||||
*
|
|
||||||
* 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<OFString *> *)sitesWithFilter: (OFString *)filter
|
|
||||||
{
|
|
||||||
OFArray<OFString *> *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<OFNumber *, id> *site = _storage[name];
|
|
||||||
|
|
||||||
if (site == nil)
|
|
||||||
@throw [OFInvalidArgumentException exception];
|
|
||||||
|
|
||||||
return [site[lengthField] sizeValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (bool)isSiteLegacy: (OFString *)name
|
|
||||||
{
|
|
||||||
OFDictionary<OFNumber *, id> *site = _storage[name];
|
|
||||||
|
|
||||||
if (site == nil)
|
|
||||||
@throw [OFInvalidArgumentException exception];
|
|
||||||
|
|
||||||
return [site[legacyField] boolValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (OFString *)keyFileForSite: (OFString *)name
|
|
||||||
{
|
|
||||||
OFDictionary<OFNumber *, id> *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
|
|
138
iOS/SiteStorage.swift
Normal file
138
iOS/SiteStorage.swift
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 - 2019 Jonathan Schleifer <js@heap.zone>
|
||||||
|
*
|
||||||
|
* 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<OFString, OFDictionary<OFNumber, AnyObject>>
|
||||||
|
|
||||||
|
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<OFString>
|
||||||
|
|
||||||
|
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<OFString> {
|
||||||
|
// 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<OFNumber, AnyObject>()
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,6 @@
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import ObjFW;
|
#import "PasswordGenerator.h"
|
||||||
|
#import "NewPasswordGenerator.h"
|
||||||
@interface HTTPServerDelegate: OFObject <OFHTTPServerDelegate>
|
#import "LegacyPasswordGenerator.h"
|
||||||
@end
|
|
|
@ -24,7 +24,7 @@
|
||||||
#import <ObjFW/ObjFW.h>
|
#import <ObjFW/ObjFW.h>
|
||||||
#import <ObjFW_Bridge/ObjFW_Bridge.h>
|
#import <ObjFW_Bridge/ObjFW_Bridge.h>
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
#import "scrypt_pwgen-Swift.h"
|
||||||
|
|
||||||
@interface OFAppDelegate: OFObject <OFApplicationDelegate>
|
@interface OFAppDelegate: OFObject <OFApplicationDelegate>
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -7,26 +7,26 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
4B2E52EA1DA942840040D091 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52E81DA942840040D091 /* Main.storyboard */; };
|
||||||
4B2E52EC1DA942840040D091 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52EB1DA942840040D091 /* Assets.xcassets */; };
|
4B2E52EC1DA942840040D091 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52EB1DA942840040D091 /* Assets.xcassets */; };
|
||||||
4B2E52EF1DA942840040D091 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2E52ED1DA942840040D091 /* LaunchScreen.storyboard */; };
|
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 */; };
|
4B9525251F96BB900095F259 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9525231F96BB820095F259 /* ObjFW.framework */; };
|
||||||
4B9525261F96BB900095F259 /* ObjFW_Bridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9525241F96BB820095F259 /* ObjFW_Bridge.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, ); }; };
|
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, ); }; };
|
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"; }; };
|
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"; }; };
|
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 */; };
|
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 */; };
|
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 */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
@ -45,37 +45,30 @@
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
4B0719231DAA78D80065997A /* ShowDetailsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowDetailsController.h; sourceTree = "<group>"; };
|
|
||||||
4B0719241DAA78D80065997A /* ShowDetailsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowDetailsController.m; sourceTree = "<group>"; };
|
|
||||||
4B2E52DC1DA942840040D091 /* scrypt-pwgen.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "scrypt-pwgen.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
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 = "<group>"; };
|
|
||||||
4B2E52E21DA942840040D091 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
|
||||||
4B2E52E31DA942840040D091 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
|
||||||
4B2E52E51DA942840040D091 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = "<group>"; };
|
|
||||||
4B2E52E61DA942840040D091 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = "<group>"; };
|
|
||||||
4B2E52E91DA942840040D091 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
4B2E52E91DA942840040D091 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
4B2E52EB1DA942840040D091 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
4B2E52EB1DA942840040D091 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
4B2E52EE1DA942840040D091 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
4B2E52EE1DA942840040D091 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
4B2E52F01DA942840040D091 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
4B2E52F01DA942840040D091 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
4B82D1131DAAAFCE00F32B2F /* AboutController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutController.h; sourceTree = "<group>"; };
|
4B31D80822B58F0F00494B15 /* SiteStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteStorage.swift; sourceTree = "<group>"; };
|
||||||
4B82D1141DAAAFCE00F32B2F /* AboutController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutController.m; sourceTree = "<group>"; };
|
4B38148322B5ED01005C27B2 /* bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bridge.h; sourceTree = "<group>"; };
|
||||||
|
4B5BCEF822B5B94C00E551BD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
4B5BCEFA22B5CF3200E551BD /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
|
||||||
|
4B5BCEFC22B5D98800E551BD /* SelectKeyFileController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectKeyFileController.swift; sourceTree = "<group>"; };
|
||||||
|
4B5BCEFE22B5E36900E551BD /* ShowDetailsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowDetailsController.swift; sourceTree = "<group>"; };
|
||||||
|
4B93656D22B5ADA00099DD08 /* HTTPServerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPServerDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
4B93656F22B5AE2C0099DD08 /* AboutController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutController.swift; sourceTree = "<group>"; };
|
||||||
|
4B93657122B5B1FB0099DD08 /* AddSiteController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSiteController.swift; sourceTree = "<group>"; };
|
||||||
4B9525231F96BB820095F259 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ObjFW/Frameworks/ObjFW.framework; sourceTree = "<group>"; };
|
4B9525231F96BB820095F259 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ObjFW/Frameworks/ObjFW.framework; sourceTree = "<group>"; };
|
||||||
4B9525241F96BB820095F259 /* ObjFW_Bridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW_Bridge.framework; path = ObjFW/Frameworks/ObjFW_Bridge.framework; sourceTree = "<group>"; };
|
4B9525241F96BB820095F259 /* ObjFW_Bridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW_Bridge.framework; path = ObjFW/Frameworks/ObjFW_Bridge.framework; sourceTree = "<group>"; };
|
||||||
4B9EB1142008167200EB66F2 /* HTTPServerDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTTPServerDelegate.m; sourceTree = "<group>"; };
|
|
||||||
4B9EB1162008168400EB66F2 /* HTTPServerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTTPServerDelegate.h; sourceTree = "<group>"; };
|
|
||||||
4BA115CD1DA9432D007ED4EA /* LegacyPasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LegacyPasswordGenerator.h; path = ../LegacyPasswordGenerator.h; sourceTree = "<group>"; };
|
4BA115CD1DA9432D007ED4EA /* LegacyPasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LegacyPasswordGenerator.h; path = ../LegacyPasswordGenerator.h; sourceTree = "<group>"; };
|
||||||
4BA115CE1DA9432D007ED4EA /* LegacyPasswordGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LegacyPasswordGenerator.m; path = ../LegacyPasswordGenerator.m; sourceTree = "<group>"; };
|
4BA115CE1DA9432D007ED4EA /* LegacyPasswordGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LegacyPasswordGenerator.m; path = ../LegacyPasswordGenerator.m; sourceTree = "<group>"; };
|
||||||
4BA115CF1DA9432D007ED4EA /* NewPasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NewPasswordGenerator.h; path = ../NewPasswordGenerator.h; sourceTree = "<group>"; };
|
4BA115CF1DA9432D007ED4EA /* NewPasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NewPasswordGenerator.h; path = ../NewPasswordGenerator.h; sourceTree = "<group>"; };
|
||||||
4BA115D01DA9432D007ED4EA /* NewPasswordGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NewPasswordGenerator.m; path = ../NewPasswordGenerator.m; sourceTree = "<group>"; };
|
4BA115D01DA9432D007ED4EA /* NewPasswordGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NewPasswordGenerator.m; path = ../NewPasswordGenerator.m; sourceTree = "<group>"; };
|
||||||
4BA115D11DA9432D007ED4EA /* PasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PasswordGenerator.h; path = ../PasswordGenerator.h; sourceTree = "<group>"; };
|
4BA115D11DA9432D007ED4EA /* PasswordGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PasswordGenerator.h; path = ../PasswordGenerator.h; sourceTree = "<group>"; };
|
||||||
4BA115D51DA94390007ED4EA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
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 = "<group>"; };
|
|
||||||
4BB3CDFC1DA9764300FEE5ED /* AddSiteController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddSiteController.m; sourceTree = "<group>"; };
|
|
||||||
4BC29DD41FCB5FAE00A1E786 /* SelectKeyFileController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SelectKeyFileController.m; sourceTree = "<group>"; };
|
|
||||||
4BC29DD61FCB5FC400A1E786 /* SelectKeyFileController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SelectKeyFileController.h; sourceTree = "<group>"; };
|
|
||||||
4BF4ADE91DA9A3DB0073B995 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
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 = "<group>"; };
|
4BF4C39F22B602F50034FCED /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
4BF4ADEC1DA9A6B00073B995 /* SiteStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SiteStorage.m; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -115,26 +108,19 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4B2E52EB1DA942840040D091 /* Assets.xcassets */,
|
4B2E52EB1DA942840040D091 /* Assets.xcassets */,
|
||||||
4B82D1131DAAAFCE00F32B2F /* AboutController.h */,
|
4B93656F22B5AE2C0099DD08 /* AboutController.swift */,
|
||||||
4B82D1141DAAAFCE00F32B2F /* AboutController.m */,
|
4B93657122B5B1FB0099DD08 /* AddSiteController.swift */,
|
||||||
4BB3CDFB1DA9764300FEE5ED /* AddSiteController.h */,
|
4B5BCEF822B5B94C00E551BD /* AppDelegate.swift */,
|
||||||
4BB3CDFC1DA9764300FEE5ED /* AddSiteController.m */,
|
4B93656D22B5ADA00099DD08 /* HTTPServerDelegate.swift */,
|
||||||
4B2E52E21DA942840040D091 /* AppDelegate.h */,
|
|
||||||
4B2E52E31DA942840040D091 /* AppDelegate.m */,
|
|
||||||
4B9EB1162008168400EB66F2 /* HTTPServerDelegate.h */,
|
|
||||||
4B9EB1142008167200EB66F2 /* HTTPServerDelegate.m */,
|
|
||||||
4B2E52F01DA942840040D091 /* Info.plist */,
|
4B2E52F01DA942840040D091 /* Info.plist */,
|
||||||
4B2E52ED1DA942840040D091 /* LaunchScreen.storyboard */,
|
4B2E52ED1DA942840040D091 /* LaunchScreen.storyboard */,
|
||||||
4B2E52E81DA942840040D091 /* Main.storyboard */,
|
4B2E52E81DA942840040D091 /* Main.storyboard */,
|
||||||
4B2E52E51DA942840040D091 /* MainViewController.h */,
|
4B5BCEFA22B5CF3200E551BD /* MainViewController.swift */,
|
||||||
4B2E52E61DA942840040D091 /* MainViewController.m */,
|
4B5BCEFC22B5D98800E551BD /* SelectKeyFileController.swift */,
|
||||||
4BC29DD61FCB5FC400A1E786 /* SelectKeyFileController.h */,
|
4B5BCEFE22B5E36900E551BD /* ShowDetailsController.swift */,
|
||||||
4BC29DD41FCB5FAE00A1E786 /* SelectKeyFileController.m */,
|
4B31D80822B58F0F00494B15 /* SiteStorage.swift */,
|
||||||
4B0719231DAA78D80065997A /* ShowDetailsController.h */,
|
4B38148322B5ED01005C27B2 /* bridge.h */,
|
||||||
4B0719241DAA78D80065997A /* ShowDetailsController.m */,
|
4BF4C39F22B602F50034FCED /* main.m */,
|
||||||
4BF4ADEB1DA9A6B00073B995 /* SiteStorage.h */,
|
|
||||||
4BF4ADEC1DA9A6B00073B995 /* SiteStorage.m */,
|
|
||||||
4B2E52E01DA942840040D091 /* main.m */,
|
|
||||||
);
|
);
|
||||||
name = iOS;
|
name = iOS;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -195,6 +181,7 @@
|
||||||
4B2E52DB1DA942840040D091 = {
|
4B2E52DB1DA942840040D091 = {
|
||||||
CreatedOnToolsVersion = 8.0;
|
CreatedOnToolsVersion = 8.0;
|
||||||
DevelopmentTeam = MXKNFCKFL6;
|
DevelopmentTeam = MXKNFCKFL6;
|
||||||
|
LastSwiftMigration = 1020;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -204,6 +191,7 @@
|
||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
|
English,
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
|
@ -235,17 +223,17 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
4B82D1151DAAAFCE00F32B2F /* AboutController.m in Sources */,
|
4B5BCEF922B5B94C00E551BD /* AppDelegate.swift in Sources */,
|
||||||
4BC29DD51FCB5FAE00A1E786 /* SelectKeyFileController.m in Sources */,
|
4B93656E22B5ADA00099DD08 /* HTTPServerDelegate.swift in Sources */,
|
||||||
4BB3CDFD1DA9764300FEE5ED /* AddSiteController.m in Sources */,
|
4B5BCEFB22B5CF3200E551BD /* MainViewController.swift in Sources */,
|
||||||
4B2E52E41DA942840040D091 /* AppDelegate.m in Sources */,
|
4B93657222B5B1FB0099DD08 /* AddSiteController.swift in Sources */,
|
||||||
4B9EB1152008167200EB66F2 /* HTTPServerDelegate.m in Sources */,
|
|
||||||
4BA115D21DA9432D007ED4EA /* LegacyPasswordGenerator.m in Sources */,
|
4BA115D21DA9432D007ED4EA /* LegacyPasswordGenerator.m in Sources */,
|
||||||
4B2E52E71DA942840040D091 /* MainViewController.m in Sources */,
|
|
||||||
4BA115D31DA9432D007ED4EA /* NewPasswordGenerator.m in Sources */,
|
4BA115D31DA9432D007ED4EA /* NewPasswordGenerator.m in Sources */,
|
||||||
4B0719251DAA78D80065997A /* ShowDetailsController.m in Sources */,
|
4B31D80922B58F0F00494B15 /* SiteStorage.swift in Sources */,
|
||||||
4BF4ADED1DA9A6B00073B995 /* SiteStorage.m in Sources */,
|
4B5BCEFD22B5D98800E551BD /* SelectKeyFileController.swift in Sources */,
|
||||||
4B2E52E11DA942840040D091 /* main.m in Sources */,
|
4B5BCEFF22B5E36900E551BD /* ShowDetailsController.swift in Sources */,
|
||||||
|
4BF4C3A022B602F50034FCED /* main.m in Sources */,
|
||||||
|
4B93657022B5AE2C0099DD08 /* AboutController.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -390,8 +378,12 @@
|
||||||
);
|
);
|
||||||
HEADER_SEARCH_PATHS = ObjFW/include;
|
HEADER_SEARCH_PATHS = ObjFW/include;
|
||||||
INFOPLIST_FILE = Info.plist;
|
INFOPLIST_FILE = Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "zone.heap.scrypt-pwgen.ios";
|
PRODUCT_BUNDLE_IDENTIFIER = "zone.heap.scrypt-pwgen.ios";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = bridge.h;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
@ -411,8 +403,11 @@
|
||||||
);
|
);
|
||||||
HEADER_SEARCH_PATHS = ObjFW/include;
|
HEADER_SEARCH_PATHS = ObjFW/include;
|
||||||
INFOPLIST_FILE = Info.plist;
|
INFOPLIST_FILE = Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "zone.heap.scrypt-pwgen.ios";
|
PRODUCT_BUNDLE_IDENTIFIER = "zone.heap.scrypt-pwgen.ios";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = bridge.h;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue