diff --git a/js/ajax.js b/js/ajax.js index 875303d361..0ac45f9bdb 100644 --- a/js/ajax.js +++ b/js/ajax.js @@ -255,7 +255,7 @@ var AJAX = { $('#selflink > a').attr('href', data._selflink); } if (data._scripts) { - AJAX.scriptHandler.load(data._scripts, 1); + AJAX.scriptHandler.load(data._scripts); } if (data._selflink && data._scripts && data._menuHash && data._params) { AJAX.cache.add( @@ -329,46 +329,46 @@ var AJAX = { return this; }, /** - * Queues up an array of files to be downloaded + * Download a list of js files in one request * * @param array files An array of filenames and flags * * @return void */ - load: function (files, reset) { - if (reset) { - this._scriptsToBeLoaded = []; - this._scriptsToBeFired = []; - } + load: function (files) { + var self = this; + self._scriptsToBeLoaded = []; + self._scriptsToBeFired = []; for (var i in files) { - this._scriptsToBeLoaded.push(files[i].name); + self._scriptsToBeLoaded.push(files[i].name); if (files[i].fire) { - this._scriptsToBeFired.push(files[i].name); + self._scriptsToBeFired.push(files[i].name); } } - this.callback(); - }, - /** - * Called whenever a file is loaded. - * Will queue up another file, or call done(); - * - * @return void - */ - callback: function () { - var scripts = this._scriptsToBeLoaded; - if (scripts.length > 0) { - var script = scripts.shift(); - if ($.inArray(script, this._scripts) == -1) { + // Generate a request string + var request = []; + var needRequest = false; + for (var index in self._scriptsToBeLoaded) { + var script = self._scriptsToBeLoaded[index]; + // Only for scripts that we don't already have + if ($.inArray(script, self._scripts) == -1) { + needRequest = true; this.add(script); - var self = this; - $.getScript('js/' + script, function () { - self.callback(); - }); - } else { - this.callback(); + request.push("scripts[]=" + script); } + } + // Download the composite js file, if necessary + if (needRequest) { + $.ajax({ + url: "js/get_scripts.js.php?" + request.join("&"), + cache: true, + success: function () { + self.done(); + }, + dataType: "script" + }); } else { - this.done(); + self.done(); } }, /** @@ -386,7 +386,6 @@ var AJAX = { * Fires all the teardown event handlers for the current page * and rebinds all forms and links to the request handler * - * @param object ctx Context for the callback * @param function callback The callback to call after resetting * * @return void diff --git a/js/get_scripts.js.php b/js/get_scripts.js.php new file mode 100644 index 0000000000..564fda7dd2 --- /dev/null +++ b/js/get_scripts.js.php @@ -0,0 +1,38 @@ + $filename) { + if (! preg_match("@^\.+$@", $filename) + && preg_match("@^[\w\.-]+$@", $filename) + ) { + // Disallow "." and ".." alone + // Allow alphanumeric, "." and "-" chars only + $script_name .= DIRECTORY_SEPARATOR . $filename; + } + } + // Output file contents + if (preg_match("@\.js$@", $script_name) && is_readable($script_name)) { + readfile($script_name); + echo ";\n\n"; + } + } +} + +?> diff --git a/libraries/Scripts.class.php b/libraries/Scripts.class.php index 7b09b197de..58cfbe89ce 100644 --- a/libraries/Scripts.class.php +++ b/libraries/Scripts.class.php @@ -44,32 +44,38 @@ class PMA_Scripts /** * Returns HTML code to include javascript file. * - * @param string $url Location of javascript, relative to js/ folder. - * @param int $timestamp The date when the file was last modified - * @param string $ie_conditional true - wrap with IE conditional comment - * 'lt 9' etc. - wrap for specific IE version + * @param array $files The list of js file to include * * @return string HTML code for javascript inclusion. */ - private function _includeFile($url, $timestamp = null, $ie_conditional = false) + private function _includeFiles($files) { - $include = ''; - if ($ie_conditional !== false) { - if ($ie_conditional === true) { - $include .= '' . "\n"; - } - return $include; + $static_scripts = sprintf( + "", + implode("&", $params) + ); + return $static_scripts . $dynamic_scripts; } /** @@ -99,14 +105,9 @@ class PMA_Scripts $hash = md5($filename); if (empty($this->_files[$hash])) { $has_onload = $this->_eventBlacklist($filename); - $timestamp = null; - if (strpos($filename, '?') === false) { - $timestamp = filemtime('js/' . $filename); - } $this->_files[$hash] = array( 'has_onload' => $has_onload, 'filename' => $filename, - 'timestamp' => $timestamp, 'conditional_ie' => $conditional_ie ); } @@ -175,11 +176,13 @@ class PMA_Scripts { $retval = array(); foreach ($this->_files as $file) { - if (! $file['conditional_ie'] || PMA_USR_BROWSER_AGENT == 'IE') { - $retval[] = array( - 'name' => $file['filename'], - 'fire' => $file['has_onload'] - ); + if (strpos($file['filename'], "?") === false) { + if (! $file['conditional_ie'] || PMA_USR_BROWSER_AGENT == 'IE') { + $retval[] = array( + 'name' => $file['filename'], + 'fire' => $file['has_onload'] + ); + } } } return $retval; @@ -194,13 +197,12 @@ class PMA_Scripts { $retval = ''; - foreach ($this->_files as $file) { - $retval .= $this->_includeFile( - 'js/' . $file['filename'], - $file['timestamp'], - $file['conditional_ie'] + if (count($this->_files) > 0) { + $retval .= $this->_includeFiles( + $this->_files ); } + $code = 'AJAX.scriptHandler'; foreach ($this->_files as $file) { $code .= sprintf(