RingWizardWC.mm 11.4 KB
Newer Older
1
/*
2
 *  Copyright (C) 2015-2016 Savoir-faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */
#import "RingWizardWC.h"

21 22 23 24
//Qt
#import <QUrl>

//LRC
25 26 27 28
#import <accountmodel.h>
#import <protocolmodel.h>
#import <QItemSelectionModel>
#import <account.h>
29
#import <certificate.h>
30 31 32

#import "AppDelegate.h"

Alexandre Lision's avatar
Alexandre Lision committed
33
@implementation RingWizardWC {
34 35 36 37 38 39
    __unsafe_unretained IBOutlet NSButton* goToAppButton;
    __unsafe_unretained IBOutlet NSTextField* nicknameField;
    __unsafe_unretained IBOutlet NSProgressIndicator* progressBar;
    __unsafe_unretained IBOutlet NSTextField* indicationLabel;
    __unsafe_unretained IBOutlet NSButton* createButton;
    __unsafe_unretained IBOutlet NSButton* showCustomCertsButton;
40 41
    IBOutlet NSView *securityContainer;

42 43 44 45 46
    __unsafe_unretained IBOutlet NSSecureTextField* passwordField;
    __unsafe_unretained IBOutlet NSView* pvkContainer;
    __unsafe_unretained IBOutlet NSPathControl* certificatePathControl;
    __unsafe_unretained IBOutlet NSPathControl* caListPathControl;
    __unsafe_unretained IBOutlet NSPathControl* pvkPathControl;
47
    BOOL isExpanded;
Alexandre Lision's avatar
Alexandre Lision committed
48
    Account* accountToCreate;
49
}
50

Alexandre Lision's avatar
Alexandre Lision committed
51 52
NSInteger const PVK_PASSWORD_TAG    = 0;
NSInteger const NICKNAME_TAG        = 1;
53 54 55 56

- (void)windowDidLoad {
    [super windowDidLoad];

57
    [passwordField setTag:PVK_PASSWORD_TAG];
58
    [nicknameField setTag:NICKNAME_TAG];
59 60

    isExpanded = false;
61 62 63
    [self.window makeKeyAndOrderFront:nil];
    [self.window setLevel:NSStatusWindowLevel];
    [self.window makeMainWindow];
64 65 66
    AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];

    if(![appDelegate checkForRingAccount]) {
67
        accountToCreate = AccountModel::instance().add("", Account::Protocol::RING);
68 69
        [nicknameField setStringValue:NSFullUserName()];
        [self toggleCreateButton:NSFullUserName()];
70
    } else {
71 72
        [indicationLabel setStringValue:NSLocalizedString(@"Ring is already ready to work",
                                                          @"Display message to user")];
73
        auto accList = AccountModel::instance().getAccountsByProtocol(Account::Protocol::RING);
74 75 76 77 78 79
        [self displayHash:accList[0]->username().toNSString()];
    }

    [caListPathControl setDelegate:self];
    [certificatePathControl setDelegate:self];
    [pvkPathControl setDelegate:self];
80 81 82 83
}

- (void) displayHash:(NSString* ) hash
{
84 85 86 87
    [nicknameField setFrameSize:NSMakeSize(400, nicknameField.frame.size.height)];
    [nicknameField setStringValue:hash];
    [nicknameField setEditable:NO];
    [nicknameField setHidden:NO];
88

Alexandre Lision's avatar
Alexandre Lision committed
89 90
    [showCustomCertsButton setHidden:YES];

91 92 93 94
    [goToAppButton setHidden:NO];

    NSSharingService* emailSharingService = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeEmail];

95 96
    [createButton setTitle:NSLocalizedString(@"Share by mail",
                                             @"Share button")];
97
    [createButton setAlternateImage:emailSharingService.alternateImage];
Alexandre Lision's avatar
Alexandre Lision committed
98 99
    [createButton setEnabled:YES];

100 101 102
    [createButton setAction:@selector(shareByEmail)];
}

103 104
- (IBAction)createRingAccount:(id)sender
{
105
    [nicknameField setHidden:YES];
106 107
    [progressBar setHidden:NO];
    [createButton setEnabled:NO];
108 109
    [indicationLabel setStringValue:NSLocalizedString(@"Just a moment...",
                                                      @"Indication for user")];
110

111
    QModelIndex qIdx =  AccountModel::instance().protocolModel()->selectionModel()->currentIndex();
112 113

    [self setCallback];
114 115 116 117
    if (isExpanded) {
        // retract panel
        [self chooseOwnCertificates:nil];
    }
Alexandre Lision's avatar
Alexandre Lision committed
118
    [showCustomCertsButton setHidden:YES];
119

Alexandre Lision's avatar
Alexandre Lision committed
120
    [self performSelector:@selector(saveAccount) withObject:nil afterDelay:1];
121 122 123 124 125 126 127 128 129 130
    [self registerAutoStartup];
}

/**
 * Enable launch at startup by default
 */
- (void) registerAutoStartup
{
    LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
    if (loginItemsRef == nil) return;
131
    CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
132 133
    LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL);
    if (itemRef) CFRelease(itemRef);
134 135 136 137
}

- (void) saveAccount
{
138 139
    accountToCreate->setUpnpEnabled(YES); // Always active upnp
    accountToCreate << Account::EditAction::SAVE;
140 141 142 143
}

- (void) setCallback
{
144
    QObject::connect(&AccountModel::instance(),
145 146 147 148 149
                     &AccountModel::accountStateChanged,
                     [=](Account *account, const Account::RegistrationState state) {
                         NSLog(@"Account created!");
                         [progressBar setHidden:YES];
                         [createButton setEnabled:YES];
150
                         [indicationLabel setStringValue:NSLocalizedString(@"This is your number, share it with your friends!", @"Indication to user")];
151 152 153 154
                         [self displayHash:account->username().toNSString()];
                     });
}

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
- (IBAction)chooseOwnCertificates:(NSButton*)sender
{
    if (isExpanded) {
        [securityContainer removeFromSuperview];
        NSRect frame = [self.window frame];
        frame.size = CGSizeMake(securityContainer.frame.size.width, frame.size.height - securityContainer.frame.size.height);
        frame.origin.y = frame.origin.y + securityContainer.frame.size.height;
        [self.window setFrame:frame display:YES animate:YES];
        isExpanded = false;
        [sender setImage:[NSImage imageNamed:@"NSAddTemplate"]];
    } else {
        NSRect frame = [self.window frame];
        frame.size = CGSizeMake(securityContainer.frame.size.width, frame.size.height + securityContainer.frame.size.height);
        frame.origin.y = frame.origin.y - securityContainer.frame.size.height;
        [self.window setFrame:frame display:YES animate:YES];

        [securityContainer setFrameOrigin:CGPointMake(0, 50)];
        [self.window.contentView addSubview:securityContainer];
        isExpanded = true;
        [sender setImage:[NSImage imageNamed:@"NSRemoveTemplate"]];
    }
}

178 179 180 181 182 183 184
- (void) toggleCreateButton:(NSString*) alias
{
    [createButton setEnabled:![alias isEqualToString:@""]];
    accountToCreate->setAlias([alias UTF8String]);
    accountToCreate->setDisplayName([alias UTF8String]);
}

185 186
- (IBAction)goToApp:(id)sender
{
187 188 189 190 191 192 193
    [self.window close];
    AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
    [appDelegate showMainWindow];
}

- (void) shareByEmail
{
194
    NSMutableArray *shareItems = [[NSMutableArray alloc] initWithObjects:[nicknameField stringValue], nil];
195 196 197 198
    NSSharingService* emailSharingService = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeEmail];
    [emailSharingService performWithItems:shareItems];
}

199
#pragma mark - NSPathControl delegate methods
200

201 202 203 204 205 206 207 208 209 210
- (IBAction)caListPathControlSingleClick:(id)sender
{
    NSURL* fileURL;
    if ([sender isKindOfClass:[NSMenuItem class]]) {
        fileURL = nil;
    } else {
        fileURL = [[sender clickedPathComponentCell] URL];
    }
    [self->caListPathControl setURL:fileURL];
    accountToCreate->setTlsCaListCertificate([[fileURL path] UTF8String]);
211

212 213 214
}

- (IBAction)certificatePathControlSingleClick:(id)sender
215
{
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
    NSURL* fileURL;
    if ([sender isKindOfClass:[NSMenuItem class]]) {
        fileURL = nil;
    } else {
        fileURL = [[sender clickedPathComponentCell] URL];
    }
    [self->certificatePathControl setURL:fileURL];
    accountToCreate->setTlsCertificate([[fileURL path] UTF8String]);

    auto cert = accountToCreate->tlsCertificate();

    if (cert) {
        [pvkContainer setHidden:!cert->requirePrivateKey()];
    } else {
        [pvkContainer setHidden:YES];
    }

233 234
}

235
- (IBAction)pvkFilePathControlSingleClick:(id)sender
236
{
237 238 239 240 241 242 243 244 245 246 247 248 249 250
    NSURL* fileURL;
    if ([sender isKindOfClass:[NSMenuItem class]]) {
        fileURL = nil;
    } else {
        fileURL = [[sender clickedPathComponentCell] URL];
    }
    [self->pvkPathControl setURL:fileURL];
    accountToCreate->setTlsPrivateKey([[fileURL path] UTF8String]);

    if(accountToCreate->tlsCertificate()->requirePrivateKeyPassword()) {
        [passwordField setHidden:NO];
    } else {
        [passwordField setHidden:YES];
    }
251 252
}

253 254 255 256
/*
 Delegate method of NSPathControl to determine how the NSOpenPanel will look/behave.
 */
- (void)pathControl:(NSPathControl *)pathControl willDisplayOpenPanel:(NSOpenPanel *)openPanel
257
{
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
    NSLog(@"willDisplayOpenPanel");
    [openPanel setAllowsMultipleSelection:NO];
    [openPanel setCanChooseDirectories:NO];
    [openPanel setCanChooseFiles:YES];
    [openPanel setResolvesAliases:YES];

    if(pathControl == caListPathControl) {
        [openPanel setTitle:NSLocalizedString(@"Choose a CA list", @"Open panel title")];
    } else if (pathControl == certificatePathControl) {
        [openPanel setTitle:NSLocalizedString(@"Choose a certificate", @"Open panel title")];
    } else {
        [openPanel setTitle:NSLocalizedString(@"Choose a private key file", @"Open panel title")];
    }

    [openPanel setPrompt:NSLocalizedString(@"Choose", @"Open panel prompt for 'Choose a file'")];
    [openPanel setDelegate:self];
274 275
}

276
- (void)pathControl:(NSPathControl *)pathControl willPopUpMenu:(NSMenu *)menu
277
{
278 279
    NSMenuItem *item;
    if(pathControl == caListPathControl) {
280 281
        item = [menu addItemWithTitle:NSLocalizedString(@"Remove value", @"Contextual menu entry")
                               action:@selector(caListPathControlSingleClick:) keyEquivalent:@""];
282
    } else if (pathControl == certificatePathControl) {
283 284
        item = [menu addItemWithTitle:NSLocalizedString(@"Remove value", @"Contextual menu entry")
                               action:@selector(certificatePathControlSingleClick:) keyEquivalent:@""];
285
    } else {
286 287
        item = [menu addItemWithTitle:NSLocalizedString(@"Remove value", @"Contextual menu entry")
                               action:@selector(pvkFilePathControlSingleClick:) keyEquivalent:@""];
288 289
    }
    [item setTarget:self]; // or whatever target you want
290 291
}

292 293 294
#pragma mark - NSOpenSavePanelDelegate delegate methods

- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
295
{
296
    return YES;
297 298
}

299 300 301 302
#pragma mark - NSTextFieldDelegate methods

-(void)controlTextDidChange:(NSNotification *)notif
{
303
    NSTextField* textField = [notif object];
304 305 306 307 308 309
    if (textField.tag == PVK_PASSWORD_TAG) {
        accountToCreate->setTlsPassword([textField.stringValue UTF8String]);
        return;
    }

    // else it is NICKNAME_TAG field
310
    [self toggleCreateButton:textField.stringValue];
311 312 313 314
}

# pragma NSWindowDelegate methods

315 316 317
- (void)windowWillClose:(NSNotification *)notification
{
    AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
318 319 320
    if ([appDelegate checkForRingAccount]) {
        [appDelegate showMainWindow];
    }
321 322 323
}

@end