CyberChef/src/core/operations/PHP.js

161 lines
4.6 KiB
JavaScript
Raw Normal View History

2017-11-12 21:37:29 -05:00
/**
* PHP operations.
2017-11-12 21:37:29 -05:00
*
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
* @copyright Jarmo van Lenthe
* @license Apache-2.0
2017-11-12 21:37:29 -05:00
*
* @namespace
*/
const PHP = {
2017-11-12 21:37:29 -05:00
/**
* @constant
* @default
*/
OUTPUT_VALID_JSON: true,
2017-11-12 22:11:16 -05:00
/**
* PHP Deserialize operation.
*
* This Javascript implementation is based on the Python implementation by
* Armin Ronacher (2016), who released it under the 3-Clause BSD license.
* See: https://github.com/mitsuhiko/phpserialize/
*
2017-11-12 22:11:16 -05:00
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runDeserialize: function (input, args) {
/**
* Recursive method for deserializing.
* @returns {*}
*/
2017-11-12 21:37:29 -05:00
function handleInput() {
/**
* Read `length` characters from the input, shifting them out the input.
* @param length
* @returns {string}
*/
2017-11-12 21:37:29 -05:00
function read(length) {
let result = "";
for (let idx = 0; idx < length; idx++) {
let char = inputPart.shift();
if (char === undefined) {
throw "End of input reached before end of script";
}
result += char;
}
return result;
}
/**
* Read characters from the input until `until` is found.
* @param until
* @returns {string}
*/
2017-11-12 21:37:29 -05:00
function readUntil(until) {
let result = "";
2017-11-12 22:23:38 -05:00
for (;;) {
2017-11-12 21:37:29 -05:00
let char = read(1);
if (char === until) {
break;
2017-11-12 22:11:16 -05:00
} else {
2017-11-12 21:37:29 -05:00
result += char;
}
}
return result;
}
/**
* Read characters from the input that must be equal to `expect`
* @param expect
* @returns {string}
*/
2017-11-12 21:37:29 -05:00
function expect(expect) {
let result = read(expect.length);
if (result !== expect) {
throw "Unexpected input found";
}
return result;
}
/**
* Helper function to handle deserialized arrays.
* @returns {Array}
*/
2017-11-12 21:37:29 -05:00
function handleArray() {
2017-11-12 22:11:16 -05:00
let items = parseInt(readUntil(":"), 10) * 2;
expect("{");
2017-11-12 21:37:29 -05:00
let result = [];
let isKey = true;
2017-11-12 22:11:16 -05:00
let lastItem = null;
2017-11-12 21:37:29 -05:00
for (let idx = 0; idx < items; idx++) {
let item = handleInput();
if (isKey) {
2017-11-12 22:11:16 -05:00
lastItem = item;
2017-11-12 21:37:29 -05:00
isKey = false;
} else {
2017-11-12 22:11:16 -05:00
let numberCheck = lastItem.match(/[0-9]+/);
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
result.push("\"" + lastItem + "\": " + item);
2017-11-12 21:37:29 -05:00
} else {
2017-11-12 22:11:16 -05:00
result.push(lastItem + ": " + item);
2017-11-12 21:37:29 -05:00
}
isKey = true;
}
}
2017-11-12 22:11:16 -05:00
expect("}");
2017-11-12 21:37:29 -05:00
return result;
}
let kind = read(1).toLowerCase();
switch (kind) {
2017-11-12 22:11:16 -05:00
case "n":
expect(";");
return "";
case "i":
case "d":
case "b": {
expect(":");
let data = readUntil(";");
if (kind === "b") {
return (parseInt(data, 10) !== 0);
}
2017-11-12 21:37:29 -05:00
return data;
2017-11-12 22:11:16 -05:00
}
2017-11-12 21:37:29 -05:00
2017-11-12 22:11:16 -05:00
case "a":
expect(":");
return "{" + handleArray() + "}";
2017-11-12 21:37:29 -05:00
2017-11-12 22:11:16 -05:00
case "s": {
expect(":");
let length = readUntil(":");
expect("\"");
2017-11-12 21:37:29 -05:00
let value = read(length);
2017-11-12 22:11:16 -05:00
expect("\";");
if (args[0]) {
return "\"" + value.replace(/"/g, "\\\"") + "\"";
} else {
return "\"" + value + "\"";
}
}
2017-11-12 21:37:29 -05:00
default:
throw "Unknown type: " + kind;
}
}
2017-11-12 22:11:16 -05:00
let inputPart = input.split("");
2017-11-12 21:37:29 -05:00
return handleInput();
}
2017-11-12 21:37:29 -05:00
};
export default PHP;