fix(preview): improve file content handling

Refined how file content is displayed in the preview, distinguishing and safely handling text, Markdown, and image files. Introduced proper escaping for non-Markdown text files to prevent potential security issues.
This commit is contained in:
Kumi 2024-06-19 10:48:28 +02:00
parent a179e2999f
commit dce9c4d3b0
Signed by: kumi
GPG key ID: ECBCC9082395383F
2 changed files with 18 additions and 7 deletions

View file

@ -5,6 +5,7 @@ import logging
import os
import base64
import mimetypes
import html
from pathlib import Path
logger = logging.getLogger(__name__)
@ -164,9 +165,15 @@ def preview_file(owner: str, repo: str, file_path: str):
file_content = git.get_file_content(file_path)
content_type, _ = mimetypes.guess_type(file_path)
is_text = content_type and content_type.startswith("text")
try:
file_content.decode("utf-8")
is_text = True
except UnicodeDecodeError:
is_text = False
is_image = content_type and content_type.startswith("image")
is_safe = False
is_raw = True
if content_type == "text/markdown":
base_url = f"/{owner}/{repo}/raw/main/{'/'.join(file_path.split('/')[:-1])}".rstrip(
@ -175,7 +182,11 @@ def preview_file(owner: str, repo: str, file_path: str):
file_content = RelativeURLRewriter(base_url).convert(
file_content.decode("utf-8")
)
is_safe = True
is_raw = False
elif is_text:
file_content = file_content.decode("utf-8")
file_content = html.escape(file_content)
if is_image:
file_content = base64.b64encode(file_content).decode("utf-8")
@ -188,7 +199,7 @@ def preview_file(owner: str, repo: str, file_path: str):
file_content=file_content,
is_text=is_text,
is_image=is_image,
is_safe=is_safe,
is_raw=is_raw,
)
except Exception as e:
logger.error(f"Error previewing file {file_path} in {owner}/{repo}: {e}")

View file

@ -14,10 +14,10 @@
<div class="card">
<div class="card-body">
{% if is_text %}
{% if is_safe %}
<div>{{ file_content | safe }}</div>
{% if is_raw %}
<pre>{{ file_content | safe }}</pre>
{% else %}
<pre>{{ file_content }}</pre>
<div>{{ file_content | safe }}</div>
{% endif %}
{% elif is_image %}
<img src="data:image/png;base64,{{ file_content }}" class="img-fluid" alt="{{ file_path }}">