Added feature #11819: Added inline Javascript rendering type for TYPO3AJAX
[Packages/TYPO3.CMS.git] / typo3 / classes / class.typo3ajax.php
index 510c9fd..1414567 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008 Benjamin Mack <mack@xnos.org>
+*  (c) 2008-2009 Benjamin Mack <mack@xnos.org>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  * @subpackage core
  */
 class TYPO3AJAX {
-       private $ajaxId        = null;
-       private $errorMessage  = null;
-       private $isError       = false;
-       private $content       = array();
-       private $contentFormat = 'plain';
-       private $charset       = 'utf-8';
+       protected $ajaxId        = null;
+       protected $errorMessage  = null;
+       protected $isError       = false;
+       protected $content       = array();
+       protected $contentFormat = 'plain';
+       protected $charset       = 'utf-8';
+       protected $requestCharset = 'utf-8';
 
        /**
         * sets the charset and the ID for the AJAX call
+        * due some charset limitations in Javascript (prototype uses encodeURIcomponent, which converts
+        * all data to utf-8), we need to detect if the encoding of the request differs from the
+        * backend encoding (e.g. forceCharset), and then convert all incoming data (_GET and _POST)
+        * in the expected backend encoding.
         *
         * @param       string          the AJAX id
         * @return      void
         */
        public function __construct($ajaxId) {
-               global $LANG;
 
-               if($LANG->charSet != $this->charset) {
-                       $this->charset = $LANG->charSet;
+               if ($GLOBALS['LANG']->charSet != $this->charset) {
+                       $this->charset = $GLOBALS['LANG']->charSet;
+               }
+
+                       // get charset from current AJAX request (which is expected to be utf-8)
+               preg_match('/;\s*charset\s*=\s*([a-zA-Z0-9_-]*)/i', $_SERVER['CONTENT_TYPE'], $contenttype);
+               $charset = $GLOBALS['LANG']->csConvObj->parse_charset($contenttype[1]);
+               if ($charset && $charset != $this->requestCharset) {
+                       $this->requestCharset = $charset;
+               }
+
+                               // if the AJAX request does not have the same encoding like the backend
+                               // we need to convert the POST and GET parameters in the right charset
+               if ($this->charset != $this->requestCharset) {
+                       $GLOBALS['LANG']->csConvObj->convArray($_POST, $this->requestCharset, $this->charset);
+                       $GLOBALS['LANG']->csConvObj->convArray($_GET,  $this->requestCharset, $this->charset);
                }
 
                $this->ajaxId = $ajaxId;
@@ -124,7 +142,7 @@ class TYPO3AJAX {
         * @return      void
         */
        public function setContentFormat($format) {
-               if (t3lib_div::inArray(array('plain', 'xml', 'json', 'jsonhead', 'jsonbody'), $format)) {
+               if (t3lib_div::inArray(array('plain', 'xml', 'json', 'jsonhead', 'jsonbody', 'javascript'), $format)) {
                        $this->contentFormat = $format;
                }
        }
@@ -168,6 +186,9 @@ class TYPO3AJAX {
                        case 'json':
                                $this->renderAsJSON();
                                break;
+                       case 'javascript':
+                               $this->renderAsJavascript();
+                               break;
                        case 'xml':
                                $this->renderAsXML();
                                break;
@@ -184,7 +205,8 @@ class TYPO3AJAX {
         *
         * @return      void
         */
-       private function renderAsError() {
+       protected function renderAsError() {
+               header(t3lib_div::HTTP_STATUS_500 . ' (AJAX)');
                header('Content-type: text/xml; charset='.$this->charset);
                header('X-JSON: false');
                die('<t3err>'.htmlspecialchars($this->errorMessage).'</t3err>');
@@ -197,7 +219,7 @@ class TYPO3AJAX {
         *
         * @return      void
         */
-       private function renderAsPlain() {
+       protected function renderAsPlain() {
                header('Content-type: text/html; charset='.$this->charset);
                header('X-JSON: true');
                echo implode('', $this->content);
@@ -210,7 +232,7 @@ class TYPO3AJAX {
         *
         * @return      void
         */
-       private function renderAsXML() {
+       protected function renderAsXML() {
                header('Content-type: text/xml; charset='.$this->charset);
                header('X-JSON: true');
                echo implode('', $this->content);
@@ -229,8 +251,8 @@ class TYPO3AJAX {
         *
         * @return      void
         */
-       private function renderAsJSON() {
-               $content = t3lib_div::array2json($this->content);
+       protected function renderAsJSON() {
+               $content = json_encode($this->content);
 
                header('Content-type: application/json; charset='.$this->charset);
                header('X-JSON: '.($this->contentFormat != 'jsonbody' ? $content : true));
@@ -240,6 +262,25 @@ class TYPO3AJAX {
                        echo $content;
                }
        }
+
+       /**
+        * Renders the AJAX call as inline JSON inside a script tag. This is useful
+        * when an iframe is used as the AJAX transport.
+        *
+        * @return       void
+        */
+       protected function renderAsJavascript() {
+               $content = '<script type="text/javascript">
+                                       /*<![CDATA[*/
+
+                                       response = ' . json_encode($this->content) . ';
+
+                                       /*]]>*/
+                                       </script>';
+
+               header('Content-type: text/html; charset=' . $this->charset);
+               echo $content;
+       }
 }
 
 
@@ -247,4 +288,4 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.typo3ajax.php']);
 }
 
-?>
+?>
\ No newline at end of file