예제 #1
0
파일: crypto.py 프로젝트: douglas/thumbor
    def encrypt(self, 
                width,
                height,
                smart,
                fit_in,
                flip_horizontal,
                flip_vertical,
                halign,
                valign,
                crop_left,
                crop_top,
                crop_right,
                crop_bottom,
                image):

        url = "%s/%s" % (Url.generate_options(width,
                                              height,
                                              smart,
                                              False,
                                              fit_in,
                                              flip_horizontal,
                                              flip_vertical,
                                              halign,
                                              valign,
                                              crop_left,
                                              crop_top,
                                              crop_right,
                                              crop_bottom),
                        hashlib.md5(image).hexdigest())

        pad = lambda s: s + (16 - len(s) % 16) * "{"
        cipher = AES.new(self.salt)
        encrypted = base64.urlsafe_b64encode(cipher.encrypt(pad(url)))

        return encrypted
예제 #2
0
파일: test_url.py 프로젝트: 5um1th/thumbor
    def test_can_generate_url(self):
        url = Url.generate_options(
            debug=True,
            width=300,
            height=200,
            smart=True,
            meta=True,
            trim=True,
            adaptive=True,
            full=True,
            fit_in=True,
            horizontal_flip=True,
            vertical_flip=True,
            halign='left',
            valign='top',
            crop_left=100,
            crop_top=100,
            crop_right=400,
            crop_bottom=400,
            filters='brightness(100)'
        )

        expect(url).to_equal(
            'debug/meta/trim/100x100:400x400/adaptive-full-fit-in/-300x-200/left/top/smart/filters:brightness(100)'
        )
예제 #3
0
    def encrypt(self, width, height, smart, adaptive, full, fit_in,
                flip_horizontal, flip_vertical, halign, valign, trim,
                crop_left, crop_top, crop_right, crop_bottom, filters, image):

        generated_url = Url.generate_options(width=width,
                                             height=height,
                                             smart=smart,
                                             meta=False,
                                             adaptive=adaptive,
                                             full=full,
                                             fit_in=fit_in,
                                             horizontal_flip=flip_horizontal,
                                             vertical_flip=flip_vertical,
                                             halign=halign,
                                             valign=valign,
                                             trim=trim,
                                             crop_left=crop_left,
                                             crop_top=crop_top,
                                             crop_right=crop_right,
                                             crop_bottom=crop_bottom,
                                             filters=filters)

        url = "%s/%s" % (generated_url, hashlib.md5(image).hexdigest())

        def pad(s):
            return s + (16 - len(s) % 16) * "{"

        cipher = AES.new(self.security_key, MODE_ECB)
        encrypted = base64.urlsafe_b64encode(
            cipher.encrypt(pad(url.encode('utf-8'))))

        return encrypted
예제 #4
0
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
예제 #5
0
def test_url_generate_min():
    url = Url.generate_options(
        width=300,
        height=200
    )

    assert url == "300x200"
예제 #6
0
def test_url_generate_with_alignments():
    url = Url.generate_options(
        halign='left',
        valign='top'
    )

    assert url == "0x0/left/top", url
예제 #7
0
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
예제 #8
0
def test_url_generate_with_smart():
    url = Url.generate_options(
        width=300,
        height=200,
        smart=True
    )

    assert url == "300x200/smart"
예제 #9
0
def test_url_generate_with_flipping():
    url = Url.generate_options(width=300,
                               height=200,
                               smart=True,
                               horizontal_flip=True,
                               vertical_flip=True)

    assert url == '-300x-200/smart'
예제 #10
0
def test_url_generate_with_manual_crop():
    url = Url.generate_options(width=300,
                               height=200,
                               crop_left=10,
                               crop_top=11,
                               crop_right=12,
                               crop_bottom=13)

    assert url == '10x11:12x13/300x200'
예제 #11
0
def test_url_generate_with_flipping():
    url = Url.generate_options(
        width=300,
        height=200,
        smart=True,
        horizontal_flip=True,
        vertical_flip=True
    )

    assert url == "-300x-200/smart"
예제 #12
0
def test_url_generate_with_manual_crop():
    url = Url.generate_options(
        width=300,
        height=200,
        crop_left=10,
        crop_top=11,
        crop_right=12,
        crop_bottom=13
    )

    assert url == "10x11:12x13/300x200"
예제 #13
0
def test_complete_url():
    url = Url.generate_options(width=300,
                               height=200,
                               smart=True,
                               meta=True,
                               horizontal_flip=True,
                               vertical_flip=True,
                               crop_left=10,
                               crop_top=11,
                               crop_right=12,
                               crop_bottom=13)

    assert url == 'meta/10x11:12x13/-300x-200/smart', url
예제 #14
0
파일: crypto.py 프로젝트: torkil/thumbor
    def encrypt(self, width, height, smart, fit_in, flip_horizontal,
                flip_vertical, halign, valign, crop_left, crop_top, crop_right,
                crop_bottom, image):

        url = "%s/%s" % (Url.generate_options(
            width, height, smart, False, fit_in, flip_horizontal,
            flip_vertical, halign, valign, crop_left, crop_top, crop_right,
            crop_bottom), hashlib.md5(image).hexdigest())

        pad = lambda s: s + (16 - len(s) % 16) * "{"
        cipher = AES.new(self.salt)
        encrypted = base64.urlsafe_b64encode(cipher.encrypt(pad(url)))

        return encrypted
예제 #15
0
def test_complete_url():
    url = Url.generate_options(
        width=300,
        height=200,
        smart=True,
        meta=True,
        horizontal_flip=True,
        vertical_flip=True,
        crop_left=10,
        crop_top=11,
        crop_right=12,
        crop_bottom=13
    )

    assert url == "meta/10x11:12x13/-300x-200/smart", url
예제 #16
0
파일: crypto.py 프로젝트: okor/thumbor
    def encrypt(self,
                width,
                height,
                smart,
                adaptive,
                full,
                fit_in,
                flip_horizontal,
                flip_vertical,
                halign,
                valign,
                trim,
                crop_left,
                crop_top,
                crop_right,
                crop_bottom,
                filters,
                image):

        generated_url = Url.generate_options(
            width=width,
            height=height,
            smart=smart,
            meta=False,
            adaptive=adaptive,
            full=full,
            fit_in=fit_in,
            horizontal_flip=flip_horizontal,
            vertical_flip=flip_vertical,
            halign=halign,
            valign=valign,
            trim=trim,
            crop_left=crop_left,
            crop_top=crop_top,
            crop_right=crop_right,
            crop_bottom=crop_bottom,
            filters=filters
        )

        url = "%s/%s" % (generated_url, hashlib.md5(image).hexdigest())

        def pad(s):
            return s + (16 - len(s) % 16) * "{"

        cipher = AES.new(self.security_key, MODE_ECB)
        encrypted = base64.urlsafe_b64encode(cipher.encrypt(pad(url.encode('utf-8'))))

        return encrypted
예제 #17
0
파일: crypto.py 프로젝트: bguided/thumbor
    def encrypt(
        self,
        width,
        height,
        smart,
        adaptive,
        fit_in,
        flip_horizontal,
        flip_vertical,
        halign,
        valign,
        crop_left,
        crop_top,
        crop_right,
        crop_bottom,
        filters,
        image,
    ):

        url = "%s/%s" % (
            Url.generate_options(
                width=width,
                height=height,
                smart=smart,
                meta=False,
                adaptive=adaptive,
                fit_in=fit_in,
                horizontal_flip=flip_horizontal,
                vertical_flip=flip_vertical,
                halign=halign,
                valign=valign,
                crop_left=crop_left,
                crop_top=crop_top,
                crop_right=crop_right,
                crop_bottom=crop_bottom,
                filters=filters,
            ),
            hashlib.md5(image).hexdigest(),
        )

        pad = lambda s: s + (16 - len(s) % 16) * "{"
        cipher = AES.new(self.security_key)
        encrypted = base64.urlsafe_b64encode(cipher.encrypt(pad(url.encode("utf-8"))))

        return encrypted
예제 #18
0
파일: crypto.py 프로젝트: rahbirul/thumbor
    def encrypt(self, 
                width,
                height,
                smart,
                adaptive,
                fit_in,
                flip_horizontal,
                flip_vertical,
                halign,
                valign,
                crop_left,
                crop_top,
                crop_right,
                crop_bottom,
                filters,
                image):

        url = "%s/%s" % (Url.generate_options(width=width,
                                              height=height,
                                              smart=smart,
                                              meta=False,
                                              adaptive=adaptive,
                                              fit_in=fit_in,
                                              horizontal_flip=flip_horizontal,
                                              vertical_flip=flip_vertical,
                                              halign=halign,
                                              valign=valign,
                                              crop_left=crop_left,
                                              crop_top=crop_top,
                                              crop_right=crop_right,
                                              crop_bottom=crop_bottom,
                                              filters=filters),
                        hashlib.md5(image).hexdigest())

        pad = lambda s: s + (16 - len(s) % 16) * "{"
        cipher = AES.new(self.salt)
        encrypted = base64.urlsafe_b64encode(cipher.encrypt(pad(url.encode('utf-8'))))

        return encrypted
예제 #19
0
    def test_can_generate_url(self):
        url = Url.generate_options(debug=True,
                                   width=300,
                                   height=200,
                                   smart=True,
                                   meta=True,
                                   trim=True,
                                   adaptive=True,
                                   full=True,
                                   fit_in=True,
                                   horizontal_flip=True,
                                   vertical_flip=True,
                                   halign='left',
                                   valign='top',
                                   crop_left=100,
                                   crop_top=100,
                                   crop_right=400,
                                   crop_bottom=400,
                                   filters='brightness(100)')

        expect(url).to_equal(
            'debug/meta/trim/100x100:400x400/adaptive-full-fit-in/-300x-200/left/top/smart/filters:brightness(100)'
        )
예제 #20
0
def test_url_generate_min():
    url = Url.generate_options(width=300, height=200)

    assert url == '300x200'
예제 #21
0
def test_default_url():
    url = Url.generate_options()
    assert url == "0x0"
예제 #22
0
def test_url_generate_with_meta():
    url = Url.generate_options(
        meta=True
    )

    assert url == "meta/0x0"
예제 #23
0
def test_url_generate_with_smart():
    url = Url.generate_options(width=300, height=200, smart=True)

    assert url == '300x200/smart'
예제 #24
0
def test_url_generate_with_alignments():
    url = Url.generate_options(halign='left', valign='top')

    assert url == '0x0/left/top', url
예제 #25
0
def test_url_generate_with_meta():
    url = Url.generate_options(meta=True)

    assert url == 'meta/0x0'
예제 #26
0
    def test_can_generate_url_with_fitin(self):
        url = Url.generate_options(fit_in=True, adaptive=False, full=False)

        expect(url).to_equal('fit-in')
예제 #27
0
파일: test_url.py 프로젝트: 5um1th/thumbor
    def test_can_generate_url_with_defaults(self):
        url = Url.generate_options()

        expect(url).to_be_empty()
예제 #28
0
파일: test_url.py 프로젝트: 5um1th/thumbor
    def test_can_generate_url_with_fitin(self):
        url = Url.generate_options(fit_in=True, adaptive=False, full=False)

        expect(url).to_equal('fit-in')
예제 #29
0
파일: url_composer.py 프로젝트: mal/thumbor
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
예제 #30
0
 def topic(self):
     return Url.generate_options(**kw)
예제 #31
0
파일: url_vows.py 프로젝트: cezarsa/thumbor
 def topic(self):
     return Url.generate_options(**kw)
예제 #32
0
    def validate_image_permutations(self, kw):
        security_key = None
        if self.context.config.STORES_CRYPTO_KEY_FOR_EACH_IMAGE:
            security_key = yield gen.maybe_future(
                self.context.modules.storage.get_crypto(
                    self.context.request.image_url))

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

        if self.validate_url(self.request.path, security_key):
            return
        else:
            # From the kw args given, generate a URL options fragment
            args = kw.copy()
            del args['hash']
            del args['image']
            del args['unsafe']
            args = dict((k, v) for k, v in args.iteritems() if v)
            url_options = Url.generate_options(**args)

            load_target = kw['image']

            # Undo `:` decoding
            load_target_with_encoded_colon = load_target.replace(':', '%3A')
            unescaped_url = "/%s/%s/%s" % (kw['hash'], url_options,
                                           load_target_with_encoded_colon)
            if self.validate_url(unescaped_url, security_key):
                kw['image'] = unquote(load_target_with_encoded_colon)
                self.request.path = unescaped_url
                return

            # Undo collapsed slashes with encoded `:`
            collapsed_slash = RE_SINGLE_SLASH_ENCODED.match(
                load_target_with_encoded_colon)
            if collapsed_slash:
                load_target_with_encoded_colon = load_target_with_encoded_colon.replace(
                    collapsed_slash.group(1),
                    collapsed_slash.group(1) + "/")
                unescaped_url = "/%s/%s/%s" % (kw['hash'], url_options,
                                               load_target_with_encoded_colon)
                if self.validate_url(unescaped_url, security_key):
                    kw['image'] = unquote(load_target_with_encoded_colon)
                    self.request.path = unescaped_url
                    return

            # Undo %3A -> %253A encoding (can have multiple 252525...)
            quoted_target = quote(load_target.encode('utf-8'))
            encoded_percentage = RE_ENCODED_PERCENTAGE.match(quoted_target)
            if encoded_percentage:
                fixed_target = quoted_target.replace(
                    encoded_percentage.group(1), '%3A')
                fixed_url = "/%s/%s/%s" % (kw['hash'], url_options,
                                           fixed_target)
                if self.validate_url(fixed_url, security_key):
                    kw['image'] = unquote(fixed_target)
                    self.request.path = fixed_url
                    return

            # Undo collapsed slashes
            collapsed_slash = RE_SINGLE_SLASH.match(load_target)
            if collapsed_slash:
                load_target = load_target.replace(
                    collapsed_slash.group(1),
                    collapsed_slash.group(1) + "/")
                unescaped_url = "/%s/%s/%s" % (kw['hash'], url_options,
                                               load_target)
                if self.validate_url(unescaped_url, security_key):
                    kw['image'] = load_target
                    self.request.path = unescaped_url
                    return

            # Attempt to validate with unescaped quoting
            load_target = quote(load_target.encode('utf-8'), safe='')
            unescaped_url = "/%s/%s/%s" % (kw['hash'], url_options,
                                           load_target)
            if self.validate_url(unescaped_url, security_key):
                kw['image'] = unquote(load_target)
                self.request.path = unescaped_url
                return

            # Attempt to validate with unquoting
            load_target = unquote(kw['image'])
            unescaped_url = "/%s/%s/%s" % (kw['hash'], url_options,
                                           quote(load_target.encode('utf-8'),
                                                 safe=''))
            if self.validate_url(unescaped_url, security_key):
                self.request.path = unescaped_url
                kw['image'] = load_target
예제 #33
0
def test_default_url():
    url = Url.generate_options()
    assert url == '0x0'
예제 #34
0
    def test_can_generate_url_with_defaults(self):
        url = Url.generate_options()

        expect(url).to_be_empty()
예제 #35
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