blob: 003f6a483f09a677629da51a2ee4b5ab3d49f87b [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
8static int32_t
9cfnum_to_int32(CFNumberRef num)
10{
11 int32_t result;
12
13 CFNumberGetValue(num, kCFNumberSInt32Type, &result);
14 return result;
15}
16
17static PyObject*
18cfstring_to_pystring(CFStringRef ref)
19{
20 const char* s;
21
22 s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
23 if (s) {
24 return PyString_FromString(s);
25
26 } else {
27 CFIndex len = CFStringGetLength(ref);
28 Boolean ok;
29 PyObject* result;
30 result = PyString_FromStringAndSize(NULL, len*4);
31
32 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 }
45}
46
47
48static PyObject*
49get_proxy_settings(PyObject* mod __attribute__((__unused__)))
50{
51 CFDictionaryRef proxyDict = NULL;
52 CFNumberRef aNum = NULL;
53 CFArrayRef anArray = NULL;
54 PyObject* result = NULL;
55 PyObject* v;
56 int r;
57
58 proxyDict = SCDynamicStoreCopyProxies(NULL);
59 if (!proxyDict) {
60 Py_INCREF(Py_None);
61 return Py_None;
62 }
63
64 result = PyDict_New();
65 if (result == NULL) goto error;
66
67 aNum = CFDictionaryGetValue(proxyDict,
68 kSCPropNetProxiesExcludeSimpleHostnames);
69 if (aNum == NULL) {
70 v = PyBool_FromLong(0);
71 } else {
72 v = PyBool_FromLong(cfnum_to_int32(aNum));
73 }
74 if (v == NULL) goto error;
75
76 r = PyDict_SetItemString(result, "exclude_simple", v);
77 Py_DECREF(v); v = NULL;
78 if (r == -1) goto error;
79
80 anArray = CFDictionaryGetValue(proxyDict,
81 kSCPropNetProxiesExceptionsList);
82 if (anArray != NULL) {
83 CFIndex len = CFArrayGetCount(anArray);
84 CFIndex i;
85 v = PyTuple_New(len);
86 if (v == NULL) goto error;
87
88 r = PyDict_SetItemString(result, "exceptions", v);
89 Py_DECREF(v);
90 if (r == -1) goto error;
91
92 for (i = 0; i < len; i++) {
93 CFStringRef aString = NULL;
94
95 aString = CFArrayGetValueAtIndex(anArray, i);
96 if (aString == NULL) {
97 PyTuple_SetItem(v, i, Py_None);
98 Py_INCREF(Py_None);
99 } else {
100 PyObject* t = cfstring_to_pystring(aString);
101 if (!t) {
102 PyTuple_SetItem(v, i, Py_None);
103 Py_INCREF(Py_None);
104 } else {
105 PyTuple_SetItem(v, i, t);
106 }
107 }
108 }
109 }
110
111 CFRelease(proxyDict);
112 return result;
113
114error:
115 if (proxyDict) CFRelease(proxyDict);
116 Py_XDECREF(result);
117 return NULL;
118}
119
120static int
121set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
122 CFStringRef enabledKey,
123 CFStringRef hostKey, CFStringRef portKey)
124{
125 CFNumberRef aNum;
126
127 aNum = CFDictionaryGetValue(proxyDict, enabledKey);
128 if (aNum && cfnum_to_int32(aNum)) {
129 CFStringRef hostString;
130
131 hostString = CFDictionaryGetValue(proxyDict, hostKey);
132 aNum = CFDictionaryGetValue(proxyDict, portKey);
133
134 if (hostString) {
135 int r;
136 PyObject* h = cfstring_to_pystring(hostString);
137 PyObject* v;
138 if (h) {
139 if (aNum) {
140 int32_t port = cfnum_to_int32(aNum);
141 v = PyString_FromFormat("http://%s:%ld",
142 PyString_AS_STRING(h),
143 (long)port);
144 } else {
145 v = PyString_FromFormat("http://%s",
146 PyString_AS_STRING(h));
147 }
148 Py_DECREF(h);
149 if (!v) return -1;
150 r = PyDict_SetItemString(proxies, proto,
151 v);
152 Py_DECREF(v);
153 return r;
154 }
155 }
156
157 }
158 return 0;
159}
160
161
162
163static PyObject*
164get_proxies(PyObject* mod __attribute__((__unused__)))
165{
166 PyObject* result = NULL;
167 int r;
168 CFDictionaryRef proxyDict = NULL;
169
170 proxyDict = SCDynamicStoreCopyProxies(NULL);
171 if (proxyDict == NULL) {
172 return PyDict_New();
173 }
174
175 result = PyDict_New();
176 if (result == NULL) goto error;
177
178 r = set_proxy(result, "http", proxyDict,
179 kSCPropNetProxiesHTTPEnable,
180 kSCPropNetProxiesHTTPProxy,
181 kSCPropNetProxiesHTTPPort);
182 if (r == -1) goto error;
183 r = set_proxy(result, "https", proxyDict,
184 kSCPropNetProxiesHTTPSEnable,
185 kSCPropNetProxiesHTTPSProxy,
186 kSCPropNetProxiesHTTPSPort);
187 if (r == -1) goto error;
188 r = set_proxy(result, "ftp", proxyDict,
189 kSCPropNetProxiesFTPEnable,
190 kSCPropNetProxiesFTPProxy,
191 kSCPropNetProxiesFTPPort);
192 if (r == -1) goto error;
193 r = set_proxy(result, "gopher", proxyDict,
194 kSCPropNetProxiesGopherEnable,
195 kSCPropNetProxiesGopherProxy,
196 kSCPropNetProxiesGopherPort);
197 if (r == -1) goto error;
198
199 CFRelease(proxyDict);
200 return result;
201error:
202 if (proxyDict) CFRelease(proxyDict);
203 Py_XDECREF(result);
204 return NULL;
205}
206
207static PyMethodDef mod_methods[] = {
208 {
209 "_get_proxy_settings",
210 (PyCFunction)get_proxy_settings,
211 METH_NOARGS,
212 NULL,
213 },
214 {
215 "_get_proxies",
216 (PyCFunction)get_proxies,
217 METH_NOARGS,
218 NULL,
219 },
220 { 0, 0, 0, 0 }
221};
222
223void init_scproxy(void)
224{
225 (void)Py_InitModule4("_scproxy", mod_methods, NULL, NULL, PYTHON_API_VERSION);
226}