diff options
author | Ronald Oussoren <ronaldoussoren@mac.com> | 2010-04-18 20:46:11 (GMT) |
---|---|---|
committer | Ronald Oussoren <ronaldoussoren@mac.com> | 2010-04-18 20:46:11 (GMT) |
commit | 8415120af34d7239dca90f6cd47d0714c226d123 (patch) | |
tree | 350627ffb1ae96418a7dcd31eeeee0a6ca8e8f8f /Modules | |
parent | f88db8de767460a6a2bd4307278ba6e9253b7770 (diff) | |
download | cpython-8415120af34d7239dca90f6cd47d0714c226d123.zip cpython-8415120af34d7239dca90f6cd47d0714c226d123.tar.gz cpython-8415120af34d7239dca90f6cd47d0714c226d123.tar.bz2 |
For for issue #7154: Port the code that uses
the SystemConfiguration framework to detect the
proxy settings on OSX from the trunk to python 3.2
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_scproxy.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Modules/_scproxy.c b/Modules/_scproxy.c new file mode 100644 index 0000000..602fbe3 --- /dev/null +++ b/Modules/_scproxy.c @@ -0,0 +1,261 @@ +/* + * Helper method for urllib to fetch the proxy configuration settings + * using the SystemConfiguration framework. + */ +#include <Python.h> +#include <SystemConfiguration/SystemConfiguration.h> + +static int32_t +cfnum_to_int32(CFNumberRef num) +{ + int32_t result; + + CFNumberGetValue(num, kCFNumberSInt32Type, &result); + return result; +} + +static PyObject* +cfstring_to_pystring(CFStringRef ref) +{ + const char* s; + + s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8); + if (s) { + return PyUnicode_DecodeUTF8( + s, strlen(s), NULL); + + } else { + CFIndex len = CFStringGetLength(ref); + Boolean ok; + PyObject* result; + char* buf; + + buf = PyMem_Malloc(len*4); + if (buf == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ok = CFStringGetCString(ref, + buf, len * 4, + kCFStringEncodingUTF8); + if (!ok) { + PyMem_Free(buf); + return NULL; + } else { + result = PyUnicode_DecodeUTF8( + buf, strlen(buf), NULL); + PyMem_Free(buf); + } + return result; + } +} + + +static PyObject* +get_proxy_settings(PyObject* mod __attribute__((__unused__))) +{ + CFDictionaryRef proxyDict = NULL; + CFNumberRef aNum = NULL; + CFArrayRef anArray = NULL; + PyObject* result = NULL; + PyObject* v; + int r; + + proxyDict = SCDynamicStoreCopyProxies(NULL); + if (!proxyDict) { + Py_INCREF(Py_None); + return Py_None; + } + + result = PyDict_New(); + if (result == NULL) goto error; + + if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) { + aNum = CFDictionaryGetValue(proxyDict, + kSCPropNetProxiesExcludeSimpleHostnames); + if (aNum == NULL) { + v = PyBool_FromLong(1); + } else { + v = PyBool_FromLong(cfnum_to_int32(aNum)); + } + } else { + v = PyBool_FromLong(1); + } + + if (v == NULL) goto error; + + r = PyDict_SetItemString(result, "exclude_simple", v); + Py_DECREF(v); v = NULL; + if (r == -1) goto error; + + anArray = CFDictionaryGetValue(proxyDict, + kSCPropNetProxiesExceptionsList); + if (anArray != NULL) { + CFIndex len = CFArrayGetCount(anArray); + CFIndex i; + v = PyTuple_New(len); + if (v == NULL) goto error; + + r = PyDict_SetItemString(result, "exceptions", v); + Py_DECREF(v); + if (r == -1) goto error; + + for (i = 0; i < len; i++) { + CFStringRef aString = NULL; + + aString = CFArrayGetValueAtIndex(anArray, i); + if (aString == NULL) { + PyTuple_SetItem(v, i, Py_None); + Py_INCREF(Py_None); + } else { + PyObject* t = cfstring_to_pystring(aString); + if (!t) { + PyTuple_SetItem(v, i, Py_None); + Py_INCREF(Py_None); + } else { + PyTuple_SetItem(v, i, t); + } + } + } + } + + CFRelease(proxyDict); + return result; + +error: + if (proxyDict) CFRelease(proxyDict); + Py_XDECREF(result); + return NULL; +} + +static int +set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict, + CFStringRef enabledKey, + CFStringRef hostKey, CFStringRef portKey) +{ + CFNumberRef aNum; + + aNum = CFDictionaryGetValue(proxyDict, enabledKey); + if (aNum && cfnum_to_int32(aNum)) { + CFStringRef hostString; + + hostString = CFDictionaryGetValue(proxyDict, hostKey); + aNum = CFDictionaryGetValue(proxyDict, portKey); + + if (hostString) { + int r; + PyObject* h = cfstring_to_pystring(hostString); + PyObject* v; + if (h) { + if (aNum) { + int32_t port = cfnum_to_int32(aNum); + v = PyUnicode_FromFormat("http://%U:%ld", + h, (long)port); + } else { + v = PyUnicode_FromFormat("http://%U", h); + } + Py_DECREF(h); + if (!v) return -1; + r = PyDict_SetItemString(proxies, proto, + v); + Py_DECREF(v); + return r; + } + } + + } + return 0; +} + + + +static PyObject* +get_proxies(PyObject* mod __attribute__((__unused__))) +{ + PyObject* result = NULL; + int r; + CFDictionaryRef proxyDict = NULL; + + proxyDict = SCDynamicStoreCopyProxies(NULL); + if (proxyDict == NULL) { + return PyDict_New(); + } + + result = PyDict_New(); + if (result == NULL) goto error; + + r = set_proxy(result, "http", proxyDict, + kSCPropNetProxiesHTTPEnable, + kSCPropNetProxiesHTTPProxy, + kSCPropNetProxiesHTTPPort); + if (r == -1) goto error; + r = set_proxy(result, "https", proxyDict, + kSCPropNetProxiesHTTPSEnable, + kSCPropNetProxiesHTTPSProxy, + kSCPropNetProxiesHTTPSPort); + if (r == -1) goto error; + r = set_proxy(result, "ftp", proxyDict, + kSCPropNetProxiesFTPEnable, + kSCPropNetProxiesFTPProxy, + kSCPropNetProxiesFTPPort); + if (r == -1) goto error; + r = set_proxy(result, "gopher", proxyDict, + kSCPropNetProxiesGopherEnable, + kSCPropNetProxiesGopherProxy, + kSCPropNetProxiesGopherPort); + if (r == -1) goto error; + + CFRelease(proxyDict); + return result; +error: + if (proxyDict) CFRelease(proxyDict); + Py_XDECREF(result); + return NULL; +} + +static PyMethodDef mod_methods[] = { + { + "_get_proxy_settings", + (PyCFunction)get_proxy_settings, + METH_NOARGS, + NULL, + }, + { + "_get_proxies", + (PyCFunction)get_proxies, + METH_NOARGS, + NULL, + }, + { 0, 0, 0, 0 } +}; + + + +static struct PyModuleDef mod_module = { + PyModuleDef_HEAD_INIT, + "_scproxy", + NULL, + -1, + mod_methods, + NULL, + NULL, + NULL, + NULL +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +PyObject* +PyInit__scproxy(void) +{ + return PyModule_Create(&mod_module); +} + +#ifdef __cplusplus +} +#endif + |