Statistics
| Branch: | Tag: | Revision:

root / Classes / PasscodeViewController.m @ 7db1712d

History | View | Annotate | Download (33.3 kB)

1
//
2
//  PasscodeViewController.m
3
//  OpenStack
4
//
5
//  Created by Mike Mayo on 10/26/10.
6
//  The OpenStack project is provided under the Apache 2.0 license.
7
//
8

    
9
#import "PasscodeViewController.h"
10
#import "UIViewController+Conveniences.h"
11
#import "UIColor+MoreColors.h"
12
#import "Keychain.h"
13
#import "PasscodeLockViewController.h"
14
#import "SettingsViewController.h"
15
#import <QuartzCore/QuartzCore.h>
16
#import "Archiver.h"
17
#import "RootViewController.h"
18
#import "OpenStackAccount.h"
19
#import "AccountHomeViewController.h"
20
#import "OpenStackAppDelegate.h"
21

    
22

    
23
@implementation PasscodeViewController
24

    
25
@synthesize mode, passcodeLockViewController, settingsViewController, rootViewController, accountHomeViewController;
26

    
27
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
28
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
29
}
30

    
31
- (UITextField *)allocAndInitPasscodeTextField {
32
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(29.0, 13.0, 271.0, 24.0)];
33
    textField.text = @"";
34
    textField.textColor = [UIColor value1DetailTextLabelColor];
35
    textField.secureTextEntry = YES;
36
    textField.delegate = self;
37
    
38
    textField.keyboardAppearance = UIKeyboardAppearanceAlert;
39
    
40
    return textField;
41
}
42

    
43
- (void)addNextButton {
44
    if (!simplePasscodeOn) {
45
        UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" style:UIBarButtonItemStyleBordered target:self action:@selector(nextButtonPressed:)];
46
        self.navigationItem.rightBarButtonItem = nextButton;
47
        [nextButton release];
48
    }
49
}
50

    
51
- (void)addDoneButton {
52
    if (!simplePasscodeOn) {
53
        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)];
54
        self.navigationItem.rightBarButtonItem = doneButton;
55
        [doneButton release];
56
    }
57
}
58

    
59
- (void)incrementAndShowFailedAttemptsLabel {
60
    enterPasscodeTextField.text = @"";
61
    if (simplePasscodeOn) {
62
        for (int i = 0; i < 4; i++) {
63
            [[[squares objectAtIndex:tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]];
64
        }    
65
    }
66
    
67
    failedAttemptsCount += 1;
68
    if (failedAttemptsCount == 1) {
69
        failedAttemptsLabel.text = @"1 Failed Passcode Attempt";
70
    } else {
71
        failedAttemptsLabel.text = [NSString stringWithFormat:@"%i Failed Passcode Attempts", failedAttemptsCount];
72
    }
73
    CGSize size = [failedAttemptsLabel.text sizeWithFont:[UIFont boldSystemFontOfSize:14.0]];
74
    failedAttemptsView.frame = CGRectMake((viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0);
75
    failedAttemptsLabel.frame = CGRectMake((viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0); 
76
    
77
    CAGradientLayer *gradient = [CAGradientLayer layer];
78
    gradient.frame = failedAttemptsView.bounds;        
79
    gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.714 green:0.043 blue:0.043 alpha:1.0] CGColor], 
80
                       (id)[[UIColor colorWithRed:0.761 green:0.192 blue:0.192 alpha:1.0] CGColor], nil];
81
    [failedAttemptsView.layer insertSublayer:gradient atIndex:0];
82
    failedAttemptsView.layer.masksToBounds = YES;
83
    
84
    failedAttemptsLabel.hidden = NO;
85
    failedAttemptsView.hidden = NO;
86
    
87
    if (failedAttemptsCount == 10 && eraseData) {
88
        [Archiver deleteEverything];
89
        [OpenStackAccount persist:[NSMutableArray array]];        
90
        if ([Keychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]) {
91
            [Keychain setString:@"" forKey:@"passcode_lock_passcode"];
92
        }        
93
        [self dismissModalViewControllerAnimated:YES];
94
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
95
            [UIView beginAnimations:@"fadeIn" context:nil];
96
            [UIView setAnimationDelay:0.25];
97
            [UIView setAnimationDuration:0.5];
98
            OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
99
            for (UIViewController *svc in app.splitViewController.viewControllers) {
100
                svc.view.alpha = 1.0;
101
            }
102
            [UIView commitAnimations];
103
        }
104
        
105
        [self alert:@"" message:@"You have entered an incorrect passcode too many times. All account data in this app has been deleted."];
106
        if (self.rootViewController) {
107
            [self.rootViewController.navigationController popToRootViewControllerAnimated:NO];
108
            [self.rootViewController.tableView reloadData];
109
        }
110
    }
111
    
112
}
113

    
114
- (void)moveToNextTableView {
115
    tableIndex += 1;
116
    UITableView *oldTableView = [tableViews objectAtIndex:tableIndex - 1];
117
    UITableView *newTableView = [tableViews objectAtIndex:tableIndex];
118
    newTableView.frame = CGRectMake(oldTableView.frame.origin.x + viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height);
119
    
120
    if (simplePasscodeOn) {
121
        for (int i = 0; i < 4; i++) {
122
            [[[squares objectAtIndex:tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]];
123
        }    
124
    }
125
    
126
    [UIView beginAnimations:@"" context:nil];
127
    [UIView setAnimationDuration:0.25];                    
128
    oldTableView.frame = CGRectMake(oldTableView.frame.origin.x - viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height);
129
    newTableView.frame = self.view.frame;
130
    [UIView commitAnimations];
131
    
132
    if (tableIndex == [tableViews count] - 1) {
133
        [self addDoneButton];
134
    } else {
135
        [self addNextButton];
136
    }
137
    
138
    [[textFields objectAtIndex:tableIndex - 1] resignFirstResponder];
139
    [[textFields objectAtIndex:tableIndex] becomeFirstResponder];
140
}
141

    
142
- (void)moveToPreviousTableView {
143
    tableIndex -= 1;
144
    UITableView *oldTableView = [tableViews objectAtIndex:tableIndex + 1];
145
    UITableView *newTableView = [tableViews objectAtIndex:tableIndex];
146
    newTableView.frame = CGRectMake(oldTableView.frame.origin.x - viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height);
147
    
148
    if (simplePasscodeOn) {
149
        for (int i = 0; i < 4; i++) {
150
            [[[squares objectAtIndex:tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]];
151
        }    
152
    }
153
    
154
    [UIView beginAnimations:@"" context:nil];
155
    [UIView setAnimationDuration:0.25];                    
156
    oldTableView.frame = CGRectMake(oldTableView.frame.origin.x + viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height);
157
    newTableView.frame = self.view.frame;
158
    [UIView commitAnimations];
159
    
160
    if (tableIndex == [tableViews count] - 1) {
161
        [self addDoneButton];
162
    } else {
163
        [self addNextButton];
164
    }
165
    
166
    [[textFields objectAtIndex:tableIndex + 1] resignFirstResponder];
167
    [[textFields objectAtIndex:tableIndex] becomeFirstResponder];
168
}
169

    
170
- (void)nextButtonPressed:(id)sender {
171
    
172
    UITextField *textField = [textFields objectAtIndex:tableIndex];
173
    
174
    if (![textField.text isEqualToString:@""]) {
175
        
176
        if (mode == kModeSetPasscode) {
177
            if ([textField isEqual:setPasscodeTextField]) {
178
                [self moveToNextTableView];
179
            } else if ([textField isEqual:confirmPasscodeTextField]) {
180
                if (![confirmPasscodeTextField.text isEqualToString:setPasscodeTextField.text]) {
181
                    confirmPasscodeTextField.text = @"";
182
                    setPasscodeTextField.text = @"";
183
                    passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again.";
184
                    [self moveToPreviousTableView];
185
                } else {
186
                    if ([Keychain setString:setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) {
187
                        [Keychain setString:@"YES" forKey:@"passcode_lock_passcode_on"];
188
                    }
189
                    [self.passcodeLockViewController.tableView reloadData];
190
                    [self.settingsViewController.tableView reloadData];
191
                    [self dismissModalViewControllerAnimated:YES];
192
                }
193
            }            
194
        } else if (mode == kModeChangePasscode) {
195
            NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
196
            if ([textField isEqual:enterPasscodeTextField]) {
197
                if ([passcode isEqualToString:enterPasscodeTextField.text]) {
198
                    [self moveToNextTableView];
199
                } else {
200
                    [self incrementAndShowFailedAttemptsLabel];
201
                }
202
            } else if ([textField isEqual:setPasscodeTextField]) {
203
                if ([passcode isEqualToString:setPasscodeTextField.text]) {
204
                    setPasscodeTextField.text = @"";
205
                    passcodeConfirmationWarningLabel.text = @"Enter a different passcode. Cannot re-use the same passcode.";
206
                    passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 131.5, viewWidth, 60.0);
207
                } else {
208
                    passcodeConfirmationWarningLabel.text = @"";
209
                    passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 146.5, viewWidth, 30.0);
210
                    [self moveToNextTableView];
211
                }
212
            } else if ([textField isEqual:confirmPasscodeTextField]) {
213
                if (![confirmPasscodeTextField.text isEqualToString:setPasscodeTextField.text]) {
214
                    confirmPasscodeTextField.text = @"";
215
                    setPasscodeTextField.text = @"";
216
                    passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again.";
217
                    [self moveToPreviousTableView];
218
                } else {
219
                    if ([Keychain setString:setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) {
220
                        [Keychain setString:@"YES" forKey:@"passcode_lock_passcode_on"];
221
                    }
222
                    [self.passcodeLockViewController.tableView reloadData];
223
                    [self.settingsViewController.tableView reloadData];
224
                    [self dismissModalViewControllerAnimated:YES];
225
                }
226
            }
227
        }
228
    }    
229
}
230

    
231
- (void)doneButtonPressed:(id)sender {
232
    
233
    UITextField *textField = [textFields objectAtIndex:tableIndex];
234
        
235
    if (mode == kModeEnterPasscode) {
236
        NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
237
        if ([enterPasscodeTextField.text isEqualToString:passcode]) {
238
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
239
                [UIView beginAnimations:@"fadeIn" context:nil];
240
                [UIView setAnimationDelay:0.25];
241
                [UIView setAnimationDuration:0.5];
242
                OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
243
                for (UIViewController *svc in app.splitViewController.viewControllers) {
244
                    svc.view.alpha = 1.0;
245
                }
246
                [UIView commitAnimations];
247
            }
248
            [self dismissModalViewControllerAnimated:YES];
249
        } else { 
250
            [self incrementAndShowFailedAttemptsLabel];
251
        }
252
    } else if (mode == kModeSetPasscode) {
253
        if ([textField isEqual:setPasscodeTextField]) {
254
            [self moveToNextTableView];
255
        } else if ([textField isEqual:confirmPasscodeTextField]) {
256
            if (![confirmPasscodeTextField.text isEqualToString:setPasscodeTextField.text]) {
257
                confirmPasscodeTextField.text = @"";
258
                setPasscodeTextField.text = @"";
259
                passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again.";
260
                [self moveToPreviousTableView];
261
            } else {
262
                if ([Keychain setString:setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) {
263
                    [Keychain setString:@"YES" forKey:@"passcode_lock_passcode_on"];
264
                }
265
                [self.passcodeLockViewController.tableView reloadData];
266
                [self.settingsViewController.tableView reloadData];
267
                [self dismissModalViewControllerAnimated:YES];
268
            }
269
        }            
270
    } else if (mode == kModeChangePasscode) {
271
        NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
272
        if ([textField isEqual:enterPasscodeTextField]) {
273
            if ([passcode isEqualToString:enterPasscodeTextField.text]) {
274
                [self moveToNextTableView];
275
            } else {
276
                [self incrementAndShowFailedAttemptsLabel];
277
            }
278
        } else if ([textField isEqual:setPasscodeTextField]) {
279
            if ([passcode isEqualToString:setPasscodeTextField.text]) {
280
                setPasscodeTextField.text = @"";
281
                passcodeConfirmationWarningLabel.text = @"Enter a different passcode. Cannot re-use the same passcode.";
282
                passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 131.5, viewWidth, 60.0);
283
            } else {
284
                passcodeConfirmationWarningLabel.text = @"";
285
                passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 146.5, viewWidth, 30.0);
286
                [self moveToNextTableView];
287
            }
288
        } else if ([textField isEqual:confirmPasscodeTextField]) {
289
            if (![confirmPasscodeTextField.text isEqualToString:setPasscodeTextField.text]) {
290
                confirmPasscodeTextField.text = @"";
291
                setPasscodeTextField.text = @"";
292
                passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again.";
293
                [self moveToPreviousTableView];
294
            } else {
295
                if ([Keychain setString:setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) {
296
                    [Keychain setString:@"YES" forKey:@"passcode_lock_passcode_on"];
297
                }
298
                [self.passcodeLockViewController.tableView reloadData];
299
                [self.settingsViewController.tableView reloadData];
300
                [self dismissModalViewControllerAnimated:YES];
301
            }
302
        }
303
    } else if (mode == kModeDisablePasscode) {
304
        NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
305
        if ([enterPasscodeTextField.text isEqualToString:passcode]) {
306
            if ([Keychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]) {
307
                [Keychain setString:@"" forKey:@"passcode_lock_passcode"];
308
            }
309
            [self.passcodeLockViewController.tableView reloadData];
310
            [self.settingsViewController.tableView reloadData];
311
            [self dismissModalViewControllerAnimated:YES];
312
        } else { 
313
            [self incrementAndShowFailedAttemptsLabel];
314
        }
315
    }
316
}
317

    
318
#pragma mark -
319
#pragma mark View lifecycle
320

    
321
- (void)viewDidLoad {
322
    [super viewDidLoad];        
323
    simplePasscodeOn = [[Keychain getStringForKey:@"passcode_lock_simple_passcode_on"] isEqualToString:@"YES"];
324
    passcodeLockOn = [[Keychain getStringForKey:@"passcode_lock_passcode_on"] isEqualToString:@"YES"];
325
    eraseData = [[Keychain getStringForKey:@"passcode_lock_erase_data_on"] isEqualToString:@"YES"];
326
    
327
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
328
        viewWidth = 540.0;
329
    } else {
330
        viewWidth = 320.0;
331
    }
332
}
333

    
334
- (UIView *)passwordHeaderViewForTextField:(UITextField *)textField {
335
    
336
    if (simplePasscodeOn) {
337
        textField.keyboardType = UIKeyboardTypeNumberPad;
338

    
339
        // hide the text field and add it to the view.  we'll use the squares, but we need a text field
340
        textField.hidden = YES;
341
        [self.view addSubview:textField];
342
    } else {
343
        textField.keyboardType = UIKeyboardTypeDefault;
344
        textField.returnKeyType = UIReturnKeyNext;
345
    }
346
    
347
    UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, 70.0)] autorelease];
348
    UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 27.5, viewWidth, 30.0)];
349
    headerLabel.textColor = [UIColor tableViewHeaderColor];
350
    headerLabel.backgroundColor = [UIColor clearColor];
351
    headerLabel.textAlignment = UITextAlignmentCenter;
352
    headerLabel.font = [UIFont boldSystemFontOfSize:17.0];
353
    headerLabel.shadowOffset = CGSizeMake(0, 1.0);
354
    headerLabel.shadowColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
355
    
356
    if ([textField isEqual:setPasscodeTextField]) {
357
        passcodeConfirmationWarningLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 146.5, viewWidth, 30.0)];
358
        passcodeConfirmationWarningLabel.textColor = [UIColor tableViewHeaderColor];
359
        passcodeConfirmationWarningLabel.backgroundColor = [UIColor clearColor];
360
        passcodeConfirmationWarningLabel.textAlignment = UITextAlignmentCenter;
361
        passcodeConfirmationWarningLabel.font = [UIFont systemFontOfSize:14.0];
362
        passcodeConfirmationWarningLabel.shadowOffset = CGSizeMake(0, 1.0);
363
        passcodeConfirmationWarningLabel.shadowColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
364
        passcodeConfirmationWarningLabel.text = @"";
365
        passcodeConfirmationWarningLabel.numberOfLines = 0;
366
        passcodeConfirmationWarningLabel.lineBreakMode = UILineBreakModeWordWrap;
367
        [headerView addSubview:passcodeConfirmationWarningLabel];
368
    }
369
    
370
    if ([textField isEqual:enterPasscodeTextField]) {
371
        //UIView *failedAttemptsView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 146.5, viewWidth, 30.0)];
372
        
373
        NSString *text = @"1 Failed Passcode Attempt";
374
        CGSize size = [text sizeWithFont:[UIFont boldSystemFontOfSize:14.0]];
375
        failedAttemptsView = [[UIView alloc] initWithFrame:CGRectMake((viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0)];
376
        failedAttemptsLabel = [[UILabel alloc] initWithFrame:CGRectMake((viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0)]; 
377
        failedAttemptsLabel.backgroundColor = [UIColor clearColor];
378
        failedAttemptsLabel.textColor = [UIColor whiteColor];
379
        failedAttemptsLabel.text = text;
380
        failedAttemptsLabel.font = [UIFont boldSystemFontOfSize:14.0];
381
        failedAttemptsLabel.textAlignment = UITextAlignmentCenter;
382
        failedAttemptsLabel.shadowOffset = CGSizeMake(0, -1.0);
383
        failedAttemptsLabel.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
384
        failedAttemptsView.layer.cornerRadius = 14;
385
        failedAttemptsView.layer.borderWidth = 1.0;
386
        failedAttemptsView.layer.borderColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.25] CGColor];
387

    
388
        failedAttemptsLabel.hidden = YES;
389
        failedAttemptsView.hidden = YES;
390

    
391
        CAGradientLayer *gradient = [CAGradientLayer layer];
392
        gradient.frame = failedAttemptsView.bounds;        
393
        gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.714 green:0.043 blue:0.043 alpha:1.0] CGColor], 
394
                                (id)[[UIColor colorWithRed:0.761 green:0.192 blue:0.192 alpha:1.0] CGColor], nil];
395
        [failedAttemptsView.layer insertSublayer:gradient atIndex:1];
396
        failedAttemptsView.layer.masksToBounds = YES;
397
        
398
        [headerView addSubview:failedAttemptsView];
399
        [headerView addSubview:failedAttemptsLabel];
400

    
401
        [failedAttemptsView release];
402
        [failedAttemptsLabel release];
403
    }
404
    
405
    if (mode == kModeSetPasscode) {
406
        self.navigationItem.title = @"Set Passcode";
407
        [self addCancelButton];    
408
        
409
        if ([textField isEqual:enterPasscodeTextField]) {
410
            headerLabel.text = @"Enter your passcode";
411
        } else if ([textField isEqual:setPasscodeTextField]) {
412
            headerLabel.text = @"Enter a passcode";
413
            [self addCancelButton];    
414
        } else if ([textField isEqual:confirmPasscodeTextField]) {
415
            headerLabel.text = @"Re-enter your passcode";
416
        }
417
    } else if (mode == kModeDisablePasscode) {
418
        self.navigationItem.title = @"Turn off Passcode";
419
        [self addCancelButton];    
420
        headerLabel.text = @"Enter your passcode";
421
    } else if (mode == kModeChangePasscode) {
422
        self.navigationItem.title = @"Change Passcode";
423
        [self addCancelButton];
424
        if ([textField isEqual:enterPasscodeTextField]) {
425
            headerLabel.text = @"Enter your old passcode";
426
        } else if ([textField isEqual:setPasscodeTextField]) {
427
            headerLabel.text = @"Enter your new passcode";
428
        } else {
429
            headerLabel.text = @"Re-enter your new passcode";
430
        }
431
    } else {
432
        self.navigationItem.title = @"Enter Passcode";
433
        headerLabel.text = @"Enter your passcode";
434
    }
435
    
436
    [headerView addSubview:headerLabel];
437
    [headerLabel release];
438
    
439
    return headerView;
440
}
441

    
442
- (NSArray *)squares {
443
    NSMutableArray *squareViews = [[NSMutableArray alloc] initWithCapacity:4];    
444
    NSInteger squareX = 23.0;
445
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
446
        squareX = 133.0;
447
    }
448
    
449
    for (int i = 0; i < 4; i++) {
450
        UIImageView *square = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"passcode_square_empty.png"]];
451
        square.frame = CGRectMake(squareX, 74.0, 61.0, 53.0);
452
        [squareViews addObject:square];
453
        [square release];
454
        squareX += 71.0;
455
    }    
456
    return [[NSArray alloc] initWithArray:squareViews];
457
}
458

    
459
- (void)viewWillAppear:(BOOL)animated {
460
    [super viewWillAppear:animated];
461
    
462
    enterPasscodeTextField = [self allocAndInitPasscodeTextField];
463
    setPasscodeTextField = [self allocAndInitPasscodeTextField];
464
    confirmPasscodeTextField = [self allocAndInitPasscodeTextField];
465

    
466
    tableViews = [[NSMutableArray alloc] init];
467
    textFields = [[NSMutableArray alloc] init];
468
    squares = [[NSMutableArray alloc] init];
469

    
470
    if (mode == kModeSetPasscode || mode == kModeChangePasscode) {
471
        // we're setting the passcode, so add possibly all of the table views
472
        if (passcodeLockOn) {
473
            enterPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:enterPasscodeTextField];
474
            [tableViews addObject:enterPasscodeTableView];
475
            [textFields addObject:enterPasscodeTextField];
476
            if (simplePasscodeOn) {
477
                [squares addObject:[self squares]];
478
                for (int i = 0; i < [[squares lastObject] count]; i++) {
479
                    [enterPasscodeTableView.tableHeaderView addSubview:[[squares lastObject] objectAtIndex:i]];
480
                }
481
            }
482
        }
483
        setPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:setPasscodeTextField];
484
        [tableViews addObject:setPasscodeTableView];
485
        [textFields addObject:setPasscodeTextField];
486
        if (simplePasscodeOn) {
487
            [squares addObject:[self squares]];
488
            for (int i = 0; i < [[squares lastObject] count]; i++) {
489
                [setPasscodeTableView.tableHeaderView addSubview:[[squares lastObject] objectAtIndex:i]];
490
            }
491
        }
492
        confirmPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:confirmPasscodeTextField];
493
        [tableViews addObject:confirmPasscodeTableView];
494
        [textFields addObject:confirmPasscodeTextField];
495
        if (simplePasscodeOn) {
496
            [squares addObject:[self squares]];
497
            for (int i = 0; i < [[squares lastObject] count]; i++) {
498
                [confirmPasscodeTableView.tableHeaderView addSubview:[[squares lastObject] objectAtIndex:i]];
499
            }
500
        }
501
    } else {        
502
        enterPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:enterPasscodeTextField];
503
        [tableViews addObject:enterPasscodeTableView];
504
        [textFields addObject:enterPasscodeTextField];
505
        if (simplePasscodeOn) {
506
            [squares addObject:[self squares]];
507
            for (int i = 0; i < [[squares lastObject] count]; i++) {
508
                [enterPasscodeTableView.tableHeaderView addSubview:[[squares lastObject] objectAtIndex:i]];
509
            }
510
        }
511
    }
512
    
513
    [self.view addSubview:[tableViews objectAtIndex:0]];
514

    
515
    // shift any extra table views away
516
    for (int i = 1; i < [tableViews count]; i++) {
517
        UITableView *tableView = [tableViews objectAtIndex:i];
518
        tableView.frame = CGRectMake(tableView.frame.origin.x + viewWidth, tableView.frame.origin.y, tableView.frame.size.width, tableView.frame.size.height);
519
        [self.view addSubview:tableView];
520
    }
521
    
522
    if (tableIndex == [tableViews count] - 1) {
523
        [self addDoneButton];
524
    } else {
525
        [self addNextButton];
526
    }
527
    
528
    [[textFields objectAtIndex:0] becomeFirstResponder];
529
    [[tableViews objectAtIndex:0] reloadData];
530
    [[textFields objectAtIndex:[tableViews count] - 1] setReturnKeyType:UIReturnKeyDone];
531

    
532
    // table looks all screwy on iPad at first, so shuffle around to get the drawing right
533
    // yes, i know this is a dirty hack.
534
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
535
        if ([tableViews count] > 1) {
536
            [self moveToNextTableView];
537
            [self moveToPreviousTableView];
538
        } else {
539
            UITableView *tv = [tableViews objectAtIndex:0];
540
            tv.frame = CGRectMake(tv.frame.origin.x, tv.frame.origin.y, 768.0, 960.0);
541
        }
542
    }
543
}
544

    
545
#pragma mark -
546
#pragma mark Table view data source
547

    
548
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
549
    return simplePasscodeOn ? 0 : 1;
550
}
551

    
552
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
553
    return 1;
554
}
555

    
556
// Customize the appearance of table view cells.
557
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
558
    
559
    static NSString *CellIdentifier = @"Cell";
560
    
561
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
562
    if (cell == nil) {
563
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
564
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
565
    }
566
    
567
    // Configure the cell...
568
    //cell.accessoryView = enterPasscodeTextField; //[textFields objectAtIndex:tableIndex];
569
    if ([aTableView isEqual:enterPasscodeTableView]) {
570
        cell.accessoryView = enterPasscodeTextField;
571
    } else if ([aTableView isEqual:setPasscodeTableView]) {
572
        cell.accessoryView = setPasscodeTextField;
573
    } else if ([aTableView isEqual:confirmPasscodeTableView]) {
574
        cell.accessoryView = confirmPasscodeTextField;
575
    }
576
    
577
    return cell;
578
}
579

    
580
#pragma mark -
581
#pragma mark Text Field Delegate
582

    
583
/*
584
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
585
    // we don't want iPad users to be able to dismiss the keyboard at all
586
    return NO;
587
}
588
 */
589

    
590
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
591
    if ([textField isEqual:[textFields lastObject]]) {
592
        [self doneButtonPressed:nil];
593
    } else {
594
        [self nextButtonPressed:nil];
595
    }
596
    return NO;
597
}
598

    
599
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
600
    
601
    // if we're in simple passcode mode, update the squares to show entered numbers
602
    if (simplePasscodeOn) {
603
        NSString *result = [textField.text stringByReplacingCharactersInRange:range withString:string];
604

    
605
        // we're setting here and returning no since i'm messing with the responder chain.
606
        // otherwise the last character will become the first character of the next textField
607
        textField.text = result;
608
        
609
        for (int i = 0; i < 4; i++) {
610
            UIImageView *square = [[squares objectAtIndex:tableIndex] objectAtIndex:i];
611
            if (i < [result length]) {
612
                square.image = [UIImage imageNamed:@"passcode_square_filled.png"];
613
            } else {
614
                square.image = [UIImage imageNamed:@"passcode_square_empty.png"];
615
            }
616
        }
617
        
618
        // if we're at 4 characters, it could be time to move on to confirming
619
        if ([result length] == 4) {
620

    
621
            if (mode == kModeDisablePasscode) {
622
                NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
623
                if ([enterPasscodeTextField.text isEqualToString:passcode]) {
624
                    if ([Keychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]) {
625
                        [Keychain setString:@"" forKey:@"passcode_lock_passcode"];
626
                    }
627
                    [self.passcodeLockViewController.tableView reloadData];
628
                    [self.settingsViewController.tableView reloadData];
629
                    [self dismissModalViewControllerAnimated:YES];
630
                } else { 
631
                    [self incrementAndShowFailedAttemptsLabel];
632
                }
633
            } else if (mode == kModeEnterPasscode) {
634
                NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
635
                if ([enterPasscodeTextField.text isEqualToString:passcode]) {
636
                    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
637
                        [UIView beginAnimations:@"fadeIn" context:nil];
638
                        [UIView setAnimationDelay:0.25];
639
                        [UIView setAnimationDuration:0.5];
640
                        OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
641
                        for (UIViewController *svc in app.splitViewController.viewControllers) {
642
                            svc.view.alpha = 1.0;
643
                        }
644
                        [UIView commitAnimations];
645
                    }
646
                    [self dismissModalViewControllerAnimated:YES];
647
                } else { 
648
                    [self incrementAndShowFailedAttemptsLabel];
649
                }
650
            } else if (mode == kModeChangePasscode) {
651
                NSString *passcode = [Keychain getStringForKey:@"passcode_lock_passcode"];
652
                if ([textField isEqual:enterPasscodeTextField]) {
653
                    if ([passcode isEqualToString:enterPasscodeTextField.text]) {
654
                        [self moveToNextTableView];
655
                    } else {
656
                        [self incrementAndShowFailedAttemptsLabel];
657
                    }
658
                } else if ([textField isEqual:setPasscodeTextField]) {
659
                    if ([passcode isEqualToString:setPasscodeTextField.text]) {
660
                        setPasscodeTextField.text = @"";
661
                        for (int i = 0; i < 4; i++) {
662
                            [[[squares objectAtIndex:tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]];
663
                        }    
664
                        passcodeConfirmationWarningLabel.text = @"Enter a different passcode. Cannot re-use the same passcode.";
665
                        passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 131.5, viewWidth, 60.0);
666
                    } else {
667
                        passcodeConfirmationWarningLabel.text = @"";
668
                        passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 146.5, viewWidth, 30.0);
669
                        [self moveToNextTableView];
670
                    }
671
                } else if ([textField isEqual:confirmPasscodeTextField]) {
672
                    if (![confirmPasscodeTextField.text isEqualToString:setPasscodeTextField.text]) {
673
                        confirmPasscodeTextField.text = @"";
674
                        setPasscodeTextField.text = @"";
675
                        passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again.";
676
                        [self moveToPreviousTableView];
677
                    } else {
678
                        if ([Keychain setString:setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) {
679
                            [Keychain setString:@"YES" forKey:@"passcode_lock_passcode_on"];
680
                        }
681
                        [self.passcodeLockViewController.tableView reloadData];
682
                        [self.settingsViewController.tableView reloadData];
683
                        [self dismissModalViewControllerAnimated:YES];
684
                    }
685
                }
686
            } else if ([textField isEqual:setPasscodeTextField]) {
687
                [self moveToNextTableView];
688
            } else if ([textField isEqual:confirmPasscodeTextField]) {
689
                if (![confirmPasscodeTextField.text isEqualToString:setPasscodeTextField.text]) {
690
                    confirmPasscodeTextField.text = @"";
691
                    setPasscodeTextField.text = @"";
692
                    passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again.";
693
                    [self moveToPreviousTableView];
694
                } else {
695
                    if ([Keychain setString:setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) {
696
                        [Keychain setString:@"YES" forKey:@"passcode_lock_passcode_on"];
697
                    }
698
                    [self.passcodeLockViewController.tableView reloadData];
699
                    [self.settingsViewController.tableView reloadData];
700
                    [self dismissModalViewControllerAnimated:YES];
701
                }
702
            }
703
        }
704
        
705
        return NO;
706
    }
707

    
708
    return YES;
709
}
710

    
711
#pragma mark -
712
#pragma mark Memory management
713

    
714
- (void)dealloc {
715
    
716
    [enterPasscodeTextField release];
717
    [setPasscodeTextField release];
718
    [confirmPasscodeTextField release];
719
    [tableViews release];
720
    [textFields release];
721
    [squares release];
722
    [passcodeLockViewController release];
723
    [settingsViewController release];
724
    [rootViewController release];
725
    [accountHomeViewController release];
726
    [super dealloc];
727
}
728

    
729
@end