blob: 21fb68c096255e10eb0afc35a4a25246899b6f66 [file] [log] [blame]
Alexandre Lision745e4d62015-03-22 20:03:10 -04001/*
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -04002 * Copyright (C) 2015 Savoir-faire Linux Inc.
Alexandre Lision745e4d62015-03-22 20:03:10 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Alexandre Lision745e4d62015-03-22 20:03:10 -040018 */
19#import "RingWizardWC.h"
20
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040021//Qt
22#import <QUrl>
23
24//LRC
Alexandre Lision745e4d62015-03-22 20:03:10 -040025#import <accountmodel.h>
26#import <protocolmodel.h>
27#import <QItemSelectionModel>
28#import <account.h>
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040029#import <certificate.h>
Alexandre Lision745e4d62015-03-22 20:03:10 -040030
31#import "AppDelegate.h"
32
Alexandre Lision08abfac2015-09-22 12:20:51 -040033@implementation RingWizardWC {
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040034 __unsafe_unretained IBOutlet NSButton *goToAppButton;
35 __unsafe_unretained IBOutlet NSTextField *nickname;
36 __unsafe_unretained IBOutlet NSProgressIndicator *progressBar;
37 __unsafe_unretained IBOutlet NSTextField *indicationLabel;
38 __unsafe_unretained IBOutlet NSButton *createButton;
39 __unsafe_unretained IBOutlet NSButton *showCustomCertsButton;
40 IBOutlet NSView *securityContainer;
41
42 __unsafe_unretained IBOutlet NSSecureTextField *passwordField;
43 __unsafe_unretained IBOutlet NSView *pvkContainer;
44 __unsafe_unretained IBOutlet NSPathControl *certificatePathControl;
45 __unsafe_unretained IBOutlet NSPathControl *caListPathControl;
46 __unsafe_unretained IBOutlet NSPathControl *pvkPathControl;
47 BOOL isExpanded;
Alexandre Lision08abfac2015-09-22 12:20:51 -040048 Account* accountToCreate;
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040049}
50
Alexandre Lision08abfac2015-09-22 12:20:51 -040051NSInteger const PVK_PASSWORD_TAG = 0;
52NSInteger const NICKNAME_TAG = 1;
Alexandre Lision745e4d62015-03-22 20:03:10 -040053
54- (void)windowDidLoad {
55 [super windowDidLoad];
56
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040057 [passwordField setTag:PVK_PASSWORD_TAG];
58 [nickname setTag:NICKNAME_TAG];
59
60 isExpanded = false;
Alexandre Lision745e4d62015-03-22 20:03:10 -040061 [self.window makeKeyAndOrderFront:nil];
62 [self.window setLevel:NSStatusWindowLevel];
63 [self.window makeMainWindow];
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040064 if(![self checkForRingAccount]) {
65 accountToCreate = AccountModel::instance()->add("", Account::Protocol::RING);
66 } else {
Alexandre Lision922380d2015-09-15 10:25:17 -040067 [indicationLabel setStringValue:NSLocalizedString(@"Ring is already ready to work",
68 @"Display message to user")];
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040069 auto accList = AccountModel::instance()->getAccountsByProtocol(Account::Protocol::RING);
70 [self displayHash:accList[0]->username().toNSString()];
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040071 }
72
73 [caListPathControl setDelegate:self];
74 [certificatePathControl setDelegate:self];
75 [pvkPathControl setDelegate:self];
Alexandre Lision745e4d62015-03-22 20:03:10 -040076}
77
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040078- (BOOL) checkForRingAccount
Alexandre Lision745e4d62015-03-22 20:03:10 -040079{
80 for (int i = 0 ; i < AccountModel::instance()->rowCount() ; ++i) {
81 QModelIndex idx = AccountModel::instance()->index(i);
82 Account* acc = AccountModel::instance()->getAccountByModelIndex(idx);
83 if(acc->protocol() == Account::Protocol::RING) {
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040084 return YES;
Alexandre Lision745e4d62015-03-22 20:03:10 -040085 }
86 }
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -040087 return false;
Alexandre Lision745e4d62015-03-22 20:03:10 -040088}
89
90- (void) displayHash:(NSString* ) hash
91{
92 [nickname setFrameSize:NSMakeSize(400, nickname.frame.size.height)];
93 [nickname setStringValue:hash];
94 [nickname setEditable:NO];
95 [nickname setHidden:NO];
96
Alexandre Lision08abfac2015-09-22 12:20:51 -040097 [showCustomCertsButton setHidden:YES];
98
Alexandre Lision745e4d62015-03-22 20:03:10 -040099 [goToAppButton setHidden:NO];
100
101 NSSharingService* emailSharingService = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeEmail];
102
Alexandre Lision922380d2015-09-15 10:25:17 -0400103 [createButton setTitle:NSLocalizedString(@"Share by mail",
104 @"Share button")];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400105 [createButton setAlternateImage:emailSharingService.alternateImage];
Alexandre Lision08abfac2015-09-22 12:20:51 -0400106 [createButton setEnabled:YES];
107
Alexandre Lision745e4d62015-03-22 20:03:10 -0400108 [createButton setAction:@selector(shareByEmail)];
109}
110
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400111- (IBAction)createRingAccount:(id)sender
112{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400113 [nickname setHidden:YES];
114 [progressBar setHidden:NO];
115 [createButton setEnabled:NO];
Alexandre Lision922380d2015-09-15 10:25:17 -0400116 [indicationLabel setStringValue:NSLocalizedString(@"Just a moment...",
117 @"Indication for user")];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400118
119 QModelIndex qIdx = AccountModel::instance()->protocolModel()->selectionModel()->currentIndex();
120
121 [self setCallback];
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400122 if (isExpanded) {
123 // retract panel
124 [self chooseOwnCertificates:nil];
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400125 }
Alexandre Lision08abfac2015-09-22 12:20:51 -0400126 [showCustomCertsButton setHidden:YES];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400127
Alexandre Lision08abfac2015-09-22 12:20:51 -0400128 [self performSelector:@selector(saveAccount) withObject:nil afterDelay:1];
Alexandre Lision41981972015-06-04 13:27:33 -0400129 [self registerAutoStartup];
130}
131
132/**
133 * Enable launch at startup by default
134 */
135- (void) registerAutoStartup
136{
137 LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
138 if (loginItemsRef == nil) return;
Alexandre Lision81c97212015-06-17 15:51:53 -0400139 CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
Alexandre Lision41981972015-06-04 13:27:33 -0400140 LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL);
141 if (itemRef) CFRelease(itemRef);
Alexandre Lision745e4d62015-03-22 20:03:10 -0400142}
143
144- (void) saveAccount
145{
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400146 accountToCreate->setUpnpEnabled(YES); // Always active upnp
147 accountToCreate << Account::EditAction::SAVE;
Alexandre Lision745e4d62015-03-22 20:03:10 -0400148}
149
150- (void) setCallback
151{
152 QObject::connect(AccountModel::instance(),
153 &AccountModel::accountStateChanged,
154 [=](Account *account, const Account::RegistrationState state) {
155 NSLog(@"Account created!");
156 [progressBar setHidden:YES];
157 [createButton setEnabled:YES];
Alexandre Lision922380d2015-09-15 10:25:17 -0400158 [indicationLabel setStringValue:NSLocalizedString(@"This is your number, share it with your friends!", @"Indication to user")];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400159 [self displayHash:account->username().toNSString()];
160 });
161}
162
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400163- (IBAction)chooseOwnCertificates:(NSButton*)sender
164{
165 if (isExpanded) {
166 [securityContainer removeFromSuperview];
167 NSRect frame = [self.window frame];
168 frame.size = CGSizeMake(securityContainer.frame.size.width, frame.size.height - securityContainer.frame.size.height);
169 frame.origin.y = frame.origin.y + securityContainer.frame.size.height;
170 [self.window setFrame:frame display:YES animate:YES];
171 isExpanded = false;
172 [sender setImage:[NSImage imageNamed:@"NSAddTemplate"]];
173 } else {
174 NSRect frame = [self.window frame];
175 frame.size = CGSizeMake(securityContainer.frame.size.width, frame.size.height + securityContainer.frame.size.height);
176 frame.origin.y = frame.origin.y - securityContainer.frame.size.height;
177 [self.window setFrame:frame display:YES animate:YES];
178
179 [securityContainer setFrameOrigin:CGPointMake(0, 50)];
180 [self.window.contentView addSubview:securityContainer];
181 isExpanded = true;
182 [sender setImage:[NSImage imageNamed:@"NSRemoveTemplate"]];
183 }
184}
185
186- (IBAction)goToApp:(id)sender
187{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400188 [self.window close];
189 AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
190 [appDelegate showMainWindow];
191}
192
193- (void) shareByEmail
194{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400195 NSMutableArray *shareItems = [[NSMutableArray alloc] initWithObjects:[nickname stringValue], nil];
196 NSSharingService* emailSharingService = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeEmail];
Alexandre Lision745e4d62015-03-22 20:03:10 -0400197 [emailSharingService performWithItems:shareItems];
198}
199
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400200#pragma mark - NSPathControl delegate methods
Alexandre Lision745e4d62015-03-22 20:03:10 -0400201
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400202- (IBAction)caListPathControlSingleClick:(id)sender
Alexandre Lision745e4d62015-03-22 20:03:10 -0400203{
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400204 NSURL* fileURL;
205 if ([sender isKindOfClass:[NSMenuItem class]]) {
206 fileURL = nil;
207 } else {
208 fileURL = [[sender clickedPathComponentCell] URL];
209 }
210 [self->caListPathControl setURL:fileURL];
211 accountToCreate->setTlsCaListCertificate([[fileURL path] UTF8String]);
212
213}
214
215- (IBAction)certificatePathControlSingleClick:(id)sender
216{
217 NSURL* fileURL;
218 if ([sender isKindOfClass:[NSMenuItem class]]) {
219 fileURL = nil;
220 } else {
221 fileURL = [[sender clickedPathComponentCell] URL];
222 }
223 [self->certificatePathControl setURL:fileURL];
224 accountToCreate->setTlsCertificate([[fileURL path] UTF8String]);
225
226 auto cert = accountToCreate->tlsCertificate();
227
228 if (cert) {
229 [pvkContainer setHidden:!cert->requirePrivateKey()];
230 } else {
231 [pvkContainer setHidden:YES];
232 }
233
234}
235
236- (IBAction)pvkFilePathControlSingleClick:(id)sender
237{
238 NSURL* fileURL;
239 if ([sender isKindOfClass:[NSMenuItem class]]) {
240 fileURL = nil;
241 } else {
242 fileURL = [[sender clickedPathComponentCell] URL];
243 }
244 [self->pvkPathControl setURL:fileURL];
245 accountToCreate->setTlsPrivateKey([[fileURL path] UTF8String]);
246
247 if(accountToCreate->tlsCertificate()->requirePrivateKeyPassword()) {
248 [passwordField setHidden:NO];
249 } else {
250 [passwordField setHidden:YES];
251 }
252}
253
254/*
255 Delegate method of NSPathControl to determine how the NSOpenPanel will look/behave.
256 */
257- (void)pathControl:(NSPathControl *)pathControl willDisplayOpenPanel:(NSOpenPanel *)openPanel
258{
259 NSLog(@"willDisplayOpenPanel");
260 [openPanel setAllowsMultipleSelection:NO];
261 [openPanel setCanChooseDirectories:NO];
262 [openPanel setCanChooseFiles:YES];
263 [openPanel setResolvesAliases:YES];
264
265 if(pathControl == caListPathControl) {
266 [openPanel setTitle:NSLocalizedString(@"Choose a CA list", @"Open panel title")];
267 } else if (pathControl == certificatePathControl) {
268 [openPanel setTitle:NSLocalizedString(@"Choose a certificate", @"Open panel title")];
269 } else {
270 [openPanel setTitle:NSLocalizedString(@"Choose a private key file", @"Open panel title")];
271 }
272
273 [openPanel setPrompt:NSLocalizedString(@"Choose", @"Open panel prompt for 'Choose a file'")];
274 [openPanel setDelegate:self];
275}
276
277- (void)pathControl:(NSPathControl *)pathControl willPopUpMenu:(NSMenu *)menu
278{
279 NSMenuItem *item;
280 if(pathControl == caListPathControl) {
281 item = [menu addItemWithTitle:@"Remove value" action:@selector(caListPathControlSingleClick:) keyEquivalent:@""];
282 } else if (pathControl == certificatePathControl) {
283 item = [menu addItemWithTitle:@"Remove value" action:@selector(certificatePathControlSingleClick:) keyEquivalent:@""];
284 } else {
285 item = [menu addItemWithTitle:@"Remove value" action:@selector(pvkFilePathControlSingleClick:) keyEquivalent:@""];
286 }
287 [item setTarget:self]; // or whatever target you want
288}
289
290#pragma mark - NSOpenSavePanelDelegate delegate methods
291
292- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
293{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400294 return YES;
295}
296
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400297#pragma mark - NSTextFieldDelegate methods
298
299-(void)controlTextDidChange:(NSNotification *)notif
Alexandre Lision745e4d62015-03-22 20:03:10 -0400300{
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400301 NSTextField *textField = [notif object];
302 if (textField.tag == PVK_PASSWORD_TAG) {
303 accountToCreate->setTlsPassword([textField.stringValue UTF8String]);
304 return;
305 }
306
307 // else it is NICKNAME_TAG field
308 if ([textField.stringValue isEqualToString:@""]) {
309 [createButton setEnabled:NO];
310 } else {
311 [createButton setEnabled:YES];
312 }
313
314 accountToCreate->setAlias([textField.stringValue UTF8String]);
315 accountToCreate->setDisplayName([textField.stringValue UTF8String]);
Alexandre Lision745e4d62015-03-22 20:03:10 -0400316}
317
Alexandre Lisionb3f7ed62015-08-17 11:53:13 -0400318# pragma NSWindowDelegate methods
Alexandre Lision745e4d62015-03-22 20:03:10 -0400319
320- (void)windowWillClose:(NSNotification *)notification
321{
Alexandre Lision745e4d62015-03-22 20:03:10 -0400322 AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
323 [appDelegate showMainWindow];
324}
325
326@end