PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.9.2
WP 2FA – Two-factor authentication for WordPress v2.9.2
1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Utils / class-debugging.php
wp-2fa / includes / classes / Utils Last commit date
class-abstract-migration.php 10 months ago class-date-time-utils.php 10 months ago class-debugging.php 10 months ago class-generate-modal.php 10 months ago class-migration.php 10 months ago class-request-utils.php 10 months ago class-settings-utils.php 10 months ago class-user-utils.php 10 months ago class-validator.php 10 months ago class-white-label.php 10 months ago index.php 10 months ago
class-debugging.php
195 lines
1 <?php
2 /**
3 * Responsible for logging.
4 *
5 * @package wp2fa
6 * @subpackage utils
7 * @copyright 2025 Melapress
8 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
9 * @link https://wordpress.org/plugins/wp-2fa/
10 * @since 1.4.2
11 */
12
13 declare(strict_types=1);
14
15 namespace WP2FA\Utils;
16
17 if ( ! class_exists( '\WP2FA\Utils\Debugging' ) ) {
18 /**
19 * Utility class for creating modal popup markup.
20 *
21 * @package WP2FA\Utils
22 *
23 * @since 1.4.2
24 */
25 class Debugging {
26
27 /**
28 * Local cache for the logging dir so that it doesn't need to be repopulated each time get_logging_dir_path is called.
29 *
30 * @var string
31 *
32 * @since 1.4.2
33 */
34 private static $logging_dir_path = '';
35
36 /**
37 * Retrieve the logging status
38 *
39 * @return boolean
40 *
41 * @since 1.4.2
42 */
43 private static function is_logging_enabled() {
44 /**
45 * Enables / Disables the logging for the plugin.
46 *
47 * @param bool $disabled - Default logging for the plugin.
48 */
49 return apply_filters( WP_2FA_PREFIX . 'logging_enabled', false );
50 }
51
52 /**
53 * Logs the given message
54 *
55 * @param string $message - The message to log.
56 *
57 * @return void
58 *
59 * @since 1.4.2
60 */
61 public static function log( $message ) {
62 if ( self::is_logging_enabled() ) {
63 self::write_to_log( self::get_log_timestamp() . "\n" . sanitize_text_field( $message ) . "\n" . __( 'Current memory usage: ', 'wp-2fa' ) . memory_get_usage( true ) . "\n" );
64 }
65 }
66
67 /**
68 * Retrieves the path to the log file
69 *
70 * @return string
71 *
72 * @since 1.4.2
73 */
74 private static function get_logging_dir_path() {
75 if ( strlen( self::$logging_dir_path ) === 0 ) {
76 $uploads_dir = wp_upload_dir( null, false );
77 self::$logging_dir_path = trailingslashit( trailingslashit( $uploads_dir['basedir'] ) . WP_2FA_LOGS_DIR );
78 }
79
80 return self::$logging_dir_path;
81 }
82
83 /**
84 * Write data to log file.
85 *
86 * @param string $data - Data to write to file.
87 * @param bool $override - Set to true if overriding the file.
88 *
89 * @return bool
90 *
91 * @since 1.4.2
92 */
93 private static function write_to_log( $data, $override = false ) {
94 $logging_dir_path = self::get_logging_dir_path();
95 if ( ! is_dir( $logging_dir_path ) ) {
96 self::create_index_file();
97 self::create_htaccess_file();
98 }
99
100 $log_file_name = gmdate( 'Y-m-d' );
101
102 return self::write_to_file( 'wp-2fa-debug-' . $log_file_name . '-' . self::get_random_file_string_addon() . '.log', $data, $override );
103 }
104
105 /**
106 * Create an index.php file, if none exists, in order to
107 * avoid directory listing in the specified directory.
108 *
109 * @return bool
110 *
111 * @since 1.4.2
112 */
113 private static function create_index_file() {
114 return self::write_to_file( 'index.php', '<?php // Silence is golden' );
115 }
116
117 /**
118 * Create an .htaccess file, if none exists, in order to
119 * block access to directory listing in the specified directory.
120 *
121 * @return bool
122 *
123 * @since 1.4.2
124 */
125 private static function create_htaccess_file() {
126 return self::write_to_file( '.htaccess', 'Deny from all' );
127 }
128
129 /**
130 * Write data to log file in the uploads directory.
131 *
132 * @param string $filename - File name.
133 * @param string $content - Contents of the file.
134 * @param bool $override - (Optional) True if overriding file contents.
135 *
136 * @return bool
137 *
138 * @since 1.4.2
139 */
140 private static function write_to_file( $filename, $content, $override = false ) {
141 global $wp_filesystem;
142 require_once ABSPATH . 'wp-admin/includes/file.php';
143 WP_Filesystem();
144
145 $logging_dir = self::get_logging_dir_path();
146
147 $result = false;
148
149 if ( ! is_dir( $logging_dir ) ) {
150 if ( false === wp_mkdir_p( $logging_dir ) ) {
151 return false;
152 }
153 }
154
155 $filepath = $logging_dir . $filename;
156 if ( ! $wp_filesystem->exists( $filepath ) || $override ) {
157 $result = $wp_filesystem->put_contents( $filepath, $content, FS_CHMOD_FILE );
158 } else {
159 $existing_content = $wp_filesystem->get_contents( $filepath );
160 $result = $wp_filesystem->put_contents( $filepath, $existing_content . $content, FS_CHMOD_FILE );
161 }
162
163 return $result;
164 }
165
166 /**
167 * Returns the timestamp for log files.
168 *
169 * @return string
170 *
171 * @since 1.4.2
172 */
173 private static function get_log_timestamp() {
174 return '[' . gmdate( 'd-M-Y H:i:s' ) . ' UTC]';
175 }
176
177 /**
178 * Generates a short random string which is used to generate log file name.
179 *
180 * @return string
181 *
182 * @since 2.8.0
183 */
184 private static function get_random_file_string_addon(): string {
185 $rnd_string = Settings_Utils::get_option( 'debug_name', false );
186 if ( ! $rnd_string ) {
187 $rnd_string = (string) \wp_generate_password( 20, false, false );
188 Settings_Utils::update_option( 'debug_name', $rnd_string );
189 }
190
191 return sanitize_text_field( $rnd_string );
192 }
193 }
194 }
195