def test_thumbor_can_decrypt_lib_thumbor_generated_url():
    key = "my-security-key"
    image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg"
    thumbor_crypto = Cryptor(key)

    crypto = CryptoURL(key=key)

    url = crypto.generate(
        width=300,
        height=200,
        smart=True,
        image_url=image,
        old=True
    )

    reg = "/([^/]+)/(.+)"
    options = re.match(reg, url).groups()[0]

    decrypted_url = thumbor_crypto.decrypt(options)

    assert decrypted_url
    assert decrypted_url['height'] == 200
    assert decrypted_url['width'] == 300
    assert decrypted_url['smart']
    assert decrypted_url['image_hash'] == hashlib.md5(image).hexdigest()
Exemple #2
0
def test_usage():
    key = "my-security-key"
    image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg"
    thumbor_crypto = Cryptor(key)

    thumbor_options = thumbor_crypto.encrypt(width=300,
                                             height=200,
                                             smart=True,
                                             adaptive=False,
                                             full=False,
                                             fit_in=False,
                                             flip_horizontal=False,
                                             flip_vertical=False,
                                             halign='center',
                                             valign='middle',
                                             trim=None,
                                             crop_left=0,
                                             crop_top=0,
                                             crop_right=0,
                                             crop_bottom=0,
                                             filters=[],
                                             image=image)
    thumbor_url = "/%s/%s" % (thumbor_options, image)

    crypto = CryptoURL(key=key)

    url = crypto.generate(width=300,
                          height=200,
                          smart=True,
                          image_url=image,
                          old=True)

    assert url == thumbor_url
Exemple #3
0
def test_decrypting_combinations():
    cryptor = Cryptor('my-security-key')
    for test in DECRYPT_TESTS:
        base_copy = copy.copy(BASE_PARAMS)
        base_copy.update(test['params'])
        encrypted = cryptor.encrypt(**base_copy)
        yield decrypted_result_should_match, cryptor.decrypt(encrypted), test['result']
Exemple #4
0
 def topic(self):
     cryptor = Cryptor('my-security-key')
     for test in DECRYPT_TESTS:
         base_copy = copy.copy(BASE_PARAMS)
         base_copy.update(test['params'])
         encrypted = cryptor.encrypt(**base_copy)
         yield (cryptor.decrypt(encrypted), test['result'])
Exemple #5
0
 def topic(self):
     cryptor = Cryptor('my-security-key')
     for test in DECRYPT_TESTS:
         base_copy = copy.copy(BASE_PARAMS)
         base_copy.update(test['params'])
         encrypted = cryptor.encrypt(**base_copy)
         yield(cryptor.decrypt(encrypted), test['result'])
Exemple #6
0
    def get(self, **kw):
        url = self.request.uri

        if not self.validate(kw["image"]):
            self._error(404, "No original image was specified in the given URL")
            return

        self.context.request = RequestParameters(**kw)

        self.context.request.unsafe = self.context.request.unsafe == "unsafe"

        if self.request.query:
            self.context.request.image_url += "?%s" % self.request.query
        self.context.request.image_url = quote(self.context.request.image_url, "/:?%=&")

        has_none = not self.context.request.unsafe and not self.context.request.hash
        has_both = self.context.request.unsafe and self.context.request.hash

        if has_none or has_both:
            self._error(404, "URL does not have hash or unsafe, or has both: %s" % url)
            return

        if self.context.request.unsafe and not self.context.config.ALLOW_UNSAFE_URL:
            self._error(404, "URL has unsafe but unsafe is not allowed by the config: %s" % url)
            return

        url_signature = self.context.request.hash
        if url_signature:
            signer = Signer(self.context.server.security_key)

            url_to_validate = url.replace("/%s/" % self.context.request.hash, "")
            valid = signer.validate(url_signature, url_to_validate)

            if not valid and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE:
                # Retrieves security key for this image if it has been seen before
                security_key = self.context.modules.storage.get_crypto(self.context.request.image_url)
                if security_key is not None:
                    signer = Signer(security_key)
                    valid = signer.validate(url_signature, url_to_validate)

            if not valid:
                is_valid = True
                if self.context.config.ALLOW_OLD_URLS:
                    cr = Cryptor(self.context.server.security_key)
                    options = cr.get_options(self.context.request.hash, self.context.request.image_url)
                    if options is None:
                        is_valid = False
                    else:
                        self.context.request = RequestParameters(**options)
                        logger.warning(
                            "OLD FORMAT URL DETECTED!!! This format of URL will be discontinued in upcoming versions. Please start using the new format as soon as possible. More info at https://github.com/globocom/thumbor/wiki/3.0.0-release-changes"
                        )
                else:
                    is_valid = False

                if not is_valid:
                    self._error(404, "Malformed URL: %s" % url)
                    return

        return self.execute_image_operations()
def test_usage():
    key = "my-security-key"
    image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg"
    thumbor_crypto = Cryptor(key)

    thumbor_options = thumbor_crypto.encrypt(
        width=300,
        height=200,
        smart=True,
        adaptive=False,
        fit_in=False,
        flip_horizontal=False,
        flip_vertical=False,
        halign='center',
        valign='middle',
        crop_left=0,
        crop_top=0,
        crop_right=0,
        crop_bottom=0,
        filters=[],
        image=image
    )
    thumbor_url = "/%s/%s" % (thumbor_options, image)

    crypto = CryptoURL(key=key)

    url = crypto.generate(
        width=300,
        height=200,
        smart=True,
        image_url=image,
        old=True
    )

    assert url == thumbor_url
Exemple #8
0
    def test_decrypting_with_wrong_key(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        cryptor = Cryptor(security_key="simething")
        wrong = cryptor.decrypt(encrypted_str)
        right = self.cryptor.decrypt(encrypted_str)
        expect(wrong['image_hash']).not_to_equal(str(right['image_hash']))
Exemple #9
0
def test_decrypting_combinations():
    cryptor = Cryptor('my-security-key')
    for test in DECRYPT_TESTS:
        base_copy = copy.copy(BASE_PARAMS)
        base_copy.update(test['params'])
        encrypted = cryptor.encrypt(**base_copy)
        yield decrypted_result_should_match, cryptor.decrypt(
            encrypted), test['result']
Exemple #10
0
    def test_decrypting_with_wrong_key(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        cryptor = Cryptor(security_key="simething")
        wrong = cryptor.decrypt(encrypted_str)
        right = self.cryptor.decrypt(encrypted_str)
        expect(wrong['image_hash']).not_to_equal(str(right['image_hash']))
Exemple #11
0
    def test_get_options_from_storage(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(
                STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True
            ),
            modules=mock.Mock(
                storage=mock_storage
            ),
        )

        mock_storage.get_crypto.return_value = custom_security_key

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).not_to_be_null()

        expected_options = {
            'trim': 'trim', 'full': False, 'halign': 'center', 'fit_in': False,
            'vertical_flip': True, 'image': '/some/image.jpg',
            'crop': {'top': 11, 'right': 12, 'bottom': 13, 'left': 10},
            'height': 300, 'width': 300, 'meta': False, 'horizontal_flip': True,
            'filters': 'some_filter()', 'valign': 'middle', 'debug': False,
            'hash': 'e2baf424fa420b73a97476956dfb858f', 'adaptive': False, 'smart': True
        }

        expect(options).to_be_like(expected_options)
Exemple #12
0
 def setUp(self, *args, **kw):
     super(CryptoTestCase, self).setUp(*args, **kw)
     self.cryptor = Cryptor(security_key="something")
     self.cryptor.context = mock.Mock(
         config=mock.Mock(
             STORES_CRYPTO_KEY_FOR_EACH_IMAGE=False
         ),
     )
Exemple #13
0
    def test_get_options_from_storage_returns_null_if_key_not_found(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(
                STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True
            ),
            modules=mock.Mock(
                storage=mock_storage
            ),
        )

        mock_storage.get_crypto.return_value = None

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()
Exemple #14
0
def test_thumbor_can_decrypt_lib_thumbor_generated_url():
    key = "my-security-key"
    image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg"
    thumbor_crypto = Cryptor(key)

    crypto = CryptoURL(key=key)

    url = crypto.generate(width=300,
                          height=200,
                          smart=True,
                          image_url=image,
                          old=True)

    reg = "/([^/]+)/(.+)"
    options = re.match(reg, url).groups()[0]

    decrypted_url = thumbor_crypto.decrypt(options)

    assert decrypted_url
    assert decrypted_url['height'] == 200
    assert decrypted_url['width'] == 300
    assert decrypted_url['smart']
    assert decrypted_url['image_hash'] == hashlib.md5(image).hexdigest()
Exemple #15
0
    def test_get_options_from_storage_returns_null_if_key_not_found(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True),
            modules=mock.Mock(storage=mock_storage),
        )

        mock_storage.get_crypto.return_value = None

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()
Exemple #16
0
    def get(self, **kw):
        url = self.request.uri

        if not self.validate(kw['image']):
            self._error(404,
                        'No original image was specified in the given URL')
            return

        self.context.request = RequestParameters(**kw)

        self.context.request.unsafe = self.context.request.unsafe == 'unsafe'

        if (self.request.query):
            self.context.request.image_url += '?%s' % self.request.query
        self.context.request.image_url = self.encode_url(
            self.context.request.image_url.encode('utf-8'))

        has_none = not self.context.request.unsafe and not self.context.request.hash
        has_both = self.context.request.unsafe and self.context.request.hash

        if has_none or has_both:
            self._error(
                404, 'URL does not have hash or unsafe, or has both: %s' % url)
            return

        if self.context.request.unsafe and not self.context.config.ALLOW_UNSAFE_URL:
            self._error(
                404,
                'URL has unsafe but unsafe is not allowed by the config: %s' %
                url)
            return

        url_signature = self.context.request.hash
        if url_signature:
            signer = Signer(self.context.server.security_key)

            url_to_validate = self.encode_url(url).replace(
                '/%s/' % self.context.request.hash, '')
            valid = signer.validate(url_signature, url_to_validate)

            if not valid and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE:
                # Retrieves security key for this image if it has been seen before
                security_key = self.context.modules.storage.get_crypto(
                    self.context.request.image_url)
                if security_key is not None:
                    signer = Signer(security_key)
                    valid = signer.validate(url_signature, url_to_validate)

            if not valid:
                is_valid = True
                if self.context.config.ALLOW_OLD_URLS:
                    cr = Cryptor(self.context.server.security_key)
                    options = cr.get_options(self.context.request.hash,
                                             self.context.request.image_url)
                    if options is None:
                        is_valid = False
                    else:
                        self.context.request = RequestParameters(**options)
                        logger.warning(
                            'OLD FORMAT URL DETECTED!!! This format of URL will be discontinued in upcoming versions. Please start using the new format as soon as possible. More info at https://github.com/globocom/thumbor/wiki/3.0.0-release-changes'
                        )
                else:
                    is_valid = False

                if not is_valid:
                    self._error(404, 'Malformed URL: %s' % url)
                    return

        return self.execute_image_operations()
Exemple #17
0
            def topic(self, encrypted, crypto):
                crypto2 = Cryptor(security_key="simething")

                return (crypto2.decrypt(encrypted), crypto.decrypt(encrypted))
Exemple #18
0
            def topic(self, encrypted, crypto):
                crypto2 = Cryptor(security_key="simething")

                return (crypto2.decrypt(encrypted), crypto.decrypt(encrypted))
Exemple #19
0
def main(arguments=None):
    '''Converts a given url with the specified arguments.'''
    if arguments is None:
        arguments = sys.argv[1:]

    parser = optparse.OptionParser(usage='thumbor-url [options] imageurl or type thumbor-url -h (--help) for help', description=__doc__, version=__version__)

    parser.add_option('-l', '--key_file', dest='key_file', default=None, help = 'The file to read the security key from [default: %default].' )
    parser.add_option('-k', '--key', dest='key', default=None, help = 'The security key to encrypt the url with [default: %default].' )
    parser.add_option('-w', '--width', dest='width', type='int', default=0, help = 'The target width for the image [default: %default].' )
    parser.add_option('-e', '--height', dest='height', type='int', default=0, help = 'The target height for the image [default: %default].' )
    parser.add_option('-n', '--fitin', dest='fitin', action='store_true', default=False, help = 'Indicates that fit-in resizing should be performed.' )
    parser.add_option('-m', '--meta', dest='meta', action='store_true', default=False, help = 'Indicates that meta information should be retrieved.' )
    parser.add_option('', '--adaptive', action='store_true', dest='adaptive', default=False, help = 'Indicates that adaptive fit-in cropping should be used.' )
    parser.add_option('-s', '--smart', action='store_true', dest='smart', default=False, help = 'Indicates that smart cropping should be used.' )
    parser.add_option('-t', '--trim', action='store_true', default=False, help='Indicate that surrounding whitespace should be trimmed.')
    parser.add_option('-f', '--horizontal-flip', action='store_true', dest='horizontal_flip', default=False, help = 'Indicates that the image should be horizontally flipped.' )
    parser.add_option('-v', '--vertical-flip', action='store_true', dest='vertical_flip', default=False, help = 'Indicates that the image should be vertically flipped.')
    parser.add_option('-a', '--halign', dest='halign', default='center', help = 'The horizontal alignment to use for cropping [default: %default].' )
    parser.add_option('-i', '--valign', dest='valign', default='middle', help = 'The vertical alignment to use for cropping [default: %default].' )
    parser.add_option('',   '--filters', dest='filters', default='', help = 'Filters to be applied to the image, e.g. brightness(10) [default: %default].' )
    parser.add_option('-o', '--old-format', dest='old', action='store_true', default=False, help = 'Indicates that thumbor should generate old-format urls [default: %default].' )

    parser.add_option('-c', '--crop', dest='crop', default=None, help = 'The coordinates of the points to manual cropping in the format leftxtop:rightxbottom (100x200:400x500) [default: %default].' )

    (parsed_options, arguments) = parser.parse_args(arguments)

    if not arguments:
        print 'Error: The image argument is mandatory. For more information type thumbor-url -h'
        return

    image_url = arguments[0]
    if image_url.startswith('/'):
        image_url = image_url[1:]

    try:
        config = Config.load(None)
    except:
        config = None

    if config:
        print
        print "USING CONFIGURATION FILE AT %s" % config.config_file
        print

    if not parsed_options.key and not config:
        print 'Error: The -k or --key argument is mandatory. For more information type thumbor-url -h'
        return

    if parsed_options.key_file:
        f = open(parsed_options.key_file)
        security_key = f.read().strip()
        f.close()
    else:
        security_key = config.SECURITY_KEY if not parsed_options.key else parsed_options.key


    crop_left = crop_top = crop_right = crop_bottom = 0
    if parsed_options.crop:
        crops = parsed_options.crop.split(':')
        crop_left, crop_top = crops[0].split('x')
        crop_right, crop_bottom = crops[1].split('x')

    if parsed_options.old:
        crypt = Cryptor(security_key)
        opt = crypt.encrypt(parsed_options.width,
                            parsed_options.height,
                            parsed_options.smart,
                            parsed_options.adaptive,
                            parsed_options.fitin,
                            parsed_options.horizontal_flip,
                            parsed_options.vertical_flip,
                            parsed_options.halign,
                            parsed_options.valign,
                            crop_left,
                            crop_top,
                            crop_right,
                            crop_bottom,
                            parsed_options.filters,
                            image_url)
        url = '/%s/%s' % (opt, image_url)

        print 'Encrypted URL:'
    else:
        signer = Signer(security_key)
        url = Url.generate_options(
            width=parsed_options.width,
            height=parsed_options.height,
            smart=parsed_options.smart,
            meta=parsed_options.meta,
            adaptive=parsed_options.adaptive,
            fit_in=parsed_options.fitin,
            horizontal_flip=parsed_options.horizontal_flip,
            vertical_flip=parsed_options.vertical_flip,
            halign=parsed_options.halign,
            valign=parsed_options.valign,
            trim=parsed_options.trim,
            crop_left=crop_left,
            crop_top=crop_top,
            crop_right=crop_right,
            crop_bottom=crop_bottom,
            filters=parsed_options.filters
        )

        url = '%s/%s' % (url, image_url)
        url = url.lstrip('/')

        signature = signer.signature(url)

        url = '/%s/%s' % (signature, url)

        print 'Signed URL:'

    print url
Exemple #20
0
 def topic(self):
     return Cryptor(security_key="something")
Exemple #21
0
 def test_can_create_crypto_with_key(self):
     cryptor = Cryptor("key")
     expect(cryptor).not_to_be_null()
     expect(cryptor.security_key).to_equal("keykeykeykeykeyk")
Exemple #22
0
class CryptoTestCase(TestCase):
    def setUp(self, *args, **kw):
        super(CryptoTestCase, self).setUp(*args, **kw)
        self.cryptor = Cryptor(security_key="something")
        self.cryptor.context = mock.Mock(
            config=mock.Mock(
                STORES_CRYPTO_KEY_FOR_EACH_IMAGE=False
            ),
        )

    def test_can_create_crypto_with_key(self):
        cryptor = Cryptor("key")
        expect(cryptor).not_to_be_null()
        expect(cryptor.security_key).to_equal("keykeykeykeykeyk")

    def test_can_encrypt(self):
        encrypted = self.cryptor.encrypt(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image="/some/image.jpg"
        )

        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        expect(encrypted).to_equal(encrypted_str)

    def test_can_decrypt(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        decrypted = self.cryptor.decrypt(encrypted_str)

        expect(decrypted).not_to_be_null()
        expect(decrypted).not_to_be_an_error()
        expect(decrypted).not_to_be_empty()
        expect(decrypted['width']).to_equal(300)
        expect(decrypted['height']).to_equal(300)
        expect(decrypted['smart']).to_be_true()
        expect(decrypted['fit_in']).to_be_false()
        expect(decrypted['horizontal_flip']).to_be_true()
        expect(decrypted['vertical_flip']).to_be_true()
        expect(decrypted['halign']).to_equal('center')
        expect(decrypted['valign']).to_equal('middle')
        expect(decrypted['crop']['left']).to_equal(10)
        expect(decrypted['crop']['top']).to_equal(11)
        expect(decrypted['crop']['right']).to_equal(12)
        expect(decrypted['crop']['bottom']).to_equal(13)
        expect(decrypted['filters']).to_equal('some_filter()')

        image_hash = hashlib.md5('/some/image.jpg').hexdigest()
        expect(decrypted['image_hash']).to_equal(image_hash)

    def test_decrypting_with_wrong_key(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        cryptor = Cryptor(security_key="simething")
        wrong = cryptor.decrypt(encrypted_str)
        right = self.cryptor.decrypt(encrypted_str)
        expect(wrong['image_hash']).not_to_equal(str(right['image_hash']))

    def test_get_options(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"
        image_url = "/some/image.jpg"

        expected_options = {
            'trim': 'trim', 'full': False, 'halign': 'center', 'fit_in': False,
            'vertical_flip': True, 'image': '/some/image.jpg',
            'crop': {'top': 11, 'right': 12, 'bottom': 13, 'left': 10},
            'height': 300, 'width': 300, 'meta': False, 'horizontal_flip': True,
            'filters': 'some_filter()', 'valign': 'middle', 'debug': False,
            'hash': 'e2baf424fa420b73a97476956dfb858f', 'adaptive': False, 'smart': True
        }
        options = self.cryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_like(expected_options)

    def test_get_options_returns_null_if_invalid(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs"
        image_url = "/some/image.jpg"

        options = self.cryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()

    def test_get_options_returns_null_if_different_path(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"
        image_url = "/some/image2.jpg"

        options = self.cryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()

    def test_get_options_from_storage(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(
                STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True
            ),
            modules=mock.Mock(
                storage=mock_storage
            ),
        )

        mock_storage.get_crypto.return_value = custom_security_key

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).not_to_be_null()

        expected_options = {
            'trim': 'trim', 'full': False, 'halign': 'center', 'fit_in': False,
            'vertical_flip': True, 'image': '/some/image.jpg',
            'crop': {'top': 11, 'right': 12, 'bottom': 13, 'left': 10},
            'height': 300, 'width': 300, 'meta': False, 'horizontal_flip': True,
            'filters': 'some_filter()', 'valign': 'middle', 'debug': False,
            'hash': 'e2baf424fa420b73a97476956dfb858f', 'adaptive': False, 'smart': True
        }

        expect(options).to_be_like(expected_options)

    def test_get_options_from_storage_returns_null_if_key_not_found(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(
                STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True
            ),
            modules=mock.Mock(
                storage=mock_storage
            ),
        )

        mock_storage.get_crypto.return_value = None

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()
Exemple #23
0
 def setUp(self, *args, **kw):
     super(CryptoTestCase, self).setUp(*args, **kw)
     self.cryptor = Cryptor(security_key="something")
     self.cryptor.context = mock.Mock(
         config=mock.Mock(STORES_CRYPTO_KEY_FOR_EACH_IMAGE=False), )
Exemple #24
0
class CryptoTestCase(TestCase):
    def setUp(self, *args, **kw):
        super(CryptoTestCase, self).setUp(*args, **kw)
        self.cryptor = Cryptor(security_key="something")
        self.cryptor.context = mock.Mock(
            config=mock.Mock(STORES_CRYPTO_KEY_FOR_EACH_IMAGE=False), )

    def test_can_create_crypto_with_key(self):
        cryptor = Cryptor("key")
        expect(cryptor).not_to_be_null()
        expect(cryptor.security_key).to_equal("keykeykeykeykeyk")

    def test_can_encrypt(self):
        encrypted = self.cryptor.encrypt(width=300,
                                         height=300,
                                         smart=True,
                                         adaptive=False,
                                         full=False,
                                         fit_in=False,
                                         flip_horizontal=True,
                                         flip_vertical=True,
                                         halign="center",
                                         valign="middle",
                                         trim=True,
                                         crop_left=10,
                                         crop_top=11,
                                         crop_right=12,
                                         crop_bottom=13,
                                         filters='some_filter()',
                                         image="/some/image.jpg")

        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        expect(encrypted).to_equal(encrypted_str)

    def test_can_decrypt(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        decrypted = self.cryptor.decrypt(encrypted_str)

        expect(decrypted).not_to_be_null()
        expect(decrypted).not_to_be_an_error()
        expect(decrypted).not_to_be_empty()
        expect(decrypted['width']).to_equal(300)
        expect(decrypted['height']).to_equal(300)
        expect(decrypted['smart']).to_be_true()
        expect(decrypted['fit_in']).to_be_false()
        expect(decrypted['horizontal_flip']).to_be_true()
        expect(decrypted['vertical_flip']).to_be_true()
        expect(decrypted['halign']).to_equal('center')
        expect(decrypted['valign']).to_equal('middle')
        expect(decrypted['crop']['left']).to_equal(10)
        expect(decrypted['crop']['top']).to_equal(11)
        expect(decrypted['crop']['right']).to_equal(12)
        expect(decrypted['crop']['bottom']).to_equal(13)
        expect(decrypted['filters']).to_equal('some_filter()')

        image_hash = hashlib.md5('/some/image.jpg').hexdigest()
        expect(decrypted['image_hash']).to_equal(image_hash)

    def test_decrypting_with_wrong_key(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"

        cryptor = Cryptor(security_key="simething")
        wrong = cryptor.decrypt(encrypted_str)
        right = self.cryptor.decrypt(encrypted_str)
        expect(wrong['image_hash']).not_to_equal(str(right['image_hash']))

    def test_get_options(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"
        image_url = "/some/image.jpg"

        expected_options = {
            'trim': 'trim',
            'full': False,
            'halign': 'center',
            'fit_in': False,
            'vertical_flip': True,
            'image': '/some/image.jpg',
            'crop': {
                'top': 11,
                'right': 12,
                'bottom': 13,
                'left': 10
            },
            'height': 300,
            'width': 300,
            'meta': False,
            'horizontal_flip': True,
            'filters': 'some_filter()',
            'valign': 'middle',
            'debug': False,
            'hash': 'e2baf424fa420b73a97476956dfb858f',
            'adaptive': False,
            'smart': True
        }
        options = self.cryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_like(expected_options)

    def test_get_options_returns_null_if_invalid(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs"
        image_url = "/some/image.jpg"

        options = self.cryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()

    def test_get_options_returns_null_if_different_path(self):
        encrypted_str = "hELdyDzyYtjXU5GhGxJVHjRvGrSP_iYKnIQbq_MuVq86rSObCeJvo2iXFRUjLgs" \
            "U9wDzhqK9J_SHmpxDJHW_rBD8eilO26x2M_hzJfGB-V9cGF65GO_7CgJXI8Ktw188"
        image_url = "/some/image2.jpg"

        options = self.cryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()

    def test_get_options_from_storage(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True),
            modules=mock.Mock(storage=mock_storage),
        )

        mock_storage.get_crypto.return_value = custom_security_key

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).not_to_be_null()

        expected_options = {
            'trim': 'trim',
            'full': False,
            'halign': 'center',
            'fit_in': False,
            'vertical_flip': True,
            'image': '/some/image.jpg',
            'crop': {
                'top': 11,
                'right': 12,
                'bottom': 13,
                'left': 10
            },
            'height': 300,
            'width': 300,
            'meta': False,
            'horizontal_flip': True,
            'filters': 'some_filter()',
            'valign': 'middle',
            'debug': False,
            'hash': 'e2baf424fa420b73a97476956dfb858f',
            'adaptive': False,
            'smart': True
        }

        expect(options).to_be_like(expected_options)

    def test_get_options_from_storage_returns_null_if_key_not_found(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True),
            modules=mock.Mock(storage=mock_storage),
        )

        mock_storage.get_crypto.return_value = None

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).to_be_null()
Exemple #25
0
    def test_get_options_from_storage(self):
        image_url = "/some/image.jpg"
        custom_security_key = "custom-sec"
        cryptor = Cryptor(security_key=custom_security_key)
        decryptor = Cryptor(security_key="something")

        expected_options = dict(
            width=300,
            height=300,
            smart=True,
            adaptive=False,
            full=False,
            fit_in=False,
            flip_horizontal=True,
            flip_vertical=True,
            halign="center",
            valign="middle",
            trim=True,
            crop_left=10,
            crop_top=11,
            crop_right=12,
            crop_bottom=13,
            filters='some_filter()',
            image=image_url,
        )

        encrypted_str = cryptor.encrypt(**expected_options)

        mock_storage = mock.Mock()
        decryptor.context = mock.Mock(
            config=mock.Mock(STORES_CRYPTO_KEY_FOR_EACH_IMAGE=True),
            modules=mock.Mock(storage=mock_storage),
        )

        mock_storage.get_crypto.return_value = custom_security_key

        options = decryptor.get_options(encrypted_str, image_url)
        expect(options).not_to_be_null()

        expected_options = {
            'trim': 'trim',
            'full': False,
            'halign': 'center',
            'fit_in': False,
            'vertical_flip': True,
            'image': '/some/image.jpg',
            'crop': {
                'top': 11,
                'right': 12,
                'bottom': 13,
                'left': 10
            },
            'height': 300,
            'width': 300,
            'meta': False,
            'horizontal_flip': True,
            'filters': 'some_filter()',
            'valign': 'middle',
            'debug': False,
            'hash': 'e2baf424fa420b73a97476956dfb858f',
            'adaptive': False,
            'smart': True
        }

        expect(options).to_be_like(expected_options)
def decrypt_in_thumbor(key, encrypted):
    """Uses thumbor to decrypt libthumbor's encrypted URL"""
    crypto = Cryptor(key)
    return crypto.decrypt(encrypted)
Exemple #27
0
    def check_image(self, kw):
        if self.context.config.MAX_ID_LENGTH > 0:
            # Check if an image with an uuid exists in storage
            exists = yield gen.maybe_future(
                self.context.modules.storage.exists(
                    kw['image'][:self.context.config.MAX_ID_LENGTH]))
            if exists:
                kw['image'] = kw['image'][:self.context.config.MAX_ID_LENGTH]

        url = self.request.uri

        if not self.validate(kw['image']):
            self._error(400,
                        'No original image was specified in the given URL')
            return

        kw['request'] = self.request

        self.context.request = RequestParameters(**kw)

        has_none = not self.context.request.unsafe and not self.context.request.hash
        has_both = self.context.request.unsafe and self.context.request.hash

        if has_none or has_both:
            self._error(
                400, 'URL does not have hash or unsafe, or has both: %s' % url)
            return

        if self.context.request.unsafe and not self.context.config.ALLOW_UNSAFE_URL:
            self._error(
                400,
                'URL has unsafe but unsafe is not allowed by the config: %s' %
                url)
            return

        if self.context.config.USE_BLACKLIST:
            blacklist = yield self.get_blacklist_contents()
            if self.context.request.image_url in blacklist:
                self._error(
                    400, 'Source image url has been blacklisted: %s' %
                    self.context.request.image_url)
                return

        url_signature = self.context.request.hash
        if url_signature:
            signer = self.context.modules.url_signer(
                self.context.server.security_key)

            url_to_validate = Url.encode_url(url).replace(
                '/%s/' % self.context.request.hash, '')
            valid = signer.validate(url_signature, url_to_validate)

            if not valid and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE:
                # Retrieves security key for this image if it has been seen before
                security_key = yield gen.maybe_future(
                    self.context.modules.storage.get_crypto(
                        self.context.request.image_url))
                if security_key is not None:
                    signer = self.context.modules.url_signer(security_key)
                    valid = signer.validate(url_signature, url_to_validate)

            if not valid:
                is_valid = True
                if self.context.config.ALLOW_OLD_URLS:
                    cr = Cryptor(self.context.server.security_key)
                    options = cr.get_options(self.context.request.hash,
                                             self.context.request.image_url)
                    if options is None:
                        is_valid = False
                    else:
                        options['request'] = self.request
                        self.context.request = RequestParameters(**options)
                        logger.warning(
                            'OLD FORMAT URL DETECTED!!! This format of URL will be discontinued in '
                            +
                            'upcoming versions. Please start using the new format as soon as possible. '
                            +
                            'More info at https://github.com/thumbor/thumbor/wiki/3.0.0-release-changes'
                        )
                else:
                    is_valid = False

                if not is_valid:
                    self._error(400, 'Malformed URL: %s' % url)
                    return

        self.execute_image_operations()
Exemple #28
0
def main(arguments=None):
    '''Converts a given url with the specified arguments.'''
    if arguments is None:
        arguments = sys.argv[1:]

    parser = optparse.OptionParser(usage='thumbor-url [options] imageurl or type thumbor-url -h (--help) for help', description=__doc__, version=__version__)

    parser.add_option('-l', '--key_file', dest='key_file', default=None, help='The file to read the security key from [default: %default].')
    parser.add_option('-k', '--key', dest='key', default=None, help='The security key to encrypt the url with [default: %default].')
    parser.add_option('-w', '--width', dest='width', type='int', default=0, help='The target width for the image [default: %default].')
    parser.add_option('-e', '--height', dest='height', type='int', default=0, help='The target height for the image [default: %default].')
    parser.add_option('-n', '--fitin', dest='fitin', action='store_true', default=False, help='Indicates that fit-in resizing should be performed.')
    parser.add_option('-m', '--meta', dest='meta', action='store_true', default=False, help='Indicates that meta information should be retrieved.')
    parser.add_option('', '--adaptive', action='store_true', dest='adaptive', default=False, help='Indicates that adaptive fit-in cropping should be used.')
    parser.add_option('', '--full', action='store_true', dest='full', default=False, help='Indicates that fit-full cropping should be used.')
    parser.add_option('-s', '--smart', action='store_true', dest='smart', default=False, help='Indicates that smart cropping should be used.')
    parser.add_option('-t', '--trim', action='store_true', default=False, help='Indicate that surrounding whitespace should be trimmed.')
    parser.add_option('-f', '--horizontal-flip', action='store_true', dest='horizontal_flip', default=False, help='Indicates that the image should be horizontally flipped.')
    parser.add_option('-v', '--vertical-flip', action='store_true', dest='vertical_flip', default=False, help='Indicates that the image should be vertically flipped.')
    parser.add_option('-a', '--halign', dest='halign', default='center', help='The horizontal alignment to use for cropping [default: %default].')
    parser.add_option('-i', '--valign', dest='valign', default='middle', help='The vertical alignment to use for cropping [default: %default].')
    parser.add_option('', '--filters', dest='filters', default='', help='Filters to be applied to the image, e.g. brightness(10) [default: %default].')
    parser.add_option('-o', '--old-format', dest='old', action='store_true', default=False, help='Indicates that thumbor should generate old-format urls [default: %default].')

    parser.add_option('-c', '--crop', dest='crop', default=None, help='The coordinates of the points to manual cropping in the format leftxtop:rightxbottom (100x200:400x500) [default: %default].')

    (parsed_options, arguments) = parser.parse_args(arguments)

    if not arguments:
        print 'Error: The image argument is mandatory. For more information type thumbor-url -h'
        return

    image_url = arguments[0]
    if image_url.startswith('/'):
        image_url = image_url[1:]

    try:
        config = Config.load(None)
    except:
        config = None

    if not parsed_options.key and not config:
        print 'Error: The -k or --key argument is mandatory. For more information type thumbor-url -h'
        return

    if parsed_options.key_file:
        f = open(parsed_options.key_file)
        security_key = f.read().strip()
        f.close()
    else:
        security_key = config.SECURITY_KEY if not parsed_options.key else parsed_options.key

    crop_left = crop_top = crop_right = crop_bottom = 0
    if parsed_options.crop:
        crops = parsed_options.crop.split(':')
        crop_left, crop_top = crops[0].split('x')
        crop_right, crop_bottom = crops[1].split('x')

    if parsed_options.old:
        crypt = Cryptor(security_key)
        opt = crypt.encrypt(parsed_options.width,
                            parsed_options.height,
                            parsed_options.smart,
                            parsed_options.adaptive,
                            parsed_options.full,
                            parsed_options.fitin,
                            parsed_options.horizontal_flip,
                            parsed_options.vertical_flip,
                            parsed_options.halign,
                            parsed_options.valign,
                            parsed_options.trim,
                            crop_left,
                            crop_top,
                            crop_right,
                            crop_bottom,
                            parsed_options.filters,
                            image_url)
        url = '/%s/%s' % (opt, image_url)

        print 'Encrypted URL:'
    else:
        signer = Signer(security_key)
        url = Url.generate_options(
            width=parsed_options.width,
            height=parsed_options.height,
            smart=parsed_options.smart,
            meta=parsed_options.meta,
            adaptive=parsed_options.adaptive,
            full=parsed_options.full,
            fit_in=parsed_options.fitin,
            horizontal_flip=parsed_options.horizontal_flip,
            vertical_flip=parsed_options.vertical_flip,
            halign=parsed_options.halign,
            valign=parsed_options.valign,
            trim=parsed_options.trim,
            crop_left=crop_left,
            crop_top=crop_top,
            crop_right=crop_right,
            crop_bottom=crop_bottom,
            filters=parsed_options.filters
        )

        url = '%s/%s' % (url, image_url)
        url = url.lstrip('/')

        signature = signer.signature(url)

        url = '/%s/%s' % (signature, url)

        print 'Signed URL:'

    print url
    return url
Exemple #29
0
    def get(self, **kw):

        # Check if an image with an uuid exists in storage
        if self.context.modules.storage.exists(kw['image'][:32]):
            kw['image'] = kw['image'][:32]

        url = self.request.uri

        if not self.validate(kw['image']):
            self._error(404, 'No original image was specified in the given URL')
            return

        self.context.request = RequestParameters(**kw)

        self.context.request.unsafe = self.context.request.unsafe == 'unsafe'

        if (self.request.query):
            self.context.request.image_url += '?%s' % self.request.query
        self.context.request.image_url = self.encode_url(self.context.request.image_url.encode('utf-8'))

        has_none = not self.context.request.unsafe and not self.context.request.hash
        has_both = self.context.request.unsafe and self.context.request.hash

        if has_none or has_both:
            self._error(404, 'URL does not have hash or unsafe, or has both: %s' % url)
            return

        if self.context.request.unsafe and not self.context.config.ALLOW_UNSAFE_URL:
            self._error(404, 'URL has unsafe but unsafe is not allowed by the config: %s' % url)
            return

        url_signature = self.context.request.hash
        if url_signature:
            signer = Signer(self.context.server.security_key)

            url_to_validate = self.encode_url(url).replace('/%s/' % self.context.request.hash, '')
            valid = signer.validate(url_signature, url_to_validate)

            if not valid and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE:
                # Retrieves security key for this image if it has been seen before
                security_key = self.context.modules.storage.get_crypto(self.context.request.image_url)
                if security_key is not None:
                    signer = Signer(security_key)
                    valid = signer.validate(url_signature, url_to_validate)

            if not valid:
                is_valid = True
                if self.context.config.ALLOW_OLD_URLS:
                    cr = Cryptor(self.context.server.security_key)
                    options = cr.get_options(self.context.request.hash, self.context.request.image_url)
                    if options is None:
                        is_valid = False
                    else:
                        self.context.request = RequestParameters(**options)
                        logger.warning('OLD FORMAT URL DETECTED!!! This format of URL will be discontinued in upcoming versions. Please start using the new format as soon as possible. More info at https://github.com/globocom/thumbor/wiki/3.0.0-release-changes')
                else:
                    is_valid = False

                if not is_valid:
                    self._error(404, 'Malformed URL: %s' % url)
                    return

        return self.execute_image_operations()
def decrypt_in_thumbor(url):
    '''Uses thumbor to decrypt libthumbor's encrypted URL'''
    encrypted = url.split('/')[1]
    cryptor = Cryptor(KEY)
    return cryptor.decrypt(encrypted)
Exemple #31
0
    def check_image(self, kw):
        if self.context.config.MAX_ID_LENGTH > 0:
            # Check if an image with an uuid exists in storage
            exists = yield gen.maybe_future(self.context.modules.storage.exists(kw['image'][:self.context.config.MAX_ID_LENGTH]))
            if exists:
                kw['image'] = kw['image'][:self.context.config.MAX_ID_LENGTH]

        url = self.request.uri

        if not self.validate(kw['image']):
            self._error(400, 'No original image was specified in the given URL')
            return

        kw['request'] = self.request

        self.context.request = RequestParameters(**kw)

        has_none = not self.context.request.unsafe and not self.context.request.hash
        has_both = self.context.request.unsafe and self.context.request.hash

        if has_none or has_both:
            self._error(400, 'URL does not have hash or unsafe, or has both: %s' % url)
            return

        if self.context.request.unsafe and not self.context.config.ALLOW_UNSAFE_URL:
            self._error(400, 'URL has unsafe but unsafe is not allowed by the config: %s' % url)
            return

        if self.context.config.USE_BLACKLIST:
            blacklist = yield self.get_blacklist_contents()
            if self.context.request.image_url in blacklist:
                self._error(400, 'Source image url has been blacklisted: %s' % self.context.request.image_url )
                return

        url_signature = self.context.request.hash
        if url_signature:
            signer = Signer(self.context.server.security_key)

            url_to_validate = Url.encode_url(url).replace('/%s/' % self.context.request.hash, '')
            valid = signer.validate(url_signature, url_to_validate)

            if not valid and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE:
                # Retrieves security key for this image if it has been seen before
                security_key = yield gen.maybe_future(self.context.modules.storage.get_crypto(self.context.request.image_url))
                if security_key is not None:
                    signer = Signer(security_key)
                    valid = signer.validate(url_signature, url_to_validate)

            if not valid:
                is_valid = True
                if self.context.config.ALLOW_OLD_URLS:
                    cr = Cryptor(self.context.server.security_key)
                    options = cr.get_options(self.context.request.hash, self.context.request.image_url)
                    if options is None:
                        is_valid = False
                    else:
                        options['request'] = self.request
                        self.context.request = RequestParameters(**options)
                        logger.warning(
                            'OLD FORMAT URL DETECTED!!! This format of URL will be discontinued in ' +
                            'upcoming versions. Please start using the new format as soon as possible. ' +
                            'More info at https://github.com/globocom/thumbor/wiki/3.0.0-release-changes'
                        )
                else:
                    is_valid = False

                if not is_valid:
                    self._error(400, 'Malformed URL: %s' % url)
                    return

        self.execute_image_operations()
Exemple #32
0
def decrypt_in_thumbor(key, encrypted):
    '''Uses thumbor to decrypt libthumbor's encrypted URL'''
    crypto = Cryptor(key)
    return crypto.decrypt(encrypted)