Index: openacs-4/packages/acs-templating/tcl/head-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/head-procs.tcl,v diff -u -r1.20 -r1.21 --- openacs-4/packages/acs-templating/tcl/head-procs.tcl 27 Oct 2014 16:40:11 -0000 1.20 +++ openacs-4/packages/acs-templating/tcl/head-procs.tcl 7 Aug 2017 23:48:02 -0000 1.21 @@ -19,55 +19,96 @@ handled by the templating system. } { array unset ::template::head::scripts - #array set ::template::head::scripts [list] - array unset ::template::head::links - #array set ::template::head::links [list] - array unset ::template::head::metas - #array set ::template::head::metas [list] - array unset ::template::body_handlers - #array set ::template::head::body_handlers [list] - array unset ::template::body_scripts - #array set ::template::body_scripts [list] set ::template::headers [list] set ::template::footers [list] } -ad_proc -public template::head::add_script { - {-type:required} - {-defer:boolean} +ad_proc -public template::add_script { {-async:boolean} - {-src ""} {-charset ""} + {-crossorigin ""} + {-defer:boolean} + {-integrity ""} + {-order "0"} {-script ""} + {-section "head"} + {-src ""} + {-type "text/javascript"} +} { + @param async whether execution of the script should be executed asynchronously + as soon as it is available + @param charset the charset attribute of the script tag, ie. the character + set of the script if it differs from the main document + @param crossorigin Enumerated attribute to indicate whether CORS + (Cross-Origin Resource Sharing) should be used + @param defer whether execution of the script should be defered until after + the page has been loaded + @param integrity provide hash values for W3C Subresource Integrity recommentation + @param order specify inclusion order + @param script the inline script for the body of the script tag. This + parameter will be ignored if a value has been supplied for src + @param section section, where script is added ("head" or "body") + @param src the src attribute of the script tag, ie. the source url of the + script + @param type the type attribute of the script tag, eg. 'text/javascript' +} { + if {$section eq "head"} { + # + # A head script + # + ::template::head::add_script -type $type -defer=$defer_p -async=$async_p \ + -src $src -charset $charset -script $script -order $order \ + -crossorigin $crossorigin -integrity $integrity + } else { + # + # A body script. The order is ignored. + # + ::template::add_body_script -type $type -defer=$defer_p -async=$async_p \ + -src $src -charset $charset -script $script \ + -crossorigin $crossorigin -integrity $integrity + } +} + +ad_proc -public template::head::add_script { + {-async:boolean} + {-charset ""} + {-crossorigin ""} + {-defer:boolean} + {-integrity ""} {-order "0"} + {-script ""} + {-src ""} + {-type "text/javascript"} } { Add a script to the head section of the document to be returned to the - users client. A script library in an external file may only be included - once; subsequent calls to add_script will replace the existing entry. - Anonymous script blocks will be added without checking for duplicates; the - caller must ensure that anonymous script blocks are not inadvertantly added + users client. A script library in an external file may only be included + once; subsequent calls to add_script will replace the existing entry. + Anonymous script blocks will be added without checking for duplicates; the + caller must ensure that anonymous script blocks are not inadvertently added multiple times. You must supply either src or script. - @param type the type attribute of the script tag, eg. 'text/javascript' - @param defer whether execution of the script should be defered until after - the page has been loaded @param async whether execution of the script should be executed asynchronously as soon as it is available + @param charset the charset attribute of the script tag, ie. the character + set of the script if it differs from the main document + @param crossorigin Enumerated attribute to indicate whether CORS + (Cross-Origin Resource Sharing) should be used + @param defer whether execution of the script should be defered until after + the page has been loaded + @param integrity provide hash values for W3C Subresource Integrity recommentation + @param order specify inclusion order + @param script the inline script for the body of the script tag. This + parameter will be ignored if a value has been supplied for src @param src the src attribute of the script tag, ie. the source url of the script - @param charset the charset attribute of the script tag, ie. the character - set of the script if it differs from the main document - @param script the inline script for the body of the script tag. This - parameter will be ignored if a value has been supplied for - src -} { - variable ::template::head::scripts + @param type the type attribute of the script tag, eg. 'text/javascript' +} { if {$defer_p} { set defer defer } else { @@ -85,42 +126,56 @@ error "You must supply either -src or -script." } - lappend scripts(anonymous) $type "" $charset $defer $async $script $order + # + # For the time being, not all browsers support + # nonces. According to the specs the added 'unsafe-inline', + # is ignored on browsers supporting nonces. + # + # We could restrict setting of unsafe-inline to certain + # browsers by checking the user agent. + # + security::csp::require script-src 'unsafe-inline' + + lappend ::template::head::scripts(anonymous) $type "" $charset $defer $async $script $order $crossorigin $integrity } else { - set scripts($src) [list $type $src $charset $defer $async "" $order] + set ::template::head::scripts($src) [list $type $src $charset $defer $async "" $order $crossorigin $integrity] } } ad_proc -public template::head::add_link { - {-rel:required} + {-crossorigin ""} {-href:required} - {-type ""} - {-media ""} - {-title ""} + {-integrity ""} {-lang ""} + {-media ""} {-order "0"} + {-rel:required} + {-title ""} + {-type ""} } { Add a link tag to the head section of the document to be returned to the - users client. A given target document may only be added once for a - specified relation; subsequent calls to add_link will replace the existing - entry. + users client. A given target document may only be added once for a + specified relation; subsequent calls to add_link will replace the existing + entry. - @param rel the rel attribute of the link tag defining the relationship - of the linked document to the current one, eg. 'stylesheet' + @param crossorigin Enumerated attribute to indicate whether CORS + (Cross-Origin Resource Sharing) should be used @param href the href attribute of the link tag, eg. the target document of the link - @param type the type attribute of the link tag, eg. 'text/css' + @param integrity provide hash values for W3C Subresource Integrity recommentation + @param lang the lang attribute of the link tag specifying the language + of its attributes if they differ from the document language @param media the media attribute of the link tag describing which display - media this link is relevant to. This may be a comma - separated list of values, eg. 'screen,print,braille' + media this link is relevant to. This may be a comma + @param order specify inclusion order + @param rel the rel attribute of the link tag defining the relationship + of the linked document to the current one, eg. 'stylesheet' @param title the title attribute of the link tag describing the target of - this link - @param lang the lang attribute of the link tag specifying the language - of its attributes if they differ from the document language + this link + @param type the type attribute of the link tag, eg. 'text/css' + separated list of values, eg. 'screen,print,braille' } { - variable ::template::head::links - - set links($rel,$href) [list $rel $href $type $media $title $lang $order] + set ::template::head::links($rel,$href) [list $rel $href $type $media $title $lang $order $crossorigin $integrity] } ad_proc -public template::head::add_meta { @@ -132,20 +187,20 @@ } { Add a meta tag to the head section of the document to be returned to the users client. A meta tag with a given name or http-equiv may only be added - once; subsequent calls to add_meta will replace the existing entry. You + once; subsequent calls to add_meta will replace the existing entry. You must supply either name or http_equiv. - @param http_equiv the http-equiv attribute of the meta tag, ie. the + @param http_equiv the http-equiv attribute of the meta tag, ie. the HTTP header which this metadata is equivalent to eg. 'content-type' - @param name the name attribute of the meta tag, ie. the metadata + @param name the name attribute of the meta tag, ie. the metadata identifier - @param scheme the scheme attribute of the meta tag defining which - metadata scheme should be used to interpret the metadata, + @param scheme the scheme attribute of the meta tag defining which + metadata scheme should be used to interpret the metadata, eg. 'DC' for Dublin Core (http://dublincore.org/) @param content the content attribute of the meta tag, ie the metadata value - @param lang the lang attribute of the meta tag specifying the language + @param lang the lang attribute of the meta tag specifying the language of its attributes if they differ from the document language } { variable ::template::head::metas @@ -172,58 +227,80 @@ } { Add an embedded css style declaration - + @author Dave Bauer (dave@thedesignexperience.org) @creation-date 2007-11-30 - + @param style CSS content to be included in the style tag @param type the type attribute of the link tag, eg. 'text/css' @param media the media attribute of the link tag describing which display - media this link is relevant to. This may be a comma + media this link is relevant to. This may be a comma separated list of values, eg. 'screen,print,braille' @param title the title attribute of the link tag describing the target of - this link - @param lang the lang attribute of the link tag specifying the language + this link + @param lang the lang attribute of the link tag specifying the language of its attributes if they differ from the document language } { variable ::template::head::styles + if {[info exists styles(anonymous)]} { + # + # Add this combination only once + # + foreach {_type _media _title _lang _style} $styles(anonymous) { + if {$type eq $_type + && $_media eq $media + && $_title eq $title + && $_lang eq $lang + && $_style eq $style + } { + return + } + } + } lappend styles(anonymous) $type $media $title $lang $style - } ad_proc -public template::head::add_javascript { - {-defer:boolean} {-async:boolean} - {-src ""} {-charset ""} - {-script ""} + {-crossorigin ""} + {-defer:boolean} + {-integrity ""} {-order "0"} + {-script ""} + {-src ""} } { - Add a script of type 'text/javascript' to the head section of the document - to be returned to the users client. This function is a wrapper around + Add a script of type 'text/javascript' to the head section of the document + to be returned to the users client. This function is a wrapper around template::head::add_script. You must supply either src or script. - @param defer whether execution of the script should be defered until after - the page has been loaded @param async whether execution of the script should be executed asynchronously as soon as it is available - @param src the src attribute of the script tag, ie. the source url of the - script - @param charset the charset attribute of the script tag, ie. the character + @param charset the charset attribute of the script tag, ie. the character set of the script if it differs from the main document - @param script the inline script for the body of the script tag. This + @param crossorigin Enumerated attribute to indicate whether CORS + (Cross-Origin Resource Sharing) should be used + @param defer whether execution of the script should be defered until after + the page has been loaded + @param integrity provide hash values for W3C Subresource Integrity recommentation + @param order specify inclusion order + @param script the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src + @param src the src attribute of the script tag, ie. the source url of the + script @see template::head::add_script } { - template::head::add_script -defer=$defer_p -async=$async_p \ + template::head::add_script \ + -defer=$defer_p -async=$async_p \ -type text/javascript \ -src $src \ -charset $charset \ -script $script \ - -order $order + -order $order \ + -crossorigin $crossorigin -integrity $integrity } ad_proc -public template::head::add_css { @@ -235,22 +312,22 @@ {-order "0"} } { Add a link tag with relation type 'stylesheet' or 'alternate stylesheet', - and type 'text/css' to the head section of the document to be returned to - the users client. A given target stylesheet may only be added once; - subsequent calls to add_css will replace the existing entry. This function - is a wrapper around template::head::add_link. + and type 'text/css' to the head section of the document to be returned to + the users client. A given target stylesheet may only be added once; + subsequent calls to add_css will replace the existing entry. This function + is a wrapper around template::head::add_link. - @param href the href attribute of the link tag, eg. the target + @param href the href attribute of the link tag, eg. the target stylesheet - @param alternate sets the rel attribute of the link tag defining to - 'alternate stylesheet' if set, sets it to 'stylesheet' + @param alternate sets the rel attribute of the link tag defining to + 'alternate stylesheet' if set, sets it to 'stylesheet' otherwise - @param media the media attribute of the link tag describing which - display media this link is relevant to. This may be a + @param media the media attribute of the link tag describing which + display media this link is relevant to. This may be a comma separated list of values, eg. 'screen,print,braille' - @param title the title attribute of the link tag describing the target - of this link - @param lang the lang attribute of the link tag specifying the language + @param title the title attribute of the link tag describing the target + of this link + @param lang the lang attribute of the link tag specifying the language of its attributes if they differ from the document language @see template::head::add_link @@ -275,11 +352,11 @@ {-script:required} {-identifier anonymous} } { - Adds javascript code to an event handler in the body tag. Several - javascript code blocks may be assigned to each handler by subsequent calls + Adds javascript code to an event handler in the body tag. Several + javascript code blocks may be assigned to each handler by subsequent calls to template::add_body_handler. -

If your script may only be added once you may supply an identifier. +

If your script may only be added once you may supply an identifier. Subsequent calls to template::add_body_handler with the same identifier will replace your script rather than appending to it.

@@ -299,7 +376,7 @@
  • onkeyup
  • - @param event the event during which the supplied script should be + @param event the event during which the supplied script should be executed @param script the javascript code to execute @param identifier a name, if supplied, used to ensure this javascript code @@ -313,35 +390,39 @@ # Even a one event handler needs to be added in a list # since all handlers, anonymous and specific are treated as a # list in blank-master.tcl - set body_handlers($event,$identifier) [list $script] + set body_handlers($event,$identifier) [list $script] } } ad_proc -public template::add_body_script { - {-type:required} - {-defer:boolean} {-async:boolean} - {-src ""} {-charset ""} + {-crossorigin ""} + {-defer:boolean} + {-integrity ""} {-script ""} + {-src ""} + {-type "text/javascript"} } { Add a script to the start of the body section of the document to be returned to the users client. You must supply either src or script. - @param type the type attribute of the script tag, eg. 'text/javascript' - @param defer whether execution of the script should be defered until after - the page has been loaded @param async whether execution of the script should be executed asynchronously as soon as it is available - @param src the src attribute of the script tag, ie. the source url of the - script - @param charset the charset attribute of the script tag, ie. the character + @param charset the charset attribute of the script tag, ie. the character set of the script if it differs from the main document - @param script the inline script for the body of the script tag. This + @param crossorigin Enumerated attribute to indicate whether CORS + (Cross-Origin Resource Sharing) should be used + @param defer whether execution of the script should be defered until after + the page has been loaded + @param integrity provide hash values for W3C Subresource Integrity recommentation + @param script the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src + @param src the src attribute of the script tag, ie. the source url of the + script + @param type the type attribute of the script tag, eg. 'text/javascript' } { - variable ::template::body_scripts if {$defer_p} { set defer defer @@ -358,7 +439,19 @@ error "You must supply either -src or -script." } - lappend body_scripts $type $src $charset $defer $async $script + if {$script ne ""} { + # + # For the time being, not all browsers support + # nonces. According to the specs the added 'unsafe-inline', + # is ignored on browsers supporting nonces. + # + # We could restrict setting of unsafe-inline to certain + # browsers by checking the user agent. + # + security::csp::require script-src 'unsafe-inline' + } + + lappend ::template::body_scripts $type $src $charset $defer $async $script $crossorigin $integrity } ad_proc -public template::add_header { @@ -369,15 +462,15 @@ } { Add a header include to the beginning of the document body. This function is used by site wide services to add functionality to the beginning of a - page. Examples include the developer support toolbar, acs-lang translation + page. Examples include the developer support toolbar, acs-lang translation interface and the acs-templating WYSIWYG editor textarea place holder. If you are not implementing a site wide service, you should not be using this function to add content to your page. You must supply either src or html. - @param direction whether the header should be added as the outer most + @param direction whether the header should be added as the outer most page content or the inner most @param src the path to the include - @param params a list of name, value pairs to pass as parameter to the + @param params a list of name, value pairs to pass as parameter to the include @param html literal html to include in the page. This parameter will be ignored if a values has been supplied for src. @@ -414,15 +507,15 @@ } { Add a footer include to the end of the document body. This function is used by site wide services to add functionality to the end of a - page. Examples include the developer support toolbar, acs-lang translation + page. Examples include the developer support toolbar, acs-lang translation interface and the acs-templating WYSIWYG editor textarea place holder. If you are not implementing a site wide service, you should not be using this function to add content to your page. You must supply either src or html. - @param direction whether the footer should be added as the outer most + @param direction whether the footer should be added as the outer most page content or the inner most @param src the path to the include - @param params a list of name, value pairs to pass as parameter to the + @param params a list of name, value pairs to pass as parameter to the include @param html literal html to include in the page. This parameter will be ignored if a values has been supplied for src. @@ -475,11 +568,11 @@ # Generate the tag multirow variable ::template::head::links - template::multirow create link rel type href title lang media order + template::multirow create link rel type href title lang media order crossorigin integrity if {[array exists links]} { # first non alternate stylesheet foreach name [array names links] { - foreach {rel href type media title lang order} $links($name) { + foreach {rel href type media title lang order crossorigin integrity} $links($name) { if {$rel ne "alternate stylesheet"} { template::multirow append link \ $rel \ @@ -488,7 +581,8 @@ $title \ $lang \ $media \ - $order + $order \ + $crossorigin $integrity set links($name) "" } } @@ -497,7 +591,7 @@ template::multirow sort link order # now alternate stylesheet foreach name [array names links] { - foreach {rel href type media title lang order} $links($name) { + foreach {rel href type media title lang order crossorigin integrity} $links($name) { if {$links($name) ne ""} { template::multirow append link \ $rel \ @@ -506,15 +600,16 @@ $title \ $lang \ $media \ - $order + $order \ + $crossorigin $integrity set links($name) "" } } } - unset links + array unset links } - # Generate the