init(); $crazy_bone->add_action(); register_activation_hook(__FILE__, array($crazy_bone, 'activate')); register_deactivation_hook(__FILE__, array($crazy_bone, 'deactivate')); load_plugin_textdomain(crazy_bone::TEXT_DOMAIN, false, dirname(plugin_basename(__FILE__)) . '/languages/'); class crazy_bone { const USER_META_KEY = 'user_login_log'; const TEXT_DOMAIN = 'user-login-log'; const LIST_PER_PAGE = 20; const DEBUG_MODE = false; const OPTION_NAME = 'user-login-log'; const ADMIN_MENU_CAPABILITY = 'level_0'; const SEC_MINUITE = 60; const SEC_HOUR = 3600; const SEC_DAY = 86400; const SEC_MONTH = 2592000; const SEC_YEAR = 31536000; private $ull_table = 'user_login_log'; private $admin_action; private $plugin_version; private $options; static $instance; private function __construct() {} public static function get_instance() { if( !isset( self::$instance ) ) { $c = __CLASS__; self::$instance = new $c(); } return self::$instance; } // initialize public function init(){ global $wpdb; self::$instance = $this; $this->ull_table = $wpdb->prefix.$this->ull_table; $this->admin_action = admin_url('profile.php') . '?page=' . plugin_basename(__FILE__); $data = get_file_data(__FILE__, array('version' => 'Version')); $this->plugin_version = isset($data['version']) ? $data['version'] : ''; $this->options = get_option( self::OPTION_NAME, array() ); if (!is_array($this->options)) $this->options = array('installed' => false); if (!isset($this->options['installed']) || !$this->options['installed']) $this->activate(); } // added action public function add_action(){ add_action('wp_login', array($this, 'user_login_log'), 10, 2); add_action('wp_authenticate', array($this, 'wp_authenticate_log'), 10, 2); add_action('login_form_logout', array($this, 'user_logout_log')); add_action('auth_cookie_expired', array($this, 'cookie_expired_log'), 10, 2); add_action('auth_cookie_bad_hash', array($this, 'cookie_bad_hash_log'), 10, 2); add_action('admin_enqueue_scripts', array($this,'enqueue_scripts')); add_action('wp_enqueue_scripts', array($this,'enqueue_scripts')); add_action('admin_bar_init', array($this, 'admin_bar_init'), 9999); add_action('admin_menu', array($this,'add_admin_menu')); add_action('wp_ajax_ull_info', array($this, 'ajax_info')); add_action('wp_ajax_nopriv_ull_info', array($this, 'ajax_info')); add_action('wp_ajax_dismiss-ull-wp-pointer', array($this, 'ajax_dismiss')); add_action('wp_ajax_nopriv_dismiss-ull-wp-pointer', array($this, 'ajax_dismiss')); } public function activate(){ global $wpdb; if (isset($this->options['installed']) && $this->options['installed']) return; if ($wpdb->get_var("show tables like '{$this->ull_table}'") != $this->ull_table) $this->create_table(); } public function deactivate(){ delete_option( self::OPTION_NAME ); } private function create_table(){ global $wpdb; if ($wpdb->get_var("show tables like '{$this->ull_table}'") != $this->ull_table) { $wpdb->query(" CREATE TABLE `{$this->ull_table}` ( `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `user_id` bigint(20) unsigned NOT NULL DEFAULT 0, `activity_status` varchar(255) NOT NULL, `activity_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `activity_agent` varchar(255) NOT NULL, `activity_IP` varchar(100) NOT NULL, `activity_errors` text NULL, `country_name` varchar(100) NULL, `country_code` varchar(10) NULL, PRIMARY KEY (`ID`), KEY `user_id` (`user_id`), KEY `activity_status` (`activity_status`), KEY `activity_date` (`activity_date`), KEY `country_code` (`country_code`) )"); } $this->options['installed'] = true; update_option( self::OPTION_NAME, $this->options ); } public function enqueue_scripts(){ if (!is_user_logged_in()) return; wp_enqueue_style('wp-pointer'); wp_enqueue_script('jquery'); wp_enqueue_script('wp-pointer', array('jquery')); } public function admin_bar_init() { add_action('admin_bar_menu', array($this, 'customize_admin_bar_menu'), 9999); wp_enqueue_style('user_login_log', plugins_url('css/user_login_log.css', __FILE__), array(), $this->plugin_version); $realtime_check = apply_filters('crazy_bone::realtime_check', true); if ($realtime_check) { add_action('admin_footer', array($this, 'footer_js')); add_action('wp_footer', array($this, 'footer_js')); } } public function customize_admin_bar_menu($wp_admin_bar){ $capability = apply_filters('crazy_bone::admin_menu_capability', self::ADMIN_MENU_CAPABILITY); if (!current_user_can($capability)) return; $title = $this->login_info(); if ($title === false) return; $wp_admin_bar->add_menu(array( 'id' => 'user-login-log', 'parent' => 'my-account', 'title' => $title, 'meta' => array(), 'href' => $this->admin_action, )); } private function last_login_info() { $user = wp_get_current_user(); if (is_wp_error($user)) return false; $login_log = get_user_meta($user->ID, self::USER_META_KEY . '-login', true); if (!$login_log) $login_log = $this->logging($user->ID, 'login'); $date = isset($login_log['Date']) ? strtotime($login_log['Date']) : time(); $ip = isset($login_log['IP']) ? $login_log['IP'] : ''; $ua = isset($login_log['User Agent']) ? $login_log['User Agent'] : ''; return array('date' => $date, 'ip' => $ip, 'ua' => $ua); } private function login_info($args = '') { $user = wp_get_current_user(); if (is_wp_error($user)) return false; if (empty($args)) $args = $this->last_login_info(); $date = isset($args['date']) ? $args['date'] : $this->time(); $ip = isset($args['ip']) ? $args['ip'] : $this->ip(); $ua = isset($args['ua']) ? $args['ua'] : $this->ua(); list($browser_name, $browser_code, $browser_ver, $os_name, $os_code, $os_ver, $pda_name, $pda_code, $pda_ver) = $this->detect_browser($ua); list($country_name, $country_code) = $this->detect_country($ip); $title = trim(sprintf( __('Last login: %s%s%s', self::TEXT_DOMAIN), $this->nice_time($date), !empty($ip) ? ' '.$this->get_country_flag($ip) : '', !empty($ua) ? ' '.$this->get_browser_icon($ua) : '' )); return $title; } public function user_login_log($user_login, $user) { $this->logging($user->ID, 'login'); } public function cookie_expired_log($cookie_elements) { if ( function_exists('get_userdatabylogin') ) { $user = get_userdatabylogin($cookie_elements['username']); $this->logging($user->ID, 'cookie_expired'); } } public function cookie_bad_hash_log($cookie_elements) { if ( function_exists('get_userdatabylogin') ) { $user = get_userdatabylogin($cookie_elements['username']); $this->logging($user->ID, 'cookie_bad_hash'); } } function wp_authenticate_log($user_login, $user_password) { if (empty($user_login)) return; $user = wp_authenticate($user_login, $user_password); if (!is_wp_error($user)) return; $errors = $user->errors; $args = array('errors' => $errors); if (array_key_exists('invalid_username', $errors)) { $user_id = 0; $args['user_login'] = $user_login; $args['user_password'] = $user_password; } else { $user = get_user_by('login', $user_login); $user_id = isset($user->ID) ? $user->ID : 0; } $this->logging($user_id, 'login_error', $args); } public function user_logout_log() { $user = wp_get_current_user(); if (is_wp_error($user)) return; $this->logging($user->ID, 'logout'); } private function logging($user_id, $status, $args = array()) { global $wpdb; $activity_date = $this->time(); $activity_agent = $this->ua(); $activity_IP = $this->ip(); list($country_name, $country_code) = self::detect_country($activity_IP); if ($user_id != 0) { $meta_value = array_merge(array( 'status' => $status, 'Date' => $activity_date, 'User Agent' => $activity_agent, 'IP' => $activity_IP, 'Country Name' => $country_name, 'Country Code' => $country_code, ), (array)$args); update_user_meta($user_id, self::USER_META_KEY . "-{$status}", $meta_value); } if ($status === 'login_error') { $sql = $wpdb->prepare( "insert into {$this->ull_table} (`user_id`, `activity_status`, `activity_date`, `activity_agent`, `activity_IP`, `activity_errors`, `country_name`, `country_code`) values (%d, %s, %s, %s, %s, %s, %s, %s)", $user_id, $status, $activity_date, $activity_agent, $activity_IP, serialize($args), $country_name, $country_code ); } else { $sql = $wpdb->prepare( "insert into {$this->ull_table} (`user_id`, `activity_status`, `activity_date`, `activity_agent`, `activity_IP`, `country_name`, `country_code`) values (%d, %s, %s, %s, %s, %s, %s)", $user_id, $status, $activity_date, $activity_agent, $activity_IP, $country_name, $country_code ); } $wpdb->query($sql); return $meta_value; } public function ajax_info(){ if (!is_user_logged_in()) return; $args = $this->last_login_info(); $content = $this->login_info($args); if ($content === false) wp_die('Not logged in.'); $transient_key = 'ull-dismiss-'.md5($this->ip().(isset($args['ip']) ? $args['ip'] : '')); $dismiss = get_transient($transient_key); header('Content-Type: application/json; charset='.get_option('blog_charset')); echo json_encode(array( 'content' => $content, 'login_IP' => isset($args['ip']) ? $args['ip'] : '', 'login_country' => isset($args['ip']) ? $this->get_country_flag($args['ip']) : '', 'login_time' => isset($args['date']) ? $this->nice_time($args['date']) : '', 'IP' => $this->ip(), 'country' => $this->get_country_flag($this->ip()), 'dismiss' => $dismiss, )); die(); } public function ajax_dismiss(){ if (!is_user_logged_in()) return; $args = $this->last_login_info(); $transient_key = 'ull-dismiss-'.md5($this->ip().(isset($args['ip']) ? $args['ip'] : '')); set_transient($transient_key, TRUE, 60 * 60); die(); } public function footer_js(){ if (!is_user_logged_in()) return; $args = $this->last_login_info(); $transient_key = 'ull-dismiss-'.md5($this->ip().(isset($args['ip']) ? $args['ip'] : '')); $dismiss = get_transient($transient_key); $caution = sprintf( "
%s (' + res.login_time + ')
". "".
"%s' + res.login_country + '' + res.login_IP + '
".
"%s' + res.country + '' + res.IP + '".
"
%s
| activity_date); ?> | activity_status); ?> | activity_IP, '', true) . ' ' . esc_html($row->activity_IP)); ?> |
activity_agent) . ' ' . esc_html($ua)); ?> |
| activity_status); ?> | count); ?> |