Skip to content

Commit

Permalink
matomo-org#7060 feat(bot) added support for detecting bots through cl…
Browse files Browse the repository at this point in the history
…ient-hints
  • Loading branch information
sanchezzzhak committed Dec 30, 2022
1 parent 701351c commit 1bb3bc0
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 8 deletions.
31 changes: 28 additions & 3 deletions ClientHints.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ class ClientHints
*/
protected $app = '';

/**
* Represents `x-client` header field: additional header from applications/bots
* @var string
*/
protected $xClient = '';

/**
* Constructor
*
Expand All @@ -88,8 +94,9 @@ class ClientHints
* @param string $architecture `Sec-CH-UA-Arch` header field
* @param string $bitness `Sec-CH-UA-Bitness`
* @param string $app `HTTP_X-REQUESTED-WITH`
* @param string $xClient `HTTP_X_CLIENT`
*/
public function __construct(string $model = '', string $platform = '', string $platformVersion = '', string $uaFullVersion = '', array $fullVersionList = [], bool $mobile = false, string $architecture = '', string $bitness = '', string $app = '') // phpcs:ignore Generic.Files.LineLength
public function __construct(string $model = '', string $platform = '', string $platformVersion = '', string $uaFullVersion = '', array $fullVersionList = [], bool $mobile = false, string $architecture = '', string $bitness = '', string $app = '', string $xClient = '') // phpcs:ignore Generic.Files.LineLength
{
$this->model = $model;
$this->platform = $platform;
Expand All @@ -100,6 +107,7 @@ public function __construct(string $model = '', string $platform = '', string $p
$this->architecture = $architecture;
$this->bitness = $bitness;
$this->app = $app;
$this->xClient = $xClient;
}

/**
Expand Down Expand Up @@ -221,6 +229,16 @@ public function getApp(): string
return $this->app;
}

/**
* Returns the xClient string
*
* @return string
*/
public function getXClient(): string
{
return $this->xClient;
}

/**
* Factory method to easily instantiate this class using an array containing all available (client hint) headers
*
Expand All @@ -231,7 +249,7 @@ public function getApp(): string
public static function factory(array $headers): ClientHints
{
$model = $platform = $platformVersion = $uaFullVersion = $architecture = $bitness = '';
$app = '';
$app = $xClient = '';
$mobile = false;
$fullVersionList = [];

Expand Down Expand Up @@ -294,6 +312,7 @@ public static function factory(array $headers): ClientHints
if (!empty($fullVersionList)) {
break;
}

// use this only if no other header already set the list
case 'http-sec-ch-ua-full-version-list':
case 'sec-ch-ua-full-version-list':
Expand All @@ -316,6 +335,11 @@ public static function factory(array $headers): ClientHints
$app = $value;
}

break;
case 'http-x-client':
case 'x-client':
$xClient = $value;

break;
}
}
Expand All @@ -329,7 +353,8 @@ public static function factory(array $headers): ClientHints
$mobile,
$architecture,
$bitness,
$app
$app,
$xClient
);
}
}
4 changes: 2 additions & 2 deletions Parser/AbstractParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ abstract class AbstractParser
* Contains a list of mappings from names we use to known client hint values
* @var array<string, array<string>>
*/
protected static $clientHintMapping = [];
protected static $xClientMapping = [];

/**
* Holds an array with method that should be available global
Expand Down Expand Up @@ -269,7 +269,7 @@ protected function getRegexes(): array
*/
protected function applyClientHintMapping(string $name): string
{
foreach (static::$clientHintMapping as $mappedName => $clientHints) {
foreach (static::$xClientMapping as $mappedName => $clientHints) {
foreach ($clientHints as $clientHint) {
if (\strtolower($name) === \strtolower($clientHint)) {
return $mappedName;
Expand Down
27 changes: 27 additions & 0 deletions Parser/Bot.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

namespace DeviceDetector\Parser;

use DeviceDetector\ClientHints;

/**
* Class Bot
*
Expand Down Expand Up @@ -44,6 +46,19 @@ public function discardDetails(): void
$this->discardDetails = true;
}

/**
* Contains a list of mappings from xClient names we use to known x-client values of bots
*
* @var array<string, array<string>>
*/
protected static $xClientMapping = [
'Collabim' => [
'name' => 'Collabim',
'category' => 'Crawler',
'url' => 'https://www.collabim.com/',
],
];

/**
* Parses the current UA and checks whether it contains bot information
*
Expand All @@ -64,6 +79,18 @@ public function discardDetails(): void
*/
public function parse(): ?array
{
if ($this->clientHints instanceof ClientHints && $this->clientHints->getXClient()) {
foreach (self::$xClientMapping as $key => $result) {
if ($this->fuzzyCompare($key, $this->clientHints->getXClient())) {
if ($this->discardDetails) {
return [true];
}

return $result;
}
}
}

$result = null;

if ($this->preMatchOverall()) {
Expand Down
2 changes: 1 addition & 1 deletion Parser/OperatingSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class OperatingSystem extends AbstractParser
*
* @var array<string, array<string>>
*/
protected static $clientHintMapping = [
protected static $xClientMapping = [
'GNU/Linux' => ['Linux'],
'Mac' => ['MacOS'],
];
Expand Down
8 changes: 6 additions & 2 deletions Tests/DeviceDetectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,12 @@ public function testVersionTruncationForClientHints(): void
*/
public function testParseBots(array $fixtureData): void
{
$ua = $fixtureData['user_agent'];
$dd = new DeviceDetector($ua);
$ua = $fixtureData['user_agent'];
$headers = $fixtureData['headers'] ?? [];
$clientHints = ClientHints::factory($headers);
$dd = new DeviceDetector($ua);

$dd->setClientHints($clientHints);
$dd->parse();
$this->assertTrue($dd->isBot());
$botData = $dd->getBot();
Expand Down
8 changes: 8 additions & 0 deletions Tests/fixtures/bots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5452,3 +5452,11 @@
name: ReqBin
category: Crawler
url: https://reqbin.com/curl
-
user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15
headers:
http-x-client: Collabim
bot:
name: Collabim
category: Crawler
url: https://www.collabim.com/

0 comments on commit 1bb3bc0

Please sign in to comment.