def test_usage(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_crypto = Crypto(salt=key) thumbor_options = thumbor_crypto.encrypt( width=300, height=200, smart=True, 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, 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 ) assert url == thumbor_url
def get(self, crypto, image, security_key=None, **kw): cr = Crypto(security_key or self.context.server.security_key) try: opt = cr.decrypt(crypto) except ValueError: opt = None if not opt and not security_key and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE: security_key = self.storage.get_crypto(image) cr = Crypto(security_key or self.context.server.security_key) opt = cr.decrypt(crypto) image_hash = opt and opt.get('image_hash') image_hash = image_hash[1:] if image_hash and image_hash.startswith('/') else image_hash path_hash = hashlib.md5(image.encode('utf-8')).hexdigest() if not image_hash or image_hash != path_hash: self._error(404, 'Request denied because the specified image hash is not valid.') return opt['image'] = image self.context.request = RequestParameters(**opt) return self.execute_image_operations()
def get(self, crypto, image, security_key=None, **kw): if not security_key and options.STORES_CRYPTO_KEY_FOR_EACH_IMAGE: security_key = self.storage.get_crypto(image) try: cr = Crypto(security_key or options.SECURITY_KEY) opt = cr.decrypt(crypto) except TypeError: self._error(404, 'Request denied because the specified encrypted url "%s" could not be decripted' % crypto) return image_hash = opt and opt.get('image_hash') image_hash = image_hash[1:] if image_hash and image_hash.startswith('/') else image_hash path_hash = hashlib.md5(image).hexdigest() if not image_hash or image_hash != path_hash: self._error(404, 'Request denied because the specified image hash "%s" does not match the given image path hash "%s"' %( unicode(image_hash, errors='replace'), path_hash )) return if not self.validate(image): self._error(404) return return self.execute_image_operations(opt, image)
def test_usage(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_crypto = Crypto(salt=key) thumbor_options = thumbor_crypto.encrypt( 300, 200, True, False, False, 'center', 'middle', 0, 0, 0, 0, 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 ) assert url == thumbor_url
def get(self, crypto, image, security_key=None, **kw): cr = Crypto(security_key or conf.SECURITY_KEY) try: opt = cr.decrypt(crypto) except ValueError: opt = None if not opt and not security_key and conf.STORES_CRYPTO_KEY_FOR_EACH_IMAGE: security_key = self.storage.get_crypto(image) cr = Crypto(security_key or conf.SECURITY_KEY) opt = cr.decrypt(crypto) image_hash = opt and opt.get('image_hash') image_hash = image_hash[1:] if image_hash and image_hash.startswith('/') else image_hash path_hash = hashlib.md5(image).hexdigest() if not image_hash or image_hash != path_hash: self._error(404, 'Request denied because the specified image hash is not valid.') return return self.execute_image_operations(opt, image)
def test_encdec_with_extra_args(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=200, smart=False, fit_in=True, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image") decrypted = crypto.decrypt(encrypted) assert decrypted['width'] == 300 assert decrypted['height'] == 200 assert not decrypted['smart'] assert decrypted['fit_in'] assert decrypted['horizontal_flip'] assert decrypted['vertical_flip'] assert decrypted['halign'] == "center" assert decrypted['valign'] == "middle" assert decrypted['crop'] assert decrypted['crop']['left'] == 10 assert decrypted['crop']['top'] == 11 assert decrypted['crop']['right'] == 12 assert decrypted['crop']['bottom'] == 13
def test_encdec_with_extra_args(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=200, smart=False, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image") decrypted = crypto.decrypt(encrypted) assert decrypted['width'] == 300 assert decrypted['height'] == 200 assert not decrypted['smart'] assert decrypted['horizontal_flip'] assert decrypted['vertical_flip'] assert decrypted['halign'] == "center" assert decrypted['valign'] == "middle" assert decrypted['crop'] assert decrypted['crop']['left'] == 10 assert decrypted['crop']['top'] == 11 assert decrypted['crop']['right'] == 12 assert decrypted['crop']['bottom'] == 13
def get(self, crypto, image, security_key=None, **kw): if not security_key and options.STORES_CRYPTO_KEY_FOR_EACH_IMAGE: security_key = self.storage.get_crypto(image) try: cr = Crypto(security_key or options.SECURITY_KEY) opt = cr.decrypt(crypto) except TypeError: self._error( 404, 'Request denied because the specified encrypted url "%s" could not be decripted' % crypto) return image_hash = opt and opt.get('image_hash') image_hash = image_hash[1:] if image_hash and image_hash.startswith( '/') else image_hash path_hash = hashlib.md5(image).hexdigest() if not image_hash or image_hash != path_hash: self._error( 404, 'Request denied because the specified image hash "%s" does not match the given image path hash "%s"' % (unicode(image_hash, errors='replace'), path_hash)) return if not self.validate(image): self._error(404) return return self.execute_image_operations(opt, image)
def test_crypto_encrypts(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=300, smart=True, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image.jpg") assert encrypted == 'OI8j7z9h88_IVzYLiq9UWPkBPBwwJ1pMKQw1UVrL7odTcog5UT4PBBrzoehKm7WUNxU5oq8mV59xMJJUc2aKWA=='
def test_crypto_encrypts(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=300, smart=True, fit_in=False, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image.jpg") assert encrypted == 'OI8j7z9h88_IVzYLiq9UWPkBPBwwJ1pMKQw1UVrL7odTcog5UT4PBBrzoehKm7WUNxU5oq8mV59xMJJUc2aKWA=='
def test_decrypt(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=200, smart=True, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image.jpg") decrypted = crypto.decrypt(encrypted) assert decrypted['width'] == 300 assert decrypted['height'] == 200 assert decrypted['smart'] == True
def get(self, crypto, image, security_key=None, **kw): cr = Crypto(security_key or self.context.config.SECURITY_KEY) try: opt = cr.decrypt(crypto) except ValueError: opt = None if not opt and not security_key and self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE: security_key = self.storage.get_crypto(image) cr = Crypto(security_key or self.context.config.SECURITY_KEY) opt = cr.decrypt(crypto) image_hash = opt and opt.get('image_hash') image_hash = image_hash[1:] if image_hash and image_hash.startswith('/') else image_hash path_hash = hashlib.md5(image).hexdigest() if not image_hash or image_hash != path_hash: self._error(404, 'Request denied because the specified image hash is not valid.') return opt['image'] = image self.context.request = RequestParameters(**opt) return self.execute_image_operations()
def test_decrypt(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=200, smart=True, fit_in=False, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image.jpg") decrypted = crypto.decrypt(encrypted) assert decrypted['width'] == 300 assert decrypted['height'] == 200 assert decrypted['smart'] == True
def test_decrypting_with_wrong_key_fails(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=200, smart=True, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image/") crypto = Crypto(salt="simething") decrypted = crypto.decrypt(encrypted) assert decrypted
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 = Crypto(salt=key) crypto = CryptoURL(key=key) url = crypto.generate( width=300, height=200, smart=True, image_url=image ) 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()
def test_decrypting_with_wrong_key_fails(): crypto = Crypto(salt="something") encrypted = crypto.encrypt(width=300, height=200, smart=True, fit_in=False, flip_horizontal=True, flip_vertical=True, halign="center", valign="middle", crop_left=10, crop_top=11, crop_right=12, crop_bottom=13, image="/some/image/") crypto = Crypto(salt="simething") decrypted = crypto.decrypt(encrypted) assert decrypted
def main(): '''Converts a given url with the specified arguments.''' parser = optparse.OptionParser(usage='thumbor-url [options] imageurl or type thumbor-url -h (--help) for help', description=__doc__, version=__version__) 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('-s', '--smart', action='store_true', dest='smart', default=False, help = 'Indicates that smart cropping should be used.' ) 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('-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() 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:] conf_file = ThumborServiceApp.get_conf_file('') if conf_file: print print "USING CONFIGURATION FILE AT %s" % conf_file print parse_config_file(conf_file) if not parsed_options.key and not conf_file: print 'Error: The -k or --key argument is mandatory. For more information type thumbor-url -h' return security_key = options.SECURITY_KEY if not parsed_options.key else parsed_options.key crypt = Crypto(security_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') opt = crypt.encrypt(parsed_options.width, parsed_options.height, parsed_options.smart, parsed_options.horizontal_flip, parsed_options.vertical_flip, parsed_options.halign, parsed_options.valign, crop_left, crop_top, crop_right, crop_bottom, image_url) url = '/%s/%s' % (opt, image_url) print 'Encrypted URL: "%s" (without quotes)' % url
def decrypt_in_thumbor(key, encrypted): '''Uses thumbor to decrypt libthumbor's encrypted URL''' crypto = Crypto(key) return crypto.decrypt(encrypted)
def topic(self, encrypted, crypto): crypto2 = Crypto(salt="simething") return (crypto2.decrypt(encrypted), crypto.decrypt(encrypted))
def topic(self): return Crypto(salt="something")
# Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com [email protected] from os.path import abspath, join, dirname from pyvows import Vows, expect from tornado_pyvows.context import TornadoHTTPContext from thumbor.crypto import Crypto from thumbor.app import ThumborServiceApp from thumbor.importer import Importer from thumbor.config import Config from thumbor.context import Context get_encrypted_url = lambda url, width, height, security_key='HandlerVows': '/%s/%s' % (Crypto(security_key).encrypt(width, height, False, False, False, False, 'center', 'middle', None, None, None, None, '', url), url) fixture_for = lambda path: abspath(join(dirname(__file__), 'fixtures', path)) image_url = 'alabama1_ap620.jpg' @Vows.batch class CryptoHandlerVows(TornadoHTTPContext): def get_app(self): cfg = Config.load(fixture_for('encrypted_handler_conf.py')) importer = Importer(cfg) importer.import_modules() ctx = Context(None, cfg, importer) application = ThumborServiceApp(ctx) return application
def decrypt_in_thumbor(url): '''Uses thumbor to decrypt libthumbor's encrypted URL''' encrypted = url.split('/')[1] crypto = Crypto(KEY) return crypto.decrypt(encrypted)
def test_can_create_crypto(): crypto = Crypto(salt="something") assert crypto assert crypto.salt == "somethingsomethi"
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( '', '--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( '-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( '-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() f.close() else: security_key = config.SECURITY_KEY if not parsed_options.key else parsed_options.key crypt = Crypto(security_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') 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:' print url
from os.path import abspath, join, dirname from pyvows import Vows, expect from tornado_pyvows.context import TornadoHTTPContext import urllib from thumbor.crypto import Crypto from thumbor.app import ThumborServiceApp from thumbor.importer import Importer from thumbor.config import Config from thumbor.context import Context, ServerParameters get_encrypted_url = lambda url, width, height, security_key='HandlerVows': '/%s/%s' % ( Crypto(security_key ).encrypt(width, height, False, False, False, False, False, 'center', 'middle', None, None, None, None, '', url), url) fixture_for = lambda path: abspath(join(dirname(__file__), 'fixtures', path)) image_url = 'alabama1_ap620é.jpg' @Vows.batch class CryptoHandlerVows(TornadoHTTPContext): def get_app(self): cfg = Config.load(fixture_for('encrypted_handler_conf.py')) server_params = ServerParameters(None, None, None, None, None, None) server_params.security_key = 'HandlerVows' importer = Importer(cfg) importer.import_modules()