mirror of
https://github.com/kokororin/typecho-plugin-Access.git
synced 2024-12-27 13:20:54 +08:00
1.7 使用离线ip数据库,支持前端异步写入日志
This commit is contained in:
parent
3a9bf16e98
commit
e471904dac
@ -9,6 +9,7 @@ class Access_Core
|
||||
protected $prefix;
|
||||
protected $table;
|
||||
public $config;
|
||||
protected $response;
|
||||
protected $request;
|
||||
protected $pageSize;
|
||||
protected $isDrop;
|
||||
@ -25,6 +26,7 @@ class Access_Core
|
||||
$this->prefix = $this->db->getPrefix();
|
||||
$this->table = $this->prefix . 'access';
|
||||
$this->config = Typecho_Widget::widget('Widget_Options')->plugin('Access');
|
||||
$this->response = Typecho_Response::getInstance();
|
||||
$this->request = Typecho_Request::getInstance();
|
||||
$this->pageSize = $this->config->pageSize;
|
||||
$this->isDrop = $this->config->isDrop;
|
||||
@ -176,4 +178,48 @@ class Access_Core
|
||||
}
|
||||
}
|
||||
|
||||
public function getReferer()
|
||||
{
|
||||
$referer = Typecho_Cookie::get('__typecho_access_referer');
|
||||
if ($referer == null) {
|
||||
$referer = $this->request->getReferer();
|
||||
if (strpos($referer, rtrim(Helper::options()->siteUrl, '/')) !== false) {
|
||||
$referer = null;
|
||||
}
|
||||
if ($referer != null) {
|
||||
Typecho_Cookie::set('__typecho_access_referer', $referer);
|
||||
}
|
||||
}
|
||||
return $referer;
|
||||
}
|
||||
|
||||
public function writeLogs($url = null)
|
||||
{
|
||||
if ($this->isAdmin()) {
|
||||
return;
|
||||
}
|
||||
$ip = $this->request->getIp();
|
||||
if ($url == null) {
|
||||
$url = $this->request->getServer('REQUEST_URI');
|
||||
}
|
||||
if ($ip == null) {
|
||||
$ip = 'UnKnown';
|
||||
}
|
||||
|
||||
$timeStamp = Helper::options()->gmtTime;
|
||||
$offset = Helper::options()->timezone - Helper::options()->serverTimezone;
|
||||
$gtime = $timeStamp + $offset;
|
||||
$referer = $this->getReferer();
|
||||
$rows = array(
|
||||
'ua' => $this->request->getAgent(),
|
||||
'url' => $url,
|
||||
'ip' => $ip,
|
||||
'referer' => $referer,
|
||||
'referer_domain' => parse_url($this->request->getReferer(), PHP_URL_HOST),
|
||||
'date' => $gtime,
|
||||
);
|
||||
|
||||
$this->db->query($this->db->insert('table.access')->rows($rows));
|
||||
}
|
||||
|
||||
}
|
||||
|
89
Access_Ip.php
Normal file
89
Access_Ip.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
if (!defined('__ACCESS_PLUGIN_ROOT__')) {
|
||||
throw new Exception('Boostrap file not found');
|
||||
}
|
||||
|
||||
class Access_Ip
|
||||
{
|
||||
private static $ip = null;
|
||||
|
||||
private static $fp = null;
|
||||
private static $offset = null;
|
||||
private static $index = null;
|
||||
|
||||
private static $cached = array();
|
||||
|
||||
public static function find($ip)
|
||||
{
|
||||
if (empty($ip) === true) {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
$nip = gethostbyname($ip);
|
||||
$ipdot = explode('.', $nip);
|
||||
|
||||
if ($ipdot[0] < 0 || $ipdot[0] > 255 || count($ipdot) !== 4) {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
if (isset(self::$cached[$nip]) === true) {
|
||||
return self::$cached[$nip];
|
||||
}
|
||||
|
||||
if (self::$fp === null) {
|
||||
self::init();
|
||||
}
|
||||
|
||||
$nip2 = pack('N', ip2long($nip));
|
||||
|
||||
$tmp_offset = (int) $ipdot[0] * 4;
|
||||
$start = unpack('Vlen', self::$index[$tmp_offset] . self::$index[$tmp_offset + 1] . self::$index[$tmp_offset + 2] . self::$index[$tmp_offset + 3]);
|
||||
|
||||
$index_offset = $index_length = null;
|
||||
$max_comp_len = self::$offset['len'] - 1024 - 4;
|
||||
for ($start = $start['len'] * 8 + 1024; $start < $max_comp_len; $start += 8) {
|
||||
if (self::$index{$start} . self::$index{$start + 1} . self::$index{$start + 2} . self::$index{$start + 3} >= $nip2) {
|
||||
$index_offset = unpack('Vlen', self::$index{$start + 4} . self::$index{$start + 5} . self::$index{$start + 6} . "\x0");
|
||||
$index_length = unpack('Clen', self::$index{$start + 7});
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($index_offset === null) {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
fseek(self::$fp, self::$offset['len'] + $index_offset['len'] - 1024);
|
||||
|
||||
self::$cached[$nip] = explode("\t", fread(self::$fp, $index_length['len']));
|
||||
|
||||
return self::$cached[$nip];
|
||||
}
|
||||
|
||||
private static function init()
|
||||
{
|
||||
if (self::$fp === null) {
|
||||
self::$ip = new self();
|
||||
|
||||
self::$fp = fopen(__ACCESS_PLUGIN_ROOT__ . '/lib/17monipdb.dat', 'rb');
|
||||
if (self::$fp === false) {
|
||||
throw new Exception('Invalid 17monipdb.dat file!');
|
||||
}
|
||||
|
||||
self::$offset = unpack('Nlen', fread(self::$fp, 4));
|
||||
if (self::$offset['len'] < 4) {
|
||||
throw new Exception('Invalid 17monipdb.dat file!');
|
||||
}
|
||||
|
||||
self::$index = fread(self::$fp, self::$offset['len'] - 4);
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (self::$fp !== null) {
|
||||
fclose(self::$fp);
|
||||
}
|
||||
}
|
||||
}
|
23
Action.php
23
Action.php
@ -22,17 +22,32 @@ class Access_Action implements Widget_Interface_Do
|
||||
{
|
||||
}
|
||||
|
||||
public function writeLogs()
|
||||
{
|
||||
$this->access->writeLogs($this->request->u);
|
||||
$this->response->setStatus(206);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function ip()
|
||||
{
|
||||
$this->response->setContentType('application/json');
|
||||
try {
|
||||
$this->checkAuth();
|
||||
$ip = $this->request->get('ip');
|
||||
$response = file_get_contents('http://ip.taobao.com/service/getIpInfo.php?ip=' . $ip);
|
||||
if (!$response) {
|
||||
throw new Exception('HTTP request failed');
|
||||
$response = Access_Ip::find($ip);
|
||||
if (is_array($response)) {
|
||||
$response = array(
|
||||
'code' => 0,
|
||||
'data' => implode(' ', $response),
|
||||
);
|
||||
} else {
|
||||
$response = array(
|
||||
'code' => 100,
|
||||
'message' => '解析ip失败',
|
||||
);
|
||||
}
|
||||
exit($response);
|
||||
exit(Json::encode($response));
|
||||
} catch (Exception $e) {
|
||||
exit(Json::encode(array(
|
||||
'code' => 100,
|
||||
|
67
Plugin.php
67
Plugin.php
@ -4,7 +4,7 @@
|
||||
*
|
||||
* @package Access
|
||||
* @author Kokororin
|
||||
* @version 1.5
|
||||
* @version 1.6
|
||||
* @link https://kotori.love
|
||||
*/
|
||||
class Access_Plugin implements Typecho_Plugin_Interface
|
||||
@ -14,9 +14,11 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
{
|
||||
$msg = Access_Plugin::install();
|
||||
Helper::addPanel(1, self::$panel, 'Access控制台', 'Access插件控制台', 'subscriber');
|
||||
Helper::addRoute("access_write_logs", "/access/log/write.json", "Access_Action", 'writeLogs');
|
||||
Helper::addRoute("access_ip", "/access/ip.json", "Access_Action", 'ip');
|
||||
Helper::addRoute("access_delete_logs", "/access/log/delete", "Access_Action", 'deleteLogs');
|
||||
Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('Access_Plugin', 'start');
|
||||
Helper::addRoute("access_delete_logs", "/access/log/delete.json", "Access_Action", 'deleteLogs');
|
||||
Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('Access_Plugin', 'backend');
|
||||
Typecho_Plugin::factory('Widget_Archive')->footer = array('Access_Plugin', 'frontend');
|
||||
Typecho_Plugin::factory('admin/footer.php')->end = array('Access_Plugin', 'adminFooter');
|
||||
return _t($msg);
|
||||
}
|
||||
@ -31,6 +33,7 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
$db->query("DROP TABLE `" . $prefix . "access`", Typecho_Db::WRITE);
|
||||
}
|
||||
Helper::removePanel(1, self::$panel);
|
||||
Helper::removeRoute("access_write_logs");
|
||||
Helper::removeRoute("access_ip");
|
||||
Helper::removeRoute("access_delete_logs");
|
||||
}
|
||||
@ -45,6 +48,11 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
'0' => '删除',
|
||||
'1' => '不删除',
|
||||
), '1', '删除数据表:', '请选择是否在禁用插件时,删除日志数据表');
|
||||
$writeType = new Typecho_Widget_Helper_Form_Element_Radio(
|
||||
'writeType', array(
|
||||
'0' => '后端',
|
||||
'1' => '前端',
|
||||
), '0', '日志写入类型:', '请选择日志写入类型,数据量大时(几万以上),后端写入可能会拖慢博客访问速度');
|
||||
$canAnalytize = new Typecho_Widget_Helper_Form_Element_Radio(
|
||||
'canAnalytize', array(
|
||||
'0' => '不允许',
|
||||
@ -52,6 +60,7 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
), '1', '允许统计使用情况:', '请选择是否允许插件作者统计使用情况');
|
||||
$form->addInput($pageSize);
|
||||
$form->addInput($isDrop);
|
||||
$form->addInput($writeType);
|
||||
$form->addInput($canAnalytize);
|
||||
}
|
||||
|
||||
@ -92,7 +101,10 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
return '成功创建数据表,插件启用成功,' . $configLink;
|
||||
} catch (Typecho_Db_Exception $e) {
|
||||
$code = $e->getCode();
|
||||
if (('Mysql' == $type && $code == (1050 || '42S01'))) {
|
||||
if ($type != 'Mysql') {
|
||||
throw new Typecho_Plugin_Exception('你的适配器为' . $type . ',目前只支持Mysql');
|
||||
}
|
||||
if ($code == (1050 || '42S01')) {
|
||||
$script = 'SELECT * from `' . $prefix . 'access`';
|
||||
$installDb->query($script, Typecho_Db::READ);
|
||||
if (!array_key_exists('referer', $installDb->fetchRow($installDb->select()->from('table.access')))) {
|
||||
@ -103,50 +115,29 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
} else {
|
||||
throw new Typecho_Plugin_Exception('数据表建立失败,插件启用失败。错误号:' . $code);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new Typecho_Plugin_Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static function start($archive)
|
||||
public static function backend($archive)
|
||||
{
|
||||
require_once __DIR__ . '/Access_Bootstrap.php';
|
||||
$access = new Access_Core();
|
||||
if ($access->isAdmin()) {
|
||||
return;
|
||||
}
|
||||
$access->getReferer();
|
||||
$config = Typecho_Widget::widget('Widget_Options')->plugin('Access');
|
||||
|
||||
$request = Typecho_Request::getInstance();
|
||||
$ip = $request->getIp();
|
||||
$url = $request->getServer('REQUEST_URI');
|
||||
if ($ip == null) {
|
||||
$ip = 'UnKnown';
|
||||
if ($config->writeType == 0) {
|
||||
$access->writeLogs();
|
||||
}
|
||||
$options = Typecho_Widget::widget('Widget_Options');
|
||||
$timeStamp = $options->gmtTime;
|
||||
$offset = $options->timezone - $options->serverTimezone;
|
||||
$gtime = $timeStamp + $offset;
|
||||
$db = Typecho_Db::get();
|
||||
$referer = Typecho_Cookie::get('__typecho_access_referer');
|
||||
if ($referer == null) {
|
||||
$referer = $request->getReferer();
|
||||
if (strpos($referer, rtrim(Helper::options()->siteUrl, '/')) !== false) {
|
||||
$referer = null;
|
||||
}
|
||||
if ($referer != null) {
|
||||
Typecho_Cookie::set('__typecho_access_referer', $referer);
|
||||
}
|
||||
}
|
||||
|
||||
public static function frontend()
|
||||
{
|
||||
$config = Typecho_Widget::widget('Widget_Options')->plugin('Access');
|
||||
if ($config->writeType == 1) {
|
||||
echo '<script type="text/javascript">(function(){var xhr=new XMLHttpRequest();xhr.open("GET","' . rtrim(Helper::options()->index, '/') . '/access/log/write.json?u="+location.pathname+location.search+location.hash' . ',true);xhr.send();})();</script>';
|
||||
}
|
||||
|
||||
$rows = array(
|
||||
'ua' => $request->getAgent(),
|
||||
'url' => $url,
|
||||
'ip' => $ip,
|
||||
'referer' => $referer,
|
||||
'referer_domain' => parse_url($request->getReferer(), PHP_URL_HOST),
|
||||
'date' => $gtime,
|
||||
);
|
||||
$db->query($db->insert('table.access')->rows($rows));
|
||||
|
||||
}
|
||||
|
||||
public static function adminFooter()
|
||||
|
BIN
lib/17monipdb.dat
Executable file
BIN
lib/17monipdb.dat
Executable file
Binary file not shown.
@ -254,7 +254,7 @@ $(document).ready(function() {
|
||||
$('a[data-action="ip"]').click(function() {
|
||||
swal({
|
||||
title: "IP查询中...",
|
||||
text: '正在请求Taobao API...',
|
||||
text: '正在查询...',
|
||||
type: "info",
|
||||
confirmButtonText: "OK"
|
||||
});
|
||||
@ -267,7 +267,7 @@ $(document).ready(function() {
|
||||
if (data.code == 0) {
|
||||
swal({
|
||||
title: "IP查询成功",
|
||||
text: data.data.country + data.data.area + data.data.city + data.data.country + data.data.isp,
|
||||
text: data.data,
|
||||
type: "success",
|
||||
confirmButtonText: "OK"
|
||||
});
|
||||
@ -314,7 +314,7 @@ $(document).ready(function() {
|
||||
return swal("错误", "你并没有勾选任何内容", "warning");
|
||||
}
|
||||
$.ajax({
|
||||
url: '<?php echo rtrim(Helper::options()->index, '/').'/access/log/delete';?>',
|
||||
url: '<?php echo rtrim(Helper::options()->index, '/').'/access/log/delete.json';?>',
|
||||
method: 'post',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
|
Loading…
Reference in New Issue
Block a user