Compare commits

...

10 commits

Author SHA1 Message Date
kristuff
d7b635875a v1.1
- Fixed: Update email pattern in `cleanMessage()` method to handle local addresses without TLD and to allow using the caracter `@` in custom message. Close #4
2022-10-06 00:16:16 +02:00
kristuff
af62240932 Update email pattern in cleanMessage() method
Update email pattern to handle local addresses without TLD and to allow using the caracter `@` in custom message. Close #4
2022-10-06 00:14:00 +02:00
kristuff
5639f1813a v1.0 2022-01-26 22:24:24 +01:00
kristuff
dc30007818 v0.9.15
**Changes**
- **New** `ApiHandler::setTimeout(int $timeout)` method allows to change default timeout before any API request. Timeout is expressed in milliseconds. Overwrites the value passed in constructor, useful when performing multiple queries with same handler but different timeout.
2021-12-08 20:42:33 +01:00
kristuff
d1d9cf9ad0 v0.9.14
**Changes**
- **New**: the `ApiHandler` (and `QuietApiHandler`) constructor takes now a **timeout** in third parameter. The timeout is expressed in **milliseconds** .  The timeout will apply to all API request methods (will raise exception if reached out). Default is **0** (no timeout).
- Formatting
2021-12-06 21:40:39 +01:00
kristuff
3ab67950a1 v0.9.13 2021-09-18 21:42:24 +02:00
kristuff
c4b5c65598 Fix #3
Check *properly* if property exists to prevent PHP notice.
2021-09-18 21:41:42 +02:00
kristuff
37b0a2eaa9 v0.9.12
**Fixed**
- Incorrect return type in `ApiResponse::getObject()` method (bug introduced in v0.9.8 with PHP strict types)
- cleaning, typos
2021-07-04 13:09:24 +02:00
kristuff
adff27d86d v0.9.11
**Fixed**
- getCategoryIdByName and getCategoryNameById now return string (instead array)
- IoT Targeted report category now named iot (instead of oit)
2021-02-23 20:31:53 +01:00
kristuff
77c2857eb8 v0.9.10
**Changed**
- report categories methods related now static
- `SilentApiHandler` class renamed `QuietApiHandler` **break change**
- new static method `ApiResponse::createErrorResponse`
2021-01-29 20:30:12 +01:00
10 changed files with 186 additions and 136 deletions

2
.gitignore vendored
View file

@ -1,3 +1 @@
_*
.old*
vendor/*

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020-2021 kristuff
Copyright (c) 2020-2022 kristuff
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -17,6 +17,7 @@ Features
- Bulk report request (send `csv` file) **✓**
- Clear IP address request (remove your own reports) **✓**
- Auto cleaning report comments from sensitive data (email, custom ip/domain names list) **✓**
- Define timeout for cURL internal requests **✓**
Requirements
------------
@ -32,7 +33,7 @@ Deploy with composer:
```json
...
"require": {
"kristuff/abuseipdb": ">=0.9.9-stable"
"kristuff/abuseipdb": "^1.1-stable"
},
```
@ -41,8 +42,7 @@ More infos
- [Project website](https://kristuff.fr/projects/abuseipdb)
- [Api documentation](https://kristuff.fr/projects/abuseipdb/doc)
- [Config/Install guide](https://kristuff.fr/projects/abuseipdb/technical#configuration)
- [CLI version](https://kristuff.fr/projects/abuseipdbcli)
- CLI version: [github](https://github.com/kristuff/abuseipdb-cli) | [website](https://kristuff.fr/projects/abuseipdbcli)
License
@ -50,7 +50,7 @@ License
The MIT License (MIT)
Copyright (c) 2020-2021 Kristuff
Copyright (c) 2020-2022 Kristuff
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -2,11 +2,14 @@
"name": "kristuff/abuseipdb",
"description": "A PHP wrapper for AbuseIPDB API v2",
"type": "library",
"keywords": ["abuseIPDB", "API"],
"license": "MIT",
"authors": [
{
"name": "Kristuff",
"homepage": "https://github.com/kristuff"
"homepage": "https://github.com/kristuff",
"email": "kristuff@kristuff.fr",
"role": "Developer"
}
],
"require": {

View file

@ -1,21 +1,20 @@
<?php declare(strict_types=1);
/**
* _ _ ___ ____ ____ ____
* / \ | |__ _ _ ___ ___|_ _| _ \| _ \| __ )
* / _ \ | '_ \| | | / __|/ _ \| || |_) | | | | _ \
* / ___ \| |_) | |_| \__ \ __/| || __/| |_| | |_) |
* /_/ \_\_.__/ \__,_|___/\___|___|_| |____/|____/
* _ ___ ___ ___ ___
* __ _| |__ _ _ ___ ___|_ _| _ \ \| _ )
* / _` | '_ \ || (_-</ -_)| || _/ |) | _ \
* \__,_|_.__/\_,_/__/\___|___|_| |___/|___/
*
* This file is part of Kristuff\AbsuseIPDB.
* This file is part of Kristuff\AbuseIPDB.
*
* (c) Kristuff <contact@kristuff.fr>
* (c) Kristuff <kristuff@kristuff.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @version 0.9.9
* @copyright 2020-2021 Kristuff
* @version 1.1
* @copyright 2020-2022 Kristuff
*/
namespace Kristuff\AbuseIPDB;
@ -44,12 +43,13 @@ abstract class ApiBase
/**
* AbuseIPDB API v2 categories
* shorname, id (string), long name
* last paramter is false when the category cant' be used alone
* shortname, id (string), long name
* last parameter is false when the category can't be used alone
*
* @static
* @var array
*/
protected $aipdbApiCategories = [
protected static $aipdbApiCategories = [
// Altering DNS records resulting in improper redirection.
['dns-c' , '1', 'DNS Compromise', true],
@ -127,34 +127,36 @@ abstract class ApiBase
// Abuse was targeted at an "Internet of Things" type device. Include
// information about what type of device was targeted in the comments.
['oit' , '23', 'IoT Targeted', true],
['iot' , '23', 'IoT Targeted', true],
];
/**
* Get the list of report categories
*
* @access public
* @static
*
* @return array
*/
public function getCategories()
public static function getCategories(): array
{
return $this->aipdbApiCategories;
return self::$aipdbApiCategories;
}
/**
* Get the category id corresponding to given name
*
* @access public
* @param string $categoryName The report categoriy name
* @static
* @param string $categoryName The report category name
*
* @return string|bool The category id in string format if found, otherwise false
*/
public function getCategoryIdbyName(string $categoryName)
public static function getCategoryIdByName(string $categoryName)
{
foreach ($this->aipdbApiCategories as $cat){
foreach (self::$aipdbApiCategories as $cat){
if ($cat[0] === $categoryName) {
return $cat;
return $cat[1];
}
}
@ -166,15 +168,16 @@ abstract class ApiBase
* Get the category name corresponding to given id
*
* @access public
* @static
* @param string $categoryId The report category id
*
* @return string|bool The category name if found, otherwise false
*/
public function getCategoryNameById(string $categoryId)
public static function getCategoryNameById(string $categoryId)
{
foreach ($this->aipdbApiCategories as $cat){
foreach (self::$aipdbApiCategories as $cat){
if ($cat[1] === $categoryId) {
return $cat;
return $cat[0];
}
}
@ -186,15 +189,16 @@ abstract class ApiBase
* Get the index of category corresponding to given value
*
* @access protected
* @static
* @param string $value The report category id or name
* @param string $index The index in value array
*
* @return int|bool The category index if found, otherwise false
*/
protected function getCategoryIndex(string $value, int $index)
protected static function getCategoryIndex(string $value, int $index)
{
$i = 0;
foreach ($this->aipdbApiCategories as $cat){
foreach (self::$aipdbApiCategories as $cat){
if ($cat[$index] === $value) {
return $i;
}
@ -229,7 +233,7 @@ abstract class ApiBase
foreach ($cats as $cat) {
// get index on our array of categories
$catIndex = is_numeric($cat) ? $this->getCategoryIndex($cat, 1) : $this->getCategoryIndex($cat, 0);
$catIndex = is_numeric($cat) ? self::getCategoryIndex($cat, 1) : self::getCategoryIndex($cat, 0);
// check if found
if ($catIndex === false ){
@ -237,13 +241,13 @@ abstract class ApiBase
}
// get Id
$catId = $this->aipdbApiCategories[$catIndex][1];
$catId = self::$aipdbApiCategories[$catIndex][1];
// need another ?
if ($needAnother !== false){
// is a standalone cat ?
if ($this->aipdbApiCategories[$catIndex][3] === false) {
if (self::$aipdbApiCategories[$catIndex][3] === false) {
$needAnother = true;
} else {

View file

@ -1,21 +1,20 @@
<?php declare(strict_types=1);
/**
* _ _ ___ ____ ____ ____
* / \ | |__ _ _ ___ ___|_ _| _ \| _ \| __ )
* / _ \ | '_ \| | | / __|/ _ \| || |_) | | | | _ \
* / ___ \| |_) | |_| \__ \ __/| || __/| |_| | |_) |
* /_/ \_\_.__/ \__,_|___/\___|___|_| |____/|____/
* _ ___ ___ ___ ___
* __ _| |__ _ _ ___ ___|_ _| _ \ \| _ )
* / _` | '_ \ || (_-</ -_)| || _/ |) | _ \
* \__,_|_.__/\_,_/__/\___|___|_| |___/|___/
*
* This file is part of Kristuff\AbsuseIPDB.
* This file is part of Kristuff\AbuseIPDB.
*
* (c) Kristuff <contact@kristuff.fr>
* (c) Kristuff <kristuff@kristuff.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @version 0.9.9
* @copyright 2020-2021 Kristuff
* @version 1.1
* @copyright 2020-2022 Kristuff
*/
namespace Kristuff\AbuseIPDB;
@ -33,9 +32,9 @@ class ApiHandler extends ApiBase
use CurlTrait;
/**
* @var string $version
* @var string
*/
const VERSION = 'v0.9.9';
const VERSION = 'v1.1';
/**
* The ips to remove from report messages
@ -46,18 +45,46 @@ class ApiHandler extends ApiBase
*/
protected $selfIps = [];
/**
* The maximum number of milliseconds to allow cURL functions to execute. If libcurl is
* built to use the standard system name resolver, that portion of the connect will still
* use full-second resolution for timeouts with a minimum timeout allowed of one second.
*
* @access protected
* @var int
*/
protected $timeout = 0;
/**
* Constructor
*
* @access public
* @param string $apiKey The AbuseIPDB api key
* @param array $myIps The Ips/domain name you don't want to display in report messages
* @param int $timeout The maximum number of milliseconds to allow internal cURL functions
* to execute. Default is 0, no timeout
*
*/
public function __construct(string $apiKey, array $myIps = [])
public function __construct(string $apiKey, array $myIps = [], int $timeout = 0)
{
$this->aipdbApiKey = $apiKey;
$this->selfIps = $myIps;
$this->timeout = $timeout;
}
/**
* Sets the cURL timeout (apply then to any API request). Overwrites the value passed in
* constructor, useful when performing multiple queries with same handler but different timeout.
*
* @access public
* @param int $timeout The maximum number of milliseconds to allow internal cURL functions
* to execute.
*
* @return void
*/
public function setTimeout(int $timeout): void
{
$this->timeout = $timeout;
}
/**
@ -72,6 +99,7 @@ class ApiHandler extends ApiBase
return array(
'apiKey' => $this->aipdbApiKey,
'selfIps' => $this->selfIps,
'timeout' => $this->timeout,
);
}
@ -160,6 +188,7 @@ class ApiHandler extends ApiBase
* @return ApiResponse
* @throws \RuntimeException
* @throws \InvalidArgumentException
* @throws InvalidPermissionException
*/
public function bulkReport(string $filePath): ApiResponse
{
@ -314,7 +343,7 @@ class ApiHandler extends ApiBase
* @param bool $plainText True to get the response in plaintext list. Default is false
* @param int $confidenceMinimum The abuse confidence score minimum (subscribers feature). Default is 100.
* The confidence minimum must be between 25 and 100.
* This parameter is subscriber feature (not honored otherwise).
* This parameter is a subscriber feature (not honored otherwise).
*
* @return ApiResponse
* @throws \RuntimeException
@ -356,8 +385,9 @@ class ApiHandler extends ApiBase
*/
protected function apiRequest(string $path, array $data, string $method = 'GET', string $csvFilePath = ''): ApiResponse
{
// set api url
$url = $this->aipdbApiEndpoint . $path;
$curlErrorNumber = -1; // will be used later to check curl execution
$curlErrorMessage = '';
$url = $this->aipdbApiEndpoint . $path; // api url
// set the wanted format, JSON (required to prevent having full html page on error)
// and the AbuseIPDB API Key as a header
@ -386,17 +416,35 @@ class ApiHandler extends ApiBase
$url .= '?' . http_build_query($data);
}
// set the url to call
// set url and options
$this->setCurlOption($ch, CURLOPT_URL, $url);
$this->setCurlOption($ch, CURLOPT_RETURNTRANSFER, 1);
$this->setCurlOption($ch, CURLOPT_HTTPHEADER, $headers);
/**
* set timeout
*
* @see https://curl.se/libcurl/c/CURLOPT_TIMEOUT_MS.html
* @see https://curl.se/libcurl/c/CURLOPT_CONNECTTIMEOUT_MS.html
* If libcurl is built to use the standard system name resolver, that portion of the transfer
* will still use full-second resolution for timeouts with a minimum timeout allowed of one second.
* In unix-like systems, this might cause signals to be used unless CURLOPT_NOSIGNAL is set.
*/
$this->setCurlOption($ch, CURLOPT_NOSIGNAL, 1);
$this->setCurlOption($ch, CURLOPT_TIMEOUT_MS, $this->timeout);
// execute curl call
$result = curl_exec($ch);
$curlErrorNumber = curl_errno($ch);
$curlErrorMessage = curl_error($ch);
// close connection
curl_close($ch);
if ($curlErrorNumber !== 0){
throw new \RuntimeException($curlErrorMessage);
}
return new ApiResponse($result !== false ? $result : '');
}
@ -421,7 +469,7 @@ class ApiHandler extends ApiBase
}
// If we're reporting spam, further munge any email addresses in the report
$emailPattern = "/[^@\s]*@[^@\s]*\.[^@\s]*/";
$emailPattern = "/\b[A-Z0-9!#$%&'*`\/?^{|}~=+_.-]+@[A-Z0-9.-]+\b/i";
$message = preg_replace($emailPattern, "*", $message);
// Make sure message is less 1024 chars

View file

@ -1,21 +1,20 @@
<?php declare(strict_types=1);
/**
* _ _ ___ ____ ____ ____
* / \ | |__ _ _ ___ ___|_ _| _ \| _ \| __ )
* / _ \ | '_ \| | | / __|/ _ \| || |_) | | | | _ \
* / ___ \| |_) | |_| \__ \ __/| || __/| |_| | |_) |
* /_/ \_\_.__/ \__,_|___/\___|___|_| |____/|____/
* _ ___ ___ ___ ___
* __ _| |__ _ _ ___ ___|_ _| _ \ \| _ )
* / _` | '_ \ || (_-</ -_)| || _/ |) | _ \
* \__,_|_.__/\_,_/__/\___|___|_| |___/|___/
*
* This file is part of Kristuff\AbsuseIPDB.
* This file is part of Kristuff\AbuseIPDB.
*
* (c) Kristuff <contact@kristuff.fr>
* (c) Kristuff <kristuff@kristuff.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @version 0.9.9
* @copyright 2020-2021 Kristuff
* @version 1.1
* @copyright 2020-2022 Kristuff
*/
namespace Kristuff\AbuseIPDB;
@ -50,7 +49,7 @@ class ApiResponse
public function __construct(?string $plaintext = null)
{
$this->curlResponse = $plaintext;
$this->decodedResponse = json_decode($plaintext, false);
$this->decodedResponse = !empty($plaintext) ? json_decode($plaintext, false) : null;
}
/**
@ -70,9 +69,9 @@ class ApiResponse
*
* @access public
*
* @return object|null
* @return \stdClass|null
*/
public function getObject(): ?object
public function getObject(): ?\stdClass
{
return $this->decodedResponse;
}
@ -110,6 +109,29 @@ class ApiResponse
*/
public function errors(): array
{
return ($this->decodedResponse && $this->decodedResponse->errors) ? $this->decodedResponse->errors : [];
return ($this->decodedResponse && property_exists($this->decodedResponse, 'errors')) ? $this->decodedResponse->errors : [];
}
/**
* Get an internal error message in an ApiResponse object
*
* @access public
* @static
* @param string $message The error message
*
* @return ApiResponse
*/
public static function createErrorResponse(string $message): ApiResponse
{
$response = [
"errors" => [
[
"title" => "Internal Error",
"detail" => $message
]
]
];
return new ApiResponse(json_encode($response));
}
}

View file

@ -1,21 +1,20 @@
<?php declare(strict_types=1);
/**
* _ _ ___ ____ ____ ____
* / \ | |__ _ _ ___ ___|_ _| _ \| _ \| __ )
* / _ \ | '_ \| | | / __|/ _ \| || |_) | | | | _ \
* / ___ \| |_) | |_| \__ \ __/| || __/| |_| | |_) |
* /_/ \_\_.__/ \__,_|___/\___|___|_| |____/|____/
* _ ___ ___ ___ ___
* __ _| |__ _ _ ___ ___|_ _| _ \ \| _ )
* / _` | '_ \ || (_-</ -_)| || _/ |) | _ \
* \__,_|_.__/\_,_/__/\___|___|_| |___/|___/
*
* This file is part of Kristuff\AbsuseIPDB.
* This file is part of Kristuff\AbuseIPDB.
*
* (c) Kristuff <contact@kristuff.fr>
* (c) Kristuff <kristuff@kristuff.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @version 0.9.9
* @copyright 2020-2021 Kristuff
* @version 1.1
* @copyright 2020-2022 Kristuff
*/
namespace Kristuff\AbuseIPDB;

View file

@ -1,21 +1,20 @@
<?php declare(strict_types=1);
/**
* _ _ ___ ____ ____ ____
* / \ | |__ _ _ ___ ___|_ _| _ \| _ \| __ )
* / _ \ | '_ \| | | / __|/ _ \| || |_) | | | | _ \
* / ___ \| |_) | |_| \__ \ __/| || __/| |_| | |_) |
* /_/ \_\_.__/ \__,_|___/\___|___|_| |____/|____/
* _ ___ ___ ___ ___
* __ _| |__ _ _ ___ ___|_ _| _ \ \| _ )
* / _` | '_ \ || (_-</ -_)| || _/ |) | _ \
* \__,_|_.__/\_,_/__/\___|___|_| |___/|___/
*
* This file is part of Kristuff\AbsuseIPDB.
* This file is part of Kristuff\AbuseIPDB.
*
* (c) Kristuff <contact@kristuff.fr>
* (c) Kristuff <kristuff@kristuff.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @version 0.9.9
* @copyright 2020-2021 Kristuff
* @version 1.1
* @copyright 2020-2022 Kristuff
*/
namespace Kristuff\AbuseIPDB;

View file

@ -1,56 +1,33 @@
<?php declare(strict_types=1);
/**
* _ _ ___ ____ ____ ____
* / \ | |__ _ _ ___ ___|_ _| _ \| _ \| __ )
* / _ \ | '_ \| | | / __|/ _ \| || |_) | | | | _ \
* / ___ \| |_) | |_| \__ \ __/| || __/| |_| | |_) |
* /_/ \_\_.__/ \__,_|___/\___|___|_| |____/|____/
* _ ___ ___ ___ ___
* __ _| |__ _ _ ___ ___|_ _| _ \ \| _ )
* / _` | '_ \ || (_-</ -_)| || _/ |) | _ \
* \__,_|_.__/\_,_/__/\___|___|_| |___/|___/
*
* This file is part of Kristuff\AbsuseIPDB.
* This file is part of Kristuff\AbuseIPDB.
*
* (c) Kristuff <contact@kristuff.fr>
* (c) Kristuff <kristuff@kristuff.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @version 0.9.9
* @copyright 2020-2021 Kristuff
* @version 1.1
* @copyright 2020-2022 Kristuff
*/
namespace Kristuff\AbuseIPDB;
/**
* Class SilentApiHandler
* Class QuietApiHandler
*
* Overwrite ApiHandler with Exception handling
* Instead of Exception, all method return an ApiResponse that may
* Instead of Exception, all methods return an ApiResponse that may
* contains errors from the AbuseIPDB API, or internal errors
*/
class SilentApiHandler extends ApiHandler
class QuietApiHandler extends ApiHandler
{
/**
* Get an internal error message in an ApiResponse object
*
* @access public
* @param string $message The error message
*
* @return ApiResponse
*/
public function getErrorResponse(string $message): ApiResponse
{
$response = [
"errors" => [
[
"title" => "Internal Error",
"detail" => $message
]
]
];
return new ApiResponse(json_encode($response));
}
/**
* Performs a 'report' api request, with Exception handling
*
@ -66,7 +43,7 @@ class SilentApiHandler extends ApiHandler
try {
return parent::report($ip,$categories,$message);
} catch (\Exception $e) {
return $this->getErrorResponse($e->getMessage());
return ApiResponse::createErrorResponse($e->getMessage());
}
}
@ -83,7 +60,7 @@ class SilentApiHandler extends ApiHandler
try {
return parent::bulkReport($filePath);
} catch (\Exception $e) {
return $this->getErrorResponse($e->getMessage());
return ApiResponse::createErrorResponse($e->getMessage());
}
}
@ -100,7 +77,7 @@ class SilentApiHandler extends ApiHandler
try {
return parent::clearAddress($ip);
} catch (\Exception $e) {
return $this->getErrorResponse($e->getMessage());
return ApiResponse::createErrorResponse($e->getMessage());
}
}
@ -119,7 +96,7 @@ class SilentApiHandler extends ApiHandler
try {
return parent::check($ip, $maxAgeInDays, $verbose);
} catch (\Exception $e) {
return $this->getErrorResponse($e->getMessage());
return ApiResponse::createErrorResponse($e->getMessage());
}
}
@ -137,7 +114,7 @@ class SilentApiHandler extends ApiHandler
try {
return parent::checkBlock($network, $maxAgeInDays);
} catch (\Exception $e) {
return $this->getErrorResponse($e->getMessage());
return ApiResponse::createErrorResponse($e->getMessage());
}
}
@ -149,7 +126,7 @@ class SilentApiHandler extends ApiHandler
* @param bool $plainText True to get the response in plaintext list. Default is false
* @param int $confidenceMinimum The abuse confidence score minimum (subscribers feature). Default is 100.
* The confidence minimum must be between 25 and 100.
* This parameter is subscriber feature (not honored otherwise).
* This parameter is a subscriber feature (not honored otherwise).
*
* @return ApiResponse
*/
@ -158,7 +135,7 @@ class SilentApiHandler extends ApiHandler
try {
return parent::blacklist($limit, $plainText, $confidenceMinimum);
} catch (\Exception $e) {
return $this->getErrorResponse($e->getMessage());
return ApiResponse::createErrorResponse($e->getMessage());
}
}
}