diff --git a/lookyloo/lookyloo.py b/lookyloo/lookyloo.py index a168d1dd..719c3ba7 100644 --- a/lookyloo/lookyloo.py +++ b/lookyloo/lookyloo.py @@ -880,13 +880,13 @@ class Lookyloo(): return known, legitimate - def get_ressource(self, tree_uuid: str, urlnode_uuid: str, h: Optional[str]) -> Optional[Tuple[str, BytesIO]]: + def get_ressource(self, tree_uuid: str, urlnode_uuid: str, h: Optional[str]) -> Optional[Tuple[str, BytesIO, str]]: url = self.get_urlnode_from_tree(tree_uuid, urlnode_uuid) if url.empty_response: return None if not h or h == url.body_hash: # we want the body - return url.filename if url.filename else 'file.bin', url.body + return url.filename if url.filename else 'file.bin', url.body, url.mimetype # We want an embedded ressource if h not in url.resources_hashes: @@ -894,7 +894,7 @@ class Lookyloo(): for mimetype, blobs in url.embedded_ressources.items(): for ressource_h, blob in blobs: if ressource_h == h: - return 'embedded_ressource.bin', blob + return 'embedded_ressource.bin', blob, mimetype return None def misp_export(self, capture_uuid: str) -> Union[MISPEvent, Dict[str, str]]: diff --git a/website/web/__init__.py b/website/web/__init__.py index 81aa7347..88b5108d 100644 --- a/website/web/__init__.py +++ b/website/web/__init__.py @@ -603,7 +603,7 @@ def get_ressource(tree_uuid: str, node_uuid: str): to_return = BytesIO() with ZipFile(to_return, 'w', ZIP_DEFLATED) as zfile: if ressource: - filename, r = ressource + filename, r, mimetype = ressource zfile.writestr(filename, r.getvalue()) else: zfile.writestr('file.txt', b'Unknown Hash') @@ -612,6 +612,22 @@ def get_ressource(tree_uuid: str, node_uuid: str): as_attachment=True, attachment_filename='file.zip') +@app.route('/tree//url//ressource_preview', methods=['POST', 'GET']) +def get_ressource_preview(tree_uuid: str, node_uuid: str): + if request.method == 'POST': + h_request = request.form.get('ressource_hash') + else: + h_request = None + ressource = lookyloo.get_ressource(tree_uuid, node_uuid, h_request) + if not ressource: + return None + filename, r, mimetype = ressource + if mimetype.startswith('image'): + return send_file(r, mimetype=mimetype, + as_attachment=True, attachment_filename=filename) + return None + + @app.route('/tree//url//hashes', methods=['GET']) def hashes_urlnode(tree_uuid: str, node_uuid: str): hashes = lookyloo.get_hashes(tree_uuid, urlnode_uuid=node_uuid) diff --git a/website/web/static/tree.css b/website/web/static/tree.css index 6e602de9..9c39d219 100644 --- a/website/web/static/tree.css +++ b/website/web/static/tree.css @@ -130,6 +130,14 @@ z-index: 2; } +.tooltip img { + background: white; + border: 1px solid #ddd; + border-radius: 4px; + padding: 5px; + width: 150px; +} + hr { display: block; margin-top: 0.1em; diff --git a/website/web/templates/hostname_popup.html b/website/web/templates/hostname_popup.html index 9caadff3..c059c055 100644 --- a/website/web/templates/hostname_popup.html +++ b/website/web/templates/hostname_popup.html @@ -61,7 +61,13 @@ }); }); - + {% endblock %} {% block content %} diff --git a/website/web/templates/macros.html b/website/web/templates/macros.html index be2ef023..08b613b8 100644 --- a/website/web/templates/macros.html +++ b/website/web/templates/macros.html @@ -255,8 +255,12 @@ {{ key }} {% elif key in ["js", "exe", "css", "font", "html", "json", "image", "video", "unknown_mimetype", "text", "unset_mimetype", "octet-stream", "livestream"] and not urlnode.empty_response %} - - {{ key }} + + {{ key }}
Click to download the content of the response in a zip file' + {% endif %} + />
{% elif key != "redirect" %} {{ key }}