Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
87
third_party/FreeRDP/client/iOS/Misc/Reachability.h
vendored
Normal file
87
third_party/FreeRDP/client/iOS/Misc/Reachability.h
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
|
||||
File: Reachability.h
|
||||
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
|
||||
|
||||
Version: 2.2
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under
|
||||
Apple's copyrights in this original Apple software (the "Apple Software"), to
|
||||
use, reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions
|
||||
of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may be used
|
||||
to endorse or promote products derived from the Apple Software without specific
|
||||
prior written permission from Apple. Except as expressly stated in this notice,
|
||||
no other rights or licenses, express or implied, are granted by Apple herein,
|
||||
including but not limited to any patent rights that may be infringed by your
|
||||
derivative works or by other works in which the Apple Software may be
|
||||
incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
|
||||
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
|
||||
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2010 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#import <netinet/in.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NotReachable = 0,
|
||||
ReachableViaWiFi = 1,
|
||||
ReachableViaWWAN = 2
|
||||
} NetworkStatus;
|
||||
#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
|
||||
|
||||
@interface Reachability : NSObject
|
||||
{
|
||||
BOOL localWiFiRef;
|
||||
SCNetworkReachabilityRef reachabilityRef;
|
||||
}
|
||||
|
||||
// reachabilityWithHostName- Use to check the reachability of a particular host name.
|
||||
+ (Reachability *)reachabilityWithHostName:(NSString *)hostName;
|
||||
|
||||
// reachabilityWithAddress- Use to check the reachability of a particular IP address.
|
||||
+ (Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
|
||||
|
||||
// reachabilityForInternetConnection- checks whether the default route is available.
|
||||
// Should be used by applications that do not connect to a particular host
|
||||
+ (Reachability *)reachabilityForInternetConnection;
|
||||
|
||||
// reachabilityForLocalWiFi- checks whether a local wifi connection is available.
|
||||
+ (Reachability *)reachabilityForLocalWiFi;
|
||||
|
||||
// Start listening for reachability notifications on the current run loop
|
||||
- (BOOL)startNotifier;
|
||||
- (void)stopNotifier;
|
||||
|
||||
- (NetworkStatus)currentReachabilityStatus;
|
||||
// WWAN may be available, but not active until a connection has been established.
|
||||
// WiFi may require a connection for VPN on Demand.
|
||||
- (BOOL)connectionRequired;
|
||||
@end
|
||||
278
third_party/FreeRDP/client/iOS/Misc/Reachability.m
vendored
Normal file
278
third_party/FreeRDP/client/iOS/Misc/Reachability.m
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
|
||||
File: Reachability.m
|
||||
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
|
||||
|
||||
Version: 2.2
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under
|
||||
Apple's copyrights in this original Apple software (the "Apple Software"), to
|
||||
use, reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions
|
||||
of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may be used
|
||||
to endorse or promote products derived from the Apple Software without specific
|
||||
prior written permission from Apple. Except as expressly stated in this notice,
|
||||
no other rights or licenses, express or implied, are granted by Apple herein,
|
||||
including but not limited to any patent rights that may be infringed by your
|
||||
derivative works or by other works in which the Apple Software may be
|
||||
incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
|
||||
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
|
||||
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2010 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#import <sys/socket.h>
|
||||
#import <netinet/in.h>
|
||||
#import <netinet6/in6.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <ifaddrs.h>
|
||||
#import <netdb.h>
|
||||
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#import "Reachability.h"
|
||||
|
||||
#define kShouldPrintReachabilityFlags 1
|
||||
|
||||
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char *comment)
|
||||
{
|
||||
#if kShouldPrintReachabilityFlags
|
||||
|
||||
NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
|
||||
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
|
||||
|
||||
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', comment);
|
||||
#endif
|
||||
}
|
||||
|
||||
@implementation Reachability
|
||||
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,
|
||||
void *info)
|
||||
{
|
||||
#pragma unused(target, flags)
|
||||
NSCAssert(info != nullptr, @"info was nullptr in ReachabilityCallback");
|
||||
NSCAssert([(NSObject *)info isKindOfClass:[Reachability class]],
|
||||
@"info was wrong class in ReachabilityCallback");
|
||||
|
||||
// We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
|
||||
// in case someone uses the Reachablity object in a different thread.
|
||||
NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
Reachability *noteObject = (Reachability *)info;
|
||||
// Post a notification to notify the client that the network reachability changed.
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
|
||||
object:noteObject];
|
||||
|
||||
[myPool release];
|
||||
}
|
||||
|
||||
- (BOOL)startNotifier
|
||||
{
|
||||
BOOL retVal = NO;
|
||||
SCNetworkReachabilityContext context = { 0, self, nullptr, nullptr, nullptr };
|
||||
if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
|
||||
{
|
||||
if (SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(),
|
||||
kCFRunLoopDefaultMode))
|
||||
{
|
||||
retVal = YES;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
- (void)stopNotifier
|
||||
{
|
||||
if (reachabilityRef != nullptr)
|
||||
{
|
||||
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(),
|
||||
kCFRunLoopDefaultMode);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self stopNotifier];
|
||||
if (reachabilityRef != nullptr)
|
||||
{
|
||||
CFRelease(reachabilityRef);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
+ (Reachability *)reachabilityWithHostName:(NSString *)hostName;
|
||||
{
|
||||
Reachability *retVal = nullptr;
|
||||
SCNetworkReachabilityRef reachability =
|
||||
SCNetworkReachabilityCreateWithName(nullptr, [hostName UTF8String]);
|
||||
if (reachability != nullptr)
|
||||
{
|
||||
retVal = [[[self alloc] init] autorelease];
|
||||
if (retVal != nullptr)
|
||||
{
|
||||
retVal->reachabilityRef = reachability;
|
||||
retVal->localWiFiRef = NO;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
+ (Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
|
||||
{
|
||||
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(
|
||||
kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
|
||||
Reachability *retVal = nullptr;
|
||||
if (reachability != nullptr)
|
||||
{
|
||||
retVal = [[[self alloc] init] autorelease];
|
||||
if (retVal != nullptr)
|
||||
{
|
||||
retVal->reachabilityRef = reachability;
|
||||
retVal->localWiFiRef = NO;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
+ (Reachability *)reachabilityForInternetConnection;
|
||||
{
|
||||
struct sockaddr_in zeroAddress;
|
||||
bzero(&zeroAddress, sizeof(zeroAddress));
|
||||
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||
zeroAddress.sin_family = AF_INET;
|
||||
return [self reachabilityWithAddress:&zeroAddress];
|
||||
}
|
||||
|
||||
+ (Reachability *)reachabilityForLocalWiFi;
|
||||
{
|
||||
struct sockaddr_in localWifiAddress;
|
||||
bzero(&localWifiAddress, sizeof(localWifiAddress));
|
||||
localWifiAddress.sin_len = sizeof(localWifiAddress);
|
||||
localWifiAddress.sin_family = AF_INET;
|
||||
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
|
||||
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
|
||||
Reachability *retVal = [self reachabilityWithAddress:&localWifiAddress];
|
||||
if (retVal != nullptr)
|
||||
{
|
||||
retVal->localWiFiRef = YES;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#pragma mark Network Flag Handling
|
||||
|
||||
- (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
|
||||
{
|
||||
PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
|
||||
|
||||
BOOL retVal = NotReachable;
|
||||
if ((flags & kSCNetworkReachabilityFlagsReachable) &&
|
||||
(flags & kSCNetworkReachabilityFlagsIsDirect))
|
||||
{
|
||||
retVal = ReachableViaWiFi;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
|
||||
{
|
||||
PrintReachabilityFlags(flags, "networkStatusForFlags");
|
||||
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
|
||||
{
|
||||
// if target host is not reachable
|
||||
return NotReachable;
|
||||
}
|
||||
|
||||
BOOL retVal = NotReachable;
|
||||
|
||||
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
|
||||
{
|
||||
// if target host is reachable and no connection is required
|
||||
// then we'll assume (for now) that your on Wi-Fi
|
||||
retVal = ReachableViaWiFi;
|
||||
}
|
||||
|
||||
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0) ||
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
|
||||
{
|
||||
// ... and the connection is on-demand (or on-traffic) if the
|
||||
// calling application is using the CFSocketStream or higher APIs
|
||||
|
||||
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
|
||||
{
|
||||
// ... and no [user] intervention is needed
|
||||
retVal = ReachableViaWiFi;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
|
||||
{
|
||||
// ... but WWAN connections are OK if the calling application
|
||||
// is using the CFNetwork (CFSocketStream?) APIs.
|
||||
retVal = ReachableViaWWAN;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
- (BOOL)connectionRequired;
|
||||
{
|
||||
NSAssert(reachabilityRef != nullptr, @"connectionRequired called with nullptr reachabilityRef");
|
||||
SCNetworkReachabilityFlags flags;
|
||||
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
|
||||
{
|
||||
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NetworkStatus)currentReachabilityStatus
|
||||
{
|
||||
NSAssert(reachabilityRef != nullptr,
|
||||
@"currentNetworkStatus called with nullptr reachabilityRef");
|
||||
NetworkStatus retVal = NotReachable;
|
||||
SCNetworkReachabilityFlags flags;
|
||||
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
|
||||
{
|
||||
if (localWiFiRef)
|
||||
{
|
||||
retVal = [self localWiFiStatusForFlags:flags];
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = [self networkStatusForFlags:flags];
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
@end
|
||||
48
third_party/FreeRDP/client/iOS/Misc/SFHFKeychainUtils.h
vendored
Normal file
48
third_party/FreeRDP/client/iOS/Misc/SFHFKeychainUtils.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// SFHFKeychainUtils.h
|
||||
//
|
||||
// Created by Buzz Andersen on 10/20/08.
|
||||
// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
|
||||
// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SFHFKeychainUtils : NSObject
|
||||
{
|
||||
}
|
||||
|
||||
+ (NSString *)getPasswordForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error;
|
||||
+ (BOOL)storeUsername:(NSString *)username
|
||||
andPassword:(NSString *)password
|
||||
forServerName:(NSString *)serverName
|
||||
updateExisting:(BOOL)updateExisting
|
||||
error:(NSError **)error;
|
||||
+ (BOOL)deleteItemForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error;
|
||||
|
||||
@end
|
||||
501
third_party/FreeRDP/client/iOS/Misc/SFHFKeychainUtils.m
vendored
Normal file
501
third_party/FreeRDP/client/iOS/Misc/SFHFKeychainUtils.m
vendored
Normal file
@@ -0,0 +1,501 @@
|
||||
//
|
||||
// SFHFKeychainUtils.m
|
||||
//
|
||||
// Created by Buzz Andersen on 10/20/08.
|
||||
// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
|
||||
// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import "SFHFKeychainUtils.h"
|
||||
#import <Security/Security.h>
|
||||
|
||||
static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
|
||||
@interface SFHFKeychainUtils (PrivateMethods)
|
||||
+ (SecKeychainItemRef)getKeychainItemReferenceForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error;
|
||||
@end
|
||||
#endif
|
||||
|
||||
@implementation SFHFKeychainUtils
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
|
||||
|
||||
+ (NSString *)getPasswordForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !serviceName)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername:username
|
||||
andServerName:serverName
|
||||
error:error];
|
||||
|
||||
if (*error || !item)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
// from Advanced Mac OS X Programming, ch. 16
|
||||
UInt32 length;
|
||||
char *password;
|
||||
SecKeychainAttribute attributes[8];
|
||||
SecKeychainAttributeList list;
|
||||
|
||||
attributes[0].tag = kSecAccountItemAttr;
|
||||
attributes[1].tag = kSecDescriptionItemAttr;
|
||||
attributes[2].tag = kSecLabelItemAttr;
|
||||
attributes[3].tag = kSecModDateItemAttr;
|
||||
|
||||
list.count = 4;
|
||||
list.attr = attributes;
|
||||
|
||||
OSStatus status = SecKeychainItemCopyContent(item, nullptr, &list, &length, (void **)&password);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *passwordString = nil;
|
||||
|
||||
if (password != nullptr)
|
||||
{
|
||||
char passwordBuffer[1024];
|
||||
|
||||
if (length > 1023)
|
||||
{
|
||||
length = 1023;
|
||||
}
|
||||
strncpy(passwordBuffer, password, length);
|
||||
|
||||
passwordBuffer[length] = '\0';
|
||||
passwordString = [NSString stringWithCString:passwordBuffer encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
SecKeychainItemFreeContent(&list, password);
|
||||
|
||||
CFRelease(item);
|
||||
|
||||
return passwordString;
|
||||
}
|
||||
|
||||
+ (void)storeUsername:(NSString *)username
|
||||
andPassword:(NSString *)password
|
||||
forServerName:(NSString *)serverName
|
||||
updateExisting:(BOOL)updateExisting
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !password || !serverName)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
OSStatus status = noErr;
|
||||
|
||||
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername:username
|
||||
andServerName:serverName
|
||||
error:error];
|
||||
|
||||
if (*error && [*error code] != noErr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*error = nil;
|
||||
|
||||
if (item)
|
||||
{
|
||||
status = SecKeychainItemModifyAttributesAndData(
|
||||
item, nullptr, strlen([password UTF8String]), [password UTF8String]);
|
||||
|
||||
CFRelease(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SecKeychainAddGenericPassword(
|
||||
nullptr, strlen([serverName UTF8String]), [serverName UTF8String],
|
||||
strlen([username UTF8String]), [username UTF8String], strlen([password UTF8String]),
|
||||
[password UTF8String], nullptr);
|
||||
}
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)deleteItemForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !serverName)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:2000 userInfo:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
*error = nil;
|
||||
|
||||
SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername:username
|
||||
andServerName:serverName
|
||||
error:error];
|
||||
|
||||
if (*error && [*error code] != noErr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OSStatus status;
|
||||
|
||||
if (item)
|
||||
{
|
||||
status = SecKeychainItemDelete(item);
|
||||
|
||||
CFRelease(item);
|
||||
}
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (SecKeychainItemRef)getKeychainItemReferenceForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !serverName)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
*error = nil;
|
||||
|
||||
SecKeychainItemRef item;
|
||||
|
||||
OSStatus status = SecKeychainFindGenericPassword(
|
||||
nullptr, strlen([serverName UTF8String]), [serverName UTF8String],
|
||||
strlen([username UTF8String]), [username UTF8String], nullptr, nullptr, &item);
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
if (status != errSecItemNotFound)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
|
||||
code:status
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
+ (NSString *)getPasswordForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !serverName)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (error != nil)
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
// Set up a query dictionary with the base query attributes: item type (generic), username, and
|
||||
// service
|
||||
|
||||
NSArray *keys = [[[NSArray alloc]
|
||||
initWithObjects:(NSString *)kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease];
|
||||
NSArray *objects = [[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword,
|
||||
username, serverName, nil] autorelease];
|
||||
|
||||
NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects:objects
|
||||
forKeys:keys] autorelease];
|
||||
|
||||
// First do a query for attributes, in case we already have a Keychain item with no password
|
||||
// data set. One likely way such an incorrect item could have come about is due to the previous
|
||||
// (incorrect) version of this code (which set the password as a generic attribute instead of
|
||||
// password data).
|
||||
|
||||
NSDictionary *attributeResult = nullptr;
|
||||
NSMutableDictionary *attributeQuery = [query mutableCopy];
|
||||
[attributeQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
|
||||
OSStatus status =
|
||||
SecItemCopyMatching((CFDictionaryRef)attributeQuery, (CFTypeRef *)&attributeResult);
|
||||
|
||||
[attributeResult release];
|
||||
[attributeQuery release];
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
// No existing item found--simply return nil for the password
|
||||
if (error != nil && status != errSecItemNotFound)
|
||||
{
|
||||
// Only return an error if a real exception happened--not simply for "not found."
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
|
||||
code:status
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
// We have an existing item, now query for the password data associated with it.
|
||||
|
||||
NSData *resultData = nil;
|
||||
NSMutableDictionary *passwordQuery = [query mutableCopy];
|
||||
[passwordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
|
||||
|
||||
status = SecItemCopyMatching((CFDictionaryRef)passwordQuery, (CFTypeRef *)&resultData);
|
||||
|
||||
[resultData autorelease];
|
||||
[passwordQuery release];
|
||||
|
||||
if (status != noErr)
|
||||
{
|
||||
if (status == errSecItemNotFound)
|
||||
{
|
||||
// We found attributes for the item previously, but no password now, so return a special
|
||||
// error. Users of this API will probably want to detect this error and prompt the user
|
||||
// to re-enter their credentials. When you attempt to store the re-entered credentials
|
||||
// using storeUsername:andPassword:forServiceName:updateExisting:error
|
||||
// the old, incorrect entry will be deleted and a new one with a properly encrypted
|
||||
// password will be added.
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
|
||||
code:-1999
|
||||
userInfo:nil];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something else went wrong. Simply return the normal Keychain API error code.
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain
|
||||
code:status
|
||||
userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *password = nil;
|
||||
|
||||
if (resultData)
|
||||
{
|
||||
password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is an existing item, but we weren't able to get password data for it for some
|
||||
// reason, Possibly as a result of an item being incorrectly entered by the previous code.
|
||||
// Set the -1999 error so the code above us can prompt the user again.
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-1999 userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return [password autorelease];
|
||||
}
|
||||
|
||||
+ (BOOL)storeUsername:(NSString *)username
|
||||
andPassword:(NSString *)password
|
||||
forServerName:(NSString *)serverName
|
||||
updateExisting:(BOOL)updateExisting
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !password || !serverName)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
// See if we already have a password entered for these credentials.
|
||||
NSError *getError = nil;
|
||||
NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername:username
|
||||
andServerName:serverName
|
||||
error:&getError];
|
||||
|
||||
if ([getError code] == -1999)
|
||||
{
|
||||
// There is an existing entry without a password properly stored (possibly as a result of
|
||||
// the previous incorrect version of this code. Delete the existing item before moving on
|
||||
// entering a correct one.
|
||||
|
||||
getError = nil;
|
||||
|
||||
[self deleteItemForUsername:username andServerName:serverName error:&getError];
|
||||
|
||||
if ([getError code] != noErr)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = getError;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
else if ([getError code] != noErr)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = getError;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (error != nil)
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
OSStatus status = noErr;
|
||||
|
||||
if (existingPassword)
|
||||
{
|
||||
// We have an existing, properly entered item with a password.
|
||||
// Update the existing item.
|
||||
|
||||
if (![existingPassword isEqualToString:password] && updateExisting)
|
||||
{
|
||||
// Only update if we're allowed to update existing. If not, simply do nothing.
|
||||
|
||||
NSArray *keys =
|
||||
[[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrService,
|
||||
kSecAttrLabel, kSecAttrAccount, nil] autorelease];
|
||||
|
||||
NSArray *objects =
|
||||
[[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword, serverName,
|
||||
serverName, username, nil] autorelease];
|
||||
|
||||
NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects
|
||||
forKeys:keys] autorelease];
|
||||
|
||||
status = SecItemUpdate(
|
||||
(CFDictionaryRef)query,
|
||||
(CFDictionaryRef)[NSDictionary
|
||||
dictionaryWithObject:[password dataUsingEncoding:NSUTF8StringEncoding]
|
||||
forKey:(NSString *)kSecValueData]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No existing entry (or an existing, improperly entered, and therefore now
|
||||
// deleted, entry). Create a new entry.
|
||||
|
||||
NSArray *keys =
|
||||
[[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrService, kSecAttrLabel,
|
||||
kSecAttrAccount, kSecValueData, nil] autorelease];
|
||||
|
||||
NSArray *objects = [[[NSArray alloc]
|
||||
initWithObjects:(NSString *)kSecClassGenericPassword, serverName, serverName, username,
|
||||
[password dataUsingEncoding:NSUTF8StringEncoding], nil] autorelease];
|
||||
|
||||
NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects
|
||||
forKeys:keys] autorelease];
|
||||
|
||||
status = SecItemAdd((CFDictionaryRef)query, nullptr);
|
||||
}
|
||||
|
||||
if (error != nil && status != noErr)
|
||||
{
|
||||
// Something went wrong with adding the new item. Return the Keychain error code.
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)deleteItemForUsername:(NSString *)username
|
||||
andServerName:(NSString *)serverName
|
||||
error:(NSError **)error
|
||||
{
|
||||
if (!username || !serverName)
|
||||
{
|
||||
if (error != nil)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (error != nil)
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
|
||||
NSArray *keys =
|
||||
[[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrAccount, kSecAttrService,
|
||||
kSecReturnAttributes, nil] autorelease];
|
||||
NSArray *objects =
|
||||
[[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword, username,
|
||||
serverName, kCFBooleanTrue, nil] autorelease];
|
||||
|
||||
NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects forKeys:keys] autorelease];
|
||||
|
||||
OSStatus status = SecItemDelete((CFDictionaryRef)query);
|
||||
|
||||
if (error != nil && status != noErr)
|
||||
{
|
||||
*error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
57
third_party/FreeRDP/client/iOS/Misc/TSXTypes.h
vendored
Normal file
57
third_party/FreeRDP/client/iOS/Misc/TSXTypes.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Basic type defines for TSX RDC
|
||||
|
||||
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/.
|
||||
*/
|
||||
|
||||
#ifndef TSXRemoteDesktop_TSXTypes_h
|
||||
#define TSXRemoteDesktop_TSXTypes_h
|
||||
|
||||
#pragma mark Internal state
|
||||
|
||||
// Represents the underlying state of a TWSession RDP connection.
|
||||
typedef enum
|
||||
{
|
||||
TSXConnectionClosed =
|
||||
0, // Session either hasn't begun connecting, or its connection has finished disconnecting.
|
||||
TSXConnectionConnecting =
|
||||
1, // Session is in the process of establishing an RDP connection. A TCP or SSL connection
|
||||
// might be established, but the RDP initialization sequence isn't finished.
|
||||
TSXConnectionConnected =
|
||||
2, // Session has a full RDP connection established; though if the windows computer doesn't
|
||||
// support NLA, a login screen might be shown in the session.
|
||||
TSXConnectionDisconnected = 3 // Session is disconnected at the RDP layer. TSX RDC might still
|
||||
// be disposing of resources, however.
|
||||
} TSXConnectionState;
|
||||
|
||||
#pragma mark Session settings
|
||||
|
||||
// Represents the type of screen resolution the user has selected. Most are dynamic sizes, meaning
|
||||
// that the actual session dimensions are calculated when connecting.
|
||||
typedef enum
|
||||
{
|
||||
TSXScreenOptionFixed = 0, // A static resolution, like 1024x768
|
||||
TSXScreenOptionFitScreen = 1, // Upon connection, fit the session to the entire screen size
|
||||
TSXScreenOptionCustom = 2, // Like fixed just specified by the user
|
||||
} TSXScreenOptions;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSXAudioPlaybackLocal = 0,
|
||||
TSXAudioPlaybackServer = 1,
|
||||
TSXAudioPlaybackSilent = 2
|
||||
} TSXAudioPlaybackOptions;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSXProtocolSecurityAutomatic = 0,
|
||||
TSXProtocolSecurityRDP = 1,
|
||||
TSXProtocolSecurityTLS = 2,
|
||||
TSXProtocolSecurityNLA = 3
|
||||
} TSXProtocolSecurityOptions;
|
||||
|
||||
#endif
|
||||
80
third_party/FreeRDP/client/iOS/Misc/Utils.h
vendored
Normal file
80
third_party/FreeRDP/client/iOS/Misc/Utils.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
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.
|
||||
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 <CoreGraphics/CoreGraphics.h>
|
||||
#import "TSXTypes.h"
|
||||
|
||||
// helper macro to encode a table path into a tag value (used to identify controls in their delegate
|
||||
// handlers)
|
||||
#define GET_TAG(section, row) ((((int)section) << 16) | ((int)(row)))
|
||||
#define GET_TAG_FROM_PATH(path) ((((int)path.section) << 16) | ((int)(path.row)))
|
||||
|
||||
BOOL ScanHostNameAndPort(NSString *address, NSString **host, unsigned short *port);
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Screen Resolutions
|
||||
|
||||
NSString *ScreenResolutionDescription(TSXScreenOptions type, int width, int height);
|
||||
BOOL ScanScreenResolution(NSString *description, int *width, int *height, TSXScreenOptions *type);
|
||||
|
||||
NSDictionary *SelectionForColorSetting(void);
|
||||
NSArray *ResolutionModes(void);
|
||||
|
||||
#pragma mark Security Protocol
|
||||
|
||||
NSString *ProtocolSecurityDescription(TSXProtocolSecurityOptions type);
|
||||
BOOL ScanProtocolSecurity(NSString *description, TSXProtocolSecurityOptions *type);
|
||||
NSDictionary *SelectionForSecuritySetting(void);
|
||||
|
||||
#pragma mark Bookmarks
|
||||
@class BookmarkBase;
|
||||
NSMutableArray *FilterBookmarks(NSArray *bookmarks, NSArray *filter_words);
|
||||
NSMutableArray *FilterHistory(NSArray *history, NSString *filterStr);
|
||||
|
||||
#pragma mark iPad/iPhone detection
|
||||
|
||||
BOOL IsPad(void);
|
||||
BOOL IsPhone(void);
|
||||
|
||||
#pragma mark Version Info
|
||||
NSString *TSXAppFullVersion(void);
|
||||
|
||||
#pragma mark Touch/Mouse handling
|
||||
|
||||
// set mouse buttons swapped flag
|
||||
void SetSwapMouseButtonsFlag(BOOL swapped);
|
||||
|
||||
// set invert scrolling flag
|
||||
void SetInvertScrollingFlag(BOOL invert);
|
||||
|
||||
// return event value for left mouse button
|
||||
int GetLeftMouseButtonClickEvent(BOOL down);
|
||||
|
||||
// return event value for right mouse button
|
||||
int GetRightMouseButtonClickEvent(BOOL down);
|
||||
|
||||
// return event value for mouse move event
|
||||
int GetMouseMoveEvent(void);
|
||||
|
||||
// return mouse wheel event
|
||||
int GetMouseWheelEvent(BOOL down);
|
||||
|
||||
// scrolling gesture detection delta
|
||||
CGFloat GetScrollGestureDelta(void);
|
||||
|
||||
#pragma mark Connectivity tools
|
||||
// activates the iphone's WWAN interface in case it is offline
|
||||
void WakeUpWWAN(void);
|
||||
|
||||
#pragma mark System Info functions
|
||||
NSString *TSXGetPlatform(void);
|
||||
BOOL TSXDeviceHasJailBreak(void);
|
||||
NSString *TSXGetPrimaryMACAddress(NSString *sep);
|
||||
397
third_party/FreeRDP/client/iOS/Misc/Utils.m
vendored
Normal file
397
third_party/FreeRDP/client/iOS/Misc/Utils.m
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
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.
|
||||
If a copy of the MPL was not distributed with this file, You can obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#import "Utils.h"
|
||||
#import "OrderedDictionary.h"
|
||||
#import "TSXAdditions.h"
|
||||
|
||||
#import <freerdp/input.h>
|
||||
#import <freerdp/version.h>
|
||||
#import <freerdp/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if_dl.h>
|
||||
|
||||
BOOL ScanHostNameAndPort(NSString *address, NSString **host, unsigned short *port)
|
||||
{
|
||||
*host = @"";
|
||||
*port = 0;
|
||||
|
||||
if (![address length])
|
||||
return NO;
|
||||
|
||||
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"rdp://%@", address]];
|
||||
|
||||
if (!url || ![[url host] length])
|
||||
return NO;
|
||||
|
||||
*host = [url host];
|
||||
*port = [[url port] unsignedShortValue];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Working with Screen Resolutions
|
||||
|
||||
NSString *LocalizedFitScreen()
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
BOOL ScanScreenResolution(NSString *description, int *width, int *height, TSXScreenOptions *type)
|
||||
{
|
||||
*height = 0;
|
||||
*width = 0;
|
||||
*type = TSXScreenOptionFixed;
|
||||
|
||||
if ([description isEqualToString:LocalizedFitScreen()])
|
||||
{
|
||||
*type = TSXScreenOptionFitScreen;
|
||||
return YES;
|
||||
}
|
||||
else if ([description isEqualToString:LocalizedCustom()])
|
||||
{
|
||||
*type = TSXScreenOptionCustom;
|
||||
return YES;
|
||||
}
|
||||
|
||||
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];
|
||||
return YES;
|
||||
}
|
||||
|
||||
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: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;
|
||||
}
|
||||
|
||||
#pragma mark Working with Security Protocols
|
||||
|
||||
NSString *LocalizedAutomaticSecurity()
|
||||
{
|
||||
return NSLocalizedString(@"Automatic", @"Automatic protocol security selection");
|
||||
}
|
||||
|
||||
NSString *ProtocolSecurityDescription(TSXProtocolSecurityOptions type)
|
||||
{
|
||||
if (type == TSXProtocolSecurityNLA)
|
||||
return @"NLA";
|
||||
else if (type == TSXProtocolSecurityTLS)
|
||||
return @"TLS";
|
||||
else if (type == TSXProtocolSecurityRDP)
|
||||
return @"RDP";
|
||||
|
||||
return LocalizedAutomaticSecurity();
|
||||
}
|
||||
|
||||
BOOL ScanProtocolSecurity(NSString *description, TSXProtocolSecurityOptions *type)
|
||||
{
|
||||
*type = TSXProtocolSecurityRDP;
|
||||
|
||||
if ([description isEqualToString:@"NLA"])
|
||||
{
|
||||
*type = TSXProtocolSecurityNLA;
|
||||
return YES;
|
||||
}
|
||||
else if ([description isEqualToString:@"TLS"])
|
||||
{
|
||||
*type = TSXProtocolSecurityTLS;
|
||||
return YES;
|
||||
}
|
||||
else if ([description isEqualToString:@"RDP"])
|
||||
{
|
||||
*type = TSXProtocolSecurityRDP;
|
||||
return YES;
|
||||
}
|
||||
else if ([description isEqualToString:LocalizedAutomaticSecurity()])
|
||||
{
|
||||
*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;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Bookmarks
|
||||
|
||||
#import "Bookmark.h"
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
#pragma mark Version Info
|
||||
NSString *TSXAppFullVersion()
|
||||
{
|
||||
return [NSString stringWithUTF8String:FREERDP_GIT_REVISION];
|
||||
}
|
||||
|
||||
#pragma mark iPad/iPhone detection
|
||||
|
||||
BOOL IsPad()
|
||||
{
|
||||
#ifdef UI_USER_INTERFACE_IDIOM
|
||||
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL IsPhone()
|
||||
{
|
||||
#ifdef UI_USER_INTERFACE_IDIOM
|
||||
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone);
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
// set mouse buttons swapped flag
|
||||
static BOOL g_swap_mouse_buttons = NO;
|
||||
void SetSwapMouseButtonsFlag(BOOL swapped)
|
||||
{
|
||||
g_swap_mouse_buttons = swapped;
|
||||
}
|
||||
|
||||
// set invert scrolling flag
|
||||
static BOOL g_invert_scrolling = NO;
|
||||
void SetInvertScrollingFlag(BOOL invert)
|
||||
{
|
||||
g_invert_scrolling = invert;
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// get mouse move event
|
||||
int GetMouseMoveEvent()
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
// scrolling gesture detection delta
|
||||
CGFloat GetScrollGestureDelta()
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
#pragma mark System Info functions
|
||||
|
||||
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 != nullptr; 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:@"/etc/apt/"])
|
||||
return YES;
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *TSXGetPlatform()
|
||||
{
|
||||
size_t size;
|
||||
sysctlbyname("hw.machine", nullptr, &size, nullptr, 0);
|
||||
char *machine = malloc(size);
|
||||
sysctlbyname("hw.machine", machine, &size, nullptr, 0);
|
||||
NSString *platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];
|
||||
free(machine);
|
||||
return platform;
|
||||
}
|
||||
Reference in New Issue
Block a user