diff --git a/CHANGES.txt b/CHANGES.txt index f2d4345..cd9e9ce 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -42,12 +42,13 @@ * 1.1.2: Added keep JPEG quality option and set JPEG subsampling to keep * 1.1.3: Fix auto rotation on JPEG with missing Exif data * 1.1.4: Exception handling around invalid Exif data - * 1.1.5: Fix image requests without content types + * 1.1.5: Fixed image requests without content types * 1.1.6: Support custom applications that need command line arguments * 1.1.7: Support adapt resize mode - * 1.1.8: Add preserve Exif flag - * 1.1.9: Increase Pillow version to 2.8.1 - * 1.1.10: Add ca_certs option + * 1.1.8: Added preserve Exif flag + * 1.1.9: Increased Pillow version to 2.8.1 + * 1.1.10: Added ca_certs option * 1.1.11: Added support for TIFF * 1.2.0: Support setting background when saving a transparent image - *Backwards incompatible*: default background property changed to `0fff`. To restore previous behavior, set background in config to `ffff`. + * 1.2.1: Added max operations config property diff --git a/README.rst b/README.rst index 5ae315a..7e2adfd 100644 --- a/README.rst +++ b/README.rst @@ -137,6 +137,7 @@ To see a list of all available options, run --filter default filter to use when resizing --help show this help information --implicit_base_url prepend protocol/host to url paths + --max_operations maximum operations to perform (default 10) --max_requests max concurrent requests (default 40) --operation default operation to perform --optimize default to optimize when saving @@ -609,14 +610,14 @@ Changelog - 1.1.0: Proxy server support - 1.1.1: Added JPEG auto rotation based on Exif orientation - 1.1.2: Added keep JPEG quality option and set JPEG subsampling to keep -- 1.1.3: Fix auto rotation on JPEG with missing Exif data +- 1.1.3: Fixed auto rotation on JPEG with missing Exif data - 1.1.4: Exception handling around invalid Exif data -- 1.1.5: Fix image requests without content types +- 1.1.5: Fixed image requests without content types - 1.1.6: Support custom applications that need command line arguments - 1.1.7: Support adapt resize mode -- 1.1.8: Add preserve Exif flag -- 1.1.9: Increase Pillow version to 2.8.1 -- 1.1.10: Add ca_certs option +- 1.1.8: Added preserve Exif flag +- 1.1.9: Increased Pillow version to 2.8.1 +- 1.1.10: Added ca_certs option - 1.1.11: Added support for TIFF - 1.2.0: Support setting background when saving a transparent image @@ -624,6 +625,8 @@ Changelog ``0fff``. To restore previous behavior, set background in config to ``ffff``. +- 1.2.1: Added max operations config property + TODO ==== diff --git a/pilbox/__init__.py b/pilbox/__init__.py index a8ef4d9..a2a70e0 100644 --- a/pilbox/__init__.py +++ b/pilbox/__init__.py @@ -61,26 +61,27 @@ * 1.1.0: Proxy server support * 1.1.1: Added JPEG auto rotation based on Exif orientation * 1.1.2: Added keep JPEG quality option and set JPEG subsampling to keep - * 1.1.3: Fix auto rotation on JPEG with missing Exif data + * 1.1.3: Fixed auto rotation on JPEG with missing Exif data * 1.1.4: Exception handling around invalid Exif data - * 1.1.5: Fix for images requests without content types + * 1.1.5: Fixed image requests without content types * 1.1.6: Support custom applications that need command line arguments * 1.1.7: Support adapt resize mode - * 1.1.8: Add preserve Exif flag - * 1.1.9: Increase Pillow version to 2.8.1 - * 1.1.10: Add ca_certs option + * 1.1.8: Added preserve Exif flag + * 1.1.9: Increased Pillow version to 2.8.1 + * 1.1.10: Added ca_certs option * 1.1.11: Added support for TIFF * 1.2.0: Support setting background when saving a transparent image * *Backwards incompatible*: default background property changed to `0fff`. To restore previous behavior, set background in config to `ffff`. + * 1.2.1: Added max operations config property """ # human-readable version number -version = "1.2.0" +version = "1.2.1" # The first three numbers are the components of the version number. # The fourth is zero for an official release, positive for a development # branch, or negative for a release candidate or beta (after the base version # number has been incremented) -version_info = (1, 2, 0, 0) +version_info = (1, 2, 1, 0) diff --git a/pilbox/app.py b/pilbox/app.py index d3678a9..949801d 100755 --- a/pilbox/app.py +++ b/pilbox/app.py @@ -54,6 +54,7 @@ define("client_key", help="client key") define("allowed_hosts", help="valid hosts", default=[], multiple=True) define("allowed_operations", help="valid ops", default=[], multiple=True) +define("max_operations", help="maximum operations to perform", default=10) # request related settings define("max_requests", help="max concurrent requests", type=int, default=40) @@ -98,6 +99,7 @@ def __init__(self, **kwargs): allowed_hosts=options.allowed_hosts, allowed_operations=set( options.allowed_operations or ImageHandler.OPERATIONS), + max_operations=options.max_operations, background=options.background, expand=options.expand, filter=options.filter, @@ -297,6 +299,8 @@ def _validate_operation(self): operations = set(self._get_operations()) if not operations.issubset(self.settings.get("allowed_operations")): raise errors.OperationError("Unsupported operation") + elif len(operations) > self.settings.get("max_operations"): + raise errors.OperationError("Too many operations") def _validate_url(self): url = self.get_argument("url") diff --git a/pilbox/test/app_test.py b/pilbox/test/app_test.py index 8d91397..60a0ebf 100644 --- a/pilbox/test/app_test.py +++ b/pilbox/test/app_test.py @@ -436,6 +436,33 @@ def test_valid_default_operation(self): self.assertEqual(resp.buffer.read(), expected.read(), msg) +class AppMaxOperationsTest(AsyncHTTPTestCase, _AppAsyncMixin): + def get_app(self): + return _PilboxTestApplication(max_operations=1) + + def test_invalid_max_operations(self): + qs = urlencode(dict( + url=self.get_url("/test/data/test1.jpg"), + op="resize,rotate", + deg=180, + w=100, + h=100 + )) + resp = self.fetch_error(400, "/?%s" % qs) + self.assertEqual(resp.get("error_code"), + errors.OperationError.get_code()) + + def test_valid_max_operations(self): + url = self.get_url("/test/data/test1.jpg") + qs = urlencode(dict(url=url, op="noop")) + resp = self.fetch_success("/?%s" % qs) + expected_path = os.path.join( + os.path.dirname(__file__), "data", "test1.jpg") + msg = "/?%s does not match %s" % (qs, expected_path) + with open(expected_path, "rb") as expected: + self.assertEqual(resp.buffer.read(), expected.read(), msg) + + class AppOverrideContentTypeTest(AsyncHTTPTestCase, _AppAsyncMixin): def get_app(self): return _PilboxTestApplication(content_type_from_image=True) diff --git a/setup.py b/setup.py index 66312e3..c897c6a 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def run(self): setup(name='pilbox', - version='1.2.0', + version='1.2.1', description='Pilbox is an image processing application server built on the Tornado web framework using the Pillow Imaging Library', long_description=readme, classifiers=[