1 | /*
|
---|
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 |
|
---|
8 | static int32_t
|
---|
9 | cfnum_to_int32(CFNumberRef num)
|
---|
10 | {
|
---|
11 | int32_t result;
|
---|
12 |
|
---|
13 | CFNumberGetValue(num, kCFNumberSInt32Type, &result);
|
---|
14 | return result;
|
---|
15 | }
|
---|
16 |
|
---|
17 | static PyObject*
|
---|
18 | cfstring_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 |
|
---|
48 | static PyObject*
|
---|
49 | get_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 | if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) {
|
---|
68 | aNum = CFDictionaryGetValue(proxyDict,
|
---|
69 | kSCPropNetProxiesExcludeSimpleHostnames);
|
---|
70 | if (aNum == NULL) {
|
---|
71 | v = PyBool_FromLong(0);
|
---|
72 | } else {
|
---|
73 | v = PyBool_FromLong(cfnum_to_int32(aNum));
|
---|
74 | }
|
---|
75 | } else {
|
---|
76 | v = PyBool_FromLong(0);
|
---|
77 | }
|
---|
78 |
|
---|
79 | if (v == NULL) goto error;
|
---|
80 |
|
---|
81 | r = PyDict_SetItemString(result, "exclude_simple", v);
|
---|
82 | Py_DECREF(v); v = NULL;
|
---|
83 | if (r == -1) goto error;
|
---|
84 |
|
---|
85 | 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;
|
---|
92 |
|
---|
93 | r = PyDict_SetItemString(result, "exceptions", v);
|
---|
94 | Py_DECREF(v);
|
---|
95 | if (r == -1) goto error;
|
---|
96 |
|
---|
97 | for (i = 0; i < len; i++) {
|
---|
98 | CFStringRef aString = NULL;
|
---|
99 |
|
---|
100 | 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 | }
|
---|
115 |
|
---|
116 | CFRelease(proxyDict);
|
---|
117 | return result;
|
---|
118 |
|
---|
119 | error:
|
---|
120 | if (proxyDict) CFRelease(proxyDict);
|
---|
121 | Py_XDECREF(result);
|
---|
122 | return NULL;
|
---|
123 | }
|
---|
124 |
|
---|
125 | static int
|
---|
126 | set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
|
---|
127 | CFStringRef enabledKey,
|
---|
128 | CFStringRef hostKey, CFStringRef portKey)
|
---|
129 | {
|
---|
130 | CFNumberRef aNum;
|
---|
131 |
|
---|
132 | aNum = CFDictionaryGetValue(proxyDict, enabledKey);
|
---|
133 | if (aNum && cfnum_to_int32(aNum)) {
|
---|
134 | CFStringRef hostString;
|
---|
135 |
|
---|
136 | hostString = CFDictionaryGetValue(proxyDict, hostKey);
|
---|
137 | aNum = CFDictionaryGetValue(proxyDict, portKey);
|
---|
138 |
|
---|
139 | 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 | }
|
---|
161 |
|
---|
162 | }
|
---|
163 | return 0;
|
---|
164 | }
|
---|
165 |
|
---|
166 |
|
---|
167 |
|
---|
168 | static PyObject*
|
---|
169 | get_proxies(PyObject* mod __attribute__((__unused__)))
|
---|
170 | {
|
---|
171 | PyObject* result = NULL;
|
---|
172 | int r;
|
---|
173 | CFDictionaryRef proxyDict = NULL;
|
---|
174 |
|
---|
175 | proxyDict = SCDynamicStoreCopyProxies(NULL);
|
---|
176 | if (proxyDict == NULL) {
|
---|
177 | return PyDict_New();
|
---|
178 | }
|
---|
179 |
|
---|
180 | result = PyDict_New();
|
---|
181 | if (result == NULL) goto error;
|
---|
182 |
|
---|
183 | 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;
|
---|
203 |
|
---|
204 | CFRelease(proxyDict);
|
---|
205 | return result;
|
---|
206 | error:
|
---|
207 | if (proxyDict) CFRelease(proxyDict);
|
---|
208 | Py_XDECREF(result);
|
---|
209 | return NULL;
|
---|
210 | }
|
---|
211 |
|
---|
212 | static PyMethodDef mod_methods[] = {
|
---|
213 | {
|
---|
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 }
|
---|
226 | };
|
---|
227 |
|
---|
228 | void init_scproxy(void)
|
---|
229 | {
|
---|
230 | (void)Py_InitModule4("_scproxy", mod_methods, NULL, NULL, PYTHON_API_VERSION);
|
---|
231 | }
|
---|