コード例 #1
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def _update_metadata_from_fn(fwobj, fn):
    """
    Re-parses the .cab file and updates the database version.
    """

    # load cab file
    arc = cabarchive.CabArchive()
    try:
        if os.path.exists(CABEXTRACT_CMD):
            arc.set_decompressor(CABEXTRACT_CMD)
        arc.parse_file(fn)
    except cabarchive.CorruptionError as e:
        return error_internal('Invalid file type: %s' % str(e))

    # parse the MetaInfo file
    cf = arc.find_file("*.metainfo.xml")
    if not cf:
        return error_internal('The firmware file had no valid metadata')
    component = appstream.Component()
    try:
        component.parse(str(cf.contents))
    except appstream.ParseError as e:
        return error_internal('The metadata could not be parsed: ' + str(e))

    # parse the inf file
    cf = arc.find_file("*.inf")
    if not cf:
        return error_internal('The firmware file had no valid inf file')
    cfg = InfParser()
    cfg.read_data(cf.contents)
    try:
        tmp = cfg.get('Version', 'DriverVer')
        driver_ver = tmp.split(',')
        if len(driver_ver) != 2:
            return error_internal('The inf file Version:DriverVer was invalid')
    except ConfigParser.NoOptionError as e:
        driver_ver = None

    # get the contents
    fw_data = arc.find_file('*.bin')
    if not fw_data:
        fw_data = arc.find_file('*.rom')
    if not fw_data:
        fw_data = arc.find_file('*.cap')
    if not fw_data:
        return error_internal('No firmware found in the archive')

    # update sizes
    fwobj.mds[0].release_installed_size = len(fw_data.contents)
    fwobj.mds[0].release_download_size = os.path.getsize(fn)

    # update the descriptions
    fwobj.mds[0].release_description = component.releases[0].description
    fwobj.mds[0].description = component.description
    if driver_ver:
        fwobj.version_display = driver_ver[1]
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    db_firmware.update(fwobj)
    return None
コード例 #2
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def device():
    """
    Show all devices -- probably only useful for the admin user.
    """

    # security check
    if session['username'] != 'admin':
        return error_permission_denied('Unable to view devices')

    # get all firmware
    try:
        db = LvfsDatabase(os.environ)
        db_firmware = LvfsDatabaseFirmware(db)
        items = db_firmware.get_items()
    except CursorError as e:
        return error_internal(str(e))

    # get all the guids we can target
    devices = []
    seen_guid = {}
    for item in items:
        for md in item.mds:
            if md.guid in seen_guid:
                continue
            seen_guid[md.guid] = 1
            devices.append(md.guid)

    return render_template('devices.html', devices=devices)
コード例 #3
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def firmware_delete_force(fwid):
    """ Delete a firmware entry and also delete the file from disk """

    # check firmware exists in database
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    try:
        item = db_firmware.get_item(fwid)
    except CursorError as e:
        return error_internal(str(e))
    if not item:
        return error_internal("No firmware file with hash %s exists" % fwid)
    if session['username'] != 'admin' and item.qa_group != session['qa_group']:
        return error_permission_denied("No QA access to %s" % fwid)

    # only QA users can delete once the firmware has gone stable
    if not session['qa_capability'] and item.target == 'stable':
        return error_permission_denied('Unable to delete stable firmware as not QA')

    # delete id from database
    try:
        db_firmware.remove(fwid)
    except CursorError as e:
        return error_internal(str(e))

    # delete file(s)
    for loc in [DOWNLOAD_DIR]:
        path = os.path.join(loc, item.filename)
        if os.path.exists(path):
            os.remove(path)

    # update everything
    try:
        metadata_update_qa_group(item.qa_group)
        if item.target == 'stable':
            metadata_update_targets(targets=['stable', 'testing'])
        elif item.target == 'testing':
            metadata_update_targets(targets=['testing'])
    except NoKeyError as e:
        return error_internal('Failed to sign metadata: ' + str(e))
    except CursorError as e:
        return error_internal('Failed to generate metadata: ' + str(e))

    _event_log("Deleted firmware %s" % fwid)
    return redirect(url_for('.firmware'))
コード例 #4
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def device_list():
    # add devices in stable or testing
    try:
        db = LvfsDatabase(os.environ)
        db_firmware = LvfsDatabaseFirmware(db)
        items = db_firmware.get_items()
    except CursorError as e:
        return error_internal(str(e))

    # get a sorted list of vendors
    vendors = []
    for item in items:
        if item.target != 'stable':
            continue
        vendor = item.mds[0].developer_name
        if vendor in vendors:
            continue
        vendors.append(vendor)

    seen_guid = {}
    mds_by_vendor = {}
    for vendor in sorted(vendors):
        for item in items:
            if item.target != 'stable':
                continue
            for md in item.mds:

                # only show correct vendor
                if vendor != md.developer_name:
                    continue

                # only show the newest version
                if md.guid in seen_guid:
                    continue
                seen_guid[md.guid] = 1

                # add
                if not vendor in mds_by_vendor:
                    mds_by_vendor[vendor] = []
                mds_by_vendor[vendor].append(md)

    return render_template('devicelist.html',
                           vendors=sorted(vendors),
                           mds_by_vendor=mds_by_vendor)
コード例 #5
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def firmware_promote(fwid, target):
    """
    Promote or demote a firmware file from one target to another,
    for example from testing to stable, or stable to testing.
     """

    # check is QA
    if not session['qa_capability']:
        return error_permission_denied('Unable to promote as not QA')

    # check valid
    if target not in ['stable', 'testing', 'private', 'embargo']:
        return error_internal("Target %s invalid" % target)

    # check firmware exists in database
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    try:
        item = db_firmware.get_item(fwid)
    except CursorError as e:
        return error_internal(str(e))
    if session['username'] != 'admin' and item.qa_group != session['qa_group']:
        return error_permission_denied("No QA access to %s" % fwid)
    try:
        db_firmware.set_target(fwid, target)
    except CursorError as e:
        return error_internal(str(e))
    # set correct response code
    _event_log("Moved firmware %s to %s" % (fwid, target))

    # update everything
    try:
        metadata_update_qa_group(item.qa_group)
        if target == 'stable':
            metadata_update_targets(['stable', 'testing'])
        elif target == 'testing':
            metadata_update_targets(['testing'])
    except NoKeyError as e:
        return error_internal('Failed to sign metadata: ' + str(e))
    except CursorError as e:
        return error_internal('Failed to generate metadata: ' + str(e))
    return redirect(url_for('.firmware_id', fwid=fwid))
コード例 #6
0
ファイル: metadata.py プロジェクト: hughsie/lvfs-website
def metadata_update_qa_group(qa_group):
    """ updates metadata for a specific qa_group """

    # explicit
    affidavit = create_affidavit()
    if qa_group:
        filename = 'firmware-%s.xml.gz' % _qa_hash(qa_group)
        _generate_metadata_kind(filename,
                                qa_group=qa_group,
                                affidavit=affidavit)
        return

    # do for all
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    qa_groups = db_firmware.get_qa_groups()
    for qa_group in qa_groups:
        filename_qa = 'firmware-%s.xml.gz' % _qa_hash(qa_group)
        _generate_metadata_kind(filename_qa,
                                qa_group=qa_group,
                                affidavit=affidavit)
コード例 #7
0
ファイル: metadata.py プロジェクト: superm1/lvfs-website
def metadata_update_qa_group(qa_group):
    """ updates metadata for a specific qa_group """

    # explicit
    if qa_group:
        filename = 'firmware-%s.xml.gz' % _qa_hash(qa_group)
        _generate_metadata_kind(filename, qa_group=qa_group)
        return [os.path.join(DOWNLOAD_DIR, filename)]

    # do for all
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    qa_groups = db_firmware.get_qa_groups()
    filenames = []
    for qa_group in qa_groups:
        filename_qa = 'firmware-%s.xml.gz' % _qa_hash(qa_group)
        filename = _generate_metadata_kind(filename_qa, qa_group=qa_group)
        filenames.append(filename)

    # return all the files we have to sign
    return filenames
コード例 #8
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def firmware_modify(fwid):
    """ Modifies the update urgency and release notes for the update """

    if request.method != 'POST':
        return redirect(url_for('.firmware'))

    # find firmware
    try:
        db = LvfsDatabase(os.environ)
        db_firmware = LvfsDatabaseFirmware(db)
        fwobj = db_firmware.get_item(fwid)
    except CursorError as e:
        return error_internal(str(e))
    if not fwobj:
        return error_internal("No firmware %s" % fwid)

    # set new metadata values
    for md in fwobj.mds:
        if 'urgency' in request.form:
            md.release_urgency = request.form['urgency']
        if 'description' in request.form:
            txt = request.form['description']
            if txt.find('<p>') == -1:
                txt = appstream.utils.import_description(txt)
            try:
                appstream.utils.validate_description(txt)
            except appstream.ParseError as e:
                return error_internal("Failed to parse %s: %s" % (txt, str(e)))
            md.release_description = txt

    # modify
    try:
        db_firmware.update(fwobj)
    except CursorError as e:
        return error_internal(str(e))

    # log
    _event_log('Changed update description on %s' % fwid)

    return redirect(url_for('.firmware_id', fwid=fwid))
コード例 #9
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def firmware(show_all=False):
    """
    Show all previsouly uploaded firmware for this user.
    """

    # get all firmware
    try:
        db = LvfsDatabase(os.environ)
        db_firmware = LvfsDatabaseFirmware(db)
        items = db_firmware.get_items()
    except CursorError as e:
        return error_internal(str(e))

    # group by the firmware name
    names = {}
    for item in items:
        # admin can see everything
        if session['username'] != 'admin':
            if item.qa_group != session['qa_group']:
                continue
        name = item.mds[0].name
        if not name in names:
            names[name] = []
        names[name].append(item)

    # only show one version in each state
    for name in sorted(names):
        targets_seen = {}
        for item in names[name]:
            if item.target in targets_seen:
                item.is_newest_in_state = False
            else:
                item.is_newest_in_state = True
                targets_seen[item.target] = item

    return render_template('firmware.html',
                           fw_by_name=names,
                           names_sorted=sorted(names),
                           qa_group=session['qa_group'],
                           show_all=show_all)
コード例 #10
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def device_guid(guid):
    """
    Show information for one device, which can be seen without a valid login
    """

    # get all firmware
    try:
        db = LvfsDatabase(os.environ)
        db_firmware = LvfsDatabaseFirmware(db)
        items = db_firmware.get_items()
    except CursorError as e:
        return error_internal(str(e))

    # get all the guids we can target
    firmware_items = []
    for item in items:
        for md in item.mds:
            if md.guid != guid:
                continue
            firmware_items.append(item)
            break

    return render_template('device.html', items=firmware_items)
コード例 #11
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def firmware_id(fwid):
    """ Show firmware information """

    # get details about the firmware
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    try:
        item = db_firmware.get_item(fwid)
    except CursorError as e:
        return error_internal(str(e))
    if not item:
        return error_internal('No firmware matched!')

    # we can only view our own firmware, unless admin
    qa_group = item.qa_group
    if qa_group != session['qa_group'] and session['username'] != 'admin':
        return error_permission_denied('Unable to view other vendor firmware')
    if not qa_group:
        embargo_url = '/downloads/firmware.xml.gz'
        qa_group = 'None'
    else:
        embargo_url = '/downloads/firmware-%s.xml.gz' % _qa_hash(qa_group)

    db = LvfsDatabase(os.environ)
    db_clients = LvfsDatabaseClients(db)
    cnt_fn = db_clients.get_firmware_count_filename(item.filename)
    data_fw = db_clients.get_stats_for_fn(12, 30, item.filename)
    return render_template('firmware-details.html',
                           fw=item,
                           qa_capability=session['qa_capability'],
                           orig_filename='-'.join(item.filename.split('-')[1:]),
                           embargo_url=embargo_url,
                           qa_group=qa_group,
                           cnt_fn=cnt_fn,
                           fwid=fwid,
                           graph_labels=_get_chart_labels_months()[::-1],
                           graph_data=data_fw[::-1])
コード例 #12
0
ファイル: metadata.py プロジェクト: hughsie/lvfs-website
def _generate_metadata_kind(filename, targets=None, qa_group=None, affidavit=None):
    """ Generates AppStream metadata of a specific kind """
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    items = db_firmware.get_items()
    store = appstream.Store('lvfs')
    for item in items:

        # filter
        if item.target == 'private':
            continue
        if targets and item.target not in targets:
            continue
        if qa_group and qa_group != item.qa_group:
            continue

        # add each component
        for md in item.mds:
            component = appstream.Component()
            component.id = md.cid
            component.kind = 'firmware'
            component.name = md.name
            component.summary = md.summary
            component.description = md.description
            if md.url_homepage:
                component.urls['homepage'] = md.url_homepage
            component.metadata_license = md.metadata_license
            component.project_license = md.project_license
            component.developer_name = md.developer_name

            # add provide
            if md.guid:
                prov = appstream.Provide()
                prov.kind = 'firmware-flashed'
                prov.value = md.guid
                component.add_provide(prov)

            # add release
            if md.version:
                rel = appstream.Release()
                rel.version = md.version
                rel.description = md.release_description
                if md.release_timestamp:
                    rel.timestamp = md.release_timestamp
                rel.checksums = []
                rel.location = 'https://secure-lvfs.rhcloud.com/downloads/' + item.filename
                rel.size_installed = md.release_installed_size
                rel.size_download = md.release_download_size
                rel.urgency = md.release_urgency
                component.add_release(rel)

                # add container checksum
                if md.checksum_container:
                    csum = appstream.Checksum()
                    csum.target = 'container'
                    csum.value = md.checksum_container
                    csum.filename = item.filename
                    rel.add_checksum(csum)

                # add content checksum
                if md.checksum_contents:
                    csum = appstream.Checksum()
                    csum.target = 'content'
                    csum.value = md.checksum_contents
                    csum.filename = md.filename_contents
                    rel.add_checksum(csum)

            # add screenshot
            if md.screenshot_caption:
                ss = appstream.Screenshot()
                ss.caption = md.screenshot_caption
                if md.screenshot_url:
                    im = appstream.Image()
                    im.url = md.screenshot_url
                    ss.add_image(im)
                component.add_screenshot(ss)

            # add component
            store.add(component)

    # dump to file
    if not os.path.exists(DOWNLOAD_DIR):
        os.mkdir(DOWNLOAD_DIR)
    filename = os.path.join(DOWNLOAD_DIR, filename)
    store.to_file(filename)

    # upload to the CDN
    blob = open(filename, 'rb').read()
    _upload_to_cdn(filename, blob)

    # generate and upload the detached signature
    if affidavit:
        blob_asc = affidavit.create(blob)
        _upload_to_cdn(filename + '.asc', blob_asc)
コード例 #13
0
ファイル: lvfs.py プロジェクト: hughsie/lvfs-website
def upload():
    """ Upload a .cab file to the LVFS service """

    # only accept form data
    if request.method != 'POST':
        return redirect(url_for('.index'))

    # not correct parameters
    if not 'target' in request.form:
        return error_internal('No target')
    if not 'file' in request.files:
        return error_internal('No file')

    # can the user upload directly to stable
    if request.form['target'] in ['stable', 'testing']:
        if not session['qa_capability']:
            return error_permission_denied('Unable to upload to this target as not QA user')

    # check size < 50Mb
    fileitem = request.files['file']
    if not fileitem:
        return error_internal('No file object')
    data = fileitem.read()
    if len(data) > 50000000:
        return error_internal('File too large, limit is 50Mb', 413)
    if len(data) == 0:
        return error_internal('File has no content')
    if len(data) < 1024:
        return error_internal('File too small, mimimum is 1k')

    # check the file does not already exist
    db = LvfsDatabase(os.environ)
    db_firmware = LvfsDatabaseFirmware(db)
    fwid = hashlib.sha1(data).hexdigest()
    try:
        item = db_firmware.get_item(fwid)
    except CursorError as e:
        return error_internal(str(e))
    if item:
        return error_internal("A firmware file with hash %s already exists" % fwid, 422)

    # parse the file
    arc = cabarchive.CabArchive()
    try:
        if os.path.exists(CABEXTRACT_CMD):
            arc.set_decompressor(CABEXTRACT_CMD)
        arc.parse(data)
    except cabarchive.CorruptionError as e:
        return error_internal('Invalid file type: %s' % str(e), 415)
    except cabarchive.NotSupportedError as e:
        return error_internal('The file is unsupported: %s' % str(e), 415)

    # check .inf exists
    fw_version_inf = None
    fw_version_display_inf = None
    cf = arc.find_file("*.inf")
    if cf:
        if cf.contents.find('FIXME') != -1:
            return error_internal("The inf file was not complete; "
                                  "Any FIXME text must be replaced with the correct values.")

        # check .inf file is valid
        cfg = InfParser()
        cfg.read_data(cf.contents)
        try:
            tmp = cfg.get('Version', 'Class')
        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError) as e:
            return error_internal('The inf file Version:Class was missing')
        if tmp != 'Firmware':
            return error_internal('The inf file Version:Class was invalid')
        try:
            tmp = cfg.get('Version', 'ClassGuid')
        except ConfigParser.NoOptionError as e:
            return error_internal('The inf file Version:ClassGuid was missing')
        if tmp != '{f2e7dd72-6468-4e36-b6f1-6488f42c1b52}':
            return error_internal('The inf file Version:ClassGuid was invalid')
        try:
            tmp = cfg.get('Version', 'DriverVer')
            fw_version_display_inf = tmp.split(',')
            if len(fw_version_display_inf) != 2:
                return error_internal('The inf file Version:DriverVer was invalid')
        except ConfigParser.NoOptionError as e:
            pass

        # this is optional, but if supplied must match the version in the XML
        # -- also note this will not work with multi-firmware .cab files
        try:
            fw_version_inf = cfg.get('Firmware_AddReg', 'HKR->FirmwareVersion')
            if fw_version_inf.startswith('0x'):
                fw_version_inf = str(int(fw_version_inf[2:], 16))
            if fw_version_inf == '0':
                fw_version_inf = None
        except (ConfigParser.NoOptionError, ConfigParser.NoSectionError) as e:
            pass

    # check metainfo exists
    cfs = arc.find_files("*.metainfo.xml")
    if len(cfs) == 0:
        return error_internal('The firmware file had no .metadata.xml files')

    # parse each MetaInfo file
    apps = []
    for cf in cfs:
        component = appstream.Component()
        try:
            component.parse(str(cf.contents))
            component.validate()
        except appstream.ParseError as e:
            return error_internal('The metadata %s could not be parsed: %s' % (cf, str(e)))
        except appstream.ValidationError as e:
            return error_internal('The metadata %s file did not validate: %s' % (cf, str(e)))

        # check the file does not have any missing request.form
        if cf.contents.find('FIXME') != -1:
            return error_internal("The metadata file was not complete; "
                                  "Any FIXME text must be replaced with the correct values.")

        # check the firmware provides something
        if len(component.provides) == 0:
            return error_internal("The metadata file did not provide any GUID.")
        if len(component.releases) == 0:
            return error_internal("The metadata file did not provide any releases.")

        # check the inf file matches up with the .xml file
        if fw_version_inf and fw_version_inf != component.releases[0].version:
            return error_internal("The inf Firmware_AddReg[HKR->FirmwareVersion] "
                                  "'%s' did not match the metainfo.xml value '%s'."
                                  % (fw_version_inf, component.releases[0].version))

        # check the guid and version does not already exist
        try:
            items = db_firmware.get_items()
        except CursorError as e:
            return error_internal(str(e))
        for item in items:
            for md in item.mds:
                if md.guid == component.provides[0].value and md.version == component.releases[0].version:
                    return error_internal("A firmware file for this version already exists", 422)

        # check the ID hasn't been reused by a different GUID
        for item in items:
            for md in item.mds:
                if md.cid == component.id and not md.guid == component.provides[0].value:
                    return error_internal("The %s ID has already been used by GUID %s" % (md.cid, md.guid), 422)

        # add to array
        apps.append(component)

    # only save if we passed all tests
    basename = os.path.basename(fileitem.filename)
    new_filename = fwid + '-' + basename

    # add these after parsing in case multiple components use the same file
    asc_files = {}

    # fix up the checksums and add the detached signature
    for component in apps:

        # ensure there's always a container checksum
        release = component.releases[0]
        csum = release.get_checksum_by_target('content')
        if not csum:
            csum = appstream.Checksum()
            csum.target = 'content'
            csum.filename = 'firmware.bin'
            component.releases[0].add_checksum(csum)

        # get the contents checksum
        fw_data = arc.find_file(csum.filename)
        if not fw_data:
            return error_internal('No %s found in the archive' % csum.filename)
        csum.kind = 'sha1'
        csum.value = hashlib.sha1(fw_data.contents).hexdigest()

        # set the sizes
        release.size_installed = len(fw_data.contents)
        release.size_download = len(data)

        # add the detached signature if not already signed
        sig_data = arc.find_file(csum.filename + ".asc")
        if not sig_data:
            if not csum.filename in asc_files:
                try:
                    affidavit = create_affidavit()
                except NoKeyError as e:
                    return error_internal('Failed to sign archive: ' + str(e))
                cff = cabarchive.CabFile(fw_data.filename + '.asc',
                                         affidavit.create(fw_data.contents))
                asc_files[csum.filename] = cff
        else:
            # check this file is signed by something we trust
            try:
                affidavit = create_affidavit()
                affidavit.verify(fw_data.contents)
            except NoKeyError as e:
                return error_internal('Failed to verify archive: ' + str(e))

    # add all the .asc files to the archive
    for key in asc_files:
        arc.add_file(asc_files[key])

    # export the new archive and get the checksum
    cab_data = arc.save(compressed=True)
    checksum_container = hashlib.sha1(cab_data).hexdigest()

    # dump to a file
    if not os.path.exists(DOWNLOAD_DIR):
        os.mkdir(DOWNLOAD_DIR)
    fn = os.path.join(DOWNLOAD_DIR, new_filename)
    open(fn, 'wb').write(cab_data)

    # dump to the CDN
    _upload_to_cdn(new_filename, StringIO(cab_data))

    # create parent firmware object
    target = request.form['target']
    fwobj = LvfsFirmware()
    fwobj.qa_group = session['qa_group']
    fwobj.addr = _get_client_address()
    fwobj.filename = new_filename
    fwobj.fwid = fwid
    fwobj.target = target
    if fw_version_display_inf:
        fwobj.version_display = fw_version_display_inf[1]

    # create child metadata object for the component
    for component in apps:
        md = LvfsFirmwareMd()
        md.fwid = fwid
        md.cid = component.id
        md.name = component.name
        md.summary = component.summary
        md.developer_name = component.developer_name
        md.metadata_license = component.metadata_license
        md.project_license = component.project_license
        md.url_homepage = component.urls['homepage']
        md.description = component.description
        md.checksum_container = checksum_container

        # from the provide
        prov = component.provides[0]
        md.guid = prov.value

        # from the release
        rel = component.releases[0]
        md.version = rel.version
        md.release_description = rel.description
        md.release_timestamp = rel.timestamp
        md.release_installed_size = rel.size_installed
        md.release_download_size = rel.size_download
        md.release_urgency = rel.urgency

        # from the first screenshot
        if len(component.screenshots) > 0:
            ss = component.screenshots[0]
            if ss.caption:
                md.screenshot_caption = ss.caption
            if len(ss.images) > 0:
                im = ss.images[0]
                if im.url:
                    md.screenshot_url = im.url

        # from the content checksum
        csum = component.releases[0].get_checksum_by_target('content')
        md.checksum_contents = csum.value
        md.filename_contents = csum.filename

        fwobj.mds.append(md)

    # add to database
    try:
        db_firmware.add(fwobj)
    except CursorError as e:
        return error_internal(str(e))
    # set correct response code
    _event_log("Uploaded file %s to %s" % (new_filename, target))

    # ensure up to date
    try:
        if target != 'private':
            metadata_update_qa_group(fwobj.qa_group)
        if target == 'stable':
            metadata_update_targets(['stable', 'testing'])
        elif target == 'testing':
            metadata_update_targets(['testing'])

    except NoKeyError as e:
        return error_internal('Failed to sign metadata: ' + str(e))
    except CursorError as e:
        return error_internal('Failed to generate metadata: ' + str(e))

    return redirect(url_for('.firmware_id', fwid=fwid))