File: /home/p/e/r/perditaeyz/www/wp-content/plugins/core-control/modules/core_control_http_log.php
<?php
/*
Plugin Name: HTTP Access Logger Module
Version: 1.1
Description: Core Control HTTP Logger module, This allows you to Log external connections which WordPress makes.
Author: Dion Hulse
Author URI: https://dd32.id.au/
*/
class core_control_http_log {
var $request = null;
function __construct() {
add_action('core_control-http_log', array(&$this, 'the_page'));
$this->settings = array('logging' => false);
$this->settings = get_option('core_control-http_log', $this->settings);
add_action('admin_post_core_control-http_log', array(&$this, 'handle_posts'));
add_action('admin_post_core_control-http_log-inspect', array(&$this, 'handle_ajax_inspect'));
//Enable Logging if so be it.
if ( $this->settings['logging'] != false && ( !defined('WP_HTTP_BLOCK_EXTERNAL') || !WP_HTTP_BLOCK_EXTERNAL) ) {
add_filter('pre_http_request', array(&$this, 'do_log'), 10, 3);
add_filter('http_request_args', array(&$this, 'do_log'), 10, 2 );
add_action('http_api_debug', array(&$this, 'do_log'), 10, 3);
add_action('shutdown', array(&$this, 'end_request'));
}
register_post_type('http', array(
'label' => __('Core Control: HTTP Logger data', 'core-control'),
'public' => false,
'rewrite' => false,
));
}
function has_page() {
return true;
}
function menu() {
return array('http_log', 'External HTTP Access Logger');
}
function timer_start() {
$mtime = explode(' ', microtime() );
$mtime = $mtime[1] + $mtime[0];
return $mtime;
}
function timer_stop($start) {
$mtime = explode(' ', microtime() );
$mtime = $mtime[1] + $mtime[0];
return $mtime-$start;
}
function do_log($data = '', $log_type = '', $extra = '') {
//before:
if ( 'http_request_args' == current_filter() ) {
//THIS IS A FILTER PEOPLE!
if ( is_object($this->request) ) {
//Previous request must've failed.
$this->end_request();
}
$this->request = new core_control_http_log_item();
$this->request->args = $data;
$this->request->url = ('http' == substr($log_type, 0, 4)) ? $log_type : 'unknown';
//RETURN ON FILTERS!
return $data;
//starting..
} elseif ( 'pre_http_request' == current_filter() ) {
$wp_http = new WP_HTTP;
$transport = $wp_http->_get_first_available_transport($log_type /* $args */, $extra /* $url */);
$this->request->start = $this->timer_start();
$this->request->realtime = time();
$this->request->transports = $transport;
return $data; //FILTER
//after:
} elseif ( 'http_api_debug' == current_filter() && 'response' == $log_type ) {
$result =& $data;
$class =& $extra;
//if is_wp_error() erc.
$this->request->time = $this->timer_stop($this->request->start);
$this->request->result = $result;
$this->end_request();
}
}
function end_request() {
if ( empty($this->request) )
return;
//A Request has finished, Lets remove useless items:
unset($this->request->start);
$post_content_filtered = '';
if ( !is_wp_error($this->request->result) && isset($this->request->result['body']) ) {
$post_content_filtered = $this->request->result['body'];
unset($this->request->result['body']);
}
$arr = array(
'post_type' => 'http',
'post_status' => is_wp_error($this->request->result) ? 'error' : $this->request->result['response']['code'] . ' ' . $this->request->result['response']['message'],
'post_title' => $this->request->args['method'] . ' ' . $this->request->url,
'post_name' => md5($this->request->url . $this->request->realtime),
'post_content' => addslashes(serialize($this->request)),
'guid' => md5($this->request->url . $this->request->realtime),
'post_content_filtered' => $post_content_filtered
);
//Disable error reporting for this call, Cron triggers requests before init, which causes $wp_rewrite not to be loaded causing the unique slug handler to fail.
$err = error_reporting(0);
wp_insert_post($arr);
error_reporting($err);
$this->request = null;
}
function handle_posts() {
$option =& $this->settings;
if ( isset($_POST['enable-logging']) )
$option['logging'] = true;
elseif( isset($_POST['disable-logging']) )
$option['logging'] = false;
if ( isset($_POST['delete-selected']) )
foreach ( (array)$_POST['checked'] as $id )
wp_delete_post($id);
if ( isset($_POST['delete-all']) ) {
set_time_limit(0); // we may need this if someone left it activated..
// Delete 20 at a time for memory usage reasons.
while ( $https = get_posts( array('post_type' => 'http', 'post_status' => 'any', 'numberposts' => 20) ) ) {
foreach ( $https as $post ) {
wp_delete_post($post->ID);
}
}
}
update_option('core_control-http_log', $option);
wp_redirect(admin_url('tools.php?page=core-control&module=http_log'));
}
function the_page() {
$module_action = isset($_REQUEST['module_action']) ? $_REQUEST['module_action'] : '';
if ( 'inspect' == $module_action ) {
$this->inspect($_REQUEST['ID']);
} else {
$this->form();
$this->table();
}
}
function form() {
echo '<form method="post" action="admin-post.php?action=core_control-http_log">';
if ( $this->settings['logging'] == false ) {
echo '<p>Logging is currently <strong>disabled</strong></p>';
echo '<input type="submit" name="enable-logging" class="button-primary" value="Enable HTTP Logging" />';
} else {
echo '<p>Logging is currently <strong>enabled</strong></p>';
echo '<input type="submit" name="disable-logging" class="button-primary" value="Disable HTTP Logging" />';
}
echo '<p><br class="clear" /></p>';
echo '</form>';
}
function table() {
$https = get_posts( array('post_type' => 'http', 'post_status' => 'any', 'numberposts' => -1) );
if ( defined('WP_HTTP_BLOCK_EXTERNAL') && WP_HTTP_BLOCK_EXTERNAL ) {
echo '<p>Logging is currently disabled, It appears you are blocking outgoing connections in your wp-config.php file through the define <code>WP_HTTP_BLOCK_EXTERNAL</code>.</p>';
return;
}
?>
<form method="post" action="admin-post.php?action=core_control-http_log">
<br class="clear" />
<noscript><div class="message face"><p><strong>Please Note:</strong> This page requires Javascript in order to work.</p></div></noscript>
<p>Click a row to load the details for that request</p>
<script type="text/javascript">
var tab_changer_function = function() {
var $ = jQuery;
$(this).parents('ul').find('li.current').removeClass('current');
$(this).parents('li').addClass('current');
$(this).parents('td').find('div.tab-content').hide();
$( $(this).attr('href') ).show(); //href = element id :)
return false;
};
var load_item_function = function() {
var $ = jQuery;
var id = 0;
var _ele = $(this).parents('tr').attr('id').split('-');
id = _ele[1];
if ( $('#details-' + id).length > 0 )
return $('#details-' + id).toggle();
var div = '<tr><td colspan="5">Loading.. Please wait..</td></tr>';
div = $(div);
div.attr('id', 'details-' + id);
$('#http-' + id).after( div );
$.post( '<?php echo esc_js(admin_url('admin-post.php')) ?>', {
'action': 'core_control-http_log-inspect',
'ID': id
}, function(data) {
$('#details-' + id + ' td').html( data );
$('#details-' + id + ' td ul.tab-listing a').bind('click', tab_changer_function);
$('#details-' + id + ' td ul.tab-listing a:first').click();
});
}
jQuery(document).ready( function() {
jQuery('table.requests td:not(.check-column)').bind('click', load_item_function);
});
</script>
<style type="text/css">
ul.tab-listing {
margin-bottom: 10px;
}
ul.tab-listing li {
display: inline;
list-style: none;
border: thin solid #0066FF;
margin-right: 10px;
padding: 5px 0px;
}
ul.tab-listing li a {
padding: 5px;
}
ul.tab-listing a:hover, ul.tab-listing li.current, ul.tab-listing li.current a {
background-color: #0066FF;
color:#FFFFFF;
}
.tab-content table th {
white-space: nowrap;
}
</style>
<input type="submit" name="delete-selected" class="button-primary" value="Delete Selected Requests" />
<input type="submit" name="delete-all" class="button-primary" value="Delete All Stored Requests" />
<table class="widefat requests">
<thead>
<tr>
<th class="check-column"><input type="checkbox" name="check-all" /></th>
<th>URL</th>
<th>Status</th>
<th>Time</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<?php
foreach ( (array)$https as $request ) {
$the_request = @unserialize($request->post_content);
if ( !is_wp_error($the_request->result) && isset($the_request->result['response']) && !empty($request->post_content_filtered) )
$the_request->result['body'] = $request->post_content_filtered;
echo '<tr id="http-' . $request->ID . '">';
echo '<td class="check-column"><input type="checkbox" name="checked[]" value="' . $request->ID . '" /></td>';
echo '<td class="title">' . $request->post_title . '</td>';
echo '<td>' . $request->post_status . '</td>';
echo '<td>' . round($the_request->time, 3) . 's</td>';
echo '<td>' . $request->post_date . '</td>';
echo '</tr>';
}
?>
</tbody>
</table>
<input type="submit" name="delete-selected" class="button-primary" value="Delete Selected Requests" />
<input type="submit" name="delete-all" class="button-primary" value="Delete All Stored Requests" />
</form>
<?php
}
function handle_ajax_inspect() {
if ( empty($_REQUEST['ID']) )
return;
$id = $_REQUEST['ID'];
$request = get_post($id);
$the_request = unserialize($request->post_content);
if ( !is_wp_error($the_request->result) && isset($the_request->result['response']) && !empty($request->post_content_filtered) )
$the_request->result['body'] = $request->post_content_filtered;
?>
<div><ul class="hide-if-no-js tab-listing">
<li><a href="#request-details-<?php echo $id ?>">Request Details</a></li>
<?php if ( !is_wp_error($the_request->result) && !empty($the_request->result['headers']) ) : ?><li><a href="#response-headers-<?php echo $id ?>">Response Headers</a></li> <?php endif; ?>
<?php if ( !is_wp_error($the_request->result) &&!empty($the_request->result['body']) ) : ?><li><a href="#response-body-<?php echo $id ?>">Response Body</a></li> <?php endif; ?>
</ul>
<br class="clear" /></div>
<div class="tab-content" id="request-details-<?php echo $id ?>">
<table>
<tr>
<th>URL</th>
<td><?php echo $the_request->url ?></td>
</tr>
<tr>
<th>Method</th>
<td><?php echo $the_request->args['method'] ?></td>
</tr>
<tr>
<th>Result</th>
<td><?php
if ( is_wp_error($the_request->result) || !isset($the_request->result['response']) )
echo 'error';
else
echo $the_request->result['response']['code'] . ' ' . $the_request->result['response']['message'];
?></td>
</tr>
<?php if ( is_wp_error($the_request->result) ) : ?>
<tr>
<th>Error Details</th>
<td><table><?php
foreach ( (array)$the_request->result->errors as $code => $value ) {
$value = implode(', ', (array)$value);
echo '<tr>';
echo '<td valign="top">' . $code . '</td>';
echo '<td>' . $value . '</td>';
echo '</tr>';
}
?></table></td>
</tr>
<?php endif; ?>
<tr>
<th>Time Taken</th>
<td><?php echo $the_request->time ?> seconds</td>
</tr>
<tr>
<th>HTTP Args</th>
<td><table><?php
foreach ( (array)$the_request->args as $key => $value ) {
if ( 'method' == $key || 'body' == $key )
continue;
$value = $this->pretty_type_var($value);
echo '<tr>';
echo '<td valign="top">' . $key . '</td>';
echo '<td>' . $value . '</td>';
echo '</tr>';
}
?></table></td>
</tr>
<?php if ( isset($the_request->args['body']) ) : ?>
<tr>
<th>HTTP POST <em>body</em></th>
<td><?php echo $this->pretty_type_var($the_request->args['body']); ?></td>
</tr>
<?php endif; ?>
<tr>
<th>HTTP Transports</th>
<td><?php echo ( is_array($the_request->transports) ? implode(', ', $the_request->transports) : $the_request->transports ); ?></td>
</tr>
<tr>
<th>Request Time</th>
<td><?php
//Ugly i know, I'll replace it at some point when i work out what i've done to deserve this..
echo gmdate( 'Y-m-d H:i:s', ( $the_request->realtime + ( get_option( 'gmt_offset' ) * 3600 ) ) );
echo ' ';
echo get_option( 'gmt_offset' ) > 0 ? '+' : '-';
if ( $pos = strpos(get_option( 'gmt_offset' ), '.') )
echo (int)get_option( 'gmt_offset' ) . 60 * (float)( '0.' . substr(get_option( 'gmt_offset' ), $pos+1) );
else
echo get_option( 'gmt_offset' ) * 100;
?></td>
</tr>
</table>
</div>
<div class="tab-content" id="response-headers-<?php echo $id ?>">
<table>
<?php
if ( !is_wp_error($the_request->result) && !empty($the_request->result['headers']) ) {
foreach ( $the_request->result['headers'] as $header => $value ) {
$header = htmlentities($header);
$value = htmlentities( is_array( $value ) ? print_r( $value, true ) : $value );
echo '<tr>';
echo '<th>' . $header . '</th>';
echo '<td>' . $value . '</td>';
echo '</tr>';
}
}
?>
</table>
</div>
<div class="tab-content" id="response-body-<?php echo $id ?>">
<?php
if ( !is_wp_error($the_request->result) ) {
$body =& $the_request->result['body'];
if ( is_serialized($body) ) {
echo '<p>Content looks to be a Serialized string, Deserializing</p>';
echo '<pre><code>';
echo htmlentities(print_r(unserialize($body), true));
echo "\n</code></pre>";
} else {
echo '<pre>' . htmlentities($body) . '</pre>';
}
}
?>
</div>
<?php
}
function pretty_type_var($value) {
$type = gettype($value);
switch ( $type ) {
case 'resource';
case 'object':
case 'array':
$value = '<pre><code>' . htmlentities(print_r($value, true)) . '</code></pre>';
break;
case 'double':
case 'integer':
$value = "({$type}) " . ( empty($value) ? '0' : (string)$value );
break;
case 'string':
$value = htmlentities("({$type}) $value");
break;
case 'NULL':
$value = "NULL";
break;
case 'boolean':
$value = "({$type}) " . ($value ? 'true' : 'false');
break;
default:
$value = htmlentities($value);
}
return $value;
}
}
class core_control_http_log_item {}