diff --git a/docker/Dockerfile b/docker/Dockerfile index 831627ec8..a1dc565f4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -51,7 +51,7 @@ ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 \ RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ - curl jq bash tzdata fontconfig tini libmagic1 \ + curl jq bash tzdata fontconfig tini libmagic1 media-types \ libcairo2 libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf-2.0-0 \ libharfbuzz0b libfreetype6 libjpeg62-turbo zlib1g fonts-dejavu-core; \ if [ "$WITH_GRAPHVIZ" = "1" ]; then apt-get install -y --no-install-recommends graphviz; fi; \ diff --git a/docker/config/nginx/sapl.conf b/docker/config/nginx/sapl.conf index 7e0802ef1..926adc37d 100644 --- a/docker/config/nginx/sapl.conf +++ b/docker/config/nginx/sapl.conf @@ -66,7 +66,7 @@ server { # Demais arquivos são públicos e servidos direto do disco; conteúdo que o # navegador executaria como página é forçado a download. - location ~* ^/media/.+\.(html?|xhtml|xht|shtml|svgz?|xml|xsl|xslt|rdf|js|mjs|mht|mhtml|rss|atom|mml)$ { + location ~* ^/media/.+\.(html?|xhtml|xht|shtml|svgz?|xml|xsl|xslt|rdf|js|mjs|mht|mhtml|rss|atom|mml|kml|xspf)$ { root /var/interlegis/sapl; types { } default_type application/octet-stream; diff --git a/sapl/base/tests/test_media.py b/sapl/base/tests/test_media.py index ee7a27446..de4ac7c94 100644 --- a/sapl/base/tests/test_media.py +++ b/sapl/base/tests/test_media.py @@ -17,6 +17,7 @@ from sapl.base.models import AppConfig, Autor from sapl.materia.models import Proposicao from sapl.protocoloadm.models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo) +from sapl.utils import EXTENSOES_ATIVAS DOC_PATH = 'sapl/private/documentoadministrativo/2026/1/texto.pdf' ACESSORIO_PATH = 'sapl/public/documentoacessorioadministrativo/2026/1/a.pdf' @@ -237,7 +238,7 @@ def test_arquivo_publico_passa_por_x_accel(client): @pytest.mark.django_db(transaction=False) @pytest.mark.parametrize('nome', ['x.svg', 'x.html', 'x.XML', 'x.js', - 'x.xht', 'x.rdf', 'x.xslt']) + 'x.xht', 'x.rdf', 'x.xslt', 'x.kml']) def test_arquivo_publico_ativo_e_baixado(client, nome): response = _get(client, 'sapl/public/normajuridica/2026/1/' + nome) @@ -363,3 +364,21 @@ def test_nginx_envia_ao_django_todos_os_caminhos_protegidos(): no_nginx = set(regex.group(1).split('|')) assert set(RESOLVEDORES) | set(MODELOS_DE_SESSAO) <= no_nginx assert conf.index(regex.group(0)) < conf.index('location /media/ {') + + +def test_nginx_forca_download_das_extensoes_ativas(): + caminho = os.path.join(settings.PROJECT_DIR, 'docker', 'config', + 'nginx', 'sapl.conf') + with open(caminho) as f: + conf = f.read() + regex = re.search(r'location ~\*? \^/media/\.\+\\\.\(([a-z?|]+)\)\$', + conf) + + assert regex, 'location de extensões ativas não encontrada' + no_nginx = set() + for ext in regex.group(1).split('|'): + if ext.endswith('?'): + no_nginx |= {ext[:-2], ext[:-1]} + else: + no_nginx.add(ext) + assert {'.' + e for e in no_nginx} == EXTENSOES_ATIVAS diff --git a/sapl/test_utils.py b/sapl/test_utils.py index f3956c8fe..1bb724056 100644 --- a/sapl/test_utils.py +++ b/sapl/test_utils.py @@ -43,6 +43,7 @@ ATIVOS = [ ('x.XHTML', b'%PDF-1.4'), ('x.xht', b'%PDF-1.4\n'), ('x.rdf', b'%PDF-1.4'), + ('x.kml', b''), ('x.pdf', b''), ] diff --git a/sapl/utils.py b/sapl/utils.py index fca09b993..532594801 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -603,10 +603,13 @@ class FilterOverridesMetaMixin: } -# Extensões que o navegador pode executar como página na origem do SAPL +# Extensões que o navegador pode executar como página na origem do SAPL. +# Não depender só de mimetypes: sem /etc/mime.types (imagem slim) várias +# destas não são reconhecidas. Manter em sincronia com sapl.conf. EXTENSOES_ATIVAS = { - '.html', '.htm', '.xhtml', '.shtml', '.svg', '.svgz', '.xml', '.xsl', - '.js', '.mht', '.mhtml', + '.html', '.htm', '.xhtml', '.xht', '.shtml', '.svg', '.svgz', '.xml', + '.xsl', '.xslt', '.rdf', '.js', '.mjs', '.mht', '.mhtml', '.rss', '.atom', + '.mml', '.kml', '.xspf', } MIMES_ATIVOS = {