Commit 7ca4866f authored by Carola Nitz's avatar Carola Nitz

PAPasscode: use the pod instead of individual files and added error handling

parent 909f1d64
//Copyright (c) 2012, Denis Hennessy (Peer Assembly - http://peerassembly.com)
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Peer Assembly, Denis Hennessy nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
//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 PEER ASSEMBLY OR DENIS HENNESSY 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/UIKit.h>
typedef enum {
PasscodeActionSet,
PasscodeActionEnter,
PasscodeActionChange
} PasscodeAction;
@class PAPasscodeViewController;
@protocol PAPasscodeViewControllerDelegate <NSObject>
@optional
- (void)PAPasscodeViewControllerDidCancel:(PAPasscodeViewController *)controller;
- (void)PAPasscodeViewControllerDidChangePasscode:(PAPasscodeViewController *)controller;
- (void)PAPasscodeViewControllerDidEnterAlternativePasscode:(PAPasscodeViewController *)controller;
- (void)PAPasscodeViewControllerDidEnterPasscode:(PAPasscodeViewController *)controller;
- (void)PAPasscodeViewControllerDidSetPasscode:(PAPasscodeViewController *)controller;
- (void)PAPasscodeViewController:(PAPasscodeViewController *)controller didFailToEnterPasscode:(NSInteger)attempts;
@end
@interface PAPasscodeViewController : UIViewController {
UIView *contentView;
NSInteger phase;
UILabel *promptLabel;
UILabel *messageLabel;
UIImageView *failedImageView;
UILabel *failedAttemptsLabel;
UITextField *passcodeTextField;
UIImageView *digitImageViews[4];
UIImageView *snapshotImageView;
}
@property (strong) UIView *backgroundView;
@property (readonly) PasscodeAction action;
@property (weak) id<PAPasscodeViewControllerDelegate> delegate;
@property (strong) NSString *alternativePasscode;
@property (strong) NSString *passcode;
@property (assign) BOOL simple;
@property (assign) NSInteger failedAttempts;
@property (strong) NSString *enterPrompt;
@property (strong) NSString *confirmPrompt;
@property (strong) NSString *changePrompt;
@property (strong) NSString *message;
- (id)initForAction:(PasscodeAction)action;
@end
//Copyright (c) 2012, Denis Hennessy (Peer Assembly - http://peerassembly.com)
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Peer Assembly, Denis Hennessy nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
//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 PEER ASSEMBLY OR DENIS HENNESSY 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 <QuartzCore/QuartzCore.h>
#import "PAPasscodeViewController.h"
#define NAVBAR_HEIGHT 66
#define PROMPT_HEIGHT 90
#define DIGIT_SPACING 25
#define DIGIT_WIDTH 19
#define DIGIT_HEIGHT 1
#define MARKER_WIDTH 16
#define MARKER_HEIGHT 1
#define MARKER_X 1.5
#define MARKER_Y -18
#define MESSAGE_HEIGHT 90
#define FAILED_LCAP 19
#define FAILED_RCAP 19
#define FAILED_HEIGHT 26
#define FAILED_MARGIN 10
#define TEXTFIELD_MARGIN 8
#define SLIDE_DURATION 0.3
@interface PAPasscodeViewController ()
- (void)cancel:(id)sender;
- (void)handleFailedAttempt;
- (void)handleCompleteField;
- (void)passcodeChanged:(id)sender;
- (void)resetFailedAttempts;
- (void)showFailedAttempts;
- (void)showScreenForPhase:(NSInteger)phase animated:(BOOL)animated;
@end
@implementation PAPasscodeViewController
- (id)initForAction:(PasscodeAction)action {
self = [super init];
if (self) {
_action = action;
switch (action) {
case PasscodeActionSet:
self.title = NSLocalizedString(@"PASSCODE_SET", nil);
_enterPrompt = NSLocalizedString(@"ENTER_PASSCODE", nil);
_confirmPrompt = NSLocalizedString(@"REENTER_PASSCODE", nil);
break;
case PasscodeActionEnter:
self.title = NSLocalizedString(@"ENTER_PASSCODE", nil);
_enterPrompt = NSLocalizedString(@"ENTER_PASSCODE", nil);
break;
case PasscodeActionChange:
self.title = NSLocalizedString(@"PASSCODE_CHANGE", nil);
_changePrompt = NSLocalizedString(@"PASSCODE_ENTER_OLD", nil);
_enterPrompt = NSLocalizedString(@"PASSCODE_ENTER_NEW", nil);
_confirmPrompt = NSLocalizedString(@"PASSCODE_REENTER_NEW", nil);
break;
}
self.modalPresentationStyle = UIModalPresentationFormSheet;
_simple = YES;
}
return self;
}
- (void)loadView {
UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.navigationController.navigationBarHidden = YES;
UINavigationBar *navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, view.bounds.size.width, NAVBAR_HEIGHT)];
navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
navigationBar.items = @[self.navigationItem];
navigationBar.barTintColor = [UIColor VLCOrangeTintColor];
navigationBar.tintColor = [UIColor whiteColor];
navigationBar.titleTextAttributes = @{ NSForegroundColorAttributeName : [UIColor whiteColor] };
[view addSubview:navigationBar];
contentView = [[UIView alloc] initWithFrame:CGRectMake(0, NAVBAR_HEIGHT, view.bounds.size.width, view.bounds.size.height-NAVBAR_HEIGHT)];
contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
if (_backgroundView) {
[contentView addSubview:_backgroundView];
}
contentView.backgroundColor = [UIColor VLCDarkBackgroundColor];
[view addSubview:contentView];
CGFloat panelWidth = DIGIT_WIDTH*4+DIGIT_SPACING*3;
if (_simple) {
UIView *digitPanel = [[UIView alloc] initWithFrame:CGRectMake(0, 0, panelWidth, DIGIT_HEIGHT)];
digitPanel.frame = CGRectOffset(digitPanel.frame, (contentView.bounds.size.width - panelWidth) / 2., PROMPT_HEIGHT);
digitPanel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
[contentView addSubview:digitPanel];
UIImage *backgroundImage = [UIImage imageNamed:@"papasscode_background"];
UIImage *markerImage = [UIImage imageNamed:@"papasscode_marker"];
CGFloat xLeft = 0;
for (int i=0;i<4;i++) {
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage];
backgroundImageView.frame = CGRectOffset(backgroundImageView.frame, xLeft, 0);
[digitPanel addSubview:backgroundImageView];
digitImageViews[i] = [[UIImageView alloc] initWithImage:markerImage];
digitImageViews[i].autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
digitImageViews[i].frame = CGRectOffset(digitImageViews[i].frame, backgroundImageView.frame.origin.x+MARKER_X, MARKER_Y);
[digitPanel addSubview:digitImageViews[i]];
xLeft += DIGIT_SPACING + backgroundImage.size.width;
}
passcodeTextField = [[UITextField alloc] initWithFrame:digitPanel.frame];
passcodeTextField.hidden = YES;
} else {
UIView *passcodePanel = [[UIView alloc] initWithFrame:CGRectMake(0, 0, panelWidth, DIGIT_HEIGHT)];
passcodePanel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
passcodePanel.frame = CGRectOffset(passcodePanel.frame, (contentView.bounds.size.width-passcodePanel.bounds.size.width)/2, PROMPT_HEIGHT);
passcodePanel.frame = CGRectInset(passcodePanel.frame, TEXTFIELD_MARGIN, TEXTFIELD_MARGIN);
passcodePanel.layer.borderColor = [UIColor colorWithRed:0.65 green:0.67 blue:0.70 alpha:1.0].CGColor;
passcodePanel.layer.borderWidth = 1.0;
passcodePanel.layer.cornerRadius = 5.0;
passcodePanel.layer.shadowColor = [UIColor whiteColor].CGColor;
passcodePanel.layer.shadowOffset = CGSizeMake(0, 1);
passcodePanel.layer.shadowOpacity = 1.0;
passcodePanel.layer.shadowRadius = 1.0;
passcodePanel.backgroundColor = [UIColor whiteColor];
[contentView addSubview:passcodePanel];
passcodeTextField = [[UITextField alloc] initWithFrame:CGRectInset(passcodePanel.frame, 6, 6)];
}
passcodeTextField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
passcodeTextField.borderStyle = UITextBorderStyleNone;
passcodeTextField.secureTextEntry = YES;
passcodeTextField.textColor = [UIColor colorWithRed:0.23 green:0.33 blue:0.52 alpha:1.0];
passcodeTextField.keyboardType = UIKeyboardTypeNumberPad;
[passcodeTextField addTarget:self action:@selector(passcodeChanged:) forControlEvents:UIControlEventEditingChanged];
[contentView addSubview:passcodeTextField];
promptLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, contentView.bounds.size.width, PROMPT_HEIGHT)];
promptLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
promptLabel.backgroundColor = [UIColor clearColor];
promptLabel.textColor = [UIColor VLCLightTextColor];
promptLabel.font = [UIFont boldSystemFontOfSize:17];
promptLabel.shadowColor = [UIColor VLCDarkTextShadowColor];
promptLabel.shadowOffset = CGSizeMake(0, 1);
promptLabel.textAlignment = NSTextAlignmentCenter;
promptLabel.numberOfLines = 0;
[contentView addSubview:promptLabel];
messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, PROMPT_HEIGHT+DIGIT_HEIGHT, contentView.bounds.size.width, MESSAGE_HEIGHT)];
messageLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
messageLabel.backgroundColor = [UIColor clearColor];
messageLabel.textColor = [UIColor VLCLightTextColor];
messageLabel.font = [UIFont boldSystemFontOfSize:14];
messageLabel.shadowColor = [UIColor VLCDarkTextShadowColor];
messageLabel.shadowOffset = CGSizeMake(0, 1);
messageLabel.textAlignment = NSTextAlignmentCenter;
messageLabel.numberOfLines = 0;
messageLabel.text = _message;
[contentView addSubview:messageLabel];
UIImage *failedBg = [[UIImage imageNamed:@"papasscode_failed_bg"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, FAILED_LCAP, 0, FAILED_RCAP)];
failedImageView = [[UIImageView alloc] initWithImage:failedBg];
failedImageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
failedImageView.hidden = YES;
[contentView addSubview:failedImageView];
failedAttemptsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
failedAttemptsLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
failedAttemptsLabel.backgroundColor = [UIColor clearColor];
failedAttemptsLabel.textColor = [UIColor whiteColor];
failedAttemptsLabel.font = [UIFont boldSystemFontOfSize:15];
failedAttemptsLabel.shadowColor = [UIColor blackColor];
failedAttemptsLabel.shadowOffset = CGSizeMake(0, -1);
failedAttemptsLabel.textAlignment = NSTextAlignmentCenter;
failedAttemptsLabel.hidden = YES;
[contentView addSubview:failedAttemptsLabel];
self.view = view;
}
- (void)viewDidLoad {
[super viewDidLoad];
if ([_delegate respondsToSelector:@selector(PAPasscodeViewControllerDidCancel:)]) {
if (_simple) {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel:)];
} else {
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel:)];
}
}
if (_failedAttempts > 0) {
[self showFailedAttempts];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self showScreenForPhase:0 animated:NO];
[passcodeTextField becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[passcodeTextField resignFirstResponder];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (void)cancel:(id)sender {
[_delegate PAPasscodeViewControllerDidCancel:self];
}
#pragma mark - implementation helpers
- (void)handleCompleteField {
NSString *text = passcodeTextField.text;
switch (_action) {
case PasscodeActionSet:
if (phase == 0) {
_passcode = text;
messageLabel.text = @"";
[self showScreenForPhase:1 animated:YES];
} else {
if ([text isEqualToString:_passcode]) {
if ([_delegate respondsToSelector:@selector(PAPasscodeViewControllerDidSetPasscode:)]) {
[_delegate PAPasscodeViewControllerDidSetPasscode:self];
}
} else {
[self showScreenForPhase:0 animated:YES];
messageLabel.text = NSLocalizedString(@"PASSCODES_DID_NOT_MATCH", nil);
}
}
break;
case PasscodeActionEnter:
if ([text isEqualToString:_passcode]) {
[self resetFailedAttempts];
if ([_delegate respondsToSelector:@selector(PAPasscodeViewControllerDidEnterPasscode:)]) {
[_delegate PAPasscodeViewControllerDidEnterPasscode:self];
}
} else {
if (_alternativePasscode && [text isEqualToString:_alternativePasscode]) {
[self resetFailedAttempts];
if ([_delegate respondsToSelector:@selector(PAPasscodeViewControllerDidEnterAlternativePasscode:)]) {
[_delegate PAPasscodeViewControllerDidEnterAlternativePasscode:self];
}
} else {
[self handleFailedAttempt];
[self showScreenForPhase:0 animated:NO];
}
}
break;
case PasscodeActionChange:
if (phase == 0) {
if ([text isEqualToString:_passcode]) {
[self resetFailedAttempts];
[self showScreenForPhase:1 animated:YES];
} else {
[self handleFailedAttempt];
[self showScreenForPhase:0 animated:NO];
}
} else if (phase == 1) {
_passcode = text;
messageLabel.text = @"";
[self showScreenForPhase:2 animated:YES];
} else {
if ([text isEqualToString:_passcode]) {
if ([_delegate respondsToSelector:@selector(PAPasscodeViewControllerDidChangePasscode:)]) {
[_delegate PAPasscodeViewControllerDidChangePasscode:self];
}
} else {
[self showScreenForPhase:1 animated:YES];
messageLabel.text = NSLocalizedString(@"PASSCODES_DID_NOT_MATCH", nil);
}
}
break;
}
}
- (void)handleFailedAttempt {
_failedAttempts++;
[self showFailedAttempts];
if ([_delegate respondsToSelector:@selector(PAPasscodeViewController:didFailToEnterPasscode:)]) {
[_delegate PAPasscodeViewController:self didFailToEnterPasscode:_failedAttempts];
}
}
- (void)resetFailedAttempts {
messageLabel.hidden = NO;
failedImageView.hidden = YES;
failedAttemptsLabel.hidden = YES;
_failedAttempts = 0;
}
- (void)showFailedAttempts {
messageLabel.hidden = YES;
failedImageView.hidden = NO;
failedAttemptsLabel.hidden = NO;
if (_failedAttempts == 1) {
failedAttemptsLabel.text = NSLocalizedString(@"PASSCODE_FAILED_1", nil);
} else {
failedAttemptsLabel.text = [NSString stringWithFormat:NSLocalizedString(@"PASSCODE_FAILED_FORMAT", nil), _failedAttempts];
}
[failedAttemptsLabel sizeToFit];
CGFloat bgWidth = failedAttemptsLabel.bounds.size.width + FAILED_MARGIN*2;
CGFloat x = floor((contentView.bounds.size.width-bgWidth)/2);
CGFloat y = PROMPT_HEIGHT+DIGIT_HEIGHT+floor((MESSAGE_HEIGHT-FAILED_HEIGHT)/2);
failedImageView.frame = CGRectMake(x, y, bgWidth, FAILED_HEIGHT);
x = failedImageView.frame.origin.x+FAILED_MARGIN;
y = failedImageView.frame.origin.y+floor((failedImageView.bounds.size.height-failedAttemptsLabel.frame.size.height)/2);
failedAttemptsLabel.frame = CGRectMake(x, y, failedAttemptsLabel.bounds.size.width, failedAttemptsLabel.bounds.size.height);
}
- (void)passcodeChanged:(id)sender {
NSString *text = passcodeTextField.text;
if (_simple) {
if ([text length] > 4) {
text = [text substringToIndex:4];
}
for (int i=0;i<4;i++) {
digitImageViews[i].hidden = i >= [text length];
}
if ([text length] == 4) {
[self handleCompleteField];
}
} else {
self.navigationItem.rightBarButtonItem.enabled = [text length] > 0;
}
}
- (void)showScreenForPhase:(NSInteger)newPhase animated:(BOOL)animated {
CGFloat dir = (newPhase > phase) ? 1 : -1;
if (animated) {
UIGraphicsBeginImageContext(self.view.bounds.size);
[contentView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
snapshotImageView = [[UIImageView alloc] initWithImage:snapshot];
snapshotImageView.frame = CGRectOffset(snapshotImageView.frame, -contentView.frame.size.width*dir, 0);
[contentView addSubview:snapshotImageView];
}
phase = newPhase;
passcodeTextField.text = @"";
if (!_simple) {
BOOL finalScreen = _action == PasscodeActionSet && phase == 1;
finalScreen |= _action == PasscodeActionEnter && phase == 0;
finalScreen |= _action == PasscodeActionChange && phase == 2;
if (finalScreen) {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(handleCompleteField)];
} else {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"BUTTON_NEXT", nil) style:UIBarButtonItemStylePlain target:self action:@selector(handleCompleteField)];
}
self.navigationItem.rightBarButtonItem.enabled = NO;
}
switch (_action) {
case PasscodeActionSet:
if (phase == 0) {
promptLabel.text = _enterPrompt;
} else {
promptLabel.text = _confirmPrompt;
}
break;
case PasscodeActionEnter:
promptLabel.text = _enterPrompt;
break;
case PasscodeActionChange:
if (phase == 0) {
promptLabel.text = _changePrompt;
} else if (phase == 1) {
promptLabel.text = _enterPrompt;
} else {
promptLabel.text = _confirmPrompt;
}
break;
}
for (int i=0;i<4;i++) {
digitImageViews[i].hidden = YES;
}
if (animated) {
contentView.frame = CGRectOffset(contentView.frame, contentView.frame.size.width*dir, 0);
[UIView animateWithDuration:SLIDE_DURATION animations:^() {
contentView.frame = CGRectOffset(contentView.frame, -contentView.frame.size.width*dir, 0);
} completion:^(BOOL finished) {
[snapshotImageView removeFromSuperview];
snapshotImageView = nil;
}];
}
}
@end
......@@ -15,6 +15,7 @@ pod 'XKKeychain', '~>1.0'
pod 'box-ios-sdk-v2', :git => 'git://github.com/fkuehne/box-ios-sdk-v2.git' #has a logout function added
pod 'CocoaHTTPServer', :git => 'git://github.com/fkuehne/CocoaHTTPServer.git' # has our fixes
pod 'RESideMenu', '~>4.0.7'
pod 'PAPasscode', '~>1.0'
pod 'GoogleAPIClient/Drive'
pod 'VLC-LXReorderableCollectionViewFlowLayout', '0.1.3v'
pod 'VLC-WhiteRaccoon'
......@@ -36,6 +37,7 @@ pod 'XKKeychain', '~>1.0'
pod 'box-ios-sdk-v2', :git => 'git://github.com/fkuehne/box-ios-sdk-v2.git' #has a logout function added
pod 'CocoaHTTPServer', :git => 'git://github.com/fkuehne/CocoaHTTPServer.git' # has our fixes
pod 'RESideMenu', '~>4.0.7'
pod 'PAPasscode', '~>1.0'
pod 'GoogleAPIClient/Drive'
pod 'VLC-LXReorderableCollectionViewFlowLayout', '0.1.3v'
pod 'VLC-WhiteRaccoon'
......
......@@ -48,6 +48,7 @@ PODS:
- OROpenSubtitleDownloader (1.2.0):
- AFNetworking
- xmlrpc
- PAPasscode (1.0)
- RESideMenu (4.0.7)
- TVVLCKit-unstable (3.0.0a49)
- upnpx (1.4.0)
......@@ -73,6 +74,7 @@ DEPENDENCIES:
- ObjectiveDropboxOfficial (from `git://github.com/carolanitz/dropbox-sdk-obj-c.git`)
- OBSlider (= 1.1.0)
- OROpenSubtitleDownloader (from `https://github.com/orta/OROpenSubtitleDownloader.git`, commit `0509eac2`)
- PAPasscode (~> 1.0)
- RESideMenu (~> 4.0.7)
- TVVLCKit-unstable (= 3.0.0a49)
- upnpx (~> 1.4.0)
......@@ -131,6 +133,7 @@ SPEC CHECKSUMS:
ObjectiveDropboxOfficial: e11cdf40e8965a6c24c6d6ff64905f2df43ab653
OBSlider: 490f108007bfdd5414a38650b211fe403a95b8a0
OROpenSubtitleDownloader: 154b8c08acbf8836b77ac259018dc8b5baef907e
PAPasscode: b408fb87c530cad58a554e26482e87dbb14b7bc2
RESideMenu: f24c508404b49c667344c54aba7e590883533958
TVVLCKit-unstable: 76643469a2fe5186589a14fbf35bdf893bba70e5
upnpx: c695b99229e08154d23abe5c252cb64f1600f35d
......@@ -140,6 +143,6 @@ SPEC CHECKSUMS:
XKKeychain: 852ef663c56a7194c73d3c68e8d9d4f07b121d4f
xmlrpc: 109bb21d15ed6d108b2c1ac5973a6a223a50f5f4
PODFILE CHECKSUM: 141583cd82da54cc43bba4409eac6dabe5693aed
PODFILE CHECKSUM: 7c967ad3372558a99553f8a73764e93070dc1055
COCOAPODS: 1.3.1
......@@ -20,5 +20,21 @@ NSLocalizedString(@"SECTION_HEADER_NETWORK", nil);
NSLocalizedString(@"THIS_FILE", nil);
NSLocalizedString(@"NOT_SUPPORTED_FILETYPE", nil);
NSLocalizedString(@"FILE_EXISTS", nil);
NSLocalizedString(@"BIOMETRIC_UNLOCK", nil);
//These Strings are in PAPasscode and we need to translate them
NSLocalizedString(@"Set Passcode", nil);
NSLocalizedString(@"Enter a passcode", nil);
NSLocalizedString(@"Re-enter your passcode", nil);
NSLocalizedString(@"Enter Passcode", nil);
NSLocalizedString(@"Enter your passcode", nil);
NSLocalizedString(@"Passcodes did not match. Try again.", nil);
NSLocalizedString(@"Change Passcode", nil);
NSLocalizedString(@"Enter your old passcode", nil);
NSLocalizedString(@"Enter your new passcode", nil);
NSLocalizedString(@"Re-enter your new passcode", nil);
NSLocalizedString(@"Passcodes did not match. Try again.", nil);
NSLocalizedString(@"1 Failed Passcode Attempt", nil);
NSLocalizedString(@"%d Failed Passcode Attempts", nil);
NSLocalizedString(@"Next", nil);
}
......@@ -59,7 +59,6 @@
"BUTTON_DOWNLOAD" = "Download";
"BUTTON_DELETE" = "Delete";
"BUTTON_OK" = "OK";
"BUTTON_NEXT" = "Next";
"BUTTON_CONTRIBUTE" = "Contribute";
"BUTTON_CONNECT" = "Connect";
"BUTTON_RENAME" = "Rename";
......@@ -163,18 +162,23 @@
"NO_FILES" = "No supported files";
"DOWNLOADING" = "Downloading...";
"REMAINING_TIME" = "Remaining time: %@";
"ENTER_PASSCODE" = "Enter Passcode";
"REENTER_PASSCODE" = "Re-enter Passcode";
"PASSCODE_SET" = "Set Passcode";
"PASSCODE_CHANGE" = "Change Passcode";
"PASSCODE_ENTER_OLD" = "Enter your old passcode";
"PASSCODE_ENTER_NEW" = "Enter your new passcode";
"PASSCODE_REENTER_NEW" = "Re-enter your new passcode";
"PASSCODES_DID_NOT_MATCH" = "Passcodes did not match. Try again.";
"PASSCODE_FAILED_1" = "1 Failed Passcode Attempt";
"PASSCODE_FAILED_FORMAT" = "%d Failed Passcode Attempts";
"BIOMETRIC_UNLOCK" = "Unlock Media Library\nCancel to enter Passcode";
//PAPasscode Strings that we need to localize for them
"%d Failed Passcode Attempts" = "%d Failed Passcode Attempts";
"1 Failed Passcode Attempt" = "1 Failed Passcode Attempt";
"Change Passcode" = "Change Passcode";
"Enter Passcode" = "Enter Passcode";
"Enter a passcode" = "Enter a passcode";
"Enter your new passcode" = "Enter your new passcode";
"Enter your old passcode" = "Enter your old passcode";
"Enter your passcode" = "Enter your passcode";
"Next" = "Next";
"Passcodes did not match. Try again." = "Passcodes did not match. Try again.";
"Re-enter your new passcode" = "Re-enter your new passcode";
"Re-enter your passcode" = "Re-enter your passcode";
"Set Passcode" = "Set Passcode";
"Settings" = "Settings"; // plain text key to keep compatibility with InAppSettingsKit's upstream
"ON" = "On";
"OFF" = "Off";
......@@ -332,4 +336,3 @@
/* New strings */
"PROTOCOL_NOT_SELECTED" = "PROTOCOL_NOT_SELECTED";
"Settings" = "Settings";
......@@ -33,27 +33,35 @@ class KeychainCoordinator:NSObject, PAPasscodeViewControllerDelegate {
private var avoidPromptingTouchOrFaceID = false
private var passcodeLockController:PAPasscodeViewController {
let passcodeController = PAPasscodeViewController()
passcodeController.delegate = self
return passcodeController
}
private lazy var passcodeLockController:PAPasscodeViewController = {
let passcodeController = PAPasscodeViewController(for: PasscodeActionEnter)
passcodeController!.delegate = self
return passcodeController!
}()
override init() {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(appInForeground), name: .UIApplicationDidBecomeActive, object: nil)
}
@objc class func setPasscode(passcode:String?) {
@objc class func setPasscode(passcode:String?) throws {
guard let passcode = passcode else {
try? XKKeychainGenericPasswordItem.removeItems(forService: passcodeService)
do {
try XKKeychainGenericPasswordItem.removeItems(forService: passcodeService)
} catch let error {
throw error
}
return
}
let keychainItem = XKKeychainGenericPasswordItem()
keychainItem.service = passcodeService
keychainItem.account = passcodeService
keychainItem.secret.stringValue = passcode
try? keychainItem.save()
do {
try keychainItem.save()
} catch let error {
throw error
}
}
@objc func validatePasscode(completion:@escaping ()->()) {
......@@ -68,6 +76,7 @@ class KeychainCoordinator:NSObject, PAPasscodeViewControllerDelegate {
let navigationController = UINavigationController(rootViewController: passcodeLockController)
navigationController.modalPresentationStyle = .fullScreen
navigationController.modalTransitionStyle = .crossDissolve
rootViewController.present(navigationController, animated: true) {
[weak self] in
......@@ -111,8 +120,11 @@ class KeychainCoordinator:NSObject, PAPasscodeViewControllerDelegate {
}
private func passcodeFromKeychain() -> String {
let item = try? XKKeychainGenericPasswordItem(forService: KeychainCoordinator.passcodeService, account: KeychainCoordinator.passcodeService)
return item?.secret?.stringValue ?? ""
if let item = try? XKKeychainGenericPasswordItem(forService: KeychainCoordinator.passcodeService, account: KeychainCoordinator.passcodeService) {
return item.secret.stringValue
}
assert(false, "Couldn't retrieve item from Keychain! If passcodeLockEnabled we should have an item and secret")
return ""
}
//MARK: PAPassCodeDelegate
......
......@@ -128,12 +128,15 @@
- (void)updateForPasscode:(NSString *)passcode
{
if (passcode == nil) {
//Set manually the value to NO to disable the UISwitch.
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:kVLCSettingPasscodeOnKey];
NSError *error = nil;
[VLCKeychainCoordinator setPasscodeWithPasscode:passcode error:&error];
if (error == nil) {
if (passcode == nil) {
//Set manually the value to NO to disable the UISwitch.
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:kVLCSettingPasscodeOnKey];
}
[self updateUIAndCoreSpotlightForPasscodeSetting:passcode != nil];
}
[VLCKeychainCoordinator setPasscodeWithPasscode:passcode];
[self updateUIAndCoreSpotlightForPasscodeSetting:passcode != nil];
if ([self.navigationController.presentedViewController isKindOfClass:[PAPasscodeViewController class]]) {
[self.navigationController.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
......
......@@ -6,6 +6,6 @@
#import "VLCPlaylistTableViewCell.h"
#import "VLCMediaDataSource.h"
#import "VLCLibraryViewController.h"
#import "PAPasscodeViewController.h"
#import <PAPasscode/PAPasscodeViewController.h>
#import <XKKeychain/XKKeychain.h>
#import "VLCConstants.h"