PluginProbe
WebTotem Security / 3.0.2
WebTotem Security v3.0.2
3.0.2 3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 All 110 releases
wt-security / lib / Option.php

Option.php in WebTotem Security 3.0.2, at lib/Option.php

780 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
4 if (!headers_sent()) {
5 header('HTTP/1.1 403 Forbidden');
6 }
7 exit(1);
8 }
9
10 /**
11 * WebTotem Option class.
12 */
13 class WebTotemOption {
14
15 /**
16 * Get config option.
17 *
18 * @param string $option
19 * Option name.
20 *
21 * @return mixed
22 * Returns saved data by option name.
23 */
24 public static function getOption($option) {
25 $data = WebTotemDB::getData([ 'name' => $option ],'settings');
26 return (array_key_exists('value', $data)) ? $data['value'] : '';
27 }
28
29 /**
30 * Save multiple configuration options.
31 *
32 * @param array $options
33 * Array of data, key is name of option.
34 *
35 * @return bool
36 * Returns TRUE after setting the options.
37 */
38 public static function setOptions(array $options) {
39
40 foreach ($options as $option => $value) {
41 $value = is_array($value) ? json_encode($value) : $value;
42 WebTotemDB::setData(['name' => $option, 'value' => $value,], 'settings', ['name' => $option]);
43 }
44
45 return TRUE;
46 }
47
48 /**
49 * Clear multiple configuration options.
50 *
51 * @param array $options
52 * Array of data, key is name of option.
53 *
54 * @return bool
55 * Returns TRUE after clearing the options.
56 */
57 public static function clearOptions(array $options) {
58
59 foreach ($options as $option) {
60 WebTotemDB::deleteData([ 'name' => $option ], 'settings');
61 }
62
63 return TRUE;
64 }
65
66 /**
67 * Save multiple some options to session.
68 *
69 * @param array $options
70 * Array of data, key is name of option.
71 *
72 * @return bool
73 * Returns TRUE after setting the session options.
74 */
75 public static function setSessionOptions(array $options) {
76
77 $sessions = json_decode(self::getOption('sessions'), true) ?: [];
78 $user_id = get_current_user_id();
79
80 foreach ($options as $option => $value){
81 $sessions[$user_id][$option] = $value;
82 }
83
84 self::setOptions(['sessions' => $sessions]);
85
86 return TRUE;
87 }
88
89 /**
90 * Get option from session.
91 *
92 * @param string $option
93 * Option name.
94 *
95 * @return mixed
96 * Returns saved data by option name.
97 */
98 public static function getSessionOption($option) {
99
100 $sessions = json_decode(self::getOption('sessions'), true) ?: [];
101 $user_id = get_current_user_id();
102
103 if(array_key_exists($user_id, $sessions) and array_key_exists($option, $sessions[$user_id])){
104 return $sessions[$user_id][$option];
105 } else {
106 return [];
107 }
108
109 }
110
111 /**
112 * Save multiple some plugin settings.
113 *
114 * @param array $options
115 * Array of data, key is name of option.
116 *
117 * @return bool
118 * Returns TRUE after save settings.
119 */
120 public static function setPluginSettings(array $options) {
121
122 $settings = json_decode(self::getOption('settings'), true) ?: [];
123
124 foreach ($options as $option => $value){
125 $settings[$option] = $value;
126 }
127
128 self::setOptions(['settings' => $settings]);
129
130 return TRUE;
131 }
132
133 /**
134 * Get plugin settings.
135 *
136 * @param string $option
137 * Option name.
138 *
139 * @return mixed
140 * Returns saved data by option name.
141 */
142 public static function getPluginSettings($option = null) {
143
144 $settings = json_decode(self::getOption('settings'), true) ?: [];
145
146 if($option){
147 if(array_key_exists($option, $settings)){
148 return $settings[$option];
149 } else {
150 return [];
151 }
152 } else{
153 return $settings;
154 }
155 }
156
157
158 /**
159 * Check has reCaptcha enabled.
160 *
161 * @return bool
162 * Returns TRUE if reCaptcha enabled.
163 */
164 public static function reCaptchaEnabled() {
165 return self::getPluginSettings('recaptcha') ?: false;
166 }
167
168
169 /**
170 * Save authentication token and token expiration dates in settings.
171 *
172 * @param array $params
173 * Parameters for authorization.
174 *
175 * @return string
176 * Returns TRUE after setting the options.
177 */
178 public static function login(array $params) {
179 $parts = explode('.', $params['token']);
180 $token_data = json_decode(WebTotem::base64UrlDecode($parts[1]), true);
181 $token_expired = $token_data['exp'] - 60;
182
183 self::setOptions([
184 'activated' => TRUE,
185 'auth_token_expired' => $token_expired,
186 'auth_token' => $params['token'],
187 'api_key' => $params['api_key'],
188 'multisite_options' => WebTotem::isMultiSite()
189 ]);
190
191 return TRUE;
192 }
193
194 /**
195 * Save authentication token and token expiration dates in settings.
196 *
197 * @param string $token
198 * Parameters for authorization.
199 *
200 * @return bool
201 * Returns TRUE after setting the options.
202 */
203 public static function refreshToken(string $token) {
204 $parts = explode('.', $token);
205 $token_data = json_decode(WebTotem::base64UrlDecode($parts[1]), true);
206 $token_expired = $token_data['exp'] - 60;
207
208 self::setOptions([
209 'auth_token_expired' => $token_expired,
210 'auth_token' => $token,
211 ]);
212
213 return TRUE;
214 }
215
216 /**
217 * Checks whether the user has activated the plugin using the API key.
218 *
219 * @return bool
220 * Returns the module activation status.
221 */
222 public static function isActivated() {
223 return (boolean) self::getOption('activated');
224 }
225
226 /**
227 * Remove module settings.
228 *
229 * @return string
230 * Returns TRUE after clearing the options.
231 */
232 public static function logout() {
233
234 self::clearOptions([
235 'activated',
236 'auth_token_expired',
237 'auth_token',
238 'api_key',
239 'api_url',
240 'host_id',
241 'host_name',
242 ]);
243 return TRUE;
244 }
245
246 /**
247 * Return the current API access token, authorizing only when necessary.
248 *
249 * The token is reused until it actually expires; a new sign-in happens only
250 * when there is no token or the stored one is past its expiry.
251 *
252 * @return string
253 * Access token, or an empty string when authorization failed.
254 */
255 public static function getAuthToken() {
256 $token = self::getOption('auth_token');
257 $expired_at = (int) self::getOption('auth_token_expired');
258
259 if ($token && $expired_at > time()) {
260 return $token;
261 }
262
263 $api_key = self::getOption('api_key');
264 if ($api_key && WebTotemAPI::auth($api_key) === 'success') {
265 return self::getOption('auth_token');
266 }
267
268 return $token ?: '';
269 }
270
271 /**
272 * Set notification.
273 *
274 * @param string $type
275 * Notification Type.
276 * @param string $notice
277 * Notification Text.
278 */
279 public static function setNotification($type, $notice) {
280 $notifications = self::getSessionOption('notifications') ?: [];
281
282 if (array_key_exists($type, $notifications)) {
283 if (!in_array($notice, $notifications[$type])) {
284 $notifications[$type][] = $notice;
285 self::setSessionOptions(['notifications' => $notifications]);
286 }
287 }
288 else {
289 $notifications[$type][] = $notice;
290 self::setSessionOptions(['notifications' => $notifications]);
291 }
292
293 }
294
295 /**
296 * Get notifications.
297 *
298 * @return array
299 * Notifications array.
300 */
301 public static function getNotificationsData() {
302 $types = ['error', 'info', 'warning', 'success'];
303
304 $notifications = self::getSessionOption('notifications') ?: [];
305 $result = [];
306
307 foreach ($types as $type) {
308 if (array_key_exists($type, $notifications)) {
309 foreach ($notifications[$type] as $notification) {
310 $result[] = ['type' => $type, 'notice' => $notification];
311 }
312 }
313 }
314
315 // Remove notifications.
316 self::setSessionOptions(['notifications' => []]);
317
318 return $result;
319 }
320
321 /**
322 * Set host data.
323 *
324 * @return void
325 */
326 public static function setHost($host_name, $host_id) {
327
328 if(WebTotem::isMultiSite()){
329 $blog_id = self::getBlogId($host_name);
330
331 add_blog_option($blog_id, 'wtotem_host_id', $host_id);
332 add_blog_option($blog_id, 'wtotem_host_name', $host_name);
333
334 if(!is_main_site($blog_id)){
335 $all_hosts = json_decode(self::getOption('all_hosts'), true) ?: [];
336 $all_hosts[$host_name] = $host_id;
337
338 self::setOptions([
339 'all_hosts' => $all_hosts,
340 ]);
341 } else {
342 self::setOptions([
343 'host_id' => $host_id,
344 'host_name' => $host_name,
345 ]);
346 }
347
348 } else {
349 self::setOptions([
350 'host_id' => $host_id,
351 'host_name' => $host_name,
352 ]);
353 }
354 }
355
356 /**
357 * Get host data.
358 *
359 * @param string $hid
360 * Host id.
361 *
362 * @return array
363 * Host data.
364 */
365 public static function getHost($hid = false) {
366
367 if ( $hid ) {
368 $all_hosts = self::getAllHosts() ?: [];
369 if ( $all_hosts and in_array( $hid, $all_hosts ) ) {
370 return [
371 'id' => $hid,
372 'name' => array_search( $hid, $all_hosts ),
373 ];
374 }
375 }
376
377 return self::getMainHost();
378 }
379
380 /**
381 * Get host data.
382 *
383 * @return array
384 * Host data.
385 */
386 public static function getAllHosts() {
387 $all_hosts = json_decode(self::getOption('all_hosts'), true) ?: [];
388
389 $main_host = self::getMainHost();
390 $all_hosts = ($main_host['id']) ? [$main_host['name'] => $main_host['id']] + $all_hosts : $all_hosts;
391
392 return $all_hosts;
393 }
394
395 /**
396 * Get main host data.
397 *
398 * @return array
399 * Main host data.
400 */
401 public static function getMainHost() {
402
403 return [
404 'id' => self::getOption('host_id'),
405 'name' => self::getOption('host_name'),
406 ];
407
408 }
409
410 /**
411 * Delete host data from DB.
412 *
413 * @return void
414 */
415 public static function clearAllHosts() {
416
417 $hosts = WebTotemAPI::getSites(1, 1000000);
418 foreach ($hosts as $site) {
419 if (empty($site['name'])) {
420 continue;
421 }
422 $blog_id = self::getBlogId($site['name']);
423 delete_blog_option($blog_id, 'wtotem_host_id');
424 delete_blog_option($blog_id, 'wtotem_host_name');
425 }
426
427 }
428
429 /**
430 * Get an array of new sites.
431 *
432 * @return array
433 * Returns either an empty array or an array with new sites.
434 */
435 // public static function checkNewSites() {
436 // $hosts = self::getAllHosts();
437 // $sites = get_sites();
438 // $new_sites = [];
439 //
440 // foreach ($sites as $site){
441 // $host_name = untrailingslashit($site->domain . $site->path);
442 // if(!array_key_exists($host_name, $hosts) and !array_key_exists('www.' . $host_name, $hosts)) {
443 // $new_sites[] = $host_name;
444 // }
445 // }
446 // return $new_sites;
447 // }
448
449 /**
450 * Get host id from host name.
451 *
452 * @param $host_name
453 * Host name.
454 *
455 * @return integer
456 * Blog id.
457 */
458 public static function getBlogId($host_name){
459 $local_sites = get_sites();
460
461 foreach ($local_sites as $site){
462 $domain = untrailingslashit($site->domain . $site->path);
463 if($host_name == $domain){
464 return $site->blog_id;
465 }
466 }
467 return 0;
468 }
469
470 /**
471 * Get all config options name.
472 *
473 * @return array
474 * Returns saved data by option name.
475 */
476 public static function getAllOptions() {
477 return [
478 'api_key',
479 'activated',
480 'auth_token_expired',
481 'auth_token',
482 'am_file',
483 'waf_file',
484 'av_file',
485 'am_installed',
486 'av_installed',
487 'waf_installed',
488 'time_zone_check',
489 'time_zone_offset',
490 'all_hosts',
491 'plugin_version',
492 'sessions',
493 'multisite_options',
494
495 'host_id',
496 'host_name',
497 ];
498 }
499
500 /**
501 * Checking the old version of options.
502 *
503 * @return boolean
504 * If there are old options, it will return true.
505 */
506 public static function checkOldOptions() {
507
508 // Creating a database with plugin settings.
509 if(WebTotemDB::install()){
510
511 $api_key = get_option('wtsec_api_key');
512 $am_file = get_option('wtsec_am_installed_file');
513 $waf_file = get_option('wtsec_waf_installed_file');
514
515 if($api_key){
516 self::setOptions([
517 'api_key' => $api_key,
518 'am_file' => $am_file,
519 'waf_file' => $waf_file,
520 'activated' => true,
521 'am_installed' => true,
522 'av_installed' => true,
523 'waf_installed' => true,
524 ]);
525
526 $old_options = [
527 'api_key',
528 'api_key_safe',
529 'api_key_activated',
530 'authorized',
531 'authToken',
532 'waf_installed_file',
533 'av_installed_file',
534 'am_installed_file',
535 'am_installed',
536 'logout',
537 'av_installed',
538 'waf_installed',
539 'agents_installed',
540 'api_url',
541 'color_scheme' ,
542 'time_zone',
543 'token_expired',
544 'deactivated',
545 'antivirus_event',
546 'antivirus_permissions_changed',
547 'antivirus_endCursor',
548 'antivirus_hasNextPage',
549 'firewall_endCursor',
550 'firewall_hasNextPage',
551 'reports_endCursor',
552 'reports_hasNextPage'
553 ];
554
555 foreach ($old_options as $option) {
556 delete_option('wtsec_' . $option);
557 delete_site_option('wtsec_' .$option);
558 }
559
560 }
561
562 $api_key = get_site_option('wtotem_api_key');
563 $am_file = get_site_option('wtotem_am_installed_file');
564 $waf_file = get_site_option('wtotem_waf_installed_file');
565
566 if($api_key){
567 self::setOptions([
568 'api_key' => $api_key,
569 'am_file' => $am_file,
570 'waf_file' => $waf_file,
571 'activated' => true,
572 'am_installed' => true,
573 'av_installed' => true,
574 'waf_installed' => true,
575 ]);
576
577 foreach (self::getAllOptions() as $option) {
578 delete_option('wtotem_' . $option);
579 delete_site_option('wtotem_' .$option);
580 }
581 }
582 }
583
584 return true;
585 }
586
587 /**
588 * Check multisite.
589 */
590 public static function multisiteCheck() {
591 // Check the transition to/from the multisite.
592 if ( ( WebTotem::isMultiSite() && ! WebTotemOption::getOption( 'multisite_options' ) ) or
593 ( ! WebTotem::isMultiSite() && WebTotemOption::getOption( 'multisite_options' ) ) ) {
594
595 self::setOptions([ 'multisite_options' => WebTotem::isMultiSite() ]);
596
597 if(WebTotem::isMultiSite()){
598 WebTotemOption::clearAllHosts();
599 WebTotemOption::clearOptions([ 'host_id', 'host_name' ]);
600 } else {
601 WebTotemOption::clearOptions([ 'host_id', 'host_name' ]);
602 }
603
604 WebTotemAgentManager::removeAgents();
605 }
606 }
607
608 /**
609 * Hide readme file
610 * @param string $readmeFile
611 * @return bool
612 */
613 public static function hideReadme($readmeFile = null) {
614 if ($readmeFile === null) {
615 $readmeFile = ABSPATH . 'readme.html';
616 }
617
618 if (file_exists($readmeFile)) {
619 $readmePathInfo = pathinfo($readmeFile);
620 require_once(ABSPATH . WPINC . '/pluggable.php');
621 $hiddenReadmeFile = $readmePathInfo['filename'] . '.' . wp_hash('readme') . '.' . $readmePathInfo['extension'];
622 return @rename($readmeFile, $readmePathInfo['dirname'] . '/' . $hiddenReadmeFile);
623 }
624
625 return false;
626 }
627
628 /**
629 * Restore readme file
630 * @param string $readmeFile
631 * @return bool
632 */
633 public static function restoreReadme($readmeFile = null) {
634 if ($readmeFile === null) {
635 $readmeFile = ABSPATH . 'readme.html';
636 }
637 $readmePathInfo = pathinfo($readmeFile);
638 require_once(ABSPATH . WPINC . '/pluggable.php');
639 $hiddenReadmeFile = $readmePathInfo['dirname'] . '/' . $readmePathInfo['filename'] . '.' . wp_hash('readme') . '.' . $readmePathInfo['extension'];
640 if (file_exists($hiddenReadmeFile)) {
641 return @rename($hiddenReadmeFile, $readmeFile);
642 }
643
644 return false;
645 }
646 /**
647 * Hide WP version
648 * @return void
649 */
650 public static function hideWPVersion() {
651 global $wp_version;
652 global $wp_styles;
653
654 if (!($wp_styles instanceof WP_Styles)) {
655 $wp_styles = new WP_Styles();
656 }
657 if ($wp_styles->default_version === $wp_version) {
658 $wp_styles->default_version = wp_hash($wp_styles->default_version);
659 }
660
661 foreach ($wp_styles->registered as $key => $val) {
662 if ($wp_styles->registered[$key]->ver === $wp_version) {
663 $wp_styles->registered[$key]->ver = wp_hash($wp_styles->registered[$key]->ver);
664 }
665 }
666
667 global $wp_scripts;
668 if (!($wp_scripts instanceof WP_Scripts)) {
669 $wp_scripts = new WP_Scripts();
670 }
671 if ($wp_scripts->default_version === $wp_version) {
672 $wp_scripts->default_version = wp_hash($wp_scripts->default_version);
673 }
674
675 foreach ($wp_scripts->registered as $key => $val) {
676 if ($wp_scripts->registered[$key]->ver === $wp_version) {
677 $wp_scripts->registered[$key]->ver = wp_hash($wp_scripts->registered[$key]->ver);
678 }
679 }
680 }
681
682 public static function replaceVersion($url) {
683 return preg_replace_callback("/([&;\?]ver)=(.+?)(&|$)/", "WebTotemOption::replaceVersionCallback", $url);
684 }
685
686 public static function replaceVersionCallback($matches) {
687 global $wp_version;
688 return $matches[1] . '=' . ($wp_version === $matches[2] ? wp_hash($matches[2]) : $matches[2]) . $matches[3];
689 }
690
691 /**
692 * Check the nonce comming from any of the settings pages.
693 *
694 * @return bool True if the nonce is valid, false otherwise.
695 */
696 public static function checkOptionsNonce() {
697 // Create the option_page value if permalink submission.
698 if (!isset($_POST['option_page']) && isset($_POST['permalink_structure'])) {
699 $_POST['option_page'] = 'permalink';
700 }
701
702 /* check if the option_page has an allowed value */
703 $option_page = WebTotemRequest::post('option_page');
704
705 if (!$option_page) {
706 return false;
707 }
708
709 $action = '';
710 $nonce = '_wpnonce';
711
712 switch ($option_page) {
713 case 'general':
714 case 'writing':
715 case 'reading':
716 case 'discussion':
717 case 'media':
718 case 'options':
719 $action = $option_page . '-options';
720 break;
721 case 'permalink':
722 $action = 'update-permalink';
723 break;
724 }
725
726 /* check the nonce validity */
727 return (bool) (
728 !empty($action)
729 && isset($_REQUEST[$nonce])
730 && wp_verify_nonce($_REQUEST[$nonce], $action)
731 );
732 }
733
734 /**
735 * Retrieve all the options stored by Wordpress in the database.
736 *
737 * @return array All the options stored by Wordpress in the database.
738 */
739 private static function getSiteOptions() {
740 $settings = array();
741
742 if (array_key_exists('wpdb', $GLOBALS)) {
743 $results = $GLOBALS['wpdb']->get_results(
744 'SELECT * FROM ' . $GLOBALS['wpdb']->options . ' WHERE option_name NOT LIKE "%_transient_%" ORDER BY option_id ASC'
745 );
746
747 foreach ($results as $row) {
748 $settings[$row->option_name] = $row->option_value;
749 }
750 }
751
752 return $settings;
753 }
754
755 /**
756 * Check what Wordpress options were changed comparing the values in the database
757 * with the values sent through a simple request using a GET or POST method.
758 *
759 * @param array $request The content of the global variable GET or POST considering SERVER[REQUEST_METHOD].
760 * @return array A list of all the options that were changes through this request.
761 */
762 public static function whatOptionsWereChanged($request = array())
763 {
764 $options_changed = [ 'original' => [], 'changed' => [] ];
765
766 $site_options = self::getSiteOptions();
767
768 foreach ($request as $req_name => $req_value) {
769 if (array_key_exists($req_name, $site_options) && $site_options[ $req_name ] != $req_value ) {
770 $options_changed['original'][ $req_name ] = $site_options[ $req_name ];
771 $options_changed['changed'][ $req_name ] = $req_value;
772 }
773 }
774
775 return $options_changed;
776 }
777
778
779 }
780