From 3ccea22116efd09548aa240a2a911656552d79bb Mon Sep 17 00:00:00 2001 From: Ivan Yelizariev Date: Fri, 12 Mar 2021 09:03:30 +0000 Subject: [PATCH] [FIX] link_tracker: prevent downloading big or non-html files link tracker tries to get title from HTML, but the url may be not an html page or too big html to process. It's a waste of bandwidth, but may also lead to a Server Memory Limit error. As a solution, make HEAD request and don't proceed to GET request if it's not an html page or it's too big. Also, limit page downloading to 50KB. STEPS: - Have a standard database with link_tracker and mass_mailing. - Create a new mass mail MM - Add a link to a large file in MM Mail Body - Click "SEND" - Go to Settings / Technical / Automation / Scheduled Actions - Open the "Process Mass Mailing Queue" or "Email Marketing: Process queue" - Click "RUN MANUALLY" --- opw-2457640 closes odoo/odoo#67948 X-original-commit: bdec63cf97e6904604e9f1e0bf3b6f453b6add60 Signed-off-by: Nicolas Lempereur (nle) Signed-off-by: Ivan Yelizariev // IEL --- addons/link_tracker/models/link_tracker.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/addons/link_tracker/models/link_tracker.py b/addons/link_tracker/models/link_tracker.py index 50b00b9011f..ace848971af 100644 --- a/addons/link_tracker/models/link_tracker.py +++ b/addons/link_tracker/models/link_tracker.py @@ -10,6 +10,8 @@ from werkzeug import urls from odoo import tools, models, fields, api, _ +URL_MAX_SIZE = 10 * 1024 * 1024 + class LinkTracker(models.Model): """ Link trackers allow users to wrap any URL into a short URL that can be @@ -94,7 +96,15 @@ class LinkTracker(models.Model): @api.depends('url') def _get_title_from_url(self, url): try: - page = requests.get(url, timeout=5) + head = requests.head(url, timeout=5) + if ( + int(head.headers.get('Content-Length', 0)) > URL_MAX_SIZE + or + 'text/html' not in head.headers.get('Content-Type', 'text/html') + ): + return url + # HTML parser can work with a part of page, so ask server to limit downloading to 50 KB + page = requests.get(url, timeout=5, headers={"range": "bytes=0-50000"}) p = html.fromstring(page.text.encode('utf-8'), parser=html.HTMLParser(encoding='utf-8')) title = p.find('.//title').text except: