/***************************************************************
* 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
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
+
/**
* class to hold all the information about an AJAX call and send
* the right headers for the request type
* @subpackage core
*/
class TYPO3AJAX {
- private $id = null;
- private $errorMessage = null;
- private $isError = false;
- private $content = array();
- private $contentFormat = 'plain'; // could be 'plain' (default), 'xml', 'json', 'jsonbody' or 'jsonhead'
- 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
+ * @param string the AJAX id
* @return void
*/
- public function init($id) {
- global $TYPO3_CONF_VARS;
-
- if (isset($TYPO3_CONF_VARS['BE']['forceCharset']) && trim($TYPO3_CONF_VARS['BE']['forceCharset'])) {
- $this->charset = $TYPO3_CONF_VARS['BE']['forceCharset'];
+ public function __construct($ajaxId) {
+
+ 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->id = $id;
+ $this->ajaxId = $ajaxId;
}
/**
* returns the ID for the AJAX call
*
- * @return string the AJAX id
+ * @return string the AJAX id
*/
- public function getID() {
- return $this->id;
+ public function getAjaxID() {
+ return $this->ajaxId;
}
/**
* overwrites the existing content with the first parameter
*
- * @param array the new content
- * @return mixed the old content as array; if the new content was not an array, false is returned
+ * @param array the new content
+ * @return mixed the old content as array; if the new content was not an array, false is returned
*/
public function setContent($content) {
$oldcontent = false;
/**
* adds new content
*
- * @param string the new content key where the content should be added in the content array
- * @param string the new content to add
- * @return mixed the old content; if the old content didn't exist before, false is returned
+ * @param string the new content key where the content should be added in the content array
+ * @param string the new content to add
+ * @return mixed the old content; if the old content didn't exist before, false is returned
*/
public function addContent($key, $content) {
$oldcontent = false;
/**
* returns the content for the ajax call
*
- * @return mixed the content for a specific key or the whole content
+ * @return mixed the content for a specific key or the whole content
*/
public function getContent($key = '') {
return ($key && array_key_exists($key, $this->content) ? $this->content[$key] : $this->content);
/**
* sets the content format for the ajax call
- *
- * @param string can be one of the following keywords 'plain', '
+ *
+ * @param string can be one of 'plain' (default), 'xml', 'json', 'jsonbody' or 'jsonhead'
* @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;
}
}
/**
* sets an error message and the error flag
*
- * @param string the error message
+ * @param string the error message
* @return void
*/
public function setError($errorMsg = '') {
/**
* checks whether an error occured during the execution or not
*
- * @return boolean whether this AJAX call
+ * @return boolean whether this AJAX call had errors
*/
public function isError() {
return $this->isError;
case 'json':
$this->renderAsJSON();
break;
+ case 'javascript':
+ $this->renderAsJavascript();
+ break;
case 'xml':
$this->renderAsXML();
break;
/**
* renders the AJAX call in XML error style to handle with JS
* the "responseXML" of the transport object will be filled with the error message then
- *
+ *
* @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>');
/**
* renders the AJAX call with text/html headers
* the content will be available in the "responseText" value of the transport object
- *
+ *
* @return void
*/
- private function renderAsPlain() {
+ protected function renderAsPlain() {
header('Content-type: text/html; charset='.$this->charset);
header('X-JSON: true');
echo implode('', $this->content);
/**
* renders the AJAX call with text/xml headers
* the content will be available in the "responseXML" value of the transport object
- *
+ *
* @return void
*/
- private function renderAsXML() {
+ protected function renderAsXML() {
header('Content-type: text/xml; charset='.$this->charset);
header('X-JSON: true');
echo implode('', $this->content);
* renders the AJAX call with JSON evaluated headers
* note that you need to have requestHeaders: {Accept: 'application/json'},
* in your AJAX options of your AJAX request object in JS
- *
- * the content will be available
+ *
+ * the content will be available
* - in the second parameter of the onSuccess / onComplete callback (except when contentFormat = 'jsonbody')
* - and in the xhr.responseText as a string (except when contentFormat = 'jsonhead')
* you can evaluate this in JS with xhr.responseText.evalJSON();
*
* @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));
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;
+ }
}
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.typo3ajax.php']);
}
-?>
+?>
\ No newline at end of file