/* * 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; if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) { aNum = CFDictionaryGetValue(proxyDict, kSCPropNetProxiesExcludeSimpleHostnames); if (aNum == NULL) { v = PyBool_FromLong(0); } else { v = PyBool_FromLong(cfnum_to_int32(aNum)); } } else { v = PyBool_FromLong(0); } 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); }