Skip to content

Commit

Permalink
fix: preview of certain files were not shown as text (#1315)
Browse files Browse the repository at this point in the history
e.g. javascript and json
  • Loading branch information
jstucke authored Dec 13, 2024
1 parent 2aa83a0 commit 59ba33c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 7 deletions.
16 changes: 16 additions & 0 deletions src/test/unit/web_interface/test_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest

import web_interface.filter as flt
from test.common_helper import create_test_file_object

UNSORTABLE_LIST = [[], ()]

Expand Down Expand Up @@ -496,3 +497,18 @@ def test_str_to_hex(input_, expected_result):
)
def test_octal_to_readable(input_, include_type, expected_result):
assert flt.octal_to_readable(input_, include_type=include_type) == expected_result


@pytest.mark.parametrize(
('type_analysis', 'expected_result'),
[
({'file_type': {}}, False),
({'file_type': {'result': {'mime': 'image/png'}}}, True),
({'file_type': {'result': {'mime': 'text/plain'}}}, True),
({'file_type': {'result': {'mime': 'application/octet-stream'}}}, False),
({'file_type': {'result': {'mime': 'application/javascript'}}}, True),
],
)
def test_is_text_file_or_image(type_analysis, expected_result):
fo = create_test_file_object(analyses=type_analysis)
assert flt.is_text_file_or_image(fo) == expected_result
11 changes: 8 additions & 3 deletions src/web_interface/components/ajax_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
from web_interface.file_tree.file_tree import remove_virtual_path_from_root
from web_interface.file_tree.file_tree_node import FileTreeNode
from web_interface.file_tree.jstree_conversion import convert_to_jstree_node
from web_interface.filter import bytes_to_str_filter, encode_base64_filter
from web_interface.filter import (
bytes_to_str_filter,
encode_base64_filter,
is_image,
is_text_file,
)
from web_interface.security.decorator import roles_accepted
from web_interface.security.privileges import PRIVILEGES

Expand Down Expand Up @@ -89,12 +94,12 @@ def _get_nice_uid_list_html(self, input_data, root_uid):
def ajax_get_binary(self, mime_type, uid):
mime_type = mime_type.replace('_', '/')
binary = self.intercom.get_binary_and_filename(uid)[0]
if 'text/' in mime_type:
if is_text_file(mime_type):
return (
'<pre class="line_numbering" style="white-space: pre-wrap">'
f'{html.escape(bytes_to_str_filter(binary))}</pre>'
)
if 'image/' in mime_type:
if is_image(mime_type):
return (
'<div style="display: block; border: 1px solid; border-color: #dddddd; padding: 5px; '
f'text-align: center"><img src="data:image/{mime_type[6:]} ;base64,{encode_base64_filter(binary)}" '
Expand Down
1 change: 1 addition & 0 deletions src/web_interface/components/jinja_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ def _setup_filters(self):
'hide_dts_binary_data': flt.hide_dts_binary_data,
'infection_color': flt.infection_color,
'is_list': lambda item: isinstance(item, list),
'is_text_file_or_image': flt.is_text_file_or_image,
'json_dumps': json.dumps,
'link_cve': flt.replace_cve_with_link,
'link_cwe': flt.replace_cwe_with_link,
Expand Down
27 changes: 26 additions & 1 deletion src/web_interface/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from re import Match
from string import ascii_letters
from time import localtime, strftime, struct_time, time
from typing import Iterable, Union
from typing import TYPE_CHECKING, Iterable, Union

import packaging.version
import semver
Expand All @@ -28,6 +28,9 @@
from web_interface.security.authentication import user_has_privilege
from web_interface.security.privileges import PRIVILEGES

if TYPE_CHECKING:
from objects.file import FileObject


def generic_nice_representation(i): # noqa: PLR0911
if isinstance(i, struct_time):
Expand Down Expand Up @@ -557,3 +560,25 @@ def _file_mode_to_type(mode: int) -> str:

def str_to_hex(string: str) -> str:
return string.encode(errors='replace').hex()


KNOWN_TEXT_MIME_TYPES = { # that don't start with text/
'application/javascript',
'application/json',
'application/pgp-keys',
'firmware/intel-hex',
'message/news',
}


def is_text_file(mime: str) -> bool:
return mime.startswith('text/') or mime in KNOWN_TEXT_MIME_TYPES


def is_image(mime: str) -> bool:
return mime.startswith('image/')


def is_text_file_or_image(fo: FileObject) -> bool:
mime = fo.processed_analysis.get('file_type', {}).get('result', {}).get('mime', '')
return is_image(mime) or is_text_file(mime)
4 changes: 1 addition & 3 deletions src/web_interface/templates/show_analysis.html
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,8 @@ <h5 class="modal-title">Add analysis to file</h5>
<div id="preview-content" class="m-0 mt-2 p-0"></div>
</div>

{%- set is_text_preview = firmware.processed_analysis["file_type"]["result"]['mime'][0:5] == "text/" or firmware.processed_analysis["file_type"]["result"]['mime'][0:6] == "image/" %}

<script>
const isTextOrImage = {{ 'true' if is_text_preview else 'false' }};
const isTextOrImage = {{ 'true' if firmware | is_text_file_or_image else 'false' }};
let mimeType = '{{ firmware.processed_analysis["file_type"]["result"]["mime"].replace("/", "_") }}';
</script>
<script type="text/javascript" src="{{ url_for('static', filename='js/show_analysis_preview.js') }}"></script>
Expand Down

0 comments on commit 59ba33c

Please sign in to comment.