/* 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 #import #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); }