blob: 0e3b02879b833dc83645ad8a786f755e212e9ae8 [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) {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +020067 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 }
Ronald Oussoren84151202010-04-18 20:46:11 +000069
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 result = PyDict_New();
71 if (result == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000072
Brett Cannon56be5f52016-09-07 14:07:16 -070073 aNum = CFDictionaryGetValue(proxyDict,
74 kSCPropNetProxiesExcludeSimpleHostnames);
75 if (aNum == NULL) {
Ronald Oussoren01c42892010-09-28 14:38:31 +000076 v = PyBool_FromLong(0);
Brett Cannon56be5f52016-09-07 14:07:16 -070077 } else {
78 v = PyBool_FromLong(cfnum_to_int32(aNum));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 }
Ronald Oussoren84151202010-04-18 20:46:11 +000080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 if (v == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000082
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 r = PyDict_SetItemString(result, "exclude_simple", v);
84 Py_DECREF(v); v = NULL;
85 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000086
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 anArray = CFDictionaryGetValue(proxyDict,
88 kSCPropNetProxiesExceptionsList);
89 if (anArray != NULL) {
90 CFIndex len = CFArrayGetCount(anArray);
91 CFIndex i;
92 v = PyTuple_New(len);
93 if (v == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 r = PyDict_SetItemString(result, "exceptions", v);
96 Py_DECREF(v);
97 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 for (i = 0; i < len; i++) {
100 CFStringRef aString = NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 aString = CFArrayGetValueAtIndex(anArray, i);
103 if (aString == NULL) {
104 PyTuple_SetItem(v, i, Py_None);
105 Py_INCREF(Py_None);
106 } else {
107 PyObject* t = cfstring_to_pystring(aString);
108 if (!t) {
109 PyTuple_SetItem(v, i, Py_None);
110 Py_INCREF(Py_None);
111 } else {
112 PyTuple_SetItem(v, i, t);
113 }
114 }
115 }
116 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 CFRelease(proxyDict);
119 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +0000120
121error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 if (proxyDict) CFRelease(proxyDict);
123 Py_XDECREF(result);
124 return NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000125}
126
127static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200128set_proxy(PyObject* proxies, const char* proto, CFDictionaryRef proxyDict,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 CFStringRef enabledKey,
130 CFStringRef hostKey, CFStringRef portKey)
Ronald Oussoren84151202010-04-18 20:46:11 +0000131{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 CFNumberRef aNum;
Ronald Oussoren84151202010-04-18 20:46:11 +0000133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 aNum = CFDictionaryGetValue(proxyDict, enabledKey);
135 if (aNum && cfnum_to_int32(aNum)) {
136 CFStringRef hostString;
Ronald Oussoren84151202010-04-18 20:46:11 +0000137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 hostString = CFDictionaryGetValue(proxyDict, hostKey);
139 aNum = CFDictionaryGetValue(proxyDict, portKey);
Ronald Oussoren84151202010-04-18 20:46:11 +0000140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 if (hostString) {
142 int r;
143 PyObject* h = cfstring_to_pystring(hostString);
144 PyObject* v;
145 if (h) {
146 if (aNum) {
147 int32_t port = cfnum_to_int32(aNum);
148 v = PyUnicode_FromFormat("http://%U:%ld",
149 h, (long)port);
150 } else {
151 v = PyUnicode_FromFormat("http://%U", h);
152 }
153 Py_DECREF(h);
154 if (!v) return -1;
155 r = PyDict_SetItemString(proxies, proto,
156 v);
157 Py_DECREF(v);
158 return r;
159 }
160 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 }
163 return 0;
Ronald Oussoren84151202010-04-18 20:46:11 +0000164}
165
166
167
168static PyObject*
169get_proxies(PyObject* mod __attribute__((__unused__)))
170{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000171 PyObject* result = NULL;
172 int r;
173 CFDictionaryRef proxyDict = NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000175 proxyDict = SCDynamicStoreCopyProxies(NULL);
176 if (proxyDict == NULL) {
177 return PyDict_New();
178 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 result = PyDict_New();
181 if (result == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 r = set_proxy(result, "http", proxyDict,
184 kSCPropNetProxiesHTTPEnable,
185 kSCPropNetProxiesHTTPProxy,
186 kSCPropNetProxiesHTTPPort);
187 if (r == -1) goto error;
188 r = set_proxy(result, "https", proxyDict,
189 kSCPropNetProxiesHTTPSEnable,
190 kSCPropNetProxiesHTTPSProxy,
191 kSCPropNetProxiesHTTPSPort);
192 if (r == -1) goto error;
193 r = set_proxy(result, "ftp", proxyDict,
194 kSCPropNetProxiesFTPEnable,
195 kSCPropNetProxiesFTPProxy,
196 kSCPropNetProxiesFTPPort);
197 if (r == -1) goto error;
198 r = set_proxy(result, "gopher", proxyDict,
199 kSCPropNetProxiesGopherEnable,
200 kSCPropNetProxiesGopherProxy,
201 kSCPropNetProxiesGopherPort);
202 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 CFRelease(proxyDict);
205 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +0000206error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 if (proxyDict) CFRelease(proxyDict);
208 Py_XDECREF(result);
209 return NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000210}
211
212static PyMethodDef mod_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 {
214 "_get_proxy_settings",
215 (PyCFunction)get_proxy_settings,
216 METH_NOARGS,
217 NULL,
218 },
219 {
220 "_get_proxies",
221 (PyCFunction)get_proxies,
222 METH_NOARGS,
223 NULL,
224 },
225 { 0, 0, 0, 0 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000226};
227
228
229
230static struct PyModuleDef mod_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000231 PyModuleDef_HEAD_INIT,
232 "_scproxy",
233 NULL,
234 -1,
235 mod_methods,
236 NULL,
237 NULL,
238 NULL,
239 NULL
Ronald Oussoren84151202010-04-18 20:46:11 +0000240};
241
242
243#ifdef __cplusplus
244extern "C" {
245#endif
246
Victor Stinnerf024d262015-03-17 17:48:27 +0100247PyMODINIT_FUNC
Ronald Oussoren84151202010-04-18 20:46:11 +0000248PyInit__scproxy(void)
249{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 return PyModule_Create(&mod_module);
Ronald Oussoren84151202010-04-18 20:46:11 +0000251}
252
253#ifdef __cplusplus
254}
255#endif
256