JairoDanielMT commited on
Commit
f33d8f5
·
1 Parent(s): 9677463

Handle non-latin1 filename headers

Browse files
Files changed (2) hide show
  1. app/main.py +10 -5
  2. app/renderer.py +19 -1
app/main.py CHANGED
@@ -3,7 +3,7 @@ from __future__ import annotations
3
  import io
4
  import re
5
  import unicodedata
6
- from urllib.parse import quote
7
  from typing import Any, Dict, Literal, Optional
8
 
9
  from fastapi import FastAPI, HTTPException
@@ -97,14 +97,19 @@ def compile_pdf(req: CompileRequest):
97
  safe_base = safe_base.encode("ascii", "ignore").decode("ascii") or "document"
98
  safe_base = re.sub(r"[^A-Za-z0-9_.-]+", "-", safe_base).strip("-") or "document"
99
  filename = f"{safe_base}.pdf"
100
- encoded_name = quote(f"{raw_name}.pdf")
 
 
 
 
 
 
 
101
 
102
  return StreamingResponse(
103
  io.BytesIO(pdf_bytes),
104
  media_type="application/pdf",
105
  headers={
106
- "Content-Disposition": (
107
- f'attachment; filename="{filename}"; filename*=UTF-8\'\'{encoded_name}'
108
- )
109
  },
110
  )
 
3
  import io
4
  import re
5
  import unicodedata
6
+ from urllib.parse import quote_from_bytes
7
  from typing import Any, Dict, Literal, Optional
8
 
9
  from fastapi import FastAPI, HTTPException
 
97
  safe_base = safe_base.encode("ascii", "ignore").decode("ascii") or "document"
98
  safe_base = re.sub(r"[^A-Za-z0-9_.-]+", "-", safe_base).strip("-") or "document"
99
  filename = f"{safe_base}.pdf"
100
+ encoded_name = quote_from_bytes(f"{raw_name}.pdf".encode("utf-8"))
101
+ content_disposition = (
102
+ f'attachment; filename="{filename}"; filename*=UTF-8\'\'{encoded_name}'
103
+ )
104
+ try:
105
+ content_disposition.encode("latin-1")
106
+ except UnicodeEncodeError:
107
+ content_disposition = f'attachment; filename="{filename}"'
108
 
109
  return StreamingResponse(
110
  io.BytesIO(pdf_bytes),
111
  media_type="application/pdf",
112
  headers={
113
+ "Content-Disposition": content_disposition
 
 
114
  },
115
  )
app/renderer.py CHANGED
@@ -1,11 +1,13 @@
1
  from __future__ import annotations
2
 
 
3
  import json
4
  import re
5
  from datetime import datetime
6
  from typing import Any, Dict, Literal, Union
7
 
8
  from jinja2 import Environment, FileSystemLoader, select_autoescape
 
9
  from weasyprint import HTML
10
 
11
  from .config import BASE_DIR
@@ -172,6 +174,22 @@ def _resolve_template(doc: Dict[str, Any]) -> str:
172
  return "InternalModule.html.j2"
173
 
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  # =========================
176
  # RENDER HTML
177
  # =========================
@@ -179,7 +197,7 @@ RenderMode = Literal["html", "pdf"]
179
 
180
 
181
  def render_html(doc: Union[str, Dict[str, Any]], mode: RenderMode = "html") -> str:
182
- doc = normalize_doc(doc)
183
 
184
  template_name = _resolve_template(doc)
185
  template = env.get_template(template_name)
 
1
  from __future__ import annotations
2
 
3
+ import html
4
  import json
5
  import re
6
  from datetime import datetime
7
  from typing import Any, Dict, Literal, Union
8
 
9
  from jinja2 import Environment, FileSystemLoader, select_autoescape
10
+ from markupsafe import Markup
11
  from weasyprint import HTML
12
 
13
  from .config import BASE_DIR
 
174
  return "InternalModule.html.j2"
175
 
176
 
177
+ # =========================
178
+ # SANITIZACIÓN DE TEXTOS
179
+ # =========================
180
+ def _sanitize_doc(value: Any) -> Any:
181
+ if isinstance(value, dict):
182
+ return {key: _sanitize_doc(val) for key, val in value.items()}
183
+ if isinstance(value, list):
184
+ return [_sanitize_doc(val) for val in value]
185
+ if isinstance(value, tuple):
186
+ return tuple(_sanitize_doc(val) for val in value)
187
+ if isinstance(value, str):
188
+ # Escapar etiquetas HTML para evitar que el contenido altere el render.
189
+ return Markup(html.escape(value))
190
+ return value
191
+
192
+
193
  # =========================
194
  # RENDER HTML
195
  # =========================
 
197
 
198
 
199
  def render_html(doc: Union[str, Dict[str, Any]], mode: RenderMode = "html") -> str:
200
+ doc = _sanitize_doc(normalize_doc(doc))
201
 
202
  template_name = _resolve_template(doc)
203
  template = env.get_template(template_name)