librejs-cli
Version:
Command line tool for GNU LibreJS
200 lines (179 loc) • 5.95 kB
JavaScript
/*
* librejs-cli - A command-line tool for GNU LibreJS
* Copyright (C) 2014 Nik Nyby
*
* This file is part of librejs-cli.
*
* librejs-cli 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 3 of the License, or
* (at your option) any later version.
*
* librejs-cli 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 librejs-cli. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
var util = require('../util/util');
var AstAnalyzer = require('./ast-analyzer');
var LicStartEndLicense = require('./lic-start-end-license');
var MagnetLicense = require('./magnet-license');
var Report = require('../report/report');
var ReportItem = require('../report/report-item');
/**
* `LibrejsAnalyzer.Script` is responsible for analyzing JavaScript.
*
* @constructor
*/
function Script(options) {
if (typeof options === 'undefined') {
options = {};
}
this.data = options.data;
this.report = new Report();
// Is this script loaded from a <script> tag, or via XHR?
this.isExternal = true;
// This will be updated when you call isTrivial()
this.isTrivial = false;
}
module.exports = Script;
/**
* @function analyze
*
* Run the script analysis.
*
* @return {Report}
*/
Script.prototype.analyze = function() {
var isTrivial = this._isTrivial();
var hasLicStartLicense = !!this._findLicStartLicense();
var hasMagnetLicense = !!this._findMagnetLicense();
this.report.addItem(new ReportItem({
desc: 'Trivial',
type: 'triviality',
val: isTrivial
}));
this.report.addItem(new ReportItem({
desc: 'Has @licstart/@licend license',
type: 'lic-start-end',
val: hasLicStartLicense
}));
this.report.addItem(new ReportItem({
desc: 'Has magnet license',
type: 'magnet-license',
val: hasMagnetLicense
}));
this.report.passed = isTrivial;
if (isTrivial === false) {
this.report.passed = hasLicStartLicense || hasMagnetLicense;
}
return this.report;
};
/**
* @function _isTrivial
*
* Check if this script is considered trivial. The following is from the
* LibreJS 6.0.6 manual.
*
* LibreJS considers JavaScript on a page nontrivial if any of the
* following are true:
*
* * It makes an AJAX request or is loaded along with scripts that make
* an AJAX request,
*
* * It loads external scripts dynamically or is loaded along with
* scripts that do,
*
* * It defines functions or methods and either loads an external script
* (from HTML) or is loaded as one,
*
* * It uses dynamic JavaScript constructs that are difficult to analyze
* without interpreting the program or is loaded along with scripts
* that use such constructs. These constructs are:
* * Using the eval function
* * Calling methods with the square bracket notation
* * Using any other construct than a string literal with certain
* methods ('Obj.write', 'Obj.createElement', ...).
*
*
* @return {Boolean}
*/
Script.prototype._isTrivial = function() {
var isTrivial = true;
var astAnalyzer = new AstAnalyzer(this.data);
/*
* * It makes an AJAX request or is loaded along with scripts that make
* an AJAX request,
*/
if (astAnalyzer.createsXhr()) {
this.isTrivial = false;
return this.isTrivial;
}
/*
* * It loads external scripts dynamically or is loaded along with
* scripts that do,
*/
/*
* * It defines functions or methods and either loads an external script
* (from HTML) or is loaded as one,
*/
if (this.isExternal && astAnalyzer.hasFunction()) {
this.isTrivial = false;
return this.isTrivial;
}
/*
* * It uses dynamic JavaScript constructs that are difficult to analyze
* without interpreting the program or is loaded along with scripts
* that use such constructs. These constructs are:
*/
/* * Using the eval function */
if (astAnalyzer.hasEval()) {
this.isTrivial = false;
return this.isTrivial;
}
/* * Calling methods with the square bracket notation */
/*
* * Using any other construct than a string literal with certain
* methods ('Obj.write', 'Obj.createElement', ...).
*/
this.isTrivial = isTrivial;
return this.isTrivial;
};
/**
* Look for licstart/licend license. Warn if more than one is found.
*
* @method _findLicStartLicense
* @return {Object}
*/
Script.prototype._findLicStartLicense = function() {
var licStartEndRe =
/?/mi;
var matched = util.removeWhitespace(this.data).match(licStartEndRe);
if (matched) {
var licStartEndLicense = new LicStartEndLicense(this.data);
return licStartEndLicense;
} else {
return null;
}
};
/**
* Look for magnet link. Warn if more than one is found.
*
* @method _findMagnetLicense
* @return {Object}
*/
Script.prototype._findMagnetLicense = function() {
var licenseMagnet = /.* ?(magnet\:\?xt=urn\:btih\:[0-9A-Za-z]+).*/;
var licenseEndMagnet = /.*-end.*/i;
var matched = util.removeWhitespace(this.data).match(licenseMagnet);
if (matched) {
var magnetLicense = new MagnetLicense(this.data);
return magnetLicense;
} else {
return null;
}
};