blob: 4aa6665d1350cb59647237d629d7695d53c9242c [file] [log] [blame]
Ronald Oussoren51f06332009-09-20 10:31:22 +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 Pitrouc83ea132010-05-09 14:46:46 +00008static int32_t
Ronald Oussoren51f06332009-09-20 10:31:22 +00009cfnum_to_int32(CFNumberRef num)
10{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000011 int32_t result;
Ronald Oussoren51f06332009-09-20 10:31:22 +000012
Antoine Pitrouc83ea132010-05-09 14:46:46 +000013 CFNumberGetValue(num, kCFNumberSInt32Type, &result);
14 return result;
Ronald Oussoren51f06332009-09-20 10:31:22 +000015}
16
17static PyObject*
18cfstring_to_pystring(CFStringRef ref)
19{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000020 const char* s;
Ronald Oussoren51f06332009-09-20 10:31:22 +000021
Antoine Pitrouc83ea132010-05-09 14:46:46 +000022 s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
23 if (s) {
24 return PyString_FromString(s);
Ronald Oussoren51f06332009-09-20 10:31:22 +000025
Antoine Pitrouc83ea132010-05-09 14:46:46 +000026 } else {
27 CFIndex len = CFStringGetLength(ref);
28 Boolean ok;
29 PyObject* result;
30 result = PyString_FromStringAndSize(NULL, len*4);
Ronald Oussoren51f06332009-09-20 10:31:22 +000031
Antoine Pitrouc83ea132010-05-09 14:46:46 +000032 ok = CFStringGetCString(ref,
33 PyString_AS_STRING(result),
34 PyString_GET_SIZE(result),
35 kCFStringEncodingUTF8);
36 if (!ok) {
37 Py_DECREF(result);
38 return NULL;
39 } else {
40 _PyString_Resize(&result,
41 strlen(PyString_AS_STRING(result)));
42 }
43 return result;
44 }
Ronald Oussoren51f06332009-09-20 10:31:22 +000045}
46
47
48static PyObject*
49get_proxy_settings(PyObject* mod __attribute__((__unused__)))
50{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000051 CFDictionaryRef proxyDict = NULL;
52 CFNumberRef aNum = NULL;
53 CFArrayRef anArray = NULL;
54 PyObject* result = NULL;
55 PyObject* v;
56 int r;
Ronald Oussoren51f06332009-09-20 10:31:22 +000057
Antoine Pitrouc83ea132010-05-09 14:46:46 +000058 proxyDict = SCDynamicStoreCopyProxies(NULL);
59 if (!proxyDict) {
60 Py_INCREF(Py_None);
61 return Py_None;
62 }
Ronald Oussoren51f06332009-09-20 10:31:22 +000063
Antoine Pitrouc83ea132010-05-09 14:46:46 +000064 result = PyDict_New();
65 if (result == NULL) goto error;
Ronald Oussoren51f06332009-09-20 10:31:22 +000066
Antoine Pitrouc83ea132010-05-09 14:46:46 +000067 if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) {
68 aNum = CFDictionaryGetValue(proxyDict,
69 kSCPropNetProxiesExcludeSimpleHostnames);
70 if (aNum == NULL) {
Ronald Oussoren3ceab012010-06-22 09:32:22 +000071 v = PyBool_FromLong(0);
Antoine Pitrouc83ea132010-05-09 14:46:46 +000072 } else {
73 v = PyBool_FromLong(cfnum_to_int32(aNum));
74 }
75 } else {
Ronald Oussoren8928e322010-09-28 14:43:59 +000076 v = PyBool_FromLong(0);
Antoine Pitrouc83ea132010-05-09 14:46:46 +000077 }
Ronald Oussoren1c3d1932010-04-20 08:54:48 +000078
Antoine Pitrouc83ea132010-05-09 14:46:46 +000079 if (v == NULL) goto error;
Ronald Oussoren51f06332009-09-20 10:31:22 +000080
Antoine Pitrouc83ea132010-05-09 14:46:46 +000081 r = PyDict_SetItemString(result, "exclude_simple", v);
82 Py_DECREF(v); v = NULL;
83 if (r == -1) goto error;
Ronald Oussoren51f06332009-09-20 10:31:22 +000084
Antoine Pitrouc83ea132010-05-09 14:46:46 +000085 anArray = CFDictionaryGetValue(proxyDict,
86 kSCPropNetProxiesExceptionsList);
87 if (anArray != NULL) {
88 CFIndex len = CFArrayGetCount(anArray);
89 CFIndex i;
90 v = PyTuple_New(len);
91 if (v == NULL) goto error;
Ronald Oussoren51f06332009-09-20 10:31:22 +000092
Antoine Pitrouc83ea132010-05-09 14:46:46 +000093 r = PyDict_SetItemString(result, "exceptions", v);
94 Py_DECREF(v);
95 if (r == -1) goto error;
Ronald Oussoren51f06332009-09-20 10:31:22 +000096
Antoine Pitrouc83ea132010-05-09 14:46:46 +000097 for (i = 0; i < len; i++) {
98 CFStringRef aString = NULL;
Ronald Oussoren51f06332009-09-20 10:31:22 +000099
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000100 aString = CFArrayGetValueAtIndex(anArray, i);
101 if (aString == NULL) {
102 PyTuple_SetItem(v, i, Py_None);
103 Py_INCREF(Py_None);
104 } else {
105 PyObject* t = cfstring_to_pystring(aString);
106 if (!t) {
107 PyTuple_SetItem(v, i, Py_None);
108 Py_INCREF(Py_None);
109 } else {
110 PyTuple_SetItem(v, i, t);
111 }
112 }
113 }
114 }
Ronald Oussoren51f06332009-09-20 10:31:22 +0000115
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000116 CFRelease(proxyDict);
117 return result;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000118
119error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000120 if (proxyDict) CFRelease(proxyDict);
121 Py_XDECREF(result);
122 return NULL;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000123}
124
125static int
126set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000127 CFStringRef enabledKey,
128 CFStringRef hostKey, CFStringRef portKey)
Ronald Oussoren51f06332009-09-20 10:31:22 +0000129{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000130 CFNumberRef aNum;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000131
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000132 aNum = CFDictionaryGetValue(proxyDict, enabledKey);
133 if (aNum && cfnum_to_int32(aNum)) {
134 CFStringRef hostString;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000135
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000136 hostString = CFDictionaryGetValue(proxyDict, hostKey);
137 aNum = CFDictionaryGetValue(proxyDict, portKey);
Ronald Oussoren51f06332009-09-20 10:31:22 +0000138
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000139 if (hostString) {
140 int r;
141 PyObject* h = cfstring_to_pystring(hostString);
142 PyObject* v;
143 if (h) {
144 if (aNum) {
145 int32_t port = cfnum_to_int32(aNum);
146 v = PyString_FromFormat("http://%s:%ld",
147 PyString_AS_STRING(h),
148 (long)port);
149 } else {
150 v = PyString_FromFormat("http://%s",
151 PyString_AS_STRING(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 Oussoren51f06332009-09-20 10:31:22 +0000161
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000162 }
163 return 0;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000164}
165
166
167
168static PyObject*
169get_proxies(PyObject* mod __attribute__((__unused__)))
170{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000171 PyObject* result = NULL;
172 int r;
173 CFDictionaryRef proxyDict = NULL;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000174
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000175 proxyDict = SCDynamicStoreCopyProxies(NULL);
176 if (proxyDict == NULL) {
177 return PyDict_New();
178 }
Ronald Oussoren51f06332009-09-20 10:31:22 +0000179
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000180 result = PyDict_New();
181 if (result == NULL) goto error;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000182
Antoine Pitrouc83ea132010-05-09 14:46:46 +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 Oussoren51f06332009-09-20 10:31:22 +0000203
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000204 CFRelease(proxyDict);
205 return result;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000206error:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000207 if (proxyDict) CFRelease(proxyDict);
208 Py_XDECREF(result);
209 return NULL;
Ronald Oussoren51f06332009-09-20 10:31:22 +0000210}
211
212static PyMethodDef mod_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +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 Oussoren51f06332009-09-20 10:31:22 +0000226};
227
228void init_scproxy(void)
229{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000230 (void)Py_InitModule4("_scproxy", mod_methods, NULL, NULL, PYTHON_API_VERSION);
Ronald Oussoren51f06332009-09-20 10:31:22 +0000231}