PluginProbe
CookieAdmin – Cookie Consent Banner / 1.2.3
CookieAdmin – Cookie Consent Banner v1.2.3
1.2.3 1.2.2 1.2.1 1.2.0 1.1.9 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8
← All changes | includes/enduser.php +349 -64 1.0.21.2.3 View file →
@@ -12,20 +12,30 @@
12 12 static $categorized_cookies = array();
13 13
14 14 static function enqueue_scripts(){
15 15 global $wpdb;
16 -
17 - $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
16 +
17 + $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
18 18 $policy = cookieadmin_load_policy();
19 19 $table_name = esc_sql($wpdb->prefix . 'cookieadmin_cookies');
20 20 //cookieadmin_r_print($view);
21 21 //cookieadmin_r_print($policy);
22 22
23 - if(!empty($policy) && !empty($view)){
23 + if(!empty($policy) && !empty($view) && !cookieadmin_is_editor_mode()){
24 +
25 + add_filter('mepr_design_style_handle_prefixes', '\CookieAdmin\Enduser::memberpress_allow_style_prefix');
24 26
25 - wp_enqueue_style('cookieadmin-style', COOKIEADMIN_PLUGIN_URL . 'assets/css/cookie.css', [], COOKIEADMIN_VERSION);
27 + wp_enqueue_style('cookieadmin-style', COOKIEADMIN_PLUGIN_URL . 'assets/css/consent.css', [], COOKIEADMIN_VERSION);
26 28
27 - wp_enqueue_script('cookieadmin_js', COOKIEADMIN_PLUGIN_URL . 'assets/js/consent.js', [], COOKIEADMIN_VERSION, 'async');
29 + $js_deps = [];
30 + // Free consent.js is the base script from where the functionality gets triggered
31 + // So we need to make sure the dependencies of free script gets loaded first
32 + // Like the pro/consent.js is a dependency of the free one.
33 + if(defined('COOKIEADMIN_PREMIUM')){
34 + $js_deps[] = 'cookieadmin_pro_js';
35 + }
36 +
37 + wp_enqueue_script('cookieadmin_js', COOKIEADMIN_PLUGIN_URL . 'assets/js/consent.js', $js_deps, COOKIEADMIN_VERSION);
28 38
29 39 $policy[$view]['ajax_url'] = admin_url('admin-ajax.php');
30 40 $policy[$view]['nonce'] = wp_create_nonce('cookieadmin_js_nonce');
31 41 $policy[$view]['http_cookies'] = self::$http_cookies;
@@ -31,8 +41,22 @@
31 41 $policy[$view]['http_cookies'] = self::$http_cookies;
32 42 $policy[$view]['home_url'] = home_url();
33 43 $policy[$view]['plugin_url'] = COOKIEADMIN_URL;
34 44 $policy[$view]['is_pro'] = (defined('COOKIEADMIN_PREMIUM') ? COOKIEADMIN_PREMIUM : 0);
45 + $policy[$view]['ssl'] = is_ssl();
46 +
47 + $base_path = parse_url(home_url(), PHP_URL_PATH) ?: '/';
48 + $base_path = ($base_path !== '/') ? rtrim($base_path, '/') . '/' : '/';
49 +
50 + // Used for setting cookie
51 + $policy[$view]['base_path'] = $base_path;
52 +
53 + // NOTE: Check the polylang string registration if changing these
54 + $policy[$view]['lang']['show_less'] = __('Show less', 'cookieadmin');
55 + $policy[$view]['lang']['duration'] = __('Duration', 'cookieadmin');
56 + $policy[$view]['lang']['session'] = __('Session', 'cookieadmin');
57 + $policy[$view]['lang']['days'] = __('Days', 'cookieadmin');
58 +
35 59 // cookieadmin_r_print($policy);die();
36 60
37 61 $rows = $wpdb->get_results("SELECT cookie_name, category, expires, description, patterns FROM {$table_name}");
38 62 $cookie_data = array();
@@ -42,105 +66,363 @@
42 66 }
43 67
44 68 $policy[$view]['categorized_cookies'] = self::$categorized_cookies = $cookie_data;
45 69
70 + $policy[$view] = apply_filters('cookieadmin_before_localize', $policy[$view]);
71 +
46 72 wp_localize_script('cookieadmin_js', 'cookieadmin_policy', $policy[$view]);
73 +
47 74 }
48 75 }
49 76
50 - /* static function cookieadmin_block_cookie_init_php(){
77 + static function cookieadmin_block_cookie_init_php(){
51 78
52 - //New - To catch, remove and send cookies in WP enqueue
79 + if(headers_sent() || (is_admin() && !wp_doing_ajax()) || defined('COOKIEADMIN_SCANNER') || cookieadmin_is_editor_mode()){
80 + return;
81 + }
82 +
83 + $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
84 +
85 + if(empty($view)){
86 + return;
87 + }
88 +
53 89 $http_cookies = array();
54 - $headers = headers_list();
90 + $set_cookie_headers = array();
55 91
56 - foreach($headers as $header) {
57 -
58 - if (stripos(trim($header), 'Set-Cookie:') === 0) {
92 + foreach(headers_list() as $header) {
93 + if(stripos(trim($header), 'Set-Cookie:') === 0){
59 94 $header = trim(substr($header, strlen('Set-Cookie:')));
60 - $name = trim(explode('=', $header)[0]);
61 - $http_cookies[$name]['string'] = trim($header);
62 - setcookie($name, '', time() - 999999, '/');
95 + $set_cookie_headers[] = $header;
63 96 }
64 97 }
65 98
99 + if(empty($set_cookie_headers)){
100 + return;
101 + }
102 +
103 + $policy = cookieadmin_load_policy();
104 +
105 + if(empty($policy) || empty($policy[$view])){
106 + return;
107 + }
108 +
109 + $categories = self::get_cookie_categories();
110 + $consent = self::get_consent();
111 + $preload = self::get_preload_categories($policy, $view);
112 + $allowed_headers = array();
113 +
114 + foreach($set_cookie_headers as $set_cookie){
115 + $name = self::get_cookie_name_from_header($set_cookie);
116 +
117 + if(empty($name)){
118 + continue;
119 + }
120 +
121 + if(self::is_response_cookie_allowed($set_cookie, $categories, $consent, $preload)){
122 + $allowed_headers[] = $set_cookie;
123 + continue;
124 + }
125 +
126 + $http_cookies[$name]['string'] = trim($set_cookie);
127 + }
128 +
129 + header_remove('Set-Cookie');
130 +
131 + foreach($allowed_headers as $set_cookie){
132 + header('Set-Cookie: ' . $set_cookie, false);
133 + }
134 +
66 135 $http_cookies['cookieadmin_consent'] = ["string" => "cookieadmin_consent=CookieAdmin Cookie Initialization"];
67 136
68 137 self::$http_cookies = $http_cookies;
69 - } */
138 + }
139 +
140 + static function get_cookie_categories(){
141 + global $wpdb;
142 +
143 + $table_name = $wpdb->prefix . 'cookieadmin_cookies';
144 + if(!self::cookieadmin_table_exists($table_name)){
145 + return array();
146 + }
147 +
148 + $categories = array(
149 + 'exact' => array(),
150 + 'prefix' => array(),
151 + );
152 + $rows = $wpdb->get_results("SELECT cookie_name, raw_name, category FROM {$table_name}");
153 +
154 + foreach($rows as $row){
155 + if(!empty($row->cookie_name) && !empty($row->category)){
156 + $category = strtolower($row->category);
157 + $categories['exact'][$row->cookie_name] = $category;
158 +
159 + if(!empty($row->raw_name)){
160 + $categories['exact'][$row->raw_name] = $category;
161 +
162 + if($row->raw_name !== $row->cookie_name && strpos($row->raw_name, $row->cookie_name) === 0){
163 + $categories['prefix'][$row->cookie_name] = $category;
164 + }
165 + }
166 + }
167 + }
168 +
169 + uksort($categories['prefix'], function($a, $b){
170 + return strlen($b) - strlen($a);
171 + });
172 +
173 + return $categories;
174 + }
175 +
176 + static function get_consent(){
177 + if(empty($_COOKIE['cookieadmin_consent'])){
178 + return array();
179 + }
180 +
181 + $consent = json_decode(wp_unslash($_COOKIE['cookieadmin_consent']), true);
182 + if(!is_array($consent)){
183 + return array();
184 + }
185 +
186 + $sanitized = array();
187 + foreach($consent as $key => $value){
188 + $sanitized[sanitize_key($key)] = sanitize_text_field($value);
189 + }
190 +
191 + return $sanitized;
192 + }
193 +
194 + static function get_preload_categories($policy, $view){
195 + if(empty($policy) || empty($policy[$view]['preload']) || !is_array($policy[$view]['preload'])){
196 + return array();
197 + }
198 +
199 + $preload = array();
200 + foreach($policy[$view]['preload'] as $category){
201 + $preload[] = strtolower(sanitize_key($category));
202 + }
203 +
204 + return $preload;
205 + }
206 +
207 + static function get_cookie_name_from_header($set_cookie){
208 + $parts = explode('=', $set_cookie, 2);
209 + $name = trim($parts[0]);
210 +
211 + if(empty($name)){
212 + return '';
213 + }
214 +
215 + return $name;
216 + }
217 +
218 + static function is_response_cookie_allowed($set_cookie, $categories, $consent, $preload = array()){
219 + $name = self::get_cookie_name_from_header($set_cookie);
220 +
221 + if(empty($name)){
222 + return false;
223 + }
224 +
225 + // A deletion never adds a cookie and must not be prevented.
226 + if(preg_match('/(?:^|;)\s*max-age\s*=\s*(-?\d+)/i', $set_cookie, $age) && (int) $age[1] <= 0){
227 + return true;
228 + }
229 +
230 + if(preg_match('/(?:^|;)\s*expires\s*=\s*([^;]+)/i', $set_cookie, $expires)){
231 + $expires_at = strtotime($expires[1]);
232 + if($expires_at !== false && $expires_at < time()){
233 + return true;
234 + }
235 + }
236 +
237 + if($name === 'cookieadmin_consent'){
238 + return true;
239 + }
240 +
241 + $category = self::get_cookie_category($name, $categories);
242 +
243 + if(empty($category)){
244 + return !empty($consent['accept']) && $consent['accept'] === 'true';
245 + }
246 +
247 + if($category === 'necessary' || in_array($category, $preload, true)){
248 + return true;
249 + }
250 +
251 + if(!empty($consent['reject']) && $consent['reject'] === 'true'){
252 + return false;
253 + }
254 +
255 + if(!empty($consent['accept']) && $consent['accept'] === 'true'){
256 + return true;
257 + }
258 +
259 + return !empty($consent[$category]) && $consent[$category] === 'true';
260 + }
261 +
262 + static function get_cookie_category($name, $categories){
263 + if(!empty($categories['exact'][$name])){
264 + return $categories['exact'][$name];
265 + }
266 +
267 + if(empty($categories['prefix'])){
268 + return '';
269 + }
270 +
271 + foreach($categories['prefix'] as $prefix => $category){
272 + if(strpos($name, $prefix) === 0){
273 + return $category;
274 + }
275 + }
276 +
277 + return '';
278 + }
70 279
71 - static function check_if_cookies_allowed($tag, $handle, $src){
280 + static function block_scripts(){
72 281
282 + if(wp_doing_ajax() || is_admin() || defined('REST_REQUEST') || defined('COOKIEADMIN_SCANNER') || cookieadmin_is_editor_mode()){
283 + return;
284 + }
285 +
286 + $settings = get_option('cookieadmin_settings');
287 +
288 + if(empty($settings) || empty($settings['block_scripts'])){
289 + return;
290 + }
291 +
292 + $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
293 + $policy = cookieadmin_load_policy();
294 + if(empty($policy) || empty($view)){
295 + return;
296 + }
297 +
298 + ob_start([__CLASS__, 'update_tracking_scripts']);
299 + }
300 +
301 + static function update_tracking_scripts($html){
302 + global $cookieadmin_settings;
303 +
304 + if(stripos($html, '<script') === false){
305 + return $html;
306 + }
307 +
308 + if(empty(self::$categorized_cookies)){
309 + return $html;
310 + }
311 +
73 312 $cookieadmin_consent = isset($_COOKIE['cookieadmin_consent'])
74 313 ? json_decode(wp_unslash($_COOKIE['cookieadmin_consent']), true)
75 314 : [];
76 315
316 + // Sanitizing cookies
77 317 array_walk( $cookieadmin_consent, function( $value, $key ) use ( &$cookieadmin_consent ) {
78 318 $sanitized_key = sanitize_key( $key );
79 319 $cookieadmin_consent[ $sanitized_key ] = sanitize_text_field($value);
80 320 } );
81 -
82 - foreach (self::$categorized_cookies as $item) {
83 - $category = strtolower($item->category);
84 - $patterns = json_decode($item->patterns, true);
85 -
86 - if (!empty($patterns) && !empty($category)) {
87 - foreach ($patterns as $pattern) {
88 - if (strpos($src, $pattern) !== false) {
89 -
90 - if ( $category !== 'necessary' &&
91 - (empty($cookieadmin_consent) ||
92 - (!empty($cookieadmin_consent[$category]) && $cookieadmin_consent[$category] == 'false') ||
93 - $cookieadmin_consent['reject'] == 'true')
94 - ) {
95 -
96 - // User has NOT consented -> block the script
97 321
98 - // Option 1 - completely remove script:
99 - // return '';
322 + $html = preg_replace_callback(
323 + '/<script\b([^>]*)>([\s\S]*?)<\/script>/i',
324 + function($match) use ($cookieadmin_consent, $cookieadmin_settings){
325 + $attrs = $match[1];
326 + $content = $match[2];
327 + $full_tag = $match[0];
100 328
101 - // Option 2 - transform to type="text/plain"
102 - $tag = str_replace(
103 - '<script ',
104 - '<script type="text/plain" data-cookieadmin-category="' . esc_attr($category) . '" ',
105 - $tag
106 - );
107 -
108 - return $tag;
329 + if(preg_match('/\btype\s*=\s*["\']text\/plain["\']/i', $attrs)){
330 + return $full_tag;
331 + }
332 +
333 + if(preg_match('/\b(id|src)\s*=\s*["\'][^"\']*cookieadmin[^"\']*["\']/i', $attrs)){
334 + return $full_tag;
335 + }
336 +
337 + if(preg_match('/\btype\s*=\s*["\']([^"\']+)["\']/i', $attrs, $type_match)){
338 + $type = strtolower(trim($type_match[1]));
339 + if($type !== 'text/javascript' && $type !== 'module'){
340 + return $full_tag;
341 + }
342 + }
343 +
344 + $src = '';
345 + if(preg_match('/\bsrc\s*=\s*["\']([^"\']*)["\']/i', $attrs, $src_match)){
346 + $src = $src_match[1];
347 + }
348 +
349 + $match_against = !empty($src) ? $src : trim($attrs . ' ' . $content);
350 +
351 + if(empty($match_against)){
352 + return $full_tag;
353 + }
354 +
355 + if(!empty($cookieadmin_settings['cookieadmin_google_advance_consent_mode'])){
356 + // External Google tag loader
357 + if(!empty($src) && stripos($src, 'googletagmanager.com/gtag/js') !== false){
358 + return $full_tag;
359 + }
360 + // Inline gtag() snippet
361 + if(empty($src) && stripos($content, 'gtag(') !== false){
362 + return $full_tag;
363 + }
364 + }
365 +
366 + foreach (self::$categorized_cookies as $item) {
367 + $category = !empty($item->category) ? strtolower($item->category) : '';
368 + $patterns = !empty($item->patterns) ? json_decode($item->patterns, true) : '';
369 +
370 + if(empty($patterns) || empty($category)){
371 + continue;
372 + }
373 +
374 + foreach ($patterns as $pattern) {
375 + if(strpos($match_against, $pattern) !== false){
376 + if($category !== 'necessary' &&
377 + (empty($cookieadmin_consent) ||
378 + (!empty($cookieadmin_consent[$category]) && $cookieadmin_consent[$category] == 'false') ||
379 + (!empty($cookieadmin_consent['reject']) && $cookieadmin_consent['reject'] == 'true')
380 + )
381 + ){
382 + if($attrs === ''){
383 + return '<script type="text/plain" data-cookieadmin-category="' . esc_attr($category) . '">' . $content . '</script>';
384 + }
385 + return '<script type="text/plain" data-cookieadmin-category="' . esc_attr($category) . '"' . $attrs . '>' . $content . '</script>';
386 + }
109 387 }
110 388 }
111 389 }
112 - }
113 - }
114 390
115 - return $tag;
391 + return $full_tag;
392 + },
393 + $html
394 + );
395 +
396 + return $html;
116 397 }
117 398
118 399 static function cookieadmin_show_banner(){
400 +
401 + $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
402 + $policy = cookieadmin_load_policy();
403 +
404 + // Do not show banner if banner is off via Geo rule
405 + if(empty($view)){
406 + return;
407 + }
119 408
120 - $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
121 - $policy = cookieadmin_load_policy();
409 + $raw_template = cookieadmin_load_consent_template($policy[$view], $view);
122 410
123 - $allowed_tags = wp_kses_allowed_html( 'post' );
411 + if(!is_array($raw_template) || empty($raw_template)){
412 + return false;
413 + }
124 414
125 - // Add input tag for cookie consent form
126 - $allowed_tags['input'] = array(
127 - 'type' => true,
128 - 'name' => true,
129 - 'value' => true,
130 - 'class' => true,
131 - 'id' => true,
132 - 'checked' => true,
133 - 'disabled' => true,
134 - 'placeholder' => true,
135 - );
415 + $templates = implode('', $raw_template);
136 416
137 - $templates = wp_kses(implode("", cookieadmin_load_consent_template($policy[$view], $view)), $allowed_tags);
417 + $allowed_tags = cookieadmin_kses_allowed_html();
138 418
419 + $templates = apply_filters('cookieadmin_after_banner', $templates);
420 +
139 421 // var_dump($policy[$view]);
140 - echo $templates;
422 + echo wp_kses($templates, $allowed_tags);
141 423 }
142 -
424 +
143 425 static function cookieadmin_table_exists($table_name) {
144 426 global $wpdb;
145 427
146 428 $query = $wpdb->prepare("SHOW TABLES LIKE %s", $table_name);
@@ -146,7 +428,10 @@
146 428 $query = $wpdb->prepare("SHOW TABLES LIKE %s", $table_name);
147 429
148 430 return $wpdb->get_var($query) === $table_name;
149 431 }
150 -
432 +
433 + static function memberpress_allow_style_prefix($prefix_arr){
434 + $prefix_arr[] = 'cookieadmin';
435 + return $prefix_arr;
436 + }
151 437 }
152 -