blob: 1ce4b776f3e26908353a9a1f80cb501c3cd28b74 [file] [log] [blame]
Ronald Oussoren84151202010-04-18 20:46:11 +00001/*
2 * Helper method for urllib to fetch the proxy configuration settings
3 * using the SystemConfiguration framework.
4 */
5#include <Python.h>
6#include <SystemConfiguration/SystemConfiguration.h>
7
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00008static int32_t
Ronald Oussoren84151202010-04-18 20:46:11 +00009cfnum_to_int32(CFNumberRef num)
10{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000011 int32_t result;
Ronald Oussoren84151202010-04-18 20:46:11 +000012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013 CFNumberGetValue(num, kCFNumberSInt32Type, &result);
14 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +000015}
16
17static PyObject*
18cfstring_to_pystring(CFStringRef ref)
19{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000020 const char* s;
Ronald Oussoren84151202010-04-18 20:46:11 +000021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
23 if (s) {
24 return PyUnicode_DecodeUTF8(
25 s, strlen(s), NULL);
Ronald Oussoren84151202010-04-18 20:46:11 +000026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000027 } else {
28 CFIndex len = CFStringGetLength(ref);
29 Boolean ok;
30 PyObject* result;
31 char* buf;
Ronald Oussoren84151202010-04-18 20:46:11 +000032
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000033 buf = PyMem_Malloc(len*4);
34 if (buf == NULL) {
35 PyErr_NoMemory();
36 return NULL;
37 }
38
39 ok = CFStringGetCString(ref,
40 buf, len * 4,
41 kCFStringEncodingUTF8);
42 if (!ok) {
43 PyMem_Free(buf);
44 return NULL;
45 } else {
46 result = PyUnicode_DecodeUTF8(
47 buf, strlen(buf), NULL);
48 PyMem_Free(buf);
49 }
50 return result;
51 }
Ronald Oussoren84151202010-04-18 20:46:11 +000052}
53
54
55static PyObject*
56get_proxy_settings(PyObject* mod __attribute__((__unused__)))
57{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000058 CFDictionaryRef proxyDict = NULL;
59 CFNumberRef aNum = NULL;
60 CFArrayRef anArray = NULL;
61 PyObject* result = NULL;
62 PyObject* v;
63 int r;
Ronald Oussoren84151202010-04-18 20:46:11 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 proxyDict = SCDynamicStoreCopyProxies(NULL);
66 if (!proxyDict) {
67 Py_INCREF(Py_None);
68 return Py_None;
69 }
Ronald Oussoren84151202010-04-18 20:46:11 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 result = PyDict_New();
72 if (result == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000073
Brett Cannon56be5f52016-09-07 14:07:16 -070074 aNum = CFDictionaryGetValue(proxyDict,
75 kSCPropNetProxiesExcludeSimpleHostnames);
76 if (aNum == NULL) {
Ronald Oussoren01c42892010-09-28 14:38:31 +000077 v = PyBool_FromLong(0);
Brett Cannon56be5f52016-09-07 14:07:16 -070078 } else {
79 v = PyBool_FromLong(cfnum_to_int32(aNum));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 }
Ronald Oussoren84151202010-04-18 20:46:11 +000081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 if (v == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 r = PyDict_SetItemString(result, "exclude_simple", v);
85 Py_DECREF(v); v = NULL;
86 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 anArray = CFDictionaryGetValue(proxyDict,
89 kSCPropNetProxiesExceptionsList);
90 if (anArray != NULL) {
91 CFIndex len = CFArrayGetCount(anArray);
92 CFIndex i;
93 v = PyTuple_New(len);
94 if (v == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 r = PyDict_SetItemString(result, "exceptions", v);
97 Py_DECREF(v);
98 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 for (i = 0; i < len; i++) {
101 CFStringRef aString = NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 aString = CFArrayGetValueAtIndex(anArray, i);
104 if (aString == NULL) {
105 PyTuple_SetItem(v, i, Py_None);
106 Py_INCREF(Py_None);
107 } else {
108 PyObject* t = cfstring_to_pystring(aString);
109 if (!t) {
110 PyTuple_SetItem(v, i, Py_None);
111 Py_INCREF(Py_None);
112 } else {
113 PyTuple_SetItem(v, i, t);
114 }
115 }
116 }
117 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119 CFRelease(proxyDict);
120 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +0000121
122error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 if (proxyDict) CFRelease(proxyDict);
124 Py_XDECREF(result);
125 return NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000126}
127
128static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200129set_proxy(PyObject* proxies, const char* proto, CFDictionaryRef proxyDict,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000130 CFStringRef enabledKey,
131 CFStringRef hostKey, CFStringRef portKey)
Ronald Oussoren84151202010-04-18 20:46:11 +0000132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 CFNumberRef aNum;
Ronald Oussoren84151202010-04-18 20:46:11 +0000134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 aNum = CFDictionaryGetValue(proxyDict, enabledKey);
136 if (aNum && cfnum_to_int32(aNum)) {
137 CFStringRef hostString;
Ronald Oussoren84151202010-04-18 20:46:11 +0000138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 hostString = CFDictionaryGetValue(proxyDict, hostKey);
140 aNum = CFDictionaryGetValue(proxyDict, portKey);
Ronald Oussoren84151202010-04-18 20:46:11 +0000141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000142 if (hostString) {
143 int r;
144 PyObject* h = cfstring_to_pystring(hostString);
145 PyObject* v;
146 if (h) {
147 if (aNum) {
148 int32_t port = cfnum_to_int32(aNum);
149 v = PyUnicode_FromFormat("http://%U:%ld",
150 h, (long)port);
151 } else {
152 v = PyUnicode_FromFormat("http://%U", h);
153 }
154 Py_DECREF(h);
155 if (!v) return -1;
156 r = PyDict_SetItemString(proxies, proto,
157 v);
158 Py_DECREF(v);
159 return r;
160 }
161 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 }
164 return 0;
Ronald Oussoren84151202010-04-18 20:46:11 +0000165}
166
167
168
169static PyObject*
170get_proxies(PyObject* mod __attribute__((__unused__)))
171{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 PyObject* result = NULL;
173 int r;
174 CFDictionaryRef proxyDict = NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000175
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 proxyDict = SCDynamicStoreCopyProxies(NULL);
177 if (proxyDict == NULL) {
178 return PyDict_New();
179 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 result = PyDict_New();
182 if (result == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 r = set_proxy(result, "http", proxyDict,
185 kSCPropNetProxiesHTTPEnable,
186 kSCPropNetProxiesHTTPProxy,
187 kSCPropNetProxiesHTTPPort);
188 if (r == -1) goto error;
189 r = set_proxy(result, "https", proxyDict,
190 kSCPropNetProxiesHTTPSEnable,
191 kSCPropNetProxiesHTTPSProxy,
192 kSCPropNetProxiesHTTPSPort);
193 if (r == -1) goto error;
194 r = set_proxy(result, "ftp", proxyDict,
195 kSCPropNetProxiesFTPEnable,
196 kSCPropNetProxiesFTPProxy,
197 kSCPropNetProxiesFTPPort);
198 if (r == -1) goto error;
199 r = set_proxy(result, "gopher", proxyDict,
200 kSCPropNetProxiesGopherEnable,
201 kSCPropNetProxiesGopherProxy,
202 kSCPropNetProxiesGopherPort);
203 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 CFRelease(proxyDict);
206 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +0000207error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 if (proxyDict) CFRelease(proxyDict);
209 Py_XDECREF(result);
210 return NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000211}
212
213static PyMethodDef mod_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 {
215 "_get_proxy_settings",
216 (PyCFunction)get_proxy_settings,
217 METH_NOARGS,
218 NULL,
219 },
220 {
221 "_get_proxies",
222 (PyCFunction)get_proxies,
223 METH_NOARGS,
224 NULL,
225 },
226 { 0, 0, 0, 0 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000227};
228
229
230
231static struct PyModuleDef mod_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 PyModuleDef_HEAD_INIT,
233 "_scproxy",
234 NULL,
235 -1,
236 mod_methods,
237 NULL,
238 NULL,
239 NULL,
240 NULL
Ronald Oussoren84151202010-04-18 20:46:11 +0000241};
242
243
244#ifdef __cplusplus
245extern "C" {
246#endif
247
Victor Stinnerf024d262015-03-17 17:48:27 +0100248PyMODINIT_FUNC
Ronald Oussoren84151202010-04-18 20:46:11 +0000249PyInit__scproxy(void)
250{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 return PyModule_Create(&mod_module);
Ronald Oussoren84151202010-04-18 20:46:11 +0000252}
253
254#ifdef __cplusplus
255}
256#endif
257