示例#1
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    do_delete = params['do_delete']
    file_hash = params['file_hash']
    username = params['username']
    emails = params['emails']
    openids = params['openids']
    photos = params['photos']

    # Validate inputs
    if file_hash and not is_hex(file_hash):
        LOGGER.error('file_hash is not a hexadecimal value')
        return 1
    for photo in photos:
        (photo_filename, photo_format) = photo
        if not is_hex(photo_filename):
            LOGGER.error("photo_filename '%s' is not a hexadecimal value",
                         photo_filename)
            return 1
        if photo_format != 'jpg' and photo_format != 'png' and photo_format != 'gif':
            LOGGER.error("photo_format '%s' is not recognized", photo_format)
            return 1

    dest_filename = settings.EXPORT_FILES_ROOT + file_hash + '.xml.gz'
    destination = gzip.open(dest_filename, 'w')
    destination.write(xml_header())
    destination.write(xml_account(username))
    destination.write(xml_list('email', emails))
    destination.write(xml_list('openid', openids))
    destination.write(xml_photos(photos))
    destination.write(xml_footer())
    destination.close()

    if do_delete:  # Delete files on disk
        gm_client = gearman.GearmanClient(settings.GEARMAN_SERVERS)
        for photo in photos:
            (photo_filename, photo_format) = photo
            workload = {'file_hash': photo_filename, 'format': photo_format}
            gm_client.submit_job('deletephoto',
                                 json.dumps(workload),
                                 background=True,
                                 wait_until_complete=False)

    return 0
示例#2
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    do_delete = params['do_delete']
    file_hash = params['file_hash']
    username = params['username']
    emails = params['emails']
    openids = params['openids']
    photos = params['photos']

    # Validate inputs
    if file_hash and not is_hex(file_hash):
        logger.error('file_hash is not a hexadecimal value')
        return 1
    for photo in photos:
        (photo_filename, photo_format) = photo
        if not is_hex(photo_filename):
            logger.error("photo_filename '%s' is not a hexadecimal value" % photo_filename)
            return 1
        if photo_format != 'jpg' and photo_format != 'png' and photo_format != 'gif':
            logger.error("photo_format '%s' is not recognized" % photo_format)
            return 1

    dest_filename = settings.EXPORT_FILES_ROOT + file_hash + '.xml.gz'
    destination = gzip.open(dest_filename, 'w')
    destination.write(xml_header())
    destination.write(xml_account(username))
    destination.write(xml_list('email', emails))
    destination.write(xml_list('openid', openids))
    destination.write(xml_photos(photos))
    destination.write(xml_footer())
    destination.close()

    if do_delete:  # Delete files on disk
        gm_client = libgearman.Client()
        for server in settings.GEARMAN_SERVERS:
            gm_client.add_server(server)

        for photo in photos:
            (photo_filename, photo_format) = photo
            workload = {'file_hash': photo_filename, 'format': photo_format}
            gm_client.do_background('deletephoto', json.dumps(workload))

    return 0
示例#3
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    photo_hash = params['photo_hash']
    photo_format = params['photo_format']
    md5_hash = params['md5_hash']
    sha256_hash = params['sha256_hash']

    # Validate inputs
    if photo_hash and not is_hex(photo_hash):
        LOGGER.error('photo_hash is not a hexadecimal value')
        return 1
    if photo_format and photo_format != 'jpg' and photo_format != 'png' and photo_format != 'gif':
        LOGGER.error('photo_format is not recognized')
        return 1
    if md5_hash and not is_hex(md5_hash):
        LOGGER.error('md5_hash is not a hexadecimal value')
        return 1
    if not is_hex(sha256_hash):  # mandatory
        LOGGER.error('sha256_hash is not a hexadecimal value')
        return 1

    # Remove old image
    if md5_hash:
        delete_if_exists(settings.AVATAR_ROOT + md5_hash)
    delete_if_exists(settings.AVATAR_ROOT + sha256_hash)

    # Delete all resized images
    for size in xrange(settings.AVATAR_MIN_SIZE, settings.AVATAR_MAX_SIZE):
        size_dir = settings.AVATAR_ROOT + '%s/' % size

        if md5_hash:
            delete_if_exists(size_dir + md5_hash)
        delete_if_exists(size_dir + sha256_hash)

    if not photo_hash:
        return 0

    source_filename = settings.USER_FILES_ROOT + photo_hash + '.' + photo_format
    return create_links(source_filename, md5_hash, sha256_hash)
示例#4
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    photo_hash = params['photo_hash']
    photo_format = params['photo_format']
    md5_hash = params['md5_hash']
    sha256_hash = params['sha256_hash']

    # Validate inputs
    if photo_hash and not is_hex(photo_hash):
        logger.error('photo_hash is not a hexadecimal value')
        return 1
    if photo_format and photo_format != 'jpg' and photo_format != 'png' and photo_format != 'gif':
        logger.error('photo_format is not recognized')
        return 1
    if md5_hash and not is_hex(md5_hash):
        logger.error('md5_hash is not a hexadecimal value')
        return 1
    if not is_hex(sha256_hash):  # mandatory
        logger.error('sha256_hash is not a hexadecimal value')
        return 1

    # Remove old image
    if md5_hash:
        delete_if_exists(settings.AVATAR_ROOT + md5_hash)
    delete_if_exists(settings.AVATAR_ROOT + sha256_hash)

    # Delete all resized images
    for size in xrange(settings.AVATAR_MIN_SIZE, settings.AVATAR_MAX_SIZE):
        size_dir = settings.AVATAR_ROOT + '%s/' % size

        if md5_hash:
            delete_if_exists(size_dir + md5_hash)
        delete_if_exists(size_dir + sha256_hash)

    if not photo_hash:
        return 0

    source_filename = settings.USER_FILES_ROOT + photo_hash + '.' + photo_format
    return create_links(source_filename, md5_hash, sha256_hash)
示例#5
0
    def int_to_argument(self, key, value, gen_arg):
        res = 0

        if value == None:
            gen_arg.add_int(key, int(-1))
        else:
            if utils.is_hex(value):
                gen_arg.add_int(key, int(value, 16))
            elif utils.is_int(value):
                gen_arg.add_int(key, int(value))
            else:
                print "Value error: value <", value, "> cannot be converted to int"
                res = -1
        return res
示例#6
0
    def int_to_argument(self, key, value, gen_arg):
        res = 0

        if value == None:
            gen_arg.add_int(key, int(-1))
        else:
            if utils.is_hex(value):
                gen_arg.add_int(key, int(value, 16))
            elif utils.is_int(value):
                gen_arg.add_int(key, int(value))
            else:
                print "Value error: value <", value, "> cannot be converted to int"
                res = -1
        return res
示例#7
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    x = int(params['x'])
    y = int(params['y'])
    w = int(params['w'])
    h = int(params['h'])
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        logger.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        logger.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        logger.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            logger.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    return_code = crop(filename, x, y, w, h)
    if return_code != 0:
        return return_code

    gm_client = libgearman.Client()
    for server in settings.GEARMAN_SERVERS:
        gm_client.add_server(server)

    params = {'file_hash': file_hash, 'format': file_format, 'links': links}
    gm_client.do_background('ready2user', json.dumps(params))

    return 0
示例#8
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    x = int(params['x'])
    y = int(params['y'])
    w = int(params['w'])
    h = int(params['h'])
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        logger.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        logger.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        logger.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            logger.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    return_code = crop(filename, x, y, w, h)
    if return_code != 0:
        return return_code

    gm_client = libgearman.Client()
    for server in settings.GEARMAN_SERVERS:
        gm_client.add_server(server)

    params = {'file_hash': file_hash, 'format': file_format, 'links': links}
    gm_client.do_background('ready2user', json.dumps(params))

    return 0
示例#9
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    x = int(params['x'])
    y = int(params['y'])
    w = int(params['w'])
    h = int(params['h'])
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        LOGGER.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        LOGGER.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        LOGGER.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            LOGGER.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    return_code = crop(filename, x, y, w, h)
    if return_code != 0:
        return return_code

    gm_client = gearman.GearmanClient(settings.GEARMAN_SERVERS)
    params = {'file_hash': file_hash, 'format': file_format, 'links': links}
    gm_client.submit_job('ready2user',
                         json.dumps(params),
                         background=True,
                         wait_until_complete=False)

    return 0
示例#10
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    x = int(params['x'])
    y = int(params['y'])
    w = int(params['w'])
    h = int(params['h'])
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        LOGGER.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        LOGGER.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        LOGGER.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            LOGGER.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    return_code = crop(filename, x, y, w, h)
    if return_code != 0:
        return return_code

    gm_client = gearman.GearmanClient(settings.GEARMAN_SERVERS)
    params = {'file_hash': file_hash, 'format': file_format, 'links': links}
    gm_client.submit_job('ready2user', json.dumps(params),
                         background=True, wait_until_complete=False)

    return 0
示例#11
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    email_hash = params['email_hash']
    size = int(params['size'])

    # Validate inputs
    if not is_hex(email_hash):
        logger.error('email_hash is not a hexadecimal value')
        return 1

    resize_image(email_hash, size)

    # TODO: use find -inum on the original inode to find other hashes
    # then hardlink the resized image to the other hashes

    return 0
示例#12
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    email_hash = params['email_hash']
    size = int(params['size'])

    # Validate inputs
    if not is_hex(email_hash):
        LOGGER.error('email_hash is not a hexadecimal value')
        return 1

    resize_image(email_hash, size)

    # TODO: use find -inum on the original inode to find other hashes
    # then hardlink the resized image to the other hashes

    return 0
示例#13
0
    def from_human(cls, data):
        hex_str = []
        try:
            d = shlex.split(data, posix=False)
        except Exception:
            d = data.split()
        while 1:
            if len(d) == 0:
                break
            word = d[0]
            d = d[1:]

            if word.startswith('PUSHDATA'):
                continue

            opcode = opcodes.opcodes_by_name.get(word)
            if opcode is not None:
                hex_str.append(
                    format_hex_string(hex(opcode), with_prefix=False))
                continue

            # data to be pushed
            pushdata = word

            # Make sure hex is formatted.
            if is_hex(pushdata):
                if pushdata.startswith('0x'):
                    pushdata = pushdata[2:]
                if len(pushdata) % 2 != 0:
                    pushdata = ''.join(['0', pushdata])
            # Hex-encode text.
            else:
                if pushdata.startswith('"') and pushdata.endswith('"'):
                    pushdata = pushdata[1:-1]
                pushdata = pushdata.encode('hex')
            hex_str.append(push_script(pushdata))

        hex_str = ''.join(hex_str)
        return cls(hex_str.decode('hex'))
示例#14
0
    def __parse_args(self, words, ip):
        assert len(words) <= 2
        args = []
        for w in words:
            if w.startswith('IP'):
                memory_code = 200
                sign = w[2]
                assert sign == '+' or sign == '-'
                offset = int(w[3:])

                if sign == '+':
                    args.append(memory_code + ip + offset)
                else:
                    args.append(memory_code + ip - offset)
            elif w.startswith('SP'):
                stack_code = 100
                offset = 0
                if len(w) > 2:
                    sign = w[2]
                    assert sign == '-'
                    offset = int(w[3:])
                args.append(stack_code + offset)

            elif w.isnumeric():
                args.append(int(w))
            elif is_hex(w):
                memory_code = 200
                addr = int(w, 16)
                # addr += 1  # offset for IP written in memory[0]
                args.append(memory_code + addr)
                if addr >= len(self.memory):
                    raise MemoryError
            else:  # label or variable  #TODO variable
                if w in self.labels:
                    memory_code = 200
                    args.append(memory_code + self.labels[w])
                else:  # label not found yet
                    args.append(w)
        return args
示例#15
0
    def from_human(cls, data):
        hex_str = []
        try:
            d = shlex.split(data, posix=False)
        except Exception:
            d = data.split()
        while 1:
            if len(d) == 0:
                break
            word = d[0]
            d = d[1:]

            if word.startswith('PUSHDATA'):
                continue

            opcode = opcodes.opcodes_by_name.get(word)
            if opcode is not None:
                hex_str.append(format_hex_string(hex(opcode), with_prefix=False))
                continue

            # data to be pushed
            pushdata = word

            # Make sure hex is formatted.
            if is_hex(pushdata):
                if pushdata.startswith('0x'):
                    pushdata = pushdata[2:]
                if len(pushdata) % 2 != 0:
                    pushdata = ''.join(['0', pushdata])
            # Hex-encode text.
            else:
                if pushdata.startswith('"') and pushdata.endswith('"'):
                    pushdata = pushdata[1:-1]
                pushdata = pushdata.encode('hex')
            hex_str.append(push_script(pushdata))

        hex_str = ''.join(hex_str)
        return cls(hex_str.decode('hex'))
示例#16
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']

    # Validate inputs
    if not is_hex(file_hash):
        logger.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        logger.error('file_format is not recognized')
        return 1

    filename = "%s.%s" % (file_hash, file_format)
    delete_if_exists(settings.UPLOADED_FILES_ROOT + filename)
    delete_if_exists(settings.USER_FILES_ROOT + filename)

    return 0
示例#17
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']

    # Validate inputs
    if not is_hex(file_hash):
        LOGGER.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        LOGGER.error('file_format is not recognized')
        return 1

    filename = "%s.%s" % (file_hash, file_format)
    delete_if_exists(settings.UPLOADED_FILES_ROOT + filename)
    delete_if_exists(settings.USER_FILES_ROOT + filename)

    return 0
示例#18
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        LOGGER.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        LOGGER.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        LOGGER.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            LOGGER.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    source = settings.READY_FILES_ROOT + filename
    dest = settings.USER_FILES_ROOT + filename

    # Sanity checks
    if os.path.isfile(dest):
        LOGGER.warning('Destination already exists')
        return 0

    if not os.path.isfile(source):
        LOGGER.error('Source file not found')
        return 1

    # Change file ownership so that it can no longer be modified
    try:
        os.chown(source, 0, 0)  # root:root
    except:
        LOGGER.error('Cannot change file ownership')
        return 3

    # Remove from /ready and move to /user
    try:
        shutil.move(source, dest)
    except:
        LOGGER.error('Cannot move file')
        return 2

    # All done, we can delete the original file as uploaded by the user
    uploaded_file = settings.UPLOADED_FILES_ROOT + filename
    delete_if_exists(uploaded_file)

    # Finally, create any links to email hashes that were requested
    gm_client = gearman.GearmanClient(settings.GEARMAN_SERVERS)
    for hashes in links:
        params = {
            'photo_hash': file_hash,
            'photo_format': file_format,
            'md5_hash': hashes[0],
            'sha256_hash': hashes[1]
        }
        gm_client.submit_job('changephoto',
                             json.dumps(params),
                             background=True,
                             wait_until_complete=False)

    return 0
示例#19
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        logger.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        logger.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        logger.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            logger.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    source = settings.READY_FILES_ROOT + filename
    dest = settings.USER_FILES_ROOT + filename

    # Sanity checks
    if os.path.isfile(dest):
        logger.warning('Destination already exists')
        return 0

    if not os.path.isfile(source):
        logger.error('Source file not found')
        return 1

    # Remove from /ready and move to /user
    try:
        shutil.move(source, dest)
    except:
        logger.error('Cannot move file')
        return 2

    # All done, we can delete the original file as uploaded by the user
    uploaded_file = settings.UPLOADED_FILES_ROOT + filename
    delete_if_exists(uploaded_file)

    # Finally, create any links to email hashes that were requested
    gm_client = libgearman.Client()
    for server in settings.GEARMAN_SERVERS:
        gm_client.add_server(server)

    for hashes in links:
        params = {
            'photo_hash': file_hash,
            'photo_format': file_format,
            'md5_hash': hashes[0],
            'sha256_hash': hashes[1]
        }
        gm_client.do_background('changephoto', json.dumps(params))

    return 0
示例#20
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        logger.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        logger.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        logger.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            logger.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    source = settings.READY_FILES_ROOT + filename
    dest = settings.USER_FILES_ROOT + filename

    # Sanity checks
    if os.path.isfile(dest):
        logger.warning('Destination already exists')
        return 0

    if not os.path.isfile(source):
        logger.error('Source file not found')
        return 1

    # Remove from /ready and move to /user
    try:
        shutil.move(source, dest)
    except:
        logger.error('Cannot move file')
        return 2

    # All done, we can delete the original file as uploaded by the user
    uploaded_file = settings.UPLOADED_FILES_ROOT + filename
    delete_if_exists(uploaded_file)

    # Finally, create any links to email hashes that were requested
    gm_client = libgearman.Client()
    for server in settings.GEARMAN_SERVERS:
        gm_client.add_server(server)

    for hashes in links:
        params = {'photo_hash': file_hash, 'photo_format': file_format,
                  'md5_hash': hashes[0], 'sha256_hash': hashes[1]}
        gm_client.do_background('changephoto', json.dumps(params))

    return 0
示例#21
0
'''
Find the second-smallest triangle number which is also 
pentagonal and hexagonal.
'''

from utils import triangles, is_tri, is_pen, is_hex



for tri in triangles():
    if not is_tri(tri):
        print "wtf?"
        sys.exit()
    if is_pen(tri):
        if is_hex(tri):
            print "found! %s" % tri



示例#22
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    gearman_workload = sys.stdin.read()
    params = json.loads(gearman_workload)

    file_hash = params['file_hash']
    file_format = params['format']
    links = params['links']

    # Validate inputs
    if not is_hex(file_hash):
        LOGGER.error('file_hash is not a hexadecimal value')
        return 1
    if file_format != 'jpg' and file_format != 'png' and file_format != 'gif':
        LOGGER.error('file_format is not recognized')
        return 1
    if not isinstance(links, list):
        LOGGER.error('links is not a list')
        return 1
    for l in links:
        if not is_hash_pair(l):
            LOGGER.error('links is not a list of hash pairs')
            return 1

    filename = "%s.%s" % (file_hash, file_format)
    source = settings.READY_FILES_ROOT + filename
    dest = settings.USER_FILES_ROOT + filename

    # Sanity checks
    if os.path.isfile(dest):
        LOGGER.warning('Destination already exists')
        return 0

    if not os.path.isfile(source):
        LOGGER.error('Source file not found')
        return 1

    # Change file ownership so that it can no longer be modified
    try:
        os.chown(source, 0, 0)  # root:root
    except:
        LOGGER.error('Cannot change file ownership')
        return 3

    # Remove from /ready and move to /user
    try:
        shutil.move(source, dest)
    except:
        LOGGER.error('Cannot move file')
        return 2

    # All done, we can delete the original file as uploaded by the user
    uploaded_file = settings.UPLOADED_FILES_ROOT + filename
    delete_if_exists(uploaded_file)

    # Finally, create any links to email hashes that were requested
    gm_client = gearman.GearmanClient(settings.GEARMAN_SERVERS)
    for hashes in links:
        params = {'photo_hash': file_hash, 'photo_format': file_format,
                  'md5_hash': hashes[0], 'sha256_hash': hashes[1]}
        gm_client.submit_job('changephoto', json.dumps(params),
                             background=True, wait_until_complete=False)

    return 0