diff --git a/lookyloo/lookyloo.py b/lookyloo/lookyloo.py index 5132fb19..6d548822 100644 --- a/lookyloo/lookyloo.py +++ b/lookyloo/lookyloo.py @@ -913,9 +913,15 @@ class Lookyloo(): error_img: Path = get_homedir() / 'website' / 'web' / 'static' / 'error_screenshot.png' to_thumbnail = Image.open(error_img) except UnidentifiedImageError as e: - # The capture probably doesn't have a screenshot at all, no need to log that as a warning. - self.logger.debug(f'Unable to generate the screenshot thumbnail of {capture_uuid}: {e}.') - error_img = get_homedir() / 'website' / 'web' / 'static' / 'error_screenshot.png' + # We might have a direct download link, and no screenshot. Assign the thumbnail accordingly. + try: + filename, data = self.get_data(capture_uuid) + self.logger.info(f'{capture_uuid} is is a download link, set thumbnail.') + error_img = get_homedir() / 'website' / 'web' / 'static' / 'download.png' + except Exception: + # The capture probably doesn't have a screenshot at all, no need to log that as a warning. + self.logger.debug(f'Unable to generate the screenshot thumbnail of {capture_uuid}: {e}.') + error_img = get_homedir() / 'website' / 'web' / 'static' / 'error_screenshot.png' to_thumbnail = Image.open(error_img) to_thumbnail.thumbnail(size) diff --git a/website/web/sri.txt b/website/web/sri.txt index 9459e922..afe0a2ae 100644 --- a/website/web/sri.txt +++ b/website/web/sri.txt @@ -12,6 +12,7 @@ "datatables.min.js": "8ua4soo5FXHNIbuX9zDsc7L/JOQE5q5tqJ+GOofQN4/8sDnJ3l5zNj54dIWKoppTfrthPBjetweH/PPf97P/bg==", "down.jpg": "LHRHJ5yCaSjNcDfEoChGIfh7K5HrMYbaGn7EOlxgZ8GoLIwb0nFBkpoOMG9gMHA/pBX2skkXMukvKJC6P6FBGg==", "down_left.jpg": "UwHkJaZGayY1LewuFM3bJHQCUPG1vYyrVeiGG5mCM9MD9FtAhdbD4hBY3JZNDWv93CXeEAbxL1kqEeHTKnyquQ==", + "download.png": "J8y1gDKURf3AhgYDuqCnfaVLKRG2MI6k37xSvR5pJBAZ3aNmA6dDw6+UGf65hLBN3eGksaBJUeroBW/LDlUTqQ==", "download.svg": "8Dmi0Z56+uecmE4mW03JEP6IdxeFFaQcUgdnqAzrYbVLED0YxnQTuiKqn5qeLZNlK1XQpGnDC47YzHvE7zAKig==", "empty.svg": "6tfMLNzDFV9P6t1rC2tDRQtOGzrxi/VtIBc8aV0jo4i3u+dn1fIe3/fySBFA6z13n+XjISF5bTRUNBsN3LWinQ==", "error_screenshot.png": "IkUKnQ47PYYreukA7Byvx+5ACkcCvqk+jYD0GZoQznsD9qDPWrKAMZxlIku7G3Re19vehIlYawep/THcV/ruTA==", @@ -35,7 +36,7 @@ "stats.css": "/kY943FwWBTne4IIyf7iBROSfbGd82TeBicEXqKkRwawMVRIvM/Pk5MRa7okUyGIxaDjFQGmV/U1vy+PhN6Jbw==", "stats_graph.js": "0OEouA6NAxLG2wMd7D2vtGoMrXKna7My98Euc6ecyfdO4/6mIJS87vzISOS4zSZ8u4ehpa+p7E0nWhsXXE7H/Q==", "tree.css": "R/pWQnE8kMacDrzGy/NpA1tJoHAZpOjFiX6dqtBe+PqAnhYMn1CIQzODh8Ifvh6hBTPLRWX3bsabfEvfaI7Z6A==", - "tree.js": "jvaOjno3+4vX3Caam4PSXeZf4G3o9uh8whfOsND2zTfDxLQwo1P+umNQQx7JDPsf5Fan7tHDGOnBTupb9CjLlA==", + "tree.js": "67R8M7znCyonDtD3GdqyF7uq4p18SLWB/BSwR1dK45M63SHmksENlBEPl9WS3OepzmnfW8q00sH/UBEWqGE8rQ==", "up.jpg": "d1ljZJ9f5JekyM6RLFFH2Ua44j6neiQBdUIXOenRTjGppQr3JaeglpQIH6BjPCJL177+TH52U3UIRNS5YAyKIg==", "up_right.jpg": "OMmz+n+MxR34P8/fn5t4DkqKqdJRzQbXQ7fAi2lhkZIJGhVs2vIyY1f2hpYoBxDAX1OcYsSE2lqIR2vXNDGZsA==", "video.png": "gJtmkfr8I1Kw43pYEKjg6CAjgmhl1vIBKBQ3ZkxCu3wvxQm+6kf93iLrrFiY2WuiXzxEn2Leu52GJzmVN5id0g==", diff --git a/website/web/static/download.png b/website/web/static/download.png new file mode 100644 index 00000000..95391725 Binary files /dev/null and b/website/web/static/download.png differ diff --git a/website/web/static/tree.js b/website/web/static/tree.js index fda8f2ec..7650b17c 100644 --- a/website/web/static/tree.js +++ b/website/web/static/tree.js @@ -582,82 +582,53 @@ function update(root, computed_node_width=0) { const thumbnail_size = 64; if (d.data.contains_rendered_urlnode) { center_node = d.data.uuid; - if (d.data.downloaded_filename) { - d3.select(this).append("svg").append('rect') - .attr('x', selected_node_bbox.width/3) - .attr('y', node_height - 3) - .attr('width', thumbnail_size) - .attr('height', thumbnail_size) - .attr('fill', 'white') - .attr('stroke', 'black'); - + if (favicon) { d3.select(this).append('image') - .attr('x', selected_node_bbox.width/3) - .attr('y', node_height - 3) - .attr('id', 'screenshot_thumbnail') - .attr("width", thumbnail_size) - .attr("height", thumbnail_size) - .attr("xlink:href", '/static/download.svg') - .on('mouseover', (event, d) => { - d3.select('#tooltip') - .style('opacity', 1) - .style('left', `${event.pageX + 10}px`) - .style('top', `${event.pageY + 10}px`) - .text(`Contains the downloaded file (${d.data.downloaded_filename}).`); - }) - .on('mouseout', (event, d) => { - d3.select('#tooltip').style('opacity', 0) - }); - } else { - if (favicon) { - d3.select(this).append('image') - .attr('x', selected_node_bbox.width/6) - .attr('y', node_height - 1) - .attr('id', 'favicon') - .attr("width", 32) - .attr("height", 32) - .attr("xlink:href", `data:image/png;base64,${favicon}`) - .attr('cursor', 'pointer') - .on('mouseover', (event, d) => { - d3.select('#tooltip') - .style('opacity', 1) - .style('left', `${event.pageX + 10}px`) - .style('top', `${event.pageY + 10}px`) - .text('Potential favicon.'); - }); - } - if (screenshot_thumbnail) { - d3.select(this).append("svg").append('rect') - .attr('x', selected_node_bbox.width/2) - .attr('y', node_height - 3) - .attr('width', thumbnail_size) - .attr('height', thumbnail_size) - .attr('fill', 'white') - .attr('stroke', 'black'); - - d3.select(this).append('image') - .attr('x', selected_node_bbox.width/2) - .attr('y', node_height - 3) - .attr('id', 'screenshot_thumbnail') - .attr("width", thumbnail_size) - .attr("height", thumbnail_size) - .attr("xlink:href", `data:image/png;base64,${screenshot_thumbnail}`) - .attr('cursor', 'pointer') - .on('mouseover', (event, d) => { - d3.select('#tooltip') - .style('opacity', 1) - .style('left', `${event.pageX + 10}px`) - .style('top', `${event.pageY + 10}px`) - .text('Contains the URL rendered in the browser.'); - }) - .on('click', (event, d) => { - $("#screenshotModal").modal('toggle'); - }) - .on('mouseout', (event, d) => { - d3.select('#tooltip').style('opacity', 0) - }); - } + .attr('x', selected_node_bbox.width/6) + .attr('y', node_height - 1) + .attr('id', 'favicon') + .attr("width", 32) + .attr("height", 32) + .attr("xlink:href", `data:image/png;base64,${favicon}`) + .attr('cursor', 'pointer') + .on('mouseover', (event, d) => { + d3.select('#tooltip') + .style('opacity', 1) + .style('left', `${event.pageX + 10}px`) + .style('top', `${event.pageY + 10}px`) + .text('Potential favicon.'); + }); } + d3.select(this).append("svg").append('rect') + .attr('x', selected_node_bbox.width/2) + .attr('y', node_height - 3) + .attr('width', thumbnail_size) + .attr('height', thumbnail_size) + .attr('fill', 'white') + .attr('stroke', 'black'); + + d3.select(this).append('image') + .attr('x', selected_node_bbox.width/2) + .attr('y', node_height - 3) + .attr('id', 'screenshot_thumbnail') + .attr("width", thumbnail_size) + .attr("height", thumbnail_size) + .attr("xlink:href",`data:image/png;base64,${screenshot_thumbnail}`) + .attr('cursor', 'pointer') + .on('mouseover', (event, d) => { + d3.select('#tooltip') + .data(d) + .style('opacity', 1) + .style('left', `${event.pageX + 10}px`) + .style('top', `${event.pageY + 10}px`) + .text(d => d.data.downloaded_filename ? 'Contains the URL rendered in the browser. It also downloaded a file.': 'Contains the URL rendered in the browser.'); + }) + .on('click', (event, d) => { + $("#screenshotModal").modal('toggle'); + }) + .on('mouseout', (event, d) => { + d3.select('#tooltip').style('opacity', 0) + }); }; const http_icon_size = 24; diff --git a/website/web/templates/hostname_popup.html b/website/web/templates/hostname_popup.html index 012b7592..f2ecfe2d 100644 --- a/website/web/templates/hostname_popup.html +++ b/website/web/templates/hostname_popup.html @@ -241,17 +241,20 @@ {{ popup_icons_response(url['url_object'], tree_uuid) }} {% if url['url_object'].downloaded_filename %} +