File: _scproxy.py

package info (click to toggle)
pypy 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 107,216 kB
  • sloc: python: 1,201,787; ansic: 62,419; asm: 5,169; cpp: 3,017; sh: 2,534; makefile: 545; xml: 243; lisp: 45; awk: 4
file content (130 lines) | stat: -rw-r--r-- 4,855 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""Helper methods for urllib to fetch the proxy configuration settings using
the SystemConfiguration framework.

"""
import sys
if sys.platform != 'darwin':
    raise ImportError('Requires Mac OS X')

from ctypes import c_int32, c_int64, c_void_p, c_char_p, c_int, cdll
from ctypes import pointer, create_string_buffer
from ctypes.util import find_library

kCFNumberSInt32Type = 3
kCFStringEncodingUTF8 = 134217984

def _CFSetup():
    sc = cdll.LoadLibrary(find_library("SystemConfiguration"))
    cf = cdll.LoadLibrary(find_library("CoreFoundation"))
    sctable = [
        ('SCDynamicStoreCopyProxies', [c_void_p], c_void_p),
    ]
    cftable = [
        ('CFArrayGetCount', [c_void_p], c_int64),
        ('CFArrayGetValueAtIndex', [c_void_p, c_int64], c_void_p),
        ('CFDictionaryGetValue', [c_void_p, c_void_p], c_void_p),
        ('CFStringCreateWithCString', [c_void_p, c_char_p, c_int32], c_void_p),
        ('CFStringGetLength', [c_void_p], c_int32),
        ('CFStringGetCString', [c_void_p, c_char_p, c_int32, c_int32], c_int32),
        ('CFNumberGetValue', [c_void_p, c_int, c_void_p], c_int32),
        ('CFRelease', [c_void_p], None),
    ]
    scconst = [
        'kSCPropNetProxiesExceptionsList',
        'kSCPropNetProxiesExcludeSimpleHostnames',
        'kSCPropNetProxiesHTTPEnable',
        'kSCPropNetProxiesHTTPProxy',
        'kSCPropNetProxiesHTTPPort',
        'kSCPropNetProxiesHTTPSEnable',
        'kSCPropNetProxiesHTTPSProxy',
        'kSCPropNetProxiesHTTPSPort',
        'kSCPropNetProxiesFTPEnable',
        'kSCPropNetProxiesFTPProxy',
        'kSCPropNetProxiesFTPPort',
        'kSCPropNetProxiesGopherEnable',
        'kSCPropNetProxiesGopherProxy',
        'kSCPropNetProxiesGopherPort',
    ]
    class CFProxy(object):
        def __init__(self):
            for mod, table in [(sc, sctable), (cf, cftable)]:
                for fname, argtypes, restype in table:
                    func = getattr(mod, fname)
                    func.argtypes = argtypes
                    func.restype = restype
                    setattr(self, fname, func)
            for k in scconst:
                v = None
                try:
                    v = c_void_p.in_dll(sc, k)
                except ValueError:
                    v = None
                setattr(self, k, v)
    return CFProxy()
ffi = _CFSetup()

def cfstring_to_pystring(value):
    length = (ffi.CFStringGetLength(value) * 4) + 1
    buff = create_string_buffer(length)
    ffi.CFStringGetCString(value, buff, length * 4, kCFStringEncodingUTF8)
    return unicode(buff.value, 'utf8')

def cfnum_to_int32(num):
    result_ptr = pointer(c_int32(0))
    ffi.CFNumberGetValue(num, kCFNumberSInt32Type, result_ptr)
    return result_ptr[0]

def _get_proxy_settings():
    result = {'exclude_simple': False}
    cfdct = ffi.SCDynamicStoreCopyProxies(None)
    if not cfdct:
        return result
    try:
        k = ffi.kSCPropNetProxiesExcludeSimpleHostnames
        if k:
            cfnum = ffi.CFDictionaryGetValue(cfdct, k)
            if cfnum:
                result['exclude_simple'] = bool(cfnum_to_int32(cfnum))
        k = ffi.kSCPropNetProxiesExceptionsList
        if k:
            cfarr = ffi.CFDictionaryGetValue(cfdct, k)
            if cfarr:
                lst = []
                for i in range(ffi.CFArrayGetCount(cfarr)):
                    cfstr = ffi.CFArrayGetValueAtIndex(cfarr, i)
                    if cfstr:
                        v = cfstring_to_pystring(cfstr)
                    else:
                        v = None
                    lst.append(v)
                result['exceptions'] = lst
        return result
    finally:
        ffi.CFRelease(cfdct)

def _get_proxies():
    result = {}
    cfdct = ffi.SCDynamicStoreCopyProxies(None)
    if not cfdct:
        return result
    try:
        for proto in 'HTTP', 'HTTPS', 'FTP', 'Gopher':
            enabled_key = getattr(ffi, 'kSCPropNetProxies' + proto + 'Enable')
            proxy_key = getattr(ffi, 'kSCPropNetProxies' + proto + 'Proxy')
            port_key = getattr(ffi, 'kSCPropNetProxies' + proto + 'Port')
            cfnum = ffi.CFDictionaryGetValue(cfdct, enabled_key)
            if cfnum and cfnum_to_int32(cfnum):
                cfhoststr = ffi.CFDictionaryGetValue(cfdct, proxy_key)
                cfportnum = ffi.CFDictionaryGetValue(cfdct, port_key)
                if cfhoststr:
                    host = cfstring_to_pystring(cfhoststr)
                    if host:
                        if cfportnum:
                            port = cfnum_to_int32(cfportnum)
                            v = u'http://%s:%d' % (host, port)
                        else:
                            v = u'http://%s' % (host,)
                        result[proto.lower()] = v
        return result
    finally:
        ffi.CFRelease(cfdct)