From f0864108f999fb15c459d714313f2204d3fec0d9 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 5 Aug 2016 13:14:55 +0200 Subject: [PATCH] Updated iOS client. --- client/iOS/CMakeLists.txt | 2 +- .../iOS/Controllers/PerformanceEditorController.m | 315 +++++++----- client/iOS/Defaults.plist | 8 + client/iOS/FreeRDP/ios_freerdp.m | 435 ++++++++++++----- client/iOS/FreeRDP/ios_freerdp_ui.h | 39 +- client/iOS/FreeRDP/ios_freerdp_ui.m | 168 ++++--- client/iOS/Misc/Utils.m | 344 +++++++------ client/iOS/Models/GlobalDefaults.m | 51 +- client/iOS/Models/RDPSession.m | 530 ++++++++++++--------- client/iOS/Resources/MainWindow.xib | 219 ++------- 10 files changed, 1196 insertions(+), 915 deletions(-) diff --git a/client/iOS/CMakeLists.txt b/client/iOS/CMakeLists.txt index ed14fec..4c9e2af 100644 --- a/client/iOS/CMakeLists.txt +++ b/client/iOS/CMakeLists.txt @@ -107,7 +107,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_NAME}_RESOU set(EXECUTABLE_NAME "\${EXECUTABLE_NAME}") set_target_properties(${MODULE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${IOS_CLIENT_DIR}/iFreeRDP.plist) -set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "4.3") +set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "6.3") set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "gnu++0x") set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC NO) diff --git a/client/iOS/Controllers/PerformanceEditorController.m b/client/iOS/Controllers/PerformanceEditorController.m index d1e9710..3f15e22 100644 --- a/client/iOS/Controllers/PerformanceEditorController.m +++ b/client/iOS/Controllers/PerformanceEditorController.m @@ -1,9 +1,9 @@ /* controller for performance settings selection - + 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. + + 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/. */ @@ -11,7 +11,7 @@ #import "ConnectionParams.h" #import "Utils.h" -@interface PerformanceEditorController (Private) +@interface PerformanceEditorController(Private) -(NSString*)keyPathForKey:(NSString*)key; @end @@ -19,134 +19,177 @@ - (id)initWithConnectionParams:(ConnectionParams*)params { - return [self initWithConnectionParams:params keyPath:nil]; + return [self initWithConnectionParams:params keyPath:nil]; } -- (id)initWithConnectionParams:(ConnectionParams*)params keyPath:(NSString*)keyPath; +- (id)initWithConnectionParams:(ConnectionParams*)params keyPath: + (NSString*)keyPath; { - self = [super initWithStyle:UITableViewStyleGrouped]; - if (self) { - _params = [params retain]; - _keyPath = (keyPath != nil ? [keyPath retain] : nil); - } - return self; + self = [super initWithStyle:UITableViewStyleGrouped]; + + if (self) + { + _params = [params retain]; + _keyPath = (keyPath != nil ? [keyPath retain] : nil); + } + + return self; } - (void)viewDidLoad { - [super viewDidLoad]; + [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)viewDidUnload { - [super viewDidUnload]; - // Release any retained subviews of the main view. + [super viewDidUnload]; + // Release any retained subviews of the main view. } -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) + interfaceOrientation { - return YES; + return YES; } -(NSString*)keyPathForKey:(NSString*)key { - if (_keyPath) - return [_keyPath stringByAppendingFormat:@".%@", key]; - return key; + if (_keyPath) + return [_keyPath stringByAppendingFormat:@".%@", key]; + + return key; } - (void)dealloc { - [super dealloc]; - [_params release]; + [super dealloc]; + [_params release]; } #pragma mark - #pragma mark Table view data source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - // Return the number of sections. - return 1; +- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView +{ + // Return the number of sections. + return 1; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 7; +- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection: + (NSInteger)section +{ + return 7; } // set section headers -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection: + (NSInteger)section { - return NSLocalizedString(@"Performance Settings", @"'Performance Settings': performance settings header"); + return NSLocalizedString(@"Performance Settings", + @"'Performance Settings': performance settings header"); } // Customize the appearance of table view cells. -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - - // get the table view cell - EditFlagTableViewCell *cell = (EditFlagTableViewCell*)[self tableViewCellFromIdentifier:TableCellIdentifierYesNo]; - NSAssert(cell, @"Invalid cell"); - - switch ([indexPath row]) - { - case 0: - { - [[cell label] setText:NSLocalizedString(@"RemoteFX", @"RemoteFX performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_remotefx"]]]; - break; - } - - case 1: - { - [[cell label] setText:NSLocalizedString(@"Desktop Background", @"Desktop background performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_show_desktop"]]]; - break; - } - - case 2: - { - [[cell label] setText:NSLocalizedString(@"Font Smoothing", @"Font smoothing performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_font_smoothing"]]]; - break; - } - - case 3: - { - [[cell label] setText:NSLocalizedString(@"Desktop Composition", @"Desktop composition performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_desktop_composition"]]]; - break; - } - - case 4: - { - [[cell label] setText:NSLocalizedString(@"Window contents while dragging", @"Window Dragging performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_window_dragging"]]]; - break; - } - - case 5: - { - [[cell label] setText:NSLocalizedString(@"Menu Animation", @"Menu Animations performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_menu_animation"]]]; - break; - } - - case 6: - { - [[cell label] setText:NSLocalizedString(@"Visual Styles", @"Use Themes performance setting")]; - [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_windows_themes"]]]; - break; - } - - default: - break; - } - - [[cell toggle] setTag:GET_TAG_FROM_PATH(indexPath)]; - [[cell toggle] addTarget:self action:@selector(togglePerformanceSetting:) forControlEvents:UIControlEventValueChanged]; - return cell; +- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath: + (NSIndexPath*)indexPath +{ + // get the table view cell + EditFlagTableViewCell* cell = (EditFlagTableViewCell*)[self + tableViewCellFromIdentifier:TableCellIdentifierYesNo]; + NSAssert(cell, @"Invalid cell"); + + switch ([indexPath row]) + { + case 0: + { + [[cell label] setText:NSLocalizedString(@"RemoteFX", + @"RemoteFX performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_remotefx"]]]; + break; + } + + case 1: + { + [[cell label] setText:NSLocalizedString(@"GFX", @"GFX performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey:@"perf_gfx"]]]; + break; + } + + case 2: + { + [[cell label] setText:NSLocalizedString(@"H264", @"H264 performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_h264"]]]; + break; + } + + case 3: + { + [[cell label] setText:NSLocalizedString(@"Desktop Background", + @"Desktop background performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_show_desktop"]]]; + break; + } + + case 4: + { + [[cell label] setText:NSLocalizedString(@"Font Smoothing", + @"Font smoothing performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_font_smoothing"]]]; + break; + } + + case 5: + { + [[cell label] setText:NSLocalizedString(@"Desktop Composition", + @"Desktop composition performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_desktop_composition"]]]; + break; + } + + case 6: + { + [[cell label] setText:NSLocalizedString(@"Window contents while dragging", + @"Window Dragging performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_window_dragging"]]]; + break; + } + + case 7: + { + [[cell label] setText:NSLocalizedString(@"Menu Animation", + @"Menu Animations performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_menu_animation"]]]; + break; + } + + case 8: + { + [[cell label] setText:NSLocalizedString(@"Visual Styles", + @"Use Themes performance setting")]; + [[cell toggle] setOn:[_params boolForKeyPath:[self keyPathForKey: + @"perf_windows_themes"]]]; + break; + } + + default: + break; + } + + [[cell toggle] setTag:GET_TAG_FROM_PATH(indexPath)]; + [[cell toggle] addTarget:self action:@selector(togglePerformanceSetting:) + forControlEvents:UIControlEventValueChanged]; + return cell; } #pragma mark - @@ -154,40 +197,58 @@ - (void)togglePerformanceSetting:(id)sender { - UISwitch* valueSwitch = (UISwitch*)sender; - switch(valueSwitch.tag) - { - case GET_TAG(0, 0): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_remotefx"]]; - break; - - case GET_TAG(0, 1): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_show_desktop"]]; - break; - - case GET_TAG(0, 2): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_font_smoothing"]]; - break; - - case GET_TAG(0, 3): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_desktop_composition"]]; - break; - - case GET_TAG(0, 4): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_window_dragging"]]; - break; - - case GET_TAG(0, 5): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_menu_animation"]]; - break; - - case GET_TAG(0, 6): - [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey:@"perf_windows_themes"]]; - break; - - default: - break; - } + UISwitch* valueSwitch = (UISwitch*)sender; + + switch (valueSwitch.tag) + { + case GET_TAG(0, 0): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_remotefx"]]; + break; + + case GET_TAG(0, 1): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_gfx"]]; + break; + + case GET_TAG(0, 2): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_h264"]]; + break; + + case GET_TAG(0, 3): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_show_desktop"]]; + break; + + case GET_TAG(0, 4): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_font_smoothing"]]; + break; + + case GET_TAG(0, 5): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_desktop_composition"]]; + break; + + case GET_TAG(0, 6): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_window_dragging"]]; + break; + + case GET_TAG(0, 7): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_menu_animation"]]; + break; + + case GET_TAG(0, 8): + [_params setBool:[valueSwitch isOn] forKeyPath:[self keyPathForKey: + @"perf_windows_themes"]]; + break; + + default: + break; + } } @end diff --git a/client/iOS/Defaults.plist b/client/iOS/Defaults.plist index 8010823..d0313e1 100644 --- a/client/iOS/Defaults.plist +++ b/client/iOS/Defaults.plist @@ -28,6 +28,10 @@ perf_remotefx + perf_gfx + + perf_h264 + perf_desktop_composition enable_3g_settings @@ -44,6 +48,10 @@ 16 perf_remotefx + perf_gfx + + perf_h264 + perf_desktop_composition perf_windows_themes diff --git a/client/iOS/FreeRDP/ios_freerdp.m b/client/iOS/FreeRDP/ios_freerdp.m index 4638431..f9e4024 100644 --- a/client/iOS/FreeRDP/ios_freerdp.m +++ b/client/iOS/FreeRDP/ios_freerdp.m @@ -1,8 +1,8 @@ /* RDP run-loop - + 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/. */ @@ -12,6 +12,7 @@ #import #import #import +#import #import "ios_freerdp.h" #import "ios_freerdp_ui.h" @@ -20,23 +21,99 @@ #import "RDPSession.h" #import "Utils.h" +#define TAG FREERDP_TAG("iOS") + #pragma mark Connection helpers +static void ios_OnChannelConnectedEventHandler( + rdpContext* context, + ChannelConnectedEventArgs* e) +{ + rdpSettings* settings; + mfContext* afc; + + if (!context || !e) + { + WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", + __FUNCTION__, context, e); + return; + } + + afc = (mfContext*) context; + settings = context->settings; + + if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + if (settings->SoftwareGdi) + { + gdi_graphics_pipeline_init(context->gdi, + (RdpgfxClientContext*) e->pInterface); + } + else + { + WLog_WARN(TAG, "GFX without software GDI requested. " + " This is not supported, add /gdi:sw"); + } + } +} + +static void ios_OnChannelDisconnectedEventHandler( + rdpContext* context, ChannelDisconnectedEventArgs* e) +{ + rdpSettings* settings; + mfContext* afc; + + if (!context || !e) + { + WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", + __FUNCTION__, context, e); + return; + } + + afc = (mfContext*) context; + settings = context->settings; + + if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + if (settings->SoftwareGdi) + { + gdi_graphics_pipeline_uninit(context->gdi, + (RdpgfxClientContext*) e->pInterface); + } + else + { + WLog_WARN(TAG, "GFX without software GDI requested. " + " This is not supported, add /gdi:sw"); + } + } +} + static BOOL ios_pre_connect(freerdp* instance) -{ - rdpSettings* settings = instance->settings; +{ + int rc; + rdpSettings* settings; + + if (!instance || !instance->settings) + return FALSE; + + settings = instance->settings; + + if (!settings->OrderSupport) + return FALSE; + + settings->AutoLogonEnabled = settings->Password + && (strlen(settings->Password) > 0); - settings->AutoLogonEnabled = settings->Password && (strlen(settings->Password) > 0); - // Verify screen width/height are sane - if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) || (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096)) + if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) + || (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096)) { - NSLog(@"%s: invalid dimensions %d %d", __func__, settings->DesktopWidth, settings->DesktopHeight); + NSLog(@"%s: invalid dimensions %d %d", __func__, settings->DesktopWidth, + settings->DesktopHeight); return FALSE; } - + BOOL bitmap_cache = settings->BitmapCacheEnabled; - settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE; settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; @@ -61,38 +138,154 @@ static BOOL ios_pre_connect(freerdp* instance) settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; - - settings->FrameAcknowledge = 10; + rc = PubSub_SubscribeChannelConnected( + instance->context->pubSub, + (pChannelConnectedEventHandler) + ios_OnChannelConnectedEventHandler); - if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) + if (rc != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Could not subscribe to connect event handler [%l08X]", rc); + return FALSE; + } + + rc = PubSub_SubscribeChannelDisconnected( + instance->context->pubSub, + (pChannelDisconnectedEventHandler) + ios_OnChannelDisconnectedEventHandler); + + if (rc != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "Could not subscribe to disconnect event handler [%l08X]", rc); + return FALSE; + } + + if (!freerdp_client_load_addins(instance->context->channels, + instance->settings)) + { + WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError()); + return FALSE; + } + + rc = freerdp_channels_pre_connect(instance->context->channels, instance); + + if (rc != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "freerdp_channels_pre_connect failed with %l08X", rc); + return FALSE; + } + + return TRUE; +} + +static BOOL ios_Pointer_New(rdpContext* context, rdpPointer* pointer) +{ + if (!context || !pointer || !context->gdi) return FALSE; - if (freerdp_channels_pre_connect(instance->context->channels, instance) != CHANNEL_RC_OK) + return TRUE; +} + +static void ios_Pointer_Free(rdpContext* context, rdpPointer* pointer) +{ + if (!context || !pointer) + return; +} + +static BOOL ios_Pointer_Set(rdpContext* context, + const rdpPointer* pointer) +{ + if (!context) return FALSE; return TRUE; } +static BOOL ios_Pointer_SetPosition(rdpContext* context, + UINT32 x, UINT32 y) +{ + if (!context) + return FALSE; + + return TRUE; +} + +static BOOL ios_Pointer_SetNull(rdpContext* context) +{ + if (!context) + return FALSE; + + return TRUE; +} + +static BOOL ios_Pointer_SetDefault(rdpContext* context) +{ + if (!context) + return FALSE; + + return TRUE; +} + +static BOOL ios_register_pointer(rdpGraphics* graphics) +{ + rdpPointer pointer; + + if (!graphics) + return FALSE; + + pointer.size = sizeof(pointer); + pointer.New = ios_Pointer_New; + pointer.Free = ios_Pointer_Free; + pointer.Set = ios_Pointer_Set; + pointer.SetNull = ios_Pointer_SetNull; + pointer.SetDefault = ios_Pointer_SetDefault; + pointer.SetPosition = ios_Pointer_SetPosition; + graphics_register_pointer(graphics, &pointer); + return TRUE; +} + static BOOL ios_post_connect(freerdp* instance) { - mfInfo* mfi = MFI_FROM_INSTANCE(instance); + mfInfo* mfi; + + if (!instance) + return FALSE; + + mfi = MFI_FROM_INSTANCE(instance); + + if (!mfi) + return FALSE; + + if (!gdi_init(instance, PIXEL_FORMAT_BGRA32)) + return FALSE; + + if (!ios_register_pointer(instance->context->graphics)) + return FALSE; - instance->context->cache = cache_new(instance->settings); - - // Graphics callbacks ios_allocate_display_buffer(mfi); instance->update->BeginPaint = ios_ui_begin_paint; instance->update->EndPaint = ios_ui_end_paint; instance->update->DesktopResize = ios_ui_resize_window; - + pointer_cache_register_callbacks(instance->update); + // Channel allocation - if (freerdp_channels_post_connect(instance->context->channels, instance) != CHANNEL_RC_OK) + if (freerdp_channels_post_connect(instance->context->channels, + instance) != CHANNEL_RC_OK) return FALSE; - [mfi->session performSelectorOnMainThread:@selector(sessionDidConnect) withObject:nil waitUntilDone:YES]; + [mfi->session performSelectorOnMainThread:@selector(sessionDidConnect) + withObject:nil waitUntilDone:YES]; return TRUE; } +static void ios_post_disconnect(freerdp* instance) +{ + if (instance && instance->context) + freerdp_channels_disconnect(instance->context->channels, instance); + + gdi_free(instance); +} + #pragma mark - #pragma mark Running the connection @@ -101,20 +294,18 @@ int ios_run_freerdp(freerdp* instance) mfContext* context = (mfContext*)instance->context; mfInfo* mfi = context->mfi; rdpChannels* channels = instance->context->channels; - mfi->connection_state = TSXConnectionConnecting; - + if (!freerdp_connect(instance)) { NSLog(@"%s: inst->rdp_connect failed", __func__); return mfi->unwanted ? MF_EXIT_CONN_CANCELED : MF_EXIT_CONN_FAILED; } - + if (mfi->unwanted) return MF_EXIT_CONN_CANCELED; mfi->connection_state = TSXConnectionConnected; - // Connection main loop NSAutoreleasePool* pool; int i; @@ -128,14 +319,12 @@ int ios_run_freerdp(freerdp* instance) fd_set wfds_set; struct timeval timeout; int select_status; - memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); while (!freerdp_shall_disconnect(instance)) { rcount = wcount = 0; - pool = [[NSAutoreleasePool alloc] init]; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) @@ -144,7 +333,8 @@ int ios_run_freerdp(freerdp* instance) break; } - if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) + if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, + &wcount) != TRUE) { NSLog(@"%s: freerdp_chanman_get_fds failed", __func__); break; @@ -155,54 +345,53 @@ int ios_run_freerdp(freerdp* instance) NSLog(@"%s: ios_events_get_fds", __func__); break; } - + max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); - + for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); - + if (fds > max_fds) max_fds = fds; - + FD_SET(fds, &rfds_set); } - + if (max_fds == 0) break; - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); - - // timeout? - if (select_status == 0) - { - continue; - } - else if (select_status == -1) - { - /* these are not really errors */ - if (!((errno == EAGAIN) || - (errno == EWOULDBLOCK) || - (errno == EINPROGRESS) || - (errno == EINTR))) /* signal occurred */ + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); + + // timeout? + if (select_status == 0) + { + continue; + } + else if (select_status == -1) { + /* these are not really errors */ + if (!((errno == EAGAIN) || + (errno == EWOULDBLOCK) || + (errno == EINPROGRESS) || + (errno == EINTR))) /* signal occurred */ + { NSLog(@"%s: select failed!", __func__); break; } } - + // Check the libfreerdp fds if (freerdp_check_fds(instance) != true) { NSLog(@"%s: inst->rdp_check_fds failed.", __func__); break; } - + // Check input event fds if (ios_events_check_fds(mfi, &rfds_set) != TRUE) { @@ -210,7 +399,7 @@ int ios_run_freerdp(freerdp* instance) //NSLog(@"%s: ios_events_check_fds failed: terminating connection.", __func__); break; } - + // Check channel fds if (freerdp_channels_check_fds(channels, instance) != TRUE) { @@ -218,121 +407,129 @@ int ios_run_freerdp(freerdp* instance) break; } - [pool release]; pool = nil; - } + [pool release]; + pool = nil; + } CGContextRelease(mfi->bitmap_context); - mfi->bitmap_context = NULL; + mfi->bitmap_context = NULL; mfi->connection_state = TSXConnectionDisconnected; - // Cleanup freerdp_channels_disconnect(channels, instance); freerdp_disconnect(instance); gdi_free(instance); cache_free(instance->context->cache); - - [pool release]; pool = nil; + [pool release]; + pool = nil; return MF_EXIT_SUCCESS; } #pragma mark - #pragma mark Context callbacks -BOOL ios_context_new(freerdp* instance, rdpContext* context) +static BOOL ios_client_new(freerdp* instance, rdpContext* context) { mfInfo* mfi; + mfContext* ctx = (mfContext*)context; - if (!(mfi = (mfInfo*)calloc(1, sizeof(mfInfo)))) - goto fail_mfi; + if (!instance || !context) + return FALSE; if (!(context->channels = freerdp_channels_new())) - goto fail_channels; - - if (!ios_events_create_pipe(mfi)) - goto fail_events; - - ((mfContext*) context)->mfi = mfi; - mfi->_context = context; - mfi->context = (mfContext*)context; - mfi->context->settings = instance->settings; - mfi->instance = instance; - return TRUE; + return FALSE; -fail_events: - freerdp_channels_free(context->channels); - context->channels = NULL; -fail_channels: - free(mfi); -fail_mfi: - return FALSE; + if ((ctx->mfi = calloc(1, sizeof(mfInfo))) == NULL) + return FALSE; + + ctx->mfi->context = (mfContext*)context; + ctx->mfi->_context = context; + ctx->mfi->context->settings = instance->settings; + ctx->mfi->instance = instance; + + if (!ios_events_create_pipe(ctx->mfi)) + return FALSE; + + instance->PreConnect = ios_pre_connect; + instance->PostConnect = ios_post_connect; + instance->PostDisconnect = ios_post_disconnect; + instance->Authenticate = ios_ui_authenticate; + instance->GatewayAuthenticate = ios_ui_gw_authenticate; + instance->VerifyCertificate = ios_ui_verify_certificate; + instance->VerifyChangedCertificate = ios_ui_verify_changed_certificate; + instance->LogonErrorInfo = NULL; + return TRUE; } -void ios_context_free(freerdp* instance, rdpContext* context) +static void ios_client_free(freerdp* instance, rdpContext* context) { - mfInfo* mfi = ((mfContext*) context)->mfi; - freerdp_channels_close(context->channels, instance); - freerdp_channels_free(context->channels); + mfInfo* mfi; + + if (!context) + return; + + mfi = ((mfContext*) context)->mfi; + + if (context->channels) + { + freerdp_channels_close(context->channels, instance); + freerdp_channels_free(context->channels); + context->channels = NULL; + } + ios_events_free_pipe(mfi); free(mfi); } +static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) +{ + ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS)); + pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION; + pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1); + pEntryPoints->GlobalInit = NULL; + pEntryPoints->GlobalUninit = NULL; + pEntryPoints->ContextSize = sizeof(mfContext); + pEntryPoints->ClientNew = ios_client_new; + pEntryPoints->ClientFree = ios_client_free; + pEntryPoints->ClientStart = NULL; + pEntryPoints->ClientStop = NULL; + return 0; +} + #pragma mark - #pragma mark Initialization and cleanup freerdp* ios_freerdp_new() { - freerdp* inst = freerdp_new(); - if (!inst) - return NULL; - - inst->PreConnect = ios_pre_connect; - inst->PostConnect = ios_post_connect; - inst->Authenticate = ios_ui_authenticate; - inst->VerifyCertificate = ios_ui_check_certificate; - inst->VerifyChangedCertificate = ios_ui_check_changed_certificate; - - inst->ContextSize = sizeof(mfContext); - inst->ContextNew = ios_context_new; - inst->ContextFree = ios_context_free; - freerdp_context_new(inst); - - // determine new home path - NSString* home_path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; - free(inst->settings->HomePath); - free(inst->settings->ConfigPath); - inst->settings->HomePath = strdup([home_path UTF8String]); - inst->settings->ConfigPath = strdup([[home_path stringByAppendingPathComponent:@".freerdp"] UTF8String]); - if (!inst->settings->HomePath || !inst->settings->ConfigPath) - { - free(inst->settings->HomePath); - free(inst->settings->ConfigPath); - freerdp_context_free(inst); - freerdp_free(inst); + rdpContext* context; + RDP_CLIENT_ENTRY_POINTS clientEntryPoints; + RdpClientEntry(&clientEntryPoints); + context = freerdp_client_context_new(&clientEntryPoints); + + if (!context) return NULL; - } - return inst; + return context->instance; } void ios_freerdp_free(freerdp* instance) { - freerdp_context_free(instance); - freerdp_free(instance); + if (!instance || !instance->context) + return; + + freerdp_client_context_free(instance->context); } void ios_init_freerdp() { signal(SIGPIPE, SIG_IGN); - freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); } void ios_uninit_freerdp() { - } /* compatibilty functions */ -size_t fwrite$UNIX2003( const void *ptr, size_t size, size_t nmemb, FILE *stream ) +size_t fwrite$UNIX2003(const void* ptr, size_t size, size_t nmemb, FILE* stream) { return fwrite(ptr, size , nmemb, stream); } diff --git a/client/iOS/FreeRDP/ios_freerdp_ui.h b/client/iOS/FreeRDP/ios_freerdp_ui.h index 91389dd..9dc5b13 100644 --- a/client/iOS/FreeRDP/ios_freerdp_ui.h +++ b/client/iOS/FreeRDP/ios_freerdp_ui.h @@ -1,28 +1,35 @@ /* RDP ui callbacks - + 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" -BOOL ios_ui_begin_paint(rdpContext * context); -BOOL ios_ui_end_paint(rdpContext * context); -BOOL ios_ui_resize_window(rdpContext * context); +BOOL ios_ui_begin_paint(rdpContext* context); +BOOL ios_ui_end_paint(rdpContext* context); +BOOL ios_ui_resize_window(rdpContext* context); -BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, char** domain); -DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name, - const char * subject, const char * issuer, - const char * fingerprint, BOOL host_mismatch); -DWORD ios_ui_check_changed_certificate(freerdp * instance, - const char* common_name, - const char * subject, - const char * issuer, - const char * new_fingerprint, - const char * old_fingerprint); +BOOL ios_ui_authenticate(freerdp* instance, char** username, char** password, + char** domain); +BOOL ios_ui_gw_authenticate(freerdp* instance, char** username, char** password, + char** domain); +DWORD ios_ui_verify_certificate(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* fingerprint, + BOOL host_mismatch); +DWORD ios_ui_verify_changed_certificate(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* new_fingerprint, + const char* old_subject, + const char* old_issuer, + const char* old_fingerprint); void ios_allocate_display_buffer(mfInfo* mfi); -void ios_resize_display_buffer(mfInfo* mfi); diff --git a/client/iOS/FreeRDP/ios_freerdp_ui.m b/client/iOS/FreeRDP/ios_freerdp_ui.m index 61ac318..0feae9d 100644 --- a/client/iOS/FreeRDP/ios_freerdp_ui.m +++ b/client/iOS/FreeRDP/ios_freerdp_ui.m @@ -1,8 +1,8 @@ /* RDP ui callbacks - + 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/. */ @@ -17,36 +17,37 @@ #pragma mark - #pragma mark Certificate authentication -BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, char** domain) +static void ios_resize_display_buffer(mfInfo* mfi); +static BOOL ios_ui_authenticate_raw(freerdp* instance, char** username, + char** password, + char** domain, const char* title) { mfInfo* mfi = MFI_FROM_INSTANCE(instance); - NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: - (*username) ? [NSString stringWithUTF8String:*username] : @"", @"username", - (*password) ? [NSString stringWithUTF8String:*password] : @"", @"password", - (*domain) ? [NSString stringWithUTF8String:*domain] : @"", @"domain", - [NSString stringWithUTF8String:instance->settings->ServerHostname], @"hostname", // used for the auth prompt message; not changed - nil]; - - // request auth UI - [mfi->session performSelectorOnMainThread:@selector(sessionRequestsAuthenticationWithParams:) withObject:params waitUntilDone:YES]; - - // wait for UI request to be completed - [[mfi->session uiRequestCompleted] lock]; - [[mfi->session uiRequestCompleted] wait]; - [[mfi->session uiRequestCompleted] unlock]; - + (*username) ? [NSString stringWithUTF8String:*username] : @"", @"username", + (*password) ? [NSString stringWithUTF8String:*password] : @"", @"password", + (*domain) ? [NSString stringWithUTF8String:*domain] : @"", @"domain", + [NSString stringWithUTF8String:instance->settings->ServerHostname], + @"hostname", // used for the auth prompt message; not changed + nil]; + // request auth UI + [mfi->session performSelectorOnMainThread:@selector( + sessionRequestsAuthenticationWithParams:) withObject:params waitUntilDone:YES]; + // wait for UI request to be completed + [[mfi->session uiRequestCompleted] lock]; + [[mfi->session uiRequestCompleted] wait]; + [[mfi->session uiRequestCompleted] unlock]; + if (![[params valueForKey:@"result"] boolValue]) { mfi->unwanted = YES; return FALSE; } - + // Free old values free(*username); free(*password); free(*domain); - // set values back *username = strdup([[params objectForKey:@"username"] UTF8String]); *password = strdup([[params objectForKey:@"password"] UTF8String]); @@ -59,28 +60,44 @@ BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, c free(*domain); return FALSE; } - + return TRUE; } -DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name, - const char * subject, const char * issuer, - const char * fingerprint, BOOL host_mismatch) +BOOL ios_ui_authenticate(freerdp* instance, char** username, char** password, + char** domain) +{ + return ios_ui_authenticate_raw(instance, username, password, domain, ""); +} + +BOOL ios_ui_gw_authenticate(freerdp* instance, char** username, char** password, + char** domain) +{ + return ios_ui_authenticate_raw(instance, username, password, domain, "gateway"); +} + + +DWORD ios_ui_verify_certificate(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* fingerprint, + BOOL host_mismatch) { // check whether we accept all certificates - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"] == YES) + if ([[NSUserDefaults standardUserDefaults] boolForKey: + @"security.accept_certificates"] == YES) return 2; mfInfo* mfi = MFI_FROM_INSTANCE(instance); NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: - (subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject", - (issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer", - (fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint", - nil]; - + (subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject", + (issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer", + (fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint", + nil]; // request certificate verification UI - [mfi->session performSelectorOnMainThread:@selector(sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES]; - + [mfi->session performSelectorOnMainThread:@selector( + sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES]; // wait for UI request to be completed [[mfi->session uiRequestCompleted] lock]; [[mfi->session uiRequestCompleted] wait]; @@ -95,44 +112,63 @@ DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name, return 1; } -DWORD ios_ui_check_changed_certificate(freerdp * instance, - const char * common_name, - const char * subject, - const char * issuer, - const char * new_fingerprint, - const char * old_fingerprint) +DWORD ios_ui_verify_changed_certificate(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* new_fingerprint, + const char* old_subject, + const char* old_issuer, + const char* old_fingerprint) { - return ios_ui_check_certificate(instance, common_name, subject, issuer, - new_fingerprint, FALSE); + return ios_ui_verify_certificate(instance, common_name, subject, issuer, + new_fingerprint, FALSE); } #pragma mark - #pragma mark Graphics updates -BOOL ios_ui_begin_paint(rdpContext * context) +BOOL ios_ui_begin_paint(rdpContext* context) { - rdpGdi *gdi = context->gdi; + rdpGdi* gdi = context->gdi; gdi->primary->hdc->hwnd->invalid->null = 1; - return TRUE; + return TRUE; } -BOOL ios_ui_end_paint(rdpContext * context) +BOOL ios_ui_end_paint(rdpContext* context) { - mfInfo* mfi = MFI_FROM_INSTANCE(context->instance); - rdpGdi *gdi = context->gdi; - CGRect dirty_rect = CGRectMake(gdi->primary->hdc->hwnd->invalid->x, gdi->primary->hdc->hwnd->invalid->y, gdi->primary->hdc->hwnd->invalid->w, gdi->primary->hdc->hwnd->invalid->h); - + mfInfo* mfi = MFI_FROM_INSTANCE(context->instance); + rdpGdi* gdi = context->gdi; + CGRect dirty_rect = CGRectMake(gdi->primary->hdc->hwnd->invalid->x, + gdi->primary->hdc->hwnd->invalid->y, gdi->primary->hdc->hwnd->invalid->w, + gdi->primary->hdc->hwnd->invalid->h); + if (gdi->primary->hdc->hwnd->invalid->null == 0) - [mfi->session performSelectorOnMainThread:@selector(setNeedsDisplayInRectAsValue:) withObject:[NSValue valueWithCGRect:dirty_rect] waitUntilDone:NO]; - return TRUE; + [mfi->session performSelectorOnMainThread:@selector( + setNeedsDisplayInRectAsValue:) withObject:[NSValue valueWithCGRect:dirty_rect] + waitUntilDone:NO]; + + return TRUE; } -BOOL ios_ui_resize_window(rdpContext * context) +BOOL ios_ui_resize_window(rdpContext* context) { + rdpSettings* settings; + rdpGdi* gdi; + + if (!context || !context->settings) + return FALSE; + + settings = context->settings; + gdi = context->gdi; + + if (!gdi_resize(gdi, settings->DesktopWidth, settings->DesktopHeight)) + return FALSE; + ios_resize_display_buffer(MFI_FROM_INSTANCE(context->instance)); - return TRUE; + return TRUE; } @@ -140,23 +176,28 @@ BOOL ios_ui_resize_window(rdpContext * context) #pragma mark Exported static void ios_create_bitmap_context(mfInfo* mfi) -{ - [mfi->session performSelectorOnMainThread:@selector(sessionBitmapContextWillChange) withObject:nil waitUntilDone:YES]; - - rdpGdi* gdi = mfi->instance->context->gdi; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); +{ + [mfi->session performSelectorOnMainThread:@selector( + sessionBitmapContextWillChange) withObject:nil waitUntilDone:YES]; + rdpGdi* gdi = mfi->instance->context->gdi; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + if (GetBytesPerPixel(gdi->dstFormat) == 2) - mfi->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 5, gdi->stride, colorSpace, kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst); + mfi->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, + gdi->height, 5, gdi->stride, colorSpace, + kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst); else - mfi->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->stride, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); - CGColorSpaceRelease(colorSpace); - - [mfi->session performSelectorOnMainThread:@selector(sessionBitmapContextDidChange) withObject:nil waitUntilDone:YES]; + mfi->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, + gdi->height, 8, gdi->stride, colorSpace, + kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); + + CGColorSpaceRelease(colorSpace); + [mfi->session performSelectorOnMainThread:@selector( + sessionBitmapContextDidChange) withObject:nil waitUntilDone:YES]; } void ios_allocate_display_buffer(mfInfo* mfi) { - gdi_init(mfi->instance, PIXEL_FORMAT_XRGB32); ios_create_bitmap_context(mfi); } @@ -166,7 +207,6 @@ void ios_resize_display_buffer(mfInfo* mfi) CGContextRef old_context = mfi->bitmap_context; mfi->bitmap_context = NULL; CGContextRelease(old_context); - // Create the new context ios_create_bitmap_context(mfi); } diff --git a/client/iOS/Misc/Utils.m b/client/iOS/Misc/Utils.m index 544c137..af41e10 100644 --- a/client/iOS/Misc/Utils.m +++ b/client/iOS/Misc/Utils.m @@ -1,9 +1,9 @@ /* Utility functions - + 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. + + 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/. */ @@ -21,18 +21,21 @@ #include #include -BOOL ScanHostNameAndPort(NSString* address, NSString** host, unsigned short* port) +BOOL ScanHostNameAndPort(NSString* address, NSString** host, + unsigned short* port) { - *host = @""; *port = 0; - + *host = @""; + *port = 0; + if (![address length]) return NO; - - NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"rdp://%@", address]]; - + + NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"rdp://%@", + address]]; + if (!url || ![[url host] length]) return NO; - + *host = [url host]; *port = [[url port] unsignedShortValue]; return YES; @@ -43,18 +46,22 @@ BOOL ScanHostNameAndPort(NSString* address, NSString** host, unsigned short* por NSString* LocalizedFitScreen() { - return NSLocalizedString(@"Automatic", @"Screen resolution selector: Automatic resolution (Full Screen on iPad, reasonable size on iPhone)"); + return NSLocalizedString(@"Automatic", + @"Screen resolution selector: Automatic resolution (Full Screen on iPad, reasonable size on iPhone)"); } NSString* LocalizedCustom() { - return NSLocalizedString(@"Custom", @"Screen resolution selector: Custom"); + return NSLocalizedString(@"Custom", @"Screen resolution selector: Custom"); } -BOOL ScanScreenResolution(NSString* description, int* width, int* height, TSXScreenOptions* type) +BOOL ScanScreenResolution(NSString* description, int* width, int* height, + TSXScreenOptions* type) { - *height = 0; *width = 0; *type = TSXScreenOptionFixed; - + *height = 0; + *width = 0; + *type = TSXScreenOptionFixed; + if ([description isEqualToString:LocalizedFitScreen()]) { *type = TSXScreenOptionFitScreen; @@ -65,58 +72,69 @@ BOOL ScanScreenResolution(NSString* description, int* width, int* height, TSXScr *type = TSXScreenOptionCustom; return YES; } - - NSArray* resolution_components = [description componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"x*×"]]; - + + NSArray* resolution_components = [description + componentsSeparatedByCharactersInSet:[NSCharacterSet + characterSetWithCharactersInString:@"x*×"]]; + if ([resolution_components count] != 2) return NO; - + *width = [[resolution_components objectAtIndex:0] intValue]; - *height = [[resolution_components objectAtIndex:1] intValue]; + *height = [[resolution_components objectAtIndex:1] intValue]; return YES; } -NSString* ScreenResolutionDescription(TSXScreenOptions type, int width, int height) +NSString* ScreenResolutionDescription(TSXScreenOptions type, int width, + int height) { if (type == TSXScreenOptionFitScreen) return LocalizedFitScreen(); else if (type == TSXScreenOptionCustom) return LocalizedCustom(); - + return [NSString stringWithFormat:@"%dx%d", width, height]; } NSDictionary* SelectionForColorSetting() { - OrderedDictionary* dict = [OrderedDictionary dictionaryWithCapacity:3]; - [dict setValue:[NSNumber numberWithInt:16] forKey:NSLocalizedString(@"High Color (16 Bit)", @"16 bit color selection")]; - [dict setValue:[NSNumber numberWithInt:24] forKey:NSLocalizedString(@"True Color (24 Bit)", @"24 bit color selection")]; - [dict setValue:[NSNumber numberWithInt:32] forKey:NSLocalizedString(@"Highest Quality (32 Bit)", @"32 bit color selection")]; - return dict; + OrderedDictionary* dict = [OrderedDictionary dictionaryWithCapacity:3]; + [dict setValue:[NSNumber numberWithInt:8] forKey:NSLocalizedString( + @"Palette Color (8 Bit)", @"8 bit color selection")]; + [dict setValue:[NSNumber numberWithInt:15] forKey:NSLocalizedString( + @"High Color (15 Bit)", @"15 bit color selection")]; + [dict setValue:[NSNumber numberWithInt:16] forKey:NSLocalizedString( + @"High Color (16 Bit)", @"16 bit color selection")]; + [dict setValue:[NSNumber numberWithInt:24] forKey:NSLocalizedString( + @"True Color (24 Bit)", @"24 bit color selection")]; + [dict setValue:[NSNumber numberWithInt:32] forKey:NSLocalizedString( + @"Highest Quality (32 Bit)", @"32 bit color selection")]; + return dict; } NSArray* ResolutionModes() { - NSArray* array = [NSArray arrayWithObjects:ScreenResolutionDescription(TSXScreenOptionFitScreen, 0, 0), - ScreenResolutionDescription(TSXScreenOptionFixed, 640, 480), - ScreenResolutionDescription(TSXScreenOptionFixed, 800, 600), - ScreenResolutionDescription(TSXScreenOptionFixed, 1024, 768), - ScreenResolutionDescription(TSXScreenOptionFixed, 1280, 1024), - ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 900), - ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 1050), - ScreenResolutionDescription(TSXScreenOptionFixed, 1600, 1200), - ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1080), - ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1200), - ScreenResolutionDescription(TSXScreenOptionCustom, 0, 0), nil]; - return array; + NSArray* array = [NSArray arrayWithObjects:ScreenResolutionDescription( + TSXScreenOptionFitScreen, 0, 0), + ScreenResolutionDescription(TSXScreenOptionFixed, 640, 480), + ScreenResolutionDescription(TSXScreenOptionFixed, 800, 600), + ScreenResolutionDescription(TSXScreenOptionFixed, 1024, 768), + ScreenResolutionDescription(TSXScreenOptionFixed, 1280, 1024), + ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 900), + ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 1050), + ScreenResolutionDescription(TSXScreenOptionFixed, 1600, 1200), + ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1080), + ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1200), + ScreenResolutionDescription(TSXScreenOptionCustom, 0, 0), nil]; + return array; } #pragma mark Working with Security Protocols NSString* LocalizedAutomaticSecurity() { - return NSLocalizedString(@"Automatic", @"Automatic protocl security selection"); + return NSLocalizedString(@"Automatic", @"Automatic protocl security selection"); } NSString* ProtocolSecurityDescription(TSXProtocolSecurityOptions type) @@ -127,14 +145,15 @@ NSString* ProtocolSecurityDescription(TSXProtocolSecurityOptions type) return @"TLS"; else if (type == TSXProtocolSecurityRDP) return @"RDP"; - + return LocalizedAutomaticSecurity(); } -BOOL ScanProtocolSecurity(NSString* description, TSXProtocolSecurityOptions* type) +BOOL ScanProtocolSecurity(NSString* description, + TSXProtocolSecurityOptions* type) { *type = TSXProtocolSecurityRDP; - + if ([description isEqualToString:@"NLA"]) { *type = TSXProtocolSecurityNLA; @@ -155,18 +174,22 @@ BOOL ScanProtocolSecurity(NSString* description, TSXProtocolSecurityOptions* typ *type = TSXProtocolSecurityAutomatic; return YES; } - + return NO; } NSDictionary* SelectionForSecuritySetting() { - OrderedDictionary* dict = [OrderedDictionary dictionaryWithCapacity:4]; - [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityAutomatic] forKey:ProtocolSecurityDescription(TSXProtocolSecurityAutomatic)]; - [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityRDP] forKey:ProtocolSecurityDescription(TSXProtocolSecurityRDP)]; - [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityTLS] forKey:ProtocolSecurityDescription(TSXProtocolSecurityTLS)]; - [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityNLA] forKey:ProtocolSecurityDescription(TSXProtocolSecurityNLA)]; - return dict; + OrderedDictionary* dict = [OrderedDictionary dictionaryWithCapacity:4]; + [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityAutomatic] forKey: + ProtocolSecurityDescription(TSXProtocolSecurityAutomatic)]; + [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityRDP] forKey: + ProtocolSecurityDescription(TSXProtocolSecurityRDP)]; + [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityTLS] forKey: + ProtocolSecurityDescription(TSXProtocolSecurityTLS)]; + [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityNLA] forKey: + ProtocolSecurityDescription(TSXProtocolSecurityNLA)]; + return dict; } @@ -178,47 +201,52 @@ NSDictionary* SelectionForSecuritySetting() NSMutableArray* FilterBookmarks(NSArray* bookmarks, NSArray* filter_words) { NSMutableArray* matching_items = [NSMutableArray array]; - NSArray* searched_keys = [NSArray arrayWithObjects:@"label", @"params.hostname", @"params.username", @"params.domain", nil]; - - for (ComputerBookmark* cur_bookmark in bookmarks) - { - double match_score = 0.0; - for (int i = 0; i < [searched_keys count]; i++) - { - NSString* val = [cur_bookmark valueForKeyPath:[searched_keys objectAtIndex:i]]; - - if (![val isKindOfClass:[NSString class]] || ![val length]) - continue; - - for (NSString* word in filter_words) - if ([val rangeOfString:word options:(NSCaseInsensitiveSearch | NSWidthInsensitiveSearch)].location != NSNotFound) - match_score += (1.0 / [filter_words count]) * pow(2, [searched_keys count] - i); - } - - if (match_score > 0.001) - [matching_items addObject:[NSDictionary dictionaryWithObjectsAndKeys: - cur_bookmark, @"bookmark", - [NSNumber numberWithFloat:match_score], @"score", - nil]]; - } - - [matching_items sortUsingComparator:^NSComparisonResult(NSDictionary* obj1, NSDictionary* obj2) { + NSArray* searched_keys = [NSArray arrayWithObjects:@"label", @"params.hostname", + @"params.username", @"params.domain", nil]; + + for (ComputerBookmark * cur_bookmark in bookmarks) + { + double match_score = 0.0; + + for (int i = 0; i < [searched_keys count]; i++) + { + NSString* val = [cur_bookmark valueForKeyPath:[searched_keys objectAtIndex:i]]; + + if (![val isKindOfClass:[NSString class]] || ![val length]) + continue; + + for (NSString * word in filter_words) + if ([val rangeOfString:word options:(NSCaseInsensitiveSearch | + NSWidthInsensitiveSearch)].location != NSNotFound) + match_score += (1.0 / [filter_words count]) * pow(2, [searched_keys count] - i); + } + + if (match_score > 0.001) + [matching_items addObject:[NSDictionary dictionaryWithObjectsAndKeys: + cur_bookmark, @"bookmark", + [NSNumber numberWithFloat:match_score], @"score", + nil]]; + } + + [matching_items sortUsingComparator:^NSComparisonResult(NSDictionary * obj1, + NSDictionary * obj2) + { return [[obj2 objectForKey:@"score"] compare:[obj1 objectForKey:@"score"]]; }]; - return matching_items; } NSMutableArray* FilterHistory(NSArray* history, NSString* filterStr) { - NSMutableArray* result = [NSMutableArray array]; - for (NSString* item in history) - { - if ([item rangeOfString:filterStr].location != NSNotFound) - [result addObject:item]; - } - - return result; + NSMutableArray* result = [NSMutableArray array]; + + for (NSString * item in history) + { + if ([item rangeOfString:filterStr].location != NSNotFound) + [result addObject:item]; + } + + return result; } #pragma mark Version Info @@ -232,140 +260,146 @@ NSString* TSXAppFullVersion() BOOL IsPad() { #ifdef UI_USER_INTERFACE_IDIOM - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); + return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); #else - return NO; + return NO; #endif } BOOL IsPhone() { #ifdef UI_USER_INTERFACE_IDIOM - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone); + return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone); #else - return NO; -#endif + return NO; +#endif } // set mouse buttons swapped flag static BOOL g_swap_mouse_buttons = NO; void SetSwapMouseButtonsFlag(BOOL swapped) { - g_swap_mouse_buttons = swapped; + g_swap_mouse_buttons = swapped; } // set invert scrolling flag static BOOL g_invert_scrolling = NO; void SetInvertScrollingFlag(BOOL invert) { - g_invert_scrolling = invert; + g_invert_scrolling = invert; } -// return event value for left mouse button +// return event value for left mouse button int GetLeftMouseButtonClickEvent(BOOL down) { - if (g_swap_mouse_buttons) - return (PTR_FLAGS_BUTTON2 | (down ? PTR_FLAGS_DOWN : 0)); - else - return (PTR_FLAGS_BUTTON1 | (down ? PTR_FLAGS_DOWN : 0)); + if (g_swap_mouse_buttons) + return (PTR_FLAGS_BUTTON2 | (down ? PTR_FLAGS_DOWN : 0)); + else + return (PTR_FLAGS_BUTTON1 | (down ? PTR_FLAGS_DOWN : 0)); } -// return event value for right mouse button +// return event value for right mouse button int GetRightMouseButtonClickEvent(BOOL down) { - if (g_swap_mouse_buttons) - return (PTR_FLAGS_BUTTON1 | (down ? PTR_FLAGS_DOWN : 0)); - else - return (PTR_FLAGS_BUTTON2 | (down ? PTR_FLAGS_DOWN : 0)); + if (g_swap_mouse_buttons) + return (PTR_FLAGS_BUTTON1 | (down ? PTR_FLAGS_DOWN : 0)); + else + return (PTR_FLAGS_BUTTON2 | (down ? PTR_FLAGS_DOWN : 0)); } // get mouse move event int GetMouseMoveEvent() { - return (PTR_FLAGS_MOVE); + return (PTR_FLAGS_MOVE); } // return mouse wheel event int GetMouseWheelEvent(BOOL down) { - if (g_invert_scrolling) - down = !down; - - if(down) - return (PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | (0x0088)); - else - return (PTR_FLAGS_WHEEL | (0x0078)); + if (g_invert_scrolling) + down = !down; + + if (down) + return (PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | (0x0088)); + else + return (PTR_FLAGS_WHEEL | (0x0078)); } // scrolling gesture detection delta CGFloat GetScrollGestureDelta() { - return 10.0f; + return 10.0f; } // this hack activates the iphone's WWAN interface in case it is offline void WakeUpWWAN() { - NSURL * url = [[[NSURL alloc] initWithString:@"http://www.nonexistingdummyurl.com"] autorelease]; - //NSData * data = - [NSData dataWithContentsOfURL:url]; // we don't need data but assigning one causes a "data not used" compiler warning + NSURL* url = [[[NSURL alloc] initWithString: + @"http://www.nonexistingdummyurl.com"] autorelease]; + //NSData * data = + [NSData dataWithContentsOfURL: + url]; // we don't need data but assigning one causes a "data not used" compiler warning } #pragma mark System Info functions -NSString* TSXGetPrimaryMACAddress(NSString *sep) +NSString* TSXGetPrimaryMACAddress(NSString* sep) { - NSString* macaddress = @""; - - struct ifaddrs *addrs; - - if (getifaddrs(&addrs) < 0) - { - NSLog(@"getPrimaryMACAddress: getifaddrs failed."); - return macaddress; - } - - for (struct ifaddrs *cursor = addrs; cursor!=NULL; cursor = cursor->ifa_next) - { - if(strcmp(cursor->ifa_name, "en0")) - continue; - if( (cursor->ifa_addr->sa_family == AF_LINK) - && (((struct sockaddr_dl *) cursor->ifa_addr)->sdl_type == 0x6 /*IFT_ETHER*/)) - { - struct sockaddr_dl *dlAddr = (struct sockaddr_dl *) cursor->ifa_addr; - if(dlAddr->sdl_alen != 6) - continue; - unsigned char* base = (unsigned char *) &dlAddr->sdl_data[dlAddr->sdl_nlen]; - macaddress = [NSString hexStringFromData:base ofSize:6 withSeparator:sep afterNthChar:1]; - break; - } - } - - freeifaddrs(addrs); - - return macaddress; + NSString* macaddress = @""; + struct ifaddrs* addrs; + + if (getifaddrs(&addrs) < 0) + { + NSLog(@"getPrimaryMACAddress: getifaddrs failed."); + return macaddress; + } + + for (struct ifaddrs* cursor = addrs; cursor != NULL; cursor = cursor->ifa_next) + { + if (strcmp(cursor->ifa_name, "en0")) + continue; + + if ((cursor->ifa_addr->sa_family == AF_LINK) + && (((struct sockaddr_dl*) cursor->ifa_addr)->sdl_type == 0x6 /*IFT_ETHER*/)) + { + struct sockaddr_dl* dlAddr = (struct sockaddr_dl*) cursor->ifa_addr; + + if (dlAddr->sdl_alen != 6) + continue; + + unsigned char* base = (unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen]; + macaddress = [NSString hexStringFromData:base ofSize:6 withSeparator:sep + afterNthChar:1]; + break; + } + } + + freeifaddrs(addrs); + return macaddress; } BOOL TSXDeviceHasJailBreak() { - if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app/"]) - return YES; + if ([[NSFileManager defaultManager] fileExistsAtPath: + @"/Applications/Cydia.app/"]) + return YES; - if ([[NSFileManager defaultManager] fileExistsAtPath:@"/etc/apt/"]) - return YES; + if ([[NSFileManager defaultManager] fileExistsAtPath:@"/etc/apt/"]) + return YES; - return NO; + return NO; } NSString* TSXGetPlatform() { - size_t size; - sysctlbyname("hw.machine", NULL, &size, NULL, 0); - char *machine = malloc(size); - sysctlbyname("hw.machine", machine, &size, NULL, 0); - NSString *platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding]; - free(machine); - return platform; + size_t size; + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char* machine = malloc(size); + sysctlbyname("hw.machine", machine, &size, NULL, 0); + NSString* platform = [NSString stringWithCString:machine encoding: + NSASCIIStringEncoding]; + free(machine); + return platform; } diff --git a/client/iOS/Models/GlobalDefaults.m b/client/iOS/Models/GlobalDefaults.m index b0d0fc5..fcb09b0 100644 --- a/client/iOS/Models/GlobalDefaults.m +++ b/client/iOS/Models/GlobalDefaults.m @@ -1,9 +1,9 @@ /* 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. + + 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/. */ @@ -16,33 +16,35 @@ + (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]; + _shared_global_defaults = [[GlobalDefaults alloc] init]; } } - - return _shared_global_defaults; + + return _shared_global_defaults; } - (id)init { if (!(self = [super init])) return nil; - + ComputerBookmark* bookmark = nil; - NSData* bookmark_data = [[NSUserDefaults standardUserDefaults] objectForKey:@"TSXSharedGlobalDefaultBookmark"]; - + 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]; - + bookmark = [[[ComputerBookmark alloc] initWithBaseDefaultParameters] + autorelease]; + _default_bookmark = [bookmark retain]; return self; } @@ -55,11 +57,12 @@ #pragma mark - -@synthesize bookmark=_default_bookmark; +@synthesize bookmark = _default_bookmark; - (ComputerBookmark*)newBookmark { - return [[ComputerBookmark alloc] initWithConnectionParameters:[[self newParams] autorelease]]; + return [[ComputerBookmark alloc] initWithConnectionParameters:[[self newParams] + autorelease]]; } - (ConnectionParams*)newParams @@ -70,14 +73,16 @@ - (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"]; + 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; } diff --git a/client/iOS/Models/RDPSession.m b/client/iOS/Models/RDPSession.m index 124dca8..252997f 100644 --- a/client/iOS/Models/RDPSession.m +++ b/client/iOS/Models/RDPSession.m @@ -1,9 +1,9 @@ /* - RDP Session object - + 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. + + 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/. */ @@ -17,9 +17,10 @@ #import "ConnectionParams.h" NSString* TSXSessionDidDisconnectNotification = @"TSXSessionDidDisconnect"; -NSString* TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect"; +NSString* TSXSessionDidFailToConnectNotification = + @"TSXSessionDidFailToConnect"; -@interface RDPSession (Private) +@interface RDPSession(Private) - (void)runSession; - (void)runSessionFinished:(NSNumber*)result; - (mfInfo*)mfi; @@ -35,245 +36,315 @@ NSString* TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect" @implementation RDPSession -@synthesize delegate=_delegate, params=_params, toolbarVisible = _toolbar_visible, uiRequestCompleted = _ui_request_completed, bookmark = _bookmark; +@synthesize delegate = _delegate, params = _params, + toolbarVisible = _toolbar_visible, uiRequestCompleted = _ui_request_completed, + bookmark = _bookmark; + (void)initialize { - ios_init_freerdp(); + ios_init_freerdp(); +} + +static BOOL addArgument(int* argc, char** *argv, const char* fmt, ...) +{ + va_list ap; + char* arg = NULL; + 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) +{ + int i; + + for (i = 0; i < argc; i++) + free(argv[i]); + + free(argv); } // Designated initializer. -- (id)initWithBookmark:(ComputerBookmark *)bookmark +- (id)initWithBookmark:(ComputerBookmark*)bookmark { + int status; + char** argv = NULL; + 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]; + [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; + _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]; - + _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"]) - settings->ColorDepth = [_params intForKey:@"colors" with3GEnabled:connected_via_3g]; - + if (!addArgument(&argc, &argv, + "/bpp:%d", [_params intForKey:@"colors" with3GEnabled: + connected_via_3g])) + goto out_free; + if ([_params hasValueForKey:@"port"]) - settings->ServerPort = [_params intForKey:@"port"]; - + if (!addArgument(&argc, &argv, "/port:%d", [_params intForKey:@"port"])) + goto out_free; + if ([_params boolForKey:@"console"]) - settings->ConsoleSession = 1; + if (!addArgument(&argc, &argv, "/admin")) + goto out_free; - // connection info - if (!(settings->ServerHostname = strdup([_params UTF8StringForKey:@"hostname"]))) + if (!addArgument(&argc, &argv, "/v:%s", [_params UTF8StringForKey: + @"hostname"])) goto out_free; - + // String settings if ([[_params StringForKey:@"username"] length]) { - settings->Username = strdup([_params UTF8StringForKey:@"username"]); - if (!settings->Username) + if (!addArgument(&argc, &argv, "/u:%s", [_params UTF8StringForKey: + @"username"])) goto out_free; } if ([[_params StringForKey:@"password"] length]) { - settings->Password = strdup([_params UTF8StringForKey:@"password"]); - if (!settings->Password) + if (!addArgument(&argc, &argv, "/p:%s", [_params UTF8StringForKey: + @"password"])) goto out_free; } if ([[_params StringForKey:@"domain"] length]) { - settings->Domain = strdup([_params UTF8StringForKey:@"domain"]); - if (!settings->Domain) + if (!addArgument(&argc, &argv, "/d:%s", [_params UTF8StringForKey: + @"domain"])) goto out_free; } - settings->ShellWorkingDirectory = strdup([_params UTF8StringForKey:@"working_directory"]); - settings->AlternateShell = strdup([_params UTF8StringForKey:@"remote_program"]); - - if (!settings->ShellWorkingDirectory || !settings->AlternateShell) - goto out_free; - -// RemoteFX - if ([_params boolForKey:@"perf_remotefx" with3GEnabled:connected_via_3g]) + if ([[_params StringForKey:@"working_directory"] length]) { - settings->RemoteFxCodec = TRUE; - settings->FastPathOutput = TRUE; - settings->ColorDepth = 32; - settings->LargePointerFlag = TRUE; - settings->FrameMarkerCommandEnabled = TRUE; - settings->FrameAcknowledge = 10; + if (!addArgument(&argc, &argv, "/shell-dir:%s", [_params UTF8StringForKey: + @"working_directory"])) + goto out_free; } - else + + if ([[_params StringForKey:@"remote_program"] length]) { - // enable NSCodec if remotefx is not used - settings->NSCodec = TRUE; + if (!addArgument(&argc, &argv, "/shell:%s", [_params UTF8StringForKey: + @"remote_program"])) + goto out_free; } - settings->BitmapCacheV3Enabled = 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; - + // 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"]) - settings->DesktopWidth = [_params intForKey:@"width"]; + if (!addArgument(&argc, &argv, "/w:%d", [_params intForKey:@"width"])) + goto out_free; + 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->UseRdpSecurityLayer = TRUE; - break; - - default: - break; - } - - // ts gateway settings - if ([_params boolForKey:@"enable_tsg_settings"]) - { - settings->GatewayHostname = strdup([_params UTF8StringForKey:@"tsg_hostname"]); - settings->GatewayPort = [_params intForKey:@"tsg_port"]; - settings->GatewayUsername = strdup([_params UTF8StringForKey:@"tsg_username"]); - settings->GatewayPassword = strdup([_params UTF8StringForKey:@"tsg_password"]); - settings->GatewayDomain = strdup([_params UTF8StringForKey:@"tsg_domain"]); - settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT; - settings->GatewayEnabled = TRUE; - settings->GatewayUseSameCredentials = FALSE; - - if (!settings->GatewayHostname || !settings->GatewayUsername || !settings->GatewayPassword - || !settings->GatewayDomain) - { - goto out_free; - } - } - + 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 - settings->KeyboardLayout = 0x409; - - // Audio settings - settings->AudioPlayback = FALSE; - settings->AudioCapture = FALSE; - + if (!addArgument(&argc, &argv, "/kbd:%d", 0x409)) + goto out_free; + + status = freerdp_client_settings_parse_command_line(_freerdp->settings, argc, + argv, + FALSE); + + if (0 != status) + goto out_free; + + freeArguments(argc, argv); [self mfi]->session = self; return self; - out_free: - [self release]; - return nil; + freeArguments(argc, argv); + [self release]; + return nil; } - (void)dealloc { [self setDelegate:nil]; - [_bookmark release]; - [_name release]; + [_bookmark release]; + [_name release]; [_params release]; - [_ui_request_completed release]; - + [_ui_request_completed release]; ios_freerdp_free(_freerdp); - [super dealloc]; } - (CGContextRef)bitmapContext { - return [self mfi]->bitmap_context; + 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; + 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; - } + 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); - + + // 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"]); + ios_events_send(mfi, [NSDictionary dictionaryWithObject:@"disconnect" forKey: + @"type"]); if (mfi->connection_state == TSXConnectionConnecting) { mfi->unwanted = YES; [self sessionDidDisconnect]; return; - } + } } - (TSXConnectionState)connectionState @@ -284,34 +355,34 @@ out_free: // suspends the session -(void)suspend { - if(!_suspended) - { - _suspended = YES; -// instance->update->SuppressOutput(instance->context, 0, NULL); - } + 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]; - } + 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; + return _suspended; } #pragma mark - @@ -330,7 +401,7 @@ out_free: { if ([[self delegate] respondsToSelector:@selector(session:needsRedrawInRect:)]) [[self delegate] session:self needsRedrawInRect:[rect_value CGRectValue]]; -} +} #pragma mark - @@ -338,37 +409,34 @@ out_free: - (UIImage*)getScreenshotWithSize:(CGSize)size { - NSAssert([self mfi]->bitmap_context != nil, @"Screenshot requested while having no valid RDP drawing context"); - + 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); + CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, size.height); CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); - CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, size.height), cgImage); - - UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); - + CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, + size.height), cgImage); + UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); - CGImageRelease(cgImage); - - return viewImage; + CGImageRelease(cgImage); + return viewImage; } - (rdpSettings*)getSessionParams { - return _freerdp->settings; + return _freerdp->settings; } - (NSString*)sessionName { - return _name; + return _name; } -@end +@end #pragma mark - -@implementation RDPSession (Private) +@implementation RDPSession(Private) - (mfInfo*)mfi { @@ -378,91 +446,99 @@ out_free: // 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]; + 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; - } + [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]; + if ([[self delegate] respondsToSelector:@selector(sessionDidConnect:)]) + [[self delegate] sessionDidConnect:self]; } - (void)sessionDidFailToConnect:(int)reason -{ - [[NSNotificationCenter defaultCenter] postNotificationName:TSXSessionDidFailToConnectNotification object:self]; +{ + [[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:)]) +{ + [[NSNotificationCenter defaultCenter] postNotificationName: + TSXSessionDidDisconnectNotification object:self]; + + if ([[self delegate] respondsToSelector:@selector(sessionDidDisconnect:)]) [[self delegate] sessionDidDisconnect:self]; } - (void)sessionBitmapContextWillChange { - if ([[self delegate] respondsToSelector:@selector(sessionBitmapContextWillChange:)]) + if ([[self delegate] respondsToSelector:@selector( + sessionBitmapContextWillChange:)]) [[self delegate] sessionBitmapContextWillChange:self]; } - (void)sessionBitmapContextDidChange { - if ([[self delegate] respondsToSelector:@selector(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]; + 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]; + if ([[self delegate] respondsToSelector:@selector(session: + verifyCertificateWithParams:)]) + [[self delegate] session:self verifyCertificateWithParams:params]; } @end diff --git a/client/iOS/Resources/MainWindow.xib b/client/iOS/Resources/MainWindow.xib index 25b6add..2ac5316 100644 --- a/client/iOS/Resources/MainWindow.xib +++ b/client/iOS/Resources/MainWindow.xib @@ -1,183 +1,36 @@ - - - - 1296 - 11D50b - 2182 - 1138.32 - 568.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1179 - - - IBUIWindow - IBUITabBarController - IBUITabBar - IBUICustomObject - IBProxyObject - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - IBCocoaTouchFramework - - - - 1316 - - {320, 480} - - - 1 - MSAxIDEAA - - NO - NO - - IBCocoaTouchFramework - YES - - - - - - 1 - 1 - - YES - IBCocoaTouchFramework - NO - - - - 266 - {{0, 431}, {320, 49}} - - _NS:29 - - 3 - MCAwAA - - IBCocoaTouchFramework - - - - - - - - delegate - - - - 12 - - - - window - - - - 13 - - - - tabBarController - - - - 14 - - - - - - 0 - - - - - - 2 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 4 - - - - - - - - 5 - - - - - 11 - - - AppDelegate - - - - - UIApplication - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - AppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MainTabBarController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - - 21 - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - YES - 3 - 1179 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.7.4