diff --git a/action.php b/action.php index 0c61dca..c85feaa 100644 --- a/action.php +++ b/action.php @@ -54,6 +54,18 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin { ]; /* Write out server-side info to a server log: */ + $this->writeServerLog($username); + } + + /** + * Writes data to the server log. + * + * @return void + */ + private function writeServerLog($username) { + + global $conf; + global $INFO; // what is the session identifier? $sessionId = $_COOKIE['DokuWiki'] ?? ''; @@ -69,6 +81,7 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin { // clean the page ID $pageId = preg_replace('/[\x00-\x1F]/', "\u{FFFD}", $INFO['id'] ?? ''); + // create the log array: $logArr = Array( $_SERVER['REMOTE_ADDR'] ?? '', /* remote IP */ $pageId, /* page ID */ @@ -76,7 +89,9 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin { $sessionType, /* session ID type */ $username, $_SERVER['HTTP_USER_AGENT'] ?? '', /* User agent */ - $_SERVER['HTTP_REFERER'] ?? '' /* HTTP Referrer */ + $_SERVER['HTTP_REFERER'] ?? '', /* HTTP Referrer */ + substr($conf['lang'],0,2), /* page language */ + implode(',', array_unique(array_map( function($it) { return substr($it,0,2); }, explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE'])))) /* accepted client languages */ ); //* create the log line */ @@ -96,6 +111,5 @@ class action_plugin_botmon extends DokuWiki_Action_Plugin { /* Done */ fclose($logfile); - } } \ No newline at end of file diff --git a/data/rules.json b/data/rules.json index 2c049d4..8ddb9cf 100644 --- a/data/rules.json +++ b/data/rules.json @@ -29,6 +29,10 @@ "id": "noRefs", "desc": "No referer field", "bot": 30 }, + {"func": "matchLang", "params": ["en"], + "id": "langMatch", "desc": "Client’s ‘Accept-Language’ header does not match the page language (except English pages)", + "bot": 20 + }, {"func": "clientTest", "params": ["brave"], "id": "susClient", "desc": "Client identifier that is popular with bot networks", "bot": 10 @@ -62,6 +66,7 @@ {"from": "124.243.128.0", "to": "124.243.191.255", "isp": "huawei", "loc":"sg"}, {"from": "150.40.128.0", "to": "150.40.255.255", "isp": "huawei", "loc":"hk"}, {"from": "159.138.0.0", "to": "159.138.225.255", "isp": "huawei", "loc":"th"}, + {"from": "162.128.0.2505", "to": "162.128.127.255", "isp": "zenlayer", "loc":"sg"}, {"from": "166.108.192.0", "to": "166.108.255.255", "isp": "huawei", "loc":"sg"}, {"from": "177.0.0.0", "to": "177.223.255.255", "isp": "ths", "loc":"br"}, {"from": "183.87.32.0", "to": "183.87.159.255", "isp": "huawei", "loc":"hk"}, diff --git a/img/ios.svg b/img/ios.svg index 81eab92..5c302f1 100644 --- a/img/ios.svg +++ b/img/ios.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pview.php b/pview.php index 4208919..2c5d48a 100644 --- a/pview.php +++ b/pview.php @@ -67,7 +67,7 @@ foreach ($logArr as $val) { /* write the log line to the file */ $logfile = fopen($filename, 'a'); if (!$logfile) { - http_response_code(500); + http_response_code(507); die("Error: Unable to open log file. Please check file permissions."); } diff --git a/script.js b/script.js index d3350e4..e64d12d 100644 --- a/script.js +++ b/script.js @@ -234,7 +234,9 @@ BotMon.live = { if ( v.id == visitor.id) { /* match the pre-defined IDs */ return v; } else if (v.ip == visitor.ip && v.agent == visitor.agent) { - console.warn(`Visitor ID “${v.id}” not found, using matchin IP + User-Agent instead.`); + if (v.typ !== 'ip') { + console.warn(`Visitor ID “${v.id}” not found, using matchin IP + User-Agent instead.`); + } return v; } @@ -285,6 +287,10 @@ BotMon.live = { visitor._client = BotMon.live.data.clients.match(nv.agent) ?? null; // client info visitor._platform = BotMon.live.data.platforms.match(nv.agent); // platform info model._visitors.push(visitor); + } else { // update existing + if (visitor._firstSeen < nv.ts) { + visitor._firstSeen = nv.ts; + } } // find browser @@ -307,7 +313,9 @@ BotMon.live = { (prereg.ref !== undefined && prereg.ref !== ''); // update time stamp for last-seen: - visitor._lastSeen = nv.ts; + if (visitor._lastSeen < nv.ts) { + visitor._lastSeen = nv.ts; + } // if needed: return visitor; @@ -444,6 +452,8 @@ BotMon.live = { // shortcut to make code more readable: const model = BotMon.live.data.model; + BotMon.live.gui.status.showBusy("Analysing data …"); + // loop over all visitors: model._visitors.forEach( (v) => { @@ -485,8 +495,8 @@ BotMon.live = { } }); - //console.log(this.data); - //console.log(this.groups); + BotMon.live.gui.status.hideBusy('Done.'); + } }, @@ -848,7 +858,7 @@ BotMon.live = { return false; }, - // unusual combinations of PLatform and Client: + // unusual combinations of Platform and Client: combTest: function(visitor, ...combinations) { for (let i=0; i