Newer
Older
//
// TokenViewController.m
// ISDS
//
// Created by Petr Hruška on 6/30/11.
// Copyright 2011 CZ.NIC, z.s.p.o. All rights reserved.
//
#import "TokenViewController.h"
#import "OtpStatus.h"
#import "HotpCookieTask.h"
#import "TotpCookieTask.h"
#import "SmsTask.h"
#import "DetailViewController.h"
#import "ISDSAppDelegate_iPad.h"
#define CONTINUE_BUTTON_INDEX 0
#define CANCEL_BUTTON_INDEX 1
@implementation TokenViewController
@synthesize data=_data;
@synthesize cell=_cell;
@synthesize tableView=_tableView;
@synthesize doneButton=_doneButton;
@synthesize editing=_editing;
@synthesize delegate;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@synthesize pendingRequests=pendingRequests_;
@synthesize progressViewController=progressViewController_;
@synthesize initialTasks = _initialTasks;
@synthesize whereToPop=_whereToPop;
@synthesize prompt=_prompt;
@synthesize popAnimated=_popAnimated;
@synthesize actionSheet=_actionSheet;
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundleOrNil
{
if ((self = [super initWithNibName:nibName bundle:nibBundleOrNil])) {
self.popAnimated = TRUE;
}
return self;
}
- (void)incrementPendingRequests:(NSUInteger)count
{
if (!self.pendingRequests) {
[self.progressViewController registerObserver];
self.toolbarItems = [self progressToolbarItems];
[self.navigationController setToolbarHidden:NO animated:YES];
}
self.pendingRequests += count;
}
- (void)decrementPendingRequests
{
self.pendingRequests--;
if (!self.pendingRequests) {
[self.navigationController setToolbarHidden:YES animated:YES];
self.toolbarItems = [NSArray array];
[self.progressViewController unregisterObserver];
self.progressViewController.errorCount = 0;
}
}
RequestManager* rm = [RequestManager requestManager];
for (OtpStatus* status in self.data) {
if (status.task) {
[rm removeTask:status.task];
[self decrementPendingRequests];
status.task = nil;
}
}
}
- (void)stopTimers
{
for (OtpStatus* status in self.data) {
[status stopTimer];
}
}
- (void)dismissActionSheet
{
[self.actionSheet dismissWithClickedButtonIndex:-1 animated:NO];
- (void)dealloc
{
[self cancelNetworkOperations];
[_data release];
[_tableView release];
[_doneButton release];
[progressToolbarItems_ release];
[progressViewController_ release];
[_initialTasks release];
[_actionSheet release];
[super dealloc];
}
- (void)viewDidUnload
{
self.tableView = nil;
self.doneButton = nil;
self.cancelButton = nil;
[progressToolbarItems_ release];
progressToolbarItems_ = nil;
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
[super viewDidUnload];
}
- (TokenCell*)cellAtIndex:(NSUInteger)index
{
return (TokenCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index]];
}
/* return [self.data count] if the focus should not be set */
- (NSUInteger)initialFocusIndex
{
NSUInteger index = 0;
const NSUInteger count = [self.data count];
while (index < count) {
OtpStatus* status = [self.data objectAtIndex:index];
if (status.status == OtpStatusShouldSendSms) {
return count;
} else if (status.status == OtpStatusEnterToken) {
return index;
}
index++;
}
return index;
}
- (void)viewDidLoad
{
self.doneButton.title = NSLocalizedString(@"Update", nil);
self.cancelButton.title = NSLocalizedString(@"Cancel", nil);
}
- (enum ProgressDisplayContext)currentContext
{
ISDSAppDelegate_Shared* appDelegate = (ISDSAppDelegate_Shared*)[[UIApplication sharedApplication] delegate];
if ([appDelegate iPad]) {
ISDSAppDelegate_iPad* iPadDelegate = (ISDSAppDelegate_iPad*)appDelegate;
DetailViewController* detailViewController = iPadDelegate.detailViewController;
if ([detailViewController popoverMode])
return ProgressDisplayContextPopover;
else
return ProgressDisplayContext_iPad;
} else
return ProgressDisplayContext_iPhone;
}
self.navigationItem.title = NSLocalizedString(@"Authorization", nil);
self.navigationItem.prompt = self.prompt;
self.navigationItem.rightBarButtonItem = self.doneButton;
if (self.whereToPop)
self.navigationItem.leftBarButtonItem = self.cancelButton;
[self.progressViewController setDisplayContext:[self currentContext]];
[self.navigationController setToolbarHidden:self.pendingRequests == 0];
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
/* set focus */
NSUInteger index = [self initialFocusIndex];
if (index < [self.data count]) {
TokenCell* cell = [self cellAtIndex:index];
[cell setFocus];
}
[super viewDidAppear:animated];
}
- (NSUInteger)indexFromTask:(OtpTask*)task
{
const NSUInteger count = [self.data count];
for (NSUInteger index = 0; index < count; index++) {
OtpStatus* status = [self.data objectAtIndex:index];
if (status.task == task) return index;
}
return count;
}
- (void)setupAccounts:(NSArray*)accounts
{
self.data = [NSMutableArray arrayWithCapacity:[accounts count]];
for (ISDSAccount* account in accounts) {
if (account.authType != ISDSAccountAuthPass) {
OtpStatus* status = [[OtpStatus alloc] initWithAccount:account];
[self.data addObject:status];
[status release];
}
}
}
- (void)reloadSectionForIndex:(NSUInteger)index
{
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:index] withRowAnimation:UITableViewRowAnimationFade];
}
- (void)cookieExpiredForStatus:(OtpStatus*)status
{
NSUInteger index = [self.data indexOfObject:status];
if (index == NSNotFound) return;
[self reloadSectionForIndex:index];
}
- (void)configureCell:(TokenCell*)cell withStatus:(OtpStatus*)status
{
cell.sendButton.titleLabel.text = NSLocalizedString(@"Send SMS", nil);
cell.tokenText.placeholder = NSLocalizedString(@"enter token", nil);
cell.boxName = [status.account boxName];
switch (status.status) {
case OtpStatusShouldSendSms:
break;
case OtpStatusRequestingSms:
cell.message = NSLocalizedString(@"requesting sms", nil);
break;
case OtpStatusEnterToken:
break;
case OtpStatusRequestingCookie:
cell.message = NSLocalizedString(@"requesting cookie", nil);
break;
case OtpStatusHasCookie:
cell.message = NSLocalizedString(@"account authorized", nil);
break;
}
cell.errorDescription = status.errorDescription;
- (NSArray*)progressToolbarItems
{
if (!progressToolbarItems_) {
UIBarButtonItem* item = [[UIBarButtonItem alloc] initWithCustomView:self.progressViewController.view];
[self.progressViewController setDisplayContext:[self currentContext]];
[self.progressViewController setProgressViewWidth:self.view.frame.size.width];
progressToolbarItems_ = [[NSArray arrayWithObject:item] retain];
[item release];
}
return progressToolbarItems_;
}
{
UIButton* button = (UIButton*)sender;
NSUInteger index = button.tag;
OtpStatus* status = [self.data objectAtIndex:index];
SmsTask* task = [[SmsTask alloc] initWithOtpStatus:status];
task.otpDelegate = self;
status.task = task;
[task release];
status.status = OtpStatusRequestingSms;
status.errorDescription = nil;
RequestManager* rm = [RequestManager requestManager];
[rm addTasks:[NSArray arrayWithObject:task] withPriority:YES];
[self incrementPendingRequests:1];
[self reloadSectionForIndex:index];
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
OtpStatus* status = [self.data objectAtIndex:[indexPath section]];
return [TokenCell cellHeightForErrorDescription:status.errorDescription];
}
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* reuseIdentifier = @"TokenCell";
TokenCell* cell = (TokenCell*)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"TokenCell" owner:self options:nil];
cell = self.cell;
self.cell = nil;
}
OtpStatus* status = [self.data objectAtIndex:[indexPath section]];
[self configureCell:cell withStatus:status];
[cell setupTag:indexPath.section];
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.data count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (OtpTask*)createTask:(OtpStatus*)status
{
OtpTask* t;
switch (status.account.authType) {
case ISDSAccountAuthHotp:
t = [[HotpCookieTask alloc] initWithOtpStatus:status];
t.otpDelegate = self;
[t autorelease];
break;
case ISDSAccountAuthTotp:
t = [[TotpCookieTask alloc] initWithOtpStatus:status];
t.otpDelegate = self;
[t autorelease];
break;
default:
t = nil;
break;
}
return t;
}
- (void)done
{
[self dismissActionSheet];
if (self.whereToPop)
[self.navigationController popToViewController:self.whereToPop animated:self.popAnimated];
else
[self.navigationController popViewControllerAnimated:self.popAnimated];
[self.delegate tokenViewControllerDone:self];
}
- (void)downloadCookies
{
NSUInteger taskCount = 0;
for (OtpStatus* status in self.data) {
if ([status tokenReady]) taskCount++;
}
if (!taskCount) {
[self done];
return;
}
NSMutableArray* tasks = [NSMutableArray arrayWithCapacity:taskCount];
for (OtpStatus* status in self.data)
if ([status tokenReady]) {
OtpTask* task = [self createTask:status];
status.task = task;
status.status = OtpStatusRequestingCookie;
[tasks addObject:task];
}
RequestManager* rm = [RequestManager requestManager];
[rm addTasks:tasks withPriority:YES];
[self incrementPendingRequests:[tasks count]];
if (self.actionSheet) [self dismissActionSheet];
self.actionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Some accounts are missing tokens. Do you with to continue?", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel", nil) destructiveButtonTitle:NSLocalizedString(@"Continue", nil) otherButtonTitles: nil];
[self.actionSheet showInView:self.view];
[self.actionSheet release];
}
- (void)markMissingUnwanted
{
for (OtpStatus* status in self.data) {
if (![status tokenReady] && status.shouldHaveCookie) status.shouldHaveCookie = FALSE;
}
}
- (IBAction)doneTouched
{
if (self.editing)
[self.editing resignFirstResponder];
NSUInteger missingCount = 0;
for (OtpStatus* status in self.data) {
if (status.status != OtpStatusHasCookie && ![status tokenReady] && status.shouldHaveCookie) missingCount++;
}
if (missingCount)
[self showActionSheet];
}
- (BOOL)hasAllWantedCookies
{
for (OtpStatus* status in self.data)
if (status.status != OtpStatusHasCookie && status.shouldHaveCookie) return NO;
return YES;
}
#pragma mark - OtpTaskDelegate
- (void)taskSuccessfullyDone:(ISDSTask*)task
{
NSUInteger index = [self indexFromTask:(OtpTask*)task];
OtpStatus* status = [self.data objectAtIndex:index];
switch (status.status) {
case OtpStatusRequestingSms:
status.status = OtpStatusEnterToken;
[self decrementPendingRequests];
status.task = nil;
[self reloadSectionForIndex:index];
break;
case OtpStatusRequestingCookie:
status.status = OtpStatusHasCookie;
[self decrementPendingRequests];
status.task = nil;
if ([self hasAllWantedCookies] && !self.pendingRequests)
[self done];
else
[self reloadSectionForIndex:index];
break;
default:
break;
}
}
- (void)taskFailed:(ISDSTask*)task
{
NSUInteger index = [self indexFromTask:(OtpTask*)task];
if (index == [self.data count]) return;
OtpStatus* status = [self.data objectAtIndex:index];
status.errorDescription = task.errorDescription;
// decrement of pending requests can set errorCount to zero
self.progressViewController.errorCount++;
switch (status.status) {
case OtpStatusRequestingSms:
status.status = OtpStatusShouldSendSms;
[self decrementPendingRequests];
break;
case OtpStatusRequestingCookie:
status.status = OtpStatusEnterToken;
status.token = @"";
[self decrementPendingRequests];
break;
default:
break;
}
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
[self reloadSectionForIndex:index];
}
#pragma mark - UITextFieldDelegate
- (void)setupTokenFromTextField:(UITextField *)textField
{
NSUInteger index = textField.tag;
OtpStatus* status = [self.data objectAtIndex:index];
status.token = textField.text;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.editing = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self setupTokenFromTextField:textField];
self.editing = nil;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
if ([textField isFirstResponder])
[textField resignFirstResponder];
else
textField.text = @"";
return NO;
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
case CONTINUE_BUTTON_INDEX:
// we will not ask next time
[self downloadCookies];
break;
case CANCEL_BUTTON_INDEX:
break;
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
self.actionSheet = nil;
}