def test_can_get_image_when_auth_okay(self):
        config = webapp.get_debug_config("kdu")
        config["authorizer"] = {"impl": "loris.authorizer.NullAuthorizer"}
        app = webapp.Loris(config)

        client = Client(application=webapp.Loris(config),
                        response_wrapper=BaseResponse)

        resp = client.get("/%s/full/full/0/default.jpg" % self.test_jpeg_id)
        assert resp.status_code == 200
Example #2
0
    def test_cannot_get_info_when_auth_required(self):
        config = webapp.get_debug_config("kdu")
        config["authorizer"] = {"impl": "loris.authorizer.NooneAuthorizer"}
        app = webapp.Loris(config)

        client = Client(application=webapp.Loris(config),
                        response_wrapper=BaseResponse)

        resp = client.get("/%s/info.json" % self.test_jpeg_id)
        assert resp.status_code == 401
Example #3
0
    def test_can_edit_embedded_color_profile(self):
        # By default, LorisTest uses the Kakadu transformer.  Switch to the
        # OPENJPEG transformer before we get the reference image.
        config = get_debug_config('opj')
        self.build_client_from_config(config)

        self._assert_can_edit_embedded_color_profile(
            ident=self.test_jp2_with_embedded_profile_id,
            transformer='jp2',
            debug_config='opj')
Example #4
0
 def test_hung_process_gets_terminated(self):
     config = get_debug_config('opj')
     config['transforms']['jp2']['opj_decompress'] = '/dev/null'
     config['transforms']['jp2']['timeout'] = 1
     self.build_client_from_config(config)
     ident = self.test_jp2_color_id
     request_path = '/%s/full/full/0/default.jpg' % ident
     response = self.client.get(request_path)
     assert response.status_code == 500
     assert 'JP2 transform process timed out' in response.data.decode(
         'utf8')
Example #5
0
 def test_kdu_expand_error(self):
     config = get_debug_config('kdu')
     config['transforms']['jp2']['kdu_expand'] = 'lorisrandomzzz/kdu_expand'
     config['transforms']['jp2']['timeout'] = 1
     self.build_client_from_config(config)
     ident = self.test_jp2_color_id
     request_path = '/%s/full/full/0/default.jpg' % ident
     response = self.client.get(request_path)
     assert response.status_code == 500
     assert 'Server Side Error: error generating derivative image: see log (500)' in response.data.decode(
         'utf8')
Example #6
0
 def test_respects_pil_max_image_pixels(self):
     default_max_pixels = Image.MAX_IMAGE_PIXELS
     try:
         config = get_debug_config('kdu')
         config['transforms']['pil_max_image_pixels'] = 1
         self.build_client_from_config(config)
         with pytest.raises(Image.DecompressionBombError):
             request_path = '/%s/full/300,300/0/default.jpg' % self.ident
             self.request_image_from_client(request_path)
     finally:
         # Because we have to mutate a value in an external library
         # it must be reset at the end of this test
         Image.MAX_IMAGE_PIXELS = default_max_pixels
Example #7
0
    def test_editing_embedded_color_profile_failure_is_not_error(self):
        ident = self.test_jpeg_with_embedded_cmyk_profile_id
        request_path = '/%s/full/full/0/default.jpg' % ident

        image_orig = self.request_image_from_client(request_path)

        # Set up an instance of the client with color profile editing.
        # We need to disable caching so the new request doesn't pick up
        # the cached image.
        config = get_debug_config('kdu')
        config['transforms']['jpg']['map_profile_to_srgb'] = True
        config['transforms']['jpg']['srgb_profile_fp'] = self.srgb_color_profile_fp
        config['loris.Loris']['enable_caching'] = False
        self.build_client_from_config(config)

        image_converted = self.request_image_from_client(request_path)

        # Now fetch the image, and check that it remains unmodified.
        self.assertEqual(image_orig.histogram(), image_converted.histogram())
Example #8
0
    def test_sends_content_disposition_header_for_image(self):
        config = webapp.get_debug_config("kdu")
        app = webapp.Loris(config)

        client = Client(application=webapp.Loris(config),
                        response_wrapper=BaseResponse)

        jpg_resp = client.get("/%s/full/full/0/default.jpg" %
                              self.test_jpeg_id)

        expected_filename = os.path.relpath(self.test_jpeg_fp,
                                            self.test_img_dir)

        assert jpg_resp.headers["Content-Disposition"] == (
            "filename*=utf-8''%s" % expected_filename)

        png_resp = client.get("/%s/full/full/0/default.png" %
                              self.test_jpeg_id)

        assert png_resp.headers["Content-Disposition"] == (
            "filename*=utf-8''%s.png" % expected_filename)
Example #9
0
    def _assert_can_edit_embedded_color_profile(self, ident, transformer, debug_config='kdu'):
        request_path = '/%s/full/full/0/default.jpg' % ident

        image_orig = self.request_image_from_client(request_path)

        # Set up an instance of the client with color profile editing.
        # We need to disable caching so the new request doesn't pick up
        # the cached image.
        config = get_debug_config(debug_config)
        config['transforms'][transformer]['map_profile_to_srgb'] = True
        config['transforms'][transformer]['srgb_profile_fp'] = self.srgb_color_profile_fp
        config['loris.Loris']['enable_caching'] = False
        self.build_client_from_config(config)

        image_converted = self.request_image_from_client(request_path)

        # Now check that the image pixels have been edited -- this means
        # that the color profile has changed.  Because image conversion
        # isn't stable across platforms, this is the best we can do for now.
        # TODO: Maybe try image hashing here?
        self.assertNotEqual(image_orig.histogram(), image_converted.histogram())
Example #10
0
    def setUp(self):
        self.URI_BASE = 'http://localhost'

        #for SimpleHTTPResolver
        self.SRC_IMAGE_CACHE = '/tmp/loris/cache/src_images'

        # create an instance of the app here that we can use in tests
        # see http://werkzeug.pocoo.org/docs/test/
        config = get_debug_config('kdu')
        config['logging']['log_level'] = 'INFO'
        self.build_client_from_config(config)

        # constant info about test images.
        self.test_img_dir = path.join(path.abspath(path.dirname(__file__)), 'img')
        self.test_img_dir2 = path.join(path.abspath(path.dirname(__file__)), 'img2')
        test_json_dir = path.join(path.abspath(path.dirname(__file__)), 'json')
        test_icc_dir = path.join(path.abspath(path.dirname(__file__)), 'icc')

        self.test_jp2_color_fp = path.join(self.test_img_dir,'01','02','0001.jp2')
        self.test_jp2_color_info_fp = path.join(test_json_dir,'01','02','0001.jp2','info.json')
        self.test_jp2_color_fmt = 'jp2'
        self.test_jp2_color_id = '01%2F02%2F0001.jp2'
        self.test_jp2_color_uri = '%s/%s' % (self.URI_BASE, self.test_jp2_color_id)
        self.test_jp2_color_dims = (5906,7200)
        self.test_jp2_color_levels = 6
        self.test_jp2_color_tiles = [
            { "width": 256, "scaleFactors": [1,2,4,8,16,32,64] }
        ]
        self.test_jp2_color_sizes =  [
            { "height": 113, "width": 93 },
            { "height": 225, "width": 185 },
            { "height": 450, "width": 370 },
            { "height": 900, "width": 739 },
            { "height": 1800, "width": 1477 },
            { "height": 3600, "width": 2953 },
            { "height": 7200, "width": 5906 }
        ]

        self.test_jp2_gray_fp = path.join(self.test_img_dir,'01','02','gray.jp2')
        self.test_jp2_gray_fmt = 'jp2'
        self.test_jp2_gray_id = '01%2F02%2Fgray.jp2'
        self.test_jp2_gray_uri = '%s/%s' % (self.URI_BASE,self.test_jp2_gray_id)
        self.test_jp2_gray_dims = (2477,3200) # w,h
        self.test_jp2_gray_sizes =  [
            { "height": 50, "width": 39 },
            { "height": 100, "width": 78 },
            { "height": 200, "width": 155 },
            { "height": 400, "width": 310 },
            { "height": 800, "width": 620 },
            { "height": 1600, "width": 1239 },
            { "height": 3200, "width": 2477 }
        ]
        self.test_jp2_gray_tiles = [
            { "width": 256, "scaleFactors": [1,2,4,8,16,32,64] }
        ]

        self.test_jpeg_fp = path.join(self.test_img_dir,'01','03','0001.jpg')
        self.test_jpeg_fmt = 'jpg'
        self.test_jpeg_id = '01%2F03%2F0001.jpg'
        self.test_jpeg_uri = '%s/%s' % (self.URI_BASE,self.test_jpeg_id)
        self.test_jpeg_dims = (3600,2987) # w,h
        self.test_jpeg_sizes = []

        self.test_jpeg_grid_fp = path.join(self.test_img_dir, 'black_white_grid.jpg')
        self.test_jpeg_grid_id = 'black_white_grid.jpg'
        self.test_jpeg_grid_dims = (120, 120)

        self.test_tiff_fp = path.join(self.test_img_dir,'01','04','0001.tif')
        self.test_tiff_fmt = 'tif'
        self.test_tiff_id = '01%2F04%2F0001.tif'
        self.test_tiff_uri = '%s/%s' % (self.URI_BASE,self.test_tiff_id)
        self.test_tiff_dims = (839,1080)
        self.test_tiff_sizes = []

        self.test_png_fp = path.join(self.test_img_dir,'henneken.png')
        self.test_png_fp2 = path.join(self.test_img_dir2,'henneken.png')
        self.test_png_fmt = 'png'
        self.test_png_id = 'henneken.png'
        self.test_png_uri = '%s/%s' % (self.URI_BASE,self.test_png_id)
        self.test_png_dims = (504,360) # w,h
        self.test_png_sizes = []

        self.test_altpng_id = 'foo.png'
        self.test_altpng_fp = path.join(self.test_img_dir2,'foo.png')

        self.test_jp2_with_embedded_profile_id = '47102787.jp2'
        self.test_jp2_with_embedded_profile_fp = path.join(self.test_img_dir,self.test_jp2_with_embedded_profile_id)
        self.test_jp2_embedded_profile_copy_fp = path.join(test_icc_dir,'profile.icc')
        self.test_jp2_with_embedded_profile_fmt = 'jp2'
        self.test_jp2_with_embedded_profile_uri = '%s/%s' % (self.URI_BASE,self.test_jp2_with_embedded_profile_id)

        # A copy of 47102787.jp2, with the embedded color profile converted
        # to sRGB and saved as JPG.
        self.test_jp2_with_embedded_profile_to_srgb_jpg_fp = path.join(
            self.test_img_dir, '47102787_to_srgb.jpg'
        )

        self.test_jpeg_with_embedded_profile_id = 'jpeg_with_p3_profile.jpg'
        self.test_jpeg_with_embedded_profile_fp = path.join(self.test_img_dir, self.test_jpeg_with_embedded_profile_id)

        # A JPEG with an embedded CMYK profile.  Public domain image downloaded
        # from https://commons.wikimedia.org/wiki/File:Frog_logo_CMYK.jpg
        self.test_jpeg_with_embedded_cmyk_profile_id = 'jpeg_with_cmyk_profile.jpg'

        self.test_jp2_with_precincts_id = 'sul_precincts.jp2'
        self.test_jp2_with_precincts_fp = path.join(self.test_img_dir,self.test_jp2_with_precincts_id)
        self.test_jp2_with_precincts_fmt = 'jp2'
        self.test_jp2_with_precincts_uri = '%s/%s' % (self.URI_BASE,self.test_jp2_with_precincts_id)
        self.test_jp2_with_precincts_sizes =  [
            { "height": 93, "width": 71 },
            { "height": 186, "width": 141 },
            { "height": 372, "width": 281 },
            { "height": 743, "width": 561 },
            { "height": 1486, "width": 1122 },
            { "height": 2972, "width": 2244 },
            { "height": 5944, "width": 4488 }
        ]
        self.test_jp2_with_precincts_tiles = [
            { "width": 128, "scaleFactors": [1,2,4,8,16] },
            { "width": 256, "scaleFactors": [32,64] }
        ]

        # An ICC v2 sRGB color profile.
        # Downloaded from http://www.color.org/srgbprofiles.xalter
        self.srgb_color_profile_fp = path.join(test_icc_dir, 'sRGB2014.icc')
Example #11
0
 def test_invalid_tmp_dir_is_configerror(self):
     config = get_debug_config('kdu')
     config["loris.Loris"]["tmp_dp"] = "/dev/null/tmp"
     with pytest.raises(ConfigError,
                        match="Error creating tmp_dp /dev/null/tmp:"):
         Loris(config)
Example #12
0
 def test_can_be_configured_with_authorizer(self):
     config = webapp.get_debug_config("kdu")
     config["authorizer"] = {"impl": "loris.authorizer.NullAuthorizer"}
     app = webapp.Loris(config)
     assert isinstance(app.authorizer, NullAuthorizer)
Example #13
0
 def test_can_be_configured_without_authorizer_impl(self):
     config = webapp.get_debug_config("kdu")
     del config["authorizer"]["impl"]
     app = webapp.Loris(config)
     assert app.authorizer is None
Example #14
0
 def test_debug_config_gives_openjpeg_transformer(self):
     config = webapp.get_debug_config('opj')
     app = webapp.Loris(config)
     assert isinstance(app.transformers['jp2'], OPJ_JP2Transformer)
Example #15
0
 def test_debug_config_gives_kakadu_transformer(self):
     config = webapp.get_debug_config('kdu')
     app = webapp.Loris(config)
     assert isinstance(app.transformers['jp2'], KakaduJP2Transformer)
Example #16
0
 def test_unrecognized_debug_config_is_configerror(self):
     with pytest.raises(ConfigError) as err:
         webapp.get_debug_config('no_such_jp2_transformer')
     assert 'Unrecognized debug JP2 transformer' in str(err.value)
Example #17
0
    def setUp(self):
        self.URI_BASE = 'http://localhost'

        #for SimpleHTTPResolver
        self.SRC_IMAGE_CACHE = '/tmp/loris/cache/src_images'

        # create an instance of the app here that we can use in tests
        # see http://werkzeug.pocoo.org/docs/test/
        config = get_debug_config('kdu')
        config['logging']['log_level'] = 'INFO'
        self.app = Loris(config)
        self.client = Client(self.app, BaseResponse)

        # constant info about test images.
        self.test_img_dir = path.join(path.abspath(path.dirname(__file__)),
                                      'img')
        self.test_img_dir2 = path.join(path.abspath(path.dirname(__file__)),
                                       'img2')
        test_json_dir = path.join(path.abspath(path.dirname(__file__)), 'json')
        test_icc_dir = path.join(path.abspath(path.dirname(__file__)), 'icc')

        self.test_jp2_color_fp = path.join(self.test_img_dir, '01', '02',
                                           '0001.jp2')
        self.test_jp2_color_info_fp = path.join(test_json_dir, '01', '02',
                                                '0001.jp2', 'info.json')
        self.test_jp2_color_fmt = 'jp2'
        self.test_jp2_color_id = '01%2F02%2F0001.jp2'
        self.test_jp2_color_uri = '%s/%s' % (self.URI_BASE,
                                             self.test_jp2_color_id)
        self.test_jp2_color_dims = (5906, 7200)
        self.test_jp2_color_levels = 6
        self.test_jp2_color_tiles = [{
            "width": 256,
            "scaleFactors": [1, 2, 4, 8, 16, 32, 64]
        }]
        self.test_jp2_color_sizes = [{
            "height": 113,
            "width": 93
        }, {
            "height": 225,
            "width": 185
        }, {
            "height": 450,
            "width": 370
        }, {
            "height": 900,
            "width": 739
        }, {
            "height": 1800,
            "width": 1477
        }, {
            "height": 3600,
            "width": 2953
        }, {
            "height": 7200,
            "width": 5906
        }]

        self.test_jp2_gray_fp = path.join(self.test_img_dir, '01', '02',
                                          'gray.jp2')
        self.test_jp2_gray_fmt = 'jp2'
        self.test_jp2_gray_id = '01%2F02%2Fgray.jp2'
        self.test_jp2_gray_uri = '%s/%s' % (self.URI_BASE,
                                            self.test_jp2_gray_id)
        self.test_jp2_gray_dims = (2477, 3200)  # w,h
        self.test_jp2_gray_sizes = [{
            "height": 50,
            "width": 39
        }, {
            "height": 100,
            "width": 78
        }, {
            "height": 200,
            "width": 155
        }, {
            "height": 400,
            "width": 310
        }, {
            "height": 800,
            "width": 620
        }, {
            "height": 1600,
            "width": 1239
        }, {
            "height": 3200,
            "width": 2477
        }]
        self.test_jp2_gray_tiles = [{
            "width": 256,
            "scaleFactors": [1, 2, 4, 8, 16, 32, 64]
        }]

        self.test_jpeg_fp = path.join(self.test_img_dir, '01', '03',
                                      '0001.jpg')
        self.test_jpeg_fmt = 'jpg'
        self.test_jpeg_id = '01%2F03%2F0001.jpg'
        self.test_jpeg_uri = '%s/%s' % (self.URI_BASE, self.test_jpeg_id)
        self.test_jpeg_dims = (3600, 2987)  # w,h
        self.test_jpeg_sizes = []

        self.test_tiff_fp = path.join(self.test_img_dir, '01', '04',
                                      '0001.tif')
        self.test_tiff_fmt = 'tif'
        self.test_tiff_id = '01%2F04%2F0001.tif'
        self.test_tiff_uri = '%s/%s' % (self.URI_BASE, self.test_tiff_id)
        self.test_tiff_dims = (839, 1080)
        self.test_tiff_sizes = []

        self.test_png_fp = path.join(self.test_img_dir, 'henneken.png')
        self.test_png_fp2 = path.join(self.test_img_dir2, 'henneken.png')
        self.test_png_fmt = 'png'
        self.test_png_id = 'henneken.png'
        self.test_png_uri = '%s/%s' % (self.URI_BASE, self.test_png_id)
        self.test_png_dims = (504, 360)  # w,h
        self.test_png_sizes = []

        self.test_altpng_id = 'foo.png'
        self.test_altpng_fp = path.join(self.test_img_dir2, 'foo.png')

        self.test_jp2_with_embedded_profile_id = '47102787.jp2'
        self.test_jp2_with_embedded_profile_fp = path.join(
            self.test_img_dir, self.test_jp2_with_embedded_profile_id)
        self.test_jp2_embedded_profile_copy_fp = path.join(
            test_icc_dir, 'profile.icc')
        self.test_jp2_with_embedded_profile_fmt = 'jp2'
        self.test_jp2_with_embedded_profile_uri = '%s/%s' % (
            self.URI_BASE, self.test_jp2_with_embedded_profile_id)

        self.test_jp2_with_precincts_id = 'sul_precincts.jp2'
        self.test_jp2_with_precincts_fp = path.join(
            self.test_img_dir, self.test_jp2_with_precincts_id)
        self.test_jp2_with_precincts_fmt = 'jp2'
        self.test_jp2_with_precincts_uri = '%s/%s' % (
            self.URI_BASE, self.test_jp2_with_precincts_id)
        self.test_jp2_with_precincts_sizes = [{
            "height": 93,
            "width": 71
        }, {
            "height": 186,
            "width": 141
        }, {
            "height": 372,
            "width": 281
        }, {
            "height": 743,
            "width": 561
        }, {
            "height": 1486,
            "width": 1122
        }, {
            "height": 2972,
            "width": 2244
        }, {
            "height": 5944,
            "width": 4488
        }]
        self.test_jp2_with_precincts_tiles = [{
            "width": 128,
            "scaleFactors": [1, 2, 4, 8, 16]
        }, {
            "width": 256,
            "scaleFactors": [32, 64]
        }]