| 41 | |
| 42 | |
| 43 | class DownloadInstance(object): |
| 44 | _registered_instances = [] |
| 45 | _response = b"" |
| 46 | _data = b"" |
| 47 | |
| 48 | class Response: |
| 49 | def __init__(self, status_code, headers, content): |
| 50 | self.status_code = status_code |
| 51 | self.headers = headers |
| 52 | self.content = content |
| 53 | |
| 54 | def __init__(self, provider, handle=None): |
| 55 | if handle is None: |
| 56 | self._cb = core.BNDownloadInstanceCallbacks() |
| 57 | self._cb.context = 0 |
| 58 | self._cb.destroyInstance = self._cb.destroyInstance.__class__(self._destroy_instance) |
| 59 | self._cb.performRequest = self._cb.performRequest.__class__(self._perform_request) |
| 60 | self._cb.performCustomRequest = self._cb.performCustomRequest.__class__(self._perform_custom_request) |
| 61 | self._cb.freeResponse = self._cb.freeResponse.__class__(self._free_response) |
| 62 | self.handle = core.BNInitDownloadInstance(provider.handle, self._cb) |
| 63 | self.__class__._registered_instances.append(self) |
| 64 | else: |
| 65 | self.handle = core.handle_of_type(handle, core.BNDownloadInstance) |
| 66 | self._must_free = handle is not None |
| 67 | |
| 68 | def __del__(self): |
| 69 | if self._must_free: |
| 70 | core.BNFreeDownloadInstance(self.handle) |
| 71 | |
| 72 | def _destroy_instance(self, ctxt): |
| 73 | try: |
| 74 | if self in self.__class__._registered_instances: |
| 75 | self.__class__._registered_instances.remove(self) |
| 76 | self.perform_destroy_instance() |
| 77 | except: |
| 78 | log_error(traceback.format_exc()) |
| 79 | |
| 80 | def _perform_request(self, ctxt, url): |
| 81 | try: |
| 82 | return self.perform_request(url) |
| 83 | except: |
| 84 | log_error(traceback.format_exc()) |
| 85 | return -1 |
| 86 | |
| 87 | def _perform_custom_request(self, ctxt, method, url, header_count, header_keys, header_values, response): |
| 88 | # Cast response to an array of length 1 so ctypes can write to the pointer |
| 89 | # out_response = ((BNDownloadInstanceResponse*)[1])response |
| 90 | out_response = (ctypes.POINTER(core.BNDownloadInstanceResponse) |
| 91 | * 1).from_address(ctypes.addressof(response.contents)) # type: ignore |
| 92 | try: |
| 93 | # Extract headers |
| 94 | keys_ptr = ctypes.cast(header_keys, ctypes.POINTER(ctypes.c_char_p)) |
| 95 | values_ptr = ctypes.cast(header_values, ctypes.POINTER(ctypes.c_char_p)) |
| 96 | header_key_array = (ctypes.c_char_p * header_count).from_address(ctypes.addressof(keys_ptr.contents)) |
| 97 | header_value_array = (ctypes.c_char_p * header_count).from_address(ctypes.addressof(values_ptr.contents)) |
| 98 | headers = {} |
| 99 | for i in range(header_count): |
| 100 | headers[header_key_array[i]] = header_value_array[i] |