PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260814
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260814
260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 All 189 releases
s2member / src / includes / classes / utils-logs.inc.php

utils-logs.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions 260814, at src/includes/classes/utils-logs.inc.php

281 lines 20.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * Log utilities.
5 *
6 * Copyright: © 2009-2011
7 * {@link http://websharks-inc.com/ WebSharks, Inc.}
8 * (coded in the USA)
9 *
10 * Released under the terms of the GNU General Public License.
11 * You should have received a copy of the GNU General Public License,
12 * along with this software. In the main directory, see: /licensing/
13 * If not, see: {@link http://www.gnu.org/licenses/}.
14 *
15 * @package s2Member\Utilities
16 * @since 3.5
17 */
18 if(!defined('WPINC')) // MUST have WordPress.
19 exit ('Do not access this file directly.');
20
21 if(!class_exists('c_ws_plugin__s2member_utils_logs'))
22 {
23 /**
24 * Log utilities.
25 *
26 * @package s2Member\Utilities
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_utils_logs
30 {
31 /**
32 * Logs an entry.
33 *
34 * @since 130315
35 * @package s2Member\Utilities
36 *
37 * @param string $slug The file name; i.e., a slug.
38 * e.g., `mailchimp-api`, `s2-http-api-debug`.
39 *
40 * @param mixed $data The data to log.
41 */
42 public static function log_entry($slug, $data)
43 {
44 if(!($slug = trim((string)$slug)))
45 return; // Not possible.
46
47 if(!$data) return; // Nothing to log.
48
49 if(!$GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs'])
50 return; // Nothing to do; logging not enabled right now.
51
52 if(!is_dir($logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir']))
53 return; // Log directory does not exist at this time.
54
55 if(!is_writable($logs_dir)) return; // Not writable.
56
57 $logt = c_ws_plugin__s2member_utilities::time_details();
58 $logv = c_ws_plugin__s2member_utilities::ver_details();
59 $logm = c_ws_plugin__s2member_utilities::mem_details();
60
61 $log4 = ''; // Initialize.
62 if(is_multisite() && !is_main_site()) // Child blog in a multisite network?
63 $log4 .= $GLOBALS['current_blog']->domain.$GLOBALS['current_blog']->path."\n";
64 $log4 .= @$_SERVER['HTTP_HOST'].@$_SERVER['REQUEST_URI']."\n";
65 $log4 .= 'User-Agent: '.@$_SERVER['HTTP_USER_AGENT'];
66
67 $log2 = $slug.'.log'; // Initialize.
68 if(is_multisite() && !is_main_site()) // Child blog in a multisite network?
69 $log2 = $slug.'-4-'.trim(preg_replace('/[^a-z0-9]/i', '-', $GLOBALS['current_blog']->domain.$GLOBALS['current_blog']->path), '-').'.log';
70
71 c_ws_plugin__s2member_utils_logs::archive_oversize_log_files();
72
73 file_put_contents(
74 $logs_dir.'/'.$log2,
75 'LOG ENTRY: '.$logt."\n".$logv."\n".$logm."\n".$log4."\n".
76 c_ws_plugin__s2member_utils_logs::conceal_private_info(print_r($data, TRUE))."\n\n",
77 FILE_APPEND // Append to an existing log file; if exists.
78 );
79 }
80
81 /**
82 * Logs HTTP communication (if enabled).
83 *
84 * @since 120212
85 * @package s2Member\Utilities
86 *
87 * @attaches-to `http_api_debug` hook.
88 *
89 * @param mixed $response Passed by action.
90 * @param mixed $state Passed by action.
91 * @param mixed $class Passed by action.
92 * @param mixed $args Passed by action.
93 * @param mixed $url Passed by action.
94 */
95 public static function http_api_debug($response = NULL, $state = NULL, $class = NULL, $args = NULL, $url = NULL)
96 {
97 if(!$GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs'])
98 return; // Logging is NOT enabled in this case.
99
100 $http_api_debug = array(
101 'state' => $state, 'transport_class' => $class,
102 'args' => $args, 'url' => $url, 'response' => $response
103 );
104 if(!empty($args['s2member']) || strpos($url, 's2member') !== FALSE)
105 self::log_entry('s2-http-api-debug', $http_api_debug);
106
107 if($GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs_extensive'])
108 self::log_entry('wp-http-api-debug', $http_api_debug);
109 }
110
111 /**
112 * Attempts to conceal private details in log entries.
113 *
114 * @since 130315
115 * @package s2Member\Utilities
116 *
117 * @param string $log_entry The log entry we need to conceal private details in.
118 *
119 * @return string Filtered string with some data X'd out :-)
120 */
121 public static function conceal_private_info($log_entry)
122 {
123 if(!($log_entry = trim((string)$log_entry)))
124 return $log_entry; // Nothing to do.
125
126 $log_entry = preg_replace('/\b([3456][0-9]{10,11})([0-9]{4})\b/', 'xxxxxxxxxxxx'.'$2', $log_entry);
127
128 $log_entry = preg_replace('/(\'.*pass_?(?:word)?(?:[0-9]+)?\'\s*\=\>\s*\')([^\']+)(\')/', '$1'.'xxxxxxxx/pass'.'$3', $log_entry);
129 $log_entry = preg_replace('/(\[\s*[^\]\r\n]*pass_?(?:word)?(?:[0-9]+)?[^\]\r\n]*\]\s*\=\>\s*)([^\r\n]*)/i', '$1'.'xxxxxxxx/pass', $log_entry);
130 $log_entry = preg_replace('/(\".*pass_?(?:word)?(?:[0-9]+)?\"\s*\:\s*\")([^\"]+)(\")/i', '$1'.'xxxxxxxx/pass'.'$3', $log_entry);
131 $log_entry = preg_replace('/([&?][^&]*pass_?(?:word)?(?:[0-9]+)?\=)([^&]+)/', '$1'.'xxxxxxxx/pass', $log_entry);
132
133 $log_entry = preg_replace('/(\'api_?(?:key|secret)\'\s*\=\>\s*\')([^\']+)(\')/', '$1'.'xxxxxxxx/api/key/sec'.'$3', $log_entry);
134 $log_entry = preg_replace('/(\[\s*[^\]\r\n]*api_?(?:key|secret)[^\]\r\n]*\]\s*\=\>\s*)([^\r\n]*)/i', '$1'.'xxxxxxxx/api/key/sec', $log_entry);
135 $log_entry = preg_replace('/(\"[^\"]*api_?(?:key|secret)[^\"]*\"\s*\:\s*\")([^\"]+)(\")/i', '$1'.'xxxxxxxx/api/key/sec'.'$3', $log_entry);
136 $log_entry = preg_replace('/([&?][^&]*api_?(?:key|secret)\=)([^&]+)/i', '$1'.'xxxxxxxx/api/key/sec', $log_entry);
137
138 $log_entry = preg_replace('/(\'(?:PWD|SIGNATURE)\'\s*\=\>\s*\')([^\']+)(\')/', '$1'.'xxxxxxxx/PWD/SIG'.'$3', $log_entry);
139 $log_entry = preg_replace('/(\[\s*[^\]\r\n]*(?:PWD|SIGNATURE)[^\]\r\n]*\]\s*\=\>\s*)([^\r\n]*)/', '$1'.'xxxxxxxx/PWD/SIG', $log_entry);
140 $log_entry = preg_replace('/(\"(?:PWD|SIGNATURE)\"\s*\:\s*\")([^\"]+)(\")/', '$1'.'xxxxxxxx/PWD/SIG'.'$3', $log_entry);
141 $log_entry = preg_replace('/([&?][^&]*(?:PWD|SIGNATURE)\=)([^&]+)/', '$1'.'xxxxxxxx/PWD/SIG', $log_entry);
142 $log_entry = preg_replace('/((?:^|[&?])[^&\r\n]*(?:PWD|SIGNATURE)(?:\[[^\]&=]*\]|%5B[^&=]*%5D)?\=)([^&\r\n]+)/im', '$1'.'xxxxxxxx/PWD/SIG', $log_entry);
143
144 $log_entry = preg_replace('/(\'(?:x_login|x_tran_key)\'\s*\=\>\s*\')([^\']+)(\')/', '$1'.'xxxxxxxx/key/tran'.'$3', $log_entry);
145 $log_entry = preg_replace('/(\[\s*[^\]\r\n]*(?:x_login|x_tran_key)[^\]\r\n]*\]\s*\=\>\s*)([^\r\n]*)/i', '$1'.'xxxxxxxx/key/tran', $log_entry);
146 $log_entry = preg_replace('/(\"(?:x_login|x_tran_key)\"\s*\:\s*\")([^\"]+)(\")/i', '$1'.'xxxxxxxx/key/tran'.'$3', $log_entry);
147 $log_entry = preg_replace('/([&?][^&]*(?:x_login|x_tran_key)\=)([^&]+)/i', '$1'.'xxxxxxxx/key/tran', $log_entry);
148
149 //260617 Conceal card verification values in gateway and HTTP API logs.
150 $log_entry = preg_replace('/(\'(?:CVV2?|CVC2?|CSC|CARD_?CODE|X_CARD_CODE|x_card_code|card_?code|card_?verification)\'\s*\=\>\s*\')([^\']+)(\')/i', '$1'.'xxxxxxxx/cvv'.'$3', $log_entry);
151 $log_entry = preg_replace('/(\[\s*[^\r\n]*(?:CVV2?|CVC2?|CSC|CARD_?CODE|X_CARD_CODE|x_card_code|card_?code|card_?verification)[^\r\n]*\]\s*\=\>\s*)([^\r\n]*)/i', '$1'.'xxxxxxxx/cvv', $log_entry);
152 $log_entry = preg_replace('/(\"[^\"]*(?:CVV2?|CVC2?|CSC|CARD_?CODE|X_CARD_CODE|x_card_code|card_?code|card_?verification)[^\"]*\"\s*\:\s*\")([^\"]+)(\")/i', '$1'.'xxxxxxxx/cvv'.'$3', $log_entry);
153 $log_entry = preg_replace('/((?:^|[&?])[^&\r\n]*(?:CVV2?|CVC2?|CSC|CARD_?CODE|X_CARD_CODE|x_card_code|card_?code|card_?verification)(?:\[[^\]&=]*\]|%5B[^&=]*%5D)?\=)([^&\r\n]+)/im', '$1'.'xxxxxxxx/cvv', $log_entry);
154 $log_entry = preg_replace('/(<((?:CVV2?|CVC2?|CSC|CARD_?CODE|X_CARD_CODE|x_card_code|card_?code|card_?verification))\b[^>]*>)(.*?)(<\/\2>)/is', '$1'.'xxxxxxxx/cvv'.'$4', $log_entry);
155
156 $log_entry = preg_replace('/(Authorization\s*:\s*Basic\s+)[A-Za-z0-9\/\+\=]+/i', '$1'.'xxxxxxxx/basic-auth', $log_entry);
157 $log_entry = preg_replace('/(\[\s*Authorization\s*\]\s*=\>\s*Basic\s+)[A-Za-z0-9\/\+\=]+/i', '$1'.'xxxxxxxx/basic-auth', $log_entry);
158 $log_entry = preg_replace('/(\"Authorization\"\s*:\s*\"Basic\s+)[A-Za-z0-9\/\+\=]+(\")/i', '$1'.'xxxxxxxx/basic-auth'.'$2', $log_entry);
159
160 //260303 Conceal OAuth access tokens in logged response bodies too.
161 $log_entry = preg_replace('/(\"access_token\"\s*:\s*\")([^\"]+)(\")/i', '$1'.'xxxxxxxx/access-token'.'$3', $log_entry);
162 $log_entry = preg_replace('/(\[\s*access_token\s*\]\s*=\>\s*)([^\r\n]*)/i', '$1'.'xxxxxxxx/access-token', $log_entry);
163
164 return $log_entry; // With some private info concealed now.
165 }
166
167 /**
168 * Archives logs to prevent HUGE files from building up over time.
169 *
170 * @since 3.5
171 * @package s2Member\Utilities
172 *
173 * @param bool $stagger Defaults to a `TRUE` value.
174 *
175 * @return bool Always returns a `TRUE` value.
176 */
177 public static function archive_oversize_log_files($stagger = TRUE)
178 {
179 if($stagger && !is_float($stagger = time() / 2))
180 return TRUE; // Bypass this time.
181
182 if(!is_dir($dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir']) || !is_writable($dir))
183 return TRUE; // Not necessary; directory is nonexistent or not writable.
184
185 if(!($log_files = scandir($dir)) || !shuffle($log_files))
186 return TRUE; // No files; not necessary.
187
188 $counter = 1; // Initialize archiving counter.
189 $max = apply_filters('ws_plugin__s2member_oversize_log_file_bytes', 2097152, get_defined_vars());
190
191 foreach($log_files as $file) // Go through each log file. Up to 25 files at a time.
192 {
193 if(preg_match('/\.log$/i', $file) && !preg_match('/\-ARCHIVED\-/i', $file) && is_file($dir_file = $dir.'/'.$file))
194 if(filesize($dir_file) > $max && is_writable($dir_file)) // The file must be writable.
195 if($log = preg_replace('/\.log$/i', '', $dir_file)) // Strip .log before renaming.
196 rename($dir_file, $log.'-ARCHIVED-'.date('m-d-Y').'-'.time().'.log');
197
198 if(($counter = $counter + 1) > 25) // Up to 25 files at a time.
199 break; // Stop for now.
200 }
201 return TRUE; // Always returns a `TRUE` value.
202 }
203
204 /**
205 * Removes expired Transients inserted into the database by s2Member.
206 *
207 * @since 3.5
208 * @package s2Member\Utilities
209 *
210 * @param bool $stagger Defaults to a `TRUE` value.
211 *
212 * @return bool Always returns a `TRUE` value.
213 */
214 public static function cleanup_expired_s2m_transients($stagger = TRUE)
215 {
216 global $wpdb; /** @var wpdb $wpdb */
217
218 if($stagger && !is_float($stagger = time() / 2))
219 return TRUE; // Bypass this time.
220
221 if(($expired_s2m_transients = $wpdb->get_results("SELECT * FROM `".$wpdb->options."` WHERE `option_name` LIKE '".esc_sql(c_ws_plugin__s2member_utils_strings::like_escape('_transient_timeout_s2m_'))."%' AND `option_value` < '".esc_sql(time())."' LIMIT 5")))
222 foreach($expired_s2m_transients as $_expired_s2m_transient) // Delete the _timeout, and also the transient entry name itself.
223 if(($_id = $_expired_s2m_transient->option_id) && ($_name = preg_replace('/_transient_timeout_/i', '_transient_', $_expired_s2m_transient->option_name, 1)))
224 $wpdb->query("DELETE FROM `".$wpdb->options."` WHERE (`option_id` = '".esc_sql($_id)."' OR `option_name` = '".esc_sql($_name)."')");
225
226 return TRUE; // Always returns a `TRUE` value.
227 }
228
229 /**
230 * Array of log file descriptions.
231 *
232 * @since 120214
233 * @package s2Member\Utilities
234 *
235 * @var array Array of log file descriptions.
236 */
237 public static $log_file_descriptions = array
238 ( // Array keys are regex patterns matching their associated log file names.
239 '/gateway\-core\-ipn/' => array('short' => 'Core IPN and post-processing handler.', 'long' => 'This log file records all communication between s2Member and the IPN/Webhook/Callback services associated with various payment gateways. All transactions pass through s2Member\'s core processor, and they will be logged in this file; including transactions processed via s2Member Pro-Forms—for all Payment Gateway integrations.'),
240 '/gateway\-core\-rtn/' => array('short' => 'Core PDT/Auto-Return communication.', 'long' => 'This log file records all communication between s2Member and the PDT/Auto-Return/Thank-You services associated with various payment gateways (i.e., routines that help s2Member process Thank-You pages). This log file is not used in s2Member Pro-Form integrations however.'),
241
242 '/stripe\-api/' => array('short' => 'Stripe API communication.', 'long' => 'This log file records all communication between s2Member and Stripe APIs. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
243 '/stripe\-ipn/' => array('short' => 'Stripe Webhook/IPN communication.', 'long' => 'This log file records the Webhook/IPN data that Stripe sends to s2Member. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
244
245 '/paypal\-api/' => array('short' => 'PayPal API communication.', 'long' => 'This log file records all communication between s2Member and PayPal APIs. Such as PayPal Button Encryption and PayPal Pro API calls that process transactions. This log file may be used (in some scenarios), even if you\'re running a PayPal Payments Pro (Payflow Edition) account. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
246 '/paypal\-payflow\-api/' => array('short' => 'PayPal Pro (PayFlow Edition) API communication.', 'long' => 'This log file records all communication between s2Member and the PayPal Payments Pro (PayFlow Edition) APIs. This log file is only used if you operate a PayPal Payments Pro (PayFlow Edition) account; i.e., only if you integrate s2Member Pro with Payflow for Recurring Billing. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
247 '/paypal\-checkout/' => array('short' => 'PayPal Checkout (REST/JS SDK) communication.', 'long' => 'This log file records communication related to s2Member\'s PayPal Checkout integration (REST API requests, JS SDK/checkout flow diagnostics, and webhook/notify proxy details). See also: gateway-core-ipn.log (s2Member\'s core processor).'),
248
249 '/authnet\-api/' => array('short' => 'Authorize.Net API communication.', 'long' => 'This log file records all communication between s2Member and Authorize.Net APIs (for both AIM and ARB integrations). See also: gateway-core-ipn.log (s2Member\'s core processor).'),
250 '/authnet\-arb/' => array('short' => 'Authorize.Net ARB Subscription status checks.', 'long' => 'This log file records s2Member\'s Authorize.Net ARB Subscription status checks. s2Member polls the ARB service periodically to check the status of existing Members (e.g., to see if billing is still active or not).'),
251 '/authnet\-ipn/' => array('short' => 'Authorize.Net Silent Post/IPN communication.', 'long' => 'This log file records the Silent Post/IPN data Authorize.Net sends to s2Member with details regarding new transactions. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
252
253 '/alipay\-ipn/' => array('short' => 'AliPay IPN communication.', 'long' => 'This log file records the IPN data AliPay sends to s2Member with details regarding new transactions. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
254 '/alipay\-rtn/' => array('short' => 'AliPay Auto-Return communication.', 'long' => 'This log file records the Auto-Return data AliPay sends to s2Member with details regarding new transactions (i.e., logs routines that help s2Member process Thank-You pages). See also: gateway-core-rtn.log (s2Member\'s core processor).'),
255
256 '/clickbank\-ipn/' => array('short' => 'ClickBank IPN communication.', 'long' => 'This log file records the IPN data ClickBank sends to s2Member with details regarding new transactions, cancellations, expirations, etc. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
257 '/clickbank\-rtn/' => array('short' => 'ClickBank Auto-Return communication.', 'long' => 'This log file records the Auto-Return data ClickBank sends to s2Member with details regarding new transactions (i.e., logs routines that help s2Member process Thank-You pages). See also: gateway-core-rtn.log (s2Member\'s core processor).'),
258
259 '/google\-rtn/' => array('short' => 'Google Auto-Return communication.', 'long' => 'This log file records the Auto-Return data Google sends to s2Member with details regarding new transactions (i.e., logs routines that help s2Member process Thank-You pages). See also: gateway-core-rtn.log (s2Member\'s core processor). NOTE (regarding Google Wallet)... this particular log file is currently implemented for a possible future use ONLY. At this time there is no need for an Auto-Return handler with Google Wallet, because Google Wallet return handling is done via email-only at this time.'),
260 '/google\-ipn/' => array('short' => 'Google Postback/IPN communication.', 'long' => 'This log file records the Postback/IPN data Google sends to s2Member with details regarding new transactions, cancellations, expirations, etc. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
261
262 '/ccbill\-ipn/' => array('short' => 'ccBill Bg Post/IPN communication.', 'long' => 'This log file records the Bg Post/IPN data ccBill sends to s2Member with details regarding new transactions. See also: gateway-core-ipn.log (s2Member\'s core processor).'),
263 '/ccbill\-rtn/' => array('short' => 'ccBill Auto-Return communication.', 'long' => 'This log file records the Auto-Return data ccBill sends to s2Member with details regarding new transactions (i.e., logs routines that help s2Member process Thank-You pages). See also: gateway-core-rtn.log (s2Member\'s core processor).'),
264 '/ccbill\-dl\-ipn/' => array('short' => 'ccBill Datalink Subscription status checks.', 'long' => 'This log file records s2Member\'s ccBill Datalink Subscription status checks that may result in actions taken by s2Member. s2Member polls the ccBill Datalink service periodically to check the status of existing Members (e.g., to see if billing is still active or not).'),
265 '/ccbill\-dl/' => array('short' => 'ccBill Datalink collections.', 'long' => 'This log file records s2Member\'s ccBill Datalink connections. s2Member polls the ccBill Datalink service periodically to obtain information about existing Users/Members.'),
266
267 '/mailchimp\-api/' => array('short' => 'MailChimp API communication.', 'long' => 'This log file records all of s2Member\'s communication with MailChimp APIs.'),
268 '/aweber\-api/' => array('short' => 'AWeber API communication.', 'long' => 'This log file records all of s2Member\'s communication with AWeber APIs.'),
269 '/getresponse\-api/' => array('short' => 'GetResponse API communication.', 'long' => 'This log file records all of s2Member\'s communication with GetResponse APIs.'),
270
271 '/reg\-handler/' => array('short' => 'User registrations processed by s2Member.', 'long' => 'This log file records all User/Member registrations processed by s2Member (either directly or indirectly). This includes both free and paid registrations. It also logs registrations that occur as a result of new Users/Members being created from the Dashboard by a site owner. It also includes registrations that occur through the s2Member Pro Remote Operations API.'),
272
273 '/s2\-http\-api\-debug/' => array('short' => 'All outgoing HTTP connections related to s2Member.', 'long' => 'This log file records all outgoing WP_Http connections that are specifically related to s2Member. This log file can be extremely helpful. It includes technical details about remote HTTP connections that are not available in other log files.'),
274 '/wp\-http\-api\-debug/' => array('short' => 'All outgoing WordPress HTTP connections.', 'long' => 'This log file records all outgoing HTTP connections processed by the WP_Http class. This includes everything processed by WordPress; even things unrelated to s2Member. This log file can be extremely helpful. It includes technical details about remote HTTP connections that are not available in other log files.'),
275
276 '/auto\-eot\-system/' => array('short' => 'EOTs processed via CRON job.', 'long' => 'This log file records all EOTs processed by the WP_Cron job that powers the s2Member Auto-EOT System. Once a customer has an EOT Time, the CRON job comes in and actually handles a demotion or deletion (based on your configuration). That is what this log file shows; i.e., the actual demotion or deletion taking place.'),
277 '/eot\-reminders/' => array('short' => 'EOT reminder emails processed via CRON job.', 'long' => 'This log file records all EOT reminder emails processed by the WP_Cron job that powers the s2Member Auto-EOT System. EOT Renewal/Reminder Email notifications are available only in the pro version of s2Member.'),
278 );
279 }
280 }
281