Thanks Nicholas,

The general CF rule is that if you use a function named *Get*, then you don't need to CFRelease; if you use a function named *Copy* or *Create*, you do. So, what you've written looks fine.

With that in mind one further modification seems to be necessary. Take three attached.

~ Daniel

def getproxies_internetconfig():
    """Return a dictionary of scheme -> proxy server URL mappings.
    
    This function has 'internetconfig' in its name for historical reasons only.
    It now uses the more modern 'SystemConfiguration' to obtain its result.
    """
    from ctypes import cdll, byref, c_int, create_string_buffer
    from ctypes.util import find_library

    sc = cdll.LoadLibrary(find_library("SystemConfiguration"))
    
    if not sc:
        return {}

    def CStringFromCFString(value):
        length = sc.CFStringGetLength(value) + 1
        buff = create_string_buffer(length)
        sc.CFStringGetCString(value, buff, length, 0)
        return buff.value

    def CFNumberToInt32(cfnum):
        val = c_int()
        sc.CFNumberGetValue(cfnum, kCFNumberSInt32Type, byref(val))
        return val.value

    kCFNumberSInt32Type = 3
    kSCPropNetProxiesHTTPEnable = sc.CFStringCreateWithCString(0, "HTTPEnable", 0)
    kSCPropNetProxiesHTTPProxy = sc.CFStringCreateWithCString(0, "HTTPProxy", 0)
    kSCPropNetProxiesHTTPPort = sc.CFStringCreateWithCString(0, "HTTPPort", 0)

    proxies = {}
    proxyDict = sc.SCDynamicStoreCopyProxies(None)
    try:
        # HTTP:
        enabled = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPEnable)
        if sc.CFBooleanGetValue(enabled):
            proxy = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPProxy)
            proxy = CStringFromCFString(proxy)
            port = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPPort)
            port = CFNumberToInt32(port)
            proxies["http"] = "http://%s:%i"; % (proxy, port)

        # FTP: XXXX To be done.
        # Gopher: XXXX To be done.
    finally:
        sc.CFRelease(proxyDict)

    sc.CFRelease(kSCPropNetProxiesHTTPEnable)
    sc.CFRelease(kSCPropNetProxiesHTTPProxy)
    sc.CFRelease(kSCPropNetProxiesHTTPPort)

    return proxies


def getproxies_internetconfig_ic():
    """Return a dictionary of scheme -> proxy server URL mappings.

    By convention the mac uses Internet Config to store
    proxies.  An HTTP proxy, for instance, is stored under
    the HttpProxy key.

    """
    from ctypes import cdll, byref, c_void_p, c_int, c_long, create_string_buffer
    from ctypes.util import find_library

    ic = cdll.LoadLibrary(find_library("Internet_Config"))
    if not ic:
        return {}

    proxies = {}
    icReadOnlyPerm = 1
    icinst = c_void_p(None)
    attr = c_int(0)
    ic.ICStart(byref(icinst), 0)
    ic.ICBegin(icinst, icReadOnlyPerm)
    try:
        # HTTP:
        bsize = c_long(255)
        buff = create_string_buffer(255)
        error = ic.ICGetPref(icinst, "\x0cUseHTTPProxy", byref(attr), byref(buff), byref(bsize))
        useHTTPProxy = not error and ord(buff[0])
        if useHTTPProxy:
            bsize = c_long(255)
            error = ic.ICGetPref(icinst, "\rHTTPProxyHost", byref(attr), byref(buff), byref(bsize))
            if not error and bsize.value > 0:
                # not sure why there's an extra character on the beginning of buff
                proxies["http"] = "http://"; + buff.value[1:bsize.value]

        # FTP: XXXX To be done.
        # Gopher: XXXX To be done.
    finally:
        ic.ICEnd(icinst)
        ic.ICStop(icinst)

    return proxies


def getproxies_internetconfig_original():
    """Return a dictionary of scheme -> proxy server URL mappings.

    By convention the mac uses Internet Config to store
    proxies.  An HTTP proxy, for instance, is stored under
    the HttpProxy key.

    """
    try:
        import ic
    except ImportError:
        return {}

    try:
        config = ic.IC()
    except ic.error:
        return {}
    proxies = {}
    # HTTP:
    if 'UseHTTPProxy' in config and config['UseHTTPProxy']:
        try:
            value = config['HTTPProxyHost']
        except ic.error:
            pass
        else:
            proxies['http'] = 'http://%s' % value
    # FTP: XXXX To be done.
    # Gopher: XXXX To be done.
    return proxies


class CtypesLogger(object):
    def __init__(self, lib):
        self.lib = lib
    def __getattr__(self, name):
        class c_func_wrapper(object):
            def __init__(self, func, name):
                self.__dict__["func"] = func
                self.__dict__["name"] = name
            def __getattr__(self, name):
                return getattr(self.func, name)
            def __setattr__(self, name, value):
                setattr(self.func, name, value)
            def __call__(self, *args):
                result = self.func(*args)
                print "%s%s -> %s" % (self.name, args, result)
                return result
        return c_func_wrapper(getattr(self.lib, name), name)


def test1():
    from ctypes import cdll, byref, c_void_p, c_int, c_long, create_string_buffer
    from ctypes.util import find_library

    ic = cdll.LoadLibrary(find_library("Internet_Config"))
    #ic = CtypesLogger(ic)


    icReadOnlyPerm = 1
    icinst = c_void_p(None)
    attr = c_int(0)
    ic.ICStart(byref(icinst), 0)
    ic.ICBegin(icinst, icReadOnlyPerm)
    try:
        bsize = c_long(255)
        buff = create_string_buffer(255)
        result = ic.ICGetPref(icinst, "\x0cUseHTTPProxy", byref(attr), byref(buff), byref(bsize))
        print "%r %s" % (ord(buff[0]), bsize)
    
        bsize = c_long(255)
        result = ic.ICGetPref(icinst, "\rHTTPProxyHost", byref(attr), byref(buff), byref(bsize))
        print "%r %s" % (buff.value, bsize)
    
    finally:
        ic.ICEnd(icinst)
        ic.ICStop(icinst)
        #ic.DisposeHandle(handle)

def test2():
    from ctypes import cdll, byref, cast, c_char, c_void_p, c_int, c_long, create_string_buffer
    from ctypes.util import find_library

    sc = cdll.LoadLibrary(find_library("SystemConfiguration"))
    #sc = CtypesLogger(sc)

    def create_cfstringref(cstr):
        return sc.CFStringCreateWithCString(0, cstr, 0)

    kCFNumberSInt32Type = 3
    kSCPropNetProxiesHTTPEnable = create_cfstringref("HTTPEnable")
    kSCPropNetProxiesHTTPProxy = create_cfstringref("HTTPProxy")
    kSCPropNetProxiesHTTPPort = create_cfstringref("HTTPPort")
    
    def CStringFromCFString(value):
        length = sc.CFStringGetLength(value) + 1
        buff = create_string_buffer(length)
        sc.CFStringGetCString(value, buff, length, 0)
        return buff.value

    def CFNumberToInt32(cfnum):
        val = c_int()
        sc.CFNumberGetValue(cfnum, kCFNumberSInt32Type, byref(val))
        return val.value

    proxyDict = sc.SCDynamicStoreCopyProxies(None)
    try:
        num = sc.CFDictionaryGetCount(proxyDict)
        pointer_array_type = c_void_p * num
        keys = pointer_array_type()
        vals = pointer_array_type()
        sc.CFDictionaryGetKeysAndValues(proxyDict, keys, vals)
        for i in xrange(num):
            key = CStringFromCFString(keys[i])
            print "%r = %r" % (key, vals[i])

        enabled = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPEnable)
        if sc.CFBooleanGetValue(enabled):
            proxy = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPProxy)
            proxy = CStringFromCFString(proxy)
            port = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPPort)
            port = CFNumberToInt32(port)
            
        #print CStringFromCFString(val)
    finally:
        sc.CFRelease(proxyDict)

#     icReadOnlyPerm = 1
#     icinst = c_void_p(None)
#     attr = c_int(0)
#     ic.ICStart(byref(icinst), 0)
#     ic.ICBegin(icinst, icReadOnlyPerm)
#     try:
#         bsize = c_long(255)
#         buff = create_string_buffer(255)
#         result = ic.ICGetPref(icinst, "\x0cUseHTTPProxy", byref(attr), byref(buff), byref(bsize))
#         print "%r %s" % (ord(buff[0]), bsize)
#     
#         bsize = c_long(255)
#         result = ic.ICGetPref(icinst, "\rHTTPProxyHost", byref(attr), byref(buff), byref(bsize))
#         print "%r %s" % (buff.value, bsize)
#     
#     finally:
#         ic.ICEnd(icinst)
#         ic.ICStop(icinst)
#         #ic.DisposeHandle(handle)

test2()

print getproxies_internetconfig()
_______________________________________________
Pythonmac-SIG maillist  -  Pythonmac-SIG@python.org
http://mail.python.org/mailman/listinfo/pythonmac-sig

Reply via email to