├── .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 |
--------------------------------------------------------------------------------