From e023cec6663dbed5ee621e6c1519107773ba0853 Mon Sep 17 00:00:00 2001 From: Josh Kadis Date: Fri, 1 Aug 2014 16:36:12 -0400 Subject: [PATCH 1/9] issue 203: test json_last_error() after json_encode() or json_decode() --- lib/class-wp-json-server.php | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index ae2b76bc12..5538351275 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -271,6 +271,13 @@ public function serve_request( $path = null ) { $result = json_encode( $this->prepare_response( $result ) ); + // test for json_encode() error + $json_error_message = $this->get_json_last_error(); + if ( $json_error_message ) { + $json_error_obj = new WP_Error( 'json_encode_error', __( 'json_encode() error: ' . $json_error_message ), array( 'status' => 400 ) ); + $result = $this->error_to_response( $json_error_obj ); + } + if ( isset( $_GET['_jsonp'] ) ) { // Prepend '/**/' to mitigate possible JSONP Flash attacks // http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ @@ -376,6 +383,12 @@ public function dispatch() { if ( $supported & self::ACCEPT_JSON ) { $data = json_decode( $this->get_raw_data(), true ); + // test for json_decode() error + $json_error_message = $this->get_json_last_error(); + if ( $json_error_message ) { + return new WP_Error( 'json_decode_error', __( 'json_decode() error: ' . $json_error_message ), array( 'status' => 400 ) ); + } + if ( $data !== null ) { $args = array_merge( $args, array( 'data' => $data ) ); } @@ -413,6 +426,61 @@ public function dispatch() { return new WP_Error( 'json_no_route', __( 'No route was found matching the URL and request method' ), array( 'status' => 404 ) ); } + /** + * Returns if an error occurred during most recent JSON encode/decode + * + * @return boolean|string Boolean false or string error message + */ + protected function get_json_last_error( ) { + // see https://core.trac.wordpress.org/ticket/27799 + if ( ! function_exists( 'json_last_error' ) ) { + return false; + } + + $last_error_code = json_last_error(); + + // just in case JSON_ERROR_NONE is not defined + $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; + + // return false if no error occurred + if ( $last_error_code === $error_code_none ) { + return false; + } + + // use json_last_error_msg() if available + if ( function_exists( 'json_last_error_msg' ) ) { + return json_last_error_msg(); + } + + // otherwise use built-in constants + if ( defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code ) { + return 'Maximum stack depth exceeded'; + } + elseif ( defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code ) { + return 'Invalid or malformed JSON'; + } + elseif ( defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code ) { + return 'Control character error, possibly incorrectly encoded'; + } + elseif ( defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code ) { + return 'Syntax error'; + } + elseif ( defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code ) { + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + } + elseif ( defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code ) { + return 'One or more recursive references in the value to be encoded'; + } + elseif ( defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code ) { + return 'One or more NAN or INF values in the value to be encoded'; + } + elseif ( defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code ) { + return 'A value of a type that cannot be encoded was given'; + } else { + return 'An unknown error occurred'; + } + } + /** * Sort parameters by order specified in method declaration * From fb682bb474582581d712b5f6ee384f69a8184718 Mon Sep 17 00:00:00 2001 From: Josh Kadis Date: Mon, 11 Aug 2014 16:19:13 -0700 Subject: [PATCH 2/9] move json_encode/decode error translation to get_json_last_error() method --- lib/class-wp-json-server.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index de7e4f350b..ef859d083f 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -275,7 +275,7 @@ public function serve_request( $path = null ) { // test for json_encode() error $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { - $json_error_obj = new WP_Error( 'json_encode_error', __( 'json_encode() error: ' . $json_error_message ), array( 'status' => 400 ) ); + $json_error_obj = new WP_Error( 'json_encode_error', 'json_encode() error: ' . $json_error_message, array( 'status' => 400 ) ); $result = $this->error_to_response( $json_error_obj ); } @@ -387,7 +387,7 @@ public function dispatch() { // test for json_decode() error $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { - return new WP_Error( 'json_decode_error', __( 'json_decode() error: ' . $json_error_message ), array( 'status' => 400 ) ); + return new WP_Error( 'json_decode_error', 'json_decode() error: ' . $json_error_message, array( 'status' => 400 ) ); } if ( $data !== null ) { @@ -450,35 +450,36 @@ protected function get_json_last_error( ) { // use json_last_error_msg() if available if ( function_exists( 'json_last_error_msg' ) ) { - return json_last_error_msg(); + $error_message = json_last_error_msg(); + return __( sprintf( '%s', $error_message ) ); } // otherwise use built-in constants if ( defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code ) { - return 'Maximum stack depth exceeded'; + return __( 'Maximum stack depth exceeded' ); } elseif ( defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code ) { - return 'Invalid or malformed JSON'; + return __( 'Invalid or malformed JSON' ); } elseif ( defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code ) { - return 'Control character error, possibly incorrectly encoded'; + return __( 'Control character error, possibly incorrectly encoded' ); } elseif ( defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code ) { - return 'Syntax error'; + return __( 'Syntax error' ); } elseif ( defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code ) { - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + return __( 'Malformed UTF-8 characters, possibly incorrectly encoded' ); } elseif ( defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code ) { - return 'One or more recursive references in the value to be encoded'; + return __( 'One or more recursive references in the value to be encoded' ); } elseif ( defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code ) { - return 'One or more NAN or INF values in the value to be encoded'; + return __( 'One or more NAN or INF values in the value to be encoded' ); } elseif ( defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code ) { - return 'A value of a type that cannot be encoded was given'; + return __( 'A value of a type that cannot be encoded was given' ); } else { - return 'An unknown error occurred'; + return __( 'An unknown error occurred' ); } } From 7d01c96a0840bbc7ff5b5ba98c337dcc76a8f416 Mon Sep 17 00:00:00 2001 From: Josh Kadis Date: Mon, 11 Aug 2014 16:31:39 -0700 Subject: [PATCH 3/9] return JSON encoded error inside serve_request() --- lib/class-wp-json-server.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index ef859d083f..d3b79c77ea 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -277,6 +277,7 @@ public function serve_request( $path = null ) { if ( $json_error_message ) { $json_error_obj = new WP_Error( 'json_encode_error', 'json_encode() error: ' . $json_error_message, array( 'status' => 400 ) ); $result = $this->error_to_response( $json_error_obj ); + $result = json_encode( $result->data[0] ); } if ( isset( $_GET['_jsonp'] ) ) { From 833d32e869bab2cb701604b4a4813a74368da8d1 Mon Sep 17 00:00:00 2001 From: Josh Kadis Date: Thu, 14 Aug 2014 09:57:29 -0700 Subject: [PATCH 4/9] fix status headers and move all translation into WP_JSON_Server::get_json_last_error(), then change to switch() statement for returning --- lib/class-wp-json-server.php | 89 +++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index d3b79c77ea..6803c2db50 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -275,7 +275,7 @@ public function serve_request( $path = null ) { // test for json_encode() error $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { - $json_error_obj = new WP_Error( 'json_encode_error', 'json_encode() error: ' . $json_error_message, array( 'status' => 400 ) ); + $json_error_obj = new WP_Error( 'json_encode_error', $json_error_message, array( 'status' => 500 ) ); $result = $this->error_to_response( $json_error_obj ); $result = json_encode( $result->data[0] ); } @@ -388,7 +388,7 @@ public function dispatch() { // test for json_decode() error $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { - return new WP_Error( 'json_decode_error', 'json_decode() error: ' . $json_error_message, array( 'status' => 400 ) ); + return new WP_Error( 'json_decode_error', $json_error_message, array( 'status' => 500 ) ); } if ( $data !== null ) { @@ -430,6 +430,7 @@ public function dispatch() { /** * Returns if an error occurred during most recent JSON encode/decode + * Strings to be translated will be in format like "Encoding error: Maximum stack depth exceeded" * * @return boolean|string Boolean false or string error message */ @@ -443,44 +444,58 @@ protected function get_json_last_error( ) { // just in case JSON_ERROR_NONE is not defined $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; + + // prefix error messages with this string + $error_message_prefix = 'Encoding error:'; + + switch ( true ) { - // return false if no error occurred - if ( $last_error_code === $error_code_none ) { - return false; - } + // return false if no error occurred + case $last_error_code === $error_code_none : + return false; + break; - // use json_last_error_msg() if available - if ( function_exists( 'json_last_error_msg' ) ) { - $error_message = json_last_error_msg(); - return __( sprintf( '%s', $error_message ) ); - } + // use json_last_error_msg() if available + case function_exists( 'json_last_error_msg' ) : + $error_message = json_last_error_msg(); + return __( sprintf( '%s %s', $error_message_prefix, $error_message ) ); + break; - // otherwise use built-in constants - if ( defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code ) { - return __( 'Maximum stack depth exceeded' ); - } - elseif ( defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code ) { - return __( 'Invalid or malformed JSON' ); - } - elseif ( defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code ) { - return __( 'Control character error, possibly incorrectly encoded' ); - } - elseif ( defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code ) { - return __( 'Syntax error' ); - } - elseif ( defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code ) { - return __( 'Malformed UTF-8 characters, possibly incorrectly encoded' ); - } - elseif ( defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code ) { - return __( 'One or more recursive references in the value to be encoded' ); - } - elseif ( defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code ) { - return __( 'One or more NAN or INF values in the value to be encoded' ); - } - elseif ( defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code ) { - return __( 'A value of a type that cannot be encoded was given' ); - } else { - return __( 'An unknown error occurred' ); + // otherwise use built-in constants + case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : + return __( sprintf( '%s Maximum stack depth exceeded', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : + return __( sprintf( '%s Invalid or malformed JSON', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : + return __( sprintf( '%s Control character error, possibly incorrectly encoded', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : + return __( sprintf( '%s Syntax error', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : + return __( sprintf( '%s Malformed UTF-8 characters, possibly incorrectly encoded', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : + return __( sprintf( '%s One or more recursive references in the value to be encoded', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : + return __( sprintf( '%s One or more NAN or INF values in the value to be encoded', $error_message_prefix ) ); + break; + + case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : + return __( sprintf( '%s A value of a type that cannot be encoded was given', $error_message_prefix ) ); + break; + + default : + return __( sprintf( '%s An unknown error occurred', $error_message_prefix ) ); } } From 4ea3247b9f59596dc8db50d061fc33a09d229103 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Fri, 29 Aug 2014 14:11:49 +1000 Subject: [PATCH 5/9] Correct error message string formatting --- lib/class-wp-json-server.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index 6803c2db50..bc1720110d 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -446,7 +446,7 @@ protected function get_json_last_error( ) { $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; // prefix error messages with this string - $error_message_prefix = 'Encoding error:'; + $error_message_prefix = __( 'Encoding error: %s' ); switch ( true ) { @@ -458,44 +458,44 @@ protected function get_json_last_error( ) { // use json_last_error_msg() if available case function_exists( 'json_last_error_msg' ) : $error_message = json_last_error_msg(); - return __( sprintf( '%s %s', $error_message_prefix, $error_message ) ); + return sprintf( $error_message_prefix, $error_message ); break; // otherwise use built-in constants case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : - return __( sprintf( '%s Maximum stack depth exceeded', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'Maximum stack depth exceeded' ); break; case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : - return __( sprintf( '%s Invalid or malformed JSON', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'Invalid or malformed JSON' ); break; case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : - return __( sprintf( '%s Control character error, possibly incorrectly encoded', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'Control character error, possibly incorrectly encoded' ); break; case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : - return __( sprintf( '%s Syntax error', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'Syntax error' ); break; case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : - return __( sprintf( '%s Malformed UTF-8 characters, possibly incorrectly encoded', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'Malformed UTF-8 characters, possibly incorrectly encoded' ); break; case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : - return __( sprintf( '%s One or more recursive references in the value to be encoded', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'One or more recursive references in the value to be encoded' ); break; case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : - return __( sprintf( '%s One or more NAN or INF values in the value to be encoded', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'One or more NAN or INF values in the value to be encoded' ); break; case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : - return __( sprintf( '%s A value of a type that cannot be encoded was given', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'A value of a type that cannot be encoded was given' ); break; default : - return __( sprintf( '%s An unknown error occurred', $error_message_prefix ) ); + return sprintf( $error_message_prefix, 'An unknown error occurred' ); } } From 99d67c1ad2a185500996407caf7bbb4f12ba6bda Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Fri, 29 Aug 2014 14:15:12 +1000 Subject: [PATCH 6/9] Correct switch formatting and indentation --- lib/class-wp-json-server.php | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index bc1720110d..cb0f94c1ee 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -272,7 +272,6 @@ public function serve_request( $path = null ) { $result = json_encode( $this->prepare_response( $result ) ); - // test for json_encode() error $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { $json_error_obj = new WP_Error( 'json_encode_error', $json_error_message, array( 'status' => 500 ) ); @@ -444,55 +443,45 @@ protected function get_json_last_error( ) { // just in case JSON_ERROR_NONE is not defined $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; - + // prefix error messages with this string $error_message_prefix = __( 'Encoding error: %s' ); - + switch ( true ) { // return false if no error occurred case $last_error_code === $error_code_none : return false; - break; // use json_last_error_msg() if available case function_exists( 'json_last_error_msg' ) : $error_message = json_last_error_msg(); return sprintf( $error_message_prefix, $error_message ); - break; // otherwise use built-in constants case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : return sprintf( $error_message_prefix, 'Maximum stack depth exceeded' ); - break; case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : return sprintf( $error_message_prefix, 'Invalid or malformed JSON' ); - break; case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : return sprintf( $error_message_prefix, 'Control character error, possibly incorrectly encoded' ); - break; case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : return sprintf( $error_message_prefix, 'Syntax error' ); - break; case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : return sprintf( $error_message_prefix, 'Malformed UTF-8 characters, possibly incorrectly encoded' ); - break; case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : return sprintf( $error_message_prefix, 'One or more recursive references in the value to be encoded' ); - break; case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : return sprintf( $error_message_prefix, 'One or more NAN or INF values in the value to be encoded' ); - break; case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : return sprintf( $error_message_prefix, 'A value of a type that cannot be encoded was given' ); - break; default : return sprintf( $error_message_prefix, 'An unknown error occurred' ); From 0723cc08f3d1b45140d247a1daf4801d3eac566d Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Fri, 29 Aug 2014 14:19:35 +1000 Subject: [PATCH 7/9] Don't prefix error messages Totally changed my mind on this, since they're included in the code. --- lib/class-wp-json-server.php | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index cb0f94c1ee..d755328b48 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -444,9 +444,6 @@ protected function get_json_last_error( ) { // just in case JSON_ERROR_NONE is not defined $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; - // prefix error messages with this string - $error_message_prefix = __( 'Encoding error: %s' ); - switch ( true ) { // return false if no error occurred @@ -455,36 +452,35 @@ protected function get_json_last_error( ) { // use json_last_error_msg() if available case function_exists( 'json_last_error_msg' ) : - $error_message = json_last_error_msg(); - return sprintf( $error_message_prefix, $error_message ); + return json_last_error_msg(); // otherwise use built-in constants case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : - return sprintf( $error_message_prefix, 'Maximum stack depth exceeded' ); + return 'Maximum stack depth exceeded'; case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : - return sprintf( $error_message_prefix, 'Invalid or malformed JSON' ); + return 'Invalid or malformed JSON'; case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : - return sprintf( $error_message_prefix, 'Control character error, possibly incorrectly encoded' ); + return 'Control character error, possibly incorrectly encoded'; case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : - return sprintf( $error_message_prefix, 'Syntax error' ); + return 'Syntax error'; case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : - return sprintf( $error_message_prefix, 'Malformed UTF-8 characters, possibly incorrectly encoded' ); + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : - return sprintf( $error_message_prefix, 'One or more recursive references in the value to be encoded' ); + return 'One or more recursive references in the value to be encoded'; case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : - return sprintf( $error_message_prefix, 'One or more NAN or INF values in the value to be encoded' ); + return 'One or more NAN or INF values in the value to be encoded'; case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : - return sprintf( $error_message_prefix, 'A value of a type that cannot be encoded was given' ); + return 'A value of a type that cannot be encoded was given'; default : - return sprintf( $error_message_prefix, 'An unknown error occurred' ); + return 'An unknown error occurred'; } } From 48f2da21949969afa13640a33bcae9b055328c39 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Fri, 29 Aug 2014 14:33:01 +1000 Subject: [PATCH 8/9] Split error handling into two functions Splits the actual error message generator into json_last_error_msg(), which has full compatibility with PHP 5.5's function. Note: error messages updated to match PHP source; see https://github.com/php/php-src/blob/b2d2b965b2ddb2e013a15a8858420f18614562a9/ext/json/json.c#L840-L872 --- lib/class-wp-json-server.php | 45 +++--------------------------- plugin.php | 53 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/lib/class-wp-json-server.php b/lib/class-wp-json-server.php index d755328b48..f8f2823c86 100644 --- a/lib/class-wp-json-server.php +++ b/lib/class-wp-json-server.php @@ -440,48 +440,11 @@ protected function get_json_last_error( ) { } $last_error_code = json_last_error(); - - // just in case JSON_ERROR_NONE is not defined - $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; - - switch ( true ) { - - // return false if no error occurred - case $last_error_code === $error_code_none : - return false; - - // use json_last_error_msg() if available - case function_exists( 'json_last_error_msg' ) : - return json_last_error_msg(); - - // otherwise use built-in constants - case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : - return 'Maximum stack depth exceeded'; - - case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : - return 'Invalid or malformed JSON'; - - case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : - return 'Control character error, possibly incorrectly encoded'; - - case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : - return 'Syntax error'; - - case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - - case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : - return 'One or more recursive references in the value to be encoded'; - - case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : - return 'One or more NAN or INF values in the value to be encoded'; - - case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : - return 'A value of a type that cannot be encoded was given'; - - default : - return 'An unknown error occurred'; + if ( ( defined( 'JSON_ERROR_NONE' ) && $last_error_code === JSON_ERROR_NONE ) || empty( $last_error_code ) ) { + return false; } + + return json_last_error_msg(); } /** diff --git a/plugin.php b/plugin.php index 04c0be125e..a32962e156 100644 --- a/plugin.php +++ b/plugin.php @@ -621,3 +621,56 @@ function json_handle_deprecated_argument( $function, $message, $version ) { header( sprintf( 'X-WP-DeprecatedParam: %s', $string ) ); } + +if ( ! function_exists( 'json_last_error_msg' ) ): +/** + * Returns the error string of the last json_encode() or json_decode() call + * + * @internal This is a compatibility function for PHP <5.5 + * + * @return boolean|string Returns the error message on success, "No Error" if no error has occurred, or FALSE on failure. + */ +function json_last_error_msg() { + // see https://core.trac.wordpress.org/ticket/27799 + if ( ! function_exists( 'json_last_error' ) ) { + return false; + } + + $last_error_code = json_last_error(); + + // just in case JSON_ERROR_NONE is not defined + $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; + + switch ( true ) { + case $last_error_code === $error_code_none : + return 'No error'; + + case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : + return 'Maximum stack depth exceeded'; + + case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : + return 'State mismatch (invalid or malformed JSON)'; + + case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : + return 'Control character error, possibly incorrectly encoded'; + + case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : + return 'Syntax error'; + + case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + + case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : + return 'Recursion detected'; + + case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : + return 'Inf and NaN cannot be JSON encoded'; + + case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : + return 'Type is not supported'; + + default : + return 'An unknown error occurred'; + } +} +endif; From 5fbcc3562a1870ebc9ca7c62e0a88308273f1135 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Fri, 29 Aug 2014 15:14:16 +1000 Subject: [PATCH 9/9] Tweak switch for coding standards --- plugin.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugin.php b/plugin.php index a32962e156..640844b6f9 100644 --- a/plugin.php +++ b/plugin.php @@ -642,34 +642,34 @@ function json_last_error_msg() { $error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0; switch ( true ) { - case $last_error_code === $error_code_none : + case $last_error_code === $error_code_none: return 'No error'; - case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code : + case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code: return 'Maximum stack depth exceeded'; - case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code : + case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code: return 'State mismatch (invalid or malformed JSON)'; - case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code : + case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code: return 'Control character error, possibly incorrectly encoded'; - case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code : + case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code: return 'Syntax error'; - case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code : + case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code: return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code : + case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code: return 'Recursion detected'; - case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code : + case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code: return 'Inf and NaN cannot be JSON encoded'; - case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code : + case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code: return 'Type is not supported'; - default : + default: return 'An unknown error occurred'; } }