| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Helper method for urllib to fetch the proxy configuration settings | 
					
						
							|  |  |  |  * using the SystemConfiguration framework. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <Python.h>
 | 
					
						
							|  |  |  | #include <SystemConfiguration/SystemConfiguration.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | static int32_t | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | cfnum_to_int32(CFNumberRef num) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     int32_t result; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     CFNumberGetValue(num, kCFNumberSInt32Type, &result); | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject* | 
					
						
							|  |  |  | cfstring_to_pystring(CFStringRef ref) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     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; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject* | 
					
						
							|  |  |  | get_proxy_settings(PyObject* mod __attribute__((__unused__))) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2010-06-27 12:51:31 +00:00
										 |  |  |             v = PyBool_FromLong(0); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             v = PyBool_FromLong(cfnum_to_int32(aNum)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }  else { | 
					
						
							| 
									
										
										
										
											2010-09-28 14:38:31 +00:00
										 |  |  |         v = PyBool_FromLong(0); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (proxyDict)  CFRelease(proxyDict); | 
					
						
							|  |  |  |     Py_XDECREF(result); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                 CFStringRef enabledKey, | 
					
						
							|  |  |  |                 CFStringRef hostKey, CFStringRef portKey) | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject* | 
					
						
							|  |  |  | get_proxies(PyObject* mod __attribute__((__unused__))) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | error: | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (proxyDict)  CFRelease(proxyDict); | 
					
						
							|  |  |  |     Py_XDECREF(result); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef mod_methods[] = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |         "_get_proxy_settings", | 
					
						
							|  |  |  |         (PyCFunction)get_proxy_settings, | 
					
						
							|  |  |  |         METH_NOARGS, | 
					
						
							|  |  |  |         NULL, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         "_get_proxies", | 
					
						
							|  |  |  |         (PyCFunction)get_proxies, | 
					
						
							|  |  |  |         METH_NOARGS, | 
					
						
							|  |  |  |         NULL, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { 0, 0, 0, 0 } | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef mod_module = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     "_scproxy", | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     -1, | 
					
						
							|  |  |  |     mod_methods, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | PyObject* | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | PyInit__scproxy(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return PyModule_Create(&mod_module); | 
					
						
							| 
									
										
										
										
											2010-04-18 20:46:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 |