diff options
author | Ronald Oussoren <ronaldoussoren@mac.com> | 2009-09-20 10:31:22 (GMT) |
---|---|---|
committer | Ronald Oussoren <ronaldoussoren@mac.com> | 2009-09-20 10:31:22 (GMT) |
commit | 51f0633efdc31ae29d5813881a96b0c737fca075 (patch) | |
tree | 3c340af902f24aabda493e62ff33a67ce7261db5 /Mac | |
parent | 4b017bbac0dd4e0a7e3c4424157c278dc4f8fa72 (diff) | |
download | cpython-51f0633efdc31ae29d5813881a96b0c737fca075.zip cpython-51f0633efdc31ae29d5813881a96b0c737fca075.tar.gz cpython-51f0633efdc31ae29d5813881a96b0c737fca075.tar.bz2 |
Fix for issue 6851: urllib.urlopen crashes in a thread on OSX 10.6
Diffstat (limited to 'Mac')
-rw-r--r-- | Mac/Modules/_scproxy.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/Mac/Modules/_scproxy.c b/Mac/Modules/_scproxy.c new file mode 100644 index 0000000..003f6a4 --- /dev/null +++ b/Mac/Modules/_scproxy.c @@ -0,0 +1,226 @@ +/* + * 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 PyString_FromString(s); + + } else { + CFIndex len = CFStringGetLength(ref); + Boolean ok; + PyObject* result; + result = PyString_FromStringAndSize(NULL, len*4); + + ok = CFStringGetCString(ref, + PyString_AS_STRING(result), + PyString_GET_SIZE(result), + kCFStringEncodingUTF8); + if (!ok) { + Py_DECREF(result); + return NULL; + } else { + _PyString_Resize(&result, + strlen(PyString_AS_STRING(result))); + } + 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; + + aNum = CFDictionaryGetValue(proxyDict, + kSCPropNetProxiesExcludeSimpleHostnames); + if (aNum == NULL) { + v = PyBool_FromLong(0); + } else { + v = PyBool_FromLong(cfnum_to_int32(aNum)); + } + 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 = PyString_FromFormat("http://%s:%ld", + PyString_AS_STRING(h), + (long)port); + } else { + v = PyString_FromFormat("http://%s", + PyString_AS_STRING(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 } +}; + +void init_scproxy(void) +{ + (void)Py_InitModule4("_scproxy", mod_methods, NULL, NULL, PYTHON_API_VERSION); +} |