wp/wp-includes/class-json.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
     1 <?php
     1 <?php
       
     2 _deprecated_file( basename( __FILE__ ), '5.3.0', null, 'The PHP native JSON extension is now a requirement.' );
       
     3 
     2 if ( ! class_exists( 'Services_JSON' ) ) :
     4 if ( ! class_exists( 'Services_JSON' ) ) :
     3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
     5 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
     4 /**
     6 /**
     5  * Converts to and from JSON format.
     7  * Converts to and from JSON format.
     6  *
     8  *
   103  *
   105  *
   104  * <code>
   106  * <code>
   105  * // create a new instance of Services_JSON
   107  * // create a new instance of Services_JSON
   106  * $json = new Services_JSON();
   108  * $json = new Services_JSON();
   107  *
   109  *
   108  * // convert a complexe value to JSON notation, and send it to the browser
   110  * // convert a complex value to JSON notation, and send it to the browser
   109  * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
   111  * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
   110  * $output = $json->encode($value);
   112  * $output = $json->encode($value);
   111  *
   113  *
   112  * print($output);
   114  * print($output);
   113  * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
   115  * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
   119  */
   121  */
   120 class Services_JSON
   122 class Services_JSON
   121 {
   123 {
   122    /**
   124    /**
   123     * constructs a new JSON instance
   125     * constructs a new JSON instance
       
   126     *
       
   127     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   124     *
   128     *
   125     * @param    int     $use    object behavior flags; combine with boolean-OR
   129     * @param    int     $use    object behavior flags; combine with boolean-OR
   126     *
   130     *
   127     *                           possible values:
   131     *                           possible values:
   128     *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
   132     *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
   140     *                                   strings or numbers, if you return an object, make sure it does
   144     *                                   strings or numbers, if you return an object, make sure it does
   141     *                                   not have a toJSON method, otherwise an error will occur.
   145     *                                   not have a toJSON method, otherwise an error will occur.
   142     */
   146     */
   143     function __construct( $use = 0 )
   147     function __construct( $use = 0 )
   144     {
   148     {
       
   149         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   150 
   145         $this->use = $use;
   151         $this->use = $use;
   146         $this->_mb_strlen            = function_exists('mb_strlen');
   152         $this->_mb_strlen            = function_exists('mb_strlen');
   147         $this->_mb_convert_encoding  = function_exists('mb_convert_encoding');
   153         $this->_mb_convert_encoding  = function_exists('mb_convert_encoding');
   148         $this->_mb_substr            = function_exists('mb_substr');
   154         $this->_mb_substr            = function_exists('mb_substr');
   149     }
   155     }
   150 
   156 
   151 	/**
   157 	/**
   152 	 * PHP4 constructor.
   158 	 * PHP4 constructor.
       
   159      *
       
   160      * @deprecated 5.3.0 Use __construct() instead.
       
   161      *
       
   162      * @see Services_JSON::__construct()
   153 	 */
   163 	 */
   154 	public function Services_JSON( $use = 0 ) {
   164 	public function Services_JSON( $use = 0 ) {
       
   165 		_deprecated_constructor( 'Services_JSON', '5.3.0', get_class( $this ) );
   155 		self::__construct( $use );
   166 		self::__construct( $use );
   156 	}
   167 	}
   157     // private - cache the mbstring lookup results..
   168     // private - cache the mbstring lookup results..
   158     var $_mb_strlen = false;
   169     var $_mb_strlen = false;
   159     var $_mb_substr = false;
   170     var $_mb_substr = false;
   164     *
   175     *
   165     * Normally should be handled by mb_convert_encoding, but
   176     * Normally should be handled by mb_convert_encoding, but
   166     * provides a slower PHP-only method for installations
   177     * provides a slower PHP-only method for installations
   167     * that lack the multibye string extension.
   178     * that lack the multibye string extension.
   168     *
   179     *
       
   180     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
       
   181     *
   169     * @param    string  $utf16  UTF-16 character
   182     * @param    string  $utf16  UTF-16 character
   170     * @return   string  UTF-8 character
   183     * @return   string  UTF-8 character
   171     * @access   private
   184     * @access   private
   172     */
   185     */
   173     function utf162utf8($utf16)
   186     function utf162utf8($utf16)
   174     {
   187     {
       
   188         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   189 
   175         // oh please oh please oh please oh please oh please
   190         // oh please oh please oh please oh please oh please
   176         if($this->_mb_convert_encoding) {
   191         if($this->_mb_convert_encoding) {
   177             return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
   192             return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
   178         }
   193         }
   179 
   194 
   180         $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
   195         $bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
   181 
   196 
   182         switch(true) {
   197         switch(true) {
   183             case ((0x7F & $bytes) == $bytes):
   198             case ((0x7F & $bytes) == $bytes):
   184                 // this case should never be reached, because we are in ASCII range
   199                 // this case should never be reached, because we are in ASCII range
   185                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   200                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   206    /**
   221    /**
   207     * convert a string from one UTF-8 char to one UTF-16 char
   222     * convert a string from one UTF-8 char to one UTF-16 char
   208     *
   223     *
   209     * Normally should be handled by mb_convert_encoding, but
   224     * Normally should be handled by mb_convert_encoding, but
   210     * provides a slower PHP-only method for installations
   225     * provides a slower PHP-only method for installations
   211     * that lack the multibye string extension.
   226     * that lack the multibyte string extension.
       
   227     *
       
   228     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   212     *
   229     *
   213     * @param    string  $utf8   UTF-8 character
   230     * @param    string  $utf8   UTF-8 character
   214     * @return   string  UTF-16 character
   231     * @return   string  UTF-16 character
   215     * @access   private
   232     * @access   private
   216     */
   233     */
   217     function utf82utf16($utf8)
   234     function utf82utf16($utf8)
   218     {
   235     {
       
   236         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   237 
   219         // oh please oh please oh please oh please oh please
   238         // oh please oh please oh please oh please oh please
   220         if($this->_mb_convert_encoding) {
   239         if($this->_mb_convert_encoding) {
   221             return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
   240             return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
   222         }
   241         }
   223 
   242 
   228                 return $utf8;
   247                 return $utf8;
   229 
   248 
   230             case 2:
   249             case 2:
   231                 // return a UTF-16 character from a 2-byte UTF-8 char
   250                 // return a UTF-16 character from a 2-byte UTF-8 char
   232                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   251                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   233                 return chr(0x07 & (ord($utf8{0}) >> 2))
   252                 return chr(0x07 & (ord($utf8[0]) >> 2))
   234                      . chr((0xC0 & (ord($utf8{0}) << 6))
   253                      . chr((0xC0 & (ord($utf8[0]) << 6))
   235                          | (0x3F & ord($utf8{1})));
   254                          | (0x3F & ord($utf8[1])));
   236 
   255 
   237             case 3:
   256             case 3:
   238                 // return a UTF-16 character from a 3-byte UTF-8 char
   257                 // return a UTF-16 character from a 3-byte UTF-8 char
   239                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   258                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   240                 return chr((0xF0 & (ord($utf8{0}) << 4))
   259                 return chr((0xF0 & (ord($utf8[0]) << 4))
   241                          | (0x0F & (ord($utf8{1}) >> 2)))
   260                          | (0x0F & (ord($utf8[1]) >> 2)))
   242                      . chr((0xC0 & (ord($utf8{1}) << 6))
   261                      . chr((0xC0 & (ord($utf8[1]) << 6))
   243                          | (0x7F & ord($utf8{2})));
   262                          | (0x7F & ord($utf8[2])));
   244         }
   263         }
   245 
   264 
   246         // ignoring UTF-32 for now, sorry
   265         // ignoring UTF-32 for now, sorry
   247         return '';
   266         return '';
   248     }
   267     }
   249 
   268 
   250    /**
   269    /**
   251     * encodes an arbitrary variable into JSON format (and sends JSON Header)
   270     * encodes an arbitrary variable into JSON format (and sends JSON Header)
       
   271     *
       
   272     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   252     *
   273     *
   253     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
   274     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
   254     *                           see argument 1 to Services_JSON() above for array-parsing behavior.
   275     *                           see argument 1 to Services_JSON() above for array-parsing behavior.
   255     *                           if var is a string, note that encode() always expects it
   276     *                           if var is a string, note that encode() always expects it
   256     *                           to be in ASCII or UTF-8 format!
   277     *                           to be in ASCII or UTF-8 format!
   258     * @return   mixed   JSON string representation of input var or an error if a problem occurs
   279     * @return   mixed   JSON string representation of input var or an error if a problem occurs
   259     * @access   public
   280     * @access   public
   260     */
   281     */
   261     function encode($var)
   282     function encode($var)
   262     {
   283     {
       
   284         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   285 
   263         header('Content-type: application/json');
   286         header('Content-type: application/json');
   264         return $this->encodeUnsafe($var);
   287         return $this->encodeUnsafe($var);
   265     }
   288     }
   266     /**
   289     /**
   267     * encodes an arbitrary variable into JSON format without JSON Header - warning - may allow XSS!!!!)
   290     * encodes an arbitrary variable into JSON format without JSON Header - warning - may allow XSS!!!!)
       
   291     *
       
   292     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   268     *
   293     *
   269     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
   294     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
   270     *                           see argument 1 to Services_JSON() above for array-parsing behavior.
   295     *                           see argument 1 to Services_JSON() above for array-parsing behavior.
   271     *                           if var is a string, note that encode() always expects it
   296     *                           if var is a string, note that encode() always expects it
   272     *                           to be in ASCII or UTF-8 format!
   297     *                           to be in ASCII or UTF-8 format!
   274     * @return   mixed   JSON string representation of input var or an error if a problem occurs
   299     * @return   mixed   JSON string representation of input var or an error if a problem occurs
   275     * @access   public
   300     * @access   public
   276     */
   301     */
   277     function encodeUnsafe($var)
   302     function encodeUnsafe($var)
   278     {
   303     {
       
   304         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   305 
   279         // see bug #16908 - regarding numeric locale printing
   306         // see bug #16908 - regarding numeric locale printing
   280         $lc = setlocale(LC_NUMERIC, 0);
   307         $lc = setlocale(LC_NUMERIC, 0);
   281         setlocale(LC_NUMERIC, 'C');
   308         setlocale(LC_NUMERIC, 'C');
   282         $ret = $this->_encode($var);
   309         $ret = $this->_encode($var);
   283         setlocale(LC_NUMERIC, $lc);
   310         setlocale(LC_NUMERIC, $lc);
   285         
   312         
   286     }
   313     }
   287     /**
   314     /**
   288     * PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format 
   315     * PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format 
   289     *
   316     *
       
   317     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
       
   318     *
   290     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
   319     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
   291     *                           see argument 1 to Services_JSON() above for array-parsing behavior.
   320     *                           see argument 1 to Services_JSON() above for array-parsing behavior.
   292     *                           if var is a string, note that encode() always expects it
   321     *                           if var is a string, note that encode() always expects it
   293     *                           to be in ASCII or UTF-8 format!
   322     *                           to be in ASCII or UTF-8 format!
   294     *
   323     *
   295     * @return   mixed   JSON string representation of input var or an error if a problem occurs
   324     * @return   mixed   JSON string representation of input var or an error if a problem occurs
   296     * @access   public
   325     * @access   public
   297     */
   326     */
   298     function _encode($var) 
   327     function _encode($var) 
   299     {
   328     {
   300          
   329         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   330 
   301         switch (gettype($var)) {
   331         switch (gettype($var)) {
   302             case 'boolean':
   332             case 'boolean':
   303                 return $var ? 'true' : 'false';
   333                 return $var ? 'true' : 'false';
   304 
   334 
   305             case 'NULL':
   335             case 'NULL':
   321                 * Iterate over every character in the string,
   351                 * Iterate over every character in the string,
   322                 * escaping with a slash or encoding to UTF-8 where necessary
   352                 * escaping with a slash or encoding to UTF-8 where necessary
   323                 */
   353                 */
   324                 for ($c = 0; $c < $strlen_var; ++$c) {
   354                 for ($c = 0; $c < $strlen_var; ++$c) {
   325 
   355 
   326                     $ord_var_c = ord($var{$c});
   356                     $ord_var_c = ord($var[$c]);
   327 
   357 
   328                     switch (true) {
   358                     switch (true) {
   329                         case $ord_var_c == 0x08:
   359                         case $ord_var_c == 0x08:
   330                             $ascii .= '\b';
   360                             $ascii .= '\b';
   331                             break;
   361                             break;
   344 
   374 
   345                         case $ord_var_c == 0x22:
   375                         case $ord_var_c == 0x22:
   346                         case $ord_var_c == 0x2F:
   376                         case $ord_var_c == 0x2F:
   347                         case $ord_var_c == 0x5C:
   377                         case $ord_var_c == 0x5C:
   348                             // double quote, slash, slosh
   378                             // double quote, slash, slosh
   349                             $ascii .= '\\'.$var{$c};
   379                             $ascii .= '\\'.$var[$c];
   350                             break;
   380                             break;
   351 
   381 
   352                         case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
   382                         case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
   353                             // characters U-00000000 - U-0000007F (same as ASCII)
   383                             // characters U-00000000 - U-0000007F (same as ASCII)
   354                             $ascii .= $var{$c};
   384                             $ascii .= $var[$c];
   355                             break;
   385                             break;
   356 
   386 
   357                         case (($ord_var_c & 0xE0) == 0xC0):
   387                         case (($ord_var_c & 0xE0) == 0xC0):
   358                             // characters U-00000080 - U-000007FF, mask 110XXXXX
   388                             // characters U-00000080 - U-000007FF, mask 110XXXXX
   359                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   389                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   361                                 $c += 1;
   391                                 $c += 1;
   362                                 $ascii .= '?';
   392                                 $ascii .= '?';
   363                                 break;
   393                                 break;
   364                             }
   394                             }
   365                             
   395                             
   366                             $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
   396                             $char = pack('C*', $ord_var_c, ord($var[$c + 1]));
   367                             $c += 1;
   397                             $c += 1;
   368                             $utf16 = $this->utf82utf16($char);
   398                             $utf16 = $this->utf82utf16($char);
   369                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   399                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   370                             break;
   400                             break;
   371 
   401 
   376                                 break;
   406                                 break;
   377                             }
   407                             }
   378                             // characters U-00000800 - U-0000FFFF, mask 1110XXXX
   408                             // characters U-00000800 - U-0000FFFF, mask 1110XXXX
   379                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   409                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   380                             $char = pack('C*', $ord_var_c,
   410                             $char = pack('C*', $ord_var_c,
   381                                          @ord($var{$c + 1}),
   411                                          @ord($var[$c + 1]),
   382                                          @ord($var{$c + 2}));
   412                                          @ord($var[$c + 2]));
   383                             $c += 2;
   413                             $c += 2;
   384                             $utf16 = $this->utf82utf16($char);
   414                             $utf16 = $this->utf82utf16($char);
   385                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   415                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   386                             break;
   416                             break;
   387 
   417 
   392                                 break;
   422                                 break;
   393                             }
   423                             }
   394                             // characters U-00010000 - U-001FFFFF, mask 11110XXX
   424                             // characters U-00010000 - U-001FFFFF, mask 11110XXX
   395                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   425                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   396                             $char = pack('C*', $ord_var_c,
   426                             $char = pack('C*', $ord_var_c,
   397                                          ord($var{$c + 1}),
   427                                          ord($var[$c + 1]),
   398                                          ord($var{$c + 2}),
   428                                          ord($var[$c + 2]),
   399                                          ord($var{$c + 3}));
   429                                          ord($var[$c + 3]));
   400                             $c += 3;
   430                             $c += 3;
   401                             $utf16 = $this->utf82utf16($char);
   431                             $utf16 = $this->utf82utf16($char);
   402                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   432                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   403                             break;
   433                             break;
   404 
   434 
   409                                 $c += 4;
   439                                 $c += 4;
   410                                 $ascii .= '?';
   440                                 $ascii .= '?';
   411                                 break;
   441                                 break;
   412                             }
   442                             }
   413                             $char = pack('C*', $ord_var_c,
   443                             $char = pack('C*', $ord_var_c,
   414                                          ord($var{$c + 1}),
   444                                          ord($var[$c + 1]),
   415                                          ord($var{$c + 2}),
   445                                          ord($var[$c + 2]),
   416                                          ord($var{$c + 3}),
   446                                          ord($var[$c + 3]),
   417                                          ord($var{$c + 4}));
   447                                          ord($var[$c + 4]));
   418                             $c += 4;
   448                             $c += 4;
   419                             $utf16 = $this->utf82utf16($char);
   449                             $utf16 = $this->utf82utf16($char);
   420                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   450                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   421                             break;
   451                             break;
   422 
   452 
   427                                 break;
   457                                 break;
   428                             }
   458                             }
   429                             // characters U-04000000 - U-7FFFFFFF, mask 1111110X
   459                             // characters U-04000000 - U-7FFFFFFF, mask 1111110X
   430                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   460                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   431                             $char = pack('C*', $ord_var_c,
   461                             $char = pack('C*', $ord_var_c,
   432                                          ord($var{$c + 1}),
   462                                          ord($var[$c + 1]),
   433                                          ord($var{$c + 2}),
   463                                          ord($var[$c + 2]),
   434                                          ord($var{$c + 3}),
   464                                          ord($var[$c + 3]),
   435                                          ord($var{$c + 4}),
   465                                          ord($var[$c + 4]),
   436                                          ord($var{$c + 5}));
   466                                          ord($var[$c + 5]));
   437                             $c += 5;
   467                             $c += 5;
   438                             $utf16 = $this->utf82utf16($char);
   468                             $utf16 = $this->utf82utf16($char);
   439                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   469                             $ascii .= sprintf('\u%04s', bin2hex($utf16));
   440                             break;
   470                             break;
   441                     }
   471                     }
   529     }
   559     }
   530 
   560 
   531    /**
   561    /**
   532     * array-walking function for use in generating JSON-formatted name-value pairs
   562     * array-walking function for use in generating JSON-formatted name-value pairs
   533     *
   563     *
       
   564     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
       
   565     *
   534     * @param    string  $name   name of key to use
   566     * @param    string  $name   name of key to use
   535     * @param    mixed   $value  reference to an array element to be encoded
   567     * @param    mixed   $value  reference to an array element to be encoded
   536     *
   568     *
   537     * @return   string  JSON-formatted name-value pair, like '"name":value'
   569     * @return   string  JSON-formatted name-value pair, like '"name":value'
   538     * @access   private
   570     * @access   private
   539     */
   571     */
   540     function name_value($name, $value)
   572     function name_value($name, $value)
   541     {
   573     {
       
   574         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   575 
   542         $encoded_value = $this->_encode($value);
   576         $encoded_value = $this->_encode($value);
   543 
   577 
   544         if(Services_JSON::isError($encoded_value)) {
   578         if(Services_JSON::isError($encoded_value)) {
   545             return $encoded_value;
   579             return $encoded_value;
   546         }
   580         }
   548         return $this->_encode(strval($name)) . ':' . $encoded_value;
   582         return $this->_encode(strval($name)) . ':' . $encoded_value;
   549     }
   583     }
   550 
   584 
   551    /**
   585    /**
   552     * reduce a string by removing leading and trailing comments and whitespace
   586     * reduce a string by removing leading and trailing comments and whitespace
       
   587     *
       
   588     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   553     *
   589     *
   554     * @param    $str    string      string value to strip of comments and whitespace
   590     * @param    $str    string      string value to strip of comments and whitespace
   555     *
   591     *
   556     * @return   string  string value stripped of comments and whitespace
   592     * @return   string  string value stripped of comments and whitespace
   557     * @access   private
   593     * @access   private
   558     */
   594     */
   559     function reduce_string($str)
   595     function reduce_string($str)
   560     {
   596     {
       
   597         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   598 
   561         $str = preg_replace(array(
   599         $str = preg_replace(array(
   562 
   600 
   563                 // eliminate single line comments in '// ...' form
   601                 // eliminate single line comments in '// ...' form
   564                 '#^\s*//(.+)$#m',
   602                 '#^\s*//(.+)$#m',
   565 
   603 
   575         return trim($str);
   613         return trim($str);
   576     }
   614     }
   577 
   615 
   578    /**
   616    /**
   579     * decodes a JSON string into appropriate variable
   617     * decodes a JSON string into appropriate variable
       
   618     *
       
   619     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   580     *
   620     *
   581     * @param    string  $str    JSON-formatted string
   621     * @param    string  $str    JSON-formatted string
   582     *
   622     *
   583     * @return   mixed   number, boolean, string, array, or object
   623     * @return   mixed   number, boolean, string, array, or object
   584     *                   corresponding to given JSON input string.
   624     *                   corresponding to given JSON input string.
   587     *                   in ASCII or UTF-8 format!
   627     *                   in ASCII or UTF-8 format!
   588     * @access   public
   628     * @access   public
   589     */
   629     */
   590     function decode($str)
   630     function decode($str)
   591     {
   631     {
       
   632         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   633 
   592         $str = $this->reduce_string($str);
   634         $str = $this->reduce_string($str);
   593 
   635 
   594         switch (strtolower($str)) {
   636         switch (strtolower($str)) {
   595             case 'true':
   637             case 'true':
   596                 return true;
   638                 return true;
   624                     $strlen_chrs = $this->strlen8($chrs);
   666                     $strlen_chrs = $this->strlen8($chrs);
   625 
   667 
   626                     for ($c = 0; $c < $strlen_chrs; ++$c) {
   668                     for ($c = 0; $c < $strlen_chrs; ++$c) {
   627 
   669 
   628                         $substr_chrs_c_2 = $this->substr8($chrs, $c, 2);
   670                         $substr_chrs_c_2 = $this->substr8($chrs, $c, 2);
   629                         $ord_chrs_c = ord($chrs{$c});
   671                         $ord_chrs_c = ord($chrs[$c]);
   630 
   672 
   631                         switch (true) {
   673                         switch (true) {
   632                             case $substr_chrs_c_2 == '\b':
   674                             case $substr_chrs_c_2 == '\b':
   633                                 $utf8 .= chr(0x08);
   675                                 $utf8 .= chr(0x08);
   634                                 ++$c;
   676                                 ++$c;
   654                             case $substr_chrs_c_2 == '\\\'':
   696                             case $substr_chrs_c_2 == '\\\'':
   655                             case $substr_chrs_c_2 == '\\\\':
   697                             case $substr_chrs_c_2 == '\\\\':
   656                             case $substr_chrs_c_2 == '\\/':
   698                             case $substr_chrs_c_2 == '\\/':
   657                                 if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
   699                                 if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
   658                                    ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
   700                                    ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
   659                                     $utf8 .= $chrs{++$c};
   701                                     $utf8 .= $chrs[++$c];
   660                                 }
   702                                 }
   661                                 break;
   703                                 break;
   662 
   704 
   663                             case preg_match('/\\\u[0-9A-F]{4}/i', $this->substr8($chrs, $c, 6)):
   705                             case preg_match('/\\\u[0-9A-F]{4}/i', $this->substr8($chrs, $c, 6)):
   664                                 // single, escaped unicode character
   706                                 // single, escaped unicode character
   667                                 $utf8 .= $this->utf162utf8($utf16);
   709                                 $utf8 .= $this->utf162utf8($utf16);
   668                                 $c += 5;
   710                                 $c += 5;
   669                                 break;
   711                                 break;
   670 
   712 
   671                             case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
   713                             case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
   672                                 $utf8 .= $chrs{$c};
   714                                 $utf8 .= $chrs[$c];
   673                                 break;
   715                                 break;
   674 
   716 
   675                             case ($ord_chrs_c & 0xE0) == 0xC0:
   717                             case ($ord_chrs_c & 0xE0) == 0xC0:
   676                                 // characters U-00000080 - U-000007FF, mask 110XXXXX
   718                                 // characters U-00000080 - U-000007FF, mask 110XXXXX
   677                                 //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   719                                 //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
   714                     return $utf8;
   756                     return $utf8;
   715 
   757 
   716                 } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
   758                 } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
   717                     // array, or object notation
   759                     // array, or object notation
   718 
   760 
   719                     if ($str{0} == '[') {
   761                     if ($str[0] == '[') {
   720                         $stk = array(SERVICES_JSON_IN_ARR);
   762                         $stk = array(SERVICES_JSON_IN_ARR);
   721                         $arr = array();
   763                         $arr = array();
   722                     } else {
   764                     } else {
   723                         if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
   765                         if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
   724                             $stk = array(SERVICES_JSON_IN_OBJ);
   766                             $stk = array(SERVICES_JSON_IN_OBJ);
   753                     for ($c = 0; $c <= $strlen_chrs; ++$c) {
   795                     for ($c = 0; $c <= $strlen_chrs; ++$c) {
   754 
   796 
   755                         $top = end($stk);
   797                         $top = end($stk);
   756                         $substr_chrs_c_2 = $this->substr8($chrs, $c, 2);
   798                         $substr_chrs_c_2 = $this->substr8($chrs, $c, 2);
   757 
   799 
   758                         if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
   800                         if (($c == $strlen_chrs) || (($chrs[$c] == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
   759                             // found a comma that is not inside a string, array, etc.,
   801                             // found a comma that is not inside a string, array, etc.,
   760                             // OR we've reached the end of the character list
   802                             // OR we've reached the end of the character list
   761                             $slice = $this->substr8($chrs, $top['where'], ($c - $top['where']));
   803                             $slice = $this->substr8($chrs, $top['where'], ($c - $top['where']));
   762                             array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
   804                             array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
   763                             //print("Found split at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
   805                             //print("Found split at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
   772                                 // element in an associative array,
   814                                 // element in an associative array,
   773                                 // for now
   815                                 // for now
   774                                 $parts = array();
   816                                 $parts = array();
   775                                 
   817                                 
   776                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:/Uis', $slice, $parts)) {
   818                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:/Uis', $slice, $parts)) {
   777  	                              // "name":value pair
   819                                     // "name":value pair
   778                                     $key = $this->decode($parts[1]);
   820                                     $key = $this->decode($parts[1]);
   779                                     $val = $this->decode(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B"));
   821                                     $val = $this->decode(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B"));
   780                                     if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
   822                                     if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
   781                                         $obj[$key] = $val;
   823                                         $obj[$key] = $val;
   782                                     } else {
   824                                     } else {
   794                                     }
   836                                     }
   795                                 }
   837                                 }
   796 
   838 
   797                             }
   839                             }
   798 
   840 
   799                         } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
   841                         } elseif ((($chrs[$c] == '"') || ($chrs[$c] == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
   800                             // found a quote, and we are not inside a string
   842                             // found a quote, and we are not inside a string
   801                             array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
   843                             array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs[$c]));
   802                             //print("Found start of string at {$c}\n");
   844                             //print("Found start of string at {$c}\n");
   803 
   845 
   804                         } elseif (($chrs{$c} == $top['delim']) &&
   846                         } elseif (($chrs[$c] == $top['delim']) &&
   805                                  ($top['what'] == SERVICES_JSON_IN_STR) &&
   847                                  ($top['what'] == SERVICES_JSON_IN_STR) &&
   806                                  (($this->strlen8($this->substr8($chrs, 0, $c)) - $this->strlen8(rtrim($this->substr8($chrs, 0, $c), '\\'))) % 2 != 1)) {
   848                                  (($this->strlen8($this->substr8($chrs, 0, $c)) - $this->strlen8(rtrim($this->substr8($chrs, 0, $c), '\\'))) % 2 != 1)) {
   807                             // found a quote, we're in a string, and it's not escaped
   849                             // found a quote, we're in a string, and it's not escaped
   808                             // we know that it's not escaped because there is _not_ an
   850                             // we know that it's not escaped because there is _not_ an
   809                             // odd number of backslashes at the end of the string so far
   851                             // odd number of backslashes at the end of the string so far
   810                             array_pop($stk);
   852                             array_pop($stk);
   811                             //print("Found end of string at {$c}: ".$this->substr8($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
   853                             //print("Found end of string at {$c}: ".$this->substr8($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
   812 
   854 
   813                         } elseif (($chrs{$c} == '[') &&
   855                         } elseif (($chrs[$c] == '[') &&
   814                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
   856                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
   815                             // found a left-bracket, and we are in an array, object, or slice
   857                             // found a left-bracket, and we are in an array, object, or slice
   816                             array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
   858                             array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
   817                             //print("Found start of array at {$c}\n");
   859                             //print("Found start of array at {$c}\n");
   818 
   860 
   819                         } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
   861                         } elseif (($chrs[$c] == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
   820                             // found a right-bracket, and we're in an array
   862                             // found a right-bracket, and we're in an array
   821                             array_pop($stk);
   863                             array_pop($stk);
   822                             //print("Found end of array at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
   864                             //print("Found end of array at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
   823 
   865 
   824                         } elseif (($chrs{$c} == '{') &&
   866                         } elseif (($chrs[$c] == '{') &&
   825                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
   867                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
   826                             // found a left-brace, and we are in an array, object, or slice
   868                             // found a left-brace, and we are in an array, object, or slice
   827                             array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
   869                             array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
   828                             //print("Found start of object at {$c}\n");
   870                             //print("Found start of object at {$c}\n");
   829 
   871 
   830                         } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
   872                         } elseif (($chrs[$c] == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
   831                             // found a right-brace, and we're in an object
   873                             // found a right-brace, and we're in an object
   832                             array_pop($stk);
   874                             array_pop($stk);
   833                             //print("Found end of object at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
   875                             //print("Found end of object at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
   834 
   876 
   835                         } elseif (($substr_chrs_c_2 == '/*') &&
   877                         } elseif (($substr_chrs_c_2 == '/*') &&
   864                 }
   906                 }
   865         }
   907         }
   866     }
   908     }
   867 
   909 
   868     /**
   910     /**
       
   911      * @deprecated 5.3.0 Use the PHP native JSON extension instead.
       
   912      *
   869      * @todo Ultimately, this should just call PEAR::isError()
   913      * @todo Ultimately, this should just call PEAR::isError()
   870      */
   914      */
   871     function isError($data, $code = null)
   915     function isError($data, $code = null)
   872     {
   916     {
       
   917         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   918 
   873         if (class_exists('pear')) {
   919         if (class_exists('pear')) {
   874             return PEAR::isError($data, $code);
   920             return PEAR::isError($data, $code);
   875         } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
   921         } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
   876                                  is_subclass_of($data, 'services_json_error'))) {
   922                                  is_subclass_of($data, 'services_json_error'))) {
   877             return true;
   923             return true;
   879 
   925 
   880         return false;
   926         return false;
   881     }
   927     }
   882     
   928     
   883     /**
   929     /**
   884     * Calculates length of string in bytes
   930      * Calculates length of string in bytes
   885     * @param string 
   931      *
   886     * @return integer length
   932      * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   887     */
   933      *
       
   934      * @param string
       
   935      * @return integer length
       
   936      */
   888     function strlen8( $str ) 
   937     function strlen8( $str ) 
   889     {
   938     {
       
   939         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   940 
   890         if ( $this->_mb_strlen ) {
   941         if ( $this->_mb_strlen ) {
   891             return mb_strlen( $str, "8bit" );
   942             return mb_strlen( $str, "8bit" );
   892         }
   943         }
   893         return strlen( $str );
   944         return strlen( $str );
   894     }
   945     }
   895     
   946     
   896     /**
   947     /**
   897     * Returns part of a string, interpreting $start and $length as number of bytes.
   948      * Returns part of a string, interpreting $start and $length as number of bytes.
   898     * @param string 
   949      *
   899     * @param integer start 
   950      * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   900     * @param integer length 
   951      *
   901     * @return integer length
   952      * @param string
   902     */
   953      * @param integer start
       
   954      * @param integer length
       
   955      * @return integer length
       
   956      */
   903     function substr8( $string, $start, $length=false ) 
   957     function substr8( $string, $start, $length=false ) 
   904     {
   958     {
       
   959         _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   960 
   905         if ( $length === false ) {
   961         if ( $length === false ) {
   906             $length = $this->strlen8( $string ) - $start;
   962             $length = $this->strlen8( $string ) - $start;
   907         }
   963         }
   908         if ( $this->_mb_substr ) {
   964         if ( $this->_mb_substr ) {
   909             return mb_substr( $string, $start, $length, "8bit" );
   965             return mb_substr( $string, $start, $length, "8bit" );
   915 
   971 
   916 if (class_exists('PEAR_Error')) {
   972 if (class_exists('PEAR_Error')) {
   917 
   973 
   918     class Services_JSON_Error extends PEAR_Error
   974     class Services_JSON_Error extends PEAR_Error
   919     {
   975     {
       
   976 	    /**
       
   977 	     * PHP5 constructor.
       
   978 	     *
       
   979 	     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
       
   980 	     */
   920         function __construct($message = 'unknown error', $code = null,
   981         function __construct($message = 'unknown error', $code = null,
   921                                      $mode = null, $options = null, $userinfo = null)
   982                                      $mode = null, $options = null, $userinfo = null)
   922         {
   983         {
       
   984             _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
       
   985 
   923             parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
   986             parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
   924         }
   987         }
   925 
   988 
   926 	public function Services_JSON_Error($message = 'unknown error', $code = null,
   989 	    /**
       
   990 	     * PHP4 constructor.
       
   991 	     *
       
   992 	     * @deprecated 5.3.0 Use __construct() instead.
       
   993 	     *
       
   994 	     * @see Services_JSON_Error::__construct()
       
   995 	     */
       
   996 		public function Services_JSON_Error($message = 'unknown error', $code = null,
   927                                      $mode = null, $options = null, $userinfo = null) {
   997                                      $mode = null, $options = null, $userinfo = null) {
   928 		self::__construct($message = 'unknown error', $code = null,
   998 			_deprecated_constructor( 'Services_JSON_Error', '5.3.0', get_class( $this ) );
   929                                      $mode = null, $options = null, $userinfo = null);
   999 			self::__construct($message, $code, $mode, $options, $userinfo);
   930 	}
  1000 		}
   931     }
  1001     }
   932 
  1002 
   933 } else {
  1003 } else {
   934 
  1004 
   935     /**
  1005     /**
   937      */
  1007      */
   938     class Services_JSON_Error
  1008     class Services_JSON_Error
   939     {
  1009     {
   940 	    /**
  1010 	    /**
   941 	     * PHP5 constructor.
  1011 	     * PHP5 constructor.
       
  1012 	     *
       
  1013 	     * @deprecated 5.3.0 Use the PHP native JSON extension instead.
   942 	     */
  1014 	     */
   943         function __construct( $message = 'unknown error', $code = null,
  1015         function __construct( $message = 'unknown error', $code = null,
   944                                      $mode = null, $options = null, $userinfo = null )
  1016                                      $mode = null, $options = null, $userinfo = null )
   945         {
  1017         {
   946 
  1018             _deprecated_function( __METHOD__, '5.3.0', 'The PHP native JSON extension' );
   947         }
  1019         }
   948 
  1020 
   949 	    /**
  1021 	    /**
   950 	     * PHP4 constructor.
  1022 	     * PHP4 constructor.
       
  1023 	     *
       
  1024 	     * @deprecated 5.3.0 Use __construct() instead.
       
  1025 	     *
       
  1026 	     * @see Services_JSON_Error::__construct()
   951 	     */
  1027 	     */
   952 		public function Services_JSON_Error( $message = 'unknown error', $code = null,
  1028 		public function Services_JSON_Error( $message = 'unknown error', $code = null,
   953 	                                     $mode = null, $options = null, $userinfo = null ) {
  1029 	                                     $mode = null, $options = null, $userinfo = null ) {
       
  1030 			_deprecated_constructor( 'Services_JSON_Error', '5.3.0', get_class( $this ) );
   954 			self::__construct( $message, $code, $mode, $options, $userinfo );
  1031 			self::__construct( $message, $code, $mode, $options, $userinfo );
   955 		}
  1032 		}
   956     }
  1033     }
   957     
  1034 
   958 }
  1035 }
   959 
  1036 
   960 endif;
  1037 endif;