1#include "mega/osx/osxutils.h" 2#if defined(__APPLE__) && !(TARGET_OS_IPHONE) 3#include <Cocoa/Cocoa.h> 4#include <SystemConfiguration/SystemConfiguration.h> 5#elif TARGET_OS_IOS 6#include <Foundation/Foundation.h> 7#endif 8 9#include "mega.h" 10 11using namespace mega; 12using namespace std; 13 14enum { HTTP_PROXY = 0, HTTPS_PROXY }; 15 16void path2localMac(const string* path, string* local) 17{ 18 if (!path->size()) 19 { 20 *local = ""; 21 return; 22 } 23 // Multiple calls to path2localMac cause a high memory usage on macOS. To avoid it, use autorelease pool to release any temp object at the end of the pool. 24 // At the end of the block, the temporary objects are released, which typically results in their deallocation thereby reducing the program’s memory footprint. 25 @autoreleasepool { 26 27 // Compatibility with new APFS filesystem 28 // Use the fileSystemRepresentation property of NSString objects when creating and opening 29 // files with lower-level filesystem APIs such as POSIX open(2), or when storing filenames externally from the filesystem` 30 NSString *tempPath = [[NSString alloc] initWithUTF8String:path->c_str()]; 31 const char *pathRepresentation = NULL; 32 @try 33 { 34 pathRepresentation = [tempPath fileSystemRepresentation]; 35 } 36 @catch (NSException *e) 37 { 38 LOG_err << "Failed getting file system representation (APFS filesystem)"; 39 local->clear(); 40 #if !__has_feature(objc_arc) 41 [tempPath release]; 42 #endif 43 return; 44 } 45 46 if (pathRepresentation) 47 { 48 *local = pathRepresentation; 49 } 50 else 51 { 52 local->clear(); 53 } 54 #if !__has_feature(objc_arc) 55 [tempPath release]; 56 #endif 57 58 } 59} 60 61#if defined(__APPLE__) && !(TARGET_OS_IPHONE) 62 63CFTypeRef getValueFromKey(CFDictionaryRef dict, const void *key, CFTypeID type) 64{ 65 CFTypeRef value = CFDictionaryGetValue(dict, key); 66 if (!value) 67 { 68 return NULL; 69 } 70 71 if ((CFGetTypeID(value) == type)) 72 { 73 return value; 74 } 75 76 return NULL; 77} 78 79bool getProxyConfiguration(CFDictionaryRef dict, int proxyType, Proxy* proxy) 80{ 81 int isEnabled = 0; 82 int port; 83 84 if (proxyType != HTTPS_PROXY && proxyType != HTTP_PROXY) 85 { 86 return false; 87 } 88 89 CFStringRef proxyEnableKey = proxyType == HTTP_PROXY ? kSCPropNetProxiesHTTPEnable : kSCPropNetProxiesHTTPSEnable; 90 CFStringRef proxyHostKey = proxyType == HTTP_PROXY ? kSCPropNetProxiesHTTPProxy : kSCPropNetProxiesHTTPSProxy; 91 CFStringRef portKey = proxyType == HTTP_PROXY ? kSCPropNetProxiesHTTPPort : kSCPropNetProxiesHTTPSPort; 92 93 CFNumberRef proxyEnabledRef = (CFNumberRef)getValueFromKey(dict, proxyEnableKey, CFNumberGetTypeID()); 94 if (proxyEnabledRef && CFNumberGetValue(proxyEnabledRef, kCFNumberIntType, &isEnabled) && (isEnabled != 0)) 95 { 96 if ([(NSDictionary*)dict valueForKey: proxyType == HTTP_PROXY ? @"HTTPUser" : @"HTTPSUser"] != nil) 97 { 98 // Username set, skip proxy configuration. We only allow proxies withouth user/pw credentials 99 // to not have to request the password to the user to read the keychain 100 return false; 101 } 102 103 CFStringRef hostRef = (CFStringRef)getValueFromKey(dict, proxyHostKey, CFStringGetTypeID()); 104 if (hostRef) 105 { 106 CFIndex length = CFStringGetLength(hostRef); 107 CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; 108 char *buffer = new char[maxSize]; 109 if (CFStringGetCString(hostRef, buffer, maxSize, kCFStringEncodingUTF8)) 110 { 111 CFNumberRef portRef = (CFNumberRef)getValueFromKey(dict, portKey, CFNumberGetTypeID()); 112 if (portRef && CFNumberGetValue(portRef, kCFNumberIntType, &port)) 113 { 114 ostringstream oss; 115 oss << (proxyType == HTTP_PROXY ? "http://" : "https://") << buffer << ":" << port; 116 string link = oss.str(); 117 proxy->setProxyType(Proxy::CUSTOM); 118 proxy->setProxyURL(&link); 119 delete [] buffer; 120 return true; 121 } 122 } 123 delete [] buffer; 124 } 125 } 126 return false; 127} 128 129void getOSXproxy(Proxy* proxy) 130{ 131 CFDictionaryRef proxySettings = NULL; 132 proxySettings = SCDynamicStoreCopyProxies(NULL); 133 if (!proxySettings) 134 { 135 return; 136 } 137 138 if (!getProxyConfiguration(proxySettings, HTTPS_PROXY, proxy)) 139 { 140 getProxyConfiguration(proxySettings, HTTP_PROXY, proxy); 141 } 142 CFRelease(proxySettings); 143} 144#endif 145