PageRenderTime 32ms CodeModel.GetById 13ms app.highlight 15ms RepoModel.GetById 2ms app.codeStats 0ms

/Mac/Modules/_scproxy.c

http://unladen-swallow.googlecode.com/
C | 226 lines | 190 code | 32 blank | 4 comment | 47 complexity | df9e075525c1c51c68b707c33233fcc2 MD5 | raw file
  1/*
  2 * Helper method for urllib to fetch the proxy configuration settings
  3 * using the SystemConfiguration framework.
  4 */
  5#include <Python.h>
  6#include <SystemConfiguration/SystemConfiguration.h>
  7
  8static int32_t 
  9cfnum_to_int32(CFNumberRef num)
 10{
 11	int32_t result;
 12
 13	CFNumberGetValue(num, kCFNumberSInt32Type, &result);
 14	return result;
 15}
 16
 17static PyObject*
 18cfstring_to_pystring(CFStringRef ref)
 19{
 20	const char* s; 
 21
 22	s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
 23	if (s) {
 24		return PyString_FromString(s);
 25
 26	} else {
 27		CFIndex len = CFStringGetLength(ref);
 28		Boolean ok;
 29		PyObject* result;
 30		result = PyString_FromStringAndSize(NULL, len*4);
 31
 32		ok = CFStringGetCString(ref, 
 33				PyString_AS_STRING(result),
 34				PyString_GET_SIZE(result),
 35				kCFStringEncodingUTF8);
 36		if (!ok) {
 37			Py_DECREF(result);
 38			return NULL;
 39		} else {
 40			_PyString_Resize(&result, 
 41				strlen(PyString_AS_STRING(result)));
 42		}
 43		return result;
 44	}
 45}
 46
 47
 48static PyObject*
 49get_proxy_settings(PyObject* mod __attribute__((__unused__)))
 50{
 51	CFDictionaryRef proxyDict = NULL;
 52	CFNumberRef aNum = NULL;
 53	CFArrayRef anArray = NULL;
 54	PyObject* result = NULL;
 55	PyObject* v;
 56	int r;
 57
 58	proxyDict = SCDynamicStoreCopyProxies(NULL);
 59	if (!proxyDict) {
 60		Py_INCREF(Py_None);
 61		return Py_None;
 62	}
 63
 64	result = PyDict_New();
 65	if (result == NULL) goto error;
 66
 67	aNum = CFDictionaryGetValue(proxyDict, 
 68			kSCPropNetProxiesExcludeSimpleHostnames);
 69	if (aNum == NULL) {
 70		v = PyBool_FromLong(0);
 71	} else {
 72		v = PyBool_FromLong(cfnum_to_int32(aNum));
 73	}
 74	if (v == NULL) goto error;
 75
 76	r = PyDict_SetItemString(result, "exclude_simple", v);
 77	Py_DECREF(v); v = NULL;
 78	if (r == -1) goto error;
 79
 80	anArray = CFDictionaryGetValue(proxyDict, 
 81			kSCPropNetProxiesExceptionsList);
 82	if (anArray != NULL) {
 83		CFIndex len = CFArrayGetCount(anArray);
 84		CFIndex i;
 85		v = PyTuple_New(len);
 86		if (v == NULL) goto error;
 87
 88		r = PyDict_SetItemString(result, "exceptions", v);
 89		Py_DECREF(v);
 90		if (r == -1) goto error;
 91
 92		for (i = 0; i < len; i++) {
 93			CFStringRef aString = NULL;
 94
 95			aString = CFArrayGetValueAtIndex(anArray, i);
 96			if (aString == NULL) {
 97				PyTuple_SetItem(v, i, Py_None);
 98				Py_INCREF(Py_None);
 99			} else {
100				PyObject* t = cfstring_to_pystring(aString);
101				if (!t) {
102					PyTuple_SetItem(v, i, Py_None);
103					Py_INCREF(Py_None);
104				} else {
105					PyTuple_SetItem(v, i, t);
106				}
107			}
108		}
109	}
110
111	CFRelease(proxyDict);
112	return result;
113
114error:
115	if (proxyDict)  CFRelease(proxyDict);
116	Py_XDECREF(result);
117	return NULL;
118}
119
120static int
121set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
122		CFStringRef enabledKey, 
123		CFStringRef hostKey, CFStringRef portKey)
124{
125	CFNumberRef aNum;
126
127	aNum = CFDictionaryGetValue(proxyDict, enabledKey);
128	if (aNum && cfnum_to_int32(aNum)) {
129		CFStringRef hostString;
130
131		hostString = CFDictionaryGetValue(proxyDict, hostKey);
132		aNum = CFDictionaryGetValue(proxyDict, portKey);
133
134		if (hostString) {
135			int r;
136			PyObject* h = cfstring_to_pystring(hostString);
137			PyObject* v;
138			if (h) {
139				if (aNum) {
140					int32_t port = cfnum_to_int32(aNum);
141					v = PyString_FromFormat("http://%s:%ld",
142						PyString_AS_STRING(h),
143						(long)port);
144				} else {
145					v = PyString_FromFormat("http://%s",
146						PyString_AS_STRING(h));
147				}
148				Py_DECREF(h);
149				if (!v) return -1;
150				r = PyDict_SetItemString(proxies, proto,
151					v);
152				Py_DECREF(v);
153				return r;
154			}
155		}
156
157	}
158	return 0;
159}
160
161
162
163static PyObject*
164get_proxies(PyObject* mod __attribute__((__unused__)))
165{
166	PyObject* result = NULL;
167	int r;
168	CFDictionaryRef proxyDict = NULL;
169
170	proxyDict = SCDynamicStoreCopyProxies(NULL);
171	if (proxyDict == NULL) {
172		return PyDict_New();
173	}
174
175	result = PyDict_New();
176	if (result == NULL) goto error;
177
178	r = set_proxy(result, "http", proxyDict,
179		kSCPropNetProxiesHTTPEnable,
180		kSCPropNetProxiesHTTPProxy,
181		kSCPropNetProxiesHTTPPort);
182	if (r == -1) goto error;
183	r = set_proxy(result, "https", proxyDict,
184		kSCPropNetProxiesHTTPSEnable,
185		kSCPropNetProxiesHTTPSProxy,
186		kSCPropNetProxiesHTTPSPort);
187	if (r == -1) goto error;
188	r = set_proxy(result, "ftp", proxyDict,
189		kSCPropNetProxiesFTPEnable,
190		kSCPropNetProxiesFTPProxy,
191		kSCPropNetProxiesFTPPort);
192	if (r == -1) goto error;
193	r = set_proxy(result, "gopher", proxyDict,
194		kSCPropNetProxiesGopherEnable,
195		kSCPropNetProxiesGopherProxy,
196		kSCPropNetProxiesGopherPort);
197	if (r == -1) goto error;
198
199	CFRelease(proxyDict);
200	return result;
201error:
202	if (proxyDict)  CFRelease(proxyDict);
203	Py_XDECREF(result);
204	return NULL;
205}
206
207static PyMethodDef mod_methods[] = {
208	{
209		"_get_proxy_settings",
210		(PyCFunction)get_proxy_settings,
211		METH_NOARGS,
212		NULL,
213	},
214	{
215		"_get_proxies",
216		(PyCFunction)get_proxies,
217		METH_NOARGS,
218		NULL,
219	},
220	{ 0, 0, 0, 0 }
221};
222
223void init_scproxy(void)
224{
225	(void)Py_InitModule4("_scproxy", mod_methods, NULL, NULL, PYTHON_API_VERSION);
226}