diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php index dee565526dec41b6771174c6442c87e056e63c0c..1d94dc98881c955e010f7d4f23a082074256153a 100644 --- a/core/API/ResponseBuilder.php +++ b/core/API/ResponseBuilder.php @@ -104,41 +104,30 @@ class Piwik_API_ResponseBuilder */ public function getResponseException(Exception $e) { - $message = htmlentities($e->getMessage(), ENT_COMPAT, "UTF-8"); - switch($this->outputFormat) + $format = strtolower($this->outputFormat); + + if( $format == 'original' ) { - case 'original': - throw $e; - break; - case 'xml': - @header("Content-Type: text/xml;charset=utf-8"); - $return = - "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" . - "<result>\n". - "\t<error message=\"".$message."\" />\n". - "</result>"; - break; - case 'json': - @header( "Content-Type: application/json" ); - // we remove the \n from the resulting string as this is not allowed in json - $message = str_replace("\n","",$message); - $return = '{"result":"error", "message":"'.$message.'"}'; - break; - case 'php': - $return = array('result' => 'error', 'message' => $message); - if($this->caseRendererPHPSerialize()) - { - $return = serialize($return); - } - break; - case 'html': - $return = nl2br($message); - break; - default: - $return = 'Error: '.$message; - break; + throw $e; } - return $return; + + try + { + $renderer = Piwik_DataTable_Renderer::factory($format); + + } catch (Exception $e) { + + return "Error: " . $e->getMessage(); + } + + $renderer->setException($e); + + if($format == 'php') + { + $renderer->setSerialize($this->caseRendererPHPSerialize()); + } + + return $renderer->renderException(); } /** @@ -300,5 +289,5 @@ class Piwik_API_ResponseBuilder $dataTable->addRowsFromSimpleArray($array); return $this->getRenderedDataTable($dataTable); } - } + } } diff --git a/core/DataTable/Renderer.php b/core/DataTable/Renderer.php index 582208ebcd2ce8289f9b349eb2d99929a86978fc..5f1a42671f969199bb5a9b6aebcd4463a655536f 100644 --- a/core/DataTable/Renderer.php +++ b/core/DataTable/Renderer.php @@ -24,6 +24,7 @@ abstract class Piwik_DataTable_Renderer { protected $table; + protected $exception; protected $renderSubTables = false; public function __construct() @@ -47,6 +48,13 @@ abstract class Piwik_DataTable_Renderer */ abstract public function render(); + /** + * Computes the exception output and returns the string/binary + * + * @return string + */ + abstract public function renderException(); + /** * @see render() * @return string @@ -70,6 +78,19 @@ abstract class Piwik_DataTable_Renderer $this->table = $table; } + /** + * Set the Exception to be rendered + * @param Exception $exception to be rendered + */ + public function setException($exception) + { + if(!($exception instanceof Exception)) + { + throw new Exception("The exception renderer accepts only an Exception object."); + } + $this->exception = $exception; + } + /** * Returns the DataTable associated to the output format $name * @@ -88,5 +109,16 @@ abstract class Piwik_DataTable_Renderer $availableRenderers = 'xml, json, csv, tsv, html, php, original'; throw new Exception(Piwik_TranslateException('General_ExceptionInvalidRendererFormat', array($name, $availableRenderers))); } - } -} + } + + /** + * Returns $rawData after all applicable characters have been converted to HTML entities. + * + * @param String $rawData to be converted + * @return String + */ + static protected function renderHtmlEntities( $rawData ) + { + return htmlentities($rawData, ENT_COMPAT, "UTF-8"); + } +} \ No newline at end of file diff --git a/core/DataTable/Renderer/Console.php b/core/DataTable/Renderer/Console.php index 6d99d08664885e16d42e2263afe7681cfdd83408..7d0fb5f0010c4738ec6712e2ee02a8ae67882e74 100644 --- a/core/DataTable/Renderer/Console.php +++ b/core/DataTable/Renderer/Console.php @@ -25,6 +25,12 @@ class Piwik_DataTable_Renderer_Console extends Piwik_DataTable_Renderer return $this->renderTable($this->table); } + function renderException() + { + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + return 'Error: '.$exceptionMessage; + } + function setPrefixRow($str) { $this->prefixRows = $str; diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php index a374641c96a8fcf45b515a43d53dabca129bb33f..3ff46a3dd4afa48f0760ffc1736ac0e452abac39 100644 --- a/core/DataTable/Renderer/Csv.php +++ b/core/DataTable/Renderer/Csv.php @@ -66,6 +66,12 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer return $this->output($this->renderTable($this->table)); } + function renderException() + { + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + return 'Error: '.$exceptionMessage; + } + public function setConvertToUnicode($bool) { $this->convertToUnicode = $bool; diff --git a/core/DataTable/Renderer/Html.php b/core/DataTable/Renderer/Html.php index b559d4e936867543497a780ac6fc27a6c3a83b0c..2ebc36c0ce021d2f80cad052f020ca896591a5ab 100644 --- a/core/DataTable/Renderer/Html.php +++ b/core/DataTable/Renderer/Html.php @@ -38,6 +38,12 @@ class Piwik_DataTable_Renderer_Html extends Piwik_DataTable_Renderer return $this->renderTable($this->table); } + function renderException() + { + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + return nl2br($exceptionMessage); + } + protected function renderTable($table) { if($table instanceof Piwik_DataTable_Array) diff --git a/core/DataTable/Renderer/Json.php b/core/DataTable/Renderer/Json.php index 5febed6a887813e37e274978f7f2203c9ad16750..7f724914a3859a47d627dfbad2ad2b699b59cf24 100644 --- a/core/DataTable/Renderer/Json.php +++ b/core/DataTable/Renderer/Json.php @@ -21,9 +21,21 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer { public function render() { + Piwik_DataTable_Renderer_Json::renderHeader(); return $this->renderTable($this->table); } + function renderException() + { + Piwik_DataTable_Renderer_Json::renderHeader(); + + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + $exceptionMessage = str_replace("\n", "", $exceptionMessage); + $exceptionMessage = '{"result":"error", "message":"'.$exceptionMessage.'"}'; + + return $this->jsonpWrap("\"".$exceptionMessage."\""); + } + protected function renderTable($table) { $renderer = new Piwik_DataTable_Renderer_Php(); @@ -38,6 +50,11 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer } $str = json_encode($array); + return $this->jsonpWrap($str); + } + + protected function jsonpWrap($str) + { if(($jsonCallback = Piwik_Common::getRequestVar('jsoncallback', false)) !== false) { if(preg_match('/^[0-9a-zA-Z]*$/', $jsonCallback) > 0) @@ -45,6 +62,12 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer $str = $jsonCallback . "(" . $str . ")"; } } + return $str; } + + static private function renderHeader () + { + @header( "Content-Type: application/json" ); + } } diff --git a/core/DataTable/Renderer/Php.php b/core/DataTable/Renderer/Php.php index b7d5f216da34704bf8ab2e650a3caac24ac861f5..18f24452e05c53557cc3ef625eb56fd362e9b248 100644 --- a/core/DataTable/Renderer/Php.php +++ b/core/DataTable/Renderer/Php.php @@ -64,6 +64,20 @@ class Piwik_DataTable_Renderer_Php extends Piwik_DataTable_Renderer return $toReturn; } + function renderException() + { + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + + $return = array('result' => 'error', 'message' => $exceptionMessage); + + if($this->serialize) + { + $return = serialize($return); + } + + return $return; + } + /** * Produces a flat php array from the DataTable, putting "columns" and "metadata" on the same level. * diff --git a/core/DataTable/Renderer/Rss.php b/core/DataTable/Renderer/Rss.php index 3918046def3ff39e2817f599bda85ba32d1e05ef..9c07515678f062334570cf9f4009bc76f60d776c 100644 --- a/core/DataTable/Renderer/Rss.php +++ b/core/DataTable/Renderer/Rss.php @@ -25,6 +25,12 @@ class Piwik_DataTable_Renderer_Rss extends Piwik_DataTable_Renderer return $this->renderTable($this->table); } + function renderException() + { + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + return 'Error: '.$exceptionMessage; + } + protected function renderTable($table) { if(!($table instanceof Piwik_DataTable_Array) diff --git a/core/DataTable/Renderer/Xml.php b/core/DataTable/Renderer/Xml.php index 9eb2c30bbf692fc39c2a2d1524859d106b19675c..828b890ab768ba832b0e75afa50ff9ce7df625a8 100644 --- a/core/DataTable/Renderer/Xml.php +++ b/core/DataTable/Renderer/Xml.php @@ -27,6 +27,20 @@ class Piwik_DataTable_Renderer_Xml extends Piwik_DataTable_Renderer return $this->renderTable($this->table); } + function renderException() + { + $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage()); + + @header("Content-Type: text/xml;charset=utf-8"); + $return = + "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" . + "<result>\n". + "\t<error message=\"".$exceptionMessage."\" />\n". + "</result>"; + + return $return; + } + protected function getArrayFromDataTable($table) { $renderer = new Piwik_DataTable_Renderer_Php();