blob: 3b2a38ea32faae53590f4c13adbd61f0daaa6efb [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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) {
75 aNum = CFDictionaryGetValue(proxyDict,
76 kSCPropNetProxiesExcludeSimpleHostnames);
77 if (aNum == NULL) {
Ronald Oussoren7adeed32010-06-27 12:51:31 +000078 v = PyBool_FromLong(0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 } else {
80 v = PyBool_FromLong(cfnum_to_int32(aNum));
81 }
82 } else {
Ronald Oussoren01c42892010-09-28 14:38:31 +000083 v = PyBool_FromLong(0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 }
Ronald Oussoren84151202010-04-18 20:46:11 +000085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 if (v == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 r = PyDict_SetItemString(result, "exclude_simple", v);
89 Py_DECREF(v); v = NULL;
90 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 anArray = CFDictionaryGetValue(proxyDict,
93 kSCPropNetProxiesExceptionsList);
94 if (anArray != NULL) {
95 CFIndex len = CFArrayGetCount(anArray);
96 CFIndex i;
97 v = PyTuple_New(len);
98 if (v == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +000099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 r = PyDict_SetItemString(result, "exceptions", v);
101 Py_DECREF(v);
102 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 for (i = 0; i < len; i++) {
105 CFStringRef aString = NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 aString = CFArrayGetValueAtIndex(anArray, i);
108 if (aString == NULL) {
109 PyTuple_SetItem(v, i, Py_None);
110 Py_INCREF(Py_None);
111 } else {
112 PyObject* t = cfstring_to_pystring(aString);
113 if (!t) {
114 PyTuple_SetItem(v, i, Py_None);
115 Py_INCREF(Py_None);
116 } else {
117 PyTuple_SetItem(v, i, t);
118 }
119 }
120 }
121 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 CFRelease(proxyDict);
124 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +0000125
126error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 if (proxyDict) CFRelease(proxyDict);
128 Py_XDECREF(result);
129 return NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000130}
131
132static int
133set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 CFStringRef enabledKey,
135 CFStringRef hostKey, CFStringRef portKey)
Ronald Oussoren84151202010-04-18 20:46:11 +0000136{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 CFNumberRef aNum;
Ronald Oussoren84151202010-04-18 20:46:11 +0000138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 aNum = CFDictionaryGetValue(proxyDict, enabledKey);
140 if (aNum && cfnum_to_int32(aNum)) {
141 CFStringRef hostString;
Ronald Oussoren84151202010-04-18 20:46:11 +0000142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 hostString = CFDictionaryGetValue(proxyDict, hostKey);
144 aNum = CFDictionaryGetValue(proxyDict, portKey);
Ronald Oussoren84151202010-04-18 20:46:11 +0000145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000146 if (hostString) {
147 int r;
148 PyObject* h = cfstring_to_pystring(hostString);
149 PyObject* v;
150 if (h) {
151 if (aNum) {
152 int32_t port = cfnum_to_int32(aNum);
153 v = PyUnicode_FromFormat("http://%U:%ld",
154 h, (long)port);
155 } else {
156 v = PyUnicode_FromFormat("http://%U", h);
157 }
158 Py_DECREF(h);
159 if (!v) return -1;
160 r = PyDict_SetItemString(proxies, proto,
161 v);
162 Py_DECREF(v);
163 return r;
164 }
165 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000166
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 }
168 return 0;
Ronald Oussoren84151202010-04-18 20:46:11 +0000169}
170
171
172
173static PyObject*
174get_proxies(PyObject* mod __attribute__((__unused__)))
175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 PyObject* result = NULL;
177 int r;
178 CFDictionaryRef proxyDict = NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 proxyDict = SCDynamicStoreCopyProxies(NULL);
181 if (proxyDict == NULL) {
182 return PyDict_New();
183 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 result = PyDict_New();
186 if (result == NULL) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 r = set_proxy(result, "http", proxyDict,
189 kSCPropNetProxiesHTTPEnable,
190 kSCPropNetProxiesHTTPProxy,
191 kSCPropNetProxiesHTTPPort);
192 if (r == -1) goto error;
193 r = set_proxy(result, "https", proxyDict,
194 kSCPropNetProxiesHTTPSEnable,
195 kSCPropNetProxiesHTTPSProxy,
196 kSCPropNetProxiesHTTPSPort);
197 if (r == -1) goto error;
198 r = set_proxy(result, "ftp", proxyDict,
199 kSCPropNetProxiesFTPEnable,
200 kSCPropNetProxiesFTPProxy,
201 kSCPropNetProxiesFTPPort);
202 if (r == -1) goto error;
203 r = set_proxy(result, "gopher", proxyDict,
204 kSCPropNetProxiesGopherEnable,
205 kSCPropNetProxiesGopherProxy,
206 kSCPropNetProxiesGopherPort);
207 if (r == -1) goto error;
Ronald Oussoren84151202010-04-18 20:46:11 +0000208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 CFRelease(proxyDict);
210 return result;
Ronald Oussoren84151202010-04-18 20:46:11 +0000211error:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 if (proxyDict) CFRelease(proxyDict);
213 Py_XDECREF(result);
214 return NULL;
Ronald Oussoren84151202010-04-18 20:46:11 +0000215}
216
217static PyMethodDef mod_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000218 {
219 "_get_proxy_settings",
220 (PyCFunction)get_proxy_settings,
221 METH_NOARGS,
222 NULL,
223 },
224 {
225 "_get_proxies",
226 (PyCFunction)get_proxies,
227 METH_NOARGS,
228 NULL,
229 },
230 { 0, 0, 0, 0 }
Ronald Oussoren84151202010-04-18 20:46:11 +0000231};
232
233
234
235static struct PyModuleDef mod_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 PyModuleDef_HEAD_INIT,
237 "_scproxy",
238 NULL,
239 -1,
240 mod_methods,
241 NULL,
242 NULL,
243 NULL,
244 NULL
Ronald Oussoren84151202010-04-18 20:46:11 +0000245};
246
247
248#ifdef __cplusplus
249extern "C" {
250#endif
251
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000252PyObject*
Ronald Oussoren84151202010-04-18 20:46:11 +0000253PyInit__scproxy(void)
254{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 return PyModule_Create(&mod_module);
Ronald Oussoren84151202010-04-18 20:46:11 +0000256}
257
258#ifdef __cplusplus
259}
260#endif
261