Jelajahi Sumber

Local Network: implement folder listing and browsing via FTP

Felix Paul Kühne 12 tahun lalu
induk
melakukan
3bb5575f07

+ 2 - 1
AspenProject/VLCLocalServerFolderListViewController.h

@@ -16,6 +16,7 @@
 
 @property (nonatomic, strong) UITableView *tableView;
 
-- (id)initWithUPNPDevice:(MediaServer1Device*)device header:(NSString*)header andRootID:(NSString*)rootID;
+- (id)initWithUPNPDevice:(MediaServer1Device *)device header:(NSString *)header andRootID:(NSString *)rootID;
+- (id)initWithFTPServer:(NSString *)serverAddress userName:(NSString *)username andPassword:(NSString *)password atPath:(NSString *)path;
 
 @end

+ 95 - 2
AspenProject/VLCLocalServerFolderListViewController.m

@@ -17,20 +17,31 @@
 #import "VLCAppDelegate.h"
 #import "VLCPlaylistViewController.h"
 #import "UINavigationController+Theme.h"
+#import "WhiteRaccoon.h"
 
 #define kVLCUPNPFileServer 0
 #define kVLCFTPServer 1
 
-@interface VLCLocalServerFolderListViewController () <UITableViewDataSource, UITableViewDelegate>
+@interface VLCLocalServerFolderListViewController () <UITableViewDataSource, UITableViewDelegate, WRRequestDelegate>
 {
+    /* UI */
     UIBarButtonItem *_backButton;
 
+    /* generic data storage */
     NSString *_listTitle;
     NSMutableArray *_objectList;
     NSUInteger _serverType;
 
+    /* UPNP specifics */
     MediaServer1Device *_UPNPdevice;
     NSString *_UPNProotID;
+
+    /* FTP specifics */
+    NSString *_ftpServerAddress;
+    NSString *_ftpServerUserName;
+    NSString *_ftpServerPassword;
+    NSString *_ftpServerPath;
+    WRRequestListDirectory *_listDirRequest;
 }
 
 @end
@@ -55,8 +66,21 @@
         _listTitle = header;
         _UPNProotID = rootID;
         _serverType = kVLCUPNPFileServer;
+    }
+
+    return self;
+}
+
+- (id)initWithFTPServer:(NSString *)serverAddress userName:(NSString *)username andPassword:(NSString *)password atPath:(NSString *)path
+{
+    self = [super init];
 
-        _objectList = [[NSMutableArray alloc] init];
+    if (self) {
+        _ftpServerAddress = serverAddress;
+        _ftpServerUserName = username;
+        _ftpServerPassword = password;
+        _ftpServerPath = path;
+        _serverType = kVLCFTPServer;
     }
 
     return self;
@@ -66,6 +90,8 @@
 {
     [super viewDidLoad];
 
+    _objectList = [[NSMutableArray alloc] init];
+
     if (_serverType == kVLCUPNPFileServer) {
         NSMutableString *outResult = [[NSMutableString alloc] init];
         NSMutableString *outNumberReturned = [[NSMutableString alloc] init];
@@ -77,6 +103,12 @@
         NSData *didl = [outResult dataUsingEncoding:NSUTF8StringEncoding];
         MediaServerBasicObjectParser *parser = [[MediaServerBasicObjectParser alloc] initWithMediaObjectArray:_objectList itemsOnly:NO];
         [parser parseFromData:didl];
+    } else if (_serverType == kVLCFTPServer) {
+        if ([_ftpServerPath isEqualToString:@"/"])
+            _listTitle = _ftpServerAddress;
+        else
+            _listTitle = [_ftpServerPath lastPathComponent];
+        [self _listFTPDirectory];
     }
 
     self.tableView.separatorColor = [UIColor colorWithWhite:.122 alpha:1.];
@@ -124,6 +156,16 @@
             [cell setIcon:[UIImage imageNamed:@"folder"]];
         }
         [cell setTitle:[item title]];
+    } else if (_serverType == kVLCFTPServer) {
+        cell.title = [_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceName];
+        if ([[_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceType] intValue] == 4) {
+            cell.isDirectory = YES;
+            cell.icon = [UIImage imageNamed:@"folder"];
+        } else {
+            cell.isDirectory = NO;
+            cell.icon = [UIImage imageNamed:@"blank"];
+            cell.subtitle = [NSString stringWithFormat:@"%0.2f MB", [[_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceType] intValue], (float)([[_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceSize] intValue] / 1e6)];
+        }
     }
 
     return cell;
@@ -167,7 +209,58 @@
                 [appDelegate.playlistViewController performSelector:@selector(openMovieFromURL:) withObject:itemURL afterDelay:kGHRevealSidebarDefaultAnimationDuration];
             }
         }
+    } else if (_serverType == kVLCFTPServer) {
+        if ([[_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceType] intValue] == 4) {
+            NSString *newPath;
+            if ([_ftpServerPath hasSuffix:@"/"])
+                newPath = [NSString stringWithFormat:@"%@%@", _ftpServerPath, [_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceName]];
+            else
+                newPath = [NSString stringWithFormat:@"%@/%@", _ftpServerPath, [_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceName]];
+
+            VLCLocalServerFolderListViewController *targetViewController = [[VLCLocalServerFolderListViewController alloc] initWithFTPServer:_ftpServerAddress userName:_ftpServerUserName andPassword:_ftpServerPassword atPath:newPath];
+            [self.navigationController pushViewController:targetViewController animated:YES];
+        } else {
+            NSLog(@"user would like to fetch %@", [_objectList[indexPath.row] objectForKey:(id)kCFFTPResourceName]);
+        }
     }
 }
 
+#pragma mark - FTP specifics
+- (void)_listFTPDirectory
+{
+    if (_listDirRequest)
+        return;
+
+    _listDirRequest = [[WRRequestListDirectory alloc] init];
+    _listDirRequest.delegate = self;
+    _listDirRequest.hostname = _ftpServerAddress;
+    _listDirRequest.username = _ftpServerUserName;
+    _listDirRequest.password = _ftpServerPassword;
+    _listDirRequest.path = _ftpServerPath;
+
+    [_listDirRequest start];
+}
+
+- (void)requestCompleted:(WRRequest *)request
+{
+    if (request == _listDirRequest) {
+        NSMutableArray *filteredList = [[NSMutableArray alloc] init];
+        NSArray *rawList = [(WRRequestListDirectory*)request filesInfo];
+        NSUInteger count = rawList.count;
+
+        for (NSUInteger x = 0; x < count; x++) {
+            if (![[rawList[x] objectForKey:(id)kCFFTPResourceName] hasPrefix:@"."])
+                [filteredList addObject:rawList[x]];
+        }
+
+        _objectList = [NSArray arrayWithArray:filteredList];
+        [self.tableView reloadData];
+    }
+}
+
+- (void)requestFailed:(WRRequest *)request
+{
+    APLog(@"request %@ failed with error %i message '%@'", request, request.error.errorCode, request.error.message);
+}
+
 @end

+ 10 - 4
AspenProject/VLCLocalServerListViewController.m

@@ -200,7 +200,7 @@
             [self presentModalViewController:navCon animated:YES];
 
             if (_loginViewController.navigationItem.leftBarButtonItem == nil) {
-                UIBarButtonItem *doneButton = [UIBarButtonItem themedDoneButtonWithTarget:_loginViewController andSelector:@selector(dismiss:)];
+                UIBarButtonItem *doneButton = [UIBarButtonItem themedDoneButtonWithTarget:_loginViewController andSelector:@selector(dismissWithAnimation:)];
 
                 _loginViewController.navigationItem.leftBarButtonItem = doneButton;
             }
@@ -211,10 +211,16 @@
 
 #pragma mark - login panel protocol
 
-- (void)loginToServer:(NSString *)server confirmedWithUsername:(NSString *)username andPassword:(NSString *)password
+- (void)loginToURL:(NSURL *)url confirmedWithUsername:(NSString *)username andPassword:(NSString *)password
 {
     _loginViewController = nil;
-    NSLog(@"user wants to connect to %@ with %@/%@", server, username, password);
+    if ([url.scheme isEqualToString:@"ftp"]) {
+        if (url.host.length > 0) {
+            VLCLocalServerFolderListViewController *targetViewController = [[VLCLocalServerFolderListViewController alloc] initWithFTPServer:url.host userName:username andPassword:password atPath:@"/"];
+            [self.navigationController pushViewController:targetViewController animated:YES];
+        }
+    } else
+        APLog(@"Unsupported URL Scheme requested %@", url.scheme);
 }
 
 #pragma mark - custom table view appearance
@@ -262,7 +268,7 @@
     APLog(@"found bonjour service: %@ (%@)", aNetService.name, aNetService.type);
     [_rawServices addObject:aNetService];
     aNetService.delegate = self;
-    [aNetService resolveWithTimeout:3.];
+    [aNetService resolveWithTimeout:5.];
 }
 
 - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing