view farol/document.py @ 127:d49c1ee6bc07

Harden server-side version parsing
author Benoît Allard <benoit.allard@greenbone.net>
date Thu, 23 Oct 2014 16:50:02 +0200
parents 5535ac5fef37
children d2588d88d47a
line wrap: on
line source
# -*- encoding: utf-8 -*-
# Description:
# The Document Blueprint
#
# Authors:
# BenoƮt Allard <benoit.allard@greenbone.net>
#
# Copyright:
# Copyright (C) 2014 Greenbone Networks GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.

from flask import (Blueprint, render_template, abort, redirect, request,
    url_for, flash)

from farolluz.cvrf import (CVRFNote, CVRFReference, CVRFPublisher,
    CVRFTracking, CVRFTrackingID, CVRFGenerator, CVRFRevision,
    CVRFAggregateSeverity)
from farolluz.renderer import utcnow

from .controller import (update_note_from_request, create_note_from_request,
    update_reference_from_request, create_reference_from_request,
    update_acknowledgment_from_request, create_acknowledgment_from_request,
    split_fields, parseDate, parseVersion)
from .session import document_required, get_current


document = Blueprint('document', __name__)

@document.route('/')
@document_required
def view():
    cvrf = get_current()
    return render_template('document/view.j2', cvrf=cvrf)

@document.route('/title/edit', methods=['GET', 'POST'])
@document_required
def edit_title():
    if request.method != 'POST':
        return render_template('document/edit_title.j2', title = get_current()._title, _type = get_current()._type)


    get_current()._title = request.form['title']
    get_current()._type = request.form['type']
    return redirect(url_for('.view'))

@document.route('/publisher/edit', methods=['GET', 'POST'])
@document_required
def edit_publisher():
    if request.method != 'POST':
        return render_template('document/edit_publisher.j2', publisher = get_current()._publisher or CVRFPublisher(''), types=CVRFPublisher.TYPES)

    publisher = CVRFPublisher(request.form['type'], request.form['vendorid'] or None)
    publisher.setContact(request.form['contact'] or None)
    publisher.setAuthority(request.form['authority'] or None)
    get_current().setPublisher(publisher)
    return redirect(url_for('.view'))

@document.route('/tracking/edit', methods=['GET', 'POST'])
@document_required
def edit_tracking():
    wasNone = False
    tracking = get_current()._tracking
    if tracking is None:
        wasNone = True
        tracking = CVRFTracking(CVRFTrackingID(''), 'Draft', (0,0), utcnow(), utcnow())
    generator = tracking._generator
    if not tracking._generator:
        generator = CVRFGenerator()
    if request.method != 'POST':
        return render_template('document/edit_tracking.j2', tracking=tracking, version='.'.join('%s'%v for v in tracking._version), generator=generator, now=utcnow(), statuses=tracking.STATUSES)

    tracking._identification._id = request.form['id']
    aliases = split_fields(request.form['id_aliases'])
    tracking._identification._aliases = aliases
    tracking._status = request.form['status']
    version = parseVersion(request.form['version'])
    if version is None:
        flash('Cannot parse Version field: "%s"' % request.form['version'], 'warning')
    else:
        tracking._version = version
    tracking._initialDate = parseDate(request.form['initial'])
    tracking._currentDate = parseDate(request.form['current'])
    if wasNone:
        get_current().setTracking(tracking)
    if (not request.form['gen_engine']) and (not request.form['gen_date']):
        generator = None
    else:
        generator._engine = request.form['gen_engine'] or None
        if request.form['gen_date']:
            generator._date = parseDate(request.form['gen_date'])
        else:
            generator._date = None
    tracking.setGenerator(generator)
    return redirect(url_for('.view'))

@document.route('/revision/<int:index>/edit', methods=['GET', 'POST'])
@document_required
def edit_revision(index):
    cvrf = get_current()
    if cvrf._tracking is None:
        abort(404)
    try:
        revision = cvrf._tracking._history[index]
    except IndexError:
        abort(404)
    if request.method != 'POST':
        return render_template('document/edit_revision.j2', number='.'.join('%s'%v for v in revision._number), date=revision._date, description=revision._description, action='Update')

    version = parseVersion(request.form['number'])
    if version is None:
        flash('Cannot parse Revision Number: %s' % request.form['number'])
    else:
        revision._number = version
    revision._date = parseDate(request.form['date'])
    revision._description = request.form['description']
    return redirect(url_for('.view'))

@document.route('/revision/add', methods=['GET', 'POST'])
@document_required
def add_revision():
    tracking = get_current()._tracking
    if request.method != 'POST':
        if tracking is None:
            flash('The tracking information should be set first to be able to add a revision.', 'danger')
            return redirect(url_for('.edit_tracking'))
        version = tracking._version
        version = version[:-1] + (version[-1] + 1,)
        return render_template('document/edit_revision.j2', number='.'.join("%d"%v for v in version), date=utcnow(), action='Add')

    version = parseVersion(request.form['number'])
    if version is None:
        flash('Cannot parse Revision Number: "%s", assuming "0.0"' % request.form['number'])
        version = (0,0)
    date = parseDate(request.form['date'])
    revision = CVRFRevision(version, date, request.form['description'])
    tracking.addRevision(revision)
    if 'update_tracking' in request.form:
        tracking._version = version
        tracking._currentDate = date
    return redirect(url_for('.view'))

@document.route('/revision/<int:index>/del', methods=['POST'])
@document_required
def del_revision(index):
    history = get_current()._tracking._history
    if not (0 <= index < len(history)):
        flash('Revision not found', 'danger')
        abort(404)
    del history[index]
    return redirect(url_for('.view'))

@document.route('/distribution/edit', methods=['GET', 'POST'])
@document_required
def edit_distribution():
    if request.method != 'POST':
        return render_template('document/edit_distribution.j2', distribution=get_current()._distribution)

    get_current().setDistribution(request.form['distribution'])
    return redirect(url_for('.view'))

@document.route('/severity/edit', methods=['GET', 'POST'])
@document_required
def edit_severity():
    severity = get_current()._aggregateseverity
    if severity is None:
        severity = CVRFAggregateSeverity('')
    if request.method != 'POST':
        return render_template('document/edit_severity.j2', severity=severity)
    if not request.form['severity']:
        severity = None
    else:
        severity._severity = request.form['severity']
        severity.setNamespace(request.form['namespace'] or None)
    get_current().setAggregateSeverity(severity)
    return redirect(url_for('.view'))

@document.route('/note/<int:ordinal>')
@document_required
def view_note(ordinal):
    note = get_current().getNote(ordinal)
    if note is None:
        abort(404)
    return render_template('document/view_note.j2', note=note)

@document.route('/note/<int:ordinal>/edit', methods=['GET', 'POST'])
@document_required
def edit_note(ordinal):
    note = get_current().getNote(ordinal)
    if note is None:
        abort(404)
    if request.method != 'POST':
        return render_template('document/edit_note.j2', note=note, types = note.TYPES)

    update_note_from_request(note)
    return redirect(url_for('.view_note', ordinal=note._ordinal ))


@document.route('/note/add', methods=['GET', 'POST'])
@document_required
def add_note():
    if request.method != 'POST':
        next_ordinal = 1
        notes = get_current()._notes
        if notes:
            next_ordinal = notes[-1]._ordinal + 1
        return render_template('document/edit_note.j2', ordinal=next_ordinal, types=CVRFNote.TYPES, action='Add')

    note = create_note_from_request()
    get_current().addNote(note)
    return redirect(url_for('.view'))

@document.route('/note/<int:ordinal>/del', methods=['POST'])
@document_required
def del_note(ordinal):
    cvrf = get_current()
    note = cvrf.getNote(ordinal)
    if note is None:
        flash('Note not found', 'danger')
        abort(404)
    cvrf._notes.remove(note)
    return redirect(url_for('.view'))

@document.route('/reference/<int:index>/edit', methods=['GET', 'POST'])
@document_required
def edit_reference(index):
    try:
        ref = get_current()._references[index]
    except IndexError:
        abort(404)
    if request.method != 'POST':
        return render_template('document/edit_reference.j2', _type=ref._type, url=ref._url, description=ref._description, types=('',) + ref.TYPES)

    update_reference_from_request(ref)
    return redirect(url_for('.view'))


@document.route('/reference/add', methods=['GET', 'POST'])
@document_required
def add_reference():
    if request.method != 'POST':
        return render_template('document/edit_reference.j2', action='Add', types=('',) + CVRFReference.TYPES)

    ref = create_reference_from_request()
    get_current().addReference(ref)
    return redirect(url_for('.view'))

@document.route('/reference/<int:index>/del', methods=['POST'])
@document_required
def del_reference(index):
    refs = get_current()._references
    if not (0 <= index < len(refs)):
        flash('Reference not found', 'danger')
        abort(404)
    del refs[index]
    return redirect(url_for('.view'))

@document.route('/acknowledgment/<int:index>')
@document_required
def view_acknowledgment(index):
    try:
        ack = get_current()._acknowledgments[index]
    except IndexError:
        abort(404)
    return render_template('document/view_acknowledgment.j2', acknowledgment=ack, index=index, action='Update')

@document.route('/acknowledgment/<int:index>/edit', methods=['GET', 'POST'])
@document_required
def edit_acknowledgment(index):
    try:
        ack = get_current()._acknowledgments[index]
    except IndexError:
        abort(404)
    if request.method != 'POST':
        return render_template('document/edit_acknowledgment.j2',
            names=ack._names, organizations=ack._organizations,
            description=ack._description, url=ack._url,
            action='Update')

    update_acknowledgment_from_request(ack)
    return redirect(url_for('.view'))

@document.route('/acknowledgment/add', methods=['GET', 'POST'])
@document_required
def add_acknowledgment():
    if request.method != 'POST':
        return render_template('document/edit_acknowledgment.j2',
            action='Add')

    ack = create_acknowledgment_from_request()
    get_current().addAcknowledgment(ack)
    return redirect(url_for('.view'))

@document.route('/acknowledgment/<int:index>/del', methods=['POST'])
@document_required
def del_acknowledgment(index):
    acks = get_current()._acknowledgments
    if not( 0 <= index < len(acks)):
        flash('Acknowledgment not found', 'danger')
        abort(404)
    del acks[index]
    return redirect(url_for('.view'))

http://farol.wald.intevation.org