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
cookieadmin / includes / enduser.php

enduser.php in CookieAdmin – Cookie Consent Banner 1.2.3, at includes/enduser.php

438 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace CookieAdmin;
4
5 if(!defined('COOKIEADMIN_VERSION') || !defined('ABSPATH')){
6 die('Hacking Attempt');
7 }
8
9 class Enduser{
10
11 static $http_cookies = array();
12 static $categorized_cookies = array();
13
14 static function enqueue_scripts(){
15 global $wpdb;
16
17 $view = get_option('cookieadmin_law', 'cookieadmin_gdpr');
18 $policy = cookieadmin_load_policy();
19 $table_name = esc_sql($wpdb->prefix . 'cookieadmin_cookies');
20 //cookieadmin_r_print($view);
21 //cookieadmin_r_print($policy);
22
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');
26
27 wp_enqueue_style('cookieadmin-style', COOKIEADMIN_PLUGIN_URL . 'assets/css/consent.css', [], COOKIEADMIN_VERSION);
28
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);
38
39 $policy[$view]['ajax_url'] = admin_url('admin-ajax.php');
40 $policy[$view]['nonce'] = wp_create_nonce('cookieadmin_js_nonce');
41 $policy[$view]['http_cookies'] = self::$http_cookies;
42 $policy[$view]['home_url'] = home_url();
43 $policy[$view]['plugin_url'] = COOKIEADMIN_URL;
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
59 // cookieadmin_r_print($policy);die();
60
61 $rows = $wpdb->get_results("SELECT cookie_name, category, expires, description, patterns FROM {$table_name}");
62 $cookie_data = array();
63
64 foreach ($rows as $row) {
65 $cookie_data[$row->cookie_name] = $row;
66 }
67
68 $policy[$view]['categorized_cookies'] = self::$categorized_cookies = $cookie_data;
69
70 $policy[$view] = apply_filters('cookieadmin_before_localize', $policy[$view]);
71
72 wp_localize_script('cookieadmin_js', 'cookieadmin_policy', $policy[$view]);
73
74 }
75 }
76
77 static function cookieadmin_block_cookie_init_php(){
78
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
89 $http_cookies = array();
90 $set_cookie_headers = array();
91
92 foreach(headers_list() as $header) {
93 if(stripos(trim($header), 'Set-Cookie:') === 0){
94 $header = trim(substr($header, strlen('Set-Cookie:')));
95 $set_cookie_headers[] = $header;
96 }
97 }
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
135 $http_cookies['cookieadmin_consent'] = ["string" => "cookieadmin_consent=CookieAdmin Cookie Initialization"];
136
137 self::$http_cookies = $http_cookies;
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 }
279
280 static function block_scripts(){
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
312 $cookieadmin_consent = isset($_COOKIE['cookieadmin_consent'])
313 ? json_decode(wp_unslash($_COOKIE['cookieadmin_consent']), true)
314 : [];
315
316 // Sanitizing cookies
317 array_walk( $cookieadmin_consent, function( $value, $key ) use ( &$cookieadmin_consent ) {
318 $sanitized_key = sanitize_key( $key );
319 $cookieadmin_consent[ $sanitized_key ] = sanitize_text_field($value);
320 } );
321
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];
328
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 }
387 }
388 }
389 }
390
391 return $full_tag;
392 },
393 $html
394 );
395
396 return $html;
397 }
398
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 }
408
409 $raw_template = cookieadmin_load_consent_template($policy[$view], $view);
410
411 if(!is_array($raw_template) || empty($raw_template)){
412 return false;
413 }
414
415 $templates = implode('', $raw_template);
416
417 $allowed_tags = cookieadmin_kses_allowed_html();
418
419 $templates = apply_filters('cookieadmin_after_banner', $templates);
420
421 // var_dump($policy[$view]);
422 echo wp_kses($templates, $allowed_tags);
423 }
424
425 static function cookieadmin_table_exists($table_name) {
426 global $wpdb;
427
428 $query = $wpdb->prepare("SHOW TABLES LIKE %s", $table_name);
429
430 return $wpdb->get_var($query) === $table_name;
431 }
432
433 static function memberpress_allow_style_prefix($prefix_arr){
434 $prefix_arr[] = 'cookieadmin';
435 return $prefix_arr;
436 }
437 }
438