Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

3 lat temu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * eval source code in PHP or JSON format
  4. *
  5. */
  6. class VarEval {
  7. /**
  8. * Source to run
  9. *
  10. * @var string
  11. */
  12. private $_source;
  13. /**
  14. * Source Format
  15. *
  16. * @var string
  17. */
  18. private $_format;
  19. /**
  20. * current MongoDB
  21. *
  22. * @var MongoDB
  23. */
  24. private $_db;
  25. function __construct($source, $format = "array", MongoDB $db = null) {
  26. $this->_source = $source;
  27. $this->_format = $format;
  28. if (!$this->_format) {
  29. $this->_format = "array";
  30. }
  31. $this->_db = $db;
  32. }
  33. /**
  34. * execute the code
  35. *
  36. * @return mixed
  37. */
  38. function execute() {
  39. if ($this->_format == "array") {
  40. return $this->_runPHP();
  41. }
  42. else if ($this->_format == "json") {
  43. return $this->_runJson();
  44. }
  45. }
  46. private function _runPHP() {
  47. $this->_source = "return " . $this->_source . ";";
  48. if (function_exists("token_get_all")) {//tokenizer extension may be disabled
  49. $php = "<?php\n" . $this->_source . "\n?>";
  50. $tokens = token_get_all($php);
  51. foreach ($tokens as $token) {
  52. $type = $token[0];
  53. if (is_long($type)) {
  54. if (in_array($type, array(
  55. T_OPEN_TAG,
  56. T_RETURN,
  57. T_WHITESPACE,
  58. T_ARRAY,
  59. T_LNUMBER,
  60. T_DNUMBER,
  61. T_CONSTANT_ENCAPSED_STRING,
  62. T_DOUBLE_ARROW,
  63. T_CLOSE_TAG,
  64. T_NEW,
  65. T_DOUBLE_COLON
  66. ))) {
  67. continue;
  68. }
  69. if ($type == T_STRING) {
  70. $func = strtolower($token[1]);
  71. if (in_array($func, array(
  72. //keywords allowed
  73. "mongoid",
  74. "mongocode",
  75. "mongodate",
  76. "mongoregex",
  77. "mongobindata",
  78. "mongoint32",
  79. "mongoint64",
  80. "mongodbref",
  81. "mongominkey",
  82. "mongomaxkey",
  83. "mongotimestamp",
  84. "true",
  85. "false",
  86. "null",
  87. "__set_state",
  88. "stdclass"
  89. ))) {
  90. continue;
  91. }
  92. }
  93. exit("For your security, we stoped data parsing at '(" . token_name($type) . ") " . $token[1] . "'.");
  94. }
  95. }
  96. }
  97. return eval($this->_source);
  98. }
  99. private function _runJson() {
  100. $timezone = @date_default_timezone_get();
  101. date_default_timezone_set("UTC");
  102. $ret = $this->_db->execute('function () {
  103. if (typeof(ISODate) == "undefined") {
  104. function ISODate (isoDateStr) {
  105. if (!isoDateStr) {
  106. return new Date;
  107. }
  108. var isoDateRegex = /(\d{4})-?(\d{2})-?(\d{2})([T ](\d{2})(:?(\d{2})(:?(\d{2}(\.\d+)?))?)?(Z|([+-])(\d{2}):?(\d{2})?)?)?/;
  109. var res = isoDateRegex.exec(isoDateStr);
  110. if (!res) {
  111. throw "invalid ISO date";
  112. }
  113. var year = parseInt(res[1], 10) || 1970;
  114. var month = (parseInt(res[2], 10) || 1) - 1;
  115. var date = parseInt(res[3], 10) || 0;
  116. var hour = parseInt(res[5], 10) || 0;
  117. var min = parseInt(res[7], 10) || 0;
  118. var sec = parseFloat(res[9]) || 0;
  119. var ms = Math.round(sec % 1 * 1000);
  120. sec -= ms / 1000;
  121. var time = Date.UTC(year, month, date, hour, min, sec, ms);
  122. if (res[11] && res[11] != "Z") {
  123. var ofs = 0;
  124. ofs += (parseInt(res[13], 10) || 0) * 60 * 60 * 1000;
  125. ofs += (parseInt(res[14], 10) || 0) * 60 * 1000;
  126. if (res[12] == "+") {
  127. ofs *= -1;
  128. }
  129. time += ofs;
  130. }
  131. return new Date(time);
  132. };
  133. };
  134. function r_util_convert_empty_object_to_string(obj) {
  135. if (r_util_is_empty(obj)) {
  136. return "__EMPTYOBJECT__";
  137. }
  138. if (typeof(obj) == "object") {
  139. for (var k in obj) {
  140. obj[k] = r_util_convert_empty_object_to_string(obj[k]);
  141. }
  142. }
  143. return obj;
  144. };
  145. function r_util_is_empty(obj) {
  146. if (obj == null || typeof(obj) != "object" || (obj.constructor != Object)) {
  147. return false;
  148. }
  149. for(var k in obj) {
  150. if(obj.hasOwnProperty(k)) {
  151. return false;
  152. }
  153. }
  154. return true;
  155. };
  156. var o = ' . $this->_source . '; return r_util_convert_empty_object_to_string(o); }'
  157. );
  158. $this->_fixEmptyObject($ret);
  159. date_default_timezone_set($timezone);
  160. if ($ret["ok"]) {
  161. return $ret["retval"];
  162. }
  163. return json_decode($this->_source, true);
  164. }
  165. private function _fixEmptyObject(&$object) {
  166. if (is_array($object)) {
  167. foreach ($object as &$v) {
  168. $this->_fixEmptyObject($v);
  169. }
  170. }
  171. else if (is_string($object) && $object === "__EMPTYOBJECT__") {
  172. $object = new stdClass();
  173. }
  174. }
  175. }
  176. ?>