From d16c426fb6b51f950d3e2d8b9cc0cb65248dfbff Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Fri, 19 Jul 2013 08:45:26 +0000 Subject: [PATCH] first step towards content-security by passing parameters to egw.js script via data-attributes of script tag instead of using inline scripts in page --- phpgwapi/inc/class.egw_framework.inc.php | 63 +++++------------- phpgwapi/js/jsapi/egw.js | 82 ++++++++++++++++++++++++ phpgwapi/js/jsapi/jsapi.js | 15 ++--- 3 files changed, 103 insertions(+), 57 deletions(-) diff --git a/phpgwapi/inc/class.egw_framework.inc.php b/phpgwapi/inc/class.egw_framework.inc.php index 108d1154fe..d76f97bf05 100644 --- a/phpgwapi/inc/class.egw_framework.inc.php +++ b/phpgwapi/inc/class.egw_framework.inc.php @@ -289,9 +289,10 @@ abstract class egw_framework /** * Get header as array to eg. set as vars for a template (from idots' head.inc.php) * + * @param array $extra=array() extra attributes passed as data-attribute to egw.js * @return array */ - protected function _get_header() + protected function _get_header(array $extra=array()) { // get used language code (with a little xss check, if someone tries to sneak something in) if (preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$GLOBALS['egw_info']['user']['preferences']['common']['lang'])) @@ -366,7 +367,7 @@ abstract class egw_framework 'charset' => translation::charset(), 'website_title' => strip_tags($GLOBALS['egw_info']['server']['site_title']. ($app ? " [$app]" : '')), 'body_tags' => self::_get_body_attribs(), - 'java_script' => self::_get_js(), + 'java_script' => self::_get_js($extra), 'meta_robots' => $robots, 'dir_code' => lang('language_direction_rtl') != 'rtl' ? '' : ' dir="rtl"', 'include_wz_tooltip'=> $include_wz_tooltip, @@ -814,10 +815,10 @@ abstract class egw_framework * in eGW. One change then all templates will support it (as long as they * include a call to this method). * - * @author Dave Hall (*vaguely based* on verdilak? css inclusion code) + * @param array $extra=array() extra data to pass to egw.js as data-parameter * @return string the javascript to be included */ - public static function _get_js() + public static function _get_js(array $extra=array()) { $java_script = ''; @@ -840,55 +841,26 @@ abstract class egw_framework self::validate_file('/phpgwapi/images.php',array('template' => $GLOBALS['egw_info']['user']['preferences']['common']['template_set'])); } - // set webserver_url for json - $java_script .= ""; - - $to_include = self::get_script_links(true); - - // Use LABjs to execute this stuff after all the script links are loaded - $after = 'window.egw_appName = "'.$GLOBALS['egw_info']['flags']['currentapp'].'";'."\n"; + $extra['url'] = $GLOBALS['egw_info']['server']['webserver_url']; + $extra['include'] = array_map(function($str){return substr($str,1);}, self::get_script_links(true), array(1)); + $extra['app'] = $GLOBALS['egw_info']['flags']['currentapp']; // add link registry to non-popup windows, if explicit requested (idots_framework::navbar() loads it, if not explicit specified!) if ($GLOBALS['egw_info']['flags']['js_link_registry']) { - $after .= 'egw.set_preferences('.json_encode($GLOBALS['egw_info']['user']['preferences']['common']).', "common");'."\n"; - $after .= 'egw.set_user('.$GLOBALS['egw']->accounts->json($GLOBALS['egw_info']['user']['account_id']).');'."\n"; + $extra['preferences'] = array('common' => $GLOBALS['egw_info']['user']['preferences']['common']); + $extra['user'] = $GLOBALS['egw']->accounts->json($GLOBALS['egw_info']['user']['account_id']); } // Load LABjs ONCE here $java_script .= '\n". - ''; + '\n"; if(@isset($_GET['menuaction'])) { @@ -909,7 +881,6 @@ window.egw_LAB.script( } } - return $java_script; } diff --git a/phpgwapi/js/jsapi/egw.js b/phpgwapi/js/jsapi/egw.js index 92d3f87643..de5e3b23c6 100644 --- a/phpgwapi/js/jsapi/egw.js +++ b/phpgwapi/js/jsapi/egw.js @@ -35,3 +35,85 @@ app_base; */ +(function(){ + var debug = false; + var egw_script = document.getElementById('egw_script_id'); + window.egw_webserverUrl = egw_script.getAttribute('data-url'); + window.egw_appName = egw_script.getAttribute('data-app'); + + // check if egw object was injected by window open + if (typeof window.egw == 'undefined') + { + // try finding it in top or opener's top + if (window.opener && typeof window.opener.top.egw != 'undefined') + { + window.egw = window.opener.top.egw; + if (typeof window.opener.top.framework != 'undefined') window.framework = window.opener.top.framework; + if (debug) console.log('found egw object in opener'); + } + else if (window.top && typeof window.top.egw != 'undefined') + { + window.egw = window.top.egw; + if (typeof window.top.framework != 'undefined') window.framework = window.top.framework; + if (debug) console.log('found egw object in top'); + } + else + { + window.egw = { + prefsOnly: true, + webserverUrl: egw_webserverUrl + }; + if (debug) console.log('creating new egw object'); + } + } + else console.log('found injected egw object'); + + // check for a framework object + if (typeof window.framework == 'undefined') + { + // try finding it in top or opener's top + if (window.opener && typeof window.opener.top.framework != 'undefined') + { + window.framework = window.opener.top.framework; + if (debug) console.log('found framework object in opener top'); + } + else if (window.top && typeof window.top.framework != 'undefined') + { + window.framework = window.top.framework; + if (debug) console.log('found framework object in top'); + } + // if framework not found, but requested to check for it, redirect to cd=yes to create it + else if (egw_script.getAttribute('data-check-framework')) + { + window.location.search += window.location.search ? "&cd=yes" : "?cd=yes"; + } + } + + window.egw_LAB = $LAB.setOptions({AlwaysPreserveOrder:true,BasePath:window.egw_webserverUrl+'/'}); + var include = JSON.parse(egw_script.getAttribute('data-include')); + + // remove this script from include, until server-side no longer requires it + for(var i=0; i < include.length; ++i) + { + if (include[i].match(/^phpgwapi\/js\/jsapi\/egw\.js/)) + { + include.splice(i, 1); + break; + } + } + window.egw_LAB.script(include).wait(function(){ + var data = egw_script.getAttribute('data-preferences'); + if (data) + { + data = JSON.parse(data) || {}; + for(var app in data) + { + window.egw.set_preferences(data[app], app); + } + } + if (data = egw_script.getAttribute('data-user')) + { + window.egw.set_user(JSON.parse(data)); + } + }); +})(); diff --git a/phpgwapi/js/jsapi/jsapi.js b/phpgwapi/js/jsapi/jsapi.js index 45e3a3e859..4e8704c644 100644 --- a/phpgwapi/js/jsapi/jsapi.js +++ b/phpgwapi/js/jsapi/jsapi.js @@ -11,16 +11,6 @@ * @version $Id$ */ -// Loading of the egw object, if it already is loaded in an upper window -if (window.opener && typeof window.opener.egw !== 'undefined') -{ - window['egw'] = window.opener.egw; -} -else if (window.top && typeof window.top.egw !== 'undefined') -{ - window['egw'] = window.top.egw; -} - /***********************************************\ * INITIALIZATION * \***********************************************/ @@ -43,7 +33,7 @@ else if (document.getElementById) else if (document.layers) { is_ie = false; - is_ie5 = false + is_ie5 = false; is_moz1_6 = false; is_mozilla = false; is_ns4 = true; @@ -405,6 +395,9 @@ function egw_openWindowCentered2(_url, _windowName, _width, _height, _status, _a ",screenX=" + positionLeft + ",left=" + positionLeft + ",screenY=" + positionTop + ",top=" + positionTop + ",location=no,menubar=no,directories=no,toolbar=no,scrollbars=yes,resizable=yes,status="+_status); + // inject egw object + windowID.egw = window.egw; + // returning something, replaces whole window in FF, if used in link as "javascript:egw_openWindowCentered2()" if (_returnID === false) {