<commit_before>import { FS } from 'grind-support'
import { encodeHTML } from 'entities'

const acorn = require('acorn')
acorn.walk = require('acorn/dist/walk').simple

const astring = require('astring')

export class Stone {
	viewsPath = null

	context = {
		escape: value => {
			if(value.isNil) {
				return ''
			}

			return encodeHTML(value.toString())
		}

	}

	constructor(viewsPath) {
		this.viewsPath = viewsPath
	}

	async compile(template) {
		let contents = (await FS.readFile(template)).toString().trim()

		const expressions = [ ]
		let match = null

		while((match = contents.match(/@([a-z0-9_]+)(\s*\()?/))) {
			if(match.index > 0) {
				expressions.push({
					type: 'string',
					contents: contents.substring(0, match.index)
				})

				contents = contents.substring(match.index)
			}

			let args = null

			if(match[2]) {
				let openCount = -1
				let index = 0
				let startIndex = 0
				let lastIndex = 0

				while(openCount !== 0 && (index = indexOfParenthesis(contents, index)) >= 0) {
					const parenthesis = contents.substring(index, index + 1)

					if(parenthesis === ')') {
						openCount--
					} else if(openCount === -1) {
						startIndex = index
						openCount = 1
					} else {
						openCount++
					}

					lastIndex = index
					index++
				}

				args = contents.substring(startIndex + 1, lastIndex)
				contents = contents.substring(lastIndex + 1)
			} else {
				contents = contents.substring(match[0].length)
			}

			const method = `compile${match[1][0].toUpperCase()}${match[1].substring(1)}`
			const result = this[method](args)

			if(!result.isNil) {
				expressions.push({
					type: 'code',
					contents: result
				})
			}
		}

		contents = contents.trim()

		if(contents.length > 0) {
			expressions.push({
				type: 'string',
				contents: contents
			})
		}

		let code = ''

		for(const { type, contents } of expressions) {
			if(type === 'code') {
				code += `${contents}\n`
			} else {
				code += `output += \`${sanetizeString(contents)}\`;\n`
			}
		}

		code = `template = function(_) {\nlet output = '';\n${this._contextualize(code)}\nreturn output;\n}`

		return eval(code)
	}

	render(template, context) {
		return this.compile(this.resolve(template)).then(template => template({ ...this.context, ...context }))
	}

	resolve(template) {
		return `${this.viewsPath}/${template.replace(/\./g, '/')}.stone`
	}

	_contextualize(code) {
		const tree = acorn.parse(code)
		const scopes = [
			{
				locals: new Set,
				end: Number.MAX_VALUE
			}
		]

		let scope = scopes[0]

		const checkScope = fromNode => {
			while(fromNode.start >= scope.end && scopes.length > 1) {
				scopes.pop()
				scope = scopes[scopes.length - 1]
			}
		}

		acorn.walk(tree, {
			Statement: node => {
				checkScope(node)
			},

			BlockStatement: node => {
				checkScope(node)

				scope = {
					locals: new Set(scope.locals),
					node: node,
					end: node.end
				}

				scopes.push(scope)
			},

			VariableDeclarator: node => {
				checkScope(node)
				scope.locals.add(node.id.name)
			},

			Identifier: node => {
				checkScope(node)

				if(scope.locals.has(node.name)) {
					return
				}

				node.name = `_.${node.name}`
			}
		})

		return astring(tree)
	}

	compileIf(args) {
		return `if(${args}) {`
	}

	compileElseif(args) {
		return `} else if(${args}) {`
	}

	compileElse() {
		return '} else {'
	}

	compileEndif() {
		return this.compileEnd()
	}

	compileFor(args) {
		return `for(${args}) {`
	}

	compileEndfor() {
		return this.compileEnd()
	}

	compileWhile(args) {
		return `while(${args}) {`
	}

	compileEndwhile() {
		return this.compileEnd()
	}

	compileEnd() {
		return '}'
	}

}

/**
 * [indexOfParenthesis description]
 * @param  {string} string    [description]
 * @param  {number} fromIndex [description]
 * @return {number}           [description]
 */
function indexOfParenthesis(string, fromIndex) {
	const open = string.indexOf('(', fromIndex)
	const close = string.indexOf(')', fromIndex)

	if(open === -1) {
		return close
	} else if(close === -1)  {
		return open
	}

	return Math.min(open, close)
}

function sanetizeString(string) {
	string = string.replace(/\{\{\s*(.+?)\s*\}\}/g, '${escape($1)}')
	string = string.replace(/\{!!\s*(.+?)\s*!!\}/g, '${$1}')
	string = string.replace(/[\n]/g, '\\n')
	string = string.replace(/[\r]/g, '\\r')
	string = string.replace(/[\t]/g, '\\t')

	return string
}
<commit_msg>Added very basic support for sections/layouts<commit_after>import { FS } from 'grind-support'
import { encodeHTML } from 'entities'

const acorn = require('acorn')
acorn.walk = require('acorn/dist/walk').simple

const astring = require('astring')

export class Stone {
	viewsPath = null

	context = {
		escape: value => {
			if(value.isNil) {
				return ''
			}

			return encodeHTML(value.toString())
		}

	}

	constructor(viewsPath) {
		this.viewsPath = viewsPath
	}

	async compile(template) {
		let contents = (await FS.readFile(template)).toString().trim()
		let extendsLayout = null

		const expressions = [ ]
		let match = null

		while((match = contents.match(/@([a-z0-9_]+)(\s*\()?/))) {
			if(match.index > 0) {
				expressions.push({
					type: 'string',
					contents: contents.substring(0, match.index)
				})

				contents = contents.substring(match.index)
			}

			let args = null

			if(match[2]) {
				let openCount = -1
				let index = 0
				let startIndex = 0
				let lastIndex = 0

				while(openCount !== 0 && (index = indexOfParenthesis(contents, index)) >= 0) {
					const parenthesis = contents.substring(index, index + 1)

					if(parenthesis === ')') {
						openCount--
					} else if(openCount === -1) {
						startIndex = index
						openCount = 1
					} else {
						openCount++
					}

					lastIndex = index
					index++
				}

				args = contents.substring(startIndex + 1, lastIndex)
				contents = contents.substring(lastIndex + 1)
			} else {
				contents = contents.substring(match[0].length)
			}

			if(match[1] === 'extends') {
				extendsLayout = args
				continue
			}

			const method = `compile${match[1][0].toUpperCase()}${match[1].substring(1)}`
			const result = this[method](args)

			if(!result.isNil) {
				expressions.push({
					type: 'code',
					contents: result
				})
			}
		}

		contents = contents.trim()

		if(contents.length > 0) {
			expressions.push({
				type: 'string',
				contents: contents
			})
		}

		let code = ''

		for(const { type, contents } of expressions) {
			if(type === 'code') {
				code += `${contents}\n`
			} else {
				code += `output += \`${sanetizeString(contents)}\`;\n`
			}
		}

		code = `template = function(_, _sections = { }) {\nlet output = '';\n${this._contextualize(code)}\n`

		if(extendsLayout !== null) {
			code += `return _.$engine._extends(${extendsLayout}, _, _sections);\n}`
		} else {
			code += `return output;\n}`
		}

		return eval(code)
	}

	render(template, context) {
		return this.compile(this.resolve(template)).then(template => template({
			...this.context,
			...context,
			$engine: this
		}))
	}

	_extends(template, context, sections) {
		return this.compile(this.resolve(template)).then(template => template(context, sections))
	}

	resolve(template) {
		return `${this.viewsPath}/${template.replace(/\./g, '/')}.stone`
	}

	_contextualize(code) {
		const tree = acorn.parse(code)
		const scopes = [
			{
				locals: new Set([ '_sections' ]),
				end: Number.MAX_VALUE
			}
		]

		let scope = scopes[0]

		const checkScope = fromNode => {
			while(fromNode.start >= scope.end && scopes.length > 1) {
				scopes.pop()
				scope = scopes[scopes.length - 1]
			}
		}

		acorn.walk(tree, {
			Statement: node => {
				checkScope(node)
			},

			BlockStatement: node => {
				checkScope(node)

				scope = {
					locals: new Set(scope.locals),
					node: node,
					end: node.end
				}

				scopes.push(scope)
			},

			VariableDeclarator: node => {
				checkScope(node)
				scope.locals.add(node.id.name)
			},

			Identifier: node => {
				checkScope(node)

				if(scope.locals.has(node.name)) {
					return
				}

				node.name = `_.${node.name}`
			}
		})

		return astring(tree)
	}

	compileIf(args) {
		return `if(${args}) {`
	}

	compileElseif(args) {
		return `} else if(${args}) {`
	}

	compileElse() {
		return '} else {'
	}

	compileEndif() {
		return this.compileEnd()
	}

	compileFor(args) {
		return `for(${args}) {`
	}

	compileEndfor() {
		return this.compileEnd()
	}

	compileWhile(args) {
		return `while(${args}) {`
	}

	compileEndwhile() {
		return this.compileEnd()
	}

	compileEnd() {
		return '}'
	}

	compileSection(args) {
		return `_sections[${args}] = function() {\nlet output = '';\n`
	}

	compileEndsection() {
		return 'return output;\n}'
	}

	compileYield(section) {
		return `output += typeof _sections[${section}] === 'function' ? _sections[${section}]() : ''`
	}

}

/**
 * [indexOfParenthesis description]
 * @param  {string} string    [description]
 * @param  {number} fromIndex [description]
 * @return {number}           [description]
 */
function indexOfParenthesis(string, fromIndex) {
	const open = string.indexOf('(', fromIndex)
	const close = string.indexOf(')', fromIndex)

	if(open === -1) {
		return close
	} else if(close === -1)  {
		return open
	}

	return Math.min(open, close)
}

function sanetizeString(string) {
	string = string.replace(/\{\{\s*(.+?)\s*\}\}/g, '${escape($1)}')
	string = string.replace(/\{!!\s*(.+?)\s*!!\}/g, '${$1}')
	string = string.replace(/[\n]/g, '\\n')
	string = string.replace(/[\r]/g, '\\r')
	string = string.replace(/[\t]/g, '\\t')

	return string
}
<|endoftext|>


<commit_before>// @flow

import type { $Request, $Response } from "express";

import { exec as execSync } from "child_process";
import jsesc from "jsesc";
import Logger from "../logger/logger.model";
import { promisify } from "util";

const exec = promisify(execSync);

// Compile java code
// export function compile(req: $Request, res: $Response) {
//   const fileName = req.body.fileName;
//   let dirName = `users/${req.body.user._id}/`;
//   const dateTime = new Date();
//   dirName += dateTime.getMonth();
//   dirName += dateTime.getDate();
//   dirName += dateTime.getFullYear();
//
//   // make a directory for this user, if doesn't exist already
//   exec(
//     `mkdir -p ${dirName}`,
//     { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//     (error, stdout, stderr) => {
//       if (error) {
//         return res.status(200).send(stderr);
//       }
//
//       const escapedCode = jsesc(req.body.code, {
//         wrap: true
//       });
//       exec(
//         `echo ${escapedCode} > ${dirName}/${fileName}`,
//         { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//         (error, stdout, stderr) => {
//           if (error) {
//             return res.status(200).send(stderr);
//           }
//           compileJavaFile(`${dirName}/${fileName}`, dirName, res);
//         }
//       );
//     }
//   );
// }
//
// // run java code
// export function run(req: $Request, res: $Response) {
//   let dirName = `users/${req.body.user._id}/`;
//   const dateTime = new Date();
//   dirName += dateTime.getMonth();
//   dirName += dateTime.getDate();
//   dirName += dateTime.getFullYear();
//   const execFile = req.body.fileName.replace(".c", "");
//   const cmd = `"${dirName}/${execFile}"`;
//   exec(
//     cmd,
//     { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//     (error, stdout, stderr) => {
//       if (error) {
//         return res.status(200).send(error);
//       }
//       return res.status(200).send({ stdout, stderr });
//     }
//   );
// }
//
// function compileJavaFile(srcFile, dirName, res) {
//   const execFile = srcFile.replace(".c", "");
//   // exec is asynchronous
//   exec(
//     `gcc "${srcFile}" -o "${execFile}"`,
//     { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//     (error, stdout, stderr) => {
//       if (error) {
//         return res.status(200).send(stderr);
//       }
//       return res.send(stdout);
//     }
//   );
// }

// In production, run student executables securely as comped-exec
export const runExecutablesAsCompedExecUser = process.env.USER === "comped";

if (runExecutablesAsCompedExecUser) {
  console.log("Running executables securely as comped-exec user");
} else {
  console.log("Running executables non-securely");
}

export async function compileLogger(req: $Request, res: $Response) {
  try {
    const userId = req.user.id;
    const loggerId = req.params.id;
    const logger = await Logger.findById(loggerId);
    if (!logger) {
      return res.status(400).json({
        error: `No logger found;`
      });
    }
    //console.log(logger);
    const dirName = "users/" + userId + "/" + loggerId;
    await exec("mkdir -p " + dirName);
    const escapedCode = jsesc(logger.code, {
      wrap: true
    });
    await exec(`echo ${escapedCode} > ${dirName}/${logger.className}.c`);
    const gcc = `gcc "${dirName}/${logger.className}.c" -o "${dirName}/${logger.className}" -lm`;
    //console.log(gcc);
    const result = await exec(gcc, {
      timeout: 10000
    });
    //console.error("result object", result);
    return res
      .status(200)
      .json({ error: false, stdout: result.stdout, stderr: result.stderr });
  } catch (err) {
    // console.error(err);
    return res
      .status(200)
      .json({ error: true, stdout: err.stdout, stderr: err.stderr });
  }
}

export async function runLogger(req: $Request, res: $Response) {
  const timeLimitInSeconds = 20;
  try {
    const userId = req.user.id;
    const loggerId = req.params.id;
    const logger = await Logger.findById(loggerId);
    if (!logger) {
      return res.status(400).json({
        error: `No logger found;`
      });
    }
    const dirName = "users/" + userId + "/" + loggerId;
    const cmd = (runExecutablesAsCompedExecUser ?
      `sudo -u comped-exec "${dirName}/${logger.className}"` :
      `"${dirName}/${logger.className}"`
    );
    const result = await exec(cmd, { timeout: timeLimitInSeconds * 1000 });
    return res
      .status(200)
      .json({ error: false, stdout: result.stdout, stderr: result.stderr });
  } catch (err) {
    let stderr = err.stderr;
    if (err.signal === "SIGTERM") {
      stderr = `TimeoutError: file took longer than ${timeLimitInSeconds} seconds to run`;
    }
    return res
      .status(200)
      .json({ error: true, stdout: err.stdout, stderr: stderr });
  }
}
<commit_msg>Wrap exec call in a promise-timeout to see if that'll help anything<commit_after>// @flow

import type { $Request, $Response } from "express";

import { exec as execSync } from "child_process";
import jsesc from "jsesc";
import Logger from "../logger/logger.model";
import { promisify } from "util";
import { timeout, TimeoutError } from 'promise-timeout';

const exec = promisify(execSync);

// Compile java code
// export function compile(req: $Request, res: $Response) {
//   const fileName = req.body.fileName;
//   let dirName = `users/${req.body.user._id}/`;
//   const dateTime = new Date();
//   dirName += dateTime.getMonth();
//   dirName += dateTime.getDate();
//   dirName += dateTime.getFullYear();
//
//   // make a directory for this user, if doesn't exist already
//   exec(
//     `mkdir -p ${dirName}`,
//     { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//     (error, stdout, stderr) => {
//       if (error) {
//         return res.status(200).send(stderr);
//       }
//
//       const escapedCode = jsesc(req.body.code, {
//         wrap: true
//       });
//       exec(
//         `echo ${escapedCode} > ${dirName}/${fileName}`,
//         { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//         (error, stdout, stderr) => {
//           if (error) {
//             return res.status(200).send(stderr);
//           }
//           compileJavaFile(`${dirName}/${fileName}`, dirName, res);
//         }
//       );
//     }
//   );
// }
//
// // run java code
// export function run(req: $Request, res: $Response) {
//   let dirName = `users/${req.body.user._id}/`;
//   const dateTime = new Date();
//   dirName += dateTime.getMonth();
//   dirName += dateTime.getDate();
//   dirName += dateTime.getFullYear();
//   const execFile = req.body.fileName.replace(".c", "");
//   const cmd = `"${dirName}/${execFile}"`;
//   exec(
//     cmd,
//     { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//     (error, stdout, stderr) => {
//       if (error) {
//         return res.status(200).send(error);
//       }
//       return res.status(200).send({ stdout, stderr });
//     }
//   );
// }
//
// function compileJavaFile(srcFile, dirName, res) {
//   const execFile = srcFile.replace(".c", "");
//   // exec is asynchronous
//   exec(
//     `gcc "${srcFile}" -o "${execFile}"`,
//     { timeout: 10000 }, // Process will time out if running for > 10 seconds.
//     (error, stdout, stderr) => {
//       if (error) {
//         return res.status(200).send(stderr);
//       }
//       return res.send(stdout);
//     }
//   );
// }

// In production, run student executables securely as comped-exec
export const runExecutablesAsCompedExecUser = process.env.USER === "comped";

if (runExecutablesAsCompedExecUser) {
  console.log("Running executables securely as comped-exec user");
} else {
  console.log("Running executables non-securely");
}

export async function compileLogger(req: $Request, res: $Response) {
  try {
    const userId = req.user.id;
    const loggerId = req.params.id;
    const logger = await Logger.findById(loggerId);
    if (!logger) {
      return res.status(400).json({
        error: `No logger found;`
      });
    }
    //console.log(logger);
    const dirName = "users/" + userId + "/" + loggerId;
    await exec("mkdir -p " + dirName);
    const escapedCode = jsesc(logger.code, {
      wrap: true
    });
    await exec(`echo ${escapedCode} > ${dirName}/${logger.className}.c`);
    const gcc = `gcc "${dirName}/${logger.className}.c" -o "${dirName}/${logger.className}" -lm`;
    //console.log(gcc);
    const result = await exec(gcc, {
      timeout: 10000
    });
    //console.error("result object", result);
    return res
      .status(200)
      .json({ error: false, stdout: result.stdout, stderr: result.stderr });
  } catch (err) {
    // console.error(err);
    return res
      .status(200)
      .json({ error: true, stdout: err.stdout, stderr: err.stderr });
  }
}

export async function runLogger(req: $Request, res: $Response) {
  const timeLimitInSeconds = 20;
  try {
    const userId = req.user.id;
    const loggerId = req.params.id;
    const logger = await Logger.findById(loggerId);
    if (!logger) {
      return res.status(400).json({
        error: `No logger found;`
      });
    }
    const dirName = "users/" + userId + "/" + loggerId;
    const cmd = (runExecutablesAsCompedExecUser ?
      `sudo -u comped-exec "${dirName}/${logger.className}"` :
      `"${dirName}/${logger.className}"`
    );
    const result = await timeout(exec(cmd, { timeout: timeLimitInSeconds * 1000 }), timeLimitInSeconds * 1000);
    return res
      .status(200)
      .json({ error: false, stdout: result.stdout, stderr: result.stderr });
  } catch (err) {
    let stderr = err.stderr;
    if (err.signal === "SIGTERM" || err instanceof TimeoutError) {
      stderr = `TimeoutError: file took longer than ${timeLimitInSeconds} seconds to run`;
    }
    return res
      .status(200)
      .json({ error: true, stdout: err.stdout || "", stderr: stderr });
  }
}
<|endoftext|>


<commit_before>$(document).ready(function(){
    WordCloud(document.getElementById('wordCloud'), { list: cloudData, gridSize: 16, weightFactor: 10} );
    var generateRatingBoxes = function(){
        $('.rating-holder .rating-bars').each(function(index){
            var up = votes[index][0].length;
            var down = votes[index][1].length;
            var total = up+down;
            $(this).html('
'+ up + '

' + down + '
');
        });
    };
    var generateButtons = function(){
        $('.rating-holder .rating-buttons').each(function(index){
            $(this).html('DownvoteUpvote');
        });
    };
    var inArray = function(needle, haystack) {
        var length = haystack.length;
        for(var i = 0; i < length; i++) {
            if(haystack[i] == needle) return true;
        }
        return false;
    };
    $('.upvote').on("click", function(){
        alert($(this).html());
    });
    $('.downvote').on("click", function(){
        alert($(this).html());
    });
    generateRatingBoxes();
    generateButtons();
});
<commit_msg>Fix to button generation<commit_after>$(document).ready(function(){
    WordCloud(document.getElementById('wordCloud'), { list: cloudData, gridSize: 16, weightFactor: 10} );
    var generateRatingBoxes = function(){
        $('.rating-holder .rating-bars').each(function(index){
            var up = votes[index][0].length;
            var down = votes[index][1].length;
            var total = up+down;
            $(this).html('
'+ up + '

' + down + '
');
        });
    };
    var generateButtons = function(){
        $('.rating-holder .rating-buttons').each(function(index){
            $(this).html('DownvoteUpvote');
        });
    };
    var inArray = function(needle, haystack) {
        var length = haystack.length;
        for(var i = 0; i < length; i++) {
            if(haystack[i] == needle) return true;
        }
        return false;
    };
    $('.upvote').on("click", function(){
        alert($(this).html());
    });
    $('.downvote').on("click", function(){
        alert($(this).html());
    });
    generateRatingBoxes();
    generateButtons();
});
<|endoftext|>


<commit_before>var w = screen.width * 0.30,
h = screen.height * 0.40,
r = 380,
x = d3.scale.linear().range([0, r]),
y = d3.scale.linear().range([0, r]),
p = 15,
label_rad = 25,
node,
root,
fc1,fc2,fc3,
chart_dyn,
chart_type;

if (typeof String.prototype.startsWith != 'function') {
    // see below for better implementation!
    String.prototype.startsWith = function (str){
        return this.indexOf(str) == 0;
    };
}

var colorMap = {"Wet Storage": "#1f77b4",
                "Dry Storage": "#aec7e8",
                "Repository": "#ffbb78",
                "Reprocessed Fuel": "#2ca02c"
               }

function colorPicker(s) {
    var c = "white";
    for (var key in colorMap) {
        if (s.startsWith(key)) {
            c = colorMap[key];
            break;
        };
    };
    return c;
}

function wrap(text, width) {
    text.each(function() {
        var text = d3.select(this),
        lines = text.text().split(/\n/).reverse(),
        line,
        lineNumber = 0,
        lineHeight = 1.1, // ems
        x = text.attr("x"),
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", x)
            .attr("y", y).attr("dy", dy + "em");
        lineNumber = - Math.floor(lines.length / 2);
        while (line = lines.pop()) {
            tspan = text.append("tspan").attr("x", x)
                .attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em")
                .text(line);
        }
    });
}

var pack = d3.layout.pack()
    .size([r, r])
    .value(function(d) { return d.size;})
    .padding(p);

function load_data(chart_node,json_data)
{
    d3.json(json_data, function(data) {
        node = root = data;
        var nodes = pack.nodes(root);
        chart_node.selectAll("circle")
            .remove();
        chart_node.selectAll("circle")
            .data(nodes)
            .enter().append("svg:circle")
            .attr("class", function(d) { return d.children ? "parent" : "child"; })
            .attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; })
            .attr("r", function(d) { return d.r; })
            .style("stroke-width",function(d) {if (d.children && !chart_dyn && d.children[0].children)
                                               {return 0}; return 1;})
            .style("fill", function(d){return colorPicker(d.name)});

        chart_node.selectAll("text")
            .remove();
        chart_node.selectAll("text")
            .data(nodes)
            .enter().append("svg:text")
            .attr("class", function(d) { return d.children ? "parent" : "child"; })
            .attr("x", function(d) { return d.x; })
            .attr("y", function(d) { if (d.children) {return d.y - d.r - 20;}; return d.y; })
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
            .style("opacity", function(d) { return d.r > label_rad ? 1 : 0; })
            .text(function(d) { if (d.children) {return d.name;}; return d.name; })
            .call(wrap);
    });
}

function add_info(chart_id)
{

    var new_chart = d3.select(chart_id + " svg")
        .attr("width", w)
        .attr("height", h)
        .append("svg:g")
        .attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");

    return new_chart;
}

function load_static(kind)
{
    var cost_ver = "";

    if (kind == "cost")
    {
        cost_ver = "-new";
    }
    load_data(fc1,"info-raw-data-run1" + cost_ver + "-2000_2050_2100-" + kind + ".json");
    load_data(fc2,"info-raw-data-run3" + cost_ver + "-2000_2050_2100-" + kind + ".json");
    load_data(fc3,"info-raw-data-run5" + cost_ver + "-2000_2050_2100-" + kind + ".json");
}

function load_fcs(kind,year) {
    var cost_ver = "";

    if (kind == "cost")
    {
        cost_ver = "-new";
    }
    load_data(fc1,"years/info-raw-data-run1" + cost_ver + "-" + year + "-" + kind + ".json");
    load_data(fc2,"years/info-raw-data-run3" + cost_ver + "-" + year + "-" + kind + ".json");
    load_data(fc3,"years/info-raw-data-run5" + cost_ver + "-" + year + "-" + kind + ".json");
}

function yearUpdate(year) {
    document.querySelector('#yearlabel').value = year;
    load_fcs(chart_type,year);
}

function info(dynamic,kind)
{
    chart_type = kind;
    chart_dyn = dynamic;

    fc1 = add_info("#chart1");
    fc2 = add_info("#chart2");
    fc3 = add_info("#chart3");

    if (dynamic)
    {
        load_fcs(kind,2000);
    }
    else
    {
        load_static(kind);
    }
}

<commit_msg>Always show value<commit_after>var w = screen.width * 0.30,
h = screen.height * 0.40,
r = 380,
x = d3.scale.linear().range([0, r]),
y = d3.scale.linear().range([0, r]),
p = 15,
label_rad = 25,
node,
root,
fc1,fc2,fc3,
chart_dyn,
chart_type;

if (typeof String.prototype.startsWith != 'function') {
    // see below for better implementation!
    String.prototype.startsWith = function (str){
        return this.indexOf(str) == 0;
    };
}

var colorMap = {"Wet Storage": "#1f77b4",
                "Dry Storage": "#aec7e8",
                "Repository": "#ffbb78",
                "Reprocessed Fuel": "#2ca02c"
               }

function colorPicker(s) {
    var c = "white";
    for (var key in colorMap) {
        if (s.startsWith(key)) {
            c = colorMap[key];
            break;
        };
    };
    return c;
}

function wrap(text, width) {
    text.each(function() {
        var text = d3.select(this),
        lines = text.text().split(/\n/).reverse(),
        line,
        lineNumber = 0,
        lineHeight = 1.1, // ems
        x = text.attr("x"),
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", x)
            .attr("y", y).attr("dy", dy + "em");
        lineNumber = - Math.floor(lines.length / 2);
        while (line = lines.pop()) {
            tspan = text.append("tspan").attr("x", x)
                .attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em")
                .text(line);
        }
    });
}

var pack = d3.layout.pack()
    .size([r, r])
    .value(function(d) { return d.size;})
    .padding(p);

function load_data(chart_node,json_data)
{
    d3.json(json_data, function(data) {
        node = root = data;
        var nodes = pack.nodes(root);
        chart_node.selectAll("circle")
            .remove();
        chart_node.selectAll("circle")
            .data(nodes)
            .enter().append("svg:circle")
            .attr("class", function(d) { return d.children ? "parent" : "child"; })
            .attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; })
            .attr("r", function(d) { return d.r; })
            .style("stroke-width",function(d) {if (d.children && !chart_dyn && d.children[0].children)
                                               {return 0}; return 1;})
            .style("fill", function(d){return colorPicker(d.name)});

        chart_node.selectAll("text")
            .remove();
        chart_node.selectAll("text")
            .data(nodes)
            .enter().append("svg:text")
            .attr("class", function(d) { return d.children ? "parent" : "child"; })
            .attr("x", function(d) { return d.x; })
            .attr("y", function(d) { if (d.children) {return d.y - d.r - 20;}; return d.y; })
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
//            .style("opacity", function(d) { return d.r > label_rad ? 1 : 0; })
            .text(function(d) { if (d.children) {return d.name;}; return d.name; })
            .call(wrap);
    });
}

function add_info(chart_id)
{

    var new_chart = d3.select(chart_id + " svg")
        .attr("width", w)
        .attr("height", h)
        .append("svg:g")
        .attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");

    return new_chart;
}

function load_static(kind)
{
    var cost_ver = "";

    if (kind == "cost")
    {
        cost_ver = "-new";
    }
    load_data(fc1,"info-raw-data-run1" + cost_ver + "-2000_2050_2100-" + kind + ".json");
    load_data(fc2,"info-raw-data-run3" + cost_ver + "-2000_2050_2100-" + kind + ".json");
    load_data(fc3,"info-raw-data-run5" + cost_ver + "-2000_2050_2100-" + kind + ".json");
}

function load_fcs(kind,year) {
    var cost_ver = "";

    if (kind == "cost")
    {
        cost_ver = "-new";
    }
    load_data(fc1,"years/info-raw-data-run1" + cost_ver + "-" + year + "-" + kind + ".json");
    load_data(fc2,"years/info-raw-data-run3" + cost_ver + "-" + year + "-" + kind + ".json");
    load_data(fc3,"years/info-raw-data-run5" + cost_ver + "-" + year + "-" + kind + ".json");
}

function yearUpdate(year) {
    document.querySelector('#yearlabel').value = year;
    load_fcs(chart_type,year);
}

function info(dynamic,kind)
{
    chart_type = kind;
    chart_dyn = dynamic;

    fc1 = add_info("#chart1");
    fc2 = add_info("#chart2");
    fc3 = add_info("#chart3");

    if (dynamic)
    {
        load_fcs(kind,2000);
    }
    else
    {
        load_static(kind);
    }
}

<|endoftext|>


<commit_before>/**
 * Projection class for Baidu Spherical Mercator
 *
 * @class BaiduSphericalMercator
 */
L.Projection.BaiduSphericalMercator = {
    /**
     * Project latLng to point coordinate
     *
     * @method project
     * @param {Object} latLng coordinate for a point on earth
     * @return {Object} leafletPoint point coordinate of L.Point
     */
    project: function(latLng) {
        var projection = new BMap.MercatorProjection();
        var point = projection.lngLatToPoint(
            new BMap.Point(latLng.lng, latLng.lat)
        );
        leafletPoint = new L.Point(point.x, point.y);
        return leafletPoint;
    },

    /**
     * unproject point coordinate to latLng
     *
     * @method unproject
     * @param {Object} bpoint baidu point coordinate
     * @return {Object} latitude and longitude
     */
    unproject: function (bpoint) {
        var projection= new BMap.MercatorProjection();
        var point = projection.pointToLngLat(
            new BMap.Pixel(bpoint.x, bpoint.y)
        );
        latLng = new L.LatLng(point.lng, point.lat);
        return latLng;
    },

    /**
     * Don't know how it used currently.
     *
     * However, I guess this is the range of coordinate.
     * Range of pixel coordinate is gotten from
     * BMap.MercatorProjection.lngLatToPoint(180, -90) and (180, 90)
     * After getting max min value of pixel coordinate, use
     * pointToLngLat() get the max lat and Lng.
     */
    bounds: (function () {
        var MAX_X= 20037726.37;
        var MIN_Y= -11708041.66;
        var MAX_Y= 12474104.17;
        var bounds = L.bounds(
            [-MAX_X, MIN_Y], //180, -71.988531
            [MAX_X, MAX_Y]  //-180, 74.000022
        );
        return bounds;
    })()
};

/**
 * Transformation class for Baidu Transformation.
 * Basically, it contains the conversion of point coordinate and
 * pixel coordinate.
 *
 * @class BTransformation
 */
L.BTransformation = function () {
};

L.BTransformation.prototype = {
    MAXZOOM: 18,
    /**
     * Don't know how it used currently.
     */
    transform: function (point, zoom) {
        return this._transform(point.clone(), zoom);
    },

    /**
     * transform point coordinate to pixel coordinate
     *
     * @method _transform
     * @param {Object} point point coordinate
     * @param {Number} zoom zoom level of the map
     * @return {Object} point, pixel coordinate
     */
    _transform: function (point, zoom) {
        point.x = point.x >> (this.MAXZOOM - zoom);
        point.y = point.y >> (this.MAXZOOM - zoom);
        return point;
    },

    /**
     * transform pixel coordinate to point coordinate
     *
     * @method untransform
     * @param {Object} point pixel coordinate
     * @param {Number} zoom zoom level of the map
     * @return {Object} point, point coordinate
     */
    untransform: function (point, zoom) {
        point.x = point.x << (this.MAXZOOM - zoom);
        point.y = point.y << (this.MAXZOOM - zoom);
        return point;
    }
};

/**
 * Coordinate system for Baidu EPSG3857
 *
 * @class BEPSG3857
 */
L.CRS.BEPSG3857 = L.extend({}, L.CRS, {
    /**
     * transform latLng to pixel coordinate
     *
     * @method untransform
     * @param {Object} latlng latitude and longitude
     * @param {Number} zoom zoom level of the map
     * @return {Object} pixel coordinate calculated for latLng
     */
    latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point
		var projectedPoint = this.projection.project(latlng);
		return this.transformation._transform(projectedPoint, zoom);
	},

    /**
     * transform pixel coordinate to latLng
     *
     * @method untransform
     * @param {Object} point pixel coordinate
     * @param {Number} zoom zoom level of the map
     * @return {Object} latitude and longitude
     */
    pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng
		var untransformedPoint = this.transformation.untransform(point, zoom);
		return this.projection.unproject(untransformedPoint);
	},

    code: 'EPSG:3857',
    projection: L.Projection.BaiduSphericalMercator,

    transformation: new L.BTransformation()
});

/**
 * Tile layer for Baidu Map
 *
 * @class Baidu
 */
L.Baidu = L.TileLayer.extend({
    options: {
        subdomains: ['online1', 'online2', 'online3'],
        //TODO: decode utf8 characters in attribution
        attribution: '© 2014 Baidu - GS(2012)6003;- Data © NavInfo & CenNavi & DaoDaoTong',
    },

    /**
     * initialize the map with key and tile URL
     *
     * @method initialize
     * @param {String} key access key of baidu map
     * @param {Object} options, option of the map
     */
    initialize: function (key, options) {
        L.Util.setOptions(this, options);
        this._key = key;
        this._url = 'http://{subdomain}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=20140711';
    },

    /**
     * Set the corresponding position of tiles in baidu map.
     * if point.y is less or equal than 256, i.e. 35=>291, -221=>547
     * if point.y is greater than 256, i.e. 291=>35, 547=>-221
     *
     * @method _getTilePos
     * @param {Object} tilePoint tile coordinate
     * @return {Object} point left and top property of
     */
    _getTilePos: function (tilePoint) {
        var origin = this._map.getPixelOrigin();
        var tileSize = this._getTileSize();

        var point = tilePoint.multiplyBy(tileSize).subtract(origin);
        if (point.y <= 256) {
            point.y = (
                2 * Math.abs(
                    Math.floor(point.y / tileSize)
                ) + 1
            ) * tileSize + point.y;
        } else {
            point.y = point.y - (
                Math.floor(point.y / tileSize) * 2 - 1
            ) * tileSize;
        }
        return point;
    },

    /**
     * get a tile url of the map
     *
     * @method getTileUrl
     * @param {Object} coords, tile coordinate
     * @return {String} url of a tile
     */
    getTileUrl: function(coords) {
        return this._url.replace('{subdomain}', this._getSubdomain(coords))
            .replace('{x}', coords.x)
            .replace('{y}', coords.y)
            .replace('{z}', this._getZoomForUrl());
    }
});

L.map = function (id, options) {
    map = new L.Map(id, options);

    /**
     * Override _getTopLeftPoint method. For Baidu Map, if dragging
     * down side of the map, y will increase rather than decrease.
     * vice versa.
     *
     * @method _getTopLeftPoint
     * @return {Object} point top left point
     */
    map._getTopLeftPoint = function() {
        if (options.baidu === true) {
            var pixel = this.getPixelOrigin();
            var pane = this._getMapPanePos();
            var point = new L.Point(pixel.x - pane.x, pixel.y + pane.y);
            return point;
        } else {
            return this.getPixelOrigin().subtract(this._getMapPanePos());
        }
    };
    return map;
};

L.baiduLayer = function (key, options) {
    return new L.Baidu(key, options);
};
<commit_msg>re #2: fix latitude<commit_after>/**
 * Projection class for Baidu Spherical Mercator
 *
 * @class BaiduSphericalMercator
 */
L.Projection.BaiduSphericalMercator = {
    /**
     * Project latLng to point coordinate
     *
     * @method project
     * @param {Object} latLng coordinate for a point on earth
     * @return {Object} leafletPoint point coordinate of L.Point
     */
    project: function(latLng) {
        var projection = new BMap.MercatorProjection();
        var point = projection.lngLatToPoint(
            new BMap.Point(latLng.lng, latLng.lat)
        );
        leafletPoint = new L.Point(point.x, point.y);
        return leafletPoint;
    },

    /**
     * unproject point coordinate to latLng
     *
     * @method unproject
     * @param {Object} bpoint baidu point coordinate
     * @return {Object} latitude and longitude
     */
    unproject: function (bpoint) {
        var projection= new BMap.MercatorProjection();
        var point = projection.pointToLngLat(
            new BMap.Pixel(bpoint.x, bpoint.y)
        );
        latLng = new L.LatLng(point.lng, point.lat);
        return latLng;
    },

    /**
     * Don't know how it used currently.
     *
     * However, I guess this is the range of coordinate.
     * Range of pixel coordinate is gotten from
     * BMap.MercatorProjection.lngLatToPoint(180, -90) and (180, 90)
     * After getting max min value of pixel coordinate, use
     * pointToLngLat() get the max lat and Lng.
     */
    bounds: (function () {
        var MAX_X= 20037726.37;
        var MIN_Y= -11708041.66;
        var MAX_Y= 12474104.17;
        var bounds = L.bounds(
            [-MAX_X, MIN_Y], //180, -71.988531
            [MAX_X, MAX_Y]  //-180, 74.000022
        );
        return bounds;
    })()
};

/**
 * Transformation class for Baidu Transformation.
 * Basically, it contains the conversion of point coordinate and
 * pixel coordinate.
 *
 * @class BTransformation
 */
L.BTransformation = function () {
};

L.BTransformation.prototype = {
    MAXZOOM: 18,
    /**
     * Don't know how it used currently.
     */
    transform: function (point, zoom) {
        return this._transform(point.clone(), zoom);
    },

    /**
     * transform point coordinate to pixel coordinate
     *
     * @method _transform
     * @param {Object} point point coordinate
     * @param {Number} zoom zoom level of the map
     * @return {Object} point, pixel coordinate
     */
    _transform: function (point, zoom) {
        point.x = point.x >> (this.MAXZOOM - zoom);
        point.y = point.y >> (this.MAXZOOM - zoom);
        return point;
    },

    /**
     * transform pixel coordinate to point coordinate
     *
     * @method untransform
     * @param {Object} point pixel coordinate
     * @param {Number} zoom zoom level of the map
     * @return {Object} point, point coordinate
     */
    untransform: function (point, zoom) {
        point.x = point.x << (this.MAXZOOM - zoom);
        point.y = point.y << (this.MAXZOOM - zoom);
        return point;
    }
};

/**
 * Coordinate system for Baidu EPSG3857
 *
 * @class BEPSG3857
 */
L.CRS.BEPSG3857 = L.extend({}, L.CRS, {
    /**
     * transform latLng to pixel coordinate
     *
     * @method untransform
     * @param {Object} latlng latitude and longitude
     * @param {Number} zoom zoom level of the map
     * @return {Object} pixel coordinate calculated for latLng
     */
    latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point
		var projectedPoint = this.projection.project(latlng);
		return this.transformation._transform(projectedPoint, zoom);
	},

    /**
     * transform pixel coordinate to latLng
     *
     * @method untransform
     * @param {Object} point pixel coordinate
     * @param {Number} zoom zoom level of the map
     * @return {Object} latitude and longitude
     */
    pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng
		var untransformedPoint = this.transformation.untransform(point, zoom);
		return this.projection.unproject(untransformedPoint);
	},

    code: 'EPSG:3857',
    projection: L.Projection.BaiduSphericalMercator,

    transformation: new L.BTransformation()
});

/**
 * Tile layer for Baidu Map
 *
 * @class Baidu
 */
L.Baidu = L.TileLayer.extend({
    options: {
        subdomains: ['online1', 'online2', 'online3'],
        //TODO: decode utf8 characters in attribution
        attribution: '© 2014 Baidu - GS(2012)6003;- Data © NavInfo & CenNavi & DaoDaoTong',
    },

    /**
     * initialize the map with key and tile URL
     *
     * @method initialize
     * @param {String} key access key of baidu map
     * @param {Object} options, option of the map
     */
    initialize: function (key, options) {
        L.Util.setOptions(this, options);
        this._key = key;
        this._url = 'http://{subdomain}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=20140711';
    },

    /**
     * Set the corresponding position of tiles in baidu map.
     * if point.y is less or equal than 256, i.e. 35=>291, -221=>547
     * if point.y is greater than 256, i.e. 291=>35, 547=>-221
     *
     * @method _getTilePos
     * @param {Object} tilePoint tile coordinate
     * @return {Object} point left and top property of
     */
    _getTilePos: function (tilePoint) {
        var origin = this._map.getPixelOrigin();
        var tileSize = this._getTileSize();

        var point = tilePoint.multiplyBy(tileSize).subtract(origin);
        if (point.y <= 256) {
            point.y = (
                2 * Math.abs(
                    Math.floor(point.y / tileSize)
                ) + 1
            ) * tileSize + point.y;
        } else {
            point.y = point.y - (
                Math.floor(point.y / tileSize) * 2 - 1
            ) * tileSize;
        }
        return point;
    },

    /**
     * get a tile url of the map
     *
     * @method getTileUrl
     * @param {Object} coords, tile coordinate
     * @return {String} url of a tile
     */
    getTileUrl: function(coords) {
        return this._url.replace('{subdomain}', this._getSubdomain(coords))
            .replace('{x}', coords.x)
            .replace('{y}', coords.y)
            .replace('{z}', this._getZoomForUrl());
    }
});

L.map = function (id, options) {
    var map = new L.Map(id, options);

    /**
     * Override _getTopLeftPoint method. For Baidu Map, if dragging
     * down side of the map, y will increase rather than decrease.
     * vice versa.
     *
     * @method _getTopLeftPoint
     * @return {Object} point top left point
     */
    var _getTopLeftPointBaidu = function () {
        var pixel = this.getPixelOrigin();
        var pane = this._getMapPanePos();
        var point = new L.Point(pixel.x - pane.x, pixel.y + pane.y);
        return point;
    };

    /**
     * These 2 methods is for calculating the correct latitude.
     * The origin leaflet doesn't suit for Baidu Map.
     * For now, the more northen I click, the larger latitude.
     * TODO: should create a method called baiduAdd/Substract
     * to use point add and substract operators
     */
    var containerPointToLayerPointBaidu = function(point) {
        var pane = this._getMapPanePos();
        return L.point(point.x - pane.x, point.y + pane.y);
    };

    var layerPointToContainerPointBaidu = function(point) {
        var pane = this._getMapPanePos();
        return L.point(point.x + pane.x, point.y - pane.y);
    };

    //if option has baidu, use custom method
    if (options.baidu === true) {
        map._getTopLeftPoint = _getTopLeftPointBaidu;
        map.containerPointToLayerPoint = containerPointToLayerPointBaidu;
        map.layerPointToContainerPoint = layerPointToContainerPointBaidu;
    }
    return map;
};

L.baiduLayer = function (key, options) {
    return new L.Baidu(key, options);
};
<|endoftext|>


<commit_before>
module.exports = {
  'extends': 'eslint:recommended',
  'rules': {
    'camelcase': 2,
    'comma-spacing': 2,
    'consistent-return': 2,
    'curly': [2, 'all'],
    'dot-notation': [2, { 'allowKeywords': true }],
    'eol-last': 2,
    'eqeqeq': 2,
    'indent': [ 1, 2, {'SwitchCase': 1}],
    'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }],
    'linebreak-style': [ 2, 'unix'],
    'new-cap': 2,
    'new-parens': 2,
    'no-alert': 2,
    'no-array-constructor': 2,
    'no-caller': 2,
    'no-catch-shadow': 2,
    'no-eval': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-extra-parens': [2, 'functions'],
    'no-implied-eval': 2,
    'no-iterator': 2,
    'no-label-var': 2,
    'no-labels': 2,
    'no-lone-blocks': 2,
    'no-loop-func': 2,
    'no-multi-spaces': 2,
    'no-multi-str': 2,
    'no-native-reassign': 2,
    'no-new': 2,
    'no-new-func': 2,
    'no-new-object': 2,
    'no-new-wrappers': 2,
    'no-octal-escape': 2,
    'no-process-exit': 2,
    'no-proto': 2,
    'no-return-assign': 2,
    'no-script-url': 2,
    'no-sequences': 2,
    'no-shadow': 2,
    'no-shadow-restricted-names': 2,
    'no-spaced-func': 2,
    'no-trailing-spaces': 2,
    'no-undef-init': 2,
    'no-underscore-dangle': 2,
    'no-unused-expressions': 2,
    'no-unused-vars': [ 2, {'args': 'after-used', 'varsIgnorePattern': '^React$'}],
    'no-use-before-define': 2,
    'no-with': 2,
    'quotes': [ 1, 'single'],
    'semi': [ 2, 'always'],
    'semi-spacing': [2, {'before': false, 'after': true}],
    'space-infix-ops': 2,
    'space-unary-ops': [2, { 'words': true, 'nonwords': false }],
    'strict': [2, 'function'],
    'yoda': [2, 'never'],
    'react/jsx-no-duplicate-props': 2,
    'react/jsx-no-undef': 2,
    'react/jsx-uses-react': 2,
    'react/jsx-uses-vars': 2,
    'react/no-danger': 2,
    'react/no-deprecated': 2,
    'react/no-did-mount-set-state': [2, 'allow-in-func'],
    'react/no-did-update-set-state': [2, 'allow-in-func'],
    'react/no-direct-mutation-state': 2,
    'react/no-is-mounted': 2,
    'react/no-unknown-property': 2,
    'react/prop-types': 2,
    'react/react-in-jsx-scope': 2
  },
  'env': {
    'es6': true,
    'node': true,
    'browser': true
  },
  'plugins': ['react'],
  'parser': 'babel-eslint',
  'parserOptions': {
    'ecmaFeatures': {
      'jsx': true
    }
  }
};
<commit_msg>Added space after keyword rule<commit_after>
module.exports = {
  'extends': 'eslint:recommended',
  'rules': {
    'camelcase': 2,
    'comma-spacing': 2,
    'consistent-return': 2,
    'curly': [2, 'all'],
    'dot-notation': [2, { 'allowKeywords': true }],
    'eol-last': 2,
    'eqeqeq': 2,
    'indent': [ 1, 2, {'SwitchCase': 1}],
    'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }],
    'linebreak-style': [ 2, 'unix'],
    'new-cap': 2,
    'new-parens': 2,
    'no-alert': 2,
    'no-array-constructor': 2,
    'no-caller': 2,
    'no-catch-shadow': 2,
    'no-eval': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-extra-parens': [2, 'functions'],
    'no-implied-eval': 2,
    'no-iterator': 2,
    'no-label-var': 2,
    'no-labels': 2,
    'no-lone-blocks': 2,
    'no-loop-func': 2,
    'no-multi-spaces': 2,
    'no-multi-str': 2,
    'no-native-reassign': 2,
    'no-new': 2,
    'no-new-func': 2,
    'no-new-object': 2,
    'no-new-wrappers': 2,
    'no-octal-escape': 2,
    'no-process-exit': 2,
    'no-proto': 2,
    'no-return-assign': 2,
    'no-script-url': 2,
    'no-sequences': 2,
    'no-shadow': 2,
    'no-shadow-restricted-names': 2,
    'no-spaced-func': 2,
    'no-trailing-spaces': 2,
    'no-undef-init': 2,
    'no-underscore-dangle': 2,
    'no-unused-expressions': 2,
    'no-unused-vars': [ 2, {'args': 'after-used', 'varsIgnorePattern': '^React$'}],
    'no-use-before-define': 2,
    'no-with': 2,
    'quotes': [ 1, 'single'],
    'semi': [ 2, 'always'],
    'semi-spacing': [2, {'before': false, 'after': true}],
    'space-after-keyword': 2,
    'space-infix-ops': 2,
    'space-unary-ops': [2, { 'words': true, 'nonwords': false }],
    'strict': [2, 'function'],
    'yoda': [2, 'never'],
    'react/jsx-no-duplicate-props': 2,
    'react/jsx-no-undef': 2,
    'react/jsx-uses-react': 2,
    'react/jsx-uses-vars': 2,
    'react/no-danger': 2,
    'react/no-deprecated': 2,
    'react/no-did-mount-set-state': [2, 'allow-in-func'],
    'react/no-did-update-set-state': [2, 'allow-in-func'],
    'react/no-direct-mutation-state': 2,
    'react/no-is-mounted': 2,
    'react/no-unknown-property': 2,
    'react/prop-types': 2,
    'react/react-in-jsx-scope': 2
  },
  'env': {
    'es6': true,
    'node': true,
    'browser': true
  },
  'plugins': ['react'],
  'parser': 'babel-eslint',
  'parserOptions': {
    'ecmaFeatures': {
      'jsx': true
    }
  }
};
<|endoftext|>


<commit_before>define(['jquery'], function ($) {
    var displayDiv = null;

    function createDisplayDiv() {
        $('#maintoolbar-container').append(
            $('<div>').attr('id', 'nbresuse-display')
                      .addClass('btn-group')
                      .addClass('pull-right')
            .append(
                $('<strong>').text('Mem: ')
            ).append(
                $('<span>').attr('id', 'nbresuse-mem')
                           .attr('title', 'Actively used Memory (updates every 5s)')
            )
        );
    }

    var displayMetrics = function() {
        $.getJSON('/metrics', function(data) {
            // FIXME: Proper setups for MB and GB. MB should have 0 things
            // after the ., but GB should have 2.
            var displayRSS = (data['rss'] / (1024 * 1024)).toFixed(0);
            $('#nbresuse-mem').text(displayRSS + " MB");
        });
    }

    var load_ipython_extension = function () {
        createDisplayDiv();
        displayMetrics();
        // Update every five seconds, eh?
        setInterval(displayMetrics, 1000 * 5);
    };

    return {
        load_ipython_extension: load_ipython_extension,
    };
});
<commit_msg>Use base_url to form metrics url<commit_after>define(['jquery', 'base/js/utils'], function ($, utils) {
    function createDisplayDiv() {
        $('#maintoolbar-container').append(
            $('<div>').attr('id', 'nbresuse-display')
                      .addClass('btn-group')
                      .addClass('pull-right')
            .append(
                $('<strong>').text('Mem: ')
            ).append(
                $('<span>').attr('id', 'nbresuse-mem')
                           .attr('title', 'Actively used Memory (updates every 5s)')
            )
        );
    }

    var displayMetrics = function() {
        $.getJSON(utils.get_body_data('baseUrl') + 'metrics', function(data) {
            // FIXME: Proper setups for MB and GB. MB should have 0 things
            // after the ., but GB should have 2.
            var displayRSS = (data['rss'] / (1024 * 1024)).toFixed(0);
            $('#nbresuse-mem').text(displayRSS + " MB");
        });
    }

    var load_ipython_extension = function () {
        createDisplayDiv();
        displayMetrics();
        // Update every five seconds, eh?
        setInterval(displayMetrics, 1000 * 5);
    };

    return {
        load_ipython_extension: load_ipython_extension,
    };
});
<|endoftext|>


<commit_before>//
// OpenRASP 官方插件只是抛砖引玉，具体检测能力请根据业务来定制
//

'use strict'
var plugin = new RASP('offical')

var clean = {
    action: 'ignore',
    message: '无风险',
    confidence: 0
}

var forcefulBrowsing = {
    dotFiles:    /\.(7z|tar|gz|bz2|xz|rar|zip|sql|db)$/,
    unwantedFilenames: [
        // user files
        '.DS_Store',
        'id_rsa', 'id_rsa.pub', 'known_hosts', 'authorized_keys',
        '.bash_history', '.csh_history', '.zsh_history', '.mysql_history',

        // project files
        '.htaccess', '.user.ini',

        'web.config', 'web.xml', 'build.property.xml', 'bower.json',
        'Gemfile', 'Gemfile.lock',
        '.gitignore',
        'error_log', 'error.log', 'nohup.out',
    ],
    unwantedDirectory: [
        '/',
        '/home',
        '/var/log',
        '/proc',
        '/sys'
    ],
    absolutePaths: [
        '/etc/shadow',
        '/etc/hosts',
        '/etc/apache2/apache2.conf',
        '/root/.bash_history',
        '/root/.bash_profile',
    ]
}

var scriptFileRegex = /\.(jspx?|php[345]?|phtml)\.?$/i
var ntfsRegex       = /::\$(DATA|INDEX)$/i // 其他的stream都没啥用

String.prototype.replaceAll = function(token, tokenValue) {
    var index  = 0;
    var string = this;

    do {
        string = string.replace(token, tokenValue);
    } while((index = string.indexOf(token, index + 1)) > -1);

    return string
}

function canonicalPath (path) {
    return path.replaceAll('/./', '/').replaceAll('//', '/').replaceAll('//', '/')
}

function basename (path) {
    var idx = path.lastIndexOf('/')
    return path.substr(idx + 1)
}

// 主要用于识别webshell里的文件管理器
// 通常程序不会主动列目录或者查看敏感目录，e.g /home /etc /var/log 等等
//
// 若有特例可调整
// 可结合业务定制: e.g 不能超出应用根目录
plugin.register('directory', function (params, context) {
    var realpath = params.realpath

    for (var i = 0; i < forcefulBrowsing.unwantedDirectory.length; i ++) {
        if (realpath == forcefulBrowsing.unwantedDirectory[i]) {
            return {
                action:     'block',
                message:    '疑似WebShell文件管理器 - 读取敏感根目录',
                confidence: 100
            }
        }
    }

    return clean
})

plugin.register('readFile', function (params, context) {

    // 算法1: 检查是否为成功的目录扫描
    var filename_1 = basename(context.url)
    var filename_2 = basename(params.realpath)

    if (filename_1 == filename_2) {
        var matched = false

        // 尝试下载压缩包、SQL文件等等
        if (forcefulBrowsing.dotFiles.test(filename_1)) {
            matched = true
        } else {
            // 尝试访问敏感文件
            for (var i = 0; i < forcefulBrowsing.unwantedFilenames; i ++) {
                if (forcefulBrowsing.unwantedFilenames[i] == filename_1) {
                    matched = true
                }
            }
        }

        if (matched) {
            return {
                action:     'block',
                message:    '尝试下载敏感文件(' + context.method.toUpperCase() + ' 方式): ' + params.realpath,

                // 如果是HEAD方式下载敏感文件，100% 扫描器攻击
                confidence: context.method == 'head' ? 100 : 90
            }
        }
    }

    // 算法2: 如果使用绝对路径访问敏感文件，判定为 webshell
    if (params.realpath == params.path) {
        for (var j = 0; j < forcefulBrowsing.absolutePaths.length; j ++) {
            if (forcefulBrowsing.absolutePaths[j] == params.realpath) {
                return {
                    action:     'block',
                    message:    'WebShell/文件管理器 - 尝试读取系统文件: ' + params.realpath,
                    confidence: 90
                }
            }
        }
    }

    // 算法3: 检查文件遍历，看是否超出web目录范围
    var path        = canonicalPath(params.path)
    var appBasePath = context.appBasePath

    if (params.realpath.indexOf(appBasePath) == -1 && (path.indexOf('/../') !== -1 || path.indexOf('\\..\\') !== -1)) {
        return {
            action:     'block',
            message:    '目录遍历攻击，跳出web目录范围 (' + appBasePath + ')',
            confidence: 90
        }
    }

    return clean
})

plugin.register('webdav', function (params, context) {

    // 源文件不是脚本 && 目标文件是脚本，判定为MOVE方式写后门
    if (! scriptFileRegex.test(params.source) && scriptFileRegex.test(params.dest)) {
        return {
            action:    'block',
            message:   '尝试通过 ' + context.method + ' 方式上传脚本文件: ' + params.dest,
            confidence: 100
        }
    }

    return clean
})

plugin.register('include', function (params, context) {
    var items = params.url.split('://')

    // 必须有协议的情况下才能利用漏洞
    if (items.length != 2) {
        return clean
    }

    // http 方式 SSRF
    if (items[0].toLowerCase() == 'http') {
        return {
            action:     'block',
            message:    'SSRF漏洞: ' + params.function + ' 方式',
            confidence: 70
        }
    }

    // file 协议
    if (items[0].toLowerCase() == 'file') {
        var basename = items[1].split('/').pop()

        if (items[1].endsWith('/')) {
            return {
                action:     'block',
                message:    '敏感目录访问: ' + params.function + ' 方式',
                confidence: 100
            }
        }

        for (var i = 0; i < forcefulBrowsing.unwantedFilenames.length; i ++) {
            if (basename == forcefulBrowsing.unwantedFilenames[i]) {
                return {
                    action:     'block',
                    message:    '敏感文件下载: ' + params.function + ' 方式',
                    confidence: 100
                }
            }
        }
    }

    return clean
})

plugin.register('writeFile', function (params, context) {
    if (ntfsRegex.test(params.realpath)) {
        return {
            action:     'block',
            message:    '尝试利用NTFS流上传后门: ' + params.realpath,
            confidence: 90
        }
    }

    if (scriptFileRegex.test(params.realpath)) {
        return {
            action:     'log',
            message:    '尝试写入脚本文件: ' + params.realpath,
            confidence: 90
        }
    }
    return clean
})

plugin.register('fileUpload', function (params, context) {
    if (scriptFileRegex.test(params.filename) || ntfsRegex.test(params.filename)) {
        return {
            action:     'block',
            message:    '尝试上传脚本文件: ' + params.filename,
            confidence: 90
        }
    }
    return clean
})

plugin.register('sql', function (params, context) {
    var reason     = false
    var parameters = context.parameter
    var tokens     = RASP.sql_tokenize(params.query, params.server)

    // 算法1: 匹配用户输入
    // 1. 简单识别逻辑是否发生改变
    // 2. 识别数据库管理器
    Object.keys(parameters).some(function (name) {
        var value = parameters[name][0]

        if (value.length <= 10) {
            return
        }

        // 判断是否为数据库管理器
        if (value.length == params.query.length && value == params.query) {
            reason = '算法2: WebShell - 数据库管理器'
            return true
        }

        // 简单识别用户输入
        if (params.query.indexOf(value) == -1) {
            return
        }

        // 去掉用户输入再次匹配
        var tokens2 = RASP.sql_tokenize(params.query.replace(value, ''), params.server)
        if (tokens.length - tokens2.length > 2) {
            reason = '算法1: 数据库查询逻辑发生改变'
            return true
        }
    })
    if (reason !== false) {
        return {
            'action':     'block',
            'confidence': 90,
            'message':    reason
        }
    }

    // 算法2: SQL语句策略检查（模拟SQL防火墙功能）
    var func_list = {
        'load_file': true,
        'benchmark': true,
        'sleep':     true,
        'pg_sleep':  true
    }
    var tokens_lc = tokens.map(v => v.toLowerCase())

    for (var i = 0; i < tokens_lc.length; i ++) {
        if (tokens_lc[i] == ';') {
            reason = '禁止多语句查询'
            break
        } else if (tokens_lc[i].indexOf('0x') == 0) {
            reason = '禁止16进制字符串'
            break
        } else if (tokens_lc[i].indexOf('/*!') == 0) {
            reason = '禁止MySQL版本号注释'
            break
        } else if (i < tokens_lc.length - 3 && (tokens_lc[i] == 'and' || tokens_lc[i] == 'or' || tokens_lc[i] == 'xor')) {
            // @FIXME: 可绕过，暂时不更新
            // 简单识别 (and|xor|or) NUMBER (>|<|>=|<=|xor) NUMBER
            //               i       i+1         i+2        i+3

            var op1    = tokens_lc[i + 1]
            var op2    = tokens_lc[i + 3]
            var method = tokens_lc[i + 2]

            if (! isNaN(op1) && ! isNaN(op2) && (method[0] == '<' || method[0] == '>' || method[0] == '=')) {
                reason = '禁止常量比较操作'
                break
            }
        } else if (i > 0 && tokens_lc[i].indexOf('(') == 0) {
            // @FIXME: 可绕过，暂时不更新
            if (func_list[tokens_lc[i - 1]]) {
                reason = '禁止执行敏感函数: ' + reason
                break
            }
        }
    }

    if (reason !== false) {
        return {
            action:     'block',
            message:    '数据库语句异常: ' + reason + '（算法3）',
            confidence: 100
        }
    }

    // 算法3: 简单正则匹配（即将移除）
    var sqlRegex = /\bupdatexml\s*\(|\bextractvalue\s*\(|\bunion.*select.*(from|into|benchmark).*\b/i

    if (sqlRegex.test(params.query)) {
        return {
            action:     'block',
            message:    'SQL 注入攻击（算法4）',
            confidence: 100
        }
    }
    return clean
})

plugin.register('command', function (params, context) {
    // 默认禁止命令执行
    return {
        action:    'block',
        message:   '尝试执行命令',
        confidence: 90
    }
})

plugin.register('xxe', function (params, context) {
    var items = params.entity.split('://')

    if (items.length >= 2) {
        var protocol = items[0]

        if (protocol === 'gopher' || protocol === 'dict' || protocol === 'expect') {
            return {
                action:     'block',
                message:    'SSRF 攻击 (' + protocol + ' 协议)',
                confidence: 100
            }
        }

        if (protocol === 'file') {
            return {
                action:     'log',
                message:    '尝试读取外部实体 (file 协议)',
                confidence: 90
            }
        }
    }
    return clean
})

plugin.register('ognl', function (params, context) {
    // 常见 struts payload 语句特征
    var ognlPayloads = [
        'ognl.OgnlContext',
        'ognl.TypeConverter',
        'ognl.MemberAccess',
        '_memberAccess',
        'ognl.ClassResolver',
        'java.lang.Runtime',
        'java.lang.Class',
        'java.lang.ClassLoader',
        'java.lang.System',
        'java.lang.ProcessBuilder',
        'java.lang.Object',
        'java.lang.Shutdown',
        'java.io.File',
        'javax.script.ScriptEngineManager',
        'com.opensymphony.xwork2.ActionContext'
    ]

    var ognlExpression = params.expression
    for (var index in ognlPayloads) {
        if (ognlExpression.indexOf(ognlPayloads[index]) > -1) {
            return {
                action:     'block',
                message:    '尝试ognl远程命令执行',
                confidence: 100
            }
        }

    }
    return clean
})

// [[ 近期调整~ ]]
plugin.register('deserialization', function (params, context) {
    var deserializationInvalidClazz = [
        'org.apache.commons.collections.functors.InvokerTransformer',
        'org.apache.commons.collections.functors.InstantiateTransformer',
        'org.apache.commons.collections4.functors.InvokerTransformer',
        'org.apache.commons.collections4.functors.InstantiateTransformer',
        'org.codehaus.groovy.runtime.ConvertedClosure',
        'org.codehaus.groovy.runtime.MethodClosure',
        'org.springframework.beans.factory.ObjectFactory',
        'xalan.internal.xsltc.trax.TemplatesImpl'
    ]

    var clazz = params.clazz
    for (var index in deserializationInvalidClazz) {
        if (clazz === deserializationInvalidClazz[index]) {
            return {
                action:     'block',
                message:    '尝试反序列化攻击',
                confidence: 100
            }
        }
    }
    return clean
})

plugin.register('reflection', function(params, context) {
    var title = '异常的执行流'
    var known = {
        'com.thoughtworks.xstream.XStream.unmarshal': 'xstream 反序列化攻击',
        'org.apache.commons.collections4.functors.InvokerTransformer.transform': 'transformer 反序列化攻击'
    }

    // 是否为已知类型的反序列化攻击？
    params.stack.some(function (method) {
        if (known[method]) {
            title = known[method]
            return true;
        }
    });

    return {
        action:     'block',
        message:    title + ': ' + params.clazz + '.' + params.method,
        confidence: 100
    }
})

plugin.log('初始化成功')
<commit_msg>Let us release that way<commit_after>//
// OpenRASP 官方插件只是抛砖引玉，具体检测能力请根据业务来定制
//

'use strict'
var plugin = new RASP('offical')

var clean = {
    action: 'ignore',
    message: '无风险',
    confidence: 0
}

var forcefulBrowsing = {
    dotFiles:    /\.(7z|tar|gz|bz2|xz|rar|zip|sql|db)$/,
    unwantedFilenames: [
        // user files
        '.DS_Store',
        'id_rsa', 'id_rsa.pub', 'known_hosts', 'authorized_keys',
        '.bash_history', '.csh_history', '.zsh_history', '.mysql_history',

        // project files
        '.htaccess', '.user.ini',

        'web.config', 'web.xml', 'build.property.xml', 'bower.json',
        'Gemfile', 'Gemfile.lock',
        '.gitignore',
        'error_log', 'error.log', 'nohup.out',
    ],
    unwantedDirectory: [
        '/',
        '/home',
        '/var/log',
        '/proc',
        '/sys'
    ],
    absolutePaths: [
        '/etc/shadow',
        '/etc/hosts',
        '/etc/apache2/apache2.conf',
        '/root/.bash_history',
        '/root/.bash_profile',
    ]
}

var scriptFileRegex = /\.(jspx?|php[345]?|phtml)\.?$/i
var ntfsRegex       = /::\$(DATA|INDEX)$/i // 其他的stream都没啥用

String.prototype.replaceAll = function(token, tokenValue) {
    var index  = 0;
    var string = this;

    do {
        string = string.replace(token, tokenValue);
    } while((index = string.indexOf(token, index + 1)) > -1);

    return string
}

function canonicalPath (path) {
    return path.replaceAll('/./', '/').replaceAll('//', '/').replaceAll('//', '/')
}

function basename (path) {
    var idx = path.lastIndexOf('/')
    return path.substr(idx + 1)
}

// 主要用于识别webshell里的文件管理器
// 通常程序不会主动列目录或者查看敏感目录，e.g /home /etc /var/log 等等
//
// 若有特例可调整
// 可结合业务定制: e.g 不能超出应用根目录
plugin.register('directory', function (params, context) {
    var realpath = params.realpath

    for (var i = 0; i < forcefulBrowsing.unwantedDirectory.length; i ++) {
        if (realpath == forcefulBrowsing.unwantedDirectory[i]) {
            return {
                action:     'block',
                message:    '疑似WebShell文件管理器 - 读取敏感根目录',
                confidence: 100
            }
        }
    }

    return clean
})

plugin.register('readFile', function (params, context) {

    // 算法1: 检查是否为成功的目录扫描
    var filename_1 = basename(context.url)
    var filename_2 = basename(params.realpath)

    if (filename_1 == filename_2) {
        var matched = false

        // 尝试下载压缩包、SQL文件等等
        if (forcefulBrowsing.dotFiles.test(filename_1)) {
            matched = true
        } else {
            // 尝试访问敏感文件
            for (var i = 0; i < forcefulBrowsing.unwantedFilenames; i ++) {
                if (forcefulBrowsing.unwantedFilenames[i] == filename_1) {
                    matched = true
                }
            }
        }

        if (matched) {
            return {
                action:     'block',
                message:    '尝试下载敏感文件(' + context.method.toUpperCase() + ' 方式): ' + params.realpath,

                // 如果是HEAD方式下载敏感文件，100% 扫描器攻击
                confidence: context.method == 'head' ? 100 : 90
            }
        }
    }

    // 算法2: 如果使用绝对路径访问敏感文件，判定为 webshell
    if (params.realpath == params.path) {
        for (var j = 0; j < forcefulBrowsing.absolutePaths.length; j ++) {
            if (forcefulBrowsing.absolutePaths[j] == params.realpath) {
                return {
                    action:     'block',
                    message:    'WebShell/文件管理器 - 尝试读取系统文件: ' + params.realpath,
                    confidence: 90
                }
            }
        }
    }

    // 算法3: 检查文件遍历，看是否超出web目录范围
    var path        = canonicalPath(params.path)
    var appBasePath = context.appBasePath

    if (params.realpath.indexOf(appBasePath) == -1 && (path.indexOf('/../') !== -1 || path.indexOf('\\..\\') !== -1)) {
        return {
            action:     'block',
            message:    '目录遍历攻击，跳出web目录范围 (' + appBasePath + ')',
            confidence: 90
        }
    }

    return clean
})

plugin.register('webdav', function (params, context) {

    // 源文件不是脚本 && 目标文件是脚本，判定为MOVE方式写后门
    if (! scriptFileRegex.test(params.source) && scriptFileRegex.test(params.dest)) {
        return {
            action:    'block',
            message:   '尝试通过 ' + context.method + ' 方式上传脚本文件: ' + params.dest,
            confidence: 100
        }
    }

    return clean
})

plugin.register('include', function (params, context) {
    var items = params.url.split('://')

    // 必须有协议的情况下才能利用漏洞
    if (items.length != 2) {
        return clean
    }

    // http 方式 SSRF
    if (items[0].toLowerCase() == 'http') {
        return {
            action:     'block',
            message:    'SSRF漏洞: ' + params.function + ' 方式',
            confidence: 70
        }
    }

    // file 协议
    if (items[0].toLowerCase() == 'file') {
        var basename = items[1].split('/').pop()

        if (items[1].endsWith('/')) {
            return {
                action:     'block',
                message:    '敏感目录访问: ' + params.function + ' 方式',
                confidence: 100
            }
        }

        for (var i = 0; i < forcefulBrowsing.unwantedFilenames.length; i ++) {
            if (basename == forcefulBrowsing.unwantedFilenames[i]) {
                return {
                    action:     'block',
                    message:    '敏感文件下载: ' + params.function + ' 方式',
                    confidence: 100
                }
            }
        }
    }

    return clean
})

plugin.register('writeFile', function (params, context) {
    if (ntfsRegex.test(params.realpath)) {
        return {
            action:     'block',
            message:    '尝试利用NTFS流上传后门: ' + params.realpath,
            confidence: 90
        }
    }

    if (scriptFileRegex.test(params.realpath)) {
        return {
            action:     'log',
            message:    '尝试写入脚本文件: ' + params.realpath,
            confidence: 90
        }
    }
    return clean
})

plugin.register('fileUpload', function (params, context) {
    if (scriptFileRegex.test(params.filename) || ntfsRegex.test(params.filename)) {
        return {
            action:     'block',
            message:    '尝试上传脚本文件: ' + params.filename,
            confidence: 90
        }
    }
    return clean
})

plugin.register('sql', function (params, context) {
    var reason     = false
    var parameters = context.parameter
    var tokens     = RASP.sql_tokenize(params.query, params.server)

    // 算法1: 匹配用户输入
    // 1. 简单识别逻辑是否发生改变
    // 2. 识别数据库管理器
    Object.keys(parameters).some(function (name) {
        var value = parameters[name][0]

        if (value.length <= 10) {
            return
        }

        // 判断是否为数据库管理器
        if (value.length == params.query.length && value == params.query) {
            reason = '算法2: WebShell - 数据库管理器'
            return true
        }

        // 简单识别用户输入
        if (params.query.indexOf(value) == -1) {
            return
        }

        // 去掉用户输入再次匹配
        var tokens2 = RASP.sql_tokenize(params.query.replace(value, ''), params.server)
        if (tokens.length - tokens2.length > 2) {
            reason = '算法1: 数据库查询逻辑发生改变'
            return true
        }
    })
    if (reason !== false) {
        return {
            'action':     'block',
            'confidence': 90,
            'message':    reason
        }
    }

    // 算法2: SQL语句策略检查（模拟SQL防火墙功能）
    var func_list = {
        'load_file': true,
        'benchmark': true,
        'sleep':     true,
        'pg_sleep':  true
    }
    var tokens_lc = tokens.map(v => v.toLowerCase())

    for (var i = 0; i < tokens_lc.length; i ++) {
        if (tokens_lc[i] == ';') {
            reason = '禁止多语句查询'
            break
        } else if (tokens_lc[i].indexOf('0x') == 0) {
            reason = '禁止16进制字符串'
            break
        } else if (tokens_lc[i].indexOf('/*!') == 0) {
            reason = '禁止MySQL版本号注释'
            break
        } else if (i < tokens_lc.length - 3 && (tokens_lc[i] == 'and' || tokens_lc[i] == 'or' || tokens_lc[i] == 'xor')) {
            // @FIXME: 可绕过，暂时不更新
            // 简单识别 (and|xor|or) NUMBER (>|<|>=|<=|xor) NUMBER
            //               i       i+1         i+2        i+3

            var op1    = tokens_lc[i + 1]
            var op2    = tokens_lc[i + 3]
            var method = tokens_lc[i + 2]

            if (! isNaN(op1) && ! isNaN(op2) && (method[0] == '<' || method[0] == '>' || method[0] == '=')) {
                reason = '禁止常量比较操作'
                break
            }
        } else if (i > 0 && tokens_lc[i].indexOf('(') == 0) {
            // @FIXME: 可绕过，暂时不更新
            if (func_list[tokens_lc[i - 1]]) {
                reason = '禁止执行敏感函数: ' + tokens_lc[i - 1]
                break
            }
        }
    }

    if (reason !== false) {
        return {
            action:     'block',
            message:    '数据库语句异常: ' + reason + '（算法3）',
            confidence: 100
        }
    }

    // 算法3: 简单正则匹配（即将移除）
    var sqlRegex = /\bupdatexml\s*\(|\bextractvalue\s*\(|\bunion.*select.*(from|into|benchmark).*\b/i

    if (sqlRegex.test(params.query)) {
        return {
            action:     'block',
            message:    'SQL 注入攻击（算法4）',
            confidence: 100
        }
    }
    return clean
})

plugin.register('command', function (params, context) {
    // 默认禁止命令执行
    return {
        action:    'block',
        message:   '尝试执行命令',
        confidence: 90
    }
})

plugin.register('xxe', function (params, context) {
    var items = params.entity.split('://')

    if (items.length >= 2) {
        var protocol = items[0]

        if (protocol === 'gopher' || protocol === 'dict' || protocol === 'expect') {
            return {
                action:     'block',
                message:    'SSRF 攻击 (' + protocol + ' 协议)',
                confidence: 100
            }
        }

        if (protocol === 'file') {
            return {
                action:     'log',
                message:    '尝试读取外部实体 (file 协议)',
                confidence: 90
            }
        }
    }
    return clean
})

plugin.register('ognl', function (params, context) {
    // 常见 struts payload 语句特征
    var ognlPayloads = [
        'ognl.OgnlContext',
        'ognl.TypeConverter',
        'ognl.MemberAccess',
        '_memberAccess',
        'ognl.ClassResolver',
        'java.lang.Runtime',
        'java.lang.Class',
        'java.lang.ClassLoader',
        'java.lang.System',
        'java.lang.ProcessBuilder',
        'java.lang.Object',
        'java.lang.Shutdown',
        'java.io.File',
        'javax.script.ScriptEngineManager',
        'com.opensymphony.xwork2.ActionContext'
    ]

    var ognlExpression = params.expression
    for (var index in ognlPayloads) {
        if (ognlExpression.indexOf(ognlPayloads[index]) > -1) {
            return {
                action:     'block',
                message:    '尝试ognl远程命令执行',
                confidence: 100
            }
        }

    }
    return clean
})

// [[ 近期调整~ ]]
plugin.register('deserialization', function (params, context) {
    var deserializationInvalidClazz = [
        'org.apache.commons.collections.functors.InvokerTransformer',
        'org.apache.commons.collections.functors.InstantiateTransformer',
        'org.apache.commons.collections4.functors.InvokerTransformer',
        'org.apache.commons.collections4.functors.InstantiateTransformer',
        'org.codehaus.groovy.runtime.ConvertedClosure',
        'org.codehaus.groovy.runtime.MethodClosure',
        'org.springframework.beans.factory.ObjectFactory',
        'xalan.internal.xsltc.trax.TemplatesImpl'
    ]

    var clazz = params.clazz
    for (var index in deserializationInvalidClazz) {
        if (clazz === deserializationInvalidClazz[index]) {
            return {
                action:     'block',
                message:    '尝试反序列化攻击',
                confidence: 100
            }
        }
    }
    return clean
})

plugin.register('reflection', function(params, context) {
    var title = '异常的执行流'
    var known = {
        'com.thoughtworks.xstream.XStream.unmarshal': 'xstream 反序列化攻击',
        'org.apache.commons.collections4.functors.InvokerTransformer.transform': 'transformer 反序列化攻击'
    }

    // 是否为已知类型的反序列化攻击？
    params.stack.some(function (method) {
        if (known[method]) {
            title = known[method]
            return true;
        }
    });

    return {
        action:     'block',
        message:    title + ': ' + params.clazz + '.' + params.method,
        confidence: 100
    }
})

plugin.log('初始化成功')
<|endoftext|>


<commit_before>// This file contains some global variables and misc procedures to
// initials shaders and some buffers we need and to render.

var SLICE = 1;

// globals (for now)
var imageProgram;
var textProgram;
var polyProgram;
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
var squareOutlinePositionBuffer;
var squarePositionBuffer;
var tileVertexPositionBuffer;
var tileVertexTextureCoordBuffer;
var tileCellBuffer;

// This global is used in every class that renders something.
// I can not test multiple canvases until I modularize the canvas
// and get rid of these globals.
var GL;

// WebGL Initialization

function initGL(canvas) {
    try {
        GL = canvas.getContext("experimental-webgl");
        GL.viewportWidth = canvas.clientWidth;
        GL.viewportHeight = canvas.clientHeight;

        canvas.width =  canvas.clientWidth;
        canvas.height= canvas.clientHeight;

    } catch (e) {
    }
    if (!GL) {
        alert("Could not initialise WebGL, sorry :-(");
    }
}

function getShader(gl, id) {
    var shaderScript = document.getElementById(id);
    if (!shaderScript) {
        return null;
    }

    var str = "";
    var k = shaderScript.firstChild;
    while (k) {
        if (k.nodeType == 3) {
            str += k.textContent;
        }
        k = k.nextSibling;
    }

    var shader;
    if (shaderScript.type == "x-shader/x-fragment") {
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }

    gl.shaderSource(shader, str);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}

function initShaderPrograms() {
    polyProgram = createProgram("shader-poly-fs", "shader-poly-vs");
    polyProgram.colorUniform = GL.getUniformLocation(polyProgram, "uColor");

    imageProgram = createProgram("shader-tile-fs", "shader-tile-vs");
    // Texture coordinate attribute and texture image uniform
    imageProgram.textureCoordAttribute
        = GL.getAttribLocation(imageProgram,"aTextureCoord");
    GL.enableVertexAttribArray(imageProgram.textureCoordAttribute);
    imageProgram.samplerUniform = GL.getUniformLocation(imageProgram, "uSampler");

    textProgram = createProgram("shader-text-fs", "shader-text-vs");
    textProgram.textureCoordAttribute
        = GL.getAttribLocation(textProgram, "aTextureCoord");
    GL.enableVertexAttribArray(textProgram.textureCoordAttribute);
    textProgram.samplerUniform
        = GL.getUniformLocation(textProgram, "uSampler");
    textProgram.colorUniform = GL.getUniformLocation(textProgram, "uColor");
}

function createProgram(fragmentShaderID, vertexShaderID) {
    var fragmentShader = getShader(GL, fragmentShaderID);
    var vertexShader = getShader(GL, vertexShaderID);

    var program = GL.createProgram();
    GL.attachShader(program, vertexShader);
    GL.attachShader(program, fragmentShader);
    GL.linkProgram(program);

    if (!GL.getProgramParameter(program, GL.LINK_STATUS)) {
        alert("Could not initialise shaders");
    }

    program.vertexPositionAttribute = GL.getAttribLocation(program, "aVertexPosition");
    GL.enableVertexAttribArray(program.vertexPositionAttribute);

    // Camera matrix
    program.pMatrixUniform = GL.getUniformLocation(program, "uPMatrix");
    // Model matrix
    program.mvMatrixUniform = GL.getUniformLocation(program, "uMVMatrix");

    return program;
}

function initOutlineBuffers() {
    // Outline Square
    vertices = [
        0.0,  0.0,  0.0,
        0.0,  1.0,  0.0,
        1.0, 1.0,  0.0,
        1.0, 0.0,  0.0,
        0.0, 0.0,  0.0];
    squareOutlinePositionBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, squareOutlinePositionBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertices), GL.STATIC_DRAW);
    squareOutlinePositionBuffer.itemSize = 3;
    squareOutlinePositionBuffer.numItems = 5;

    // Filled square
    squarePositionBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, squarePositionBuffer);
    vertices = [
        1.0,  1.0,  0.0,
        0.0,  1.0,  0.0,
        1.0,  0.0,  0.0,
        0.0,  0.0,  0.0
    ];
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertices), GL.STATIC_DRAW);
    squarePositionBuffer.itemSize = 3;
    squarePositionBuffer.numItems = 4;
}

//==============================================================================

function initImageTileBuffers() {
    var vertexPositionData = [];
    var textureCoordData = [];

    // Make 4 points
    textureCoordData.push(0.0);
    textureCoordData.push(0.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(0.0);

    textureCoordData.push(1.0);
    textureCoordData.push(0.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(0.0);

    textureCoordData.push(0.0);
    textureCoordData.push(1.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(0.0);

    textureCoordData.push(1.0);
    textureCoordData.push(1.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(0.0);

    // Now create the cell.
    var cellData = [];
    cellData.push(0);
    cellData.push(1);
    cellData.push(2);

    cellData.push(2);
    cellData.push(1);
    cellData.push(3);

    tileVertexTextureCoordBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, tileVertexTextureCoordBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(textureCoordData), GL.STATIC_DRAW);
    tileVertexTextureCoordBuffer.itemSize = 2;
    tileVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;

    tileVertexPositionBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, tileVertexPositionBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertexPositionData), GL.STATIC_DRAW);
    tileVertexPositionBuffer.itemSize = 3;
    tileVertexPositionBuffer.numItems = vertexPositionData.length / 3;

    tileCellBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, tileCellBuffer);
    GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(cellData), GL.STATIC_DRAW);
    tileCellBuffer.itemSize = 1;
    tileCellBuffer.numItems = cellData.length;
}

// Stuff for drawing
var RENDER_PENDING = false;
function eventuallyRender() {
    if (! RENDER_PENDING) {
    RENDER_PENDING = true;
    requestAnimFrame(tick);
    }
}

function tick() {
    RENDER_PENDING = false;
    draw();
}

<commit_msg>Using stable context if available<commit_after>// This file contains some global variables and misc procedures to
// initials shaders and some buffers we need and to render.

var SLICE = 1;

// globals (for now)
var imageProgram;
var textProgram;
var polyProgram;
var mvMatrix = mat4.create();
var pMatrix = mat4.create();
var squareOutlinePositionBuffer;
var squarePositionBuffer;
var tileVertexPositionBuffer;
var tileVertexTextureCoordBuffer;
var tileCellBuffer;

// This global is used in every class that renders something.
// I can not test multiple canvases until I modularize the canvas
// and get rid of these globals.
var GL;

// WebGL Initialization

function initGL(canvas) {
    try {
        GL = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
        GL.viewportWidth = canvas.clientWidth;
        GL.viewportHeight = canvas.clientHeight;

        canvas.width =  canvas.clientWidth;
        canvas.height= canvas.clientHeight;

    } catch (e) {
    }
    if (!GL) {
        alert("Could not initialise WebGL, sorry :-(");
    }
}

function getShader(gl, id) {
    var shaderScript = document.getElementById(id);
    if (!shaderScript) {
        return null;
    }

    var str = "";
    var k = shaderScript.firstChild;
    while (k) {
        if (k.nodeType == 3) {
            str += k.textContent;
        }
        k = k.nextSibling;
    }

    var shader;
    if (shaderScript.type == "x-shader/x-fragment") {
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }

    gl.shaderSource(shader, str);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}

function initShaderPrograms() {
    polyProgram = createProgram("shader-poly-fs", "shader-poly-vs");
    polyProgram.colorUniform = GL.getUniformLocation(polyProgram, "uColor");

    imageProgram = createProgram("shader-tile-fs", "shader-tile-vs");
    // Texture coordinate attribute and texture image uniform
    imageProgram.textureCoordAttribute
        = GL.getAttribLocation(imageProgram,"aTextureCoord");
    GL.enableVertexAttribArray(imageProgram.textureCoordAttribute);
    imageProgram.samplerUniform = GL.getUniformLocation(imageProgram, "uSampler");

    textProgram = createProgram("shader-text-fs", "shader-text-vs");
    textProgram.textureCoordAttribute
        = GL.getAttribLocation(textProgram, "aTextureCoord");
    GL.enableVertexAttribArray(textProgram.textureCoordAttribute);
    textProgram.samplerUniform
        = GL.getUniformLocation(textProgram, "uSampler");
    textProgram.colorUniform = GL.getUniformLocation(textProgram, "uColor");
}

function createProgram(fragmentShaderID, vertexShaderID) {
    var fragmentShader = getShader(GL, fragmentShaderID);
    var vertexShader = getShader(GL, vertexShaderID);

    var program = GL.createProgram();
    GL.attachShader(program, vertexShader);
    GL.attachShader(program, fragmentShader);
    GL.linkProgram(program);

    if (!GL.getProgramParameter(program, GL.LINK_STATUS)) {
        alert("Could not initialise shaders");
    }

    program.vertexPositionAttribute = GL.getAttribLocation(program, "aVertexPosition");
    GL.enableVertexAttribArray(program.vertexPositionAttribute);

    // Camera matrix
    program.pMatrixUniform = GL.getUniformLocation(program, "uPMatrix");
    // Model matrix
    program.mvMatrixUniform = GL.getUniformLocation(program, "uMVMatrix");

    return program;
}

function initOutlineBuffers() {
    // Outline Square
    vertices = [
        0.0,  0.0,  0.0,
        0.0,  1.0,  0.0,
        1.0, 1.0,  0.0,
        1.0, 0.0,  0.0,
        0.0, 0.0,  0.0];
    squareOutlinePositionBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, squareOutlinePositionBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertices), GL.STATIC_DRAW);
    squareOutlinePositionBuffer.itemSize = 3;
    squareOutlinePositionBuffer.numItems = 5;

    // Filled square
    squarePositionBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, squarePositionBuffer);
    vertices = [
        1.0,  1.0,  0.0,
        0.0,  1.0,  0.0,
        1.0,  0.0,  0.0,
        0.0,  0.0,  0.0
    ];
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertices), GL.STATIC_DRAW);
    squarePositionBuffer.itemSize = 3;
    squarePositionBuffer.numItems = 4;
}

//==============================================================================

function initImageTileBuffers() {
    var vertexPositionData = [];
    var textureCoordData = [];

    // Make 4 points
    textureCoordData.push(0.0);
    textureCoordData.push(0.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(0.0);

    textureCoordData.push(1.0);
    textureCoordData.push(0.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(0.0);

    textureCoordData.push(0.0);
    textureCoordData.push(1.0);
    vertexPositionData.push(0.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(0.0);

    textureCoordData.push(1.0);
    textureCoordData.push(1.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(1.0);
    vertexPositionData.push(0.0);

    // Now create the cell.
    var cellData = [];
    cellData.push(0);
    cellData.push(1);
    cellData.push(2);

    cellData.push(2);
    cellData.push(1);
    cellData.push(3);

    tileVertexTextureCoordBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, tileVertexTextureCoordBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(textureCoordData), GL.STATIC_DRAW);
    tileVertexTextureCoordBuffer.itemSize = 2;
    tileVertexTextureCoordBuffer.numItems = textureCoordData.length / 2;

    tileVertexPositionBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, tileVertexPositionBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(vertexPositionData), GL.STATIC_DRAW);
    tileVertexPositionBuffer.itemSize = 3;
    tileVertexPositionBuffer.numItems = vertexPositionData.length / 3;

    tileCellBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, tileCellBuffer);
    GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(cellData), GL.STATIC_DRAW);
    tileCellBuffer.itemSize = 1;
    tileCellBuffer.numItems = cellData.length;
}

// Stuff for drawing
var RENDER_PENDING = false;
function eventuallyRender() {
    if (! RENDER_PENDING) {
    RENDER_PENDING = true;
    requestAnimFrame(tick);
    }
}

function tick() {
    RENDER_PENDING = false;
    draw();
}

<|endoftext|>