only use -fno-strict-aliasing when needed by compiler
[python/dscho.git] / Modules / _scproxy.c
blob30afa6a5e129122193d4333813e8b760571f64b0
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>
8 static int32_t
9 cfnum_to_int32(CFNumberRef num)
11 int32_t result;
13 CFNumberGetValue(num, kCFNumberSInt32Type, &result);
14 return result;
17 static PyObject*
18 cfstring_to_pystring(CFStringRef ref)
20 const char* s;
22 s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
23 if (s) {
24 return PyUnicode_DecodeUTF8(
25 s, strlen(s), NULL);
27 } else {
28 CFIndex len = CFStringGetLength(ref);
29 Boolean ok;
30 PyObject* result;
31 char* buf;
33 buf = PyMem_Malloc(len*4);
34 if (buf == NULL) {
35 PyErr_NoMemory();
36 return NULL;
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);
50 return result;
55 static PyObject*
56 get_proxy_settings(PyObject* mod __attribute__((__unused__)))
58 CFDictionaryRef proxyDict = NULL;
59 CFNumberRef aNum = NULL;
60 CFArrayRef anArray = NULL;
61 PyObject* result = NULL;
62 PyObject* v;
63 int r;
65 proxyDict = SCDynamicStoreCopyProxies(NULL);
66 if (!proxyDict) {
67 Py_INCREF(Py_None);
68 return Py_None;
71 result = PyDict_New();
72 if (result == NULL) goto error;
74 if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) {
75 aNum = CFDictionaryGetValue(proxyDict,
76 kSCPropNetProxiesExcludeSimpleHostnames);
77 if (aNum == NULL) {
78 v = PyBool_FromLong(1);
79 } else {
80 v = PyBool_FromLong(cfnum_to_int32(aNum));
82 } else {
83 v = PyBool_FromLong(1);
86 if (v == NULL) goto error;
88 r = PyDict_SetItemString(result, "exclude_simple", v);
89 Py_DECREF(v); v = NULL;
90 if (r == -1) goto error;
92 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;
100 r = PyDict_SetItemString(result, "exceptions", v);
101 Py_DECREF(v);
102 if (r == -1) goto error;
104 for (i = 0; i < len; i++) {
105 CFStringRef aString = NULL;
107 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);
123 CFRelease(proxyDict);
124 return result;
126 error:
127 if (proxyDict) CFRelease(proxyDict);
128 Py_XDECREF(result);
129 return NULL;
132 static int
133 set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
134 CFStringRef enabledKey,
135 CFStringRef hostKey, CFStringRef portKey)
137 CFNumberRef aNum;
139 aNum = CFDictionaryGetValue(proxyDict, enabledKey);
140 if (aNum && cfnum_to_int32(aNum)) {
141 CFStringRef hostString;
143 hostString = CFDictionaryGetValue(proxyDict, hostKey);
144 aNum = CFDictionaryGetValue(proxyDict, portKey);
146 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);
158 Py_DECREF(h);
159 if (!v) return -1;
160 r = PyDict_SetItemString(proxies, proto,
162 Py_DECREF(v);
163 return r;
168 return 0;
173 static PyObject*
174 get_proxies(PyObject* mod __attribute__((__unused__)))
176 PyObject* result = NULL;
177 int r;
178 CFDictionaryRef proxyDict = NULL;
180 proxyDict = SCDynamicStoreCopyProxies(NULL);
181 if (proxyDict == NULL) {
182 return PyDict_New();
185 result = PyDict_New();
186 if (result == NULL) goto error;
188 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;
209 CFRelease(proxyDict);
210 return result;
211 error:
212 if (proxyDict) CFRelease(proxyDict);
213 Py_XDECREF(result);
214 return NULL;
217 static PyMethodDef mod_methods[] = {
219 "_get_proxy_settings",
220 (PyCFunction)get_proxy_settings,
221 METH_NOARGS,
222 NULL,
225 "_get_proxies",
226 (PyCFunction)get_proxies,
227 METH_NOARGS,
228 NULL,
230 { 0, 0, 0, 0 }
235 static struct PyModuleDef mod_module = {
236 PyModuleDef_HEAD_INIT,
237 "_scproxy",
238 NULL,
240 mod_methods,
241 NULL,
242 NULL,
243 NULL,
244 NULL
248 #ifdef __cplusplus
249 extern "C" {
250 #endif
252 PyObject*
253 PyInit__scproxy(void)
255 return PyModule_Create(&mod_module);
258 #ifdef __cplusplus
260 #endif