'retrieve(url) returns (filename, headers) for a local object
or (tempfilename, headers) for a remote object.'

def retrieve(self, url, filename=None, reporthook=None, data=None):

    url = unwrap(toBytes(url))
    if (self.tempcache and (url in self.tempcache)):
        return self.tempcache[url]
    else:
        (type, url1) = splittype(url)
        if ((filename is None) and ((not type) or (type == 'file'))):
            try:
                fp = self.open_local_file(url1)
                hdrs = fp.info()
                fp.close()
                return (url2pathname(splithost(url1)[1]), hdrs)
            except IOError:
                pass
        fp = self.open(url, data)
        try:
            headers = fp.info()
            if filename:
                tfp = open(filename, 'wb')
            else:
                import tempfile
                (garbage, path) = splittype(url)
                (garbage, path) = splithost((path or ''))
                (path, garbage) = splitquery((path or ''))
                (path, garbage) = splitattr((path or ''))
                suffix = os.path.splitext(path)[1]
                (fd, filename) = tempfile.mkstemp(suffix)
                self.__tempfiles.append(filename)
                tfp = os.fdopen(fd, 'wb')
            try:
                result = (filename, headers)
                if (self.tempcache is not None):
                    self.tempcache[url] = result
                bs = 8192
                size = (-1)
                read = 0
                blocknum = 0
                if reporthook:
                    if ('content-length' in headers):
                        size = int(headers['Content-Length'])
                    reporthook(blocknum, bs, size)
                while 1:
                    block = fp.read(bs)
                    if (block == ''):
                        break
                    read += len(block)
                    tfp.write(block)
                    blocknum += 1
                    if reporthook:
                        reporthook(blocknum, bs, size)
            finally:
                tfp.close()
        finally:
            fp.close()
        if ((size >= 0) and (read < size)):
            raise ContentTooShortError(('retrieval    incomplete:    got    only    %i    out    of    %i    bytes' % (read, size)), result)
        return result
