├── .gitignore ├── export-proxies.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── export-proxies ├── main.swift └── ProxySettings.swift └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | **/xcuserdata/* 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /export-proxies.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /export-proxies/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // export-proxies 4 | // 5 | // Created by Jan Vogt on 16.03.15. 6 | // Copyright (c) 2015 Jan Vogt. All rights reserved. 7 | // 8 | 9 | if let settings = ProxySettings() { 10 | print(settings.exports) 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # export-proxies 2 | 3 | A simple tool for exporting OS X proxy settings as environment variables. 4 | 5 | ## Usage 6 | 7 | Build export-proxies using Xcode. Then add 8 | ```sh 9 | eval `./path/to/export-proxies` 10 | ``` 11 | to your .profile, .bach_profile, .bashrc, or whatever file you're using to set up your environment. 12 | 13 | NOTE: 14 | 15 | If you want to use http protocol for https proxy, you should run 16 | ```sh 17 | eval `./path/to/export-proxies --use-http-protocol-for-https-proxy` 18 | ``` 19 | instead. 20 | 21 | ## Credits 22 | 23 | This was inspired by Mark Assad's [proxy-config](http://sydney.edu.au/engineering/it/~massad/project-proxy-config.html) that does not work with OS X 10.10. 24 | 25 | Authors: 26 | 27 | - [@janvogt](https://github.com/janvogt) 28 | - [@mckelvin](https://github.com/mckelvin) 29 | -------------------------------------------------------------------------------- /export-proxies/ProxySettings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProxySettings.swift 3 | // export-proxies 4 | // 5 | // Created by Jan Vogt on 16.03.15. 6 | // Copyright (c) 2015 janvogt. All rights reserved. 7 | // 8 | 9 | import SystemConfiguration 10 | import CoreFoundation 11 | import Foundation 12 | 13 | private protocol ValueGetter { 14 | var type: ProxySettings.ProxySetting { get } 15 | func getValueFromDict(_ dict: NSDictionary) -> String? 16 | } 17 | 18 | class ProxySettings { 19 | fileprivate var settings = [Setting]() 20 | fileprivate struct Setting { 21 | var name: String 22 | var value: String 23 | var allCapitalizations: [Setting] { 24 | return [Setting(name: name.lowercased(), value: value), 25 | Setting(name: name.uppercased(), value: value), 26 | Setting(name: name.capitalized, value: value)] 27 | } 28 | var definition: String { 29 | get { 30 | return "\(name)=\"\(value)\"" 31 | } 32 | } 33 | } 34 | fileprivate enum ProxySetting { 35 | case http, https, ftp, socks, exceptions 36 | var envVariableName: String { 37 | get { 38 | var envVar: String 39 | switch self { 40 | case .http: envVar = "http" 41 | case .https: envVar = "https" 42 | case .ftp: envVar = "ftp" 43 | case .socks: envVar = "all" 44 | case .exceptions: envVar = "no" 45 | } 46 | return suffixProxy(envVar) 47 | } 48 | } 49 | var protocolName: String? { 50 | get { 51 | var httpsProxyProtocol: String = "https" 52 | if CommandLine.argc == 2 { 53 | if CommandLine.arguments[1] == "--use-http-protocol-for-https-proxy" { 54 | httpsProxyProtocol = "http" 55 | } 56 | } 57 | var proto: String? 58 | switch self { 59 | case .http: proto = "http" 60 | case .https: proto = httpsProxyProtocol 61 | case .ftp: proto = "ftp" 62 | case .socks: proto = "socks" 63 | default: break 64 | } 65 | return proto 66 | } 67 | } 68 | fileprivate func suffixProxy(_ label: String) -> String { 69 | return "\(label)_proxy" 70 | } 71 | } 72 | fileprivate struct ProxyProtocol: ValueGetter { 73 | let type: ProxySetting 74 | let kHost, kPort, kEnabled: String 75 | func getValueFromDict(_ dict: NSDictionary) -> String? { 76 | var value: String? 77 | switch (type.protocolName, dict[kHost] as! NSString?, dict[kPort] as! NSNumber?, dict[kEnabled] as! NSNumber?) { 78 | case (.some(let proto), .some(let host), .some(let port), let enabled) where (enabled != nil && enabled! == 1): 79 | value = "\(proto)://\(host):\(port)" 80 | default: break 81 | } 82 | return value 83 | } 84 | } 85 | fileprivate struct Exception: ValueGetter { 86 | let type = ProxySetting.exceptions 87 | let kExceptions: NSString = kSCPropNetProxiesExceptionsList 88 | func getValueFromDict(_ dict: NSDictionary) -> String? { 89 | var value: String? 90 | switch (type, dict[kExceptions] as? [String]) { 91 | case (.exceptions, .some(let exceptions)): 92 | value = exceptions.map { 93 | $0.replacingOccurrences(of: "*.", with: ".") 94 | }.joined(separator: ",") 95 | default: break 96 | } 97 | return value 98 | } 99 | } 100 | fileprivate let protocols: [ValueGetter] = [ 101 | ProxyProtocol(type: .http, 102 | kHost: kSCPropNetProxiesHTTPProxy as String, 103 | kPort: kSCPropNetProxiesHTTPPort as String, 104 | kEnabled: kSCPropNetProxiesHTTPEnable as String), 105 | ProxyProtocol(type: .https, 106 | kHost: kSCPropNetProxiesHTTPSProxy as String, 107 | kPort: kSCPropNetProxiesHTTPSPort as String, 108 | kEnabled: kSCPropNetProxiesHTTPSEnable as String), 109 | ProxyProtocol(type: .ftp, 110 | kHost: kSCPropNetProxiesFTPProxy as String, 111 | kPort: kSCPropNetProxiesFTPPort as String, 112 | kEnabled: kSCPropNetProxiesFTPEnable as String), 113 | ProxyProtocol(type: .socks, 114 | kHost: kSCPropNetProxiesSOCKSProxy as String, 115 | kPort: kSCPropNetProxiesSOCKSPort as String, 116 | kEnabled: kSCPropNetProxiesSOCKSEnable as String), 117 | Exception() 118 | ] 119 | init?() { 120 | if let store = SCDynamicStoreCreateWithOptions(nil, "app" as CFString, nil, nil, nil) { 121 | if let osxProxySettings: NSDictionary = SCDynamicStoreCopyProxies(store) { 122 | for proto in protocols { 123 | switch (proto.type.envVariableName, proto.getValueFromDict(osxProxySettings)) { 124 | case (let name, .some(let value)): 125 | let setting = Setting(name: name, value: value) 126 | settings.append(contentsOf: setting.allCapitalizations) 127 | default: break 128 | } 129 | } 130 | } else { 131 | return nil 132 | } 133 | } else { 134 | return nil 135 | } 136 | } 137 | var exports: String { 138 | get { 139 | return settings.map { "export \($0.definition)" }.joined(separator: "\n") 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /export-proxies.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 610DB3911AB77DFF0005D314 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610DB3901AB77DFF0005D314 /* main.swift */; }; 11 | 610DB3981AB77E690005D314 /* ProxySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610DB3971AB77E690005D314 /* ProxySettings.swift */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 610DB38B1AB77DFF0005D314 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 610DB38D1AB77DFF0005D314 /* export-proxies */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "export-proxies"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 610DB3901AB77DFF0005D314 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 29 | 610DB3971AB77E690005D314 /* ProxySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxySettings.swift; sourceTree = ""; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | 610DB38A1AB77DFF0005D314 /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | ); 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXFrameworksBuildPhase section */ 41 | 42 | /* Begin PBXGroup section */ 43 | 610DB3841AB77DFF0005D314 = { 44 | isa = PBXGroup; 45 | children = ( 46 | 610DB38F1AB77DFF0005D314 /* export-proxies */, 47 | 610DB38E1AB77DFF0005D314 /* Products */, 48 | ); 49 | sourceTree = ""; 50 | }; 51 | 610DB38E1AB77DFF0005D314 /* Products */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 610DB38D1AB77DFF0005D314 /* export-proxies */, 55 | ); 56 | name = Products; 57 | sourceTree = ""; 58 | }; 59 | 610DB38F1AB77DFF0005D314 /* export-proxies */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 610DB3901AB77DFF0005D314 /* main.swift */, 63 | 610DB3971AB77E690005D314 /* ProxySettings.swift */, 64 | ); 65 | path = "export-proxies"; 66 | sourceTree = ""; 67 | }; 68 | /* End PBXGroup section */ 69 | 70 | /* Begin PBXNativeTarget section */ 71 | 610DB38C1AB77DFF0005D314 /* export-proxies */ = { 72 | isa = PBXNativeTarget; 73 | buildConfigurationList = 610DB3941AB77DFF0005D314 /* Build configuration list for PBXNativeTarget "export-proxies" */; 74 | buildPhases = ( 75 | 610DB3891AB77DFF0005D314 /* Sources */, 76 | 610DB38A1AB77DFF0005D314 /* Frameworks */, 77 | 610DB38B1AB77DFF0005D314 /* CopyFiles */, 78 | ); 79 | buildRules = ( 80 | ); 81 | dependencies = ( 82 | ); 83 | name = "export-proxies"; 84 | productName = "export-proxies"; 85 | productReference = 610DB38D1AB77DFF0005D314 /* export-proxies */; 86 | productType = "com.apple.product-type.tool"; 87 | }; 88 | /* End PBXNativeTarget section */ 89 | 90 | /* Begin PBXProject section */ 91 | 610DB3851AB77DFF0005D314 /* Project object */ = { 92 | isa = PBXProject; 93 | attributes = { 94 | LastSwiftMigration = 0730; 95 | LastSwiftUpdateCheck = 0730; 96 | LastUpgradeCheck = 0730; 97 | ORGANIZATIONNAME = janvogt; 98 | TargetAttributes = { 99 | 610DB38C1AB77DFF0005D314 = { 100 | CreatedOnToolsVersion = 6.2; 101 | LastSwiftMigration = 0830; 102 | }; 103 | }; 104 | }; 105 | buildConfigurationList = 610DB3881AB77DFF0005D314 /* Build configuration list for PBXProject "export-proxies" */; 106 | compatibilityVersion = "Xcode 3.2"; 107 | developmentRegion = English; 108 | hasScannedForEncodings = 0; 109 | knownRegions = ( 110 | en, 111 | ); 112 | mainGroup = 610DB3841AB77DFF0005D314; 113 | productRefGroup = 610DB38E1AB77DFF0005D314 /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | 610DB38C1AB77DFF0005D314 /* export-proxies */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXSourcesBuildPhase section */ 123 | 610DB3891AB77DFF0005D314 /* Sources */ = { 124 | isa = PBXSourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | 610DB3911AB77DFF0005D314 /* main.swift in Sources */, 128 | 610DB3981AB77E690005D314 /* ProxySettings.swift in Sources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXSourcesBuildPhase section */ 133 | 134 | /* Begin XCBuildConfiguration section */ 135 | 610DB3921AB77DFF0005D314 /* Debug */ = { 136 | isa = XCBuildConfiguration; 137 | buildSettings = { 138 | ALWAYS_SEARCH_USER_PATHS = NO; 139 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 140 | CLANG_CXX_LIBRARY = "libc++"; 141 | CLANG_ENABLE_MODULES = YES; 142 | CLANG_ENABLE_OBJC_ARC = YES; 143 | CLANG_WARN_BOOL_CONVERSION = YES; 144 | CLANG_WARN_CONSTANT_CONVERSION = YES; 145 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 150 | CLANG_WARN_UNREACHABLE_CODE = YES; 151 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 152 | COPY_PHASE_STRIP = NO; 153 | ENABLE_STRICT_OBJC_MSGSEND = YES; 154 | ENABLE_TESTABILITY = YES; 155 | GCC_C_LANGUAGE_STANDARD = gnu99; 156 | GCC_DYNAMIC_NO_PIC = NO; 157 | GCC_OPTIMIZATION_LEVEL = 0; 158 | GCC_PREPROCESSOR_DEFINITIONS = ( 159 | "DEBUG=1", 160 | "$(inherited)", 161 | ); 162 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 163 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 164 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 165 | GCC_WARN_UNDECLARED_SELECTOR = YES; 166 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 167 | GCC_WARN_UNUSED_FUNCTION = YES; 168 | GCC_WARN_UNUSED_VARIABLE = YES; 169 | MACOSX_DEPLOYMENT_TARGET = 10.10; 170 | MTL_ENABLE_DEBUG_INFO = YES; 171 | ONLY_ACTIVE_ARCH = YES; 172 | SDKROOT = macosx; 173 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 174 | }; 175 | name = Debug; 176 | }; 177 | 610DB3931AB77DFF0005D314 /* Release */ = { 178 | isa = XCBuildConfiguration; 179 | buildSettings = { 180 | ALWAYS_SEARCH_USER_PATHS = NO; 181 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 182 | CLANG_CXX_LIBRARY = "libc++"; 183 | CLANG_ENABLE_MODULES = YES; 184 | CLANG_ENABLE_OBJC_ARC = YES; 185 | CLANG_WARN_BOOL_CONVERSION = YES; 186 | CLANG_WARN_CONSTANT_CONVERSION = YES; 187 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 188 | CLANG_WARN_EMPTY_BODY = YES; 189 | CLANG_WARN_ENUM_CONVERSION = YES; 190 | CLANG_WARN_INT_CONVERSION = YES; 191 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 192 | CLANG_WARN_UNREACHABLE_CODE = YES; 193 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 194 | COPY_PHASE_STRIP = NO; 195 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 196 | ENABLE_NS_ASSERTIONS = NO; 197 | ENABLE_STRICT_OBJC_MSGSEND = YES; 198 | GCC_C_LANGUAGE_STANDARD = gnu99; 199 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 200 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 201 | GCC_WARN_UNDECLARED_SELECTOR = YES; 202 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 203 | GCC_WARN_UNUSED_FUNCTION = YES; 204 | GCC_WARN_UNUSED_VARIABLE = YES; 205 | MACOSX_DEPLOYMENT_TARGET = 10.10; 206 | MTL_ENABLE_DEBUG_INFO = NO; 207 | SDKROOT = macosx; 208 | }; 209 | name = Release; 210 | }; 211 | 610DB3951AB77DFF0005D314 /* Debug */ = { 212 | isa = XCBuildConfiguration; 213 | buildSettings = { 214 | PRODUCT_NAME = "$(TARGET_NAME)"; 215 | SWIFT_VERSION = 3.0; 216 | }; 217 | name = Debug; 218 | }; 219 | 610DB3961AB77DFF0005D314 /* Release */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | PRODUCT_NAME = "$(TARGET_NAME)"; 223 | SWIFT_VERSION = 3.0; 224 | }; 225 | name = Release; 226 | }; 227 | /* End XCBuildConfiguration section */ 228 | 229 | /* Begin XCConfigurationList section */ 230 | 610DB3881AB77DFF0005D314 /* Build configuration list for PBXProject "export-proxies" */ = { 231 | isa = XCConfigurationList; 232 | buildConfigurations = ( 233 | 610DB3921AB77DFF0005D314 /* Debug */, 234 | 610DB3931AB77DFF0005D314 /* Release */, 235 | ); 236 | defaultConfigurationIsVisible = 0; 237 | defaultConfigurationName = Release; 238 | }; 239 | 610DB3941AB77DFF0005D314 /* Build configuration list for PBXNativeTarget "export-proxies" */ = { 240 | isa = XCConfigurationList; 241 | buildConfigurations = ( 242 | 610DB3951AB77DFF0005D314 /* Debug */, 243 | 610DB3961AB77DFF0005D314 /* Release */, 244 | ); 245 | defaultConfigurationIsVisible = 0; 246 | defaultConfigurationName = Release; 247 | }; 248 | /* End XCConfigurationList section */ 249 | }; 250 | rootObject = 610DB3851AB77DFF0005D314 /* Project object */; 251 | } 252 | --------------------------------------------------------------------------------