Index: openacs-4/packages/cookie-consent/README =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/README,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/README 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,80 @@ + +Integration of the Cookie Consent Library into OpenACS + +The Cookie Consent Library is and Cookie Consent to be free and +open sourced library for for alerting users about the use of +cookies on a website. It is designed to help you comply with the +hideous EU Cookie Law and not make you want to kill yourself in +the process. So we made it fast, free, and relatively painless. + +Details: + https://cookieconsent.insites.com/ + https://github.com/insites/cookieconsent/ + +This package integrates the Consent Plugin with OpenACS, +in particular with OpenACS subsites. + +So far, this package supports on the "inform" type of cookie consent +policies. When the "opt-out" or "opt-in" variants of the policies +should really include all types of cookies (even session-cookies) +the user would not be able to login to the site. However, +most countries stick for now to the "inform" policy, and the +detailed regulation are still in flux. + +FEATURES: + +- Configure the appearance of the cookie consent widget via + the following parameter (on acs-subsite): + CookieConsentEnabled 0|1 + CookieConsentPosition bottom|top|pushdown|left|right + CookieConsentLayout block|classic|edgeless|wire + CookieConsentPalette oacs|honeybee|mono|neon|corporate + LearnMoreLink https://cookiesandyou.com/ + CookieConsentDefaultPalette + +- Usage from CDN (out-of-the box) or from + a local copy (download your local copy via + "Site-Wide Admin" link in /acs-admin/) + +- Support for host-node-mapped subsites +- Internationalized with OpenACS message keys + + +INSTALLATON: + 1) Install this package + via the OpenACS Package Manager + + 2) Add this package to the templating system + + - OpenACS 5.10.0d2: or newer + The cookie consent widgets uses the "subsite::page_plugin" + callback, so no changes on templates are necessary + + - OpenACS 5.9.1: + Add to the top of your blank-master.tcl the following snippet: + + ================================================================ + if {[info commands ::cookieconsent::initialize_widget] ne ""} { + ::cookieconsent::initialize_widget + } + ================================================================ + + 3) Configure in the parameters of the subsite (e.g. the main subsite) + the section "Cookie Consent" + + +PREREQUIREMENTS: + +The implementation uses nx from the next-scripting framework. + + https://next-scripting.org/xowiki/ + +which is automatically installed for XOTcl2 via +https://openacs.org/xowiki/naviserver-openacs + +It works best with OpenACS 5.10.0d2 or newer, but works as well +with 5.9.1 (see INSTALLATION section above) or earlier versions +supporting Content Security Policy (CSP), and probably with +earlier versions as well, when CSP code is commented out. + + Index: openacs-4/packages/cookie-consent/cookie-consent.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/cookie-consent.info,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/cookie-consent.info 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,38 @@ + + + + + Cookie Consent Widget + Cookie Consent Widgets + f + t + f + f + + + Gustaf Neumann + Cookie Consent Widget based on the free + Cookie Consent Library + 2017-12-13 + MIT License + 0 + + + + + + + + + + + + + + + + Index: openacs-4/packages/cookie-consent/catalog/cookie-consent.en_US.ISO-8859-1.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/catalog/cookie-consent.en_US.ISO-8859-1.xml,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/catalog/cookie-consent.en_US.ISO-8859-1.xml 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,7 @@ + + + + Got it! + This website uses cookies to ensure you get the best experience on our website + Learn more + Index: openacs-4/packages/cookie-consent/tcl/callback-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/tcl/callback-procs.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/tcl/callback-procs.tcl 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,92 @@ +ad_library { + + Callback procs for Cookie Consent Library into OpenACS + + + @author Gustaf Neumann + @creation-date 13 Dec 2017 + @cvs-id $Id: callback-procs.tcl,v 1.1 2017/12/17 19:55:03 gustafn Exp $ +} + +namespace eval ::cookieconsent { + + # + # Provide hooks for installing/uninstalling the package + # + ad_proc -private after-install {} { + # + # Add additional parameters to acs-subsite + # + foreach {name description default datatype} { + "Enabled" + "Enable/Disable Cookie Consent for this Subsite" + "0" "number" + + "Layout" + "Layout of the Cookie Consent Widget; possible values: block|classic|edgeless|wire" + "block" "string" + + "LearnMoreLink" + "Link for learning more about Cookies" + "https://cookiesandyou.com/" "string" + + "Palette" + "Color palette for the Cookie Consent Widget; possible values: default|oacs|honeybee|mono|neon|corporate" + "default" "string" + + "Position" + "Position of the Cookie Consent Widget; possible values: bottom|top|pushdown|left|right" + "pushdown" "string" + + "DefaultPalette" + "Default style: use the following settings, when CookieConsentPalette is set to 'default'" + "popup {text #fff background #004570} button {text #000 background #f1d600}" "string" + + } { + apm_parameter_register "CookieConsent$name" \ + $description "acs-subsite" $default $datatype "Cookie Consent" + } + } + + ad_proc -private before-uninstall {} { + # + # Remove the package specific parameters from acs-subsite + # + foreach parameter { + Enabled + Layout + LearnMoreLink + Palette + Position + DefaultPalette + } { + ns_log notice [list apm_parameter_unregister \ + -parameter "CookieConsent$parameter" \ + -package_key "acs-subsite" \ + "" ] + ::try { + apm_parameter_unregister \ + -parameter "CookieConsent$parameter" \ + -package_key "acs-subsite" \ + "" + } on error {errMsg} { + ns_log notice "apm_parameter_unregister of parameter CookieConsent$parameter lead to: $errMsg" + } + } + } + + + # + # Register a "page_plugin" callback for the subsite. In case, this + # is used with an OpenACS version earlier than 5.10.0d2, this is + # essentially no-op operation; the site admin has to add the + # "::cookieconsent::initialize_widget" manually to the templates. + # + ad_proc -public -callback subsite::page_plugin -impl cookie-consent { + } { + Implementation of subsite::page_plugin for cookie-consent + } { + ::cookieconsent::initialize_widget + } + +} Index: openacs-4/packages/cookie-consent/tcl/cookie-consent-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/tcl/cookie-consent-procs.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/tcl/cookie-consent-procs.tcl 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,390 @@ +ad_library { + + Integration of the Cookie Consent Library into OpenACS + + The Cookie Consent Library is and Cookie Consent to be free and + open sourced library for for alerting users about the use of + cookies on a website. It is designed to help you comply with the + hideous EU Cookie Law and not make you want to kill yourself in + the process. So we made it fast, free, and relatively painless. + + Details: + https://cookieconsent.insites.com/ + https://github.com/insites/cookieconsent/ + + This package integrates the Consent Plugin with OpenACS, + in particular with OpenACS subsites. + + @author Gustaf Neumann + @creation-date 13 Dec 2017 + @cvs-id $Id: cookie-consent-procs.tcl,v 1.1 2017/12/17 19:55:03 gustafn Exp $ +} + +namespace eval ::cookieconsent { + + set package_id [apm_package_id_from_key "cookieconsent"] + + # + # It is possible to configure the version of the cookie consent + # widget also via NaviServer config file: + # + # ns_section ns/server/${server}/acs/cookie-consent + # ns_param version cookieconsent2/3.0.3 + # + + set version [parameter::get \ + -package_id $package_id \ + -parameter Version \ + -default cookieconsent2/3.0.3] + + ad_proc -private get_relevant_subsite {} { + } { + set dict [security::get_register_subsite] + if {![dict exists $dict subsite_id]} { + set subsite_id [site_node::get_object_id \ + -node_id [dict get $dict host_node_id]] + } else { + set subsite_id [dict get $dict subsite_id] + } + return $subsite_id + } + + ad_proc reset_cookie { + {-subsite_id ""} + } { + + Reset the consent cookie. + + } { + if {$subsite_id eq ""} { + set subsite_id [get_relevant_subsite] + } + ad_unset_cookie "cookieconsent_status-$subsite_id" + } + + # + # Create the Class for configuring the cookie consent widget. + # This class requires nx from the next-scripting framework. + # + # https://next-scripting.org/xowiki/ + # + # which is automatically installed for XOTcl2 via + # https://openacs.org/xowiki/naviserver-openacs + # + nx::Class create CookieConsent { + :property {position pushdown};# bottom|top|pushdown|left|right + :property {layout block} ;# block|classic|edgeless|wire + :property {palette default} ;# default|oacs|honeybee|mono|neon|corporate + :property {learn-more-link https://cookiesandyou.com/} + :property {default-palette {popup {text #fff background #004570} button {text #000 background #f1d600}}} + + :property {compliance-type inform} ;# inform|opt-out|opt-in + :property {message-text "#cookie-consent.message#"} + :property {dismiss-button-text "#cookie-consent.dismiss-button-text#"} + :property {policy-link-text "#cookie-consent.policy-link-text#"} + + :property {subsite_id:required} + + :public method render_js {} { + + set static false + if {${:position} eq "pushdown"} { + set position top + set static true + } elseif {${:position} in {"left" "right"}} { + set position bottom-${:position} + } else { + set position ${:position} + } + + # + # Set up a dictionary for the palette with common + # settings: + # + set d {popup {text #fff} button {text #000}} + + # + # Update the default palette based on the value of the + # passed-in palette. + # + switch ${:palette} { + oacs { + dict set d popup background \#004570 + dict set d button background \#f1d600 + } + honeybee { + dict set d popup background \#000 + dict set d button background \#f1d600 + } + mono { + dict set d popup background \#237afc + dict set d button background transparent + dict set d button text \#fff + dict set d button border \#fff + } + neon { + dict set d popup background \#1d8a8a + dict set d button background \#62ffaa + } + corporate { + dict set d popup background \#edeff5 + dict set d popup text \#838391 + dict set d button background \#4b81e8 + } + default { + set d ${:default-palette} + } + } + + # + # We have to juggle the colors depending on the layout + # + set buttonBackground [dict get $d button background] + set buttonTextColor [dict get $d button text] + if {[dict exists $d button border]} { + set buttonBorder [dict get $d button border] + } else { + set buttonBorder $buttonBackground + } + switch ${:layout} { + block - + classic - + edgeless {set theme ${:layout}} + wire { + set theme block + set buttonBackground transparent + set buttonTextColor [dict get $d button background] + } + } + + # + # Use different cookies dependent on the subsite + # + set cookie_name "cookieconsent_status-${:subsite_id}" + + set js [subst { + window.addEventListener("load", function(){ + window.cookieconsent.initialise({ + "palette": { + "popup": { + "background": "[dict get $d popup background]", + "text": "[dict get $d popup text]", + }, + "button": { + "background": "$buttonBackground", + "border": "$buttonBorder", + "text": "$buttonTextColor" + } + }, + "cookie": { + "name": "$cookie_name", + "path": "/", + "domain": "", + "expiryDays": "365" + }, + "theme": "$theme", + "position": "$position", + "static": $static, + "content": { + "message": "[lang::util::localize ${:message-text}]", + "dismiss": "[lang::util::localize ${:dismiss-button-text}]", + "link": "[lang::util::localize ${:policy-link-text}]", + "href": "${:learn-more-link}", + "header": "Cookies used on the website!", + "deny": "Decline", + "allow": "Allow cookies" + } + })}); + }] + return $js + } + } + + ad_proc initialize_widget { + {-subsite_id ""} + } { + + Initialize an cookie-consent widget. + + } { + if {$subsite_id eq ""} { + set subsite_id [get_relevant_subsite] + } + + set enabled_p [parameter::get \ + -package_id $subsite_id \ + -parameter CookieConsentEnabled \ + -default 0] + if {$enabled_p} { + # + # Create an instance of the widget class from all configuration options + # + foreach {param default} { + Layout block + Palette oacs + Position bottom + LearnMoreLink https://cookiesandyou.com/ + DefaultPalette "popup {text #fff background #004570} button {text #000 background #f1d600}" + } { + set p($param) [parameter::get \ + -package_id $subsite_id \ + -parameter CookieConsent$param \ + -default $default] + } + + set c [CookieConsent new \ + -subsite_id $subsite_id \ + -position $p(Position) \ + -palette $p(Palette) \ + -layout $p(Layout) \ + -learn-more-link $p(LearnMoreLink) \ + -default-palette $p(DefaultPalette) \ + ] + # + # ... and add it to the page + # + add_to_page -version "" $c + $c destroy + } + } + + + ad_proc version_info { + {-version ""} + } { + + Get information about available version(s) of the + cookieconsent packages, either from the local file system, or + from CDN. + + } { + # + # If no version of the cookie consent library was specified, + # use the name-spaced variable as default. + # + if {$version eq ""} { + set version ${::cookieconsent::version} + } + + # + # Provide paths for loading either via resources or CDN + # + set resource_prefix [acs_package_root_dir cookie-consent/www/resources] + set cdn "//cdnjs.cloudflare.com/ajax/libs" + + # + # If the resources are not available locally, these will be + # loaded via CDN and the CDN host is set (necessary for CSP). + # The returned "prefix" indicates the place, from where the + # resource will be loaded. + # + if {[file exists $resource_prefix/$version]} { + set prefix /resources/cookie-consent/$version/ + } else { + set prefix $cdn/$version/ + lappend result host "cdnjs.cloudflare.com" + } + lappend result \ + cdn $cdn \ + prefix $prefix \ + cssFiles [list cookieconsent.min.css] \ + jsFiles [list cookieconsent.min.js] + + return $result + } + + + ad_proc add_to_page { + {-version ""} + object + } { + Add the necessary CSS, JavaScript and CSP to the current + page. + } { + set version_info [version_info -version $version] + + if {[dict exists $version_info host]} { + security::csp::require script-src [dict get $version_info host] + security::csp::require style-src [dict get $version_info host] + } + set prefix [dict get $version_info prefix] + + foreach cssFile [dict get $version_info cssFiles] { + template::head::add_css -href $prefix/$cssFile + } + foreach jsFile [dict get $version_info jsFiles] { + template::head::add_javascript -src $prefix/$jsFile + } + + ::template::add_body_script -script [$object render_js] + } + + + ad_proc -private download_file {url} { + # + # Helper to download from an URL and to raise exception, when + # download fails. + # + } { + set result [util::http::get -url $url -spool] + if {[dict get $result status] == 200} { + set fn [dict get $result file] + return $fn + } else { + error "download from $url failed: $result" + } + } + + + ad_proc download { + {-version ""} + } { + + Download a version of the cookie consent library + it into a directory structure similar to the CDN structure to + allow installation of multiple versions. When the local + structure is available, it will be used by initialize_widget. + + } { + # + # If no version is explicitly specified, use the name-spaced + # variable as default. + # + if {$version eq ""} { + set version ${::cookieconsent::version} + } + + set version_info [version_info -version $version] + + set download_prefix https:[dict get $version_info cdn] + set resource_prefix [acs_package_root_dir cookie-consent/www/resources/] + + # + # Do we have a writable output directory under resources? + # + if {![file isdirectory $resource_prefix/$version]} { + file mkdir $resource_prefix/$version + } + if {![file writable $resource_prefix/$version]} { + error "directory $resource_prefix/$version is not writable" + } + + # + # So far, everything is fine, download the + # files. "download_file" will raise an exception, when the + # download fails. + # + foreach file [concat \ + [dict get $version_info cssFiles] \ + [dict get $version_info jsFiles]] { + set fn [download_file $download_prefix/$version/$file] + file rename -force -- $fn $resource_prefix/$version/$file + } + } +} + +# Local variables: +# mode: tcl +# tcl-indent-level: 4 +# indent-tabs-mode: nil +# End: Index: openacs-4/packages/cookie-consent/www/sitewide-admin/download.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/www/sitewide-admin/download.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/www/sitewide-admin/download.tcl 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,10 @@ +ad_page_contract { + @author Gustaf Neumann + + @creation-date Dec 13, 2017 +} { + {version:word,notnull ""} +} + +::cookieconsent::download -version $version +ad_returnredirect . Index: openacs-4/packages/cookie-consent/www/sitewide-admin/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/www/sitewide-admin/index.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/www/sitewide-admin/index.adp 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,20 @@ + +@title;literal@ +@context;literal@ + +

@title;noquote@

+

+The current version of the @what@ is @version@. +

This version of the @what@ is installed locally +under @resources@ +

In the current installation the @what@ is used via CDN @cdn@. + +

Do you want to download + version @version@ of @what@ to your file system?

+ + +

The directory @path@ is NOT writable for the server. In + order to be able to download the @what@ via this web interface, + please change the permissions so that OpenACS can write to it.

+
+. \ No newline at end of file Index: openacs-4/packages/cookie-consent/www/sitewide-admin/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/cookie-consent/www/sitewide-admin/index.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/cookie-consent/www/sitewide-admin/index.tcl 17 Dec 2017 19:55:03 -0000 1.1 @@ -0,0 +1,24 @@ +set title "Cookie Consent Sitewide Admin" +set context [list $title] + +set resource_prefix [acs_package_root_dir cookie-consent/www/resources] +set what "Cookie Consent Widget" +set version $::cookieconsent::version + +# +# Get version info about the resource files of this package. If not +# locally installed, offer a link for download. +# +set version_info [::cookieconsent::version_info] +set first_css [lindex [dict get $version_info cssFiles] 0] + +if {[file exists $resource_prefix/$version/$first_css]} { + set resources $resource_prefix/$version +} +set cdn [dict get $version_info cdn] + +set path $resource_prefix/$version +if {![file exists $path]} { + catch {file mkdir $path} +} +set writable [file writable $path]