Bläddra i källkod

network login: reimplement server bookmarks using the Keychain, drop existing PLEX account management in settings in favor of this setup

Felix Paul Kühne 10 år sedan
förälder
incheckning
35933f8b40

+ 0 - 34
Resources/Settings.bundle/Root.inApp.plist

@@ -492,40 +492,6 @@
 			<key>DefaultValue</key>
 			<integer>5</integer>
 		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSGroupSpecifier</string>
-			<key>Title</key>
-			<string>SETTINGS_PLEX_TITLE</string>
-		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSTextFieldSpecifier</string>
-			<key>Title</key>
-			<string>SETTINGS_PLEX_LOGIN</string>
-			<key>Key</key>
-			<string>plex-login</string>
-			<key>DefaultValue</key>
-			<string></string>
-			<key>AutocorrectionType</key>
-			<string>NO</string>
-			<key>AutocapitalizationType</key>
-			<string>None</string>
-		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSTextFieldSpecifier</string>
-			<key>Title</key>
-			<string>SETTINGS_PLEX_PASSWORD</string>
-			<key>Key</key>
-			<string>plex-password</string>
-			<key>DefaultValue</key>
-			<string></string>
-			<key>AutocorrectionType</key>
-			<string>NO</string>
-			<key>IsSecure</key>
-			<true/>
-		</dict>
 	</array>
 	<key>StringsTable</key>
 	<string>Root</string>

+ 0 - 22
Resources/Settings.bundle/Root.plist

@@ -482,28 +482,6 @@
 			<key>DefaultValue</key>
 			<integer>5</integer>
 		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSGroupSpecifier</string>
-			<key>Title</key>
-			<string>SETTINGS_PLEX_TITLE</string>
-		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSTextFieldSpecifier</string>
-			<key>Title</key>
-			<string>SETINGS_PLEX_LOGIN</string>
-			<key>Key</key>
-			<string>plex-login</string>
-		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSTextFieldSpecifier</string>
-			<key>Title</key>
-			<string>SETINGS_PLEX_PASSWORD</string>
-			<key>Key</key>
-			<string>plex-password</string>
-		</dict>
 	</array>
 	<key>StringsTable</key>
 	<string>Root</string>

BIN
Resources/Settings.bundle/en.lproj/Root.strings


+ 8 - 8
Resources/VLCNetworkLoginViewController.xib

@@ -1,22 +1,23 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E36b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8121.17" systemVersion="14E36b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
     <dependencies>
         <deployment identifier="iOS"/>
         <development version="5000" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8101.14"/>
     </dependencies>
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCNetworkLoginViewController">
             <connections>
                 <outlet property="connectButton" destination="6" id="96"/>
-                <outlet property="historyLogin" destination="105" id="106"/>
                 <outlet property="loginHelpLabel" destination="lGc-Rk-dDO" id="q9y-NH-Vuw"/>
                 <outlet property="passwordField" destination="94" id="98"/>
                 <outlet property="portField" destination="apI-bG-FZ2" id="MIF-Oo-nwz"/>
                 <outlet property="portLabel" destination="Zhl-CE-wU8" id="zn0-t5-T93"/>
                 <outlet property="protocolSegmentedControl" destination="NYh-cy-I1V" id="ceN-Fw-Wvi"/>
+                <outlet property="saveButton" destination="axZ-sK-2Iz" id="V1h-25-LcT"/>
                 <outlet property="serverField" destination="7" id="1wI-tJ-SsR"/>
                 <outlet property="serverLabel" destination="LPm-mG-2Dr" id="wuB-QJ-2n3"/>
+                <outlet property="storedServersTableView" destination="105" id="spe-O0-i8M"/>
                 <outlet property="usernameField" destination="44" id="101"/>
                 <outlet property="view" destination="1" id="3"/>
             </connections>
@@ -25,6 +26,10 @@
         <view contentMode="scaleToFill" id="1">
             <rect key="frame" x="0.0" y="0.0" width="320" height="522"/>
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <userGuides>
+                <userLayoutGuide location="160" affinity="minX"/>
+                <userLayoutGuide location="160" affinity="minX"/>
+            </userGuides>
             <subviews>
                 <textField clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="yourserver.local" textAlignment="center" minimumFontSize="17" clearButtonMode="unlessEditing" id="7">
                     <rect key="frame" x="104" y="44" width="216" height="31"/>
@@ -131,9 +136,4 @@
             <point key="canvasLocation" x="380" y="373"/>
         </view>
     </objects>
-    <simulatedMetricsContainer key="defaultSimulatedMetrics">
-        <simulatedStatusBarMetrics key="statusBar"/>
-        <simulatedOrientationMetrics key="orientation"/>
-        <simulatedScreenMetrics key="destination" type="retina4"/>
-    </simulatedMetricsContainer>
 </document>

+ 9 - 11
Sources/VLCConstants.h

@@ -63,17 +63,6 @@
 #define kVLCPrivateWebStreaming @"private-streaming"
 #define kVLChttpScanSubtitle @"http-scan-subtitle"
 
-#define kVLCFTPServer @"ftp-server"
-#define kVLCFTPLogin @"ftp-login"
-#define kVLCFTPPassword @"ftp-pass"
-
-#define kVLCPLEXServer @"plex-server"
-#define kVLCPLEXPort @"plex-port"
-#define kVLCLastPLEXServer @"last-plex-server"
-#define kVLCLastPLEXPort @"last-plex-port"
-#define kVLCPLEXLogin @"plex-login"
-#define kVLCPLEXPassword @"plex-password"
-
 #define kSupportedFileExtensions @"\\.(3gp|3gp|3gp2|3gpp|amv|asf|avi|axv|divx|dv|flv|f4v|gvi|gxf|m1v|m2p|m2t|m2ts|m2v|m4v|mks|mkv|moov|mov|mp2v|mp4|mpeg|mpeg1|mpeg2|mpeg4|mpg|mpv|mt2s|mts|mxf|mxg|nsv|nuv|oga|ogg|ogm|ogv|ogx|spx|ps|qt|rec|rm|rmvb|tod|ts|tts|vlc|vob|vro|webm|wm|wmv|wtv|xesc)$"
 #define kSupportedSubtitleFileExtensions @"\\.(srt|sub|cdg|idx|utf|ass|ssa|aqt|jss|psb|rt|smi|txt|smil)$"
 #define kSupportedAudioFileExtensions @"\\.(aac|aiff|aif|amr|aob|ape|axa|caf|flac|it|m2a|m4a|m4b|mka|mlp|mod|mp1|mp2|mp3|mpa|mpc|mpga|oga|ogg|oma|opus|rmi|s3m|spx|tta|voc|vqf|wav|w64|wma|wv|xa|xm)$"
@@ -87,3 +76,12 @@
 #else
 #define WifiInterfaceName @"en0"
 #endif
+
+#define kVLCStoredServerList @"kVLCStoredServerList"
+
+/* LEGACY KEYS, DO NOT USE IN NEW CODE */
+#define kVLCFTPServer @"ftp-server"
+#define kVLCFTPLogin @"ftp-login"
+#define kVLCFTPPassword @"ftp-pass"
+#define kVLCPLEXServer @"plex-server"
+#define kVLCPLEXPort @"plex-port"

+ 1 - 1
Sources/VLCNetworkLoginViewController.h

@@ -40,7 +40,7 @@ confirmedWithUsername:(NSString *)username
 @property (nonatomic, strong) IBOutlet UITextField *usernameField;
 @property (nonatomic, strong) IBOutlet UITextField *passwordField;
 @property (nonatomic, strong) IBOutlet UILabel *loginHelpLabel;
-@property (nonatomic, strong) IBOutlet UITableView *historyLogin;
+@property (nonatomic, strong) IBOutlet UITableView *storedServersTableView;
 @property (nonatomic, strong) IBOutlet UIButton *saveButton;
 
 @property (nonatomic, readwrite) NSInteger serverProtocol;

+ 132 - 38
Sources/VLCNetworkLoginViewController.m

@@ -13,6 +13,7 @@
 
 #import "VLCNetworkLoginViewController.h"
 #import "VLCPlexWebAPI.h"
+#import "SSKeychain.h"
 
 @interface VLCNetworkLoginViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>
 {
@@ -21,6 +22,7 @@
     NSString *_password;
     UIActivityIndicatorView *_activityIndicator;
     UIView *_activityBackgroundView;
+    NSMutableArray *_serverList;
 }
 @end
 
@@ -37,6 +39,7 @@
     self.serverLabel.text = NSLocalizedString(@"SERVER", nil);
     self.portLabel.text = NSLocalizedString(@"SERVER_PORT", nil);
     self.loginHelpLabel.text = NSLocalizedString(@"ENTER_SERVER_CREDS_HELP", nil);
+    [self.saveButton setTitle:NSLocalizedString(@"BUTTON_SAVE", nil) forState:UIControlStateNormal];
 
     self.serverField.delegate = self;
     self.serverField.returnKeyType = UIReturnKeyNext;
@@ -50,7 +53,7 @@
     self.passwordField.delegate = self;
     self.passwordField.returnKeyType = UIReturnKeyDone;
     self.passwordField.clearButtonMode = UITextFieldViewModeWhileEditing;
-    self.historyLogin.backgroundColor = [UIColor VLCDarkBackgroundColor];
+    self.storedServersTableView.backgroundColor = [UIColor VLCDarkBackgroundColor];
 
     _activityBackgroundView = [[UIView alloc] initWithFrame:self.view.frame];
     _activityBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
@@ -93,28 +96,44 @@
         [self protocolSelectionChanged:nil];
     }
 
-    // FIXME: persistent state
-    /* 
-     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-     _bookmarkServer = [NSMutableArray arrayWithArray:[defaults objectForKey:kVLCPLEXServer]];
-     _bookmarkPort = [NSMutableArray arrayWithArray:[defaults objectForKey:kVLCPLEXPort]];
-
-     [super viewWillAppear:animated];
+    // persistent state
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    _serverList = [NSMutableArray arrayWithArray:[defaults objectForKey:kVLCStoredServerList]];
+
+    if (_serverList.count == 0) {
+        /* we need to migrate from previous, insecure storage fields */
+        NSArray *ftpServerList = [defaults objectForKey:kVLCFTPServer];
+        NSArray *ftpLoginList = [defaults objectForKey:kVLCFTPLogin];
+        NSArray *ftpPasswordList = [defaults objectForKey:kVLCFTPPassword];
+        NSUInteger count = ftpServerList.count;
+
+        if (count > 0) {
+            for (NSUInteger i = 0; i < count; i++) {
+                [SSKeychain setPassword:ftpPasswordList[i] forService:ftpServerList[i] account:ftpLoginList[i]];
+                [_serverList addObject:ftpServerList[i]];
+            }
+        }
 
-     if ([defaults stringForKey:kVLCLastPLEXServer])
-     self.serverAddressField.text = [defaults stringForKey:kVLCLastPLEXServer];
-     if ([defaults stringForKey:kVLCLastPLEXPort])
-     self.portField.text = [defaults stringForKey:kVLCLastPLEXPort];
+        NSArray *plexServerList = [defaults objectForKey:kVLCPLEXServer];
+        NSArray *plexPortList = [defaults objectForKey:kVLCPLEXPort];
+        count = plexServerList.count;
+        if (count > 0) {
+            for (NSUInteger i = 0; i < count; i++) {
+                [_serverList addObject:[NSString stringWithFormat:@"plex://%@:%@", plexServerList[i], plexPortList[i]]];
+            }
+        }
+        [defaults setObject:_serverList forKey:kVLCStoredServerList];
+        [defaults synchronize];
+    }
 
-     if (self.portField.text.length < 1)
-     self.portField.text = kPlexMediaServerPortDefault;
-     */
+    [self.storedServersTableView reloadData];
 }
 
 - (void)viewWillDisappear:(BOOL)animated
 {
-    // FIXME: persistent state?!
     [super viewWillDisappear:animated];
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [defaults setObject:_serverList forKey:kVLCStoredServerList];
 }
 
 - (IBAction)connectToServer:(id)sender
@@ -183,23 +202,51 @@
 
 - (IBAction)saveServer:(id)sender
 {
-    // FIXME:
-    /*
-    NSString *serverAddress = self.serverAddressField.text;
-    if (!serverAddress)
-        return;
-    if (serverAddress.length < 1)
+    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
+
+    NSString *server = self.serverField.text;
+    if (!server)
         return;
 
-    [_saveServer addObject:serverAddress];
-    [_saveLogin addObject:self.usernameField.text];
-    [_savePass  addObject:self.passwordField.text];
+    VLCServerProtocol protocol = self.protocolSegmentedControl.selectedSegmentIndex;
+    NSString *scheme;
+    switch (protocol) {
+        case VLCServerProtocolFTP:
+            scheme = @"ftp";
+            break;
+
+        case VLCServerProtocolSMB:
+            scheme = @"smb";
+            break;
+
+        case VLCServerProtocolPLEX:
+            scheme = @"plex";
+            break;
 
-     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-     [defaults setObject:[NSArray arrayWithArray:_bookmarkServer] forKey:kVLCPLEXServer];
-     [defaults setObject:[NSArray arrayWithArray:_bookmarkPort] forKey:kVLCPLEXPort];
+        default:
+            break;
+    }
 
-     [self.historyLogin reloadData];*/
+    NSString *port = self.portField.text;
+    NSString *service;
+    if (port.length > 0)
+        service = [NSString stringWithFormat:@"%@://%@:%@",
+                   scheme, server, port];
+    else
+        service = [NSString stringWithFormat:@"%@://%@",
+                   scheme, server];
+    [_serverList addObject:service];
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [defaults setObject:_serverList forKey:kVLCStoredServerList];
+    [defaults synchronize];
+
+    NSString *username = self.usernameField.text;
+    NSString *password = self.passwordField.text;
+
+    if (username || password)
+        [SSKeychain setPassword:password forService:service account:username];
+
+    [self.storedServersTableView reloadData];
 }
 
 - (IBAction)protocolSelectionChanged:(id)sender
@@ -210,16 +257,19 @@
         case VLCServerProtocolFTP:
         {
             self.portField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"21" attributes:@{NSForegroundColorAttributeName: color}];
+            self.portField.enabled = YES;
             break;
         }
         case VLCServerProtocolPLEX:
         {
             self.portField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"32400" attributes:@{NSForegroundColorAttributeName: color}];
+            self.portField.enabled = YES;
             break;
         }
         case VLCServerProtocolSMB:
         {
             self.portField.placeholder = @"";
+            self.portField.text = @"";
             self.portField.enabled = NO;
         }
 
@@ -252,12 +302,12 @@
 
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {
-    return 0; // FIXME: _saveServer.count;
+    return _serverList.count;
 }
 
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
-    static NSString *CellIdentifier = @"FTPHistoryCell";
+    static NSString *CellIdentifier = @"StoredServerListCell";
 
     UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil) {
@@ -267,9 +317,15 @@
     }
 
     NSInteger row = indexPath.row;
-/*  FIXME: fetch from storage
-    cell.textLabel.text = [_saveServer[row] lastPathComponent];
-    cell.detailTextLabel.text = _saveLogin[row];*/
+    NSString *serviceString = _serverList[row];
+    NSURL *service = [NSURL URLWithString:serviceString];
+    cell.textLabel.text = [NSString stringWithFormat:@"%@ [%@]", service.host, [service.scheme uppercaseString]];
+    NSArray *accounts = [SSKeychain accountsForService:serviceString];
+    if (accounts.count > 0) {
+        NSDictionary *account = [accounts firstObject];
+        cell.detailTextLabel.text = [account objectForKey:@"acct"];
+    } else
+        cell.detailTextLabel.text = @"";
 
     return cell;
 }
@@ -286,19 +342,57 @@
     return YES;
 }
 
-- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
+- (void)tableView:(UITableView *)tableView
+commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
+forRowAtIndexPath:(NSIndexPath *)indexPath
 {
     if (editingStyle == UITableViewCellEditingStyleDelete) {
-        // FIXME: remove from storage
+        NSString *serviceString = _serverList[indexPath.row];
+        NSArray *accounts = [SSKeychain accountsForService:serviceString];
+        NSUInteger count = accounts.count;
+        for (NSUInteger i = 0; i < count; i++) {
+            NSString *username = [accounts[i] objectForKey:@"acct"];
+            [SSKeychain deletePasswordForService:serviceString account:username];
+        }
+        [_serverList removeObject:serviceString];
+        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+        [defaults removeObjectForKey:serviceString];
+
         [tableView reloadData];
     }
 }
 
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
-    // FIXME: fetch from storage
+    [tableView deselectRowAtIndexPath:indexPath animated:NO];
+
+    NSString *serviceString = _serverList[indexPath.row];
+    NSURL *service = [NSURL URLWithString:serviceString];
+    NSString *scheme = service.scheme;
+
+    if ([scheme isEqualToString:@"smb"])
+        self.serverProtocol = VLCServerProtocolSMB;
+    else if ([scheme isEqualToString:@"ftp"])
+        self.serverProtocol = VLCServerProtocolFTP;
+    else if ([scheme isEqualToString:@"plex"])
+        self.serverProtocol = VLCServerProtocolPLEX;
+    self.protocolSegmentedControl.selectedSegmentIndex = self.serverProtocol;
+    [self protocolSelectionChanged:nil];
+
+    self.serverField.text = service.host;
+    self.portField.text = [service.port stringValue];
+
+    NSArray *accounts = [SSKeychain accountsForService:serviceString];
+    if (!accounts) {
+        self.usernameField.text = self.passwordField.text = @"";
+        return;
+    }
+
+    NSDictionary *account = [accounts firstObject];
 
-    [self.historyLogin deselectRowAtIndexPath:indexPath animated:NO];
+    NSString *username = [account objectForKey:@"acct"];
+    self.usernameField.text = username;
+    self.passwordField.text = [SSKeychain passwordForService:serviceString account:username];
 }
 
 - (void)setHostname:(NSString *)theHostname

+ 7 - 5
Sources/VLCPlexParser.m

@@ -11,7 +11,7 @@
 
 #import "VLCPlexParser.h"
 #import "VLCPlexWebAPI.h"
-#import "VLCConstants.h"
+#import "SSKeychain.h"
 
 #define kPlexMediaServerDirInit @"library/sections"
 #define kPlexVLCDeviceName @"VLC for iOS"
@@ -53,12 +53,14 @@
     if ([response statusCode] != 200) {
         NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
         if([responseString rangeOfString:@"Unauthorized"].location != NSNotFound) {
+            NSString *serviceString = [NSString stringWithFormat:@"plex://%@:%@", address, port];
 
-            NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
-            NSString *username = [prefs stringForKey:kVLCPLEXLogin];
-            NSString *password = [prefs stringForKey:kVLCPLEXPassword];
+            NSArray *accounts = [SSKeychain accountsForService:serviceString];
+            if (accounts) {
+                NSDictionary *account = [accounts firstObject];
+                NSString *username = [account objectForKey:@"acct"];
+                NSString *password = [SSKeychain passwordForService:serviceString account:username];
 
-            if ((username && password) && ((![username isEqualToString:@""]) && (![password isEqualToString:@""]))) {
                 auth = [PlexWebAPI PlexAuthentification:username password:password];
                 url = [NSURL URLWithString:[PlexWebAPI urlAuth:mediaServerUrl autentification:auth]];
                 request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];