/*
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 <Foundation/Foundation.h>
#import <freerdp/gdi/gdi.h>
#import "ios_freerdp_ui.h"
#import "RDPSession.h"
#pragma mark -
#pragma mark Certificate authentication
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];
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]);
*domain = strdup([[params objectForKey:@"domain"] UTF8String]);
if (!(*username) || !(*password) || !(*domain))
{
free(*username);
free(*password);
free(*domain);
return FALSE;
}
return TRUE;
}
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)
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];
// request certificate verification UI
[mfi->session performSelectorOnMainThread:@selector(
sessionVerifyCertificateWithParams:) 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 0;
}
return 1;
}
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_verify_certificate(instance, common_name, subject, issuer,
new_fingerprint, FALSE);
}
#pragma mark -
#pragma mark Graphics updates
BOOL ios_ui_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = TRUE;
return TRUE;
}
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);
if (!gdi->primary->hdc->hwnd->invalid->null)
[mfi->session performSelectorOnMainThread:@selector(
setNeedsDisplayInRectAsValue:) withObject:[NSValue valueWithCGRect:dirty_rect]
waitUntilDone:NO];
return TRUE;
}
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;
}
#pragma mark -
#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();
if (GetBytesPerPixel(gdi->dstFormat) == 2)
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];
}
void ios_allocate_display_buffer(mfInfo* mfi)
{
ios_create_bitmap_context(mfi);
}
void ios_resize_display_buffer(mfInfo* mfi)
{
// Release the old context in a thread-safe manner
CGContextRef old_context = mfi->bitmap_context;
mfi->bitmap_context = NULL;
CGContextRelease(old_context);
// Create the new context
ios_create_bitmap_context(mfi);
}