From 55d58c86667a47ec396e27bb01942a55643c8aa1 Mon Sep 17 00:00:00 2001
From: robocoder <anthon.pang@gmail.com>
Date: Sun, 13 Nov 2011 18:32:25 +0000
Subject: [PATCH] fixes #2735

git-svn-id: http://dev.piwik.org/svn/trunk@5432 59fd770c-687e-43c8-a1e3-f5a4ff64c105
---
 core/Common.php                             |  69 ++++
 core/DataTable/Renderer/Json.php            |   4 +-
 core/Tracker/GoalManager.php                |   2 +-
 core/Tracker/Visit.php                      |   2 +-
 core/Visualization/Chart.php                |   2 +-
 libs/upgradephp/upgrade.php                 | 376 ++++++++++----------
 plugins/CustomVariables/CustomVariables.php |   2 +-
 plugins/Dashboard/Controller.php            |   8 +-
 plugins/Goals/Controller.php                |  18 +-
 plugins/PDFReports/Controller.php           |   2 +-
 plugins/SitesManager/Controller.php         |   6 +-
 plugins/Widgetize/Controller.php            |   2 +-
 12 files changed, 284 insertions(+), 209 deletions(-)

diff --git a/core/Common.php b/core/Common.php
index a75e151269..c30d451084 100644
--- a/core/Common.php
+++ b/core/Common.php
@@ -1035,6 +1035,75 @@ class Piwik_Common
 		return Piwik_IP::long2ip($ip);
 	}
 
+	/**
+	 * Should we use the replacement json_encode/json_decode functions?
+	 *
+	 * @return bool True if broken; false otherwise
+	 */
+	static private function useJsonLibrary()
+	{
+		static $useLib;
+
+		if (!isset($useLib))
+		{
+			/*
+			 * 5.1.x - doesn't have json extension; we use lib/upgradephp instead
+			 * 5.2 to 5.2.4 - broken in various ways, including:
+			 *
+			 * @see https://bugs.php.net/bug.php?id=38680 'json_decode cannot decode basic types'
+			 * @see https://bugs.php.net/bug.php?id=41403 'json_decode cannot decode floats'
+			 * @see https://bugs.php.net/bug.php?id=42785 'json_encode outputs numbers according to locale'
+			 */
+			$useLib = false;
+			if (version_compare(PHP_VERSION, '5.2.1') < 0)
+			{
+				$useLib = true;
+			}
+			else if (version_compare(PHP_VERSION, '5.2.5') < 0)
+			{
+				$info = localeconv();
+				$useLib = $info['decimal_point'] != '.';
+			}
+		}
+
+		return $useLib;
+	}
+
+	/**
+	 * JSON encode wrapper
+	 * - missing or broken in some php 5.x versions
+	 *
+	 * @param mixed $value
+	 * @return string
+	 */
+	static public function json_encode($value)
+	{
+		if (self::useJsonLibrary())
+		{
+			return _json_encode($value);
+		}
+
+		return json_encode($value);
+	}
+
+	/**
+	 * JSON decode wrapper
+	 * - missing or broken in some php 5.x versions
+	 *
+	 * @param string $json
+	 * @param bool $assoc
+	 * @return mixed
+	 */
+	static public function json_decode($json, $assoc = false)
+	{
+		if (self::useJsonLibrary())
+		{
+			return _json_decode($json, $assoc);
+		}
+
+		return json_decode($json, $assoc);
+	}
+
 /*
  * DataFiles
  */
diff --git a/core/DataTable/Renderer/Json.php b/core/DataTable/Renderer/Json.php
index 57aa01ce70..ee991b74f5 100644
--- a/core/DataTable/Renderer/Json.php
+++ b/core/DataTable/Renderer/Json.php
@@ -11,7 +11,7 @@
  */
 
 /**
- * JSON export. Using the php 5.2 feature json_encode.
+ * JSON export.
  * Works with recursive DataTable (when a row can be associated with a subDataTable).
  * 
  * @package Piwik
@@ -54,7 +54,7 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer
 		$callback = create_function('&$value,$key', 'if(is_string($value)){$value = html_entity_decode($value, ENT_QUOTES, "UTF-8");}');
 		array_walk_recursive($array, $callback);
 		
-		$str = json_encode($array);
+		$str = Piwik_Common::json_encode($array);
 		
 		return $this->jsonpWrap($str);
 	}
diff --git a/core/Tracker/GoalManager.php b/core/Tracker/GoalManager.php
index 3542e9b638..70ff6f7f1d 100644
--- a/core/Tracker/GoalManager.php
+++ b/core/Tracker/GoalManager.php
@@ -416,7 +416,7 @@ class Piwik_Tracker_GoalManager
 			// we still record an Ecommerce order without any item in it
 			return array();
 		}
-		$items = json_decode($items, $assoc = true);
+		$items = Piwik_Common::json_decode($items, $assoc = true);
 		if(!is_array($items))
 		{
 			printDebug("Error while json_decode the Ecommerce items = ".var_export($items, true));
diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php
index 0053672271..c41035e91e 100644
--- a/core/Tracker/Visit.php
+++ b/core/Tracker/Visit.php
@@ -1044,7 +1044,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
 		}
 		
 		$customVar = Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar( $parameter, '', 'string', $request));
-		$customVar = @json_decode($customVar, $assoc = true);
+		$customVar = @Piwik_Common::json_decode($customVar, $assoc = true);
 
 		if(!is_array($customVar))
 		{
diff --git a/core/Visualization/Chart.php b/core/Visualization/Chart.php
index 4541176686..5b161b902b 100644
--- a/core/Visualization/Chart.php
+++ b/core/Visualization/Chart.php
@@ -156,7 +156,7 @@ abstract class Piwik_Visualization_Chart implements Piwik_View_Interface
 			'seriesPicker' => &$this->seriesPicker
 		);
 		
-		return json_encode($data);
+		return Piwik_Common::json_encode($data);
 	}
 	
 	public function customizeChartProperties()
diff --git a/libs/upgradephp/upgrade.php b/libs/upgradephp/upgrade.php
index 90677cf8c8..57204a5547 100644
--- a/libs/upgradephp/upgrade.php
+++ b/libs/upgradephp/upgrade.php
@@ -106,75 +106,78 @@ if(!defined('E_USER_DEPRECATED')) {   define('E_USER_DEPRECATED', 16384); }
  * @param  $var mixed  PHP variable/array/object
  * @return string      transformed into JSON equivalent
  */
-if (!function_exists("json_encode")) {
-   function json_encode($var, /*emu_args*/$obj=FALSE) {
-   
-      #-- handle locale differences
-      $locale = localeconv();
+function _json_encode($var, /*emu_args*/$obj=FALSE) {
 
-      #-- prepare JSON string
-      $json = "";
-      
-      #-- add array entries
-      if (is_array($var) || ($obj=is_object($var))) {
-
-         #-- check if array is associative
-         if (!$obj) {
-            $expect = 0;
-            foreach ((array)$var as $i=>$v) {
-               if (!is_int($i) || $i !== $expect++) {
-                  $obj = 1;
-                  break;
-               }
-            }
-         }
+   #-- handle locale differences
+   $locale = localeconv();
 
-         #-- concat invidual entries
+   #-- prepare JSON string
+   $json = "";
+   
+   #-- add array entries
+   if (is_array($var) || ($obj=is_object($var))) {
+
+      #-- check if array is associative
+      if (!$obj) {
+         $expect = 0;
          foreach ((array)$var as $i=>$v) {
-            $json .= ($json !== '' ? "," : "")    // comma separators
-                   . ($obj ? ("\"$i\":") : "")   // assoc prefix
-                   . (json_encode($v));    // value
+            if (!is_int($i) || $i !== $expect++) {
+               $obj = 1;
+               break;
+            }
          }
-
-         #-- enclose into braces or brackets
-         $json = $obj ? "{".$json."}" : "[".$json."]";
       }
 
-      #-- strings need some care
-      elseif (is_string($var)) {
-         if (!utf8_decode($var)) {
-            $var = utf8_encode($var);
-         }
-         $var = str_replace(array("\\", "\"", "/", "\b", "\f", "\n", "\r", "\t"), array("\\\\", '\"', "\\/", "\\b", "\\f", "\\n", "\\r", "\\t"), $var);
-         $json = '"' . $var . '"';
-         //@COMPAT: for fully-fully-compliance   $var = preg_replace("/[\000-\037]/", "", $var);
+      #-- concat invidual entries
+      foreach ((array)$var as $i=>$v) {
+         $json .= ($json !== '' ? "," : "")    // comma separators
+                . ($obj ? ("\"$i\":") : "")   // assoc prefix
+                . (json_encode($v));    // value
       }
 
-      #-- basic types
-      elseif (is_bool($var)) {
-         $json = $var ? "true" : "false";
-      }
-      elseif ($var === NULL) {
-         $json = "null";
-      }
-      elseif (is_int($var)) {
-         $json = "$var";
-      }
-      elseif (is_float($var)) {
-         $json = str_replace(
-            array($locale['mon_thousands_sep'], $locale['mon_decimal_point']),
-            array('', '.'),
-            $var
-         );
-      }
+      #-- enclose into braces or brackets
+      $json = $obj ? "{".$json."}" : "[".$json."]";
+   }
 
-      #-- something went wrong
-      else {
-         trigger_error("json_encode: don't know what a '" .gettype($var). "' is.", E_USER_ERROR);
+   #-- strings need some care
+   elseif (is_string($var)) {
+      if (!utf8_decode($var)) {
+         $var = utf8_encode($var);
       }
-      
-      #-- done
-      return($json);
+      $var = str_replace(array("\\", "\"", "/", "\b", "\f", "\n", "\r", "\t"), array("\\\\", '\"', "\\/", "\\b", "\\f", "\\n", "\\r", "\\t"), $var);
+      $json = '"' . $var . '"';
+      //@COMPAT: for fully-fully-compliance   $var = preg_replace("/[\000-\037]/", "", $var);
+   }
+
+   #-- basic types
+   elseif (is_bool($var)) {
+      $json = $var ? "true" : "false";
+   }
+   elseif ($var === NULL) {
+      $json = "null";
+   }
+   elseif (is_int($var)) {
+      $json = "$var";
+   }
+   elseif (is_float($var)) {
+      $json = str_replace(
+         array($locale['mon_thousands_sep'], $locale['mon_decimal_point']),
+         array('', '.'),
+         $var
+      );
+   }
+
+   #-- something went wrong
+   else {
+      trigger_error("json_encode: don't know what a '" .gettype($var). "' is.", E_USER_ERROR);
+   }
+   
+   #-- done
+   return($json);
+}
+if (!function_exists("json_encode")) {
+   function json_encode($var, /*emu_args*/$obj=FALSE) {
+      return _json_encode($var);
    }
 }
 
@@ -198,161 +201,164 @@ if (!function_exists("json_encode")) {
  * @param   $assoc bool    (optional) if outer shell should be decoded as object always
  * @return  mixed          parsed into PHP variable/array/object
  */
-if (!function_exists("json_decode")) {
-   function json_decode($json, $assoc=FALSE, /*emu_args*/$n=0,$state=0,$waitfor=0) {
+function _json_decode($json, $assoc=FALSE, /*emu_args*/$n=0,$state=0,$waitfor=0) {
 
-      #-- result var
-      $val = NULL;
-      static $lang_eq = array("true" => TRUE, "false" => FALSE, "null" => NULL);
-      static $str_eq = array("n"=>"\012", "r"=>"\015", "\\"=>"\\", '"'=>'"', "f"=>"\f", "b"=>"\b", "t"=>"\t", "/"=>"/");
+   #-- result var
+   $val = NULL;
+   static $lang_eq = array("true" => TRUE, "false" => FALSE, "null" => NULL);
+   static $str_eq = array("n"=>"\012", "r"=>"\015", "\\"=>"\\", '"'=>'"', "f"=>"\f", "b"=>"\b", "t"=>"\t", "/"=>"/");
 
-      #-- flat char-wise parsing
-      for (/*n*/; $n<strlen($json); /*n*/) {
-         $c = $json[$n];
+   #-- flat char-wise parsing
+   for (/*n*/; $n<strlen($json); /*n*/) {
+      $c = $json[$n];
 
-         #-= in-string
-         if ($state==='"') {
+      #-= in-string
+      if ($state==='"') {
 
-            if ($c == '\\') {
-               $c = $json[++$n];
-               // simple C escapes
-               if (isset($str_eq[$c])) {
-                  $val .= $str_eq[$c];
-               }
+         if ($c == '\\') {
+            $c = $json[++$n];
+            // simple C escapes
+            if (isset($str_eq[$c])) {
+               $val .= $str_eq[$c];
+            }
 
-               // here we transform \uXXXX Unicode (always 4 nibbles) references to UTF-8
-               elseif ($c == "u") {
-                  // read just 16bit (therefore value can't be negative)
-                  $hex = hexdec( substr($json, $n+1, 4) );
-                  $n += 4;
-                  // Unicode ranges
-                  if ($hex < 0x80) {    // plain ASCII character
-                     $val .= chr($hex);
-                  }
-                  elseif ($hex < 0x800) {   // 110xxxxx 10xxxxxx 
-                     $val .= chr(0xC0 + $hex>>6) . chr(0x80 + $hex&63);
-                  }
-                  elseif ($hex <= 0xFFFF) { // 1110xxxx 10xxxxxx 10xxxxxx 
-                     $val .= chr(0xE0 + $hex>>12) . chr(0x80 + ($hex>>6)&63) . chr(0x80 + $hex&63);
-                  }
-                  // other ranges, like 0x1FFFFF=0xF0, 0x3FFFFFF=0xF8 and 0x7FFFFFFF=0xFC do not apply
+            // here we transform \uXXXX Unicode (always 4 nibbles) references to UTF-8
+            elseif ($c == "u") {
+               // read just 16bit (therefore value can't be negative)
+               $hex = hexdec( substr($json, $n+1, 4) );
+               $n += 4;
+               // Unicode ranges
+               if ($hex < 0x80) {    // plain ASCII character
+                  $val .= chr($hex);
                }
-
-               // no escape, just a redundant backslash
-               //@COMPAT: we could throw an exception here
-               else {
-                  $val .= "\\" . $c;
+               elseif ($hex < 0x800) {   // 110xxxxx 10xxxxxx 
+                  $val .= chr(0xC0 + $hex>>6) . chr(0x80 + $hex&63);
+               }
+               elseif ($hex <= 0xFFFF) { // 1110xxxx 10xxxxxx 10xxxxxx 
+                  $val .= chr(0xE0 + $hex>>12) . chr(0x80 + ($hex>>6)&63) . chr(0x80 + $hex&63);
                }
+               // other ranges, like 0x1FFFFF=0xF0, 0x3FFFFFF=0xF8 and 0x7FFFFFFF=0xFC do not apply
             }
 
-            // end of string
-            elseif ($c == '"') {
-               $state = 0;
+            // no escape, just a redundant backslash
+            //@COMPAT: we could throw an exception here
+            else {
+               $val .= "\\" . $c;
             }
+         }
 
-            // yeeha! a single character found!!!!1!
-            else/*if (ord($c) >= 32)*/ { //@COMPAT: specialchars check - but native json doesn't do it?
-               $val .= $c;
-            }
+         // end of string
+         elseif ($c == '"') {
+            $state = 0;
          }
 
-         #-> end of sub-call (array/object)
-         elseif ($waitfor && (strpos($waitfor, $c) !== false)) {
-            return array($val, $n);  // return current value and state
+         // yeeha! a single character found!!!!1!
+         else/*if (ord($c) >= 32)*/ { //@COMPAT: specialchars check - but native json doesn't do it?
+            $val .= $c;
          }
-         
-         #-= in-array
-         elseif ($state===']') {
-            list($v, $n) = json_decode($json, 0, $n, 0, ",]");
-            $val[] = $v;
-            if ($json[$n] == "]") { return array($val, $n); }
+      }
+
+      #-> end of sub-call (array/object)
+      elseif ($waitfor && (strpos($waitfor, $c) !== false)) {
+         return array($val, $n);  // return current value and state
+      }
+      
+      #-= in-array
+      elseif ($state===']') {
+         list($v, $n) = json_decode($json, 0, $n, 0, ",]");
+         $val[] = $v;
+         if ($json[$n] == "]") { return array($val, $n); }
+      }
+
+      #-= in-object
+      elseif ($state==='}') {
+         list($i, $n) = json_decode($json, 0, $n, 0, ":");   // this allowed non-string indicies
+         list($v, $n) = json_decode($json, $assoc, $n+1, 0, ",}");
+         $val[$i] = $v;
+         if ($json[$n] == "}") { return array($val, $n); }
+      }
+
+      #-- looking for next item (0)
+      else {
+      
+         #-> whitespace
+         if (preg_match("/\s/", $c)) {
+            // skip
          }
 
-         #-= in-object
-         elseif ($state==='}') {
-            list($i, $n) = json_decode($json, 0, $n, 0, ":");   // this allowed non-string indicies
-            list($v, $n) = json_decode($json, $assoc, $n+1, 0, ",}");
-            $val[$i] = $v;
-            if ($json[$n] == "}") { return array($val, $n); }
+         #-> string begin
+         elseif ($c == '"') {
+            $state = '"';
          }
 
-         #-- looking for next item (0)
-         else {
-         
-            #-> whitespace
-            if (preg_match("/\s/", $c)) {
-               // skip
+         #-> object
+         elseif ($c == "{") {
+            list($val, $n) = json_decode($json, $assoc, $n+1, '}', "}");
+            if ($val && $n && !$assoc) {
+               $obj = new stdClass();
+               foreach ($val as $i=>$v) {
+                  $obj->{$i} = $v;
+               }
+               $val = $obj;
+               unset($obj);
             }
+         }
+         #-> array
+         elseif ($c == "[") {
+            list($val, $n) = json_decode($json, $assoc, $n+1, ']', "]");
+         }
 
-            #-> string begin
-            elseif ($c == '"') {
-               $state = '"';
-            }
+         #-> comment
+         elseif (($c == "/") && ($json[$n+1]=="*")) {
+            // just find end, skip over
+            ($n = strpos($json, "*/", $n+1)) or ($n = strlen($json));
+         }
 
-            #-> object
-            elseif ($c == "{") {
-               list($val, $n) = json_decode($json, $assoc, $n+1, '}', "}");
-               if ($val && $n && !$assoc) {
-                  $obj = new stdClass();
-                  foreach ($val as $i=>$v) {
-                     $obj->{$i} = $v;
-                  }
-                  $val = $obj;
-                  unset($obj);
-               }
+         #-> numbers
+         elseif (preg_match("#^(-?\d+(?:\.\d+)?)(?:[eE]([-+]?\d+))?#", substr($json, $n), $uu)) {
+            $val = $uu[1];
+            $n += strlen($uu[0]) - 1;
+            if (strpos($val, ".")) {  // float
+               $val = (float)$val;
             }
-            #-> array
-            elseif ($c == "[") {
-               list($val, $n) = json_decode($json, $assoc, $n+1, ']', "]");
+            elseif ($val[0] == "0") {  // oct
+               $val = octdec($val);
             }
-
-            #-> comment
-            elseif (($c == "/") && ($json[$n+1]=="*")) {
-               // just find end, skip over
-               ($n = strpos($json, "*/", $n+1)) or ($n = strlen($json));
+            else {
+               $val = (int)$val;
             }
-
-            #-> numbers
-            elseif (preg_match("#^(-?\d+(?:\.\d+)?)(?:[eE]([-+]?\d+))?#", substr($json, $n), $uu)) {
-               $val = $uu[1];
-               $n += strlen($uu[0]) - 1;
-               if (strpos($val, ".")) {  // float
-                  $val = (float)$val;
-               }
-               elseif ($val[0] == "0") {  // oct
-                  $val = octdec($val);
-               }
-               else {
-                  $val = (int)$val;
-               }
-               // exponent?
-               if (isset($uu[2])) {
-                  $val *= pow(10, (int)$uu[2]);
-               }
+            // exponent?
+            if (isset($uu[2])) {
+               $val *= pow(10, (int)$uu[2]);
             }
+         }
 
-            #-> boolean or null
-            elseif (preg_match("#^(true|false|null)\b#", substr($json, $n), $uu)) {
-               $val = $lang_eq[$uu[1]];
-               $n += strlen($uu[1]) - 1;
-            }
+         #-> boolean or null
+         elseif (preg_match("#^(true|false|null)\b#", substr($json, $n), $uu)) {
+            $val = $lang_eq[$uu[1]];
+            $n += strlen($uu[1]) - 1;
+         }
 
-            #-- parsing error
-            else {
-               // PHPs native json_decode() breaks here usually and QUIETLY
-              trigger_error("json_decode: error parsing '$c' at position $n", E_USER_WARNING);
-               return $waitfor ? array(NULL, 1<<30) : NULL;
-            }
+         #-- parsing error
+         else {
+            // PHPs native json_decode() breaks here usually and QUIETLY
+           trigger_error("json_decode: error parsing '$c' at position $n", E_USER_WARNING);
+            return $waitfor ? array(NULL, 1<<30) : NULL;
+         }
 
-         }//state
-         
-         #-- next char
-         if ($n === NULL) { return NULL; }
-         $n++;
-      }//for
+      }//state
+      
+      #-- next char
+      if ($n === NULL) { return NULL; }
+      $n++;
+   }//for
 
-      #-- final result
-      return ($val);
+   #-- final result
+   return ($val);
+}
+if (!function_exists("json_decode")) {
+   function json_decode($json, $assoc=FALSE) {
+      return _json_decode($json, $assoc);
    }
 }
 
diff --git a/plugins/CustomVariables/CustomVariables.php b/plugins/CustomVariables/CustomVariables.php
index dc83830216..b849beb523 100644
--- a/plugins/CustomVariables/CustomVariables.php
+++ b/plugins/CustomVariables/CustomVariables.php
@@ -214,7 +214,7 @@ class Piwik_CustomVariables extends Piwik_Plugin
 					if(substr($label, -2) != '"]') {
 						$label .= '"]';
 					}
-					$decoded = @json_decode($label);
+					$decoded = @Piwik_Common::json_decode($label);
 					if(is_array($decoded))
 					{
 						$count = 0;
diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php
index 6399d8d7b4..f6b682f561 100644
--- a/plugins/Dashboard/Controller.php
+++ b/plugins/Dashboard/Controller.php
@@ -22,7 +22,7 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
 		$view = Piwik_View::factory($template);
 		$this->setGeneralVariablesView($view);
 
-		$view->availableWidgets = json_encode(Piwik_GetWidgetsList());
+		$view->availableWidgets = Piwik_Common::json_encode(Piwik_GetWidgetsList());
 		$layout = $this->getLayout();
 		if(empty($layout)
 			|| $layout == $this->getEmptyLayout()) {
@@ -145,7 +145,7 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
 		$layout = str_replace("\n", "", $layout);
 		// if the json decoding works (ie. new Json format)
 		// we will only return the widgets that are from enabled plugins
-		$layoutObject = json_decode($layout, $assoc = false);
+		$layoutObject = Piwik_Common::json_decode($layout, $assoc = false);
 
 		if(empty($layoutObject))
 		{
@@ -175,13 +175,13 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
 				}
 			}
 		}
-		$layout = json_encode($layoutObject);
+		$layout = Piwik_Common::json_encode($layoutObject);
 		return $layout;
 	}
 	
 	protected function getEmptyLayout()
 	{
-		return json_encode(array(
+		return Piwik_Common::json_encode(array(
 			array(),
 			array(),
 			array())
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
index 604ef5fbb7..3a79cb61d0 100644
--- a/plugins/Goals/Controller.php
+++ b/plugins/Goals/Controller.php
@@ -57,7 +57,7 @@ class Piwik_Goals_Controller extends Piwik_Controller
 	{
 		$view = $this->getGoalReportView($idGoal = Piwik_Common::getRequestVar('idGoal', null, 'string'));
 		$view->displayFullReport = true;
-        $view->goalDimensions = Piwik_Goals::getReportsWithGoalMetrics();
+		$view->goalDimensions = Piwik_Goals::getReportsWithGoalMetrics();
 		echo $view->render();
 	}
 	
@@ -205,8 +205,8 @@ class Piwik_Goals_Controller extends Piwik_Controller
 	public function index()
 	{
 		$view = $this->getOverviewView();
-		$view->goalsJSON = json_encode($this->goals);
-        $view->goalDimensions = Piwik_Goals::getReportsWithGoalMetrics();
+		$view->goalsJSON = Piwik_Common::json_encode($this->goals);
+		$view->goalDimensions = Piwik_Goals::getReportsWithGoalMetrics();
 		$view->userCanEditGoals = Piwik::isUserHasAdminAccess($this->idSite);
 		$view->ecommerceEnabled = $this->site->isEcommerceEnabled();
 		$view->displayFullReport = true;
@@ -368,12 +368,12 @@ class Piwik_Goals_Controller extends Piwik_Controller
 				$conversions = $row->getColumn($columnNbConversions);
 				if($conversions > 0)
 				{
-    				$topDimension[] = array (
-    					'name' => $row->getColumn('label'),
-    					'nb_conversions' => $conversions,
+					$topDimension[] = array (
+						'name' => $row->getColumn('label'),
+						'nb_conversions' => $conversions,
 						'conversion_rate' => $this->formatConversionRate($row->getColumn($columnConversionRate)),
-    					'metadata' => $row->getMetadata(),
-    				);
+						'metadata' => $row->getMetadata(),
+					);
 				}
 			}
 			$topDimensions[$dimensionName] = $topDimension;
@@ -477,4 +477,4 @@ class Piwik_ViewDataTable_HtmlTable_EcommerceAbandonedCart extends Piwik_ViewDat
 	{
 		return Piwik_Archive::LABEL_ECOMMERCE_CART;
 	}
-}
\ No newline at end of file
+}
diff --git a/plugins/PDFReports/Controller.php b/plugins/PDFReports/Controller.php
index a07209b2c4..ed91b8c163 100644
--- a/plugins/PDFReports/Controller.php
+++ b/plugins/PDFReports/Controller.php
@@ -43,7 +43,7 @@ class Piwik_PDFReports_Controller extends Piwik_Controller
 		$columnsCount = 2;
 		$view->newColumnAfter = ceil(count($reportsByCategory) / $columnsCount);
 		$view->reportsByCategory = $reportsByCategory;
-		$view->reportsJSON = json_encode($reportsById);
+		$view->reportsJSON = Piwik_Common::json_encode($reportsById);
 		$view->periods = array_merge(array('never' => Piwik_Translate('General_Never')),
 							Piwik_PDFReports_API::getPeriodToFrequency());
 		$view->defaultFormat = Piwik_PDFReports::DEFAULT_FORMAT;
diff --git a/plugins/SitesManager/Controller.php b/plugins/SitesManager/Controller.php
index beee163c11..172349d7ec 100644
--- a/plugins/SitesManager/Controller.php
+++ b/plugins/SitesManager/Controller.php
@@ -40,10 +40,10 @@ class Piwik_SitesManager_Controller extends Piwik_Controller_Admin
 
 		$timezones = Piwik_SitesManager_API::getInstance()->getTimezonesList();
 		$view->timezoneSupported = Piwik::isTimezoneSupportEnabled();
-		$view->timezones = json_encode($timezones);
+		$view->timezones = Piwik_Common::json_encode($timezones);
 		$view->defaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone();
 
-		$view->currencies = json_encode(Piwik_SitesManager_API::getInstance()->getCurrencyList());
+		$view->currencies = Piwik_Common::json_encode(Piwik_SitesManager_API::getInstance()->getCurrencyList());
 		$view->defaultCurrency = Piwik_SitesManager_API::getInstance()->getDefaultCurrency();
 
 		$view->utcTime = Piwik_Date::now()->getDatetime();
@@ -161,6 +161,6 @@ class Piwik_SitesManager_Controller extends Piwik_Controller_Admin
 			}
 		}
 
-		print json_encode($results);
+		print Piwik_Common::json_encode($results);
 	}
 }
diff --git a/plugins/Widgetize/Controller.php b/plugins/Widgetize/Controller.php
index cb785bb8a9..825af0fe30 100644
--- a/plugins/Widgetize/Controller.php
+++ b/plugins/Widgetize/Controller.php
@@ -19,7 +19,7 @@ class Piwik_Widgetize_Controller extends Piwik_Controller
 	function index()
 	{
 		$view = Piwik_View::factory('index');
-		$view->availableWidgets = json_encode(Piwik_GetWidgetsList());
+		$view->availableWidgets = Piwik_Common::json_encode(Piwik_GetWidgetsList());
 		$this->setGeneralVariablesView($view);
 		echo $view->render();
 	}
-- 
GitLab