123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /**
- * @author Jarmo van Lenthe [github.com/jarmovanlenthe]
- * @copyright Jarmo van Lenthe
- * @license Apache-2.0
- */
- import Operation from "../Operation.mjs";
- import OperationError from "../errors/OperationError.mjs";
- /**
- * PHP Deserialize operation
- */
- class PHPDeserialize extends Operation {
- /**
- * PHPDeserialize constructor
- */
- constructor() {
- super();
- this.name = "PHP Deserialize";
- this.module = "Default";
- this.description = "Deserializes PHP serialized data, outputting keyed arrays as JSON.<br><br>This function does not support <code>object</code> tags.<br><br>Example:<br><code>a:2:{s:1:"a";i:10;i:0;a:1:{s:2:"ab";b:1;}}</code><br>becomes<br><code>{"a": 10,0: {"ab": true}}</code><br><br><u>Output valid JSON:</u> JSON doesn't support integers as keys, whereas PHP serialization does. Enabling this will cast these integers to strings. This will also escape backslashes.";
- this.infoURL = "http://www.phpinternalsbook.com/classes_objects/serialization.html";
- this.inputType = "string";
- this.outputType = "string";
- this.args = [
- {
- "name": "Output valid JSON",
- "type": "boolean",
- "value": true
- }
- ];
- }
- /**
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- run(input, args) {
- /**
- * Recursive method for deserializing.
- * @returns {*}
- */
- function handleInput() {
- /**
- * Read `length` characters from the input, shifting them out the input.
- * @param length
- * @returns {string}
- */
- function read(length) {
- let result = "";
- for (let idx = 0; idx < length; idx++) {
- const char = inputPart.shift();
- if (char === undefined) {
- throw new OperationError("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}
- */
- function readUntil(until) {
- let result = "";
- for (;;) {
- const char = read(1);
- if (char === until) {
- break;
- } else {
- result += char;
- }
- }
- return result;
- }
- /**
- * Read characters from the input that must be equal to `expect`
- * @param expect
- * @returns {string}
- */
- function expect(expect) {
- const result = read(expect.length);
- if (result !== expect) {
- throw new OperationError("Unexpected input found");
- }
- return result;
- }
- /**
- * Helper function to handle deserialized arrays.
- * @returns {Array}
- */
- function handleArray() {
- const items = parseInt(readUntil(":"), 10) * 2;
- expect("{");
- const result = [];
- let isKey = true;
- let lastItem = null;
- for (let idx = 0; idx < items; idx++) {
- const item = handleInput();
- if (isKey) {
- lastItem = item;
- isKey = false;
- } else {
- const numberCheck = lastItem.match(/[0-9]+/);
- if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
- result.push('"' + lastItem + '": ' + item);
- } else {
- result.push(lastItem + ": " + item);
- }
- isKey = true;
- }
- }
- expect("}");
- return result;
- }
- const kind = read(1).toLowerCase();
- switch (kind) {
- case "n":
- expect(";");
- return "null";
- case "i":
- case "d":
- case "b": {
- expect(":");
- const data = readUntil(";");
- if (kind === "b") {
- return (parseInt(data, 10) !== 0);
- }
- return data;
- }
- case "a":
- expect(":");
- return "{" + handleArray() + "}";
- case "s": {
- expect(":");
- const length = readUntil(":");
- expect("\"");
- const value = read(length);
- expect('";');
- if (args[0]) {
- return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]
- } else {
- return '"' + value + '"';
- }
- }
- default:
- throw new OperationError("Unknown type: " + kind);
- }
- }
- const inputPart = input.split("");
- return handleInput();
- }
- }
- export default PHPDeserialize;
|