mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
iOS: initial release of iFreeRDP
This is the initial release of iFreeRDP the FreeRDP iOS client. Build instructions can be found in docs/README.ios.
This commit is contained in:
46
client/iOS/Models/Bookmark.h
Normal file
46
client/iOS/Models/Bookmark.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Bookmark model abstraction
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Authors: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ConnectionParams.h"
|
||||
|
||||
@interface ComputerBookmark : NSObject <NSCoding> {
|
||||
@protected
|
||||
ComputerBookmark* _parent;
|
||||
NSString* _uuid, * _label;
|
||||
UIImage* _image;
|
||||
ConnectionParams* _connection_params;
|
||||
BOOL _connected_via_wlan;
|
||||
}
|
||||
|
||||
@property (nonatomic,assign) ComputerBookmark* parent;
|
||||
@property (nonatomic,readonly) NSString* uuid;
|
||||
@property (nonatomic,copy) NSString* label;
|
||||
@property (nonatomic,retain) UIImage* image;
|
||||
@property (readonly, nonatomic) ConnectionParams* params;
|
||||
@property (nonatomic, assign) BOOL conntectedViaWLAN;
|
||||
|
||||
// Creates a copy of this object, with a new UUID
|
||||
- (id)copy;
|
||||
|
||||
// Whether user can delete, move, or rename this entry
|
||||
- (BOOL)isDeletable;
|
||||
- (BOOL)isMovable;
|
||||
- (BOOL)isRenamable;
|
||||
- (BOOL)hasImmutableHost;
|
||||
|
||||
- (id)initWithConnectionParameters:(ConnectionParams*)params;
|
||||
- (id)initWithBaseDefaultParameters;
|
||||
|
||||
// A copy of @params, with _bookmark_uuid set.
|
||||
- (ConnectionParams*)copyMarkedParams;
|
||||
|
||||
@end
|
||||
|
||||
250
client/iOS/Models/Bookmark.m
Normal file
250
client/iOS/Models/Bookmark.m
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
Bookmark model abstraction
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#import "Bookmark.h"
|
||||
#import "TSXAdditions.h"
|
||||
#import "Utils.h"
|
||||
|
||||
#import "GlobalDefaults.h"
|
||||
|
||||
@interface ComputerBookmark (Private)
|
||||
- (void)willChangeValueForKeyPath:(NSString *)keyPath;
|
||||
- (void)didChangeValueForKeyPath:(NSString *)keyPath;
|
||||
@end
|
||||
|
||||
@implementation ComputerBookmark
|
||||
|
||||
@synthesize parent=_parent, uuid=_uuid, label=_label, image=_image;
|
||||
@synthesize params=_connection_params, conntectedViaWLAN = _connected_via_wlan;
|
||||
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_uuid = [[NSString stringWithUUID] retain];
|
||||
_label = @"";
|
||||
_connected_via_wlan = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
// Designated initializer.
|
||||
- (id)initWithConnectionParameters:(ConnectionParams*)params
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_connection_params = [params copy];
|
||||
_connected_via_wlan = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
if (!(self = [self init]))
|
||||
return nil;
|
||||
|
||||
if (![decoder allowsKeyedCoding])
|
||||
[NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
|
||||
|
||||
if ([decoder containsValueForKey:@"uuid"])
|
||||
{
|
||||
[_uuid release];
|
||||
_uuid = [[decoder decodeObjectForKey:@"uuid"] retain];
|
||||
}
|
||||
|
||||
if ([decoder containsValueForKey:@"label"])
|
||||
[self setLabel:[decoder decodeObjectForKey:@"label"]];
|
||||
|
||||
if ([decoder containsValueForKey:@"connectionParams"])
|
||||
{
|
||||
[_connection_params release];
|
||||
_connection_params = [[decoder decodeObjectForKey:@"connectionParams"] retain];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithBaseDefaultParameters
|
||||
{
|
||||
return [self initWithConnectionParameters:[[[ConnectionParams alloc] initWithBaseDefaultParameters] autorelease]];
|
||||
}
|
||||
|
||||
- (id)copy
|
||||
{
|
||||
ComputerBookmark* copy = [[[self class] alloc] init];
|
||||
[copy setLabel:[self label]];
|
||||
copy->_connection_params = [_connection_params copy];
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
if (![coder allowsKeyedCoding])
|
||||
[NSException raise:NSInvalidArgumentException format:@"coder must support keyed archiving"];
|
||||
|
||||
[coder encodeObject:_uuid forKey:@"uuid"];
|
||||
[coder encodeObject:_label forKey:@"label"];
|
||||
[coder encodeObject:_connection_params forKey:@"connectionParams"];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_parent = nil;
|
||||
[_label release]; _label = nil;
|
||||
[_uuid release]; _uuid = nil;
|
||||
[_connection_params release]; _connection_params = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (UIImage*)image
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
return [object respondsToSelector:@selector(uuid)] && [[object uuid] isEqual:_uuid];
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
{
|
||||
return ([self label] != nil) ? [self label] : _uuid;
|
||||
}
|
||||
|
||||
- (BOOL)validateValue:(id *)val forKey:(NSString *)key error:(NSError **)error
|
||||
{
|
||||
NSString* string_value = *val;
|
||||
|
||||
if ([key isEqualToString:@"label"])
|
||||
{
|
||||
if (![[string_value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length])
|
||||
{
|
||||
if (error)
|
||||
*error = [NSError errorWithDomain:@"" code:NSKeyValueValidationError userInfo:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
NSLocalizedString(@"Connection labels cannot be blank", @"Bookmark data validation: label blank title."), NSLocalizedDescriptionKey,
|
||||
NSLocalizedString(@"Please enter the short description of this Connection that will appear in the Connection list.", @"Bookmark data validation: label blank message."), NSLocalizedRecoverySuggestionErrorKey,
|
||||
nil]];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)validateValue:(id *)val forKeyPath:(NSString *)keyPath error:(NSError **)error
|
||||
{
|
||||
// Could be used to validate params.hostname, params.password, params.port, etc.
|
||||
return [super validateValue:val forKeyPath:keyPath error:error];
|
||||
}
|
||||
|
||||
- (BOOL)isDeletable { return YES; }
|
||||
- (BOOL)isMovable { return YES; }
|
||||
- (BOOL)isRenamable { return YES; }
|
||||
- (BOOL)hasImmutableHost { return NO; }
|
||||
|
||||
|
||||
#pragma mark Custom KVC
|
||||
|
||||
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
|
||||
{
|
||||
if ([keyPath isEqualToString:@"params.resolution"])
|
||||
{
|
||||
int width, height;
|
||||
TSXScreenOptions type;
|
||||
if (ScanScreenResolution(value, &width, &height, &type))
|
||||
{
|
||||
[_connection_params willChangeValueForKey:@"resolution"];
|
||||
[[self params] setInt:type forKey:@"screen_resolution_type"];
|
||||
|
||||
if (type == TSXScreenOptionFixed)
|
||||
{
|
||||
[[self params] setInt:width forKey:@"width"];
|
||||
[[self params] setInt:height forKey:@"height"];
|
||||
}
|
||||
[_connection_params didChangeValueForKey:@"resolution"];
|
||||
}
|
||||
else
|
||||
[NSException raise:NSInvalidArgumentException format:@"%s got invalid screen resolution '%@'", __func__, value];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self willChangeValueForKeyPath:keyPath];
|
||||
[super setValue:value forKeyPath:keyPath];
|
||||
[self didChangeValueForKeyPath:keyPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (id)valueForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
if ([keyPath isEqualToString:@"params.resolution"])
|
||||
return ScreenResolutionDescription([[self params] intForKey:@"screen_resolution_type"], [[self params] intForKey:@"width"], [[self params] intForKey:@"height"]);
|
||||
|
||||
return [super valueForKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
if ([[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue])
|
||||
[self willChangeValueForKeyPath:keyPath];
|
||||
else
|
||||
[self didChangeValueForKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (NSDictionary*)targetForChangeNotificationForKeyPath:(NSString*)keyPath
|
||||
{
|
||||
NSString* changed_key = keyPath;
|
||||
NSObject* changed_object = self;
|
||||
|
||||
if ([keyPath rangeOfString:@"params."].location == 0)
|
||||
{
|
||||
changed_key = [keyPath substringFromIndex:[@"params." length]];
|
||||
changed_object = _connection_params;
|
||||
}
|
||||
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys:changed_key, @"key", changed_object, @"object", nil];
|
||||
}
|
||||
|
||||
- (void)willChangeValueForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
NSDictionary* target = [self targetForChangeNotificationForKeyPath:keyPath];
|
||||
[[target objectForKey:@"object"] willChangeValueForKey:[target objectForKey:@"key"]];
|
||||
}
|
||||
|
||||
- (void)didChangeValueForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
NSDictionary* target = [self targetForChangeNotificationForKeyPath:keyPath];
|
||||
[[target objectForKey:@"object"] didChangeValueForKey:[target objectForKey:@"key"]];
|
||||
}
|
||||
|
||||
- (ConnectionParams*)copyMarkedParams
|
||||
{
|
||||
ConnectionParams* param_copy = [[self params] copy];
|
||||
[param_copy setValue:[self uuid] forKey:@"_bookmark_uuid"];
|
||||
return param_copy;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark No children
|
||||
- (NSUInteger)numberOfChildren { return 0; }
|
||||
- (NSUInteger)numberOfDescendants { return 1; }
|
||||
- (BookmarkBase *)childAtIndex:(NSUInteger)index { return nil; }
|
||||
- (NSUInteger)indexOfChild:(BookmarkBase *)child { return 0; }
|
||||
- (void)removeChild:(BookmarkBase *)child { }
|
||||
- (void)addChild:(BookmarkBase *)child { }
|
||||
- (void)addChild:(BookmarkBase *)child afterExistingChild:(BookmarkBase *)existingChild { }
|
||||
- (void)addChild:(BookmarkBase *)child atIndex:(NSInteger)index { }
|
||||
- (BOOL)hasDescendant:(BookmarkBase *)needle { return NO; }
|
||||
- (BOOL)canContainChildren { return NO; }
|
||||
@end
|
||||
|
||||
47
client/iOS/Models/ConnectionParams.h
Normal file
47
client/iOS/Models/ConnectionParams.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Connection Parameters abstraction
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface ConnectionParams : NSObject
|
||||
{
|
||||
@private
|
||||
NSMutableDictionary* _connection_params;
|
||||
}
|
||||
|
||||
// Designated initializer.
|
||||
- (id)initWithDictionary:(NSDictionary*)dict;
|
||||
- (id)initWithBaseDefaultParameters;
|
||||
|
||||
// Getting/setting values
|
||||
- (NSArray*)allKeys;
|
||||
- (void)setValue:(id)value forKey:(NSString *)key;
|
||||
- (id)valueForKey:(NSString*)key;
|
||||
- (BOOL)hasValueForKey:(NSString*)key;
|
||||
- (void)setInt:(int)integer forKey:(NSString*)key;
|
||||
- (int)intForKey:(NSString*)key;
|
||||
- (void)setBool:(BOOL)v forKey:(NSString*)key;
|
||||
- (BOOL)boolForKey:(NSString*)key;
|
||||
- (const char*)UTF8StringForKey:(NSString*)key;
|
||||
- (NSString*)StringForKey:(NSString*)key;
|
||||
|
||||
- (BOOL)hasValueForKeyPath:(NSString*)key;
|
||||
- (void)setInt:(int)integer forKeyPath:(NSString*)key;
|
||||
- (int)intForKeyPath:(NSString*)key;
|
||||
- (void)setBool:(BOOL)v forKeyPath:(NSString*)key;
|
||||
- (BOOL)boolForKeyPath:(NSString*)key;
|
||||
- (const char*)UTF8StringForKeyPath:(NSString*)key;
|
||||
- (NSString*)StringForKeyPath:(NSString*)key;
|
||||
|
||||
|
||||
- (int)intForKey:(NSString*)key with3GEnabled:(BOOL)enabled;
|
||||
- (BOOL)boolForKey:(NSString*)key with3GEnabled:(BOOL)enabled;
|
||||
|
||||
@end
|
||||
247
client/iOS/Models/ConnectionParams.m
Normal file
247
client/iOS/Models/ConnectionParams.m
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
Connection Parameters abstraction
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#import "ConnectionParams.h"
|
||||
#import "GlobalDefaults.h"
|
||||
#import "EncryptionController.h"
|
||||
#import "Utils.h"
|
||||
#import "TSXAdditions.h"
|
||||
|
||||
@interface ConnectionParams (Private)
|
||||
- (id)initWithConnectionParams:(ConnectionParams*)params;
|
||||
@end
|
||||
|
||||
@implementation ConnectionParams
|
||||
|
||||
// Designated initializer.
|
||||
- (id)initWithDictionary:(NSDictionary*)dict
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_connection_params = [dict mutableDeepCopy];
|
||||
|
||||
if ([[_connection_params objectForKey:@"password"] isKindOfClass:[NSData class]])
|
||||
{
|
||||
NSString* plaintext_password = [[[EncryptionController sharedEncryptionController] decryptor] decryptString:[_connection_params objectForKey:@"password"]];
|
||||
|
||||
[self setValue:plaintext_password forKey:@"password"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithBaseDefaultParameters
|
||||
{
|
||||
return [self initWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"TSXDefaultComputerBookmarkSettings"]];
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
return [self initWithDictionary:[NSDictionary dictionary]];
|
||||
}
|
||||
|
||||
- (id)initWithConnectionParams:(ConnectionParams*)params
|
||||
{
|
||||
return [self initWithDictionary:params->_connection_params];
|
||||
}
|
||||
- (void)dealloc
|
||||
{
|
||||
[_connection_params release]; _connection_params = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return [[ConnectionParams alloc] initWithDictionary:_connection_params];
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"ConnectionParams: %@", [_connection_params description]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSCoder
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
if ([decoder containsValueForKey:@"connectionParams"])
|
||||
return [self initWithDictionary:[decoder decodeObjectForKey:@"connectionParams"]];
|
||||
|
||||
return [self init];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder
|
||||
{
|
||||
NSSet* unserializable_keys = [NSSet setWithObjects:@"view", nil];
|
||||
NSMutableDictionary* serializable_params = [[NSMutableDictionary alloc] initWithCapacity:[_connection_params count]];
|
||||
|
||||
for (NSString* k in _connection_params)
|
||||
if ( ([k characterAtIndex:0] != '_') && ![unserializable_keys containsObject:k])
|
||||
[serializable_params setObject:[_connection_params objectForKey:k] forKey:k];
|
||||
|
||||
if ([serializable_params objectForKey:@"password"] != nil)
|
||||
{
|
||||
NSData* encrypted_password = [[[EncryptionController sharedEncryptionController] encryptor] encryptString:[serializable_params objectForKey:@"password"]];
|
||||
|
||||
if (encrypted_password)
|
||||
[serializable_params setObject:encrypted_password forKey:@"password"];
|
||||
else
|
||||
[serializable_params removeObjectForKey:@"password"];
|
||||
}
|
||||
|
||||
[coder encodeObject:serializable_params forKey:@"connectionParams"];
|
||||
[serializable_params release];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSKeyValueCoding
|
||||
|
||||
- (void)setValue:(id)value forKey:(NSString *)key
|
||||
{
|
||||
[self willChangeValueForKey:key];
|
||||
|
||||
if (value == nil)
|
||||
[self setNilValueForKey:key];
|
||||
else
|
||||
[_connection_params setValue:value forKey:key];
|
||||
|
||||
[self didChangeValueForKey:key];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)value forKeyPath:(NSString *)key
|
||||
{
|
||||
[self willChangeValueForKey:key];
|
||||
|
||||
if (value == nil)
|
||||
[self setNilValueForKey:key];
|
||||
else
|
||||
[_connection_params setValue:value forKeyPath:key];
|
||||
|
||||
[self didChangeValueForKey:key];
|
||||
}
|
||||
|
||||
- (void)setNilValueForKey:(NSString *)key
|
||||
{
|
||||
[_connection_params removeObjectForKey:key];
|
||||
}
|
||||
|
||||
- (id)valueForKey:(NSString*)key
|
||||
{
|
||||
return [_connection_params valueForKey:key];
|
||||
}
|
||||
|
||||
- (NSArray*)allKeys
|
||||
{
|
||||
return [_connection_params allKeys];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark KV convenience
|
||||
|
||||
- (BOOL)hasValueForKey:(NSString*)key
|
||||
{
|
||||
return [_connection_params objectForKey:key] != nil;
|
||||
}
|
||||
|
||||
- (void)setInt:(int)integer forKey:(NSString*)key
|
||||
{
|
||||
[self setValue:[NSNumber numberWithInteger:integer] forKey:key];
|
||||
}
|
||||
- (int)intForKey:(NSString*)key
|
||||
{
|
||||
return [[self valueForKey:key] intValue];
|
||||
}
|
||||
|
||||
|
||||
- (void)setBool:(BOOL)v forKey:(NSString*)key
|
||||
{
|
||||
[self setValue:[NSNumber numberWithBool:v] forKey:key];
|
||||
}
|
||||
- (BOOL)boolForKey:(NSString*)key
|
||||
{
|
||||
return [[_connection_params objectForKey:key] boolValue];
|
||||
}
|
||||
|
||||
|
||||
- (const char*)UTF8StringForKey:(NSString*)key
|
||||
{
|
||||
id val = [self valueForKey:key];
|
||||
const char* str;
|
||||
|
||||
if ([val respondsToSelector:@selector(UTF8String)] && (str = [val UTF8String]))
|
||||
return str;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
- (NSString*)StringForKey:(NSString*)key
|
||||
{
|
||||
return [self valueForKey:key];
|
||||
}
|
||||
|
||||
- (BOOL)hasValueForKeyPath:(NSString*)key
|
||||
{
|
||||
return [_connection_params valueForKeyPath:key] != nil;
|
||||
}
|
||||
|
||||
- (void)setInt:(int)integer forKeyPath:(NSString*)key
|
||||
{
|
||||
[self setValue:[NSNumber numberWithInteger:integer] forKeyPath:key];
|
||||
}
|
||||
- (int)intForKeyPath:(NSString*)key
|
||||
{
|
||||
return [[self valueForKeyPath:key] intValue];
|
||||
}
|
||||
|
||||
- (void)setBool:(BOOL)v forKeyPath:(NSString*)key
|
||||
{
|
||||
[self setValue:[NSNumber numberWithBool:v] forKeyPath:key];
|
||||
}
|
||||
|
||||
- (BOOL)boolForKeyPath:(NSString*)key
|
||||
{
|
||||
return [[self valueForKeyPath:key] boolValue];
|
||||
}
|
||||
|
||||
- (const char*)UTF8StringForKeyPath:(NSString*)key
|
||||
{
|
||||
id val = [self valueForKeyPath:key];
|
||||
const char* str;
|
||||
|
||||
if ([val respondsToSelector:@selector(UTF8String)] && (str = [val UTF8String]))
|
||||
return str;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
- (NSString*)StringForKeyPath:(NSString*)key
|
||||
{
|
||||
return [self valueForKeyPath:key];
|
||||
}
|
||||
|
||||
- (int)intForKey:(NSString*)key with3GEnabled:(BOOL)enabled
|
||||
{
|
||||
if (enabled && [self boolForKey:@"enable_3g_settings"])
|
||||
return [self intForKeyPath:[NSString stringWithFormat:@"settings_3g.%@", key]];
|
||||
return [self intForKeyPath:key];
|
||||
}
|
||||
|
||||
- (BOOL)boolForKey:(NSString*)key with3GEnabled:(BOOL)enabled
|
||||
{
|
||||
if (enabled && [self boolForKey:@"enable_3g_settings"])
|
||||
return [self boolForKeyPath:[NSString stringWithFormat:@"settings_3g.%@", key]];
|
||||
return [self boolForKeyPath:key];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
42
client/iOS/Models/Encryptor.h
Normal file
42
client/iOS/Models/Encryptor.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Password Encryptor
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/* Encrypts data using AES 128 with a 256 bit key derived using PBKDF2-HMAC-SHA1 */
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Encryption block cipher config
|
||||
#define TSXEncryptorBlockCipherAlgo kCCAlgorithmAES128
|
||||
#define TSXEncryptorBlockCipherKeySize kCCKeySizeAES256
|
||||
#define TSXEncryptorBlockCipherOptions kCCOptionPKCS7Padding
|
||||
#define TSXEncryptorBlockCipherBlockSize 16
|
||||
|
||||
// Key generation: If any of these are changed, existing password stores will no longer work
|
||||
#define TSXEncryptorPBKDF2Rounds 100
|
||||
#define TSXEncryptorPBKDF2Salt "9D¶3L}S¿lA[e€3C«"
|
||||
#define TSXEncryptorPBKDF2SaltLen TSXEncryptorBlockCipherOptions
|
||||
#define TSXEncryptorPBKDF2KeySize TSXEncryptorBlockCipherKeySize
|
||||
|
||||
|
||||
@interface Encryptor : NSObject {
|
||||
@private
|
||||
NSData* _encryption_key;
|
||||
NSString* _plaintext_password;
|
||||
}
|
||||
|
||||
@property(readonly) NSString* plaintextPassword;
|
||||
|
||||
- (id)initWithPassword:(NSString*)plaintext_password;
|
||||
|
||||
- (NSData*)encryptData:(NSData*)plaintext_data;
|
||||
- (NSData*)decryptData:(NSData*)encrypted_data;
|
||||
- (NSData*)encryptString:(NSString*)plaintext_string;
|
||||
- (NSString*)decryptString:(NSData*)encrypted_string;
|
||||
|
||||
@end
|
||||
173
client/iOS/Models/Encryptor.m
Normal file
173
client/iOS/Models/Encryptor.m
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
Password Encryptor
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/* We try to use CommonCrypto as much as possible. PBKDF2 was added to CommonCrypto in iOS 5, so use OpenSSL only as a fallback to do PBKDF2 on pre iOS 5 systems. */
|
||||
|
||||
#import "Encryptor.h"
|
||||
#import <CommonCrypto/CommonKeyDerivation.h>
|
||||
#import <CommonCrypto/CommonCryptor.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import <openssl/evp.h> // For PBKDF2 on < 5.0
|
||||
#include <fcntl.h>
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface Encryptor (Private)
|
||||
- (NSData*)randomInitializationVector;
|
||||
@end
|
||||
|
||||
@implementation Encryptor
|
||||
@synthesize plaintextPassword=_plaintext_password;
|
||||
|
||||
- (id)initWithPassword:(NSString*)plaintext_password
|
||||
{
|
||||
if (plaintext_password == nil)
|
||||
return nil;
|
||||
|
||||
if ( !(self = [super init]) )
|
||||
return nil;
|
||||
|
||||
_plaintext_password = [plaintext_password retain];
|
||||
const char* plaintext_password_data = [plaintext_password length] ? [plaintext_password UTF8String] : " ";
|
||||
|
||||
if (!plaintext_password_data || !strlen(plaintext_password_data))
|
||||
[NSException raise:NSInternalInconsistencyException format:@"%s: plaintext password data is zero length!", __func__];
|
||||
|
||||
|
||||
uint8_t* derived_key = calloc(1, TSXEncryptorPBKDF2KeySize);
|
||||
|
||||
if (CCKeyDerivationPBKDF != NULL)
|
||||
{
|
||||
int rounds = CCCalibratePBKDF(kCCPBKDF2, strlen(plaintext_password_data), TSXEncryptorPBKDF2SaltLen, kCCPRFHmacAlgSHA1, TSXEncryptorPBKDF2KeySize, 100);
|
||||
int ret = CCKeyDerivationPBKDF(kCCPBKDF2, plaintext_password_data, strlen(plaintext_password_data)-1, (const uint8_t*)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen, kCCPRFHmacAlgSHA1, rounds, derived_key, TSXEncryptorPBKDF2KeySize);
|
||||
//NSLog(@"CCKeyDerivationPBKDF ret = %d; key: %@", ret, [NSData dataWithBytesNoCopy:derived_key length:TWEncryptorPBKDF2KeySize freeWhenDone:NO]);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
NSLog(@"%s: CCKeyDerivationPBKDF ret == %d, indicating some sort of failure.", __func__, ret);
|
||||
[self autorelease];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// iOS 4.x or earlier -- use OpenSSL
|
||||
unsigned long ret = PKCS5_PBKDF2_HMAC_SHA1(plaintext_password_data, (int)strlen(plaintext_password_data)-1, (const unsigned char*)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen, TSXEncryptorPBKDF2Rounds, TSXEncryptorPBKDF2KeySize, derived_key);
|
||||
//NSLog(@"PKCS5_PBKDF2_HMAC_SHA1 ret = %lu; key: %@", ret, [NSData dataWithBytesNoCopy:derived_key length:TWEncryptorPBKDF2KeySize freeWhenDone:NO]);
|
||||
|
||||
if (ret != 1)
|
||||
{
|
||||
NSLog(@"%s: PKCS5_PBKDF2_HMAC_SHA1 ret == %lu, indicating some sort of failure.", __func__, ret);
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_encryption_key = [[NSData alloc] initWithBytesNoCopy:derived_key length:TSXEncryptorPBKDF2KeySize freeWhenDone:YES];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Encrypting/Decrypting data
|
||||
|
||||
- (NSData*)encryptData:(NSData*)plaintext_data
|
||||
{
|
||||
if (![plaintext_data length])
|
||||
return nil;
|
||||
|
||||
NSData* iv = [self randomInitializationVector];
|
||||
NSMutableData* encrypted_data = [NSMutableData dataWithLength:[iv length] + [plaintext_data length] + TSXEncryptorBlockCipherBlockSize];
|
||||
[encrypted_data replaceBytesInRange:NSMakeRange(0, [iv length]) withBytes:[iv bytes]];
|
||||
|
||||
size_t data_out_moved = 0;
|
||||
int ret = CCCrypt(kCCEncrypt, TSXEncryptorBlockCipherAlgo, TSXEncryptorBlockCipherOptions, [_encryption_key bytes], TSXEncryptorBlockCipherKeySize, [iv bytes], [plaintext_data bytes], [plaintext_data length], [encrypted_data mutableBytes]+[iv length], [encrypted_data length]-[iv length], &data_out_moved);
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case kCCSuccess:
|
||||
[encrypted_data setLength:[iv length] + data_out_moved];
|
||||
return encrypted_data;
|
||||
|
||||
default:
|
||||
NSLog(@"%s: uncaught error, ret CCCryptorStatus = %d (plaintext len = %lu; buffer size = %lu)", __func__, ret, (unsigned long)[plaintext_data length], (unsigned long)([encrypted_data length]-[iv length]));
|
||||
return nil;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSData*)decryptData:(NSData*)encrypted_data
|
||||
{
|
||||
if ([encrypted_data length] <= TSXEncryptorBlockCipherBlockSize)
|
||||
return nil;
|
||||
|
||||
NSMutableData* plaintext_data = [NSMutableData dataWithLength:[encrypted_data length] + TSXEncryptorBlockCipherBlockSize];
|
||||
size_t data_out_moved = 0;
|
||||
|
||||
int ret = CCCrypt(kCCDecrypt, TSXEncryptorBlockCipherAlgo, TSXEncryptorBlockCipherOptions, [_encryption_key bytes], TSXEncryptorBlockCipherKeySize, [encrypted_data bytes], [encrypted_data bytes] + TSXEncryptorBlockCipherBlockSize, [encrypted_data length] - TSXEncryptorBlockCipherBlockSize, [plaintext_data mutableBytes], [plaintext_data length], &data_out_moved);
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case kCCSuccess:
|
||||
[plaintext_data setLength:data_out_moved];
|
||||
return plaintext_data;
|
||||
|
||||
case kCCBufferTooSmall: // Our output buffer is big enough to decrypt valid data. This return code indicates malformed data.
|
||||
case kCCAlignmentError: // Shouldn't get this, since we're using padding.
|
||||
case kCCDecodeError: // Wrong key.
|
||||
return nil;
|
||||
|
||||
default:
|
||||
NSLog(@"%s: uncaught error, ret CCCryptorStatus = %d (encrypted data len = %lu; buffer size = %lu; dom = %lu)", __func__, ret, (unsigned long)[encrypted_data length], (unsigned long)[plaintext_data length], data_out_moved);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (NSData*)encryptString:(NSString*)plaintext_string
|
||||
{
|
||||
return [self encryptData:[plaintext_string dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
|
||||
- (NSString*)decryptString:(NSData*)encrypted_string
|
||||
{
|
||||
return [[[NSString alloc] initWithData:[self decryptData:encrypted_string] encoding:NSUTF8StringEncoding] autorelease];
|
||||
}
|
||||
|
||||
- (NSData*)randomInitializationVector
|
||||
{
|
||||
NSMutableData* iv = [NSMutableData dataWithLength:TSXEncryptorBlockCipherBlockSize];
|
||||
int fd;
|
||||
|
||||
if ( (fd = open("/dev/urandom", O_RDONLY)) < 0)
|
||||
return nil;
|
||||
|
||||
NSInteger bytes_needed = [iv length];
|
||||
char* p = [iv mutableBytes];
|
||||
|
||||
while (bytes_needed)
|
||||
{
|
||||
long bytes_read = read(fd, p, bytes_needed);
|
||||
|
||||
if (bytes_read < 0)
|
||||
continue;
|
||||
|
||||
p += bytes_read;
|
||||
bytes_needed -= bytes_read;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return iv;
|
||||
}
|
||||
|
||||
@end
|
||||
28
client/iOS/Models/GlobalDefaults.h
Normal file
28
client/iOS/Models/GlobalDefaults.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Global default bookmark settings
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ConnectionParams, ComputerBookmark;
|
||||
|
||||
@interface GlobalDefaults : NSObject{
|
||||
@private
|
||||
ComputerBookmark* _default_bookmark;
|
||||
}
|
||||
|
||||
+ (GlobalDefaults*)sharedGlobalDefaults;
|
||||
|
||||
// The same object is always returned from this method.
|
||||
@property (readonly,nonatomic) ComputerBookmark* bookmark;
|
||||
|
||||
- (ConnectionParams*)newParams;
|
||||
- (ComputerBookmark*)newBookmark;
|
||||
|
||||
@end
|
||||
71
client/iOS/Models/GlobalDefaults.m
Normal file
71
client/iOS/Models/GlobalDefaults.m
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Global default bookmark settings
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#import "GlobalDefaults.h"
|
||||
#import "Bookmark.h"
|
||||
#import "ConnectionParams.h"
|
||||
|
||||
@implementation GlobalDefaults
|
||||
|
||||
+ (GlobalDefaults*)sharedGlobalDefaults
|
||||
{
|
||||
static GlobalDefaults* _shared_global_defaults = nil;
|
||||
|
||||
if (_shared_global_defaults == nil)
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
if (_shared_global_defaults == nil)
|
||||
_shared_global_defaults = [[GlobalDefaults alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
return _shared_global_defaults;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
ComputerBookmark* bookmark = nil;
|
||||
NSData* bookmark_data = [[NSUserDefaults standardUserDefaults] objectForKey:@"TSXSharedGlobalDefaultBookmark"];
|
||||
|
||||
if (bookmark_data && [bookmark_data length])
|
||||
bookmark = [NSKeyedUnarchiver unarchiveObjectWithData:bookmark_data];
|
||||
|
||||
if (!bookmark)
|
||||
bookmark = [[[ComputerBookmark alloc] initWithBaseDefaultParameters] autorelease];
|
||||
|
||||
_default_bookmark = [bookmark retain];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_default_bookmark release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@synthesize bookmark=_default_bookmark;
|
||||
|
||||
- (ComputerBookmark*)newBookmark
|
||||
{
|
||||
return [[ComputerBookmark alloc] initWithConnectionParameters:[[self newParams] autorelease]];
|
||||
}
|
||||
|
||||
- (ConnectionParams*)newParams
|
||||
{
|
||||
ConnectionParams* param_copy = [[[self bookmark] params] copy];
|
||||
return param_copy;
|
||||
}
|
||||
|
||||
@end
|
||||
76
client/iOS/Models/RDPKeyboard.h
Normal file
76
client/iOS/Models/RDPKeyboard.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
RDP Keyboard helper
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "RDPSession.h"
|
||||
|
||||
@class RDPKeyboard;
|
||||
|
||||
|
||||
@protocol RDPKeyboardDelegate <NSObject>
|
||||
@optional
|
||||
- (void)modifiersChangedForKeyboard:(RDPKeyboard*)keyboard;
|
||||
@end
|
||||
|
||||
|
||||
@interface RDPKeyboard : NSObject {
|
||||
|
||||
RDPSession* _session;
|
||||
|
||||
int _virtual_key_map[256];
|
||||
int _unicode_map[256];
|
||||
NSDictionary* _special_keys;
|
||||
|
||||
NSObject<RDPKeyboardDelegate>* _delegate;
|
||||
|
||||
BOOL _ctrl_pressed;
|
||||
BOOL _alt_pressed;
|
||||
BOOL _shift_pressed;
|
||||
BOOL _win_pressed;
|
||||
}
|
||||
|
||||
@property (assign) id <RDPKeyboardDelegate> delegate;
|
||||
@property (readonly) BOOL ctrlPressed;
|
||||
@property (readonly) BOOL altPressed;
|
||||
@property (readonly) BOOL shiftPressed;
|
||||
@property (readonly) BOOL winPressed;
|
||||
|
||||
// returns a keyboard instance
|
||||
+ (RDPKeyboard*)getSharedRDPKeyboard;
|
||||
|
||||
// init the keyboard and assign the given rdp session and delegate
|
||||
- (void)initWithSession:(RDPSession*)session delegate:(NSObject<RDPKeyboardDelegate>*)delegate;
|
||||
|
||||
// called to reset any pending key states (i.e. pressed modifier keys)
|
||||
- (void)reset;
|
||||
|
||||
// sends the given unicode character to the server
|
||||
- (void)sendUnicode:(int)character;
|
||||
|
||||
// send a key stroke event using the given virtual key code
|
||||
- (void)sendVirtualKeyCode:(int)keyCode;
|
||||
|
||||
// toggle ctrl key, returns true if pressed, otherwise false
|
||||
- (void)toggleCtrlKey;
|
||||
|
||||
// toggle alt key, returns true if pressed, otherwise false
|
||||
- (void)toggleAltKey;
|
||||
|
||||
// toggle shift key, returns true if pressed, otherwise false
|
||||
- (void)toggleShiftKey;
|
||||
|
||||
// toggle windows key, returns true if pressed, otherwise false
|
||||
- (void)toggleWinKey;
|
||||
|
||||
// send key strokes
|
||||
- (void)sendEnterKeyStroke;
|
||||
- (void)sendEscapeKeyStroke;
|
||||
- (void)sendBackspaceKeyStroke;
|
||||
|
||||
@end
|
||||
306
client/iOS/Models/RDPKeyboard.m
Normal file
306
client/iOS/Models/RDPKeyboard.m
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
RDP Keyboard helper
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#import "RDPKeyboard.h"
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
@interface RDPKeyboard (Private)
|
||||
- (void)sendVirtualKey:(int)vKey up:(BOOL)up;
|
||||
- (void)handleSpecialKey:(int)character;
|
||||
- (void)handleAlphaNumChar:(int)character;
|
||||
- (void)notifyDelegateModifiersChanged;
|
||||
@end
|
||||
|
||||
@implementation RDPKeyboard
|
||||
|
||||
@synthesize delegate = _delegate, ctrlPressed = _ctrl_pressed, altPressed = _alt_pressed, shiftPressed = _shift_pressed, winPressed = _win_pressed;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if((self = [super init]) != nil)
|
||||
{
|
||||
[self initWithSession:nil delegate:nil];
|
||||
|
||||
memset(_virtual_key_map, 0, sizeof(_virtual_key_map));
|
||||
memset(_unicode_map, 0, sizeof(_unicode_map));
|
||||
|
||||
// init vkey map - used for alpha-num characters
|
||||
_virtual_key_map['0'] = VK_KEY_0;
|
||||
_virtual_key_map['1'] = VK_KEY_1;
|
||||
_virtual_key_map['2'] = VK_KEY_2;
|
||||
_virtual_key_map['3'] = VK_KEY_3;
|
||||
_virtual_key_map['4'] = VK_KEY_4;
|
||||
_virtual_key_map['5'] = VK_KEY_5;
|
||||
_virtual_key_map['6'] = VK_KEY_6;
|
||||
_virtual_key_map['7'] = VK_KEY_7;
|
||||
_virtual_key_map['8'] = VK_KEY_8;
|
||||
_virtual_key_map['9'] = VK_KEY_9;
|
||||
|
||||
_virtual_key_map['a'] = VK_KEY_A;
|
||||
_virtual_key_map['b'] = VK_KEY_B;
|
||||
_virtual_key_map['c'] = VK_KEY_C;
|
||||
_virtual_key_map['d'] = VK_KEY_D;
|
||||
_virtual_key_map['e'] = VK_KEY_E;
|
||||
_virtual_key_map['f'] = VK_KEY_F;
|
||||
_virtual_key_map['g'] = VK_KEY_G;
|
||||
_virtual_key_map['h'] = VK_KEY_H;
|
||||
_virtual_key_map['i'] = VK_KEY_I;
|
||||
_virtual_key_map['j'] = VK_KEY_J;
|
||||
_virtual_key_map['k'] = VK_KEY_K;
|
||||
_virtual_key_map['l'] = VK_KEY_L;
|
||||
_virtual_key_map['m'] = VK_KEY_M;
|
||||
_virtual_key_map['n'] = VK_KEY_N;
|
||||
_virtual_key_map['o'] = VK_KEY_O;
|
||||
_virtual_key_map['p'] = VK_KEY_P;
|
||||
_virtual_key_map['q'] = VK_KEY_Q;
|
||||
_virtual_key_map['r'] = VK_KEY_R;
|
||||
_virtual_key_map['s'] = VK_KEY_S;
|
||||
_virtual_key_map['t'] = VK_KEY_T;
|
||||
_virtual_key_map['u'] = VK_KEY_U;
|
||||
_virtual_key_map['v'] = VK_KEY_V;
|
||||
_virtual_key_map['w'] = VK_KEY_W;
|
||||
_virtual_key_map['x'] = VK_KEY_X;
|
||||
_virtual_key_map['y'] = VK_KEY_Y;
|
||||
_virtual_key_map['z'] = VK_KEY_Z;
|
||||
|
||||
// init scancode map - used for special characters
|
||||
_unicode_map['-'] = 45;
|
||||
_unicode_map['/'] = 47;
|
||||
_unicode_map[':'] = 58;
|
||||
_unicode_map[';'] = 59;
|
||||
_unicode_map['('] = 40;
|
||||
_unicode_map[')'] = 41;
|
||||
_unicode_map['&'] = 38;
|
||||
_unicode_map['@'] = 64;
|
||||
_unicode_map['.'] = 46;
|
||||
_unicode_map[','] = 44;
|
||||
_unicode_map['?'] = 63;
|
||||
_unicode_map['!'] = 33;
|
||||
_unicode_map['\''] = 39;
|
||||
_unicode_map['\"'] = 34;
|
||||
|
||||
_unicode_map['['] = 91;
|
||||
_unicode_map[']'] = 93;
|
||||
_unicode_map['{'] = 123;
|
||||
_unicode_map['}'] = 125;
|
||||
_unicode_map['#'] = 35;
|
||||
_unicode_map['%'] = 37;
|
||||
_unicode_map['^'] = 94;
|
||||
_unicode_map['*'] = 42;
|
||||
_unicode_map['+'] = 43;
|
||||
_unicode_map['='] = 61;
|
||||
|
||||
_unicode_map['_'] = 95;
|
||||
_unicode_map['\\'] = 92;
|
||||
_unicode_map['|'] = 124;
|
||||
_unicode_map['~'] = 126;
|
||||
_unicode_map['<'] = 60;
|
||||
_unicode_map['>'] = 62;
|
||||
_unicode_map['$'] = 36;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark class methods
|
||||
|
||||
// return a keyboard instance
|
||||
+ (RDPKeyboard*)getSharedRDPKeyboard
|
||||
{
|
||||
static RDPKeyboard* _shared_keyboard = nil;
|
||||
|
||||
if (_shared_keyboard == nil)
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
if (_shared_keyboard == nil)
|
||||
_shared_keyboard = [[RDPKeyboard alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
return _shared_keyboard;
|
||||
}
|
||||
|
||||
// reset the keyboard instance and assign the given rdp instance
|
||||
- (void)initWithSession:(RDPSession *)session delegate:(NSObject<RDPKeyboardDelegate> *)delegate
|
||||
{
|
||||
_alt_pressed = NO;
|
||||
_ctrl_pressed = NO;
|
||||
_shift_pressed = NO;
|
||||
_win_pressed = NO;
|
||||
|
||||
_session = session;
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
- (void)reset
|
||||
{
|
||||
// reset pressed ctrl, alt, shift or win key
|
||||
if(_shift_pressed)
|
||||
[self toggleShiftKey];
|
||||
if(_alt_pressed)
|
||||
[self toggleAltKey];
|
||||
if(_ctrl_pressed)
|
||||
[self toggleCtrlKey];
|
||||
if(_win_pressed)
|
||||
[self toggleWinKey];
|
||||
}
|
||||
|
||||
// handles button pressed input event from the iOS keyboard
|
||||
// performs all conversions etc.
|
||||
- (void)sendUnicode:(int)character
|
||||
{
|
||||
if(isalnum(character))
|
||||
[self handleAlphaNumChar:character];
|
||||
else
|
||||
[self handleSpecialKey:character];
|
||||
|
||||
[self reset];
|
||||
}
|
||||
|
||||
// send a backspace key press
|
||||
- (void)sendVirtualKeyCode:(int)keyCode
|
||||
{
|
||||
[self sendVirtualKey:keyCode up:NO];
|
||||
[self sendVirtualKey:keyCode up:YES];
|
||||
}
|
||||
|
||||
#pragma mark modifier key handling
|
||||
// toggle ctrl key, returns true if pressed, otherwise false
|
||||
- (void)toggleCtrlKey
|
||||
{
|
||||
[self sendVirtualKey:VK_LCONTROL up:_ctrl_pressed];
|
||||
_ctrl_pressed = !_ctrl_pressed;
|
||||
[self notifyDelegateModifiersChanged];
|
||||
}
|
||||
|
||||
// toggle alt key, returns true if pressed, otherwise false
|
||||
- (void)toggleAltKey
|
||||
{
|
||||
[self sendVirtualKey:VK_LMENU up:_alt_pressed];
|
||||
_alt_pressed = !_alt_pressed;
|
||||
[self notifyDelegateModifiersChanged];
|
||||
}
|
||||
|
||||
// toggle shift key, returns true if pressed, otherwise false
|
||||
- (void)toggleShiftKey
|
||||
{
|
||||
[self sendVirtualKey:VK_LSHIFT up:_shift_pressed];
|
||||
_shift_pressed = !_shift_pressed;
|
||||
[self notifyDelegateModifiersChanged];
|
||||
}
|
||||
|
||||
// toggle windows key, returns true if pressed, otherwise false
|
||||
- (void)toggleWinKey
|
||||
{
|
||||
[self sendVirtualKey:VK_LWIN up:_win_pressed];
|
||||
_win_pressed = !_win_pressed;
|
||||
[self notifyDelegateModifiersChanged];
|
||||
}
|
||||
|
||||
#pragma mark Sending special key strokes
|
||||
|
||||
- (void)sendEnterKeyStroke
|
||||
{
|
||||
[self sendVirtualKeyCode:VK_RETURN];
|
||||
}
|
||||
|
||||
- (void)sendEscapeKeyStroke
|
||||
{
|
||||
[self sendVirtualKeyCode:VK_ESCAPE];
|
||||
}
|
||||
|
||||
- (void)sendBackspaceKeyStroke
|
||||
{
|
||||
[self sendVirtualKeyCode:VK_BACK];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@implementation RDPKeyboard (Private)
|
||||
|
||||
- (void)handleAlphaNumChar:(int)character
|
||||
{
|
||||
// if we recive an uppercase letter - make it lower and send an shift down event to server
|
||||
BOOL shift_was_sent = NO;
|
||||
if(isupper(character) && _shift_pressed == NO)
|
||||
{
|
||||
character = tolower(character);
|
||||
[self sendVirtualKey:VK_SHIFT up:NO];
|
||||
shift_was_sent = YES;
|
||||
}
|
||||
|
||||
// convert the character to a VK
|
||||
int vk = _virtual_key_map[character];
|
||||
if(vk != 0)
|
||||
{
|
||||
// send key pressed
|
||||
[self sendVirtualKey:vk up:NO];
|
||||
[self sendVirtualKey:vk up:YES];
|
||||
}
|
||||
|
||||
// send the missing shift up if we had a shift down
|
||||
if(shift_was_sent)
|
||||
[self sendVirtualKey:VK_SHIFT up:YES];
|
||||
}
|
||||
|
||||
- (void)handleSpecialKey:(int)character
|
||||
{
|
||||
NSDictionary* eventDescriptor = nil;
|
||||
if(character < 256)
|
||||
{
|
||||
// convert the character to a unicode character
|
||||
int code = _unicode_map[character];
|
||||
if(code != 0)
|
||||
eventDescriptor = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"keyboard", @"type",
|
||||
@"unicode", @"subtype",
|
||||
[NSNumber numberWithUnsignedShort:0], @"flags",
|
||||
[NSNumber numberWithUnsignedShort:code], @"unicode_char",
|
||||
nil];
|
||||
}
|
||||
|
||||
if (eventDescriptor == nil)
|
||||
eventDescriptor = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"keyboard", @"type",
|
||||
@"unicode", @"subtype",
|
||||
[NSNumber numberWithUnsignedShort:0], @"flags",
|
||||
[NSNumber numberWithUnsignedShort:character], @"unicode_char",
|
||||
nil];
|
||||
|
||||
[_session sendInputEvent:eventDescriptor];
|
||||
}
|
||||
|
||||
// sends the vk code to the session
|
||||
- (void)sendVirtualKey:(int)vKey up:(BOOL)up
|
||||
{
|
||||
RDP_SCANCODE scancode = freerdp_keyboard_get_rdp_scancode_from_virtual_key_code(vKey);
|
||||
int flags = (up ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN);
|
||||
flags |= (RDP_SCANCODE_EXTENDED(scancode) ? KBD_FLAGS_EXTENDED : 0);
|
||||
[_session sendInputEvent:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"keyboard", @"type",
|
||||
@"scancode", @"subtype",
|
||||
[NSNumber numberWithUnsignedShort:flags], @"flags",
|
||||
[NSNumber numberWithUnsignedShort:RDP_SCANCODE_CODE(scancode)], @"scancode",
|
||||
nil]];
|
||||
}
|
||||
|
||||
- (void)notifyDelegateModifiersChanged
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(modifiersChangedForKeyboard:)])
|
||||
[[self delegate] modifiersChangedForKeyboard:self];
|
||||
}
|
||||
|
||||
@end
|
||||
108
client/iOS/Models/RDPSession.h
Normal file
108
client/iOS/Models/RDPSession.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
RDP Session object
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
// forward declaration
|
||||
@class RDPSession;
|
||||
@class ComputerBookmark;
|
||||
@class ConnectionParams;
|
||||
|
||||
// notification handler for session disconnect
|
||||
extern NSString* TSXSessionDidDisconnectNotification;
|
||||
extern NSString* TSXSessionDidFailToConnectNotification;
|
||||
|
||||
// protocol for session notifications
|
||||
@protocol RDPSessionDelegate <NSObject>
|
||||
@optional
|
||||
- (void)session:(RDPSession*)session didFailToConnect:(int)reason;
|
||||
- (void)sessionWillConnect:(RDPSession*)session;
|
||||
- (void)sessionDidConnect:(RDPSession*)session;
|
||||
- (void)sessionWillDisconnect:(RDPSession*)session;
|
||||
- (void)sessionDidDisconnect:(RDPSession*)session;
|
||||
- (void)sessionBitmapContextWillChange:(RDPSession*)session;
|
||||
- (void)sessionBitmapContextDidChange:(RDPSession*)session;
|
||||
- (void)session:(RDPSession*)session needsRedrawInRect:(CGRect)rect;
|
||||
- (CGSize)sizeForFitScreenForSession:(RDPSession*)session;
|
||||
- (void)showGoProScreen:(RDPSession*)session;
|
||||
|
||||
- (void)session:(RDPSession*)session requestsAuthenticationWithParams:(NSMutableDictionary*)params;
|
||||
- (void)session:(RDPSession*)session verifyCertificateWithParams:(NSMutableDictionary*)params;
|
||||
|
||||
@end
|
||||
|
||||
// rdp session
|
||||
@interface RDPSession : NSObject
|
||||
{
|
||||
@private
|
||||
freerdp* _freerdp;
|
||||
|
||||
ComputerBookmark* _bookmark;
|
||||
|
||||
ConnectionParams* _params;
|
||||
|
||||
NSObject<RDPSessionDelegate>* _delegate;
|
||||
|
||||
NSCondition* _ui_request_completed;
|
||||
|
||||
NSString* _name;
|
||||
|
||||
// flag if the session is suspended
|
||||
BOOL _suspended;
|
||||
|
||||
// flag that specifies whether the RDP toolbar is visible
|
||||
BOOL _toolbar_visible;
|
||||
}
|
||||
|
||||
@property (readonly) ConnectionParams* params;
|
||||
@property (readonly) ComputerBookmark* bookmark;
|
||||
@property (assign) id <RDPSessionDelegate> delegate;
|
||||
@property (assign) BOOL toolbarVisible;
|
||||
@property (readonly) CGContextRef bitmapContext;
|
||||
@property (readonly) NSCondition* uiRequestCompleted;
|
||||
|
||||
|
||||
// initialize a new session with the given bookmark
|
||||
- (id)initWithBookmark:(ComputerBookmark*)bookmark;
|
||||
|
||||
#pragma mark - session control functions
|
||||
|
||||
// connect the session
|
||||
-(void)connect;
|
||||
|
||||
// disconnect session
|
||||
-(void)disconnect;
|
||||
|
||||
// suspends the session
|
||||
-(void)suspend;
|
||||
|
||||
// resumes a previously suspended session
|
||||
-(void)resume;
|
||||
|
||||
// returns YES if the session is started
|
||||
-(BOOL)isSuspended;
|
||||
|
||||
// send input event to the server
|
||||
-(void)sendInputEvent:(NSDictionary*)event;
|
||||
|
||||
// session needs a refresh of its view
|
||||
- (void)setNeedsDisplayInRectAsValue:(NSValue*)rect_value;
|
||||
|
||||
// get a small session screenshot
|
||||
- (UIImage*)getScreenshotWithSize:(CGSize)size;
|
||||
|
||||
// returns the session's current paramters
|
||||
- (rdpSettings*)getSessionParams;
|
||||
|
||||
// returns the session's name (usually the label of the bookmark the session was created with)
|
||||
- (NSString*)sessionName;
|
||||
|
||||
@end
|
||||
430
client/iOS/Models/RDPSession.m
Normal file
430
client/iOS/Models/RDPSession.m
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
RDP Session object
|
||||
|
||||
Copyright 2013 Thinstuff Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#import "ios_freerdp.h"
|
||||
#import "ios_freerdp_ui.h"
|
||||
#import "ios_freerdp_events.h"
|
||||
|
||||
#import "RDPSession.h"
|
||||
#import "TSXTypes.h"
|
||||
#import "Bookmark.h"
|
||||
#import "ConnectionParams.h"
|
||||
|
||||
NSString* TSXSessionDidDisconnectNotification = @"TSXSessionDidDisconnect";
|
||||
NSString* TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect";
|
||||
|
||||
@interface RDPSession (Private)
|
||||
- (void)runSession;
|
||||
- (void)runSessionFinished:(NSNumber*)result;
|
||||
- (mfInfo*)mfi;
|
||||
|
||||
// The connection thread calls these on the main thread.
|
||||
- (void)sessionWillConnect;
|
||||
- (void)sessionDidConnect;
|
||||
- (void)sessionDidDisconnect;
|
||||
- (void)sessionDidFailToConnect:(int)reason;
|
||||
- (void)sessionBitmapContextWillChange;
|
||||
- (void)sessionBitmapContextDidChange;
|
||||
@end
|
||||
|
||||
@implementation RDPSession
|
||||
|
||||
@synthesize delegate=_delegate, params=_params, toolbarVisible = _toolbar_visible, uiRequestCompleted = _ui_request_completed, bookmark = _bookmark;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
ios_init_freerdp();
|
||||
}
|
||||
|
||||
// Designated initializer.
|
||||
- (id)initWithBookmark:(ComputerBookmark *)bookmark
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
if (!bookmark)
|
||||
[NSException raise:NSInvalidArgumentException format:@"%s: params may not be nil.", __func__];
|
||||
|
||||
_bookmark = [bookmark retain];
|
||||
_params = [[bookmark params] copy];
|
||||
_name = [[bookmark label] retain];
|
||||
_delegate = nil;
|
||||
_toolbar_visible = YES;
|
||||
_freerdp = ios_freerdp_new();
|
||||
rdpSettings* settings = _freerdp->settings;
|
||||
_ui_request_completed = [[NSCondition alloc] init];
|
||||
|
||||
BOOL connected_via_3g = ![bookmark conntectedViaWLAN];
|
||||
|
||||
// Screen Size is set on connect (we need a valid delegate in case the user choose an automatic screen size)
|
||||
|
||||
// Other simple numeric settings
|
||||
if ([_params hasValueForKey:@"colors"])
|
||||
settings->ColorDepth = [_params intForKey:@"colors" with3GEnabled:connected_via_3g];
|
||||
|
||||
if ([_params hasValueForKey:@"port"])
|
||||
settings->ServerPort = [_params intForKey:@"port"];
|
||||
|
||||
if ([_params boolForKey:@"console"])
|
||||
settings->ConsoleSession = 1;
|
||||
|
||||
// connection info
|
||||
settings->ServerHostname = strdup([_params UTF8StringForKey:@"hostname"]);
|
||||
|
||||
// String settings
|
||||
if ([[_params StringForKey:@"username"] length])
|
||||
settings->Username = strdup([_params UTF8StringForKey:@"username"]);
|
||||
|
||||
if ([[_params StringForKey:@"password"] length])
|
||||
settings->Password = strdup([_params UTF8StringForKey:@"password"]);
|
||||
|
||||
if ([[_params StringForKey:@"domain"] length])
|
||||
settings->Domain = strdup([_params UTF8StringForKey:@"domain"]);
|
||||
|
||||
settings->ShellWorkingDirectory = strdup([_params UTF8StringForKey:@"working_directory"]);
|
||||
settings->AlternateShell = strdup([_params UTF8StringForKey:@"remote_program"]);
|
||||
|
||||
|
||||
// RemoteFX
|
||||
if ([_params boolForKey:@"perf_remotefx" with3GEnabled:connected_via_3g])
|
||||
{
|
||||
settings->RemoteFxCodec = TRUE;
|
||||
settings->FastPathOutput = TRUE;
|
||||
settings->ColorDepth = 32;
|
||||
settings->LargePointerFlag = TRUE;
|
||||
settings->FrameMarkerCommandEnabled = TRUE;
|
||||
}
|
||||
|
||||
// Performance flags
|
||||
settings->DisableWallpaper = ![_params boolForKey:@"perf_show_desktop" with3GEnabled:connected_via_3g];
|
||||
settings->DisableFullWindowDrag = ![_params boolForKey:@"perf_window_dragging" with3GEnabled:connected_via_3g];
|
||||
settings->DisableMenuAnims = ![_params boolForKey:@"perf_menu_animation" with3GEnabled:connected_via_3g];
|
||||
settings->DisableThemes = ![_params boolForKey:@"perf_windows_themes" with3GEnabled:connected_via_3g];
|
||||
settings->AllowFontSmoothing = [_params boolForKey:@"perf_font_smoothing" with3GEnabled:connected_via_3g];
|
||||
settings->AllowDesktopComposition = [_params boolForKey:@"perf_desktop_composition" with3GEnabled:connected_via_3g];
|
||||
|
||||
settings->PerformanceFlags = PERF_FLAG_NONE;
|
||||
if (settings->DisableWallpaper)
|
||||
settings->PerformanceFlags |= PERF_DISABLE_WALLPAPER;
|
||||
if (settings->DisableFullWindowDrag)
|
||||
settings->PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
|
||||
if (settings->DisableMenuAnims)
|
||||
settings->PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
|
||||
if (settings->DisableThemes)
|
||||
settings->PerformanceFlags |= PERF_DISABLE_THEMING;
|
||||
if (settings->AllowFontSmoothing)
|
||||
settings->PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
|
||||
if (settings->AllowDesktopComposition)
|
||||
settings->PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
|
||||
|
||||
if ([_params hasValueForKey:@"width"])
|
||||
settings->DesktopWidth = [_params intForKey:@"width"];
|
||||
if ([_params hasValueForKey:@"height"])
|
||||
settings->DesktopHeight = [_params intForKey:@"height"];
|
||||
|
||||
// security
|
||||
switch ([_params intForKey:@"security"])
|
||||
{
|
||||
case TSXProtocolSecurityNLA:
|
||||
settings->RdpSecurity = FALSE;
|
||||
settings->TlsSecurity = FALSE;
|
||||
settings->NlaSecurity = TRUE;
|
||||
settings->ExtSecurity = FALSE;
|
||||
break;
|
||||
|
||||
case TSXProtocolSecurityTLS:
|
||||
settings->RdpSecurity = FALSE;
|
||||
settings->TlsSecurity = TRUE;
|
||||
settings->NlaSecurity = FALSE;
|
||||
settings->ExtSecurity = FALSE;
|
||||
break;
|
||||
|
||||
case TSXProtocolSecurityRDP:
|
||||
settings->RdpSecurity = TRUE;
|
||||
settings->TlsSecurity = FALSE;
|
||||
settings->NlaSecurity = FALSE;
|
||||
settings->ExtSecurity = FALSE;
|
||||
settings->DisableEncryption = TRUE;
|
||||
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
|
||||
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Remote keyboard layout
|
||||
settings->KeyboardLayout = 0x409;
|
||||
|
||||
// Audio settings
|
||||
settings->AudioPlayback = FALSE;
|
||||
settings->AudioCapture = FALSE;
|
||||
|
||||
[self mfi]->session = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self setDelegate:nil];
|
||||
[_bookmark release];
|
||||
[_name release];
|
||||
[_params release];
|
||||
[_ui_request_completed release];
|
||||
|
||||
ios_freerdp_free(_freerdp);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (CGContextRef)bitmapContext
|
||||
{
|
||||
return [self mfi]->bitmap_context;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Connecting and disconnecting
|
||||
|
||||
- (void)connect
|
||||
{
|
||||
// Set Screen Size to automatic if widht or height are still 0
|
||||
rdpSettings* settings = _freerdp->settings;
|
||||
if (settings->DesktopWidth == 0 || settings->DesktopHeight == 0)
|
||||
{
|
||||
CGSize size = CGSizeZero;
|
||||
if ([[self delegate] respondsToSelector:@selector(sizeForFitScreenForSession:)])
|
||||
size = [[self delegate] sizeForFitScreenForSession:self];
|
||||
|
||||
if (!CGSizeEqualToSize(CGSizeZero, size))
|
||||
{
|
||||
[_params setInt:size.width forKey:@"width"];
|
||||
[_params setInt:size.height forKey:@"height"];
|
||||
settings->DesktopWidth = size.width;
|
||||
settings->DesktopHeight = size.height;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is a hack to ensure connections to RDVH with 16bpp don't have an odd screen resolution width
|
||||
// Otherwise this could result in screen corruption ..
|
||||
if (settings->ColorDepth <= 16)
|
||||
settings->DesktopWidth &= (~1);
|
||||
|
||||
[self performSelectorInBackground:@selector(runSession) withObject:nil];
|
||||
}
|
||||
|
||||
- (void)disconnect
|
||||
{
|
||||
mfInfo* mfi = [self mfi];
|
||||
|
||||
ios_events_send(mfi, [NSDictionary dictionaryWithObject:@"disconnect" forKey:@"type"]);
|
||||
|
||||
if (mfi->connection_state == TSXConnectionConnecting)
|
||||
{
|
||||
mfi->unwanted = YES;
|
||||
[self sessionDidDisconnect];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (TSXConnectionState)connectionState
|
||||
{
|
||||
return [self mfi]->connection_state;
|
||||
}
|
||||
|
||||
// suspends the session
|
||||
-(void)suspend
|
||||
{
|
||||
if(!_suspended)
|
||||
{
|
||||
_suspended = YES;
|
||||
// instance->update->SuppressOutput(instance->context, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// resumes a previously suspended session
|
||||
-(void)resume
|
||||
{
|
||||
if(_suspended)
|
||||
{
|
||||
/* RECTANGLE_16 rec;
|
||||
rec.left = 0;
|
||||
rec.top = 0;
|
||||
rec.right = instance->settings->width;
|
||||
rec.bottom = instance->settings->height;
|
||||
*/
|
||||
_suspended = NO;
|
||||
// instance->update->SuppressOutput(instance->context, 1, &rec);
|
||||
// [delegate sessionScreenSettingsChanged:self];
|
||||
}
|
||||
}
|
||||
|
||||
// returns YES if the session is started
|
||||
-(BOOL)isSuspended
|
||||
{
|
||||
return _suspended;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Input events
|
||||
|
||||
- (void)sendInputEvent:(NSDictionary*)eventDescriptor
|
||||
{
|
||||
if ([self mfi]->connection_state == TSXConnectionConnected)
|
||||
ios_events_send([self mfi], eventDescriptor);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Server events (main thread)
|
||||
|
||||
- (void)setNeedsDisplayInRectAsValue:(NSValue*)rect_value
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(session:needsRedrawInRect:)])
|
||||
[[self delegate] session:self needsRedrawInRect:[rect_value CGRectValue]];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark interface functions
|
||||
|
||||
- (UIImage*)getScreenshotWithSize:(CGSize)size
|
||||
{
|
||||
NSAssert([self mfi]->bitmap_context != nil, @"Screenshot requested while having no valid RDP drawing context");
|
||||
|
||||
CGImageRef cgImage = CGBitmapContextCreateImage([self mfi]->bitmap_context);
|
||||
UIGraphicsBeginImageContext(size);
|
||||
|
||||
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, size.height);
|
||||
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
|
||||
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, size.height), cgImage);
|
||||
|
||||
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
UIGraphicsEndImageContext();
|
||||
CGImageRelease(cgImage);
|
||||
|
||||
return viewImage;
|
||||
}
|
||||
|
||||
- (rdpSettings*)getSessionParams
|
||||
{
|
||||
return _freerdp->settings;
|
||||
}
|
||||
|
||||
- (NSString*)sessionName
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@implementation RDPSession (Private)
|
||||
|
||||
- (mfInfo*)mfi
|
||||
{
|
||||
return MFI_FROM_INSTANCE(_freerdp);
|
||||
}
|
||||
|
||||
// Blocks until rdp session finishes.
|
||||
- (void)runSession
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// Run the session
|
||||
[self performSelectorOnMainThread:@selector(sessionWillConnect) withObject:nil waitUntilDone:YES];
|
||||
int result_code = ios_run_freerdp(_freerdp);
|
||||
[self mfi]->connection_state = TSXConnectionDisconnected;
|
||||
[self performSelectorOnMainThread:@selector(runSessionFinished:) withObject:[NSNumber numberWithInt:result_code] waitUntilDone:YES];
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
// Main thread.
|
||||
- (void)runSessionFinished:(NSNumber*)result
|
||||
{
|
||||
int result_code = [result intValue];
|
||||
|
||||
switch (result_code)
|
||||
{
|
||||
case MF_EXIT_CONN_CANCELED:
|
||||
[self sessionDidDisconnect];
|
||||
break;
|
||||
case MF_EXIT_LOGON_TIMEOUT:
|
||||
case MF_EXIT_CONN_FAILED:
|
||||
[self sessionDidFailToConnect:result_code];
|
||||
break;
|
||||
case MF_EXIT_SUCCESS:
|
||||
default:
|
||||
[self sessionDidDisconnect];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Session management (main thread)
|
||||
|
||||
- (void)sessionWillConnect
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(sessionWillConnect:)])
|
||||
[[self delegate] sessionWillConnect:self];
|
||||
}
|
||||
|
||||
- (void)sessionDidConnect
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(sessionDidConnect:)])
|
||||
[[self delegate] sessionDidConnect:self];
|
||||
}
|
||||
|
||||
- (void)sessionDidFailToConnect:(int)reason
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:TSXSessionDidFailToConnectNotification object:self];
|
||||
|
||||
if ([[self delegate] respondsToSelector:@selector(session:didFailToConnect:)])
|
||||
[[self delegate] session:self didFailToConnect:reason];
|
||||
}
|
||||
|
||||
- (void)sessionDidDisconnect
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:TSXSessionDidDisconnectNotification object:self];
|
||||
|
||||
if ([[self delegate] respondsToSelector:@selector(sessionDidDisconnect:)])
|
||||
[[self delegate] sessionDidDisconnect:self];
|
||||
}
|
||||
|
||||
- (void)sessionBitmapContextWillChange
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(sessionBitmapContextWillChange:)])
|
||||
[[self delegate] sessionBitmapContextWillChange:self];
|
||||
}
|
||||
|
||||
- (void)sessionBitmapContextDidChange
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(sessionBitmapContextDidChange:)])
|
||||
[[self delegate] sessionBitmapContextDidChange:self];
|
||||
}
|
||||
|
||||
- (void)showGoProScreen
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(showGoProScreen:)])
|
||||
[[self delegate] showGoProScreen:self];
|
||||
}
|
||||
|
||||
- (void)sessionRequestsAuthenticationWithParams:(NSMutableDictionary*)params
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(session:requestsAuthenticationWithParams:)])
|
||||
[[self delegate] session:self requestsAuthenticationWithParams:params];
|
||||
}
|
||||
|
||||
- (void)sessionVerifyCertificateWithParams:(NSMutableDictionary*)params
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(session:verifyCertificateWithParams:)])
|
||||
[[self delegate] session:self verifyCertificateWithParams:params];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user