17db96d56Sopenharmony_ci/* 27db96d56Sopenharmony_ci * Helper method for urllib to fetch the proxy configuration settings 37db96d56Sopenharmony_ci * using the SystemConfiguration framework. 47db96d56Sopenharmony_ci */ 57db96d56Sopenharmony_ci#include <Python.h> 67db96d56Sopenharmony_ci#include <SystemConfiguration/SystemConfiguration.h> 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_cistatic int32_t 97db96d56Sopenharmony_cicfnum_to_int32(CFNumberRef num) 107db96d56Sopenharmony_ci{ 117db96d56Sopenharmony_ci int32_t result; 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci CFNumberGetValue(num, kCFNumberSInt32Type, &result); 147db96d56Sopenharmony_ci return result; 157db96d56Sopenharmony_ci} 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_cistatic PyObject* 187db96d56Sopenharmony_cicfstring_to_pystring(CFStringRef ref) 197db96d56Sopenharmony_ci{ 207db96d56Sopenharmony_ci const char* s; 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ci s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8); 237db96d56Sopenharmony_ci if (s) { 247db96d56Sopenharmony_ci return PyUnicode_DecodeUTF8( 257db96d56Sopenharmony_ci s, strlen(s), NULL); 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci } else { 287db96d56Sopenharmony_ci CFIndex len = CFStringGetLength(ref); 297db96d56Sopenharmony_ci Boolean ok; 307db96d56Sopenharmony_ci PyObject* result; 317db96d56Sopenharmony_ci char* buf; 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci buf = PyMem_Malloc(len*4); 347db96d56Sopenharmony_ci if (buf == NULL) { 357db96d56Sopenharmony_ci PyErr_NoMemory(); 367db96d56Sopenharmony_ci return NULL; 377db96d56Sopenharmony_ci } 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci ok = CFStringGetCString(ref, 407db96d56Sopenharmony_ci buf, len * 4, 417db96d56Sopenharmony_ci kCFStringEncodingUTF8); 427db96d56Sopenharmony_ci if (!ok) { 437db96d56Sopenharmony_ci PyMem_Free(buf); 447db96d56Sopenharmony_ci return NULL; 457db96d56Sopenharmony_ci } else { 467db96d56Sopenharmony_ci result = PyUnicode_DecodeUTF8( 477db96d56Sopenharmony_ci buf, strlen(buf), NULL); 487db96d56Sopenharmony_ci PyMem_Free(buf); 497db96d56Sopenharmony_ci } 507db96d56Sopenharmony_ci return result; 517db96d56Sopenharmony_ci } 527db96d56Sopenharmony_ci} 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_cistatic PyObject* 567db96d56Sopenharmony_ciget_proxy_settings(PyObject* Py_UNUSED(mod), PyObject *Py_UNUSED(ignored)) 577db96d56Sopenharmony_ci{ 587db96d56Sopenharmony_ci CFDictionaryRef proxyDict = NULL; 597db96d56Sopenharmony_ci CFNumberRef aNum = NULL; 607db96d56Sopenharmony_ci CFArrayRef anArray = NULL; 617db96d56Sopenharmony_ci PyObject* result = NULL; 627db96d56Sopenharmony_ci PyObject* v; 637db96d56Sopenharmony_ci int r; 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 667db96d56Sopenharmony_ci proxyDict = SCDynamicStoreCopyProxies(NULL); 677db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci if (!proxyDict) { 707db96d56Sopenharmony_ci Py_RETURN_NONE; 717db96d56Sopenharmony_ci } 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci result = PyDict_New(); 747db96d56Sopenharmony_ci if (result == NULL) goto error; 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci aNum = CFDictionaryGetValue(proxyDict, 777db96d56Sopenharmony_ci kSCPropNetProxiesExcludeSimpleHostnames); 787db96d56Sopenharmony_ci if (aNum == NULL) { 797db96d56Sopenharmony_ci v = PyBool_FromLong(0); 807db96d56Sopenharmony_ci } else { 817db96d56Sopenharmony_ci v = PyBool_FromLong(cfnum_to_int32(aNum)); 827db96d56Sopenharmony_ci } 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci if (v == NULL) goto error; 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci r = PyDict_SetItemString(result, "exclude_simple", v); 877db96d56Sopenharmony_ci Py_DECREF(v); v = NULL; 887db96d56Sopenharmony_ci if (r == -1) goto error; 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci anArray = CFDictionaryGetValue(proxyDict, 917db96d56Sopenharmony_ci kSCPropNetProxiesExceptionsList); 927db96d56Sopenharmony_ci if (anArray != NULL) { 937db96d56Sopenharmony_ci CFIndex len = CFArrayGetCount(anArray); 947db96d56Sopenharmony_ci CFIndex i; 957db96d56Sopenharmony_ci v = PyTuple_New(len); 967db96d56Sopenharmony_ci if (v == NULL) goto error; 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci r = PyDict_SetItemString(result, "exceptions", v); 997db96d56Sopenharmony_ci Py_DECREF(v); 1007db96d56Sopenharmony_ci if (r == -1) goto error; 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci for (i = 0; i < len; i++) { 1037db96d56Sopenharmony_ci CFStringRef aString = NULL; 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci aString = CFArrayGetValueAtIndex(anArray, i); 1067db96d56Sopenharmony_ci if (aString == NULL) { 1077db96d56Sopenharmony_ci PyTuple_SetItem(v, i, Py_None); 1087db96d56Sopenharmony_ci Py_INCREF(Py_None); 1097db96d56Sopenharmony_ci } else { 1107db96d56Sopenharmony_ci PyObject* t = cfstring_to_pystring(aString); 1117db96d56Sopenharmony_ci if (!t) { 1127db96d56Sopenharmony_ci PyTuple_SetItem(v, i, Py_None); 1137db96d56Sopenharmony_ci Py_INCREF(Py_None); 1147db96d56Sopenharmony_ci } else { 1157db96d56Sopenharmony_ci PyTuple_SetItem(v, i, t); 1167db96d56Sopenharmony_ci } 1177db96d56Sopenharmony_ci } 1187db96d56Sopenharmony_ci } 1197db96d56Sopenharmony_ci } 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci CFRelease(proxyDict); 1227db96d56Sopenharmony_ci return result; 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_cierror: 1257db96d56Sopenharmony_ci if (proxyDict) CFRelease(proxyDict); 1267db96d56Sopenharmony_ci Py_XDECREF(result); 1277db96d56Sopenharmony_ci return NULL; 1287db96d56Sopenharmony_ci} 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_cistatic int 1317db96d56Sopenharmony_ciset_proxy(PyObject* proxies, const char* proto, CFDictionaryRef proxyDict, 1327db96d56Sopenharmony_ci CFStringRef enabledKey, 1337db96d56Sopenharmony_ci CFStringRef hostKey, CFStringRef portKey) 1347db96d56Sopenharmony_ci{ 1357db96d56Sopenharmony_ci CFNumberRef aNum; 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci aNum = CFDictionaryGetValue(proxyDict, enabledKey); 1387db96d56Sopenharmony_ci if (aNum && cfnum_to_int32(aNum)) { 1397db96d56Sopenharmony_ci CFStringRef hostString; 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci hostString = CFDictionaryGetValue(proxyDict, hostKey); 1427db96d56Sopenharmony_ci aNum = CFDictionaryGetValue(proxyDict, portKey); 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci if (hostString) { 1457db96d56Sopenharmony_ci int r; 1467db96d56Sopenharmony_ci PyObject* h = cfstring_to_pystring(hostString); 1477db96d56Sopenharmony_ci PyObject* v; 1487db96d56Sopenharmony_ci if (h) { 1497db96d56Sopenharmony_ci if (aNum) { 1507db96d56Sopenharmony_ci int32_t port = cfnum_to_int32(aNum); 1517db96d56Sopenharmony_ci v = PyUnicode_FromFormat("http://%U:%ld", 1527db96d56Sopenharmony_ci h, (long)port); 1537db96d56Sopenharmony_ci } else { 1547db96d56Sopenharmony_ci v = PyUnicode_FromFormat("http://%U", h); 1557db96d56Sopenharmony_ci } 1567db96d56Sopenharmony_ci Py_DECREF(h); 1577db96d56Sopenharmony_ci if (!v) return -1; 1587db96d56Sopenharmony_ci r = PyDict_SetItemString(proxies, proto, 1597db96d56Sopenharmony_ci v); 1607db96d56Sopenharmony_ci Py_DECREF(v); 1617db96d56Sopenharmony_ci return r; 1627db96d56Sopenharmony_ci } 1637db96d56Sopenharmony_ci } 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci } 1667db96d56Sopenharmony_ci return 0; 1677db96d56Sopenharmony_ci} 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_cistatic PyObject* 1727db96d56Sopenharmony_ciget_proxies(PyObject* Py_UNUSED(mod), PyObject *Py_UNUSED(ignored)) 1737db96d56Sopenharmony_ci{ 1747db96d56Sopenharmony_ci PyObject* result = NULL; 1757db96d56Sopenharmony_ci int r; 1767db96d56Sopenharmony_ci CFDictionaryRef proxyDict = NULL; 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 1797db96d56Sopenharmony_ci proxyDict = SCDynamicStoreCopyProxies(NULL); 1807db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci if (proxyDict == NULL) { 1837db96d56Sopenharmony_ci return PyDict_New(); 1847db96d56Sopenharmony_ci } 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci result = PyDict_New(); 1877db96d56Sopenharmony_ci if (result == NULL) goto error; 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci r = set_proxy(result, "http", proxyDict, 1907db96d56Sopenharmony_ci kSCPropNetProxiesHTTPEnable, 1917db96d56Sopenharmony_ci kSCPropNetProxiesHTTPProxy, 1927db96d56Sopenharmony_ci kSCPropNetProxiesHTTPPort); 1937db96d56Sopenharmony_ci if (r == -1) goto error; 1947db96d56Sopenharmony_ci r = set_proxy(result, "https", proxyDict, 1957db96d56Sopenharmony_ci kSCPropNetProxiesHTTPSEnable, 1967db96d56Sopenharmony_ci kSCPropNetProxiesHTTPSProxy, 1977db96d56Sopenharmony_ci kSCPropNetProxiesHTTPSPort); 1987db96d56Sopenharmony_ci if (r == -1) goto error; 1997db96d56Sopenharmony_ci r = set_proxy(result, "ftp", proxyDict, 2007db96d56Sopenharmony_ci kSCPropNetProxiesFTPEnable, 2017db96d56Sopenharmony_ci kSCPropNetProxiesFTPProxy, 2027db96d56Sopenharmony_ci kSCPropNetProxiesFTPPort); 2037db96d56Sopenharmony_ci if (r == -1) goto error; 2047db96d56Sopenharmony_ci r = set_proxy(result, "gopher", proxyDict, 2057db96d56Sopenharmony_ci kSCPropNetProxiesGopherEnable, 2067db96d56Sopenharmony_ci kSCPropNetProxiesGopherProxy, 2077db96d56Sopenharmony_ci kSCPropNetProxiesGopherPort); 2087db96d56Sopenharmony_ci if (r == -1) goto error; 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci CFRelease(proxyDict); 2117db96d56Sopenharmony_ci return result; 2127db96d56Sopenharmony_cierror: 2137db96d56Sopenharmony_ci if (proxyDict) CFRelease(proxyDict); 2147db96d56Sopenharmony_ci Py_XDECREF(result); 2157db96d56Sopenharmony_ci return NULL; 2167db96d56Sopenharmony_ci} 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_cistatic PyMethodDef mod_methods[] = { 2197db96d56Sopenharmony_ci { 2207db96d56Sopenharmony_ci "_get_proxy_settings", 2217db96d56Sopenharmony_ci get_proxy_settings, 2227db96d56Sopenharmony_ci METH_NOARGS, 2237db96d56Sopenharmony_ci NULL, 2247db96d56Sopenharmony_ci }, 2257db96d56Sopenharmony_ci { 2267db96d56Sopenharmony_ci "_get_proxies", 2277db96d56Sopenharmony_ci get_proxies, 2287db96d56Sopenharmony_ci METH_NOARGS, 2297db96d56Sopenharmony_ci NULL, 2307db96d56Sopenharmony_ci }, 2317db96d56Sopenharmony_ci { 0, 0, 0, 0 } 2327db96d56Sopenharmony_ci}; 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_cistatic PyModuleDef_Slot _scproxy_slots[] = { 2357db96d56Sopenharmony_ci {0, NULL} 2367db96d56Sopenharmony_ci}; 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_cistatic struct PyModuleDef _scproxy_module = { 2397db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 2407db96d56Sopenharmony_ci .m_name = "_scproxy", 2417db96d56Sopenharmony_ci .m_size = 0, 2427db96d56Sopenharmony_ci .m_methods = mod_methods, 2437db96d56Sopenharmony_ci .m_slots = _scproxy_slots, 2447db96d56Sopenharmony_ci}; 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci#ifdef __cplusplus 2477db96d56Sopenharmony_ciextern "C" { 2487db96d56Sopenharmony_ci#endif 2497db96d56Sopenharmony_ci 2507db96d56Sopenharmony_ciPyMODINIT_FUNC 2517db96d56Sopenharmony_ciPyInit__scproxy(void) 2527db96d56Sopenharmony_ci{ 2537db96d56Sopenharmony_ci return PyModuleDef_Init(&_scproxy_module); 2547db96d56Sopenharmony_ci} 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci#ifdef __cplusplus 2577db96d56Sopenharmony_ci} 2587db96d56Sopenharmony_ci#endif 259