def route_search_stats(limit=20):
    search_events = db.session.query(SearchEvent).\
                        order_by(SearchEvent.timestamp.desc()).\
                        limit(99999).all()

    keywords = {}
    for ev in search_events:
        for tok in _split_search_string(ev.value):
            if tok in keywords:
                keywords[tok] += 1
                continue
            keywords[tok] = 1
    results = []
    for keyword in keywords:
        results.append((keyword, keywords[keyword]))
    results.sort(key=lambda k: k[1], reverse=True)

    # generate the graph data
    labels = []
    data = []
    for res in results[0:limit]:
        labels.append(str(res[0]))
        data.append(res[1])
    return render_template('analytics-search-stats.html',
                           category='analytics',
                           labels=labels,
                           data=data)
Example #2
0
def route_fw(max_results=100):

    if 'value' not in request.args:
        flash('No search value!', 'danger')
        return redirect(url_for('search.route_search'))
    keywords_unsafe = _split_search_string(request.args['value'])
    if not keywords_unsafe:
        keywords_unsafe = request.args['value'].split(' ')

    # never allow empty keywords
    keywords = []
    for keyword in keywords_unsafe:
        if keyword:
            keywords.append(keyword)
    if not keywords:
        flash('No valid search value!', 'danger')
        return redirect(url_for('search.route_search'))

    # use keywords first
    fws = db.session.query(Firmware).join(Component).\
                           join(Keyword).\
                           filter(Keyword.value.in_(keywords)).\
                           distinct(Keyword.component_id).\
                           order_by(Keyword.component_id.desc(), Firmware.timestamp.desc()).\
                           limit(max_results).all()

    # try GUIDs
    if not fws:
        fws = db.session.query(Firmware).join(Component).\
                               join(Guid).\
                               filter(Guid.value.in_(keywords)).\
                               distinct(Keyword.component_id).\
                               order_by(Keyword.component_id.desc(), Firmware.timestamp.desc()).\
                               limit(max_results).all()

    # try version numbers
    if not fws:
        fws = db.session.query(Firmware).join(Component).\
                               filter(Component.version.in_(keywords)).\
                               distinct(Keyword.component_id).\
                               order_by(Keyword.component_id.desc(), Firmware.timestamp.desc()).\
                               limit(max_results).all()

    # try appstream ID
    if not fws:
        fws = db.session.query(Firmware).join(Component).\
                               filter(Component.appstream_id.startswith(keywords[0])).\
                               distinct(Keyword.component_id).\
                               order_by(Keyword.component_id.desc(), Firmware.timestamp.desc()).\
                               limit(max_results).all()

    # try CVE, e.g. CVE-2018-3646
    if not fws:
        fws = db.session.query(Firmware).join(Component).join(ComponentIssue).\
                               filter(ComponentIssue.value.in_(keywords)).\
                               distinct(Keyword.component_id).\
                               order_by(Keyword.component_id.desc(), Firmware.timestamp.desc()).\
                               limit(max_results).all()

    # filter by ACL
    fws_safe = []
    for fw in fws:
        if fw.check_acl('@view'):
            fws_safe.append(fw)

    return render_template('firmware-search.html',
                           category='firmware',
                           state='search',
                           remote=None,
                           fws=fws_safe)
Example #3
0
def route_search(max_results=150):

    # no search results
    if 'value' not in request.args:
        return render_template('search.html',
                               mds=None,
                               search_size=-1,
                               keywords_good=[],
                               keywords_bad=[])

    # components that match
    keywords = _split_search_string(request.args['value'])
    ids = db.session.query(Keyword.component_id).\
                           filter(Keyword.value.in_(keywords)).\
                           group_by(Keyword.component_id).\
                           having(func.count() == len(keywords)).\
                           subquery()
    mds = []
    appstream_ids = []
    vendors = []
    for md in db.session.query(Component).join(ids).\
                    join(Firmware).join(Remote).filter(Remote.is_public).\
                    order_by(Component.version.desc()).\
                    limit(max_results*4):
        if md.appstream_id in appstream_ids:
            continue
        mds.append(md)
        appstream_ids.append(md.appstream_id)
        if md.fw.vendor not in vendors:
            vendors.append(md.fw.vendor)

    # get any vendor information as a fallback
    keywords_good = []
    keywords_bad = []
    if mds:
        keywords_good.extend(keywords)
        search_method = 'FW'
    else:
        search_method = 'AND'

    # always add vendor results
    for vendor in db.session.query(Vendor).\
                        filter(Vendor.visible_for_search):
        for kw in keywords:
            if vendor.keywords:
                if kw in vendor.keywords:
                    if vendor not in vendors:
                        vendors.append(vendor)
                    if kw not in keywords_good:
                        keywords_good.append(kw)
                    break
            if vendor.display_name:
                if kw in _split_search_string(vendor.display_name):
                    if vendor not in vendors:
                        vendors.append(vendor)
                    if kw not in keywords_good:
                        keywords_good.append(kw)
                    break
    for kw in keywords:
        if not kw in keywords_good:
            keywords_bad.append(kw)

    # this seems like we're over-logging but I'd like to see how people are
    # searching so we can tweak the algorithm used
    _add_search_event(
        SearchEvent(value=request.args['value'],
                    addr=_addr_hash(_get_client_address()),
                    count=len(mds) + len(vendors),
                    method=search_method))

    return render_template('search.html',
                           mds=mds[:max_results],
                           search_size=len(mds),
                           vendors=vendors,
                           keywords_good=keywords_good,
                           keywords_bad=keywords_bad)