# -*- coding: utf-8 -*- """ Block ALL outgoing HTTP requests to Odoo-related domains. This patches the requests library to intercept and block external calls. """ import logging import requests from functools import wraps from urllib.parse import urlparse _logger = logging.getLogger(__name__) # Domains to block - all Odoo external services BLOCKED_DOMAINS = [ 'odoo.com', 'odoofin.com', 'odoo.sh', 'iap.odoo.com', 'iap-services.odoo.com', 'partner-autocomplete.odoo.com', 'iap-extract.odoo.com', 'iap-sms.odoo.com', 'upgrade.odoo.com', 'apps.odoo.com', 'production.odoofin.com', 'plaid.com', 'yodlee.com', 'gravatar.com', 'www.gravatar.com', 'secure.gravatar.com', ] # Store original functions _original_request = None _original_get = None _original_post = None def _is_blocked_url(url): """Check if the URL should be blocked.""" if not url: return False try: parsed = urlparse(url) domain = parsed.netloc.lower() for blocked in BLOCKED_DOMAINS: if blocked in domain: return True except Exception: pass return False def _blocked_request(method, url, **kwargs): """Intercept and block requests to Odoo domains.""" if _is_blocked_url(url): _logger.warning("HTTP REQUEST BLOCKED: %s %s", method.upper(), url) # Return a mock response response = requests.models.Response() response.status_code = 200 response._content = b'{}' response.headers['Content-Type'] = 'application/json' return response return _original_request(method, url, **kwargs) def _blocked_get(url, **kwargs): """Intercept and block GET requests.""" if _is_blocked_url(url): _logger.warning("HTTP GET BLOCKED: %s", url) response = requests.models.Response() response.status_code = 200 response._content = b'{}' response.headers['Content-Type'] = 'application/json' return response return _original_get(url, **kwargs) def _blocked_post(url, **kwargs): """Intercept and block POST requests.""" if _is_blocked_url(url): _logger.warning("HTTP POST BLOCKED: %s", url) response = requests.models.Response() response.status_code = 200 response._content = b'{}' response.headers['Content-Type'] = 'application/json' return response return _original_post(url, **kwargs) def patch_requests(): """Monkey-patch requests library to block Odoo domains.""" global _original_request, _original_get, _original_post try: if _original_request is None: _original_request = requests.Session.request _original_get = requests.get _original_post = requests.post # Patch Session.request (catches most calls) def patched_session_request(self, method, url, **kwargs): if _is_blocked_url(url): _logger.warning("HTTP SESSION REQUEST BLOCKED: %s %s", method.upper(), url) response = requests.models.Response() response.status_code = 200 response._content = b'{}' response.headers['Content-Type'] = 'application/json' response.request = requests.models.PreparedRequest() response.request.url = url response.request.method = method return response return _original_request(self, method, url, **kwargs) requests.Session.request = patched_session_request requests.get = _blocked_get requests.post = _blocked_post _logger.info("HTTP requests to Odoo domains have been BLOCKED") _logger.info("Blocked domains: %s", ', '.join(BLOCKED_DOMAINS)) except Exception as e: _logger.warning("Could not patch requests library: %s", e) # Apply patch when module is imported patch_requests()