(root)/
Python-3.11.7/
Modules/
_scproxy.c
       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  
       8  static int32_t
       9  cfnum_to_int32(CFNumberRef num)
      10  {
      11      int32_t result;
      12  
      13      CFNumberGetValue(num, kCFNumberSInt32Type, &result);
      14      return result;
      15  }
      16  
      17  static PyObject*
      18  cfstring_to_pystring(CFStringRef ref)
      19  {
      20      const char* s;
      21  
      22      s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
      23      if (s) {
      24          return PyUnicode_DecodeUTF8(
      25                          s, strlen(s), NULL);
      26  
      27      } else {
      28          CFIndex len = CFStringGetLength(ref);
      29          Boolean ok;
      30          PyObject* result;
      31          char* buf;
      32  
      33          buf = PyMem_Malloc(len*4);
      34          if (buf == NULL) {
      35              PyErr_NoMemory();
      36              return NULL;
      37          }
      38  
      39          ok = CFStringGetCString(ref,
      40                          buf, len * 4,
      41                          kCFStringEncodingUTF8);
      42          if (!ok) {
      43              PyMem_Free(buf);
      44              return NULL;
      45          } else {
      46              result = PyUnicode_DecodeUTF8(
      47                              buf, strlen(buf), NULL);
      48              PyMem_Free(buf);
      49          }
      50          return result;
      51      }
      52  }
      53  
      54  
      55  static PyObject*
      56  get_proxy_settings(PyObject* Py_UNUSED(mod), PyObject *Py_UNUSED(ignored))
      57  {
      58      CFDictionaryRef proxyDict = NULL;
      59      CFNumberRef aNum = NULL;
      60      CFArrayRef anArray = NULL;
      61      PyObject* result = NULL;
      62      PyObject* v;
      63      int r;
      64  
      65      Py_BEGIN_ALLOW_THREADS
      66      proxyDict = SCDynamicStoreCopyProxies(NULL);
      67      Py_END_ALLOW_THREADS
      68  
      69      if (!proxyDict) {
      70          Py_RETURN_NONE;
      71      }
      72  
      73      result = PyDict_New();
      74      if (result == NULL) goto error;
      75  
      76      aNum = CFDictionaryGetValue(proxyDict,
      77          kSCPropNetProxiesExcludeSimpleHostnames);
      78      if (aNum == NULL) {
      79          v = PyBool_FromLong(0);
      80      } else {
      81          v = PyBool_FromLong(cfnum_to_int32(aNum));
      82      }
      83  
      84      if (v == NULL) goto error;
      85  
      86      r = PyDict_SetItemString(result, "exclude_simple", v);
      87      Py_DECREF(v); v = NULL;
      88      if (r == -1) goto error;
      89  
      90      anArray = CFDictionaryGetValue(proxyDict,
      91                      kSCPropNetProxiesExceptionsList);
      92      if (anArray != NULL) {
      93          CFIndex len = CFArrayGetCount(anArray);
      94          CFIndex i;
      95          v = PyTuple_New(len);
      96          if (v == NULL) goto error;
      97  
      98          r = PyDict_SetItemString(result, "exceptions", v);
      99          Py_DECREF(v);
     100          if (r == -1) goto error;
     101  
     102          for (i = 0; i < len; i++) {
     103              CFStringRef aString = NULL;
     104  
     105              aString = CFArrayGetValueAtIndex(anArray, i);
     106              if (aString == NULL) {
     107                  PyTuple_SetItem(v, i, Py_None);
     108                  Py_INCREF(Py_None);
     109              } else {
     110                  PyObject* t = cfstring_to_pystring(aString);
     111                  if (!t) {
     112                      PyTuple_SetItem(v, i, Py_None);
     113                      Py_INCREF(Py_None);
     114                  } else {
     115                      PyTuple_SetItem(v, i, t);
     116                  }
     117              }
     118          }
     119      }
     120  
     121      CFRelease(proxyDict);
     122      return result;
     123  
     124  error:
     125      if (proxyDict)  CFRelease(proxyDict);
     126      Py_XDECREF(result);
     127      return NULL;
     128  }
     129  
     130  static int
     131  set_proxy(PyObject* proxies, const char* proto, CFDictionaryRef proxyDict,
     132                  CFStringRef enabledKey,
     133                  CFStringRef hostKey, CFStringRef portKey)
     134  {
     135      CFNumberRef aNum;
     136  
     137      aNum = CFDictionaryGetValue(proxyDict, enabledKey);
     138      if (aNum && cfnum_to_int32(aNum)) {
     139          CFStringRef hostString;
     140  
     141          hostString = CFDictionaryGetValue(proxyDict, hostKey);
     142          aNum = CFDictionaryGetValue(proxyDict, portKey);
     143  
     144          if (hostString) {
     145              int r;
     146              PyObject* h = cfstring_to_pystring(hostString);
     147              PyObject* v;
     148              if (h) {
     149                  if (aNum) {
     150                      int32_t port = cfnum_to_int32(aNum);
     151                      v = PyUnicode_FromFormat("http://%U:%ld",
     152                          h, (long)port);
     153                  } else {
     154                      v = PyUnicode_FromFormat("http://%U", h);
     155                  }
     156                  Py_DECREF(h);
     157                  if (!v) return -1;
     158                  r = PyDict_SetItemString(proxies, proto,
     159                      v);
     160                  Py_DECREF(v);
     161                  return r;
     162              }
     163          }
     164  
     165      }
     166      return 0;
     167  }
     168  
     169  
     170  
     171  static PyObject*
     172  get_proxies(PyObject* Py_UNUSED(mod), PyObject *Py_UNUSED(ignored))
     173  {
     174      PyObject* result = NULL;
     175      int r;
     176      CFDictionaryRef proxyDict = NULL;
     177  
     178      Py_BEGIN_ALLOW_THREADS
     179      proxyDict = SCDynamicStoreCopyProxies(NULL);
     180      Py_END_ALLOW_THREADS
     181  
     182      if (proxyDict == NULL) {
     183          return PyDict_New();
     184      }
     185  
     186      result = PyDict_New();
     187      if (result == NULL) goto error;
     188  
     189      r = set_proxy(result, "http", proxyDict,
     190          kSCPropNetProxiesHTTPEnable,
     191          kSCPropNetProxiesHTTPProxy,
     192          kSCPropNetProxiesHTTPPort);
     193      if (r == -1) goto error;
     194      r = set_proxy(result, "https", proxyDict,
     195          kSCPropNetProxiesHTTPSEnable,
     196          kSCPropNetProxiesHTTPSProxy,
     197          kSCPropNetProxiesHTTPSPort);
     198      if (r == -1) goto error;
     199      r = set_proxy(result, "ftp", proxyDict,
     200          kSCPropNetProxiesFTPEnable,
     201          kSCPropNetProxiesFTPProxy,
     202          kSCPropNetProxiesFTPPort);
     203      if (r == -1) goto error;
     204      r = set_proxy(result, "gopher", proxyDict,
     205          kSCPropNetProxiesGopherEnable,
     206          kSCPropNetProxiesGopherProxy,
     207          kSCPropNetProxiesGopherPort);
     208      if (r == -1) goto error;
     209  
     210      CFRelease(proxyDict);
     211      return result;
     212  error:
     213      if (proxyDict)  CFRelease(proxyDict);
     214      Py_XDECREF(result);
     215      return NULL;
     216  }
     217  
     218  static PyMethodDef mod_methods[] = {
     219      {
     220          "_get_proxy_settings",
     221          get_proxy_settings,
     222          METH_NOARGS,
     223          NULL,
     224      },
     225      {
     226          "_get_proxies",
     227          get_proxies,
     228          METH_NOARGS,
     229          NULL,
     230      },
     231      { 0, 0, 0, 0 }
     232  };
     233  
     234  static PyModuleDef_Slot _scproxy_slots[] = {
     235      {0, NULL}
     236  };
     237  
     238  static struct PyModuleDef _scproxy_module = {
     239      PyModuleDef_HEAD_INIT,
     240      .m_name = "_scproxy",
     241      .m_size = 0,
     242      .m_methods = mod_methods,
     243      .m_slots = _scproxy_slots,
     244  };
     245  
     246  #ifdef __cplusplus
     247  extern "C" {
     248  #endif
     249  
     250  PyMODINIT_FUNC
     251  PyInit__scproxy(void)
     252  {
     253      return PyModuleDef_Init(&_scproxy_module);
     254  }
     255  
     256  #ifdef __cplusplus
     257  }
     258  #endif