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