PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/source/plugin/mobile/json.class.php

https://github.com/kuaileshike/upload
PHP | 449 lines | 400 code | 46 blank | 3 comment | 68 complexity | 63d80834fd0163491cd03aa067643336 MD5 | raw file
  1. <?php
  2. class CJSON {
  3. const JSON_SLICE = 1;
  4. const JSON_IN_STR = 2;
  5. const JSON_IN_ARR = 4;
  6. const JSON_IN_OBJ = 8;
  7. const JSON_IN_CMT = 16;
  8. static function encode($var) {
  9. global $_G;
  10. switch (gettype($var)) {
  11. case 'boolean':
  12. return $var ? 'true' : 'false';
  13. case 'NULL':
  14. return 'null';
  15. case 'integer':
  16. return (int) $var;
  17. case 'double':
  18. case 'float':
  19. return rtrim(sprintf('%.16F',$var),'0');
  20. case 'string':
  21. if(function_exists('diconv') && strtolower($_G['charset']) != 'utf-8') {
  22. $var = diconv($var, $_G['charset'], 'utf-8');
  23. }
  24. if(function_exists('json_encode')) {
  25. return json_encode($var);
  26. }
  27. $ascii = '';
  28. $strlen_var = strlen($var);
  29. for ($c = 0; $c < $strlen_var; ++$c) {
  30. $ord_var_c = ord($var{$c});
  31. switch (true) {
  32. case $ord_var_c == 0x08:
  33. $ascii .= '\b';
  34. break;
  35. case $ord_var_c == 0x09:
  36. $ascii .= '\t';
  37. break;
  38. case $ord_var_c == 0x0A:
  39. $ascii .= '\n';
  40. break;
  41. case $ord_var_c == 0x0C:
  42. $ascii .= '\f';
  43. break;
  44. case $ord_var_c == 0x0D:
  45. $ascii .= '\r';
  46. break;
  47. case $ord_var_c == 0x22:
  48. case $ord_var_c == 0x2F:
  49. case $ord_var_c == 0x5C:
  50. $ascii .= '\\'.$var{$c};
  51. break;
  52. case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
  53. $ascii .= $var{$c};
  54. break;
  55. case (($ord_var_c & 0xE0) == 0xC0):
  56. $char = pack('C*', $ord_var_c, ord($var{$c+1}));
  57. $c+=1;
  58. $utf16 = self::utf8ToUTF16BE($char);
  59. $ascii .= sprintf('\u%04s', bin2hex($utf16));
  60. break;
  61. case (($ord_var_c & 0xF0) == 0xE0):
  62. $char = pack('C*', $ord_var_c,
  63. ord($var{$c+1}),
  64. ord($var{$c+2}));
  65. $c+=2;
  66. $utf16 = self::utf8ToUTF16BE($char);
  67. $ascii .= sprintf('\u%04s', bin2hex($utf16));
  68. break;
  69. case (($ord_var_c & 0xF8) == 0xF0):
  70. $char = pack('C*', $ord_var_c,
  71. ord($var{$c+1}),
  72. ord($var{$c+2}),
  73. ord($var{$c+3}));
  74. $c+=3;
  75. $utf16 = self::utf8ToUTF16BE($char);
  76. $ascii .= sprintf('\u%04s', bin2hex($utf16));
  77. break;
  78. case (($ord_var_c & 0xFC) == 0xF8):
  79. $char = pack('C*', $ord_var_c,
  80. ord($var{$c+1}),
  81. ord($var{$c+2}),
  82. ord($var{$c+3}),
  83. ord($var{$c+4}));
  84. $c+=4;
  85. $utf16 = self::utf8ToUTF16BE($char);
  86. $ascii .= sprintf('\u%04s', bin2hex($utf16));
  87. break;
  88. case (($ord_var_c & 0xFE) == 0xFC):
  89. $char = pack('C*', $ord_var_c,
  90. ord($var{$c+1}),
  91. ord($var{$c+2}),
  92. ord($var{$c+3}),
  93. ord($var{$c+4}),
  94. ord($var{$c+5}));
  95. $c+=5;
  96. $utf16 = self::utf8ToUTF16BE($char);
  97. $ascii .= sprintf('\u%04s', bin2hex($utf16));
  98. break;
  99. }
  100. }
  101. return '"'.$ascii.'"';
  102. case 'array':
  103. if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
  104. return '{' .
  105. join(',', array_map(array('CJSON', 'nameValue'),
  106. array_keys($var),
  107. array_values($var)))
  108. . '}';
  109. }
  110. return '[' . join(',', array_map(array('CJSON', 'encode'), $var)) . ']';
  111. case 'object':
  112. if ($var instanceof Traversable)
  113. {
  114. $vars = array();
  115. foreach ($var as $k=>$v)
  116. $vars[$k] = $v;
  117. }
  118. else
  119. $vars = get_object_vars($var);
  120. return '{' .
  121. join(',', array_map(array('CJSON', 'nameValue'),
  122. array_keys($vars),
  123. array_values($vars)))
  124. . '}';
  125. default:
  126. return '';
  127. }
  128. }
  129. static function nameValue($name, $value) {
  130. return self::encode(strval($name)) . ':' . self::encode($value);
  131. }
  132. static function reduceString($str) {
  133. $str = preg_replace(array(
  134. '#^\s*//(.+)$#m',
  135. '#^\s*/\*(.+)\*/#Us',
  136. '#/\*(.+)\*/\s*$#Us'
  137. ), '', $str);
  138. return trim($str);
  139. }
  140. static function decode($str, $useArray=true) {
  141. if(function_exists('json_decode')) {
  142. return json_decode($str, $useArray);
  143. }
  144. $str = self::reduceString($str);
  145. switch (strtolower($str)) {
  146. case 'true':
  147. return true;
  148. case 'false':
  149. return false;
  150. case 'null':
  151. return null;
  152. default:
  153. if (is_numeric($str)) {
  154. return ((float)$str == (integer)$str)
  155. ? (integer)$str
  156. : (float)$str;
  157. } elseif (preg_match('/^("|\').+(\1)$/s', $str, $m) && $m[1] == $m[2]) {
  158. $delim = substr($str, 0, 1);
  159. $chrs = substr($str, 1, -1);
  160. $utf8 = '';
  161. $strlen_chrs = strlen($chrs);
  162. for ($c = 0; $c < $strlen_chrs; ++$c) {
  163. $substr_chrs_c_2 = substr($chrs, $c, 2);
  164. $ord_chrs_c = ord($chrs{$c});
  165. switch (true) {
  166. case $substr_chrs_c_2 == '\b':
  167. $utf8 .= chr(0x08);
  168. ++$c;
  169. break;
  170. case $substr_chrs_c_2 == '\t':
  171. $utf8 .= chr(0x09);
  172. ++$c;
  173. break;
  174. case $substr_chrs_c_2 == '\n':
  175. $utf8 .= chr(0x0A);
  176. ++$c;
  177. break;
  178. case $substr_chrs_c_2 == '\f':
  179. $utf8 .= chr(0x0C);
  180. ++$c;
  181. break;
  182. case $substr_chrs_c_2 == '\r':
  183. $utf8 .= chr(0x0D);
  184. ++$c;
  185. break;
  186. case $substr_chrs_c_2 == '\\"':
  187. case $substr_chrs_c_2 == '\\\'':
  188. case $substr_chrs_c_2 == '\\\\':
  189. case $substr_chrs_c_2 == '\\/':
  190. if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
  191. ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
  192. $utf8 .= $chrs{++$c};
  193. }
  194. break;
  195. case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
  196. $utf16 = chr(hexdec(substr($chrs, ($c+2), 2)))
  197. . chr(hexdec(substr($chrs, ($c+4), 2)));
  198. $utf8 .= self::utf16beToUTF8($utf16);
  199. $c+=5;
  200. break;
  201. case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
  202. $utf8 .= $chrs{$c};
  203. break;
  204. case ($ord_chrs_c & 0xE0) == 0xC0:
  205. $utf8 .= substr($chrs, $c, 2);
  206. ++$c;
  207. break;
  208. case ($ord_chrs_c & 0xF0) == 0xE0:
  209. $utf8 .= substr($chrs, $c, 3);
  210. $c += 2;
  211. break;
  212. case ($ord_chrs_c & 0xF8) == 0xF0:
  213. $utf8 .= substr($chrs, $c, 4);
  214. $c += 3;
  215. break;
  216. case ($ord_chrs_c & 0xFC) == 0xF8:
  217. $utf8 .= substr($chrs, $c, 5);
  218. $c += 4;
  219. break;
  220. case ($ord_chrs_c & 0xFE) == 0xFC:
  221. $utf8 .= substr($chrs, $c, 6);
  222. $c += 5;
  223. break;
  224. }
  225. }
  226. return $utf8;
  227. } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
  228. if ($str{0} == '[') {
  229. $stk = array(self::JSON_IN_ARR);
  230. $arr = array();
  231. } else {
  232. if ($useArray) {
  233. $stk = array(self::JSON_IN_OBJ);
  234. $obj = array();
  235. } else {
  236. $stk = array(self::JSON_IN_OBJ);
  237. $obj = new stdClass();
  238. }
  239. }
  240. array_push($stk, array('what' => self::JSON_SLICE,
  241. 'where' => 0,
  242. 'delim' => false));
  243. $chrs = substr($str, 1, -1);
  244. $chrs = self::reduceString($chrs);
  245. if ($chrs == '') {
  246. if (reset($stk) == self::JSON_IN_ARR) {
  247. return $arr;
  248. } else {
  249. return $obj;
  250. }
  251. }
  252. $strlen_chrs = strlen($chrs);
  253. for ($c = 0; $c <= $strlen_chrs; ++$c) {
  254. $top = end($stk);
  255. $substr_chrs_c_2 = substr($chrs, $c, 2);
  256. if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == self::JSON_SLICE))) {
  257. $slice = substr($chrs, $top['where'], ($c - $top['where']));
  258. array_push($stk, array('what' => self::JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
  259. if (reset($stk) == self::JSON_IN_ARR) {
  260. array_push($arr, self::decode($slice,$useArray));
  261. } elseif (reset($stk) == self::JSON_IN_OBJ) {
  262. if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
  263. $key = self::decode($parts[1],$useArray);
  264. $val = self::decode($parts[2],$useArray);
  265. if ($useArray) {
  266. $obj[$key] = $val;
  267. } else {
  268. $obj->$key = $val;
  269. }
  270. } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
  271. $key = $parts[1];
  272. $val = self::decode($parts[2],$useArray);
  273. if ($useArray) {
  274. $obj[$key] = $val;
  275. } else {
  276. $obj->$key = $val;
  277. }
  278. }
  279. }
  280. } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != self::JSON_IN_STR)) {
  281. array_push($stk, array('what' => self::JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
  282. } elseif (($chrs{$c} == $top['delim']) &&
  283. ($top['what'] == self::JSON_IN_STR) &&
  284. (($chrs{$c - 1} != "\\") ||
  285. ($chrs{$c - 1} == "\\" && $chrs{$c - 2} == "\\"))) {
  286. array_pop($stk);
  287. } elseif (($chrs{$c} == '[') &&
  288. in_array($top['what'], array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) {
  289. array_push($stk, array('what' => self::JSON_IN_ARR, 'where' => $c, 'delim' => false));
  290. } elseif (($chrs{$c} == ']') && ($top['what'] == self::JSON_IN_ARR)) {
  291. array_pop($stk);
  292. } elseif (($chrs{$c} == '{') &&
  293. in_array($top['what'], array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) {
  294. array_push($stk, array('what' => self::JSON_IN_OBJ, 'where' => $c, 'delim' => false));
  295. } elseif (($chrs{$c} == '}') && ($top['what'] == self::JSON_IN_OBJ)) {
  296. array_pop($stk);
  297. } elseif (($substr_chrs_c_2 == '/**') &&
  298. in_array($top['what'], array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) {
  299. array_push($stk, array('what' => self::JSON_IN_CMT, 'where' => $c, 'delim' => false));
  300. $c++;
  301. } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == self::JSON_IN_CMT)) {
  302. array_pop($stk);
  303. $c++;
  304. for ($i = $top['where']; $i <= $c; ++$i) {
  305. $chrs = substr_replace($chrs, ' ', $i, 1);
  306. }
  307. }
  308. }
  309. if (reset($stk) == self::JSON_IN_ARR) {
  310. return $arr;
  311. } elseif (reset($stk) == self::JSON_IN_OBJ) {
  312. return $obj;
  313. }
  314. }
  315. }
  316. }
  317. static function utf8ToUnicode( &$str ) {
  318. $unicode = array();
  319. $values = array();
  320. $lookingFor = 1;
  321. for ($i = 0; $i < strlen( $str ); $i++ ) {
  322. $thisValue = ord( $str[ $i ] );
  323. if ( $thisValue < 128 ) {
  324. $unicode[] = $thisValue;
  325. } else {
  326. if ( count( $values ) == 0 ) {
  327. $lookingFor = ( $thisValue < 224 ) ? 2 : 3;
  328. }
  329. $values[] = $thisValue;
  330. if ( count( $values ) == $lookingFor ) {
  331. $number = ( $lookingFor == 3 ) ?
  332. ( ( $values[0] % 16 ) * 4096 ) + ( ( $values[1] % 64 ) * 64 ) + ( $values[2] % 64 ):
  333. ( ( $values[0] % 32 ) * 64 ) + ( $values[1] % 64 );
  334. $unicode[] = $number;
  335. $values = array();
  336. $lookingFor = 1;
  337. }
  338. }
  339. }
  340. return $unicode;
  341. }
  342. static function unicodeToUTF8( &$str )
  343. {
  344. $utf8 = '';
  345. foreach( $str as $unicode )
  346. {
  347. if ( $unicode < 128 )
  348. {
  349. $utf8.= chr( $unicode );
  350. }
  351. elseif ( $unicode < 2048 )
  352. {
  353. $utf8.= chr( 192 + ( ( $unicode - ( $unicode % 64 ) ) / 64 ) );
  354. $utf8.= chr( 128 + ( $unicode % 64 ) );
  355. }
  356. else
  357. {
  358. $utf8.= chr( 224 + ( ( $unicode - ( $unicode % 4096 ) ) / 4096 ) );
  359. $utf8.= chr( 128 + ( ( ( $unicode % 4096 ) - ( $unicode % 64 ) ) / 64 ) );
  360. $utf8.= chr( 128 + ( $unicode % 64 ) );
  361. }
  362. }
  363. return $utf8;
  364. }
  365. static function utf8ToUTF16BE(&$str, $bom = false) {
  366. $out = $bom ? "\xFE\xFF" : '';
  367. if(function_exists('mb_convert_encoding'))
  368. return $out.mb_convert_encoding($str,'UTF-16BE','UTF-8');
  369. $uni = self::utf8ToUnicode($str);
  370. foreach($uni as $cp)
  371. $out .= pack('n',$cp);
  372. return $out;
  373. }
  374. static function utf16beToUTF8(&$str) {
  375. $uni = unpack('n*',$str);
  376. return self::unicodeToUTF8($uni);
  377. }
  378. }