all files / src/ inputVector.js

100% Statements 52/52
100% Branches 22/22
100% Functions 4/4
100% Lines 46/46
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                                                                  62× 62× 62× 62× 62×                       25×   23×                 65×     63×   63× 63× 61×   61×   61× 61× 61× 61× 61× 61×   61× 185× 185× 185× 178×   185× 185× 185×     61× 13×             61× 61×     63×    
/**
 * @license Apache-2.0
 * Copyright (C) 2016 The Sitecheck Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
"use strict";
 
var cheerio = require('cheerio');
var winston = require('winston');
 
/**
 * An input vector : a set of data that can interract with the application via an url
 * An input vector can be a form action, a restful api call, an url with a query part, etc.
 */
class InputVector {
 
    /**
     * Constructor
     * @param {string} uri - action uri to pass the input data to.
     * @param {string} method - 'GET', 'POST', 'HEADER', 'PUT', 'DELETE', 'PATCH'. lower case chars are automatically uppercased
     * @param {Object} fields - an array fields. Fields are literals defined this way : {name:'', type:'', value:''}
     * @param {string} enctype - Data encoding type. Default value is null and should be considered equivalent to "application/x-www-form-urlencoded". Value should be (but is not restricted to) one of the 3 HTML standard values "application/x-www-form-urlencoded", "multipart/form-data", "text/plain".
     */
    constructor(url, name, method, fields, enctype) {
        this.url = url; // action url
        this.name = name;
        this.method = method; // http method : GET, POST, HEADER, PUT, DELETE, PATCH
        this.fields = fields;
        this.enctype = enctype;
    }
 
    /**
     * Returns true if the object maps a login form
     */
    isLoginForm() {
        //if (this.url && this.fields.password) return true;
        for(let fields of this.fields){
            if(fields.type == "password") return true;
        }
    }
 
    isSameVector(secondVector) {
        let firstArray = [], secondArray = [];
                for (let field of this.fields) {
                    firstArray.push({ 'name': field.name, 'type': field.type });
                }
                for (let field of secondVector.fields) {
                    secondArray.push({ 'name': field.name, 'type': field.type });
            }
        return JSON.stringify(firstArray) === JSON.stringify(secondArray);
    }
}
 
/**
 * Returns an array of input vectors found in html
 * @param {string} html - Html text to parse
 */
function parseHtml(html) {
    if (!html) {
        winston.warn("InputVector.parseHtml(html) : no html.");
        return null; 
    }
 
    var ret = []; // array of InputVectors
 
    var $ = cheerio.load(html);
    $('form').each((i, el) => {
        var $form = $(el);
 
        let f = {};
 
        f.fields = [];
        f.name = $form.attr('name');
        f.action = $form.attr('action');
        f.method = $form.attr('method');
        if (f.method) f.method = f.method.toUpperCase();
        if ($form.attr('enctype')) f.enctype = $form.attr('enctype');
 
        $form.find('input').each((i, elem) => {
            let o = {};
            if ($(elem).attr('name')) o.name = $(elem).attr('name');
            if ($(elem).attr('type')) {
                o.type = $(elem).attr('type').toLowerCase();
            }
            if ($(elem).attr('value')) o.value = $(elem).attr('value');
            if ($(elem).attr('value')) o.checked = $(elem).attr('value');
            f.fields.push(o);
        });
 
        $form.find('button').each((i, elem) => {
            if ($(elem).attr('type') && $(elem).attr('formaction')) {
                if ($(elem).attr('type').toLowerCase() == "submit") {
                    f.action = $(elem).attr('formaction');
                }
            }
        });
 
        // TODO : check uppercase attribute names are lowercased by cheerio
 
        var iv = new InputVector(f.action, f.name, f.method, f.fields, f.enctype);
        ret.push(iv);
    });
 
    return ret;
}
 
module.exports = { InputVector, parseHtml };