PHP.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * PHP operations.
  3. *
  4. * @author Jarmo van Lenthe [github.com/jarmovanlenthe]
  5. * @copyright Jarmo van Lenthe
  6. * @license Apache-2.0
  7. *
  8. * @namespace
  9. */
  10. const PHP = {
  11. /**
  12. * @constant
  13. * @default
  14. */
  15. OUTPUT_VALID_JSON: true,
  16. /**
  17. * PHP Deserialize operation.
  18. *
  19. * This Javascript implementation is based on the Python implementation by
  20. * Armin Ronacher (2016), who released it under the 3-Clause BSD license.
  21. * See: https://github.com/mitsuhiko/phpserialize/
  22. *
  23. * @param {string} input
  24. * @param {Object[]} args
  25. * @returns {string}
  26. */
  27. runDeserialize: function (input, args) {
  28. /**
  29. * Recursive method for deserializing.
  30. * @returns {*}
  31. */
  32. function handleInput() {
  33. /**
  34. * Read `length` characters from the input, shifting them out the input.
  35. * @param length
  36. * @returns {string}
  37. */
  38. function read(length) {
  39. let result = "";
  40. for (let idx = 0; idx < length; idx++) {
  41. let char = inputPart.shift();
  42. if (char === undefined) {
  43. throw "End of input reached before end of script";
  44. }
  45. result += char;
  46. }
  47. return result;
  48. }
  49. /**
  50. * Read characters from the input until `until` is found.
  51. * @param until
  52. * @returns {string}
  53. */
  54. function readUntil(until) {
  55. let result = "";
  56. for (;;) {
  57. let char = read(1);
  58. if (char === until) {
  59. break;
  60. } else {
  61. result += char;
  62. }
  63. }
  64. return result;
  65. }
  66. /**
  67. * Read characters from the input that must be equal to `expect`
  68. * @param expect
  69. * @returns {string}
  70. */
  71. function expect(expect) {
  72. let result = read(expect.length);
  73. if (result !== expect) {
  74. throw "Unexpected input found";
  75. }
  76. return result;
  77. }
  78. /**
  79. * Helper function to handle deserialized arrays.
  80. * @returns {Array}
  81. */
  82. function handleArray() {
  83. let items = parseInt(readUntil(":"), 10) * 2;
  84. expect("{");
  85. let result = [];
  86. let isKey = true;
  87. let lastItem = null;
  88. for (let idx = 0; idx < items; idx++) {
  89. let item = handleInput();
  90. if (isKey) {
  91. lastItem = item;
  92. isKey = false;
  93. } else {
  94. let numberCheck = lastItem.match(/[0-9]+/);
  95. if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
  96. result.push("\"" + lastItem + "\": " + item);
  97. } else {
  98. result.push(lastItem + ": " + item);
  99. }
  100. isKey = true;
  101. }
  102. }
  103. expect("}");
  104. return result;
  105. }
  106. let kind = read(1).toLowerCase();
  107. switch (kind) {
  108. case "n":
  109. expect(";");
  110. return "";
  111. case "i":
  112. case "d":
  113. case "b": {
  114. expect(":");
  115. let data = readUntil(";");
  116. if (kind === "b") {
  117. return (parseInt(data, 10) !== 0);
  118. }
  119. return data;
  120. }
  121. case "a":
  122. expect(":");
  123. return "{" + handleArray() + "}";
  124. case "s": {
  125. expect(":");
  126. let length = readUntil(":");
  127. expect("\"");
  128. let value = read(length);
  129. expect("\";");
  130. if (args[0]) {
  131. return "\"" + value.replace(/"/g, "\\\"") + "\"";
  132. } else {
  133. return "\"" + value + "\"";
  134. }
  135. }
  136. default:
  137. throw "Unknown type: " + kind;
  138. }
  139. }
  140. let inputPart = input.split("");
  141. return handleInput();
  142. }
  143. };
  144. export default PHP;