Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
   1  <?php
   2  /**
   3   * $Id: JSON.php 40 2007-06-18 11:43:15Z spocke $
   4   *
   5   * @package MCManager.utils
   6   * @author Moxiecode
   7   * @copyright Copyright © 2007, Moxiecode Systems AB, All rights reserved.
   8   */
   9  
  10  define('JSON_BOOL', 1);
  11  define('JSON_INT', 2);
  12  define('JSON_STR', 3);
  13  define('JSON_FLOAT', 4);
  14  define('JSON_NULL', 5);
  15  define('JSON_START_OBJ', 6);
  16  define('JSON_END_OBJ', 7);
  17  define('JSON_START_ARRAY', 8);
  18  define('JSON_END_ARRAY', 9);
  19  define('JSON_KEY', 10);
  20  define('JSON_SKIP', 11);
  21  
  22  define('JSON_IN_ARRAY', 30);
  23  define('JSON_IN_OBJECT', 40);
  24  define('JSON_IN_BETWEEN', 50);
  25  
  26  class Moxiecode_JSONReader {
  27  	 var $_data, $_len, $_pos;
  28  	 var $_value, $_token;
  29  	 var $_location, $_lastLocations;
  30  	 var $_needProp;
  31  
  32  	public function __construct($data) {
  33  	 	 $this->_data = $data;
  34  	 	 $this->_len = strlen($data);
  35  	 	 $this->_pos = -1;
  36  	 	 $this->_location = JSON_IN_BETWEEN;
  37  	 	 $this->_lastLocations = array();
  38  	 	 $this->_needProp = false;
  39  	 }
  40  
  41      /**
  42       * Old syntax of class constructor. Deprecated in PHP7.
  43       *
  44       * @deprecated since Moodle 3.1
  45       */
  46      public function Moxiecode_JSONReader($data) {
  47          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
  48          self::__construct($data);
  49      }
  50  
  51  	function getToken() {
  52  	 	 return $this->_token;
  53  	 }
  54  
  55  	function getLocation() {
  56  	 	 return $this->_location;
  57  	 }
  58  
  59  	function getTokenName() {
  60  	 	 switch ($this->_token) {
  61  	 	 	 case JSON_BOOL:
  62  	 	 	 	 return 'JSON_BOOL';
  63  
  64  	 	 	 case JSON_INT:
  65  	 	 	 	 return 'JSON_INT';
  66  
  67  	 	 	 case JSON_STR:
  68  	 	 	 	 return 'JSON_STR';
  69  
  70  	 	 	 case JSON_FLOAT:
  71  	 	 	 	 return 'JSON_FLOAT';
  72  
  73  	 	 	 case JSON_NULL:
  74  	 	 	 	 return 'JSON_NULL';
  75  
  76  	 	 	 case JSON_START_OBJ:
  77  	 	 	 	 return 'JSON_START_OBJ';
  78  
  79  	 	 	 case JSON_END_OBJ:
  80  	 	 	 	 return 'JSON_END_OBJ';
  81  
  82  	 	 	 case JSON_START_ARRAY:
  83  	 	 	 	 return 'JSON_START_ARRAY';
  84  
  85  	 	 	 case JSON_END_ARRAY:
  86  	 	 	 	 return 'JSON_END_ARRAY';
  87  
  88  	 	 	 case JSON_KEY:
  89  	 	 	 	 return 'JSON_KEY';
  90  	 	 }
  91  
  92  	 	 return 'UNKNOWN';
  93  	 }
  94  
  95  	function getValue() {
  96  	 	 return $this->_value;
  97  	 }
  98  
  99  	function readToken() {
 100  	 	 $chr = $this->read();
 101  
 102  	 	 if ($chr != null) {
 103  	 	 	 switch ($chr) {
 104  	 	 	 	 case '[':
 105  	 	 	 	 	 $this->_lastLocation[] = $this->_location;
 106  	 	 	 	 	 $this->_location = JSON_IN_ARRAY;
 107  	 	 	 	 	 $this->_token = JSON_START_ARRAY;
 108  	 	 	 	 	 $this->_value = null;
 109  	 	 	 	 	 $this->readAway();
 110  	 	 	 	 	 return true;
 111  
 112  	 	 	 	 case ']':
 113  	 	 	 	 	 $this->_location = array_pop($this->_lastLocation);
 114  	 	 	 	 	 $this->_token = JSON_END_ARRAY;
 115  	 	 	 	 	 $this->_value = null;
 116  	 	 	 	 	 $this->readAway();
 117  
 118  	 	 	 	 	 if ($this->_location == JSON_IN_OBJECT)
 119  	 	 	 	 	 	 $this->_needProp = true;
 120  
 121  	 	 	 	 	 return true;
 122  
 123  	 	 	 	 case '{':
 124  	 	 	 	 	 $this->_lastLocation[] = $this->_location;
 125  	 	 	 	 	 $this->_location = JSON_IN_OBJECT;
 126  	 	 	 	 	 $this->_needProp = true;
 127  	 	 	 	 	 $this->_token = JSON_START_OBJ;
 128  	 	 	 	 	 $this->_value = null;
 129  	 	 	 	 	 $this->readAway();
 130  	 	 	 	 	 return true;
 131  
 132  	 	 	 	 case '}':
 133  	 	 	 	 	 $this->_location = array_pop($this->_lastLocation);
 134  	 	 	 	 	 $this->_token = JSON_END_OBJ;
 135  	 	 	 	 	 $this->_value = null;
 136  	 	 	 	 	 $this->readAway();
 137  
 138  	 	 	 	 	 if ($this->_location == JSON_IN_OBJECT)
 139  	 	 	 	 	 	 $this->_needProp = true;
 140  
 141  	 	 	 	 	 return true;
 142  
 143  	 	 	 	 // String
 144  	 	 	 	 case '"':
 145  	 	 	 	 case '\'':
 146  	 	 	 	 	 return $this->_readString($chr);
 147  
 148  	 	 	 	 // Null
 149  	 	 	 	 case 'n':
 150  	 	 	 	 	 return $this->_readNull();
 151  
 152  	 	 	 	 // Bool
 153  	 	 	 	 case 't':
 154  	 	 	 	 case 'f':
 155  	 	 	 	 	 return $this->_readBool($chr);
 156  
 157  	 	 	 	 default:
 158  	 	 	 	 	 // Is number
 159  	 	 	 	 	 if (is_numeric($chr) || $chr == '-' || $chr == '.')
 160  	 	 	 	 	 	 return $this->_readNumber($chr);
 161  
 162  	 	 	 	 	 return true;
 163  	 	 	 }
 164  	 	 }
 165  
 166  	 	 return false;
 167  	 }
 168  
 169  	function _readBool($chr) {
 170  	 	 $this->_token = JSON_BOOL;
 171  	 	 $this->_value = $chr == 't';
 172  
 173  	 	 if ($chr == 't')
 174  	 	 	 $this->skip(3); // rue
 175  	 	 else
 176  	 	 	 $this->skip(4); // alse
 177  
 178  	 	 $this->readAway();
 179  
 180  	 	 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp)
 181  	 	 	 $this->_needProp = true;
 182  
 183  	 	 return true;
 184  	 }
 185  
 186  	function _readNull() {
 187  	 	 $this->_token = JSON_NULL;
 188  	 	 $this->_value = null;
 189  
 190  	 	 $this->skip(3); // ull
 191  	 	 $this->readAway();
 192  
 193  	 	 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp)
 194  	 	 	 $this->_needProp = true;
 195  
 196  	 	 return true;
 197  	 }
 198  
 199  	function _readString($quote) {
 200  	 	 $output = "";
 201  	 	 $this->_token = JSON_STR;
 202  	 	 $endString = false;
 203  
 204  	 	 while (($chr = $this->peek()) != -1) {
 205  	 	 	 switch ($chr) {
 206  	 	 	 	 case '\\':
 207  	 	 	 	 	 // Read away slash
 208  	 	 	 	 	 $this->read();
 209  
 210  	 	 	 	 	 // Read escape code
 211  	 	 	 	 	 $chr = $this->read();
 212  	 	 	 	 	 switch ($chr) {
 213  	 	 	 	 	 	 	 case 't':
 214  	 	 	 	 	 	 	 	 $output .= "\t";
 215  	 	 	 	 	 	 	 	 break;
 216  
 217  	 	 	 	 	 	 	 case 'b':
 218  	 	 	 	 	 	 	 	 $output .= "\b";
 219  	 	 	 	 	 	 	 	 break;
 220  
 221  	 	 	 	 	 	 	 case 'f':
 222  	 	 	 	 	 	 	 	 $output .= "\f";
 223  	 	 	 	 	 	 	 	 break;
 224  
 225  	 	 	 	 	 	 	 case 'r':
 226  	 	 	 	 	 	 	 	 $output .= "\r";
 227  	 	 	 	 	 	 	 	 break;
 228  
 229  	 	 	 	 	 	 	 case 'n':
 230  	 	 	 	 	 	 	 	 $output .= "\n";
 231  	 	 	 	 	 	 	 	 break;
 232  
 233  	 	 	 	 	 	 	 case 'u':
 234  	 	 	 	 	 	 	 	 $output .= $this->_int2utf8(hexdec($this->read(4)));
 235  	 	 	 	 	 	 	 	 break;
 236  
 237  	 	 	 	 	 	 	 default:
 238  	 	 	 	 	 	 	 	 $output .= $chr;
 239  	 	 	 	 	 	 	 	 break;
 240  	 	 	 	 	 }
 241  
 242  	 	 	 	 	 break;
 243  
 244  	 	 	 	 	 case '\'':
 245  	 	 	 	 	 case '"':
 246  	 	 	 	 	 	 if ($chr == $quote)
 247  	 	 	 	 	 	 	 $endString = true;
 248  
 249  	 	 	 	 	 	 $chr = $this->read();
 250  	 	 	 	 	 	 if ($chr != -1 && $chr != $quote)
 251  	 	 	 	 	 	 	 $output .= $chr;
 252  
 253  	 	 	 	 	 	 break;
 254  
 255  	 	 	 	 	 default:
 256  	 	 	 	 	 	 $output .= $this->read();
 257  	 	 	 }
 258  
 259  	 	 	 // String terminated
 260  	 	 	 if ($endString)
 261  	 	 	 	 break;
 262  	 	 }
 263  
 264  	 	 $this->readAway();
 265  	 	 $this->_value = $output;
 266  
 267  	 	 // Needed a property
 268  	 	 if ($this->_needProp) {
 269  	 	 	 $this->_token = JSON_KEY;
 270  	 	 	 $this->_needProp = false;
 271  	 	 	 return true;
 272  	 	 }
 273  
 274  	 	 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp)
 275  	 	 	 $this->_needProp = true;
 276  
 277  	 	 return true;
 278  	 }
 279  
 280  	function _int2utf8($int) {
 281  	 	 $int = intval($int);
 282  
 283  	 	 switch ($int) {
 284  	 	 	 case 0:
 285  	 	 	 	 return chr(0);
 286  
 287  	 	 	 case ($int & 0x7F):
 288  	 	 	 	 return chr($int);
 289  
 290  	 	 	 case ($int & 0x7FF):
 291  	 	 	 	 return chr(0xC0 | (($int >> 6) & 0x1F)) . chr(0x80 | ($int & 0x3F));
 292  
 293  	 	 	 case ($int & 0xFFFF):
 294  	 	 	 	 return chr(0xE0 | (($int >> 12) & 0x0F)) . chr(0x80 | (($int >> 6) & 0x3F)) . chr (0x80 | ($int & 0x3F));
 295  
 296  	 	 	 case ($int & 0x1FFFFF):
 297  	 	 	 	 return chr(0xF0 | ($int >> 18)) . chr(0x80 | (($int >> 12) & 0x3F)) . chr(0x80 | (($int >> 6) & 0x3F)) . chr(0x80 | ($int & 0x3F));
 298  	 	 }
 299  	 }
 300  
 301  	function _readNumber($start) {
 302  	 	 $value = "";
 303  	 	 $isFloat = false;
 304  
 305  	 	 $this->_token = JSON_INT;
 306  	 	 $value .= $start;
 307  
 308  	 	 while (($chr = $this->peek()) != -1) {
 309  	 	 	 if (is_numeric($chr) || $chr == '-' || $chr == '.') {
 310  	 	 	 	 if ($chr == '.')
 311  	 	 	 	 	 $isFloat = true;
 312  
 313  	 	 	 	 $value .= $this->read();
 314  	 	 	 } else
 315  	 	 	 	 break;
 316  	 	 }
 317  
 318  	 	 $this->readAway();
 319  
 320  	 	 if ($isFloat) {
 321  	 	 	 $this->_token = JSON_FLOAT;
 322  	 	 	 $this->_value = floatval($value);
 323  	 	 } else
 324  	 	 	 $this->_value = intval($value);
 325  
 326  	 	 if ($this->_location == JSON_IN_OBJECT && !$this->_needProp)
 327  	 	 	 $this->_needProp = true;
 328  
 329  	 	 return true;
 330  	 }
 331  
 332  	function readAway() {
 333  	 	 while (($chr = $this->peek()) != null) {
 334  	 	 	 if ($chr != ':' && $chr != ',' && $chr != ' ')
 335  	 	 	 	 return;
 336  
 337  	 	 	 $this->read();
 338  	 	 }
 339  	 }
 340  
 341  	function read($len = 1) {
 342  	 	 if ($this->_pos < $this->_len) {
 343  	 	 	 if ($len > 1) {
 344  	 	 	 	 $str = substr($this->_data, $this->_pos + 1, $len);
 345  	 	 	 	 $this->_pos += $len;
 346  
 347  	 	 	 	 return $str;
 348  	 	 	 } else
 349  	 	 	 	 return $this->_data[++$this->_pos];
 350  	 	 }
 351  
 352  	 	 return null;
 353  	 }
 354  
 355  	function skip($len) {
 356  	 	 $this->_pos += $len;
 357  	 }
 358  
 359  	function peek() {
 360  	 	 if ($this->_pos < $this->_len)
 361  	 	 	 return $this->_data[$this->_pos + 1];
 362  
 363  	 	 return null;
 364  	 }
 365  }
 366  
 367  /**
 368   * This class handles JSON stuff.
 369   *
 370   * @package MCManager.utils
 371   */
 372  class Moxiecode_JSON {
 373  	public function __construct() {
 374  	 }
 375  
 376      /**
 377       * Old syntax of class constructor. Deprecated in PHP7.
 378       *
 379       * @deprecated since Moodle 3.1
 380       */
 381      public function Moxiecode_JSON() {
 382          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
 383          self::__construct();
 384      }
 385  
 386  	function decode($input) {
 387  	 	 $reader = new Moxiecode_JSONReader($input);
 388  
 389  	 	 return $this->readValue($reader);
 390  	 }
 391  
 392  	function readValue(&$reader) {
 393  	 	 $this->data = array();
 394  	 	 $this->parents = array();
 395  	 	 $this->cur =& $this->data;
 396  	 	 $key = null;
 397  	 	 $loc = JSON_IN_ARRAY;
 398  
 399  	 	 while ($reader->readToken()) {
 400  	 	 	 switch ($reader->getToken()) {
 401  	 	 	 	 case JSON_STR:
 402  	 	 	 	 case JSON_INT:
 403  	 	 	 	 case JSON_BOOL:
 404  	 	 	 	 case JSON_FLOAT:
 405  	 	 	 	 case JSON_NULL:
 406  	 	 	 	 	 switch ($reader->getLocation()) {
 407  	 	 	 	 	 	 case JSON_IN_OBJECT:
 408  	 	 	 	 	 	 	 $this->cur[$key] = $reader->getValue();
 409  	 	 	 	 	 	 	 break;
 410  
 411  	 	 	 	 	 	 case JSON_IN_ARRAY:
 412  	 	 	 	 	 	 	 $this->cur[] = $reader->getValue();
 413  	 	 	 	 	 	 	 break;
 414  
 415  	 	 	 	 	 	 default:
 416  	 	 	 	 	 	 	 return $reader->getValue();
 417  	 	 	 	 	 }
 418  	 	 	 	 	 break;
 419  
 420  	 	 	 	 case JSON_KEY:
 421  	 	 	 	 	 $key = $reader->getValue();
 422  	 	 	 	 	 break;
 423  
 424  	 	 	 	 case JSON_START_OBJ:
 425  	 	 	 	 case JSON_START_ARRAY:
 426  	 	 	 	 	 if ($loc == JSON_IN_OBJECT)
 427  	 	 	 	 	 	 $this->addArray($key);
 428  	 	 	 	 	 else
 429  	 	 	 	 	 	 $this->addArray(null);
 430  
 431  	 	 	 	 	 $cur =& $obj;
 432  
 433  	 	 	 	 	 $loc = $reader->getLocation();
 434  	 	 	 	 	 break;
 435  
 436  	 	 	 	 case JSON_END_OBJ:
 437  	 	 	 	 case JSON_END_ARRAY:
 438  	 	 	 	 	 $loc = $reader->getLocation();
 439  
 440  	 	 	 	 	 if (count($this->parents) > 0) {
 441  	 	 	 	 	 	 $this->cur =& $this->parents[count($this->parents) - 1];
 442  	 	 	 	 	 	 array_pop($this->parents);
 443  	 	 	 	 	 }
 444  	 	 	 	 	 break;
 445  	 	 	 }
 446  	 	 }
 447  
 448  	 	 return $this->data[0];
 449  	 }
 450  
 451  	 // This method was needed since PHP is crapy and doesn't have pointers/references
 452  	function addArray($key) {
 453  	 	 $this->parents[] =& $this->cur;
 454  	 	 $ar = array();
 455  
 456  	 	 if ($key)
 457  	 	 	 $this->cur[$key] =& $ar;
 458  	 	 else
 459  	 	 	 $this->cur[] =& $ar;
 460  
 461  	 	 $this->cur =& $ar;
 462  	 }
 463  
 464  	function getDelim($index, &$reader) {
 465  	 	 switch ($reader->getLocation()) {
 466  	 	 	 case JSON_IN_ARRAY:
 467  	 	 	 case JSON_IN_OBJECT:
 468  	 	 	 	 if ($index > 0)
 469  	 	 	 	 	 return ",";
 470  	 	 	 	 break;
 471  	 	 }
 472  
 473  	 	 return "";
 474  	 }
 475  
 476  	function encode($input) {
 477  	 	 switch (gettype($input)) {
 478  	 	 	 case 'boolean':
 479  	 	 	 	 return $input ? 'true' : 'false';
 480  
 481  	 	 	 case 'integer':
 482  	 	 	 	 return (int) $input;
 483  
 484  	 	 	 case 'float':
 485  	 	 	 case 'double':
 486  	 	 	 	 return (float) $input;
 487  
 488  	 	 	 case 'NULL':
 489  	 	 	 	 return 'null';
 490  
 491  	 	 	 case 'string':
 492  	 	 	 	 return $this->encodeString($input);
 493  
 494  	 	 	 case 'array':
 495  	 	 	 	 return $this->_encodeArray($input);
 496  
 497  	 	 	 case 'object':
 498  	 	 	 	 return $this->_encodeArray(get_object_vars($input));
 499  	 	 }
 500  
 501  	 	 return '';
 502  	 }
 503  
 504  	function encodeString($input) {
 505  	 	 // Needs to be escaped
 506  	 	 if (preg_match('/[^a-zA-Z0-9]/', $input)) {
 507  	 	 	 $output = '';
 508  
 509  	 	 	 for ($i=0; $i<strlen($input); $i++) {
 510  	 	 	 	 switch ($input[$i]) {
 511  	 	 	 	 	 case "\b":
 512  	 	 	 	 	 	 $output .= "\\b";
 513  	 	 	 	 	 	 break;
 514  
 515  	 	 	 	 	 case "\t":
 516  	 	 	 	 	 	 $output .= "\\t";
 517  	 	 	 	 	 	 break;
 518  
 519  	 	 	 	 	 case "\f":
 520  	 	 	 	 	 	 $output .= "\\f";
 521  	 	 	 	 	 	 break;
 522  
 523  	 	 	 	 	 case "\r":
 524  	 	 	 	 	 	 $output .= "\\r";
 525  	 	 	 	 	 	 break;
 526  
 527  	 	 	 	 	 case "\n":
 528  	 	 	 	 	 	 $output .= "\\n";
 529  	 	 	 	 	 	 break;
 530  
 531  	 	 	 	 	 case '\\':
 532  	 	 	 	 	 	 $output .= "\\\\";
 533  	 	 	 	 	 	 break;
 534  
 535  	 	 	 	 	 case '\'':
 536  	 	 	 	 	 	 $output .= "\\'";
 537  	 	 	 	 	 	 break;
 538  
 539  	 	 	 	 	 case '"':
 540  	 	 	 	 	 	 $output .= '\"';
 541  	 	 	 	 	 	 break;
 542  
 543  	 	 	 	 	 default:
 544  	 	 	 	 	 	 $byte = ord($input[$i]);
 545  
 546  	 	 	 	 	 	 if (($byte & 0xE0) == 0xC0) {
 547  	 	 	 	 	 	 	 $char = pack('C*', $byte, ord($input[$i + 1]));
 548  	 	 	 	 	 	 	 $i += 1;
 549  	 	 	 	 	 	 	 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char)));
 550  	 	 	 	 	 	 } if (($byte & 0xF0) == 0xE0) {
 551  	 	 	 	 	 	 	 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]));
 552  	 	 	 	 	 	 	 $i += 2;
 553  	 	 	 	 	 	 	 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char)));
 554  	 	 	 	 	 	 } if (($byte & 0xF8) == 0xF0) {
 555  	 	 	 	 	 	 	 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]), ord($input[$i + 3]));
 556  	 	 	 	 	 	 	 $i += 3;
 557  	 	 	 	 	 	 	 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char)));
 558  	 	 	 	 	 	 } if (($byte & 0xFC) == 0xF8) {
 559  	 	 	 	 	 	 	 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]), ord($input[$i + 3]), ord($input[$i + 4]));
 560  	 	 	 	 	 	 	 $i += 4;
 561  	 	 	 	 	 	 	 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char)));
 562  	 	 	 	 	 	 } if (($byte & 0xFE) == 0xFC) {
 563  	 	 	 	 	 	 	 $char = pack('C*', $byte, ord($input[$i + 1]), ord($input[$i + 2]), ord($input[$i + 3]), ord($input[$i + 4]), ord($input[$i + 5]));
 564  	 	 	 	 	 	 	 $i += 5;
 565  	 	 	 	 	 	 	 $output .= sprintf('\u%04s', bin2hex($this->_utf82utf16($char)));
 566  	 	 	 	 	 	 } else if ($byte < 128)
 567  	 	 	 	 	 	 	 $output .= $input[$i];
 568  	 	 	 	 }
 569  	 	 	 }
 570  
 571  	 	 	 return '"' . $output . '"';
 572  	 	 }
 573  
 574  	 	 return '"' . $input . '"';
 575  	 }
 576  
 577  	function _utf82utf16($utf8) {
 578  	 	 if (function_exists('mb_convert_encoding'))
 579  	 	 	 return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
 580  
 581  	 	 switch (strlen($utf8)) {
 582  	 	 	 case 1:
 583  	 	 	 	 return $utf8;
 584  
 585  	 	 	 case 2:
 586  	 	 	 	 return chr(0x07 & (ord($utf8[0]) >> 2)) . chr((0xC0 & (ord($utf8[0]) << 6)) | (0x3F & ord($utf8[1])));
 587  
 588  	 	 	 case 3:
 589  	 	 	 	 return chr((0xF0 & (ord($utf8[0]) << 4)) | (0x0F & (ord($utf8[1]) >> 2))) . chr((0xC0 & (ord($utf8[1]) << 6)) | (0x7F & ord($utf8[2])));
 590  	 	 }
 591  
 592  	 	 return '';
 593  	 }
 594  
 595  	function _encodeArray($input) {
 596  	 	 $output = '';
 597  	 	 $isIndexed = true;
 598  
 599  	 	 $keys = array_keys($input);
 600  	 	 for ($i=0; $i<count($keys); $i++) {
 601  	 	 	 if (!is_int($keys[$i])) {
 602  	 	 	 	 $output .= $this->encodeString($keys[$i]) . ':' . $this->encode($input[$keys[$i]]);
 603  	 	 	 	 $isIndexed = false;
 604  	 	 	 } else
 605  	 	 	 	 $output .= $this->encode($input[$keys[$i]]);
 606  
 607  	 	 	 if ($i != count($keys) - 1)
 608  	 	 	 	 $output .= ',';
 609  	 	 }
 610  
 611  	 	 return $isIndexed ? '[' . $output . ']' : '{' . $output . '}';
 612  	 }
 613  }
 614  
 615  ?>