Index: openacs-4/www/blank-master.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/www/blank-master.tcl,v diff -u -N -r1.56 -r1.57 --- openacs-4/www/blank-master.tcl 10 Jun 2015 19:14:01 -0000 1.56 +++ openacs-4/www/blank-master.tcl 7 Aug 2017 23:48:31 -0000 1.57 @@ -1,5 +1,5 @@ ad_page_contract { - This is the top level master template. It allows the basic parts of an XHTML + This is the top level master template. It allows the basic parts of an HTML document to be set through convenient data structures without introducing anything site specific. @@ -53,7 +53,9 @@ @see template::add_footer @author Kevin Scaldeferri (kevin@arsdigita.com) - Lee Denison (lee@xarg.co.uk) + Lee Denison (lee@xarg.co.uk) + Gustaf Neumann + @creation-date 14 Sept 2000 $Id$ @@ -70,50 +72,54 @@ -name generator \ -lang en \ -content "OpenACS version [ad_acs_version]" - + # Add standard javascript # # Include core.js inclusion to the bottom of the body. -# The only function needed alread onload is acs_Focus() -# + template::add_body_script -type "text/javascript" -src "/resources/acs-subsite/core.js" -template::head::add_javascript -script { - function acs_Focus(form_name, element_name) { - if (document.forms == null) return; - if (document.forms[form_name] == null) return; - if (document.forms[form_name].elements[element_name] == null) return; - if (document.forms[form_name].elements[element_name].type == 'hidden') return; - - document.forms[form_name].elements[element_name].focus(); - } -} - -# The following (forms, list and xinha) should -# be done in acs-templating. - # # Add css for the current subsite, defaulting to the old list/form css which was # hard-wired in previous versions of OpenACS. -set css [parameter::get -package_id [ad_conn subsite_id] -parameter ThemeCSS -default ""] -if {$css ne "" } { +set cssList [parameter::get -package_id [ad_conn subsite_id] -parameter ThemeCSS -default ""] +if {![string is list $cssList]} { + ns_log error "ignore value in ThemeCSS, since it is not a valid list: $cssList" +} elseif { [llength $cssList] > 0 } { # DRB: Need to handle two cases, the lame first attempt and the more complete current # attempt which allows you to specify all of the parameters to template::head::add_css # (sigh, remove this kludge for 5.5.1). We need to handle the old case so upgrades # to 5.5 for mgh and various of my sites work correctly. + # + # The following syntaxes are supported + # + # 1) pairs: {/resources/acs-templating/lists.css all} ... + # 2) nested list of pairs: {{href /resources/acs-templating/lists.css} {media all} ... } ... + # 3) flat list of -att val pairs: {-href /resources/acs-templating/lists.css -media all ... } ... + # - foreach css $css { - if { [llength $css] == 2 && [llength [lindex $css 0]] == 1 } { - template::head::add_css -href [lindex $css 0] -media [lindex $css 1] - } else { + foreach css $cssList { + set first [lindex $css 0] + if { [llength $css] == 2 && [llength $first] == 1 && [string index $first 0] ne "-"} { + template::head::add_css -href $first -media [lindex $css 1] + } elseif {[llength $first] == 2} { set params [list] foreach param $css { lappend params -[lindex $param 0] [lindex $param 1] } - template::head::add_css {*}$params - } + if {[catch {template::head::add_css {*}$params} errorMsg]} { + ns_log error $errorMsg + } + } else { + if {![string match -* [lindex $css 0]]} { + error "CSS specification '$css' is incorrect" + } + if {[catch {template::head::add_css {*}$css} errorMsg]} { + ns_log error $errorMsg + } + } } } else { @@ -126,120 +132,74 @@ } # -# Temporary (?) fix to get xinha working -# -if {[info exists ::acs_blank_master(xinha)]} { - set ::xinha_dir /resources/acs-templating/xinha-nightly/ - set ::xinha_lang [lang::conn::language] - # - # Xinha localization covers 33 languages, removing - # the following restriction should be fine. - # - #if {$::xinha_lang ne "en" && $::xinha_lang ne "de"} { - # set ::xinha_lang en - #} +# Add js files via ThemeJS for the current subsite, similar to +# ThemeCSS. Syntax is the flat list syntax (3) from ThemeCSS, valid +# parameters are determined by template::add_script. It is possible to +# add head and body scripts. - # We could add site wide Xinha configurations (.js code) into xinha_params - set xinha_params "" - - # Per call configuration - set xinha_plugins $::acs_blank_master(xinha.plugins) - set xinha_options $::acs_blank_master(xinha.options) - - # HTML ids of the textareas used for Xinha - set htmlarea_ids '[join $::acs_blank_master__htmlareas "','"]' - - template::head::add_script -type text/javascript -script " - xinha_editors = null; - xinha_init = null; - xinha_config = null; - xinha_plugins = null; - xinha_init = xinha_init ? xinha_init : function() { - xinha_plugins = xinha_plugins ? xinha_plugins : - \[$xinha_plugins\]; - - // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING - if(!Xinha.loadPlugins(xinha_plugins, xinha_init)) return; - - xinha_editors = xinha_editors ? xinha_editors :\[ $htmlarea_ids \]; - xinha_config = xinha_config ? xinha_config() : new Xinha.Config(); - $xinha_params - $xinha_options - xinha_editors = - Xinha.makeEditors(xinha_editors, xinha_config, xinha_plugins); - Xinha.startEditors(xinha_editors); - } - //window.onload = xinha_init; - " - - template::add_body_handler -event onload -script "xinha_init();" - # Antonio Pisano 2015-03-27: including big javascripts in head is discouraged by current best practices for web. - # We should consider moving every inclusion like this in the body. As consequences are non-trivial, just warn for now. - template::head::add_javascript -src ${::xinha_dir}XinhaCore.js -} - -if { [info exists ::acs_blank_master(tinymce)] } { - # we are using TinyMCE - # Antonio Pisano 2015-03-27: including big javascripts in head is discouraged by current best practices for web. - # We should consider moving every inclusion like this in the body. As consequences are non-trivial, just warn for now. - template::head::add_javascript -src "/resources/acs-templating/tinymce/jscripts/tiny_mce/tiny_mce_src.js" -order tinymce0 - # get the textareas where we apply tinymce - set tinymce_elements [list] - foreach htmlarea_id [lsort -unique $::acs_blank_master__htmlareas] { - lappend tinymce_elements $htmlarea_id - } - set tinymce_config $::acs_blank_master(tinymce.config) - - # Figure out the language to use - # 1st is the user language, if not available then the system one, - # fallback to english which is provided by default - - set tinymce_relpath "packages/acs-templating/www/resources/tinymce/jscripts/tiny_mce" - set lang_list [list [lang::user::language] [lang::system::language]] - set tinymce_lang "en" - foreach elm $lang_list { - if { [file exists $::acs::rootdir/${tinymce_relpath}/langs/${elm}.js] } { - set tinymce_lang $elm - break - } +set jsSpecs [parameter::get -package_id [ad_conn subsite_id] -parameter ThemeJS -default ""] +if {![string is list $jsSpecs]} { + ns_log error "ignore value in ThemeJS since it is not a valid list: $jsSpecs" +} else { + foreach jsSpec $jsSpecs { + if {[catch {template::add_script {*}$jsSpec} errorMsg]} { + ns_log error $errorMsg + } } - - # TODO : each element should have it's own init - # Antonio Pisano 2015-03-27: including big javascripts in head is discouraged by current best practices for web. - # We should consider moving every inclusion like this in the body. As consequences are non-trivial, just warn for now. - template::head::add_javascript -script " - tinyMCE.init(\{language: \"$tinymce_lang\", $tinymce_config\}); - " -order tinymceZ } +# +# Render richtext widgets: The richtext widgets require typically a +# single configuration for all richtext widgets of a certain type on a +# page (that might require a list of the HTML IDs of all affected +# textareas). +# +# We check whether render_widgets command exists, as during a release +# upgrade this could be missing and would prevent any further action +# on the system after installing new code +if {[info proc ::template::util::richtext::render_widgets] ne ""} { + ::template::util::richtext::render_widgets +} else { + ns_log warning "::template::util::richtext::render_widgets not defined. Richtext widgets won't work. Try restarting the server." +} +# +# Get the basic content info like title and charset for the head of +# the page. +# + if {![info exists doc(title)]} { - set doc(title) "[ad_conn instance_name]" - ns_log warning "[ad_conn url] has no doc(title) set." + set doc(title) [ad_conn instance_name] + ns_log warning "[ad_conn url] has no doc(title) set, fallback to instance_name." } -# AG: Markup in tags doesn't render well. -set doc(title) [ns_striphtml $doc(title)] if {![info exists doc(charset)]} { set doc(charset) [ns_config ns/parameters OutputCharset [ad_conn charset]] } -template::head::add_meta \ - -content "text/html; charset=$doc(charset)" \ - -http_equiv "content-type" -template::head::add_meta \ - -content "text/css" \ - -http_equiv "Content-Style-Type" -template::head::add_meta \ - -content "text/javascript" \ - -http_equiv "Content-Script-Type" - +# # The document language is always set from [ad_conn lang] which by default # returns the language setting for the current user. This is probably # not a bad guess, but the rest of OpenACS must override this setting when -# appropriate and set the lang attribxute of tags which differ from the language +# appropriate and set the lang attribute of tags which differ from the language # of the page. Otherwise we are lying to the browser. +# set doc(lang) [ad_conn language] + +template::head::add_meta \ + -content "text/html; charset=$doc(charset)" \ + -http_equiv "content-type" +# +# The following meta tags are unknwon for HTML5, therefore discouraged +# +# template::head::add_meta \ +# -content "text/css" \ +# -http_equiv "Content-Style-Type" +# template::head::add_meta \ +# -content "text/javascript" \ +# -http_equiv "Content-Script-Type" + + # Determine if we should be displaying the translation UI # if {[lang::util::translator_mode_p]} { @@ -258,17 +218,70 @@ } if {[info exists focus] && $focus ne ""} { - # Handle elements where the name contains a dot + # + # Handle only values of focus where the provided name contains a + # dot. + # if { [regexp {^([^.]*)\.(.*)$} $focus match form_name element_name] } { - template::add_body_handler \ - -event onload \ - -script "acs_Focus('${form_name}', '${element_name}');" \ - -identifier "focus" + set focus_script { + function acs_Focus(form_name, element_name) { + if (document.forms == null) return; + if (document.forms[form_name] == null) return; + if (document.forms[form_name].elements[element_name] == null) return; + if (document.forms[form_name].elements[element_name].type == 'hidden') return; + + document.forms[form_name].elements[element_name].focus(); + }; + } + append focus_script "acs_Focus('${form_name}', '${element_name}');\n" + template::add_body_script -script $focus_script + } else { + ns_log warning "blank-master: variable focus has invalid value '$focus'" } } +# # Retrieve headers and footers +# set header [template::get_header_html] set footer [template::get_footer_html] + +# +# Body event handlers are converted into body_scripts +# +template::get_body_event_handlers + +# +# Build multirows: this has to be done after get_body_event_handlers +# to include these body_scripts as well. +# template::head::prepare_multirows -set event_handlers [template::get_body_event_handlers] + +# +# Add the content security policy. Since this is the blank master, we +# are defensive and check, if the system has already support for it +# via the CSPEnabledP kernel parameter. Otherwise users would be +# blocked out. +# +if {[parameter::get -parameter CSPEnabledP -package_id [ad_acs_kernel_id] -default 0] + && [info commands ::security::csp::render] ne "" +} { + set csp [::security::csp::render] + if {$csp ne ""} { + + set ua [ns_set iget [ns_conn headers] user-agent] + if {[regexp {Trident/.*rv:([0-9]{1,}[\.0-9]{0,})} $ua]} { + set field X-Content-Security-Policy + } else { + set field Content-Security-Policy + } + + ns_set put [ns_conn outputheaders] $field $csp + } +} + +# Local variables: +# mode: tcl +# tcl-indent-level: 4 +# indent-tabs-mode: nil +# End: