Changeset 3343512
- Timestamp:
- 08/12/2025 11:37:44 AM (6 months ago)
- Location:
- doccheck-login/trunk
- Files:
-
- 6 edited
-
README.txt (modified) (2 diffs)
-
client/class-dcl-client.php (modified) (4 diffs)
-
client/class-dcl-shortcodes.php (modified) (1 diff)
-
dc-login.php (modified) (1 diff)
-
includes/class-dcl-base.php (modified) (1 diff)
-
includes/class-dcl.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
doccheck-login/trunk/README.txt
r3341642 r3343512 4 4 Requires at least: 5.5 5 5 Tested up to: 6.8 6 Stable tag: 1.1. 76 Stable tag: 1.1.8 7 7 License: GPLv2 or later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 68 68 69 69 == Changelog == 70 = 1.1.8 = 71 * Fixing Deeplink function 72 70 73 = 1.1.7 = 71 74 * Enhance security & modifying parameters -
doccheck-login/trunk/client/class-dcl-client.php
r3341638 r3343512 257 257 { 258 258 259 // Verify nonce for security260 $login_nonce = isset($_GET['state']) ? sanitize_text_field(wp_unslash($_GET['state'])) : '';261 262 if (!wp_verify_nonce($login_nonce, 'dcl_login_nonce')) {263 // Nonce verification failed, redirect to login page264 $this->dcl_redirect_to_login();265 exit;266 }267 268 259 // Check if this request still makes sense 269 260 if ($this->dcl_is_valid_login_time()) { … … 385 376 } 386 377 387 // Remove state parameter from URL388 $redirect_permalink = remove_query_arg('state', $redirect_permalink);389 378 390 379 // Remove parameters from URL … … 452 441 private function dcl_login_in_progress() 453 442 { 454 $login_nonce = isset($_GET['state']) ? sanitize_text_field(wp_unslash($_GET['state'])) : ''; 455 if (isset($_GET['dc_timestamp']) && isset($_GET['code']) && wp_verify_nonce($login_nonce, 'dcl_login_nonce')) { 443 if (isset($_GET['dc_timestamp']) && isset($_GET['code'])) { 456 444 return true; 457 445 } … … 471 459 private function dcl_is_valid_login_time() 472 460 { 473 // Verify nonce for security474 $login_nonce = isset($_GET['state']) ? sanitize_text_field(wp_unslash($_GET['state'])) : '';475 if (!wp_verify_nonce($login_nonce, 'dcl_login_nonce')) {476 return false;477 }478 461 479 462 $login_timestamp = isset($_GET['dc_timestamp']) ? sanitize_text_field(wp_unslash($_GET['dc_timestamp'])) : null; -
doccheck-login/trunk/client/class-dcl-shortcodes.php
r3341638 r3343512 152 152 $iframe_url = esc_url($iframe_url) . (isset($return_uri_param) && $return_uri_param ? $return_uri_param . '/' : '') . (!empty($utm_parameters) ? $redirect_params . '/' : ''); 153 153 // Add nonce for security 154 $iframe_url .= 'state='.wp_create_nonce('dcl_login_nonce');155 154 156 155 ob_start(); -
doccheck-login/trunk/dc-login.php
r3341642 r3343512 19 19 * Plugin Name: DocCheck Login 20 20 * Description: The official DocCheck plug-in enables the authentication of certified healthcare professionals and facilitates the integration of the DocCheck login. 21 * Version: 1.1. 721 * Version: 1.1.8 22 22 * Author: doccheck ag <[email protected]> 23 23 * Author URI: https://doccheck.agency -
doccheck-login/trunk/includes/class-dcl-base.php
r3341638 r3343512 13 13 * @author DocCheck agency <[email protected]> 14 14 */ 15 class DCL_Base 16 { 17 18 /** 19 * DocCheck Crawler IP. 20 * 21 * @since 1.0.0 22 */ 23 const DCL_CRAWLER_IP = '195.82.66.150'; 24 25 /** 26 * DocCheck Crawler IP 2. 27 * 28 * @since 1.0.0 29 */ 30 const DCL_CRAWLER_IP_DEV = '195.82.85.56'; 31 32 /** 33 * Login url. 34 * 35 * @since 1.0.0 36 */ 37 const DCL_URL = 'https://login.doccheck.com/code/'; 38 39 /** 40 * OAuth serivce url. 41 * 42 * @since 1.0.0 43 */ 44 const DCL_OAUTH_SERVICE = 'https://login.doccheck.com/service/oauth/access_token/'; 45 46 /** 47 * OAuth serivce url. 48 * 49 * @since 1.0.0 50 */ 51 const DCL_OAUTH_SERVICE_USERDATA = 'https://login.doccheck.com/service/oauth/user_data/'; 52 53 /** 54 * Check token url. 55 * 56 * @since 1.0.0 57 */ 58 const DCL_CHECK_TOKEN = 'https://login.doccheck.com/service/oauth/access_token/checkToken.php'; 59 60 /** 61 * Page with login. 62 * 63 * 64 * @since 1.0.0 65 * @access protected 66 * @var string 67 */ 68 protected $dcl_page_login_id; 69 70 /** 71 * Page to redirect occupation group. 72 * 73 * 74 * @since 1.0.0 75 * @access protected 76 * @var string 77 */ 78 protected $dcl_page_redirect_id; 79 80 /** 81 * Page for restricted circle. 82 * 83 * @since 1.0.0 84 * @access protected 85 * @var string 86 */ 87 protected $dcl_page_professional_circles_id; 88 89 /** 90 * Available login form sizes. 91 * 92 * @since 1.0.0 93 * @access protected 94 * @var array 95 */ 96 protected $dcl_form_sizes = [ 97 's_red' => 'S', 98 'm_red' => 'M', 99 'l_red' => 'L', 100 'xl_red' => 'XL', 101 ]; 102 103 104 /** 105 * Available login form size dimensions. 106 * 107 * @since 1.0.0 108 * @access protected 109 * @var array 110 */ 111 protected $dcl_form_size_dimensions = [ 112 's_red' => [ 113 'width' => 156, 114 'height' => 203 115 ], 116 'm_red' => [ 117 'width' => 311, 118 'height' => 188 119 ], 120 'l_red' => [ 121 'width' => 424, 122 'height' => 215 123 ], 124 'xl_red' => [ 125 'width' => 467, 126 'height' => 231 127 ] 128 ]; 129 130 /** 131 * Available login form languages. 132 * 133 * @since 1.0.0 134 * @access protected 135 * @var array 136 */ 137 protected $dcl_form_languages = [ 138 'de' => 'German', 139 'com' => 'English', 140 'fr' => 'French', 141 'it' => 'Italian', 142 'nl' => 'Dutch', 143 'es' => 'Spanish', 144 ]; 145 146 /** 147 * Constructor. 148 * 149 * @since 1.0.0 150 * @access public 151 */ 152 public function __construct() 153 { 154 $this->dcl_page_login_id = get_option('dcl_general_login_page_id', 0); 155 $this->dcl_page_redirect_id = get_option('dcl_general_redirect_page_id', 0); 156 157 $this->dcl_page_professional_circles_id = get_option('dcl_general_professional_circles_page_id', 0); 158 } 159 160 /** 161 * Get form sizes. 162 * 163 * @return array 164 * @since 1.0.0 165 * @access public 166 */ 167 public function dcl_get_form_sizes() 168 { 169 return $this->dcl_form_sizes; 170 } 171 172 /** 173 * Get form languages. 174 * 175 * @return array 176 * @since 1.0.0 177 * @access public 178 */ 179 public function dcl_get_form_languages() 180 { 181 return $this->dcl_form_languages; 182 } 183 184 /** 185 * Return dimensions for size. 186 * 187 * @param $size 188 * 189 * @return array 190 * @since 1.0.0 191 * @access public 192 */ 193 public function dcl_get_form_dimensions_for_size($size = 'm_red') 194 { 195 return $this->dcl_form_size_dimensions[$size]; 196 } 197 198 /** 199 * Gets the request UTM parameters. 200 * 201 * 202 * @return array The request parameter. 203 */ 204 205 public function dcl_get_sanitized_utm_parameters() 206 { 207 $utm_parameters = array( 208 'utm_source', 209 'utm_medium', 210 'utm_campaign', 211 'utm_term', 212 'utm_content', 213 'state', 214 'route' 215 ); 216 217 $sanitized_utm = array(); 218 219 // Verify nonce if this is a form submission 220 // Note: UTM parameters are often passed via URL and may not have a nonce 221 // If you're processing a form, you should add nonce verification here 222 $is_valid_nonce = isset($_GET['utm_nonce']) ? wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['utm_nonce'])), 'dcl_utm_parameters') : false; 223 224 // Continue processing even without a valid nonce since UTM parameters are often in direct URLs 225 // But log or handle the case where nonce verification fails if needed 226 227 foreach ($utm_parameters as $param) { 228 // Get the parameter value from the URL, unslash it first 229 $value = isset($_GET[$param]) ? sanitize_text_field(wp_unslash($_GET[$param])) : ''; 230 231 // Escape the value for use in HTML output 232 $escaped_value = esc_html($value); 233 234 // Add the sanitized and escaped value to the array 235 if ($value != '') { 236 $sanitized_utm[$param] = $escaped_value; 237 } 238 } 239 240 return $sanitized_utm; 241 } 242 243 244 /** 245 * Check for access restriction 246 * on current post or page. 247 * 248 * @return bool 249 * @since 1.0.0 250 * @access public 251 */ 252 public function dcl_is_access_restricted() 253 { 254 global $post; 255 256 257 // Make sure we have a post object to work with 258 // Exclude 404, search and login page from access restriction 259 if (!$post || is_404() || is_search() || is_page($this->dcl_page_login_id) || (is_page($this->dcl_page_redirect_id) && (int)$this->dcl_page_redirect_id > 0)) { 260 return false; 261 } 262 263 $access_restricted = get_post_meta($post->ID, 'dcl_restrict_access', true); 264 265 if ($access_restricted === 'on') { 266 return true; 267 } 268 269 return false; 270 } 271 272 /** 273 * Check if we do have a logged in user. 274 * 275 * @return bool 276 * @since 1.0.0 277 * @access public 278 */ 279 public function dcl_has_logged_in_user() 280 { 281 $access_token = $this->dcl_get_session_token(); 282 283 return !empty($access_token); 284 } 285 286 /** 287 * Get permalink to login page. 288 * 289 * @param string $redirect_url Url to redirect to after login. 290 * 291 * @return string $login_url 292 * @since 1.0.0 293 * @access public 294 */ 295 public function dcl_get_login_permalink($redirect_url = null) 296 { 297 298 // Get url for login page or home as fallback 299 if ((int)$this->dcl_page_login_id > 0) { 300 $login_url = get_permalink($this->dcl_page_login_id); 301 } else { 302 $login_url = home_url(); 303 } 304 305 // Add redirect query arg if exists 306 if ($redirect_url !== null) { 307 $login_url = add_query_arg('dc-redirect', $redirect_url, $login_url); 308 } 309 310 return $login_url; 311 } 312 313 /** 314 * Get permalink to redirect page, when user is logged in but access to a page is restricted. 315 * 316 * @return string $redirect_url 317 * @since 1.0.0 318 * @access public 319 */ 320 public function dcl_get_restricted_redirect_permalink() 321 { 322 // Get url for login page or home as fallback 323 if ((int)$this->dcl_page_redirect_id > 0) { 324 $redirect_url = get_permalink($this->dcl_page_redirect_id); 325 } else { 326 $redirect_url = home_url(); 327 } 328 329 return $redirect_url; 330 } 331 332 /** 333 * Get permalink to professionals page. 334 * 335 * @return string $prof_url 336 * @since 1.0.0 337 * @access public 338 */ 339 public function dcl_get_professionals_permalink() 340 { 341 342 // Get url for professional circles page or home as fallback 343 if ((int)$this->dcl_page_professional_circles_id > 0) { 344 $prof_url = get_permalink($this->dcl_page_professional_circles_id); 345 } else { 346 $prof_url = home_url(); 347 } 348 349 return $prof_url; 350 } 351 352 /** 353 * Start session and set expiration time. 354 * Open _SESSION read-only 355 * @since 1.0.0 356 * @access public 357 */ 358 public function dcl_start_session() 359 { 360 session_start([ 361 'cookie_lifetime' => 86400, 362 'read_and_close' => true, // READ ACCESS FAST 363 ]); 364 } 365 366 /** 367 * Get logged in cookie. 368 * 369 * @return string 370 * @since 1.0.0 371 * @access public 372 */ 373 public function dcl_get_session_token() 374 { 375 if (isset($_SESSION['dc_login_token']) && !empty($_SESSION['dc_login_token'])) { 376 $token = sanitize_text_field($_SESSION['dc_login_token']); 377 378 // Validate the token if necessary (for example, check if it meets certain criteria) 379 // Add your validation logic here 380 381 return esc_html($token); 382 } 383 384 return null; 385 } 386 387 /** 388 * Set logged in cookie. 389 * 390 * @param string $access_token 391 * 392 * @return void 393 * @since 1.0.0 394 * @access public 395 */ 396 public function dcl_set_session_token($access_token) 397 { 398 unset($_SESSION['dc_login_token']); 399 $_SESSION['dc_login_token'] = $access_token; 400 } 401 402 /** 403 * Logged in cookie exists. 404 * 405 * @return bool 406 * @since 1.0.0 407 * @access public 408 */ 409 public function dcl_session_token_exists() 410 { 411 return isset($_SESSION['dc_login_token']); 412 } 413 414 /** 415 * Clear logged in cookie. 416 * 417 * @return void 418 * @since 1.0.0 419 * @access public 420 */ 421 public function dcl_clear_session_token() 422 { 423 unset($_SESSION['dc_login_token']); 424 $_SESSION['dc_login_token'] = null; 425 } 426 427 /** 428 * Set redirect url cookie. 429 * 430 * @param $redirect_url 431 * 432 * @since 1.0.0 433 * @access public 434 */ 435 public function dcl_set_session_redirect_url($redirect_url) 436 { 437 session_abort(); 438 439 // now open the session with write access 440 session_start(['cookie_lifetime' => 86400]); 441 unset($_SESSION['dc_login_redirect_url']); 442 $_SESSION['dc_login_redirect_url'] = esc_url($redirect_url); 443 session_write_close(); // Write session data and end session 444 session_start([ 445 'cookie_lifetime' => 86400, 446 'read_and_close' => true, // READ ACCESS FAST 447 ]); 448 } 449 450 /** 451 * Get redirect url cookie. 452 * 453 * @return string 454 * @since 1.0.0 455 * @access public 456 */ 457 public function dcl_get_session_redirect_url() 458 { 459 $redirect_url = home_url(); 460 461 if (isset($_SESSION['dc_login_redirect_url']) && !empty($_SESSION['dc_login_redirect_url'])) { 462 // Sanitize the session URL 463 $redirect_url = esc_url_raw($_SESSION['dc_login_redirect_url']); 464 } elseif ((int)$this->dcl_page_professional_circles_id > 0) { 465 // Generate the URL based on the professional circles page ID 466 $redirect_url = esc_url(get_permalink($this->dcl_page_professional_circles_id)); 467 } 468 469 // Validate the URL if necessary (for example, check if it's a valid URL) 470 // Add your validation logic here 471 472 // Escape the final URL for safe output 473 return esc_url($redirect_url); 474 } 475 476 /** 477 * Escape return URI for iframe. 478 * 479 * @param boolean|string $return_uri 480 * 481 * @return string 482 * @since 1.0.3 483 * @access public 484 */ 485 public function dcl_escape_return_uri($return_uri) 486 { 487 if ($return_uri) { 488 $escape_arr = array( 489 '{slash}' => '/', 490 '{questionmark}' => '?', 491 '{equalsign}' => '=', 492 '{ampersand}' => '&' 493 ); 494 $escaped_return_uri = $return_uri; 495 496 foreach ($escape_arr as $key => $value) { 497 $escaped_return_uri = str_replace($value, $key, $escaped_return_uri); 498 } 499 500 return $escaped_return_uri; 501 } 502 503 return null; 504 } 505 506 /** 507 * Redirect cookie exists. 508 * 509 * @return bool 510 * @since 1.0.0 511 * @access public 512 */ 513 public function dcl_session_redirect_url_exists() 514 { 515 return isset($_SESSION['dc_login_redirect_url']); 516 } 517 518 /** 519 * Clear redirect cookie. 520 * 521 * @return void 522 * @since 1.0.0 523 * @access public 524 */ 525 public function dcl_clear_session_redirect_url() 526 { 527 unset($_SESSION['dc_login_redirect_url']); 528 $_SESSION['dc_login_redirect_url'] = null; 529 } 530 531 /** 532 * Check if client is DocCheck crawler. 533 * 534 * @return bool 535 * @since 1.0.0 536 * @access public 537 */ 538 public function dcl_is_client_dc_crawler() 539 { 540 $client_ip = $this->dcl_get_client_ip(); 541 542 if (self::DCL_CRAWLER_IP === $client_ip 543 || self::DCL_CRAWLER_IP_DEV === $client_ip 544 ) { 545 return true; 546 } 547 548 return false; 549 } 550 551 /** 552 * Get client ip. 553 * 554 * @return string 555 * @since 1.0.0 556 * @access private 557 */ 558 private function dcl_get_client_ip() 559 { 560 $ipaddress = 'UNKNOWN'; 561 562 if (isset($_SERVER['HTTP_CLIENT_IP'])) : 563 $ipaddress = sanitize_text_field(wp_unslash($_SERVER['HTTP_CLIENT_IP'])); 564 elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) : 565 $ipaddress = sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR'])); 566 elseif (isset($_SERVER['HTTP_X_FORWARDED'])) : 567 $ipaddress = sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED'])); 568 elseif (isset($_SERVER['HTTP_FORWARDED_FOR'])) : 569 $ipaddress = sanitize_text_field(wp_unslash($_SERVER['HTTP_FORWARDED_FOR'])); 570 elseif (isset($_SERVER['HTTP_FORWARDED'])) : 571 $ipaddress = sanitize_text_field(wp_unslash($_SERVER['HTTP_FORWARDED'])); 572 elseif (isset($_SERVER['REMOTE_ADDR'])) : 573 $ipaddress = sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])); 574 endif; 575 576 // Validate IP address format 577 if (filter_var($ipaddress, FILTER_VALIDATE_IP) === false) { 578 // Invalid IP address, fallback to 'UNKNOWN' 579 $ipaddress = 'UNKNOWN'; 580 } 581 582 return esc_html($ipaddress); 583 } 584 585 /** 586 * Define a constant if it is not already defined. 587 * 588 * @param string $name Constant name. 589 * @param mixed $value Value. 590 * @since 1.0.4 591 */ 592 public function dcl_maybe_define_constant($name, $value) 593 { 594 if (!defined($name)) { 595 define($name, $value); 596 } 597 } 598 599 /** 600 * Validates if a URL belongs to a trusted domain. 601 * 602 * @param string $url The URL to validate. 603 * @return bool True if the URL belongs to a trusted domain, false otherwise. 604 * @since 1.1.7 605 * @access public 606 */ 607 public function dcl_is_trusted_domain($url) 608 { 609 if (empty($url)) { 610 return false; 611 } 612 613 // Parse the URL to get the host 614 $parsed_url = parse_url($url); 615 616 if (empty($parsed_url) || !isset($parsed_url['host'])) { 617 return false; 618 } 619 620 $host = $parsed_url['host']; 621 622 // Get the site's domain 623 $site_url = parse_url(get_site_url(), PHP_URL_HOST); 624 625 // List of trusted domains (can be extended as needed) 626 $trusted_domains = array( 627 $site_url, // Current site's domain 628 'doccheck.com', 629 'www.doccheck.com' 630 ); 631 632 // Allow filtering of trusted domains 633 $trusted_domains = apply_filters('dcl_trusted_domains', $trusted_domains); 634 635 // Check if the host is in the trusted domains list or is a subdomain of a trusted domain 636 foreach ($trusted_domains as $trusted_domain) { 637 if ($host === $trusted_domain || preg_match('/\.' . preg_quote($trusted_domain, '/') . '$/', $host)) { 638 return true; 639 } 640 } 641 642 return false; 643 } 15 class DCL_Base { 16 17 /** 18 * DocCheck Crawler IP. 19 * 20 * @since 1.0.0 21 */ 22 const DCL_CRAWLER_IP = '195.82.66.150'; 23 24 /** 25 * DocCheck Crawler IP 2. 26 * 27 * @since 1.0.0 28 */ 29 const DCL_CRAWLER_IP_DEV = '195.82.85.56'; 30 31 /** 32 * Login url. 33 * 34 * @since 1.0.0 35 */ 36 const DCL_URL = 'https://login.doccheck.com/code/'; 37 38 /** 39 * OAuth serivce url. 40 * 41 * @since 1.0.0 42 */ 43 const DCL_OAUTH_SERVICE = 'https://login.doccheck.com/service/oauth/access_token/'; 44 45 /** 46 * OAuth serivce url. 47 * 48 * @since 1.0.0 49 */ 50 const DCL_OAUTH_SERVICE_USERDATA = 'https://login.doccheck.com/service/oauth/user_data/'; 51 52 /** 53 * Check token url. 54 * 55 * @since 1.0.0 56 */ 57 const DCL_CHECK_TOKEN = 'https://login.doccheck.com/service/oauth/access_token/checkToken.php'; 58 59 /** 60 * Page with login. 61 * 62 * 63 * @since 1.0.0 64 * @access protected 65 * @var string 66 */ 67 protected $dcl_page_login_id; 68 69 /** 70 * Page to redirect occupation group. 71 * 72 * 73 * @since 1.0.0 74 * @access protected 75 * @var string 76 */ 77 protected $dcl_page_redirect_id; 78 79 /** 80 * Page for restricted circle. 81 * 82 * @since 1.0.0 83 * @access protected 84 * @var string 85 */ 86 protected $dcl_page_professional_circles_id; 87 88 /** 89 * Available login form sizes. 90 * 91 * @since 1.0.0 92 * @access protected 93 * @var array 94 */ 95 protected $dcl_form_sizes = [ 96 's_red' => 'S', 97 'm_red' => 'M', 98 'l_red' => 'L', 99 'xl_red' => 'XL', 100 ]; 101 102 103 /** 104 * Available login form size dimensions. 105 * 106 * @since 1.0.0 107 * @access protected 108 * @var array 109 */ 110 protected $dcl_form_size_dimensions = [ 111 's_red' => [ 112 'width' => 156, 113 'height' => 203 114 ], 115 'm_red' => [ 116 'width' => 311, 117 'height' => 188 118 ], 119 'l_red' => [ 120 'width' => 424, 121 'height' => 215 122 ], 123 'xl_red' => [ 124 'width' => 467, 125 'height' => 231 126 ] 127 ]; 128 129 /** 130 * Available login form languages. 131 * 132 * @since 1.0.0 133 * @access protected 134 * @var array 135 */ 136 protected $dcl_form_languages = [ 137 'de' => 'German', 138 'com' => 'English', 139 'fr' => 'French', 140 'it' => 'Italian', 141 'nl' => 'Dutch', 142 'es' => 'Spanish', 143 ]; 144 145 /** 146 * Constructor. 147 * 148 * @since 1.0.0 149 * @access public 150 */ 151 public function __construct() { 152 $this->dcl_page_login_id = get_option( 'dcl_general_login_page_id', 0 ); 153 $this->dcl_page_redirect_id = get_option( 'dcl_general_redirect_page_id', 0 ); 154 155 $this->dcl_page_professional_circles_id = get_option( 'dcl_general_professional_circles_page_id', 0 ); 156 } 157 158 /** 159 * Get form sizes. 160 * 161 * @return array 162 * @since 1.0.0 163 * @access public 164 */ 165 public function dcl_get_form_sizes() { 166 return $this->dcl_form_sizes; 167 } 168 169 /** 170 * Get form languages. 171 * 172 * @return array 173 * @since 1.0.0 174 * @access public 175 */ 176 public function dcl_get_form_languages() { 177 return $this->dcl_form_languages; 178 } 179 180 /** 181 * Return dimensions for size. 182 * 183 * @param $size 184 * 185 * @return array 186 * @since 1.0.0 187 * @access public 188 */ 189 public function dcl_get_form_dimensions_for_size( $size = 'm_red' ) { 190 return $this->dcl_form_size_dimensions[ $size ]; 191 } 192 193 /** 194 * Gets the request UTM parameters. 195 * 196 * 197 * @return array The request parameter. 198 */ 199 200 public function dcl_get_sanitized_utm_parameters() { 201 $utm_parameters = array( 202 'utm_source', 203 'utm_medium', 204 'utm_campaign', 205 'utm_term', 206 'utm_content', 207 'state', 208 'route' 209 ); 210 211 $sanitized_utm = array(); 212 213 // Verify nonce if this is a form submission 214 // Note: UTM parameters are often passed via URL and may not have a nonce 215 // If you're processing a form, you should add nonce verification here 216 $is_valid_nonce = isset( $_GET['utm_nonce'] ) ? wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['utm_nonce'] ) ), 'dcl_utm_parameters' ) : false; 217 218 // Continue processing even without a valid nonce since UTM parameters are often in direct URLs 219 // But log or handle the case where nonce verification fails if needed 220 221 foreach ( $utm_parameters as $param ) { 222 // Get the parameter value from the URL, unslash it first 223 $value = isset( $_GET[ $param ] ) ? sanitize_text_field( wp_unslash( $_GET[ $param ] ) ) : ''; 224 225 // Escape the value for use in HTML output 226 $escaped_value = esc_html( $value ); 227 228 // Add the sanitized and escaped value to the array 229 if ( $value != '' ) { 230 $sanitized_utm[ $param ] = $escaped_value; 231 } 232 } 233 234 return $sanitized_utm; 235 } 236 237 238 /** 239 * Check for access restriction 240 * on current post or page. 241 * 242 * @return bool 243 * @since 1.0.0 244 * @access public 245 */ 246 public function dcl_is_access_restricted() { 247 global $post; 248 249 250 // Make sure we have a post object to work with 251 // Exclude 404, search and login page from access restriction 252 if ( ! $post || is_404() || is_search() || is_page( $this->dcl_page_login_id ) || ( is_page( $this->dcl_page_redirect_id ) && (int) $this->dcl_page_redirect_id > 0 ) ) { 253 return false; 254 } 255 256 $access_restricted = get_post_meta( $post->ID, 'dcl_restrict_access', true ); 257 258 if ( $access_restricted === 'on' ) { 259 return true; 260 } 261 262 return false; 263 } 264 265 /** 266 * Check if we do have a logged in user. 267 * 268 * @return bool 269 * @since 1.0.0 270 * @access public 271 */ 272 public function dcl_has_logged_in_user() { 273 $access_token = $this->dcl_get_session_token(); 274 275 return ! empty( $access_token ); 276 } 277 278 /** 279 * Get permalink to login page. 280 * 281 * @param string $redirect_url Url to redirect to after login. 282 * 283 * @return string $login_url 284 * @since 1.0.0 285 * @access public 286 */ 287 public function dcl_get_login_permalink( $redirect_url = null ) { 288 289 // Get url for login page or home as fallback 290 if ( (int) $this->dcl_page_login_id > 0 ) { 291 $login_url = get_permalink( $this->dcl_page_login_id ); 292 } else { 293 $login_url = home_url(); 294 } 295 296 // Add redirect query arg if exists 297 if ( $redirect_url !== null ) { 298 $login_url = add_query_arg( 'dc-redirect', $redirect_url, $login_url ); 299 } 300 301 return $login_url; 302 } 303 304 /** 305 * Get permalink to redirect page, when user is logged in but access to a page is restricted. 306 * 307 * @return string $redirect_url 308 * @since 1.0.0 309 * @access public 310 */ 311 public function dcl_get_restricted_redirect_permalink() { 312 // Get url for login page or home as fallback 313 if ( (int) $this->dcl_page_redirect_id > 0 ) { 314 $redirect_url = get_permalink( $this->dcl_page_redirect_id ); 315 } else { 316 $redirect_url = home_url(); 317 } 318 319 return $redirect_url; 320 } 321 322 /** 323 * Get permalink to professionals page. 324 * 325 * @return string $prof_url 326 * @since 1.0.0 327 * @access public 328 */ 329 public function dcl_get_professionals_permalink() { 330 331 // Get url for professional circles page or home as fallback 332 if ( (int) $this->dcl_page_professional_circles_id > 0 ) { 333 $prof_url = get_permalink( $this->dcl_page_professional_circles_id ); 334 } else { 335 $prof_url = home_url(); 336 } 337 338 return $prof_url; 339 } 340 341 /** 342 * Start session and set expiration time. 343 * Open _SESSION read-only 344 * @since 1.0.0 345 * @access public 346 */ 347 public function dcl_start_session() { 348 session_start( [ 349 'cookie_lifetime' => 86400, 350 'read_and_close' => true, // READ ACCESS FAST 351 ] ); 352 } 353 354 /** 355 * Get logged in cookie. 356 * 357 * @return string 358 * @since 1.0.0 359 * @access public 360 */ 361 public function dcl_get_session_token() { 362 if ( isset( $_SESSION['dc_login_token'] ) && ! empty( $_SESSION['dc_login_token'] ) ) { 363 $token = sanitize_text_field( $_SESSION['dc_login_token'] ); 364 365 // Validate the token if necessary (for example, check if it meets certain criteria) 366 // Add your validation logic here 367 368 return esc_html( $token ); 369 } 370 371 return null; 372 } 373 374 /** 375 * Set logged in cookie. 376 * 377 * @param string $access_token 378 * 379 * @return void 380 * @since 1.0.0 381 * @access public 382 */ 383 public function dcl_set_session_token( $access_token ) { 384 unset( $_SESSION['dc_login_token'] ); 385 $_SESSION['dc_login_token'] = $access_token; 386 } 387 388 /** 389 * Logged in cookie exists. 390 * 391 * @return bool 392 * @since 1.0.0 393 * @access public 394 */ 395 public function dcl_session_token_exists() { 396 return isset( $_SESSION['dc_login_token'] ); 397 } 398 399 /** 400 * Clear logged in cookie. 401 * 402 * @return void 403 * @since 1.0.0 404 * @access public 405 */ 406 public function dcl_clear_session_token() { 407 unset( $_SESSION['dc_login_token'] ); 408 $_SESSION['dc_login_token'] = null; 409 } 410 411 /** 412 * Set redirect url cookie. 413 * 414 * @param $redirect_url 415 * 416 * @since 1.0.0 417 * @access public 418 */ 419 public function dcl_set_session_redirect_url( $redirect_url ) { 420 session_abort(); 421 422 // now open the session with write access 423 session_start( [ 'cookie_lifetime' => 86400 ] ); 424 unset( $_SESSION['dc_login_redirect_url'] ); 425 $_SESSION['dc_login_redirect_url'] = esc_url( $redirect_url ); 426 session_write_close(); // Write session data and end session 427 session_start( [ 428 'cookie_lifetime' => 86400, 429 'read_and_close' => true, // READ ACCESS FAST 430 ] ); 431 } 432 433 /** 434 * Get redirect url cookie. 435 * 436 * @return string 437 * @since 1.0.0 438 * @access public 439 */ 440 public function dcl_get_session_redirect_url() { 441 $redirect_url = home_url(); 442 443 if ( isset( $_SESSION['dc_login_redirect_url'] ) && ! empty( $_SESSION['dc_login_redirect_url'] ) ) { 444 // Sanitize the session URL 445 $redirect_url = esc_url_raw( $_SESSION['dc_login_redirect_url'] ); 446 } elseif ( (int) $this->dcl_page_professional_circles_id > 0 ) { 447 // Generate the URL based on the professional circles page ID 448 $redirect_url = esc_url( get_permalink( $this->dcl_page_professional_circles_id ) ); 449 } 450 451 // Validate the URL if necessary (for example, check if it's a valid URL) 452 // Add your validation logic here 453 454 // Escape the final URL for safe output 455 return esc_url( $redirect_url ); 456 } 457 458 /** 459 * Escape return URI for iframe. 460 * 461 * @param boolean|string $return_uri 462 * 463 * @return string 464 * @since 1.0.3 465 * @access public 466 */ 467 public function dcl_escape_return_uri( $return_uri ) { 468 if ( $return_uri ) { 469 $escape_arr = array( 470 '{slash}' => '/', 471 '{questionmark}' => '?', 472 '{equalsign}' => '=', 473 '{ampersand}' => '&' 474 ); 475 $escaped_return_uri = $return_uri; 476 477 foreach ( $escape_arr as $key => $value ) { 478 $escaped_return_uri = str_replace( $value, $key, $escaped_return_uri ); 479 } 480 481 return $escaped_return_uri; 482 } 483 484 return null; 485 } 486 487 /** 488 * Redirect cookie exists. 489 * 490 * @return bool 491 * @since 1.0.0 492 * @access public 493 */ 494 public function dcl_session_redirect_url_exists() { 495 return isset( $_SESSION['dc_login_redirect_url'] ); 496 } 497 498 /** 499 * Clear redirect cookie. 500 * 501 * @return void 502 * @since 1.0.0 503 * @access public 504 */ 505 public function dcl_clear_session_redirect_url() { 506 unset( $_SESSION['dc_login_redirect_url'] ); 507 $_SESSION['dc_login_redirect_url'] = null; 508 } 509 510 /** 511 * Check if client is DocCheck crawler. 512 * 513 * @return bool 514 * @since 1.0.0 515 * @access public 516 */ 517 public function dcl_is_client_dc_crawler() { 518 $client_ip = $this->dcl_get_client_ip(); 519 520 if ( self::DCL_CRAWLER_IP === $client_ip 521 || self::DCL_CRAWLER_IP_DEV === $client_ip 522 ) { 523 return true; 524 } 525 526 return false; 527 } 528 529 /** 530 * Get client ip. 531 * 532 * @return string 533 * @since 1.0.0 534 * @access private 535 */ 536 private function dcl_get_client_ip() { 537 $ipaddress = 'UNKNOWN'; 538 539 if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) : 540 $ipaddress = sanitize_text_field( wp_unslash( $_SERVER['HTTP_CLIENT_IP'] ) ); 541 elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) : 542 $ipaddress = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ); 543 elseif ( isset( $_SERVER['HTTP_X_FORWARDED'] ) ) : 544 $ipaddress = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED'] ) ); 545 elseif ( isset( $_SERVER['HTTP_FORWARDED_FOR'] ) ) : 546 $ipaddress = sanitize_text_field( wp_unslash( $_SERVER['HTTP_FORWARDED_FOR'] ) ); 547 elseif ( isset( $_SERVER['HTTP_FORWARDED'] ) ) : 548 $ipaddress = sanitize_text_field( wp_unslash( $_SERVER['HTTP_FORWARDED'] ) ); 549 elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) : 550 $ipaddress = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); 551 endif; 552 553 // Validate IP address format 554 if ( filter_var( $ipaddress, FILTER_VALIDATE_IP ) === false ) { 555 // Invalid IP address, fallback to 'UNKNOWN' 556 $ipaddress = 'UNKNOWN'; 557 } 558 559 return esc_html( $ipaddress ); 560 } 561 562 /** 563 * Define a constant if it is not already defined. 564 * 565 * @param string $name Constant name. 566 * @param mixed $value Value. 567 * 568 * @since 1.0.4 569 */ 570 public function dcl_maybe_define_constant( $name, $value ) { 571 if ( ! defined( $name ) ) { 572 define( $name, $value ); 573 } 574 } 575 576 /** 577 * Validates if a URL belongs to a trusted domain. 578 * 579 * @param string $url The URL to validate. 580 * 581 * @return bool True if the URL belongs to a trusted domain, false otherwise. 582 * @since 1.1.7 583 * @access public 584 */ 585 public function dcl_is_trusted_domain( $url ) { 586 if ( empty( $url ) ) { 587 return false; 588 } 589 590 // Parse the URL to get the host 591 $parsed_url = parse_url( $url ); 592 593 if ( empty( $parsed_url ) || ! isset( $parsed_url['host'] ) ) { 594 return false; 595 } 596 597 $host = $parsed_url['host']; 598 599 // Get the site's domain 600 $site_url = parse_url( get_site_url(), PHP_URL_HOST ); 601 602 // List of trusted domains (can be extended as needed) 603 $trusted_domains = array( 604 $site_url, // Current site's domain 605 'doccheck.com', 606 'www.doccheck.com' 607 ); 608 609 // Allow filtering of trusted domains 610 $trusted_domains = apply_filters( 'dcl_trusted_domains', $trusted_domains ); 611 612 // Check if the host is in the trusted domains list or is a subdomain of a trusted domain 613 foreach ( $trusted_domains as $trusted_domain ) { 614 if ( $host === $trusted_domain || preg_match( '/\.' . preg_quote( $trusted_domain, '/' ) . '$/', $host ) ) { 615 return true; 616 } 617 } 618 619 return false; 620 } 644 621 } -
doccheck-login/trunk/includes/class-dcl.php
r3341642 r3343512 66 66 67 67 $this->plugin_name = 'dc-login'; 68 $this->version = '1.1. 7';68 $this->version = '1.1.8'; 69 69 70 70 $this->set_loader();
Note: See TracChangeset
for help on using the changeset viewer.