app-validator/appvalidator/submain.py

131 строка
3.9 KiB
Python

import logging
import os
import signal
from zipfile import BadZipfile
from zlib import error as zlib_error
import testcases
from .webapp import detect_webapp
from .zip import ZipPackage
from constants import *
log = logging.getLogger()
class ValidationTimeout(Exception):
def __init__(self, timeout):
self.timeout = timeout
def __str__(self):
return "Validation timeout after %d seconds" % self.timeout
def prepare_package(err, path, timeout=None):
"""Prepares a file-based package for validation.
timeout is the number of seconds before validation is aborted.
If timeout is -1 then no timeout checking code will run.
"""
if not timeout:
timeout = DEFAULT_TIMEOUT # seconds
# Test that the package actually exists. I consider this Tier 0
# since we may not even be dealing with a real file.
if not os.path.isfile(path):
return err.error(
err_id=("main", "prepare_package", "not_found"),
error="The package could not be found")
# Pop the package extension.
package_extension = os.path.splitext(path)[1]
package_extension = package_extension.lower()
if package_extension == ".webapp":
detect_webapp(err, path)
return err
validation_state = {'complete': False}
def timeout_handler(signum, frame):
if validation_state['complete']:
# There is no need for a timeout. This might be the result of
# sequential validators, like in the test suite.
return err
ex = ValidationTimeout(timeout)
log.error("%s; Package: %s" % (str(ex), path), exc_info=True)
raise ex
with open(path, "rb") as package:
if timeout != -1:
signal.signal(signal.SIGALRM, timeout_handler)
signal.setitimer(signal.ITIMER_REAL, timeout)
test_package(err, package, path)
validation_state['complete'] = True
return err
def write_zip_error(err):
return err.error(
err_id=("submain", "badzipfile"),
error="Corrupt ZIP file",
description="We were unable to decompress all or part of the zip "
"file.")
def test_package(err, file_, name):
"""Begins tests for the package."""
# Load up a new instance of a package.
try:
package = ZipPackage(file_, mode="r", name=name)
except IOError:
# Die on this one because the file won't open.
return err.error(
err_id=("main", "test_package", "unopenable"),
error="The package could not be opened.")
except (BadZipfile, zlib_error):
# Die if the zip file is corrupt.
return write_zip_error(err)
try:
output = test_inner_package(err, package)
except ValidationTimeout as ex:
err.error(
err_id=("main", "test_package", "timeout"),
error="Validation timed out",
description=["The validation process took too long to complete. "
"Contact an Firefox Marketplace reviewer for more "
"information.", str(ex)])
output = None
return output
def test_inner_package(err, package):
"""Tests a package's inner content."""
# Iterate through each tier.
for tier in sorted(testcases._get_tiers()):
# Let the error bundler know what tier we're on.
err.set_tier(tier)
# Iterate through each test of our detected type.
try:
for test in testcases._get_tests(tier):
test(err, package)
except (BadZipfile, zlib_error):
write_zip_error(err)
# Return any errors at the end of the tier if undetermined.
if err.failed(fail_on_warnings=False) and not err.determined:
err.unfinished = True
err.discard_unused_messages(ending_tier=tier)
return err
# Return the results.
return err