Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 1 addition & 70 deletions mfr/extensions/jasp/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
from mfr.core import extension
from mfr.extensions.jasp import exceptions
from zipfile import ZipFile, BadZipFile
from distutils.version import LooseVersion

from .html_processor import HTMLProcessor

class JASPRenderer(extension.BaseRenderer):

# Minimum data archive version supported
MINIMUM_VERSION = LooseVersion('1.0.2')

TEMPLATE = TemplateLookup(
directories=[
os.path.join(os.path.dirname(__file__), 'templates')
Expand All @@ -23,7 +18,6 @@ class JASPRenderer(extension.BaseRenderer):
def render(self):
try:
with ZipFile(self.file_path) as zip_file:
self._check_file(zip_file)
body = self._render_html(zip_file, self.metadata.ext)
return self.TEMPLATE.render(base=self.assets_url, body=body)
except BadZipFile as err:
Expand Down Expand Up @@ -52,73 +46,10 @@ def _render_html(self, zip_file, ext, *args, **kwargs):
'{} Missing index.html.'.format(self.MESSAGE_FILE_CORRUPT),
extension=self.metadata.ext,
corruption_type='key_error',
reason='zip missing ./index.html',
reason='jasp missing ./index.html',
)

processor = HTMLProcessor(zip_file)
processor.feed(index)

return processor.final_html()

def _check_file(self, zip_file):
"""Check if the file is OK (not corrupt)
:param zip_file: an opened ZipFile representing the JASP file
:return: True
"""
# Extract manifest file content
try:
with zip_file.open('META-INF/MANIFEST.MF') as manifest_data:
manifest = manifest_data.read().decode('utf-8')
except KeyError:
raise exceptions.JaspFileCorruptError(
'{} Missing META-INF/MANIFEST.MF'.format(self.MESSAGE_FILE_CORRUPT),
extension=self.metadata.ext,
corruption_type='key_error',
reason='zip missing ./META-INF/MANIFEST.MF',
)

lines = manifest.split('\n')

# Search for Data-Archive-Version
dataArchiveVersionStr, createdBy = None, ''
for line in lines:
keyValue = line.split(':')
if len(keyValue) == 2:
key = keyValue[0].strip()
value = keyValue[1].strip()
if key == 'Data-Archive-Version':
dataArchiveVersionStr = value
elif key == 'Created-By':
createdBy = str(value)
if not dataArchiveVersionStr:
raise exceptions.JaspFileCorruptError(
'{} Data-Archive-Version not found.'.format(self.MESSAGE_FILE_CORRUPT),
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
reason='Data-Archive-Version not found.',
)

# Check that the file is new enough (contains preview content)
dataArchiveVersion = LooseVersion(dataArchiveVersionStr)
try:
if dataArchiveVersion < self.MINIMUM_VERSION:
minimum_version = self.MINIMUM_VERSION.vstring
data_archive_version = dataArchiveVersion.vstring
raise exceptions.JaspVersionError(
'This JASP file was created with an older data archive '
'version ({}) and cannot be previewed. Minimum data archive '
'version is {}.'.format(data_archive_version, minimum_version),
extension=self.metadata.ext,
created_by=createdBy,
actual_version=data_archive_version,
required_version=minimum_version,
)
except TypeError:
raise exceptions.JaspFileCorruptError(
'{} Data-Archive-Version not parsable.'.format(self.MESSAGE_FILE_CORRUPT),
extension=self.metadata.ext,
corruption_type='manifest_parse_error',
reason='Data-Archive-Version ({}) not parsable.'.format(dataArchiveVersionStr),
)

return True
Binary file added tests/extensions/jasp/files/new.jasp
Binary file not shown.
49 changes: 8 additions & 41 deletions tests/extensions/jasp/test_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,12 @@ def ok_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'ok.jasp')

@pytest.fixture
def not_a_zip_file_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'not-a-zip-file.jasp')

@pytest.fixture
def no_manifest_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'no-manifest.jasp')
def new_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'new.jasp')

@pytest.fixture
def no_data_archive_version_in_manifest_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'no-data-archive-version-in-manifest.jasp')

@pytest.fixture
def data_archive_version_is_too_old_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'data-archive-version-is-too-old.jasp')
def not_a_zip_file_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'not-a-zip-file.jasp')

@pytest.fixture
def no_index_html_path():
Expand Down Expand Up @@ -79,33 +71,6 @@ def test_render_JASP_not_a_zip_file(self, metadata, not_a_zip_file_path, url, as

assert False # should not get here

def test_render_JASP_no_manifest(self, metadata, no_manifest_path, url, assets_url, export_url):
try:
renderer = JASPRenderer(metadata, no_manifest_path, url, assets_url, export_url)
renderer.render()
except RendererError:
return

assert False # should not get here

def test_render_JASP_no_data_archive_version_in_manifest(self, metadata, no_data_archive_version_in_manifest_path, url, assets_url, export_url):
try:
renderer = JASPRenderer(metadata, no_data_archive_version_in_manifest_path, url, assets_url, export_url)
renderer.render()
except RendererError:
return

assert False # should not get here

def test_render_JASP_data_archive_is_too_old(self, metadata, data_archive_version_is_too_old_path, url, assets_url, export_url):
try:
renderer = JASPRenderer(metadata, data_archive_version_is_too_old_path, url, assets_url, export_url)
renderer.render()
except RendererError:
return

assert False # should not get here

def test_render_JASP_no_index_html(self, metadata, no_index_html_path, url, assets_url, export_url):
try:
renderer = JASPRenderer(metadata, no_index_html_path, url, assets_url, export_url)
Expand All @@ -121,11 +86,13 @@ def test_render_JASP_contains_malicious_script(self, metadata, contains_maliciou

assert '<script src="link-to-something-malicious.js">' not in body

def test_render_JASP_new(self, metadata, new_path, url, assets_url, export_url):
renderer = JASPRenderer(metadata, new_path, url, assets_url, export_url)
body = renderer.render()
'<div style="word-wrap: break-word; overflow: auto;" class="mfrViewer">' in body

def test_render_JASP_file_required(self, renderer):
assert renderer.file_required is True

def test_render_JASP_cache_result(self, renderer):
assert renderer.cache_result is True