def test_image_already_generated_by_thumbor_2_times(self): with open( normalize_unicode_path(u'./tests/fixtures/images/alabama1_ap620é.jpg'), 'r' ) as f: self.context.modules.storage.put( quote("http://test.com/smart/alabama1_ap620é"), f.read() ) crypto = CryptoURL('ACME-SEC') image_url = self.get_url( crypto.generate( image_url=quote(self.get_url( crypto.generate( image_url=quote("http://test.com/smart/alabama1_ap620é") ) )) ) ) url = crypto.generate( image_url=quote(image_url) ) response = self.fetch(url) expect(response.code).to_equal(200)
def test_image_already_generated_by_thumbor(self): with open('./tests/fixtures/images/image.jpg', 'r') as f: self.context.modules.storage.put( quote("http://test.com/smart/image.jpg"), f.read()) crypto = CryptoURL('ACME-SEC') image_url = self.get_url( crypto.generate( image_url=quote("http://test.com/smart/image.jpg"))) url = crypto.generate(image_url=quote(image_url)) response = self.fetch(url) expect(response.code).to_equal(200)
async def test_image_already_generated_by_thumbor(self): with open("./tests/fixtures/images/image.jpg", "rb") as fixture: await self.context.modules.storage.put( quote("http://test.com/smart/image.jpg"), fixture.read()) crypto = CryptoURL("ACME-SEC") image_url = self.get_url( crypto.generate( image_url=quote("http://test.com/smart/image.jpg"))) url = crypto.generate(image_url=quote(image_url)) response = await self.async_fetch(url) expect(response.code).to_equal(200)
def test_thumbor_filter(self): testing.setUp(settings={ 'thumbor.security_key': 'foo', }) crypto = CryptoURL(key='foo') self.assertEqual( thumbor_filter({}, 'image', 25, 25), crypto.generate(width=25, height=25, image_url='image')) self.assertEqual(thumbor_filter({}, 'image', 25), crypto.generate(width=25, image_url='image')) self.assertEqual( thumbor_filter({}, 'image', 25, None), crypto.generate(width=25, height=0, image_url='image'))
def test_thumbor_filter(self): testing.setUp(settings={ 'thumbor.security_key': 'foo', }) crypto = CryptoURL(key='foo') self.assertEqual( thumbor_filter({}, 'image', 25, 25), crypto.generate(width=25, height=25, image_url='image')) self.assertEqual( thumbor_filter({}, 'image', 25), crypto.generate(width=25, image_url='image')) self.assertEqual( thumbor_filter({}, 'image', 25, None), crypto.generate(width=25, height=0, image_url='image'))
def thumb(self, image, **kwargs): url = image.url if not url: return None if settings.THUMBOR_BASE_URL: # If THUMBOR_BASE_URL is explicity set, use that base = settings.THUMBOR_BASE_URL else: # otherwise assume that thumbor is setup behind the same # CDN behind the `thumbor` namespace. scheme, netloc = urlparse.urlsplit(url)[:2] base = '{}://{}/thumbor'.format(scheme, netloc) crypto = CryptoURL(key=settings.THUMBOR_KEY) # just for code clarity thumbor_kwargs = kwargs if not 'fit_in' in thumbor_kwargs: thumbor_kwargs['fit_in'] = False thumbor_kwargs['image_url'] = url path = crypto.generate(**thumbor_kwargs) return u'{}{}'.format(base, path)
def main(arguments=None): """Converts a given url with the specified arguments.""" parsed_options, arguments = get_options(arguments) image_url = arguments[0] image_url = quote(image_url) try: config = Config.load(None) except: config = None if not parsed_options.key and not config: sys.stdout.write("Error: The -k or --key argument is mandatory. For more information type thumbor-url -h\n") return security_key, thumbor_params = get_thumbor_params(image_url, parsed_options, config) crypto = CryptoURL(key=security_key) url = crypto.generate(**thumbor_params) sys.stdout.write("URL:\n") sys.stdout.write("%s\n" % url) return url
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 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
def generate_thumbnail_url(path: str, size: str='0x0') -> str: if not (path.startswith('https://') or path.startswith('http://')): path = '/' + path if not is_thumbor_enabled(): if path.startswith('http://'): return get_camo_url(path) return path if not user_uploads_or_external(path): return path source_type = get_source_type(path) safe_url = base64.urlsafe_b64encode(path.encode()).decode('utf-8') image_url = '%s/source_type/%s' % (safe_url, source_type) width, height = map(int, size.split('x')) crypto = CryptoURL(key=settings.THUMBOR_KEY) encrypted_url = crypto.generate( width=width, height=height, smart=True, filters=['no_upscale()', 'sharpen(0.5,0.2,true)'], image_url=image_url ) if settings.THUMBOR_URL == 'http://127.0.0.1:9995': # If THUMBOR_URL is the default then thumbor is hosted on same machine # as the Zulip server and we should serve a relative URL. # We add a /thumbor in front of the relative url because we make # use of a proxy pass to redirect request internally in Nginx to 9995 # port where thumbor is running. thumbnail_url = '/thumbor' + encrypted_url else: thumbnail_url = urllib.parse.urljoin(settings.THUMBOR_URL, encrypted_url) return thumbnail_url
def test_usage_new_format(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_signer = Signer(key) thumbor_url = Url.generate_options(width=300, height=200, smart=True, adaptive=False, fit_in=False, horizontal_flip=False, vertical_flip=False, halign='center', valign='middle', crop_left=0, crop_top=0, crop_right=0, crop_bottom=0, filters=[]) thumbor_url = ('%s/%s' % (thumbor_url, image)).lstrip('/') thumbor_url = '/%s/%s' % (thumbor_signer.signature(thumbor_url), thumbor_url) crypto = CryptoURL(key=key) url = crypto.generate(width=300, height=200, smart=True, image_url=image) assert url == thumbor_url
def main(arguments=None): '''Converts a given url with the specified arguments.''' parsed_options, arguments = get_options(arguments) image_url = arguments[0] image_url = quote(image_url) try: config = Config.load(None) except: config = None if not parsed_options.key and not config: sys.stdout.write( 'Error: The -k or --key argument is mandatory. For more information type thumbor-url -h\n' ) return security_key, thumbor_params = get_thumbor_params(image_url, parsed_options, config) crypto = CryptoURL(key=security_key) url = crypto.generate(**thumbor_params) sys.stdout.write('URL:\n') sys.stdout.write('%s\n' % url) return url
def test_usage_new_format(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_signer = Signer(key) thumbor_url = Url.generate_options( width=300, height=200, smart=True, adaptive=False, fit_in=False, horizontal_flip=False, vertical_flip=False, crop_left=0, crop_top=0, crop_right=0, crop_bottom=0, filters=[], ) thumbor_url = (f"{thumbor_url}/{image}").lstrip("/") signature = thumbor_signer.signature(thumbor_url).decode("ascii") thumbor_url = f"/{signature}/{thumbor_url}" crypto = CryptoURL(key=key) url = crypto.generate(width=300, height=200, smart=True, image_url=image) assert url == thumbor_url
def main(arguments=None): """Converts a given url with the specified arguments.""" parsed_options, arguments = get_options(arguments) if not arguments: sys.stdout.write( "Error: The image argument is mandatory. For more information type thumbor-url -h\n" ) sys.exit(1) image_url = arguments[0] image_url = quote(image_url) try: config = Config.load(None) except Exception: # pylint: disable=broad-except config = None if not parsed_options.key and not config: sys.stdout.write("Error: The -k or --key argument is mandatory." " For more information type thumbor-url -h\n") sys.exit(1) security_key, thumbor_params = get_thumbor_params(image_url, parsed_options, config) crypto = CryptoURL(key=security_key) url = crypto.generate(**thumbor_params) sys.stdout.write("URL:\n") sys.stdout.write(f"{url}\n")
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()
def test_usage_new_format(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_signer = Signer(key) thumbor_url = Url.generate_options( width=300, height=200, smart=True, adaptive=False, fit_in=False, horizontal_flip=False, vertical_flip=False, halign='center', valign='middle', crop_left=0, crop_top=0, crop_right=0, crop_bottom=0, filters=[] ) thumbor_url = ('%s/%s' % (thumbor_url, image)).lstrip('/') thumbor_url = '/%s/%s' % (thumbor_signer.signature(thumbor_url), thumbor_url) crypto = CryptoURL(key=key) url = crypto.generate( width=300, height=200, smart=True, image_url=image ) assert url == thumbor_url
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 generate_thumbnail_url(path: str, size: str = '0x0') -> str: if not (path.startswith('https://') or path.startswith('http://')): path = '/' + path if not is_thumbor_enabled(): if path.startswith('http://'): return get_camo_url(path) return path if not user_uploads_or_external(path): return path source_type = get_source_type(path) safe_url = base64.urlsafe_b64encode(path.encode()).decode('utf-8') image_url = '%s/source_type/%s' % (safe_url, source_type) width, height = map(int, size.split('x')) crypto = CryptoURL(key=settings.THUMBOR_KEY) encrypted_url = crypto.generate( width=width, height=height, smart=True, filters=['no_upscale()', 'sharpen(0.5,0.2,true)'], image_url=image_url) if settings.THUMBOR_URL == 'http://127.0.0.1:9995': # If THUMBOR_URL is the default then thumbor is hosted on same machine # as the Zulip server and we should serve a relative URL. # We add a /thumbor in front of the relative url because we make # use of a proxy pass to redirect request internally in Nginx to 9995 # port where thumbor is running. thumbnail_url = '/thumbor' + encrypted_url else: thumbnail_url = urllib.parse.urljoin(settings.THUMBOR_URL, encrypted_url) return thumbnail_url
class ThumborService(object): def __init__(self, baseurl='http://localhost:8888/', secretkey='MY_SECURE_KEY'): self.baseurl = baseurl.rstrip('/') self._urlgen = CryptoURL(key=secretkey) def generate_url(self, options): return self.baseurl + self._urlgen.generate(**options)
def thumb(img, **kwargs): ''' returns a thumbor url for 'img' with **kwargs as thumbor options. Positional arguments: img -- can be a string representing the image path or any object with a url property. Keyword arguments: For the complete list of thumbor options https://github.com/globocom/thumbor/wiki/Usage and the actual implementation for the url generation https://github.com/heynemann/libthumbor/blob/master/libthumbor/url.py ''' # url is DNS sharded url try: url = img.url except ValueError: # When trying to access the url of an image object when # the image does not exist, a ValueError is raised logger.exception("No file for object (%s) in thumbor", img.instance) return '' except AttributeError: # If it's an attribute error, assume it's a string already url = img if settings.THUMBOR_BASE_URL: # If THUMBOR_BASE_URL is explicity set, use that base = settings.THUMBOR_BASE_URL else: # otherwise assume that thumbor is setup behind the same # CDN behind the `thumbor` namespace. scheme, netloc = urlparse.urlsplit(url)[:2] base = '{}://{}/thumbor'.format(scheme, netloc) url = remove_url_scheme(url) # just for code clarity thumbor_kwargs = kwargs if 'fit_in' not in thumbor_kwargs: thumbor_kwargs['fit_in'] = True # normalizes url to make it work localy if settings.LOCAL: thumbor_kwargs['unsafe'] = True # strips 'media/' from the start of the url if url.startswith('media/'): url = url[len('media/'):] url = '{}/{}'.format(settings.AWS_S3_CUSTOM_DOMAIN, url) thumbor_kwargs['image_url'] = url crypto = CryptoURL(key=settings.THUMBOR_KEY) path = crypto.generate(**thumbor_kwargs).lstrip('/') return '{}/{}'.format(base, path)
def own_thumbnail(m, s): global thumbor proto = 'http%s' % s thumbor_base = config.thumbor % { 'proto': proto } if thumbor is None: thumbor = CryptoURL(key=config.thumbor_key) return thumbor_base+thumbor.generate(image_url=m(0), **config.thumbor_pars)
def fit_in_urls(self, original_url, sizes): crypto = CryptoURL(key=self._config.THUMBOR_SECURITY_KEY) unschemed_original_url = original_url.replace('http://', '') urls = {} for size in sizes: split_size = size.split('x') path = crypto.generate(image_url=unschemed_original_url, width=split_size[0], height=split_size[1], fit_in=True) urls[size] = self._config.THUMBOR_SERVER_URL.rstrip('/') + path return urls
def test_image_already_generated_by_thumbor(self): with open('./tests/fixtures/images/image.jpg', 'r') as f: self.context.modules.storage.put( quote("http://test.com/smart/image.jpg"), f.read() ) crypto = CryptoURL('ACME-SEC') image_url = self.get_url( crypto.generate( image_url=quote("http://test.com/smart/image.jpg") ) ) url = crypto.generate( image_url=quote(image_url) ) response = self.fetch(url) expect(response.code).to_equal(200)
def own_thumbnail(m, s): global thumbor proto = 'http%s' % s thumbor_base = config.thumbor % {'proto': proto} if thumbor is None: thumbor = CryptoURL(key=config.thumbor_key) return thumbor_base + thumbor.generate(image_url=m(0), **config.thumbor_pars)
def get_image_url(self, image_host, image_uuid, width=None, height=None): security_key = self.settings.get('thumbor.security_key') if not (security_key and image_host and image_uuid): return '' crypto = CryptoURL(key=security_key) if not (width or height): image_url = crypto.generate(image_url=image_uuid) elif width and height: image_url = crypto.generate( width=width, height=height, image_url=image_uuid) elif width: image_url = crypto.generate( width=width, height=0, image_url=image_uuid) else: image_url = crypto.generate( width=0, height=height, image_url=image_uuid) return urljoin(image_host, image_url)
def test_image_with_utf8_url(self): with open('./tests/fixtures/images/maracujá.jpg', 'r') as f: self.context.modules.storage.put( quote(u"http://test.com/maracujá.jpg".encode('utf-8')), f.read()) crypto = CryptoURL('ACME-SEC') image_url = self.get_url( quote(u"/unsafe/http://test.com/maracujá.jpg".encode('utf-8'))) url = crypto.generate(image_url=quote(image_url)) response = self.fetch(url) expect(response.code).to_equal(200)
async def test_image_with_utf8_url(self): with open("./tests/fixtures/images/maracujá.jpg", "rb") as fixture: await self.context.modules.storage.put( quote("http://test.com/maracujá.jpg".encode("utf-8")), fixture.read(), ) crypto = CryptoURL("ACME-SEC") image_url = self.get_url( quote("/unsafe/http://test.com/maracujá.jpg".encode("utf-8"))) url = crypto.generate(image_url=quote(image_url)) response = await self.async_fetch(url) expect(response.code).to_equal(200)
async def test_shouldnt_auto_convert_png_to_jpg_if_png_has_transparency_with_signed_images( # NOQA self, context_mock): context_mock.return_value = self.context crypto = CryptoURL("ACME-SEC") url = crypto.generate(image_url="watermark.png") self.context.request = self.get_request(url=url) # save on result storage response = await self.async_fetch(url) expect(response.code).to_equal(200) expect(response.headers).not_to_include("Vary") expect(response.body).to_be_png()
def _fetch_images(self): crypto = CryptoURL(key=self.context.server.security_key) image_ops = [] if not hasattr(self.context.config, 'DISTRIBUTED_COLLAGE_FILTER_HTTP_LOADER'): self.context.config.DISTRIBUTED_COLLAGE_FILTER_HTTP_LOADER = 'thumbor.loaders.http_loader' self.context.modules.importer.import_item( 'DISTRIBUTED_COLLAGE_FILTER_HTTP_LOADER') loader = self.context.modules.importer.distributed_collage_filter_http_loader for i, url in enumerate(self.urls): width = self.image_width if i < len( self.urls) - 1 else self.last_image_width params = { 'width': int(width), 'height': int(self.context.request.height), 'image_url': url, 'smart': True, 'halign': 'center', 'valign': 'middle', 'filters': ['quality(100)'], } thumbor_host = getattr( self.context.config, 'DISTRIBUTED_COLLAGE_FILTER_THUMBOR_SERVER_URL', '%s://%s' % ( self.context.request_handler.request.protocol, self.context.request_handler.request.host, ), ) encrypted_url = '%s%s' % (thumbor_host, crypto.generate(**params)) image_ops.append(loader.load(self.context, encrypted_url)) images = yield image_ops successful = all([image.successful for image in images]) if not successful: logger.error( 'Retrieving at least one of the collaged images failed: %s' % (', '.join( [image.error for image in images if not image.successful]), )) self.callback() return max_age = min([ self.get_max_age(image.metadata.get('Cache-Control'), self.max_age) for image in images ]) self.assembly_images(images) self.callback()
def test_can_auto_convert_jpeg_from_result_storage(self, context_mock): context_mock.return_value = self.context crypto = CryptoURL('ACME-SEC') url = crypto.generate(image_url=quote("http://test.com/smart/image.jpg")) self.context.request = self.get_request(url=url, accepts_webp=True) with open('./tests/fixtures/images/image.webp', 'r') as f: self.context.modules.result_storage.put(f.read()) response = self.get_as_webp(url) expect(response.code).to_equal(200) expect(response.headers).to_include('Vary') expect(response.headers['Vary']).to_include('Accept') expect(response.body).to_be_webp()
async def test_should_auto_convert_png_to_webp_if_auto_webp_is_true_and_png_has_transparency_with_signed_images( # NOQA self, context_mock): self.config.AUTO_WEBP = True context_mock.return_value = self.context crypto = CryptoURL("ACME-SEC") url = crypto.generate(image_url="watermark.png") self.context.request = self.get_request(url=url) # save on result storage response = await self.get_as_webp(url) expect(response.code).to_equal(200) expect(response.headers).to_include("Vary") expect(response.body).to_be_webp()
async def test_should_auto_convert_png_to_jpg_with_signed_images( self, context_mock): context_mock.return_value = self.context crypto = CryptoURL("ACME-SEC") url = crypto.generate( image_url="Giunchedi%2C_Filippo_January_2015_01.png") self.context.request = self.get_request(url=url) context_mock.return_value = self.context response = await self.async_fetch(url) expect(response.code).to_equal(200) expect(response.headers).not_to_include("Vary") expect(response.body).to_be_jpeg()
def test_thumbor_can_decrypt_lib_thumbor_generated_url_new_format(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_signer = Signer(key) crypto = CryptoURL(key=key) url = crypto.generate(width=300, height=200, smart=True, image_url=image) reg = "/([^/]+)/(.+)" (signature, url) = re.match(reg, url).groups() assert thumbor_signer.validate(signature, url)
async def test_should_auto_convert_png_to_webp_if_auto_webp_is_true_with_signed_images( # NOQA self, context_mock): self.config.AUTO_WEBP = True context_mock.return_value = self.context crypto = CryptoURL("ACME-SEC") url = crypto.generate( image_url="Giunchedi%2C_Filippo_January_2015_01.png") self.context.request = self.get_request(url=url, accepts_webp=True) # save on result storage response = await self.get_as_webp(url) expect(response.code).to_equal(200) expect(response.headers).to_include("Vary") expect(response.body).to_be_webp()
def thumborurl(image, size): ''' Método que cria, através da libthumbor a url codificada para exibição de imagens na galeria ''' #print "CODIFICANDO:", size, image crypto = CryptoURL(key=app.config['THUMBOR_KEY']) codigo = crypto.generate( width=size[0] if isinstance(size[0], int) else None, height=size[1] if isinstance(size[1], int) else None, smart=True, image_url=image.replace('http://', '')) #print "CODIGO:", codigo return app.config['THUMBOR_URL'] + codigo
def thumbor_filter(ctx, image, width, height=0): registry = get_current_registry(context=ctx) security_key = registry.settings.get('thumbor.security_key') if not all([security_key, image]): return '' # libthumbor generates an invalid url when height is None: # https://github.com/thumbor/libthumbor/blob/master/libthumbor/url.py#L19 # Coerce it to 0. This scales the height proportionally. if height is None: height = 0 crypto = CryptoURL(key=security_key) return crypto.generate(width=width, height=height, image_url=image)
async def test_can_auto_convert_jpeg_from_result_storage( self, context_mock): # NOQA context_mock.return_value = self.context crypto = CryptoURL("ACME-SEC") url = crypto.generate( image_url=quote("http://test.com/smart/image.jpg")) self.context.request = self.get_request(url=url, accepts_webp=True) with open("./tests/fixtures/images/image.webp", "rb") as fixture: await self.context.modules.result_storage.put(fixture.read()) response = await self.get_as_webp(url) expect(response.code).to_equal(200) expect(response.headers).to_include("Vary") expect(response.headers["Vary"]).to_include("Accept") expect(response.body).to_be_webp()
def thumborurl(image, size): ''' Método que cria, através da libthumbor a url codificada para exibição de imagens na galeria ''' #print "CODIFICANDO:", size, image crypto = CryptoURL(key=app.config['THUMBOR_KEY']) codigo = crypto.generate( width=size[0] if isinstance(size[0], int) else None, height=size[1] if isinstance(size[1], int) else None, smart=True, image_url=image.replace('http://','') ) #print "CODIGO:", codigo return app.config['THUMBOR_URL'] + codigo
def test_image_with_utf8_url(self): with open('./tests/fixtures/images/maracujá.jpg', 'r') as f: self.context.modules.storage.put( quote(u"http://test.com/maracujá.jpg".encode('utf-8')), f.read() ) crypto = CryptoURL('ACME-SEC') image_url = self.get_url( quote(u"/unsafe/http://test.com/maracujá.jpg".encode('utf-8')) ) url = crypto.generate( image_url=quote(image_url) ) response = self.fetch(url) expect(response.code).to_equal(200)
def generate_thumbnail_url(path: str, size: str = '0x0', is_camo_url: bool = False) -> str: path = urljoin("/", path) if not is_thumbor_enabled(): if is_safe_url(path, allowed_hosts=None): return path return get_camo_url(path) if is_safe_url( path, allowed_hosts=None) and not path.startswith("/user_uploads/"): return path source_type = get_source_type(path) safe_url = base64.urlsafe_b64encode(path.encode()).decode('utf-8') image_url = f'{safe_url}/source_type/{source_type}' width, height = map(int, size.split('x')) crypto = CryptoURL(key=settings.THUMBOR_KEY) smart_crop_enabled = True apply_filters = ['no_upscale()'] if is_camo_url: smart_crop_enabled = False apply_filters.append('quality(100)') if size != '0x0': apply_filters.append('sharpen(0.5,0.2,true)') encrypted_url = crypto.generate( width=width, height=height, smart=smart_crop_enabled, filters=apply_filters, image_url=image_url, ) if settings.THUMBOR_URL == 'http://127.0.0.1:9995': # If THUMBOR_URL is the default then thumbor is hosted on same machine # as the Zulip server and we should serve a relative URL. # We add a /thumbor in front of the relative url because we make # use of a proxy pass to redirect request internally in Nginx to 9995 # port where thumbor is running. thumbnail_url = '/thumbor' + encrypted_url else: thumbnail_url = urllib.parse.urljoin(settings.THUMBOR_URL, encrypted_url) return thumbnail_url
def test_thumbor_can_decrypt_lib_thumbor_generated_url_new_format(): key = "my-security-key" image = "s.glbimg.com/et/bb/f/original/2011/03/24/VN0JiwzmOw0b0lg.jpg" thumbor_signer = Signer(key) crypto = CryptoURL(key=key) url = crypto.generate( width=300, height=200, smart=True, image_url=image ) reg = "/([^/]+)/(.+)" (signature, url) = re.match(reg, url).groups() assert thumbor_signer.validate(b(signature), url)
def thumb(img, **kwargs): """ Uses thumbor to prepare image served by S3. """ image_url = img.url if hasattr(img, 'url') else img if settings.LOCAL: image_url = u"{}{}".format("http://localhost:8000", image_url) kwargs['image_url'] = image_url base = settings.THUMBOR_BASE_URL crypto = CryptoURL(key=settings.THUMBOR_KEY) path = crypto.generate(**kwargs) # With the unsafe option, path has no leading slash # so we add it ourselves if kwargs.get('unsafe'): path = "/{}".format(path) return u'{}{}'.format(base, path)
def thumb(url, **kwargs): """ Inspired by: http://tech.yipit.com/2013/01/03/how-yipit-scales-thumbnailing-with-thumbor-and-cloudfront/ returns a thumbor url for 'url' with **kwargs as thumbor options. Positional arguments: url -- the location of the original image Keyword arguments: For the complete list of thumbor options https://github.com/globocom/thumbor/wiki/Usage and the actual implementation for the url generation https://github.com/heynemann/libthumbor/blob/master/libthumbor/url.py """ THUMBOR_BASE_URL = getattr(settings, 'THUMBOR_BASE_URL', None) THUMBOR_KEY = getattr(settings, 'THUMBOR_KEY', 'MY_SECURE_KEY') if THUMBOR_BASE_URL: base = THUMBOR_BASE_URL else: # otherwise assume that thumbor is setup behind the same # CDN behind the `thumbor` namespace. scheme, netloc = urlparse.urlsplit(url)[:2] base = '{}://{}/thumbor'.format(scheme, netloc) crypto = CryptoURL(key=THUMBOR_KEY) # just for code clarity thumbor_kwargs = kwargs if not 'fit_in' in thumbor_kwargs: thumbor_kwargs['fit_in'] = True thumbor_kwargs['image_url'] = url path = crypto.generate(**thumbor_kwargs) return u'{}{}'.format(base, path)
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') crypto = CryptoURL(key=security_key) url = crypto.generate( old=parsed_options.old, 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, image_url=image_url, ) print 'URL:' print url return url
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", action="append", help="Filters to be applied to the image, e.g. brightness(10).", ) 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") options = { "old": parsed_options.old, "width": parsed_options.width, "height": parsed_options.height, "smart": parsed_options.smart, "meta": parsed_options.meta, "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, "image_url": image_url, } if parsed_options.fitin and parsed_options.full and parsed_options.adaptive: options["adaptive_full_fit_in"] = True elif parsed_options.fitin and parsed_options.full: options["full_fit_in"] = True elif parsed_options.fitin and parsed_options.adaptive: options["adaptive_fit_in"] = True elif parsed_options.fitin: options["fit_in"] = True crypto = CryptoURL(key=security_key) url = crypto.generate(**options) print "URL:" print url return url
def thumbor_image_url(key): crypto = CryptoURL(key=settings.THUMBOR_SECURITY_KEY) return "%s%s" % (settings.THUMBOR_SERVER, crypto.generate(image_url=key))
## This program is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public License ## as published by the Free Software Foundation; either version 2 ## of the License, or (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU Lesser General Public License for more details. ## ## You should have received a copy of the GNU Lesser General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., or visit: http://www.gnu.org/. ## ## import urlparse from libthumbor import CryptoURL SECRET_KEY = 'MY_SECURE_KEY' THUMBOR_SERVER = 'http://127.0.0.1:8888' # upload & get the thumbnail url crypto = CryptoURL(key=SECRET_KEY) image_url = crypto.generate(width=150, height=150, image_url='29.media.tumblr.com/tumblr_lltzgnHi5F1qzib3wo1_400.jpg') print urlparse.urljoin(THUMBOR_SERVER, image_url)