Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
48
third_party/FreeRDP/client/iOS/Models/Bookmark.h
vendored
Normal file
48
third_party/FreeRDP/client/iOS/Models/Bookmark.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Bookmark model abstraction
|
||||
|
||||
Copyright 2013 Thincast 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 <UIKit/UIKit.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;
|
||||
- (id)copyWithUUID;
|
||||
|
||||
// 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
|
||||
312
third_party/FreeRDP/client/iOS/Models/Bookmark.m
vendored
Normal file
312
third_party/FreeRDP/client/iOS/Models/Bookmark.m
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
Bookmark model abstraction
|
||||
|
||||
Copyright 2013 Thincast 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 = [self 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;
|
||||
}
|
||||
|
||||
- (id)copyWithUUID
|
||||
{
|
||||
ComputerBookmark *copy = [self copy];
|
||||
copy->_uuid = [[self uuid] 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
|
||||
46
third_party/FreeRDP/client/iOS/Models/ConnectionParams.h
vendored
Normal file
46
third_party/FreeRDP/client/iOS/Models/ConnectionParams.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Connection Parameters abstraction
|
||||
|
||||
Copyright 2013 Thincast 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
|
||||
258
third_party/FreeRDP/client/iOS/Models/ConnectionParams.m
vendored
Normal file
258
third_party/FreeRDP/client/iOS/Models/ConnectionParams.m
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
Connection Parameters abstraction
|
||||
|
||||
Copyright 2013 Thincast 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];
|
||||
|
||||
[self decryptPasswordForKey:@"password"];
|
||||
[self decryptPasswordForKey:@"tsg_password"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)decryptPasswordForKey:(NSString *)key
|
||||
{
|
||||
if ([[_connection_params objectForKey:key] isKindOfClass:[NSData class]])
|
||||
{
|
||||
NSString *plaintext_password = [[[EncryptionController sharedEncryptionController]
|
||||
decryptor] decryptString:[_connection_params objectForKey:key]];
|
||||
[self setValue:plaintext_password forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (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)
|
||||
[self serializeDecryptedForKey:@"password" forParams:serializable_params];
|
||||
if ([serializable_params objectForKey:@"tsg_password"] != nil)
|
||||
[self serializeDecryptedForKey:@"tsg_password" forParams:serializable_params];
|
||||
|
||||
[coder encodeObject:serializable_params forKey:@"connectionParams"];
|
||||
[serializable_params release];
|
||||
}
|
||||
|
||||
- (void)serializeDecryptedForKey:(NSString *)key forParams:(NSMutableDictionary *)params
|
||||
{
|
||||
NSData *encrypted_password = [[[EncryptionController sharedEncryptionController] encryptor]
|
||||
encryptString:[params objectForKey:key]];
|
||||
|
||||
if (encrypted_password)
|
||||
[params setObject:encrypted_password forKey:key];
|
||||
else
|
||||
[params removeObjectForKey:key];
|
||||
}
|
||||
|
||||
#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
|
||||
43
third_party/FreeRDP/client/iOS/Models/Encryptor.h
vendored
Normal file
43
third_party/FreeRDP/client/iOS/Models/Encryptor.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Password Encryptor
|
||||
|
||||
Copyright 2013 Thincast 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
|
||||
206
third_party/FreeRDP/client/iOS/Models/Encryptor.m
vendored
Normal file
206
third_party/FreeRDP/client/iOS/Models/Encryptor.m
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
Password Encryptor
|
||||
|
||||
Copyright 2013 Thincast 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 != nullptr)
|
||||
{
|
||||
int ret = CCKeyDerivationPBKDF(
|
||||
kCCPBKDF2, plaintext_password_data, strlen(plaintext_password_data) - 1,
|
||||
(const uint8_t *)TSXEncryptorPBKDF2Salt, TSXEncryptorPBKDF2SaltLen, kCCPRFHmacAlgSHA1,
|
||||
TSXEncryptorPBKDF2Rounds, 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);
|
||||
free(derived_key);
|
||||
[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);
|
||||
free(derived_key);
|
||||
[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
|
||||
30
third_party/FreeRDP/client/iOS/Models/GlobalDefaults.h
vendored
Normal file
30
third_party/FreeRDP/client/iOS/Models/GlobalDefaults.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Global default bookmark settings
|
||||
|
||||
Copyright 2013 Thincast 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;
|
||||
- (ComputerBookmark *)newTestServerBookmark;
|
||||
|
||||
@end
|
||||
88
third_party/FreeRDP/client/iOS/Models/GlobalDefaults.m
vendored
Normal file
88
third_party/FreeRDP/client/iOS/Models/GlobalDefaults.m
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Global default bookmark settings
|
||||
|
||||
Copyright 2013 Thincast 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;
|
||||
}
|
||||
|
||||
- (ComputerBookmark *)newTestServerBookmark
|
||||
{
|
||||
ComputerBookmark *bm = [self newBookmark];
|
||||
[bm setLabel:@"Test Server"];
|
||||
[[bm params] setValue:@"testservice.ifreerdp.com" forKey:@"hostname"];
|
||||
[[bm params] setInt:0 forKey:@"screen_resolution_type"];
|
||||
[[bm params] setInt:1024 forKey:@"width"];
|
||||
[[bm params] setInt:768 forKey:@"height"];
|
||||
[[bm params] setInt:32 forKey:@"colors"];
|
||||
[[bm params] setBool:YES forKey:@"perf_remotefx"];
|
||||
[[bm params] setBool:YES forKey:@"perf_gfx"];
|
||||
[[bm params] setBool:YES forKey:@"perf_h264"];
|
||||
return bm;
|
||||
}
|
||||
|
||||
@end
|
||||
76
third_party/FreeRDP/client/iOS/Models/RDPKeyboard.h
vendored
Normal file
76
third_party/FreeRDP/client/iOS/Models/RDPKeyboard.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
RDP Keyboard helper
|
||||
|
||||
Copyright 2013 Thincast 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
|
||||
310
third_party/FreeRDP/client/iOS/Models/RDPKeyboard.m
vendored
Normal file
310
third_party/FreeRDP/client/iOS/Models/RDPKeyboard.m
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
RDP Keyboard helper
|
||||
|
||||
Copyright 2013 Thincast 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 | KBDEXT) up:_win_pressed];
|
||||
_win_pressed = !_win_pressed;
|
||||
[self notifyDelegateModifiersChanged];
|
||||
}
|
||||
|
||||
#pragma mark Sending special key strokes
|
||||
|
||||
- (void)sendEnterKeyStroke
|
||||
{
|
||||
[self sendVirtualKeyCode:(VK_RETURN | KBDEXT)];
|
||||
}
|
||||
|
||||
- (void)sendEscapeKeyStroke
|
||||
{
|
||||
[self sendVirtualKeyCode:VK_ESCAPE];
|
||||
}
|
||||
|
||||
- (void)sendBackspaceKeyStroke
|
||||
{
|
||||
[self sendVirtualKeyCode:VK_BACK];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@implementation RDPKeyboard (Private)
|
||||
|
||||
- (void)handleAlphaNumChar:(int)character
|
||||
{
|
||||
// if we receive 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_LSHIFT 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_LSHIFT 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
|
||||
{
|
||||
DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(vKey, 4);
|
||||
int flags = (up ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN);
|
||||
flags |= ((scancode & KBDEXT) ? KBD_FLAGS_EXTENDED : 0);
|
||||
[_session
|
||||
sendInputEvent:[NSDictionary
|
||||
dictionaryWithObjectsAndKeys:@"keyboard", @"type", @"scancode",
|
||||
@"subtype",
|
||||
[NSNumber numberWithUnsignedShort:flags],
|
||||
@"flags",
|
||||
[NSNumber
|
||||
numberWithUnsignedShort:(scancode &
|
||||
0xFF)],
|
||||
@"scancode", nil]];
|
||||
}
|
||||
|
||||
- (void)notifyDelegateModifiersChanged
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(modifiersChangedForKeyboard:)])
|
||||
[[self delegate] modifiersChangedForKeyboard:self];
|
||||
}
|
||||
|
||||
@end
|
||||
109
third_party/FreeRDP/client/iOS/Models/RDPSession.h
vendored
Normal file
109
third_party/FreeRDP/client/iOS/Models/RDPSession.h
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
RDP Session object
|
||||
|
||||
Copyright 2013 Thincast 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>
|
||||
#import <UIKit/UIKit.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)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 parameters
|
||||
- (rdpSettings *)getSessionParams;
|
||||
|
||||
// returns the session's name (usually the label of the bookmark the session was created with)
|
||||
- (NSString *)sessionName;
|
||||
|
||||
@end
|
||||
534
third_party/FreeRDP/client/iOS/Models/RDPSession.m
vendored
Normal file
534
third_party/FreeRDP/client/iOS/Models/RDPSession.m
vendored
Normal file
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
RDP Session object
|
||||
|
||||
Copyright 2013 Thincast 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();
|
||||
}
|
||||
|
||||
static BOOL addArgument(int *argc, char ***argv, const char *fmt, ...)
|
||||
{
|
||||
va_list ap = WINPR_C_ARRAY_INIT;
|
||||
char *arg = nullptr;
|
||||
char **tmp = realloc(*argv, (*argc + 1) * sizeof(char *));
|
||||
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
|
||||
*argv = tmp;
|
||||
*argc = *argc + 1;
|
||||
va_start(ap, fmt);
|
||||
vasprintf(&arg, fmt, ap);
|
||||
va_end(ap);
|
||||
(*argv)[*argc - 1] = arg;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL addFlag(int *argc, char ***argv, const char *str, BOOL flag)
|
||||
{
|
||||
return addArgument(argc, argv, "%s%s", flag ? "+" : "-", str);
|
||||
}
|
||||
|
||||
static void freeArguments(int argc, char **argv)
|
||||
{
|
||||
for (int i = 0; i < argc; i++)
|
||||
free(argv[i]);
|
||||
|
||||
free(argv);
|
||||
}
|
||||
|
||||
// Designated initializer.
|
||||
- (id)initWithBookmark:(ComputerBookmark *)bookmark
|
||||
{
|
||||
int status;
|
||||
char **argv = nullptr;
|
||||
int argc = 0;
|
||||
|
||||
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();
|
||||
_ui_request_completed = [[NSCondition alloc] init];
|
||||
BOOL connected_via_3g = ![bookmark conntectedViaWLAN];
|
||||
|
||||
if (!addArgument(&argc, &argv, "iFreeRDP"))
|
||||
goto out_free;
|
||||
|
||||
if (!addArgument(&argc, &argv, "/gdi:sw"))
|
||||
goto out_free;
|
||||
|
||||
// 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"])
|
||||
if (!addArgument(&argc, &argv, "/bpp:%d",
|
||||
[_params intForKey:@"colors" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if ([_params hasValueForKey:@"port"])
|
||||
if (!addArgument(&argc, &argv, "/port:%d", [_params intForKey:@"port"]))
|
||||
goto out_free;
|
||||
|
||||
if ([_params boolForKey:@"console"])
|
||||
if (!addArgument(&argc, &argv, "/admin"))
|
||||
goto out_free;
|
||||
|
||||
if (!addArgument(&argc, &argv, "/v:%s", [_params UTF8StringForKey:@"hostname"]))
|
||||
goto out_free;
|
||||
|
||||
// String settings
|
||||
if ([[_params StringForKey:@"username"] length])
|
||||
{
|
||||
if (!addArgument(&argc, &argv, "/u:%s", [_params UTF8StringForKey:@"username"]))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if ([[_params StringForKey:@"password"] length])
|
||||
{
|
||||
if (!addArgument(&argc, &argv, "/p:%s", [_params UTF8StringForKey:@"password"]))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if ([[_params StringForKey:@"domain"] length])
|
||||
{
|
||||
if (!addArgument(&argc, &argv, "/d:%s", [_params UTF8StringForKey:@"domain"]))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if ([[_params StringForKey:@"working_directory"] length])
|
||||
{
|
||||
if (!addArgument(&argc, &argv, "/shell-dir:%s",
|
||||
[_params UTF8StringForKey:@"working_directory"]))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if ([[_params StringForKey:@"remote_program"] length])
|
||||
{
|
||||
if (!addArgument(&argc, &argv, "/shell:%s", [_params UTF8StringForKey:@"remote_program"]))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
// RemoteFX
|
||||
if ([_params boolForKey:@"perf_remotefx" with3GEnabled:connected_via_3g])
|
||||
if (!addArgument(&argc, &argv, "/rfx"))
|
||||
goto out_free;
|
||||
|
||||
if ([_params boolForKey:@"perf_gfx" with3GEnabled:connected_via_3g])
|
||||
if (!addArgument(&argc, &argv, "/gfx"))
|
||||
goto out_free;
|
||||
|
||||
if ([_params boolForKey:@"perf_h264" with3GEnabled:connected_via_3g])
|
||||
if (!addArgument(&argc, &argv, "/gfx-h264"))
|
||||
goto out_free;
|
||||
|
||||
if (![_params boolForKey:@"perf_remotefx" with3GEnabled:connected_via_3g] &&
|
||||
![_params boolForKey:@"perf_gfx" with3GEnabled:connected_via_3g] &&
|
||||
![_params boolForKey:@"perf_h264" with3GEnabled:connected_via_3g])
|
||||
if (!addArgument(&argc, &argv, "/nsc"))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "bitmap-cache", TRUE))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "wallpaper",
|
||||
[_params boolForKey:@"perf_show_desktop" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "window-drag",
|
||||
[_params boolForKey:@"perf_window_dragging" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "menu-anims",
|
||||
[_params boolForKey:@"perf_menu_animation" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "themes",
|
||||
[_params boolForKey:@"perf_windows_themes" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "fonts",
|
||||
[_params boolForKey:@"perf_font_smoothing" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if (!addFlag(&argc, &argv, "aero",
|
||||
[_params boolForKey:@"perf_desktop_composition" with3GEnabled:connected_via_3g]))
|
||||
goto out_free;
|
||||
|
||||
if ([_params hasValueForKey:@"width"])
|
||||
if (!addArgument(&argc, &argv, "/w:%d", [_params intForKey:@"width"]))
|
||||
goto out_free;
|
||||
|
||||
if ([_params hasValueForKey:@"height"])
|
||||
if (!addArgument(&argc, &argv, "/h:%d", [_params intForKey:@"height"]))
|
||||
goto out_free;
|
||||
|
||||
// security
|
||||
switch ([_params intForKey:@"security"])
|
||||
{
|
||||
case TSXProtocolSecurityNLA:
|
||||
if (!addArgument(&argc, &argv, "/sec:NLA"))
|
||||
goto out_free;
|
||||
|
||||
break;
|
||||
|
||||
case TSXProtocolSecurityTLS:
|
||||
if (!addArgument(&argc, &argv, "/sec:TLS"))
|
||||
goto out_free;
|
||||
|
||||
break;
|
||||
|
||||
case TSXProtocolSecurityRDP:
|
||||
if (!addArgument(&argc, &argv, "/sec:RDP"))
|
||||
goto out_free;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// ts gateway settings
|
||||
if ([_params boolForKey:@"enable_tsg_settings"])
|
||||
{
|
||||
if (!addArgument(&argc, &argv, "/g:%s", [_params UTF8StringForKey:@"tsg_hostname"]))
|
||||
goto out_free;
|
||||
|
||||
if (!addArgument(&argc, &argv, "/gp:%d", [_params intForKey:@"tsg_port"]))
|
||||
goto out_free;
|
||||
|
||||
if (!addArgument(&argc, &argv, "/gu:%s", [_params intForKey:@"tsg_username"]))
|
||||
goto out_free;
|
||||
|
||||
if (!addArgument(&argc, &argv, "/gp:%s", [_params intForKey:@"tsg_password"]))
|
||||
goto out_free;
|
||||
|
||||
if (!addArgument(&argc, &argv, "/gd:%s", [_params intForKey:@"tsg_domain"]))
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
// Remote keyboard layout
|
||||
if (!addArgument(&argc, &argv, "/kbd:%d", 0x409))
|
||||
goto out_free;
|
||||
|
||||
status =
|
||||
freerdp_client_settings_parse_command_line(_freerdp->context->settings, argc, argv, FALSE);
|
||||
|
||||
if (0 != status)
|
||||
goto out_free;
|
||||
|
||||
freeArguments(argc, argv);
|
||||
[self mfi]->session = self;
|
||||
return self;
|
||||
out_free:
|
||||
freeArguments(argc, argv);
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (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 width or height are still 0
|
||||
rdpSettings *settings = _freerdp->context->settings;
|
||||
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) == 0 ||
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_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"];
|
||||
(void)freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, size.width);
|
||||
(void)freerdp_settings_set_uint32(settings, FreeRDP_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 (freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth) <= 16)
|
||||
{
|
||||
const UINT32 w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) & (~1);
|
||||
(void)freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, w);
|
||||
}
|
||||
|
||||
[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, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// resumes a previously suspended session
|
||||
- (void)resume
|
||||
{
|
||||
if (_suspended)
|
||||
{
|
||||
/* RECTANGLE_16 rec;
|
||||
rec.left = 0;
|
||||
rec.top = 0;
|
||||
rec.right = freerdp_settings_get_uint32(instance->settings, FreeRDP_DesktopWidth);
|
||||
rec.bottom = freerdp_settings_get_uint32(instance->settings, FreeRDP_DesktopHeight);
|
||||
*/
|
||||
_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->context->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)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