← All changes
|
vendor/convertkit/convertkit-wordpress-libraries/src/class-convertkit-log.php
+138
-21
2.2.2
→
3.4.5
View file →
| @@ -13,8 +13,17 @@ | ||
| 13 | 13 | */ |
| 14 | 14 | class ConvertKit_Log { |
| 15 | 15 | |
| 16 | 16 | /** |
| 17 | + * The path to the directory that will contain the log file. | |
| 18 | + * | |
| 19 | + * @since 1.4.2 | |
| 20 | + * | |
| 21 | + * @var string | |
| 22 | + */ | |
| 23 | + private $path = ''; | |
| 24 | + | |
| 25 | + /** | |
| 17 | 26 | * The path and filename of the log file. |
| 18 | 27 | * |
| 19 | 28 | * @since 1.0.0 |
| 20 | 29 | * |
| @@ -19,9 +28,9 @@ | ||
| 19 | 28 | * @since 1.0.0 |
| 20 | 29 | * |
| 21 | 30 | * @var string |
| 22 | 31 | */ |
| 23 | - private $log_file; | |
| 32 | + private $log_file = ''; | |
| 24 | 33 | |
| 25 | 34 | /** |
| 26 | 35 | * Constructor. Defines the log file location. |
| 27 | 36 | * |
| @@ -30,18 +39,93 @@ | ||
| 30 | 39 | * @param string $path Path to where log file should be created/edited/read. |
| 31 | 40 | */ |
| 32 | 41 | public function __construct( $path ) { |
| 33 | 42 | |
| 43 | + // If legacy log files exist in the Plugin's directory, delete them now. | |
| 44 | + $this->maybe_delete_legacy_log_files( $path ); | |
| 45 | + | |
| 46 | + // Fetch the uploads directory. | |
| 47 | + $upload_dir = wp_upload_dir(); | |
| 48 | + | |
| 49 | + // Bail if the uploads directory is unavailable. | |
| 50 | + if ( ! empty( $upload_dir['error'] ) || empty( $upload_dir['basedir'] ) ) { | |
| 51 | + return; | |
| 52 | + } | |
| 53 | + | |
| 34 | 54 | // Define location of log file. |
| 35 | - $this->log_file = trailingslashit( $path ) . 'log.txt'; | |
| 55 | + $this->path = trailingslashit( $upload_dir['basedir'] ) . 'kit-logs/'; | |
| 56 | + $this->log_file = $this->path . $this->get_log_file_name( $path ); | |
| 36 | 57 | |
| 37 | - // Initialize WP_Filesystem. | |
| 38 | - require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 39 | - WP_Filesystem(); | |
| 58 | + // If the secure log directory does not exist, create it now. | |
| 59 | + $this->maybe_create_secure_log_directory(); | |
| 40 | 60 | |
| 41 | 61 | } |
| 42 | 62 | |
| 43 | 63 | /** |
| 64 | + * Deletes log files stored in the Plugin's directory by earlier versions of | |
| 65 | + * this class. | |
| 66 | + * | |
| 67 | + * Deletes: | |
| 68 | + * - `log.txt`, used prior to 1.4.2, which has no .htaccess or index.html protection, | |
| 69 | + * - `log` directory and its contents, used from 1.4.2 to 2.6.0. | |
| 70 | + * | |
| 71 | + * @since 1.4.2 | |
| 72 | + * | |
| 73 | + * @param string $path Path to the Plugin. | |
| 74 | + */ | |
| 75 | + private function maybe_delete_legacy_log_files( $path ) { | |
| 76 | + | |
| 77 | + // If a log.txt file exists in the Plugin's directory (i.e. from 1.4.2 or earlier), delete it. | |
| 78 | + $legacy_file = trailingslashit( $path ) . 'log.txt'; | |
| 79 | + if ( file_exists( $legacy_file ) ) { | |
| 80 | + wp_delete_file( $legacy_file ); | |
| 81 | + } | |
| 82 | + | |
| 83 | + // If a log directory exists in the Plugin's directory (i.e. from 1.4.2 to 2.6.0), delete it and its contents. | |
| 84 | + $legacy_path = trailingslashit( $path ) . 'log'; | |
| 85 | + if ( is_dir( $legacy_path ) ) { | |
| 86 | + // Delete the files this class created in the log directory. | |
| 87 | + foreach ( array( 'log.txt', '.htaccess', 'index.html' ) as $file ) { | |
| 88 | + if ( file_exists( trailingslashit( $legacy_path ) . $file ) ) { | |
| 89 | + wp_delete_file( trailingslashit( $legacy_path ) . $file ); | |
| 90 | + } | |
| 91 | + } | |
| 92 | + | |
| 93 | + // Delete the log directory. | |
| 94 | + rmdir( trailingslashit( $path ) . 'log' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir | |
| 95 | + } | |
| 96 | + | |
| 97 | + } | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * Creates a directory to store the log file, with .htaccess and index.html | |
| 101 | + * files to protect the log file, as WooCommerce does. | |
| 102 | + * | |
| 103 | + * Disables logging if the directory could not be created, or isn't writable. | |
| 104 | + * | |
| 105 | + * @since 1.4.2 | |
| 106 | + */ | |
| 107 | + private function maybe_create_secure_log_directory() { | |
| 108 | + | |
| 109 | + // Create directory. | |
| 110 | + wp_mkdir_p( $this->path ); | |
| 111 | + | |
| 112 | + // Disable logging if the directory doesn't exist or isn't writable. | |
| 113 | + if ( ! is_dir( $this->path ) || ! wp_is_writable( $this->path ) ) { | |
| 114 | + $this->path = ''; | |
| 115 | + $this->log_file = ''; | |
| 116 | + return; | |
| 117 | + } | |
| 118 | + | |
| 119 | + // Define files to protect the directory. | |
| 120 | + // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents | |
| 121 | + file_put_contents( $this->path . '.htaccess', 'deny from all' ); | |
| 122 | + file_put_contents( $this->path . 'index.html', '' ); | |
| 123 | + // phpcs:enable WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents | |
| 124 | + | |
| 125 | + } | |
| 126 | + | |
| 127 | + /** | |
| 44 | 128 | * Returns the path and filename of the log file. |
| 45 | 129 | * |
| 46 | 130 | * @since 1.0.0 |
| 47 | 131 | * |
| @@ -61,8 +145,13 @@ | ||
| 61 | 145 | * @return bool |
| 62 | 146 | */ |
| 63 | 147 | public function exists() { |
| 64 | 148 | |
| 149 | + // Bail if logging is disabled. | |
| 150 | + if ( ! $this->log_file ) { | |
| 151 | + return false; | |
| 152 | + } | |
| 153 | + | |
| 65 | 154 | return file_exists( $this->get_filename() ); |
| 66 | 155 | |
| 67 | 156 | } |
| 68 | 157 | |
| @@ -74,23 +163,29 @@ | ||
| 74 | 163 | * @param string $entry Log Line Entry. |
| 75 | 164 | */ |
| 76 | 165 | public function add( $entry ) { |
| 77 | 166 | |
| 78 | - // Initialize WordPress file system. | |
| 79 | - global $wp_filesystem; | |
| 167 | + // Bail if logging is disabled. | |
| 168 | + if ( ! $this->log_file ) { | |
| 169 | + return; | |
| 170 | + } | |
| 80 | 171 | |
| 81 | 172 | // Prefix the entry with a date and time. |
| 82 | 173 | $entry = '(' . gmdate( 'Y-m-d H:i:s' ) . ') ' . $entry . "\n"; |
| 83 | 174 | |
| 84 | - // Get any existing log file contents. | |
| 85 | - $contents = $wp_filesystem->get_contents( $this->get_filename() ); | |
| 175 | + // Mask email addresses that may be contained within the entry. | |
| 176 | + $entry = preg_replace_callback( | |
| 177 | + '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})^', | |
| 178 | + function ( $matches ) { | |
| 179 | + return preg_replace( '/\B[^@.]/', '*', $matches[0] ); | |
| 180 | + }, | |
| 181 | + $entry | |
| 182 | + ); | |
| 86 | 183 | |
| 87 | 184 | // Append entry. |
| 88 | - $contents .= $entry; | |
| 185 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents | |
| 186 | + file_put_contents( $this->get_filename(), $entry, FILE_APPEND ); | |
| 89 | 187 | |
| 90 | - // Write contents. | |
| 91 | - $wp_filesystem->put_contents( $this->get_filename(), $contents ); | |
| 92 | - | |
| 93 | 188 | } |
| 94 | 189 | |
| 95 | 190 | /** |
| 96 | 191 | * Reads the given number of lines from the log file. |
| @@ -101,11 +196,8 @@ | ||
| 101 | 196 | * @return string Log file data |
| 102 | 197 | */ |
| 103 | 198 | public function read( $number_of_lines = 500 ) { |
| 104 | 199 | |
| 105 | - // Initialize WordPress file system. | |
| 106 | - global $wp_filesystem; | |
| 107 | - | |
| 108 | 200 | // Bail if the log file does not exist. |
| 109 | 201 | if ( ! $this->exists() ) { |
| 110 | 202 | return ''; |
| 111 | 203 | } |
| @@ -110,9 +202,10 @@ | ||
| 110 | 202 | return ''; |
| 111 | 203 | } |
| 112 | 204 | |
| 113 | 205 | // Open log file. |
| 114 | - $log = $wp_filesystem->get_contents_array( $this->get_filename() ); | |
| 206 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file | |
| 207 | + $log = file( $this->get_filename() ); | |
| 115 | 208 | |
| 116 | 209 | // Bail if the log file is empty. |
| 117 | 210 | if ( ! is_array( $log ) || ! count( $log ) ) { |
| 118 | 211 | return ''; |
| @@ -129,12 +222,15 @@ | ||
| 129 | 222 | * @since 1.0.0 |
| 130 | 223 | */ |
| 131 | 224 | public function clear() { |
| 132 | 225 | |
| 133 | - // Initialize WordPress file system. | |
| 134 | - global $wp_filesystem; | |
| 226 | + // Bail if logging is disabled. | |
| 227 | + if ( ! $this->log_file ) { | |
| 228 | + return; | |
| 229 | + } | |
| 135 | 230 | |
| 136 | - $wp_filesystem->put_contents( $this->get_filename(), '' ); | |
| 231 | + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents | |
| 232 | + file_put_contents( $this->get_filename(), '' ); | |
| 137 | 233 | |
| 138 | 234 | } |
| 139 | 235 | |
| 140 | 236 | /** |
| @@ -143,9 +239,30 @@ | ||
| 143 | 239 | * @since 1.0.0 |
| 144 | 240 | */ |
| 145 | 241 | public function delete() { |
| 146 | 242 | |
| 147 | - unlink( $this->get_filename() ); | |
| 243 | + // Bail if logging is disabled. | |
| 244 | + if ( ! $this->log_file ) { | |
| 245 | + return; | |
| 246 | + } | |
| 247 | + | |
| 248 | + wp_delete_file( $this->get_filename() ); | |
| 249 | + | |
| 250 | + } | |
| 251 | + | |
| 252 | + /** | |
| 253 | + * Returns the log file's name for the Plugin at the given path. | |
| 254 | + * | |
| 255 | + * @since 2.6.1 | |
| 256 | + * | |
| 257 | + * @param string $path Path to the Plugin. | |
| 258 | + * @return string | |
| 259 | + */ | |
| 260 | + private function get_log_file_name( $path ) { | |
| 261 | + | |
| 262 | + $slug = sanitize_key( basename( untrailingslashit( $path ) ) ); | |
| 263 | + | |
| 264 | + return $slug . '-' . wp_hash( $slug ) . '.log'; | |
| 148 | 265 | |
| 149 | 266 | } |
| 150 | 267 | |
| 151 | 268 | } |