mirror of
https://github.com/rekryt/iplist.git
synced 2025-10-13 08:59:34 +03:00
feat: custom output text format
This commit is contained in:
23
README.en.md
23
README.en.md
@@ -151,6 +151,29 @@ composer install
|
|||||||
php index.php
|
php index.php
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Output Format
|
||||||
|
To export data according to a specified template, use format=custom and template=template, where the template can include patterns such as:
|
||||||
|
|
||||||
|
| свойство | описание |
|
||||||
|
|------------|----------------------------------------|
|
||||||
|
| group | Group name |
|
||||||
|
| site | Site name |
|
||||||
|
| data | Selected data |
|
||||||
|
| shortmask | Subnet mask (short) (for IP and CIDR) |
|
||||||
|
| mask | Subnet mask (full) (for IP and CIDR) |
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```
|
||||||
|
Wildcard domains for Twitter DNS static add on MikroTik for forward-to=localhost:
|
||||||
|
https://iplist.opencck.org/?format=custom&data=domains&site=x.com&wildcard=1&template=%2Fip%20dns%20static%20add%20name%3D%7Bdata%7D%20type%3DFWD%20address-list%3D%7Bgroup%7D_%7Bsite%7D%20match-subdomain%3Dyes%20forward-to%3Dlocalhost
|
||||||
|
|
||||||
|
Wildcard domains in custom format:
|
||||||
|
https://iplist.opencck.org/?format=custom&data=domains&wildcard=1&template=data%3A%20%7Bdata%7D%20group%3A%20%7Bgroup%7D%20site%3A%20%7Bsite%7D
|
||||||
|
|
||||||
|
Subnet mask in custom format:
|
||||||
|
https://iplist.opencck.org/?format=custom&data=cidr4&template=data%3A%20%7Bdata%7D%20group%3A%20%7Bgroup%7D%20site%3A%20%7Bsite%7D%20shortmask%3A%20%7Bshortmask%7D%20mask%3A%20%7Bmask%7D
|
||||||
|
```
|
||||||
|
|
||||||
## Setting up Mikrotik
|
## Setting up Mikrotik
|
||||||
- In the router's admin panel (or via winbox), navigate to System -> Scripts.
|
- In the router's admin panel (or via winbox), navigate to System -> Scripts.
|
||||||
- Create a new script by clicking "Add new" and give it a name, for example `iplist_v4_cidr`
|
- Create a new script by clicking "Add new" and give it a name, for example `iplist_v4_cidr`
|
||||||
|
23
README.md
23
README.md
@@ -160,6 +160,29 @@ composer install
|
|||||||
php index.php
|
php index.php
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Кастомный формат вывода
|
||||||
|
Для получения выгрузки данных по заданному шаблону используется format=custom и template=шаблон, где шаблон может содержать такие паттерны как:
|
||||||
|
|
||||||
|
| свойство | описание |
|
||||||
|
|------------|------------------------------------------|
|
||||||
|
| group | Имя группы |
|
||||||
|
| site | Имя сайта |
|
||||||
|
| data | Выбранные данные |
|
||||||
|
| shortmask | Маска подсети (короткая) (для ip и cidr) |
|
||||||
|
| mask | Маска подсети (полная) (для ip и cidr) |
|
||||||
|
|
||||||
|
Примеры:
|
||||||
|
```
|
||||||
|
Wildcard домены twitter для dns static add под mikrotik для forward-to=localhost:
|
||||||
|
https://iplist.opencck.org/?format=custom&data=domains&site=x.com&wildcard=1&template=%2Fip%20dns%20static%20add%20name%3D%7Bdata%7D%20type%3DFWD%20address-list%3D%7Bgroup%7D_%7Bsite%7D%20match-subdomain%3Dyes%20forward-to%3Dlocalhost
|
||||||
|
|
||||||
|
Wildcard домены в кастомном формате:
|
||||||
|
https://iplist.opencck.org/?format=custom&data=domains&wildcard=1&template=data%3A%20%7Bdata%7D%20group%3A%20%7Bgroup%7D%20site%3A%20%7Bsite%7D
|
||||||
|
|
||||||
|
Маска подсети в кастомном формате:
|
||||||
|
https://iplist.opencck.org/?format=custom&data=cidr4&template=data%3A%20%7Bdata%7D%20group%3A%20%7Bgroup%7D%20site%3A%20%7Bsite%7D%20shortmask%3A%20%7Bshortmask%7D%20mask%3A%20%7Bmask%7D
|
||||||
|
```
|
||||||
|
|
||||||
## Настройка Mikrotik
|
## Настройка Mikrotik
|
||||||
- В администраторской панели роутера (или через winbox) откройте раздел System -> Scripts
|
- В администраторской панели роутера (или через winbox) откройте раздел System -> Scripts
|
||||||
- Создайте новый скрипт "Add new" с произвольным именем, например `iplist_v4_cidr`
|
- Создайте новый скрипт "Add new" с произвольным именем, например `iplist_v4_cidr`
|
||||||
|
@@ -57,7 +57,7 @@ abstract class AbstractIPListController extends AbstractController {
|
|||||||
*/
|
*/
|
||||||
protected function getGroups(): array {
|
protected function getGroups(): array {
|
||||||
$groups = [];
|
$groups = [];
|
||||||
foreach ($this->service->sites as $siteEntity) {
|
foreach ($this->getSites() as $siteEntity) {
|
||||||
$groups[$siteEntity->group][$siteEntity->name] = $siteEntity;
|
$groups[$siteEntity->group][$siteEntity->name] = $siteEntity;
|
||||||
}
|
}
|
||||||
return $groups;
|
return $groups;
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
namespace OpenCCK\App\Controller;
|
namespace OpenCCK\App\Controller;
|
||||||
|
|
||||||
use OpenCCK\Domain\Factory\SiteFactory;
|
use OpenCCK\Domain\Factory\SiteFactory;
|
||||||
|
use OpenCCK\Domain\Helper\IP4Helper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://help.keenetic.com/hc/ru/articles/213966749-%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85-%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%BE%D0%B2-%D0%B8%D0%B7-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-bat-%D0%B2-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BD%D0%B5%D1%82-%D1%86%D0%B5%D0%BD%D1%82%D1%80-%D0%B4%D0%BB%D1%8F-%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B9-NDMS-2-11-%D0%B8-%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5-%D1%80%D0%B0%D0%BD%D0%BD%D0%B8%D1%85
|
* @see https://help.keenetic.com/hc/ru/articles/213966749-%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85-%D0%BC%D0%B0%D1%80%D1%88%D1%80%D1%83%D1%82%D0%BE%D0%B2-%D0%B8%D0%B7-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-bat-%D0%B2-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BD%D0%B5%D1%82-%D1%86%D0%B5%D0%BD%D1%82%D1%80-%D0%B4%D0%BB%D1%8F-%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B9-NDMS-2-11-%D0%B8-%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5-%D1%80%D0%B0%D0%BD%D0%BD%D0%B8%D1%85
|
||||||
@@ -39,27 +40,9 @@ class BatController extends AbstractIPListController {
|
|||||||
"\n",
|
"\n",
|
||||||
array_map(function (string $item) {
|
array_map(function (string $item) {
|
||||||
$parts = explode('/', $item);
|
$parts = explode('/', $item);
|
||||||
$mask = $this->formatShortIpMask($parts[1] ?? '');
|
$mask = IP4Helper::formatShortIpMask($parts[1] ?? '');
|
||||||
return 'route add ' . $parts[0] . ' mask ' . $mask . ' 0.0.0.0';
|
return 'route add ' . $parts[0] . ' mask ' . $mask . ' 0.0.0.0';
|
||||||
}, $response)
|
}, $response)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $mask
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function formatShortIpMask(string $mask): string {
|
|
||||||
if ($mask == '') {
|
|
||||||
$mask = '32';
|
|
||||||
}
|
|
||||||
$binaryMask = str_repeat('1', $mask) . str_repeat('0', 32 - $mask);
|
|
||||||
$octets = [];
|
|
||||||
|
|
||||||
for ($i = 0; $i < 4; $i++) {
|
|
||||||
$octets[] = bindec(substr($binaryMask, $i * 8, 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode('.', $octets);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
104
src/App/Controller/CustomController.php
Normal file
104
src/App/Controller/CustomController.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OpenCCK\App\Controller;
|
||||||
|
|
||||||
|
use OpenCCK\Domain\Entity\Site;
|
||||||
|
use OpenCCK\Domain\Factory\SiteFactory;
|
||||||
|
use OpenCCK\Domain\Helper\IP4Helper;
|
||||||
|
use OpenCCK\Domain\Helper\IP6Helper;
|
||||||
|
|
||||||
|
class CustomController extends AbstractIPListController {
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBody(): string {
|
||||||
|
$this->setHeaders(['content-type' => 'text/plain']);
|
||||||
|
|
||||||
|
$sites = SiteFactory::normalizeArray($this->request->getQueryParameters()['site'] ?? []);
|
||||||
|
$data = $this->request->getQueryParameter('data') ?? '';
|
||||||
|
$template = $this->request->getQueryParameter('template') ?? '';
|
||||||
|
if ($data == '') {
|
||||||
|
return "# Error: The 'data' GET parameter is required in the URL to access this page";
|
||||||
|
}
|
||||||
|
if ($template == '') {
|
||||||
|
return "# Error: The 'template' GET parameter is required in the URL to access this page";
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [];
|
||||||
|
foreach ($this->getGroups() as $groupName => $groupSites) {
|
||||||
|
if (count($sites)) {
|
||||||
|
$groupSites = array_filter($groupSites, fn(Site $siteEntity) => in_array($siteEntity->name, $sites));
|
||||||
|
}
|
||||||
|
if (!count($groupSites)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
foreach ($groupSites as $siteName => $siteEntity) {
|
||||||
|
$items = array_merge(
|
||||||
|
$items,
|
||||||
|
$this->generateList(
|
||||||
|
$siteEntity,
|
||||||
|
SiteFactory::normalizeArray(
|
||||||
|
$siteEntity->{$data},
|
||||||
|
in_array($data, ['ip4', 'ip6', 'cidr4', 'cidr6'])
|
||||||
|
),
|
||||||
|
$data,
|
||||||
|
$template
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = array_merge($response, $items);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Site $siteEntity
|
||||||
|
* @param array $dataArray
|
||||||
|
* @param string $data
|
||||||
|
* @param string $template
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function generateList(Site $siteEntity, array $dataArray, string $data, string $template): array {
|
||||||
|
$items = [];
|
||||||
|
foreach ($dataArray as $item) {
|
||||||
|
$patterns = [
|
||||||
|
'group' => $siteEntity->group,
|
||||||
|
'site' => $siteEntity->name,
|
||||||
|
'data' => $item,
|
||||||
|
];
|
||||||
|
switch ($data) {
|
||||||
|
case 'ip4':
|
||||||
|
$patterns['shortmask'] = '32';
|
||||||
|
$patterns['mask'] = IP4Helper::formatShortIpMask($patterns['shortmask']);
|
||||||
|
break;
|
||||||
|
case 'ip6':
|
||||||
|
$patterns['shortmask'] = '128';
|
||||||
|
$patterns['mask'] = IP6Helper::formatShortIpMask($patterns['shortmask']);
|
||||||
|
break;
|
||||||
|
case 'cidr4':
|
||||||
|
$parts = explode('/', $item);
|
||||||
|
$patterns['shortmask'] = $parts[1];
|
||||||
|
$patterns['mask'] = IP4Helper::formatShortIpMask($patterns['shortmask']);
|
||||||
|
break;
|
||||||
|
case 'cidr6':
|
||||||
|
$parts = explode('/', $item);
|
||||||
|
$patterns['shortmask'] = $parts[1];
|
||||||
|
$patterns['mask'] = IP6Helper::formatShortIpMask($patterns['shortmask']);
|
||||||
|
break;
|
||||||
|
case 'domains':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $template;
|
||||||
|
foreach ($patterns as $key => $value) {
|
||||||
|
$result = str_replace('{' . $key . '}', $value, $result);
|
||||||
|
}
|
||||||
|
$items[] = $result;
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
}
|
@@ -155,4 +155,23 @@ class IP4Helper {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* преобразование короткой маски IPv4 в полную
|
||||||
|
* @param string $mask
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function formatShortIpMask(string $mask): string {
|
||||||
|
if ($mask == '') {
|
||||||
|
$mask = '32';
|
||||||
|
}
|
||||||
|
$binaryMask = str_repeat('1', (int) $mask) . str_repeat('0', 32 - $mask);
|
||||||
|
$octets = [];
|
||||||
|
|
||||||
|
for ($i = 0; $i < 4; $i++) {
|
||||||
|
$octets[] = bindec(substr($binaryMask, $i * 8, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode('.', $octets);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -201,4 +201,24 @@ class IP6Helper {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* преобразование короткой маски IPv6 в полную
|
||||||
|
* @param string $mask
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function formatShortIpMask(string $mask): string {
|
||||||
|
if ($mask === '') {
|
||||||
|
$mask = '128';
|
||||||
|
}
|
||||||
|
|
||||||
|
$binaryMask = str_repeat('1', (int) $mask) . str_repeat('0', 128 - $mask);
|
||||||
|
$hextets = [];
|
||||||
|
|
||||||
|
for ($i = 0; $i < 8; $i++) {
|
||||||
|
$hextets[] = dechex(bindec(substr($binaryMask, $i * 16, 16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(':', $hextets);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user