格式化代码

This commit is contained in:
coolxitech 2024-11-09 11:40:37 +08:00
parent 06a0bda77b
commit ec51a2e6b3
47 changed files with 7347 additions and 4394 deletions

View File

@ -1,5 +1,6 @@
<?php
declare (strict_types = 1);
declare (strict_types=1);
namespace app;

View File

@ -1,5 +1,6 @@
<?php
declare (strict_types = 1);
declare (strict_types=1);
namespace app;
@ -102,15 +103,17 @@ abstract class BaseController
if ($url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : (string)$this->app->route->buildUrl($url);
}
if(empty($msg)) $msg = '未知错误';
if (empty($msg)) {
$msg = '未知错误';
}
if (request()->isApi) {
return json(['code'=>$code=='success'?0:-1, 'msg'=>$msg]);
if ($this->request->isApi) {
return json(['code' => $code == 'success' ? 0 : -1, 'msg' => $msg]);
}
if (request()->isAjax()) {
return json(['code'=>$code=='success'?0:-1, 'msg'=>$msg, 'url'=>$url]);
if ($this->request->isAjax()) {
return json(['code' => $code == 'success' ? 0 : -1, 'msg' => $msg, 'url' => $url]);
}
View::assign([
'code' => $code,
'msg' => $msg,

View File

@ -1,4 +1,5 @@
<?php
namespace app;
use think\db\exception\DataNotFoundException;

View File

@ -1,8 +1,8 @@
<?php
namespace app;
// 应用请求对象类
class Request extends \think\Request
{
}

View File

@ -1,80 +1,82 @@
<?php
declare (strict_types = 1);
namespace app\command;
use Exception;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;
use app\lib\TaskRunner;
class Dmtask extends Command
{
protected function configure()
{
// 指令配置
$this->setName('dmtask')
->setDescription('容灾切换任务');
}
protected function execute(Input $input, Output $output)
{
$res = Db::name('config')->cache('configs',0)->column('value','key');
Config::set($res, 'sys');
config_set('run_error', '');
if(!extension_loaded('swoole')){
$output->writeln('[Error] 未安装Swoole扩展');
config_set('run_error', '未安装Swoole扩展');
return;
}
try{
$output->writeln('进程启动成功.');
$this->runtask();
}catch(Exception $e){
$output->writeln('[Error] '.$e->getMessage());
config_set('run_error', $e->getMessage());
}
}
private function runtask(){
\Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
\Co\run(function() {
$date = date("Ymd");
$count = config_get('run_count', null, true) ?? 0;
while(true){
sleep(1);
if($date != date("Ymd")){
$count = 0;
$date = date("Ymd");
}
$rows = Db::name('dmtask')->where('checknexttime', '<=', time())->where('active', 1)->order('id', 'ASC')->select();
foreach($rows as $row){
\go(function () use($row) {
try{
(new TaskRunner())->execute($row);
} catch (\Swoole\ExitException $e) {
echo $e->getStatus()."\n";
} catch (Exception $e) {
echo $e->__toString()."\n";
}
});
Db::name('dmtask')->where('id', $row['id'])->update([
'checktime' => time(),
'checknexttime' => time() + $row['frequency']
]);
$count++;
}
config_set('run_time', date("Y-m-d H:i:s"));
config_set('run_count', $count);
}
});
}
}
<?php
declare (strict_types=1);
namespace app\command;
use Exception;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;
use app\lib\TaskRunner;
class Dmtask extends Command
{
protected function configure()
{
// 指令配置
$this->setName('dmtask')
->setDescription('容灾切换任务');
}
protected function execute(Input $input, Output $output)
{
$res = Db::name('config')->cache('configs', 0)->column('value', 'key');
Config::set($res, 'sys');
config_set('run_error', '');
if (!extension_loaded('swoole')) {
$output->writeln('[Error] 未安装Swoole扩展');
config_set('run_error', '未安装Swoole扩展');
return;
}
try {
$output->writeln('进程启动成功.');
$this->runtask();
} catch (Exception $e) {
$output->writeln('[Error] '.$e->getMessage());
config_set('run_error', $e->getMessage());
}
}
private function runtask()
{
\Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);
\Co\run(function () {
$date = date("Ymd");
$count = config_get('run_count', null, true) ?? 0;
while (true) {
sleep(1);
if ($date != date("Ymd")) {
$count = 0;
$date = date("Ymd");
}
$rows = Db::name('dmtask')->where('checknexttime', '<=', time())->where('active', 1)->order('id', 'ASC')->select();
foreach ($rows as $row) {
\go(function () use ($row) {
try {
(new TaskRunner())->execute($row);
} catch (\Swoole\ExitException $e) {
echo $e->getStatus()."\n";
} catch (Exception $e) {
echo $e->__toString()."\n";
}
});
Db::name('dmtask')->where('id', $row['id'])->update([
'checktime' => time(),
'checknexttime' => time() + $row['frequency']
]);
$count++;
}
config_set('run_time', date("Y-m-d H:i:s"));
config_set('run_count', $count);
}
});
}
}

View File

@ -1,32 +1,33 @@
<?php
declare (strict_types = 1);
namespace app\command;
use Exception;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;
use app\lib\OptimizeService;
class Opiptask extends Command
{
protected function configure()
{
// 指令配置
$this->setName('opiptask')
->setDescription('CF优选IP任务');
}
protected function execute(Input $input, Output $output)
{
$res = Db::name('config')->cache('configs',0)->column('value','key');
Config::set($res, 'sys');
(new OptimizeService())->execute();
}
}
<?php
declare (strict_types=1);
namespace app\command;
use Exception;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Config;
use app\lib\OptimizeService;
class Opiptask extends Command
{
protected function configure()
{
// 指令配置
$this->setName('opiptask')
->setDescription('CF优选IP任务');
}
protected function execute(Input $input, Output $output)
{
$res = Db::name('config')->cache('configs', 0)->column('value', 'key');
Config::set($res, 'sys');
(new OptimizeService())->execute();
}
}

View File

@ -1,228 +1,257 @@
<?php
// 应用公共文件
use think\facade\Db;
function get_curl($url, $post=0, $referer=0, $cookie=0, $header=0, $ua=0, $nobody=0, $addheader=0)
// 应用公共文件
use app\model\Config;
use think\facade\Db;
use GuzzleHttp\Client;
use think\facade\Request;
function get_curl(string $url, $post = 0, $referer = 0, $cookie = 0, $header = 0, $ua = 0, $nobody = 0)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$httpheader[] = "Accept: */*";
$httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
$httpheader[] = "Connection: close";
if($addheader){
$httpheader = array_merge($httpheader, $addheader);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
if ($post) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
}
if ($header) {
curl_setopt($ch, CURLOPT_HEADER, true);
}
if ($cookie) {
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
}
if($referer){
curl_setopt($ch, CURLOPT_REFERER, $referer);
}
if ($ua) {
curl_setopt($ch, CURLOPT_USERAGENT, $ua);
}
else {
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0");
}
if ($nobody) {
curl_setopt($ch, CURLOPT_NOBODY, 1);
}
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
$options = [];
if (is_array($header) && !empty($header)) {
$options['headers'] = $header;
}
if ($ua) {
$options['headers']['user-agent'] = $ua;
} else {
$options['headers']['user-agent'] = 'Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0';
}
if (is_string($referer) && $referer != '') {
$options['headers']['referer'] = $referer;
}
if (is_string($cookie) && $cookie != '') {
$options['headers']['cookie'] = $cookie;
}
$client = new Client($options);
if (!is_array($post)) {
$response = $client->get($url);
} else {
$response = $client->post($url, [
'form_params' => $post,
'headers' => $header,
'verify' => false
]);
}
if ($nobody) {
$ret = $response->getHeaders();
} else {
$ret = $response->getBody()->getContents();
}
return $ret;
}
function real_ip($type=0){
function real_ip($type = 0)
{
$ip = $_SERVER['REMOTE_ADDR'];
if($type<=0 && isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
foreach ($matches[0] AS $xip) {
if ($type <= 0 && isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
foreach ($matches[0] as $xip) {
if (filter_var($xip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$ip = $xip;
break;
}
}
} elseif ($type<=0 && isset($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
} elseif ($type <= 0 && isset($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif ($type<=1 && isset($_SERVER['HTTP_CF_CONNECTING_IP']) && filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
} elseif ($type <= 1 && isset($_SERVER['HTTP_CF_CONNECTING_IP']) && filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
} elseif ($type<=1 && isset($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
} elseif ($type <= 1 && isset($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$ip = $_SERVER['HTTP_X_REAL_IP'];
}
return $ip;
}
function strexists($string, $find) {
return !(strpos($string, $find) === FALSE);
function strexists($string, $find)
{
return !(strpos($string, $find) === false);
}
function dstrpos($string, $arr) {
if(empty($string)) return false;
foreach((array)$arr as $v) {
if(strpos($string, $v) !== false) {
return true;
}
}
return false;
function dstrpos($string, $arr)
{
if (empty($string)) {
return false;
}
foreach ((array)$arr as $v) {
if (strpos($string, $v) !== false) {
return true;
}
}
return false;
}
function checkmobile() {
$useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
$ualist = array('android', 'midp', 'nokia', 'mobile', 'iphone', 'ipod', 'blackberry', 'windows phone');
if((dstrpos($useragent, $ualist) || strexists($_SERVER['HTTP_ACCEPT'], "VND.WAP") || strexists($_SERVER['HTTP_VIA'],"wap")))
return true;
else
return false;
function checkmobile()
{
$useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
$ualist = array('android', 'midp', 'nokia', 'mobile', 'iphone', 'ipod', 'blackberry', 'windows phone');
if ((dstrpos($useragent, $ualist) || strexists($_SERVER['HTTP_ACCEPT'], "VND.WAP") || strexists($_SERVER['HTTP_VIA'], "wap"))) {
return true;
} else {
return false;
}
}
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if(((int)substr($result, 0, 10) == 0 || (int)substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.base64_encode($result);
}
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
{
$ckey_length = 4;
$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for ($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for ($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for ($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if ($operation == 'DECODE') {
if (((int)substr($result, 0, 10) == 0 || (int)substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.base64_encode($result);
}
}
function random($length, $numeric = 0) {
$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
$hash = '';
$max = strlen($seed) - 1;
for($i = 0; $i < $length; $i++) {
$hash .= $seed[mt_rand(0, $max)];
}
return $hash;
function random($length, $numeric = 0)
{
$seed = base_convert(md5(microtime().$_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
$seed = $numeric ? (str_replace('0', '', $seed).'012340567890') : ($seed.'zZ'.strtoupper($seed));
$hash = '';
$max = strlen($seed) - 1;
for ($i = 0; $i < $length; $i++) {
$hash .= $seed[mt_rand(0, $max)];
}
return $hash;
}
function checkDomain($domain){
if(empty($domain) || !preg_match('/^[-$a-z0-9_*.]{2,512}$/i', $domain) || (stripos($domain, '.') === false) || substr($domain, -1) == '.' || substr($domain, 0 ,1) == '.' || substr($domain, 0 ,1) == '*' && substr($domain, 1 ,1) != '.' || substr_count($domain, '*')>1 || strpos($domain, '*')>0 || strlen($domain)<4) return false;
return true;
function checkDomain($domain)
{
if (empty($domain) || !preg_match('/^[-$a-z0-9_*.]{2,512}$/i', $domain) || (stripos($domain, '.') === false) || str_ends_with($domain, '.') || str_starts_with($domain, '.') || str_starts_with($domain, '*') && substr($domain, 1, 1) != '.' || substr_count($domain, '*') > 1 || strpos($domain, '*') > 0 || strlen($domain) < 4) {
return false;
}
return true;
}
function getSubstr($str, $leftStr, $rightStr)
{
$left = strpos($str, $leftStr);
$start = $left+strlen($leftStr);
$right = strpos($str, $rightStr, $start);
if($left < 0) return '';
if($right>0){
return substr($str, $start, $right-$start);
}else{
return substr($str, $start);
}
$left = strpos($str, $leftStr);
$start = $left + strlen($leftStr);
$right = strpos($str, $rightStr, $start);
if ($left < 0) {
return '';
}
if ($right > 0) {
return substr($str, $start, $right - $start);
} else {
return substr($str, $start);
}
}
function checkRefererHost(){
if(!request()->header('referer'))return false;
$url_arr = parse_url(request()->header('referer'));
$http_host = request()->header('host');
if(strpos($http_host,':'))$http_host = substr($http_host, 0, strpos($http_host, ':'));
function checkRefererHost()
{
if (!Request::header('referer')) {
return false;
}
$url_arr = parse_url(Request::header('referer'));
$http_host = Request::header('host');
if (strpos($http_host, ':')) {
$http_host = substr($http_host, 0, strpos($http_host, ':'));
}
return $url_arr['host'] === $http_host;
}
function checkIfActive($string) {
$array=explode(',',$string);
$action = request()->action();
if (in_array($action,$array)){
return 'active';
}else
return null;
function checkIfActive($string)
{
$array = explode(',', $string);
$action = Request::action();
if (in_array($action, $array)) {
return 'active';
} else {
return null;
}
}
function getSid() {
function getSid()
{
return md5(uniqid(mt_rand(), true) . microtime());
}
function getMd5Pwd($pwd, $salt=null) {
function getMd5Pwd($pwd, $salt = null)
{
return md5(md5($pwd) . md5('1277180438'.$salt));
}
function isNullOrEmpty($str){
return $str === null || $str === '';
function isNullOrEmpty($str)
{
return $str === null || $str === '';
}
function checkPermission($type, $domain = null){
$user = request()->user;
if(empty($user)) return false;
if($user['level'] == 2) return true;
if($type == 1 && $user['level'] == 1 || $type == 0 && $user['level'] >= 0){
if($domain == null) return true;
if(in_array($domain, $user['permission'])){
return true;
}
}
return false;
function checkPermission($type, $domain = null)
{
$user = Request()->user;
if (empty($user)) {
return false;
}
if ($user['level'] == 2) {
return true;
}
if ($type == 1 && $user['level'] == 1 || $type == 0 && $user['level'] >= 0) {
if ($domain == null) {
return true;
}
if (in_array($domain, $user['permission'])) {
return true;
}
}
return false;
}
function getAdminSkin(){
$skin = cookie('admin_skin');
if(empty($skin)){
$skin = config_get('admin_skin');
}
if(empty($skin)){
$skin = 'skin-black-blue';
}
return $skin;
function getAdminSkin()
{
$skin = cookie('admin_skin');
if (empty($skin)) {
$skin = config_get('admin_skin');
}
if (empty($skin)) {
$skin = 'skin-black-blue';
}
return $skin;
}
function config_get($key, $default = null, $force = false)
{
if ($force) {
$value = Db::name('config')->where('key', $key)->value('value');
} else {
$value = config('sys.'.$key);
}
if ($force) {
$value = Config::where('key', $key)->value('value');
} else {
$value = config("sys.$key");
}
return $value ?: $default;
}
function config_set($key, $value)
{
$res = Db::name('config')->replace()->insert(['key'=>$key, 'value'=>$value]);
return $res!==false;
$res = Db::name('config')->replace()->insert(['key' => $key, 'value' => $value]);
return $res !== false;
}
function getMillisecond()
@ -231,24 +260,30 @@ function getMillisecond()
return (int)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
function getDnsType($value){
if(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))return 'A';
else if(filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))return 'AAAA';
else return 'CNAME';
function getDnsType($value)
{
if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
return 'A';
} elseif (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
return 'AAAA';
} else {
return 'CNAME';
}
}
function convert_second($s){
$m = floor($s/60);
if($m == 0){
return $s.'秒';
}else{
$s = $s%60;
$h = floor($m/60);
if($h == 0){
return $m.'分钟'.$s.'秒';
}else{
$m = $m%60;
return $h.'小时'.$m.'分钟'.$s.'秒';
}
}
}
function convert_second($s)
{
$m = floor($s / 60);
if ($m == 0) {
return $s.'秒';
} else {
$s = $s % 60;
$h = floor($m / 60);
if ($h == 0) {
return $m.'分钟'.$s.'秒';
} else {
$m = $m % 60;
return $h.'小时'.$m.'分钟'.$s.'秒';
}
}
}

View File

@ -1,61 +1,60 @@
<?php
namespace app\controller;
use app\BaseController;
use Exception;
use think\facade\Db;
use think\facade\View;
use app\lib\DnsHelper;
use app\model\Log;
use app\model\User;
use app\model\Domain as DomainModel;
use think\captcha\facade\Captcha;
use think\response;
class Auth extends BaseController
{
public function verifycode()
public function login(): response
{
return captcha();
}
public function login(){
$login_limit_count = 5;//登录失败次数
$login_limit_file = app()->getRuntimePath().'@login.lock';
$login_limit_file = app()->getRuntimePath() . '@login.lock';
if(request()->islogin){
if ($this->request->islogin) {
return redirect('/');
}
if(request()->isAjax()){
$username = input('post.username',null,'trim');
$password = input('post.password',null,'trim');
$code = input('post.code',null,'trim');
if(empty($username) || empty($password)){
return json(['code'=>-1, 'msg'=>'用户名或密码不能为空']);
if ($this->request->isAjax()) {
$username = $this->request->post('username', null, 'trim');
$password = $this->request->post('password', null, 'trim');
$code = $this->request->post('code', null, 'trim');
if (empty($username) || empty($password)) {
return json(['code' => -1, 'msg' => '用户名或密码不能为空']);
}
if(!captcha_check($code)){
return json(['code'=>-1, 'msg'=>'验证码错误', 'vcode'=>1]);
if (!Captcha::check($code)) {
return json(['code' => -1, 'msg' => '验证码错误', 'vcode' => 1]);
}
if (file_exists($login_limit_file)) {
$login_limit = unserialize(file_get_contents($login_limit_file));
if ($login_limit['count'] >= $login_limit_count && $login_limit['time'] > time() - 7200) {
exit(json_encode(['code' => -1, 'msg' => '多次登录失败,暂时禁止登录。可删除/runtime/@login.lock文件解除限制', 'vcode'=>1]));
return json(['code' => -1, 'msg' => '多次登录失败,暂时禁止登录。可删除/runtime/@login.lock文件解除限制', 'vcode' => 1]);
}
}
$user = Db::name('user')->where('username', $username)->find();
if($user && password_verify($password, $user['password'])){
if($user['status'] == 0) return json(['code'=>-1, 'msg'=>'此用户已被封禁', 'vcode'=>1]);
Db::name('log')->insert(['uid' => $user['id'], 'action' => '登录后台', 'data' => 'IP:'.$this->clientip, 'addtime' => date("Y-m-d H:i:s")]);
DB::name('user')->where('id', $user['id'])->update(['lasttime' => date("Y-m-d H:i:s")]);
$session = md5($user['id'].$user['password']);
$expiretime = time()+2562000;
$user = User::where('username', $username)->find();
if ($user && password_verify($password, $user['password'])) {
if ($user['status'] == 0) {
return json(['code' => -1, 'msg' => '此用户已被封禁', 'vcode' => 1]);
}
Log::insert(['uid' => $user['id'], 'action' => '登录后台', 'data' => 'IP:' . $this->clientip, 'addtime' => date("Y-m-d H:i:s")]);
User::where('id', $user['id'])->update(['lasttime' => date("Y-m-d H:i:s")]);
$session = md5($user['id'] . $user['password']);
$expiretime = time() + 2562000;
$token = authcode("user\t{$user['id']}\t{$session}\t{$expiretime}", 'ENCODE', config_get('sys_key'));
cookie('user_token', $token, ['expire' => $expiretime, 'httponly' => true]);
if (file_exists($login_limit_file)) {
unlink($login_limit_file);
}
return json(['code'=>0]);
}else{
if($user){
Db::name('log')->insert(['uid' => $user['id'], 'action' => '登录失败', 'data' => 'IP:'.$this->clientip, 'addtime' => date("Y-m-d H:i:s")]);
return json(['code' => 0]);
} else {
if ($user) {
Log::insert(['uid' => $user['id'], 'action' => '登录失败', 'data' => 'IP:' . $this->clientip, 'addtime' => date("Y-m-d H:i:s")]);
}
if (!file_exists($login_limit_file)) {
$login_limit = ['count' => 0, 'time' => 0];
@ -75,44 +74,49 @@ class Auth extends BaseController
return view();
}
public function logout()
public function logout(): response
{
cookie('user_token', null);
return redirect('/login');
}
public function quicklogin()
public function quicklogin(): response
{
$domain = input('get.domain',null,'trim');
$timestamp = input('get.timestamp',null,'trim');
$token = input('get.token',null,'trim');
$sign = input('get.sign',null,'trim');
if(empty($domain) || empty($timestamp) || empty($token) || empty($sign)){
$domain = $this->request->get('domain', null, 'trim');
$timestamp = $this->request->get('timestamp', null, 'trim');
$token = $this->request->get('token', null, 'trim');
$sign = $this->request->get('sign', null, 'trim');
if (empty($domain) || empty($timestamp) || empty($token) || empty($sign)) {
return $this->alert('error', '参数错误');
}
if($timestamp < time()-300 || $timestamp > time()+300){
if ($timestamp < time() - 300 || $timestamp > time() + 300) {
return $this->alert('error', '时间戳无效');
}
if(md5(config_get('sys_key').$domain.$timestamp.$token.config_get('sys_key')) !== $sign){
if (md5(config_get('sys_key') . $domain . $timestamp . $token . config_get('sys_key')) !== $sign) {
return $this->alert('error', '签名错误');
}
if($token != cache('quicklogin_'.$domain)){
if ($token != cache('quicklogin_' . $domain)) {
return $this->alert('error', 'Token无效');
}
$row = Db::name('domain')->where('name', $domain)->find();
if(!$row){
$row = DomainModel::where('name', $domain)->find();
if (!$row) {
return $this->alert('error', '该域名不存在');
}
if(!$row['is_sso']){
if (!$row['is_sso']) {
return $this->alert('error', '该域名不支持快捷登录');
}
Db::name('log')->insert(['uid' => 0, 'action' => '域名快捷登录', 'data' => 'IP:'.$this->clientip, 'addtime' => date("Y-m-d H:i:s"), 'domain' => $domain]);
Log::insert(['uid' => 0, 'action' => '域名快捷登录', 'data' => 'IP:' . $this->clientip, 'addtime' => date("Y-m-d H:i:s"), 'domain' => $domain]);
$session = md5($row['id'].$row['name']);
$expiretime = time()+2562000;
$session = md5($row['id'] . $row['name']);
$expiretime = time() + 2562000;
$token = authcode("domain\t{$row['id']}\t{$session}\t{$expiretime}", 'ENCODE', config_get('sys_key'));
cookie('user_token', $token, ['expire' => $expiretime, 'httponly' => true]);
return redirect('/record/'.$row['id']);
return redirect('/record/' . $row['id']);
}
public function verifycode()
{
return Captcha::create();
}
}

View File

@ -1,301 +1,309 @@
<?php
namespace app\controller;
use app\BaseController;
use Exception;
use think\facade\Db;
use think\facade\View;
use think\facade\Cache;
use app\lib\DnsHelper;
class Dmonitor extends BaseController
{
public function overview()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$switch_count = Db::name('dmlog')->where('date', '>=', date("Y-m-d H:i:s",strtotime("-1 days")))->count();
$fail_count = Db::name('dmlog')->where('date', '>=', date("Y-m-d H:i:s",strtotime("-1 days")))->where('action', 1)->count();
$run_time = config_get('run_time', null, true);
$run_state = $run_time ? (time()-strtotime($run_time) > 10 ? 0 : 1) : 0;
View::assign('info', [
'run_count' => config_get('run_count', null, true) ?? 0,
'run_time' => $run_time ?? '无',
'run_state' => $run_state,
'run_error' => config_get('run_error', null, true),
'switch_count' => $switch_count,
'fail_count' => $fail_count,
'swoole' => extension_loaded('swoole') ? '<font color="green">已安装</font>' : '<font color="red">未安装</font>',
]);
return View::fetch();
}
public function task()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
return View::fetch();
}
public function task_data(){
if(!checkPermission(2)) return json(['total'=>0, 'rows'=>[]]);
$type = input('post.type/d', 1);
$kw = input('post.kw', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('dmtask')->alias('A')->join('domain B','A.did = B.id');
if(!empty($kw)){
if($type == 1){
$select->whereLike('rr|B.name', '%'.$kw.'%');
}elseif($type == 2){
$select->where('recordid', $kw);
}elseif($type == 3){
$select->where('main_value', $kw);
}elseif($type == 4){
$select->where('backup_value', $kw);
}elseif($type == 5){
$select->whereLike('remark', '%'.$kw.'%');
}
}
$total = $select->count();
$list = $select->order('A.id','desc')->limit($offset, $limit)->field('A.*,B.name domain')->select()->toArray();
foreach($list as &$row){
$row['checktimestr'] = date('Y-m-d H:i:s', $row['checktime']);
}
return json(['total'=>$total, 'rows'=>$list]);
}
public function taskform()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$action = input('param.action');
if(request()->isPost()){
if($action == 'add'){
$task = [
'did' => input('post.did/d'),
'rr' => input('post.rr', null, 'trim'),
'recordid' => input('post.recordid', null, 'trim'),
'type' => input('post.type/d'),
'main_value' => input('post.main_value', null, 'trim'),
'backup_value' => input('post.backup_value', null, 'trim'),
'checktype' => input('post.checktype/d'),
'checkurl' => input('post.checkurl', null, 'trim'),
'tcpport' => !empty(input('post.tcpport')) ? input('post.tcpport/d') : null,
'frequency' => input('post.frequency/d'),
'cycle' => input('post.cycle/d'),
'timeout' => input('post.timeout/d'),
'proxy' => input('post.proxy/d'),
'remark' => input('post.remark', null, 'trim'),
'recordinfo' => input('post.recordinfo', null, 'trim'),
'addtime' => time(),
'active' => 1
];
if(empty($task['did']) || empty($task['rr']) || empty($task['recordid']) || empty($task['main_value']) || empty($task['frequency']) || empty($task['cycle'])){
return json(['code'=>-1, 'msg'=>'必填项不能为空']);
}
if($task['checktype'] > 0 && $task['timeout'] > $task['frequency']){
return json(['code'=>-1, 'msg'=>'为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
}
if($task['type'] == 2 && $task['backup_value'] == $task['main_value']){
return json(['code'=>-1, 'msg'=>'主备地址不能相同']);
}
if(Db::name('dmtask')->where('recordid', $task['recordid'])->find()){
return json(['code'=>-1, 'msg'=>'当前容灾切换策略已存在']);
}
Db::name('dmtask')->insert($task);
return json(['code'=>0, 'msg'=>'添加成功']);
}elseif($action == 'edit'){
$id = input('post.id/d');
$task = [
'did' => input('post.did/d'),
'rr' => input('post.rr', null, 'trim'),
'recordid' => input('post.recordid', null, 'trim'),
'type' => input('post.type/d'),
'main_value' => input('post.main_value', null, 'trim'),
'backup_value' => input('post.backup_value', null, 'trim'),
'checktype' => input('post.checktype/d'),
'checkurl' => input('post.checkurl', null, 'trim'),
'tcpport' => !empty(input('post.tcpport')) ? input('post.tcpport/d') : null,
'frequency' => input('post.frequency/d'),
'cycle' => input('post.cycle/d'),
'timeout' => input('post.timeout/d'),
'proxy' => input('post.proxy/d'),
'remark' => input('post.remark', null, 'trim'),
'recordinfo' => input('post.recordinfo', null, 'trim'),
];
if(empty($task['did']) || empty($task['rr']) || empty($task['recordid']) || empty($task['main_value']) || empty($task['frequency']) || empty($task['cycle'])){
return json(['code'=>-1, 'msg'=>'必填项不能为空']);
}
if($task['checktype'] > 0 && $task['timeout'] > $task['frequency']){
return json(['code'=>-1, 'msg'=>'为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
}
if($task['type'] == 2 && $task['backup_value'] == $task['main_value']){
return json(['code'=>-1, 'msg'=>'主备地址不能相同']);
}
if(Db::name('dmtask')->where('recordid', $task['recordid'])->where('id', '<>', $id)->find()){
return json(['code'=>-1, 'msg'=>'当前容灾切换策略已存在']);
}
Db::name('dmtask')->where('id', $id)->update($task);
return json(['code'=>0, 'msg'=>'修改成功']);
}elseif($action == 'setactive'){
$id = input('post.id/d');
$active = input('post.active/d');
Db::name('dmtask')->where('id', $id)->update(['active'=>$active]);
return json(['code'=>0, 'msg'=>'设置成功']);
}elseif($action == 'del'){
$id = input('post.id/d');
Db::name('dmtask')->where('id', $id)->delete();
Db::name('dmlog')->where('taskid', $id)->delete();
return json(['code'=>0, 'msg'=>'删除成功']);
}else{
return json(['code'=>-1, 'msg'=>'参数错误']);
}
}
$task = null;
if($action == 'edit'){
$id = input('get.id/d');
$task = Db::name('dmtask')->where('id', $id)->find();
if(empty($task)) return $this->alert('error', '切换策略不存在');
}
$domains = [];
foreach(Db::name('domain')->select() as $row){
$domains[$row['id']] = $row['name'];
}
View::assign('domains', $domains);
View::assign('info', $task);
View::assign('action', $action);
View::assign('support_ping', function_exists('exec')?'1':'0');
return View::fetch();
}
public function taskinfo()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$id = input('param.id/d');
$task = Db::name('dmtask')->where('id', $id)->find();
if(empty($task)) return $this->alert('error', '切换策略不存在');
$switch_count = Db::name('dmlog')->where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s",strtotime("-1 days")))->count();
$fail_count = Db::name('dmlog')->where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s",strtotime("-1 days")))->where('action', 1)->count();
$task['switch_count'] = $switch_count;
$task['fail_count'] = $fail_count;
if($task['type'] == 3){
$task['action_name'] = ['未知', '<font color="red">开启解析</font>', '<font color="green">暂停解析</font>'];
}elseif($task['type'] == 2){
$task['action_name'] = ['未知', '<font color="red">切换备用解析记录</font>', '<font color="green">恢复主解析记录</font>'];
}else{
$task['action_name'] = ['未知', '<font color="red">暂停解析</font>', '<font color="green">启用解析</font>'];
}
View::assign('info', $task);
return View::fetch();
}
public function tasklog_data(){
if(!checkPermission(2)) return json(['total'=>0, 'rows'=>[]]);
$taskid = input('param.id/d');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$action = input('post.action/d', 0);
$select = Db::name('dmlog')->where('taskid', $taskid);
if($action > 0){
$select->where('action', $action);
}
$total = $select->count();
$list = $select->order('id','desc')->limit($offset, $limit)->select();
return json(['total'=>$total, 'rows'=>$list]);
}
public function noticeset()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
if(request()->isPost()){
$params = input('post.');
if(isset($params['mail_type']) && isset($params['mail_name2']) && $params['mail_type'] > 0){
$params['mail_name'] = $params['mail_name2'];
unset($params['mail_name2']);
}
foreach ($params as $key=>$value){
if (empty($key)) {
continue;
}
config_set($key, $value);
Cache::delete('configs');
}
return json(['code'=>0, 'msg'=>'succ']);
}
return View::fetch();
}
public function proxyset()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
if(request()->isPost()){
$params = input('post.');
foreach ($params as $key=>$value){
if (empty($key)) {
continue;
}
config_set($key, $value);
Cache::delete('configs');
}
return json(['code'=>0, 'msg'=>'succ']);
}
return View::fetch();
}
public function mailtest()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$mail_name = config_get('mail_recv')?config_get('mail_recv'):config_get('mail_name');
if(empty($mail_name)) return json(['code'=>-1, 'msg'=>'您还未设置邮箱!']);
$result = \app\lib\MsgNotice::send_mail($mail_name,'邮件发送测试。','这是一封测试邮件!<br/><br/>来自:'.request()->root(true));
if($result === true){
return json(['code'=>0, 'msg'=>'邮件发送成功!']);
}else{
return json(['code'=>-1, 'msg'=>'邮件发送失败!'.$result]);
}
}
public function tgbottest()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$tgbot_token = config_get('tgbot_token');
$tgbot_chatid = config_get('tgbot_chatid');
if(empty($tgbot_token) || empty($tgbot_chatid)) return json(['code'=>-1, 'msg'=>'请先保存设置']);
$content = "<strong>消息发送测试</strong>\n\n这是一封测试消息!\n\n来自:".request()->root(true);
$result = \app\lib\MsgNotice::send_telegram_bot($content);
if($result === true){
return json(['code'=>0, 'msg'=>'消息发送成功!']);
}else{
return json(['code'=>-1, 'msg'=>'消息发送失败!'.$result]);
}
}
public function clean()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
if(request()->isPost()){
$days = input('post.days/d');
if(!$days || $days < 0) return json(['code'=>-1, 'msg'=>'参数错误']);
Db::execute("DELETE FROM `".config('database.connections.mysql.prefix')."dmlog` WHERE `date`<'".date("Y-m-d H:i:s",strtotime("-".$days." days"))."'");
Db::execute("OPTIMIZE TABLE `".config('database.connections.mysql.prefix')."dmlog`");
return json(['code'=>0, 'msg'=>'清理成功']);
}
}
public function status()
{
$run_time = config_get('run_time', null, true);
$run_state = $run_time ? (time()-strtotime($run_time) > 10 ? 0 : 1) : 0;
return $run_state == 1 ? 'ok' : 'error';
}
}
<?php
namespace app\controller;
use app\BaseController;
use app\lib\MsgNotice;
use app\model\Dmlog;
use app\model\Dmtask;
use Exception;
use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use think\facade\Db;
use think\facade\Request;
use think\facade\View;
use think\facade\Cache;
use app\model\Domain;
class Dmonitor extends BaseController
{
public function overview()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$switch_count = Dmlog::where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->count();
$fail_count = Dmlog::where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->where('action', 1)->count();
$run_time = config_get('run_time', null, true);
$run_state = $run_time ? (time() - strtotime($run_time) > 10 ? 0 : 1) : 0;
View::assign('info', [
'run_count' => config_get('run_count', null, true) ?? 0,
'run_time' => $run_time ?? '无',
'run_state' => $run_state,
'run_error' => config_get('run_error', null, true),
'switch_count' => $switch_count,
'fail_count' => $fail_count,
'swoole' => extension_loaded('swoole') ? '<font color="green">已安装</font>' : '<font color="red">未安装</font>',
]);
return View::fetch();
}
public function task()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
return View::fetch();
}
public function task_data()
{
if (!checkPermission(2)) {
return json(['total' => 0, 'rows' => []]);
}
$type = $this->request->post('type', 1);
$kw = $this->request->post('kw', null, 'trim');
$offset = $this->request->post('offset');
$limit = $this->request->post('limit');
$select = Dmtask::alias('A')->join('domain B', 'A.did = B.id');
if (!empty($kw)) {
$select = match ($type) {
1 => $select->where('rr', $kw),
2 => $select->where('recordid', $kw),
3 => $select->where('main_value', $kw),
4 => $select->where('backup_value', $kw),
5 => $select->where('remark', $kw),
default => throw new Exception('参数错误'),
};
}
$total = $select->count();
$list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select()->toArray();
foreach ($list as &$row) {
$row['checktimestr'] = date('Y-m-d H:i:s', $row['checktime']);
}
return json(['total' => $total, 'rows' => $list]);
}
public function taskform()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$action = $this->request->param('action');
if ($this->request->isPost()) {
if ($action == 'add') {
$task = $this->request->post();
$task['addtime'] = time();
$task['active'] = 1;
if (!isset($task['did'], $task['rr'], $task['recordid'], $task['main_value'], $task['frequency'], $task['cycle'])) {
return json(['code' => -1, 'msg' => '必填项不能为空']);
}
if ($task['checktype'] > 0 && $task['timeout'] > $task['frequency']) {
return json(['code' => -1, 'msg' => '为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
}
if ($task['type'] == 2 && $task['backup_value'] == $task['main_value']) {
return json(['code' => -1, 'msg' => '主备地址不能相同']);
}
if (Db::name('dmtask')->where('recordid', $task['recordid'])->find()) {
return json(['code' => -1, 'msg' => '当前容灾切换策略已存在']);
}
Db::name('dmtask')->insert($task);
return json(['code' => 0, 'msg' => '添加成功']);
} elseif ($action == 'edit') {
$id = $this->request->post('id');
$task = $this->request->post();
unset($task['id']);
if (!isset($task['did'], $task['rr'], $task['recordid'], $task['main_value'], $task['frequency'], $task['cycle'])) {
return json(['code' => -1, 'msg' => '必填项不能为空']);
}
if ($task['checktype'] > 0 && $task['timeout'] > $task['frequency']) {
return json(['code' => -1, 'msg' => '为保障容灾切换任务正常运行,最大超时时间不能大于检测间隔']);
}
if ($task['type'] == 2 && $task['backup_value'] == $task['main_value']) {
return json(['code' => -1, 'msg' => '主备地址不能相同']);
}
if (Dmtask::where('recordid', $task['recordid'])->where('id', '<>', $id)->find()) {
return json(['code' => -1, 'msg' => '当前容灾切换策略已存在']);
}
Dmtask::where('id', $id)->update($task);
return json(['code' => 0, 'msg' => '修改成功']);
} elseif ($action == 'setactive') {
$id = $this->request->post('id');
$active = $this->request->post('active');
Dmtask::where('id', $id)->update(['active' => $active]);
return json(['code' => 0, 'msg' => '设置成功']);
} elseif ($action == 'del') {
$id = $this->request->post('id');
Dmtask::where('id', $id)->delete();
Dmlog::where('taskid', $id)->delete();
return json(['code' => 0, 'msg' => '删除成功']);
} else {
return json(['code' => -1, 'msg' => '参数错误']);
}
}
$task = null;
if ($action == 'edit') {
$id = $this->request->get('id');
$task = Dmtask::where('id', $id)->find();
if (empty($task)) {
return $this->alert('error', '切换策略不存在');
}
}
$domains = [];
foreach (Domain::select() as $row) {
$domains[$row['id']] = $row['name'];
}
View::assign('domains', $domains);
View::assign('info', $task);
View::assign('action', $action);
View::assign('support_ping', function_exists('exec') ? '1' : '0');
return View::fetch();
}
public function taskinfo()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$id = $this->request->param('id');
$task = Dmtask::where('id', $id)->find();
if (empty($task)) {
return $this->alert('error', '切换策略不存在');
}
$switch_count = Dmlog::where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->count();
$fail_count = Dmlog::where('taskid', $id)->where('date', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))->where('action', 1)->count();
$task['switch_count'] = $switch_count;
$task['fail_count'] = $fail_count;
if ($task['type'] == 3) {
$task['action_name'] = ['未知', '<span style="color: red; ">开启解析</span>', '<span style="color: green; ">暂停解析</span>'];
} elseif ($task['type'] == 2) {
$task['action_name'] = ['未知', '<span style="color: red; ">切换备用解析记录</span>', '<span style="color: green; ">恢复主解析记录</span>'];
} else {
$task['action_name'] = ['未知', '<span style="color: red; ">暂停解析</span>', '<span style="color: green; ">启用解析</span>'];
}
View::assign('info', $task);
return View::fetch();
}
public function tasklog_data()
{
if (!checkPermission(2)) {
return json(['total' => 0, 'rows' => []]);
}
$taskid = $this->request->param('id');
$offset = $this->request->post('offset');
$limit = $this->request->post('limit');
$action = $this->request->post('action', 0);
$select = Dmlog::where('taskid', $taskid);
if ($action > 0) {
$select->where('action', $action);
}
$total = $select->count();
$list = $select->order('id', 'desc')->limit($offset, $limit)->select();
return json(['total' => $total, 'rows' => $list]);
}
public function noticeset()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
if ($this->request->isPost()) {
$params = $this->request->post();
if (isset($params['mail_type']) && isset($params['mail_name2']) && $params['mail_type'] > 0) {
$params['mail_name'] = $params['mail_name2'];
unset($params['mail_name2']);
}
foreach ($params as $key => $value) {
if (empty($key)) {
continue;
}
config_set($key, $value);
Cache::delete('configs');
}
return json(['code' => 0, 'msg' => 'succ']);
}
return View::fetch();
}
public function proxyset()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
if ($this->request->isPost()) {
$params = $this->request->post();
foreach ($params as $key => $value) {
if (empty($key)) {
continue;
}
config_set($key, $value);
Cache::delete('configs');
}
return json(['code' => 0, 'msg' => 'succ']);
}
return View::fetch();
}
public function mailtest()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
if (empty($mail_name)) {
return json(['code' => -1, 'msg' => '您还未设置邮箱!']);
}
$result = MsgNotice::send_mail($mail_name, '邮件发送测试。', '这是一封测试邮件!<br/><br/>来自:' . $this->request->root(true));
if ($result === true) {
return json(['code' => 0, 'msg' => '邮件发送成功!']);
} else {
return json(['code' => -1, 'msg' => '邮件发送失败!' . $result]);
}
}
public function tgbottest()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$tgbot_token = config_get('tgbot_token');
$tgbot_chatid = config_get('tgbot_chatid');
if (empty($tgbot_token) || empty($tgbot_chatid)) {
return json(['code' => -1, 'msg' => '请先保存设置']);
}
$content = "<strong>消息发送测试</strong>\n\n这是一封测试消息!\n\n来自:" . $this->request->root(true);
$result = MsgNotice::send_telegram_bot($content);
if ($result === true) {
return json(['code' => 0, 'msg' => '消息发送成功!']);
} else {
return json(['code' => -1, 'msg' => '消息发送失败!' . $result]);
}
}
public function clean()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
if (Request::isPost()) {
$days = $this->request->post('days');
if (!$days || $days < 0) {
return json(['code' => -1, 'msg' => '参数错误']);
}
Dmlog::where('date', '<', date("Y-m-d H:i:s", strtotime("-" . $days . " days")))->delete();
Db::execute("OPTIMIZE TABLE `" . config('database.connections.mysql.prefix') . "dmlog`");
return json(['code' => 0, 'msg' => '清理成功']);
}
}
public function status()
{
$run_time = config_get('run_time', null, true);
$run_state = $run_time ? (time() - strtotime($run_time) > 10 ? 0 : 1) : 0;
return $run_state == 1 ? 'ok' : 'error';
}
}

View File

@ -1,38 +1,41 @@
<?php
namespace app\controller;
use app\BaseController;
use Exception;
use think\captcha\facade\Captcha;
use think\facade\Db;
use think\facade\View;
use think\facade\Cache;
use think\facade\Request;
use app\lib\DnsHelper;
class Index extends BaseController
{
public function index()
{
if(request()->user['type'] == 'domain'){
return redirect('/record/'.request()->user['id']);
if ($this->request->user['type'] == 'domain') {
return redirect('/record/' . $this->request->user['id']);
}
if(request()->isAjax()){
if(input('post.do') == 'stat'){
$stat = ['domains'=>0, 'users'=>0, 'records'=>0, 'types'=>count(DnsHelper::$dns_config)];
if(request()->user['level'] == 2){
if ($this->request->isAjax()) {
if (input('post.do') == 'stat') {
$stat = ['domains' => 0, 'users' => 0, 'records' => 0, 'types' => count(DnsHelper::$dns_config)];
if ($this->request->user['level'] == 2) {
$stat['domains'] = Db::name('domain')->count();
$stat['users'] = Db::name('user')->count();
$stat['records'] = Db::name('domain')->sum('recordcount');
}else{
$stat['domains'] = Db::name('domain')->where('name', 'in', request()->user['permission'])->count();
} else {
$stat['domains'] = Db::name('domain')->where('name', 'in', $this->request->user['permission'])->count();
$stat['users'] = 1;
$stat['records'] = Db::name('domain')->where('name', 'in', request()->user['permission'])->sum('recordcount');
$stat['records'] = Db::name('domain')->where('name', 'in', $this->request->user['permission'])->sum('recordcount');
}
return json($stat);
}
return json(['code'=>-3]);
return json(['code' => -3]);
}
if(config('app.dbversion') && config_get('version') != config('app.dbversion')){
if (config('app.dbversion') && config_get('version') != config('app.dbversion')) {
$this->db_update();
config_set('version', config('app.dbversion'));
Cache::clear();
@ -49,74 +52,120 @@ class Index extends BaseController
'date' => date("Y-m-d H:i:s"),
];
View::assign('info', $info);
View::assign('checkupdate', '//auth.cccyun.cc/app/dnsmgr.php?ver='.config('app.version'));
View::assign('checkupdate', '//auth.cccyun.cc/app/dnsmgr.php?ver=' . config('app.version'));
return view();
}
private function db_update(){
$sqls=file_get_contents(app()->getAppPath().'sql/update.sql');
private function db_update()
{
$sqls = file_get_contents(app()->getAppPath() . 'sql/update.sql');
$mysql_prefix = env('database.prefix', 'dnsmgr_');
$sqls=explode(';', $sqls);
$sqls = explode(';', $sqls);
foreach ($sqls as $value) {
$value=trim($value);
if(empty($value))continue;
$value = str_replace('dnsmgr_',$mysql_prefix,$value);
try{
$value = trim($value);
if (empty($value)) {
continue;
}
$value = str_replace('dnsmgr_', $mysql_prefix, $value);
try {
Db::execute($value);
}catch(Exception $e){
} catch (Exception $e) {
}
}
}
public function changeskin(){
public function changeskin()
{
$skin = input('post.skin');
if(request()->user['level'] == 2){
if(cookie('admin_skin')){
if ($this->request->user['level'] == 2) {
if (cookie('admin_skin')) {
cookie('admin_skin', null);
}
config_set('admin_skin', $skin);
Cache::delete('configs');
}else{
} else {
cookie('admin_skin', $skin);
}
return json(['code'=>0,'msg'=>'succ']);
return json(['code' => 0, 'msg' => 'succ']);
}
public function cleancache(){
if(!checkPermission(1)) return $this->alert('error', '无权限');
public function cleancache()
{
if (!checkPermission(1)) {
return $this->alert('error', '无权限');
}
Cache::clear();
return json(['code'=>0,'msg'=>'succ']);
$this->clearDirectory(app()->getRuntimePath().'cache/');
$this->clearDirectory(app()->getRuntimePath().'temp/');
return json(['code' => 0, 'msg' => 'succ']);
}
public function doc(){
if(!checkPermission(1)) return $this->alert('error', '无权限');
View::assign('siteurl', request()->root(true));
public function doc()
{
if (!checkPermission(1)) {
return $this->alert('error', '无权限');
}
View::assign('siteurl', $this->request->root(true));
return view();
}
public function setpwd(){
if(!checkPermission(1)) return $this->alert('error', '无权限');
if(request()->isPost()){
public function setpwd()
{
if (!checkPermission(1)) {
return $this->alert('error', '无权限');
}
if ($this->request->isPost()) {
$oldpwd = input('post.oldpwd');
$newpwd = input('post.newpwd');
$newpwd2 = input('post.newpwd2');
if(empty($oldpwd) || empty($newpwd) || empty($newpwd2)){
return json(['code'=>-1, 'msg'=>'密码不能为空']);
if (empty($oldpwd) || empty($newpwd) || empty($newpwd2)) {
return json(['code' => -1, 'msg' => '密码不能为空']);
}
if($newpwd != $newpwd2){
return json(['code'=>-1, 'msg'=>'两次输入的密码不一致']);
if ($newpwd != $newpwd2) {
return json(['code' => -1, 'msg' => '两次输入的密码不一致']);
}
if(!password_verify($oldpwd, request()->user['password'])){
return json(['code'=>-1, 'msg'=>'原密码错误']);
if (!password_verify($oldpwd, $this->request->user['password'])) {
return json(['code' => -1, 'msg' => '原密码错误']);
}
Db::name('user')->where('id', request()->user['id'])->update(['password'=>password_hash($newpwd, PASSWORD_DEFAULT)]);
return json(['code'=>0, 'msg'=>'succ']);
Db::name('user')->where('id', $this->request->user['id'])->update(['password' => password_hash($newpwd, PASSWORD_DEFAULT)]);
return json(['code' => 0, 'msg' => 'succ']);
}
return view();
}
public function test(){
public function test()
{
}
private function clearDirectory($dir)
{
// 确保路径是目录
if (!is_dir($dir)) {
return false;
}
// 打开目录
$items = scandir($dir);
foreach ($items as $item) {
// 跳过 '.' 和 '..'
if ($item == '.' || $item == '..') {
continue;
}
// 完整路径
$path = $dir . DIRECTORY_SEPARATOR . $item;
// 如果是目录,递归删除其内容
if (is_dir($path)) {
clearDirectory($path);
// 删除空目录
rmdir($path);
} else {
// 删除文件
unlink($path);
}
}
return true;
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\controller;
use Exception;
@ -12,10 +13,10 @@ class Install extends BaseController
{
public function index()
{
if (file_exists(app()->getRootPath().'.env')){
if (file_exists(app()->getRootPath() . '.env')) {
return '当前已经安装成功,如果需要重新安装,请手动删除根目录.env文件';
}
if(request()->isPost()){
if (Request::isPost()) {
$mysql_host = Request::post('mysql_host');
$mysql_port = intval(Request::post('mysql_port', '3306'));
$mysql_user = Request::post('mysql_user', null, 'trim');
@ -25,65 +26,66 @@ class Install extends BaseController
$admin_username = Request::post('admin_username', null, 'trim');
$admin_password = Request::post('admin_password', null, 'trim');
if(!$mysql_host || !$mysql_user || !$mysql_pwd || !$mysql_name || !$admin_username || !$admin_password){
return json(['code'=>0, 'msg'=>'必填项不能为空']);
if (!$mysql_host || !$mysql_user || !$mysql_pwd || !$mysql_name || !$admin_username || !$admin_password) {
return json(['code' => 0, 'msg' => '必填项不能为空']);
}
$configData = file_get_contents(app()->getRootPath().'.example.env');
$configData = str_replace(['{dbhost}','{dbname}','{dbuser}','{dbpwd}','{dbport}','{dbprefix}'], [$mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configData);
$configData = file_get_contents(app()->getRootPath() . '.example.env');
$configData = str_replace(['{dbhost}', '{dbname}', '{dbuser}', '{dbpwd}', '{dbport}', '{dbprefix}'], [$mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configData);
try{
$DB = Db::connect();
$DB=new PDO("mysql:host=".$mysql_host.";dbname=".$mysql_name.";port=".$mysql_port,$mysql_user,$mysql_pwd);
}catch(Exception $e){
if($e->getCode() == 2002){
$errorMsg='连接数据库失败:数据库地址填写错误!';
}elseif($e->getCode() == 1045){
$errorMsg='连接数据库失败:数据库用户名或密码填写错误!';
}elseif($e->getCode() == 1049){
$errorMsg='连接数据库失败:数据库名不存在!';
}else{
$errorMsg='连接数据库失败:'.$e->getMessage();
try {
$DB = new PDO("mysql:host=" . $mysql_host . ";dbname=" . $mysql_name . ";port=" . $mysql_port, $mysql_user, $mysql_pwd);
} catch (Exception $e) {
if ($e->getCode() == 2002) {
$errorMsg = '连接数据库失败:数据库地址填写错误!';
} elseif ($e->getCode() == 1045) {
$errorMsg = '连接数据库失败:数据库用户名或密码填写错误!';
} elseif ($e->getCode() == 1049) {
$errorMsg = '连接数据库失败:数据库名不存在!';
} else {
$errorMsg = '连接数据库失败:' . $e->getMessage();
}
return json(['code'=>0, 'msg'=>$errorMsg]);
return json(['code' => 0, 'msg' => $errorMsg]);
}
$DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$DB->exec("set sql_mode = ''");
$DB->exec("set names utf8");
$sqls=file_get_contents(app()->getAppPath().'sql/install.sql');
$sqls=explode(';', $sqls);
$sqls = file_get_contents(app()->getAppPath() . 'sql/install.sql');
$sqls = explode(';', $sqls);
$password = password_hash($admin_password, PASSWORD_DEFAULT);
$sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('sys_key', '".random(16)."')";
$sqls[]="INSERT INTO `".$mysql_prefix."user` (`username`,`password`,`level`,`regtime`,`lasttime`,`status`) VALUES ('".addslashes($admin_username)."', '$password', 2, NOW(), NOW(), 1)";
$sqls[] = "REPLACE INTO `" . $mysql_prefix . "config` VALUES ('sys_key', '" . random(16) . "')";
$sqls[] = "INSERT INTO `" . $mysql_prefix . "user` (`username`,`password`,`level`,`regtime`,`lasttime`,`status`) VALUES ('" . addslashes($admin_username) . "', '$password', 2, NOW(), NOW(), 1)";
$success = 0;
$error = 0;
$errorMsg = null;
foreach ($sqls as $value) {
$value=trim($value);
if(empty($value))continue;
$value = str_replace('dnsmgr_',$mysql_prefix,$value);
if($DB->exec($value)===false){
$value = trim($value);
if (empty($value)) {
continue;
}
$value = str_replace('dnsmgr_', $mysql_prefix, $value);
if ($DB->exec($value) === false) {
$error++;
$dberror=$DB->errorInfo();
$errorMsg.=$dberror[2]."\n";
}else{
$dberror = $DB->errorInfo();
$errorMsg .= $dberror[2] . "\n";
} else {
$success++;
}
}
if(empty($errorMsg)){
if(!file_put_contents(app()->getRootPath().'.env', $configData)){
return json(['code'=>0, 'msg'=>'保存失败,请确保网站根目录有写入权限']);
if (empty($errorMsg)) {
if (!file_put_contents(app()->getRootPath() . '.env', $configData)) {
return json(['code' => 0, 'msg' => '保存失败,请确保网站根目录有写入权限']);
}
Cache::clear();
return json(['code'=>1, 'msg'=>'安装完成成功执行SQL语句'.$success.'条']);
}else{
return json(['code'=>0, 'msg'=>$errorMsg]);
return json(['code' => 1, 'msg' => '安装完成成功执行SQL语句' . $success . '条']);
} else {
return json(['code' => 0, 'msg' => $errorMsg]);
}
}
return view();
}
}

View File

@ -1,174 +1,192 @@
<?php
namespace app\controller;
use app\BaseController;
use Exception;
use think\facade\Db;
use think\facade\View;
use think\facade\Cache;
use app\lib\OptimizeService;
class Optimizeip extends BaseController
{
public function opipset()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
if(request()->isPost()){
$params = input('post.');
foreach ($params as $key=>$value){
if (empty($key)) {
continue;
}
config_set($key, $value);
Cache::delete('configs');
}
return json(['code'=>0, 'msg'=>'succ']);
}
return View::fetch();
}
public function opiplist()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
return View::fetch();
}
public function opiplist_data(){
if(!checkPermission(2)) return json(['total'=>0, 'rows'=>[]]);
$type = input('post.type/d', 1);
$kw = input('post.kw', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('optimizeip')->alias('A')->join('domain B','A.did = B.id');
if(!empty($kw)){
if($type == 1){
$select->whereLike('rr|B.name', '%'.$kw.'%');
}elseif($type == 2){
$select->whereLike('remark', '%'.$kw.'%');
}
}
$total = $select->count();
$list = $select->order('A.id','desc')->limit($offset, $limit)->field('A.*,B.name domain')->select();
return json(['total'=>$total, 'rows'=>$list]);
}
public function opipform()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$action = input('param.action');
if(request()->isPost()){
if($action == 'add'){
$task = [
'did' => input('post.did/d'),
'rr' => input('post.rr', null, 'trim'),
'type' => input('post.type/d'),
'ip_type' => input('post.ip_type', null, 'trim'),
'cdn_type' => input('post.cdn_type/d'),
'recordnum' => input('post.recordnum/d'),
'ttl' => input('post.ttl/d'),
'remark' => input('post.remark', null, 'trim'),
'addtime' => date('Y-m-d H:i:s'),
'active' => 1
];
if(empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])){
return json(['code'=>-1, 'msg'=>'必填项不能为空']);
}
if($task['recordnum'] > 5){
return json(['code'=>-1, 'msg'=>'解析数量不能超过5个']);
}
if(Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->find()){
return json(['code'=>-1, 'msg'=>'当前域名的优选IP任务已存在']);
}
Db::name('optimizeip')->insert($task);
return json(['code'=>0, 'msg'=>'添加成功']);
}elseif($action == 'edit'){
$id = input('post.id/d');
$task = [
'did' => input('post.did/d'),
'rr' => input('post.rr', null, 'trim'),
'type' => input('post.type/d'),
'ip_type' => input('post.ip_type', null, 'trim'),
'cdn_type' => input('post.cdn_type/d'),
'recordnum' => input('post.recordnum/d'),
'ttl' => input('post.ttl/d'),
'remark' => input('post.remark', null, 'trim'),
];
if(empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])){
return json(['code'=>-1, 'msg'=>'必填项不能为空']);
}
if($task['recordnum'] > 5){
return json(['code'=>-1, 'msg'=>'解析数量不能超过5个']);
}
if(Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->where('id', '<>', $id)->find()){
return json(['code'=>-1, 'msg'=>'当前域名的优选IP任务已存在']);
}
Db::name('optimizeip')->where('id', $id)->update($task);
return json(['code'=>0, 'msg'=>'修改成功']);
}elseif($action == 'setactive'){
$id = input('post.id/d');
$active = input('post.active/d');
Db::name('optimizeip')->where('id', $id)->update(['active'=>$active]);
return json(['code'=>0, 'msg'=>'设置成功']);
}elseif($action == 'del'){
$id = input('post.id/d');
Db::name('optimizeip')->where('id', $id)->delete();
return json(['code'=>0, 'msg'=>'删除成功']);
}elseif($action == 'run'){
$id = input('post.id/d');
$task = Db::name('optimizeip')->where('id', $id)->find();
if(empty($task)) return json(['code'=>-1, 'msg'=>'任务不存在']);
try{
$result = (new OptimizeService())->execute_one($task);
Db::name('optimizeip')->where('id', $id)->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]);
return json(['code'=>0, 'msg'=>'优选任务执行成功:'.$result]);
}catch(Exception $e){
Db::name('optimizeip')->where('id', $id)->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]);
return json(['code'=>-1, 'msg'=>'优选任务执行失败:'.$e->getMessage(), 'stack'=>$e->__toString()]);
}
}else{
return json(['code'=>-1, 'msg'=>'参数错误']);
}
}
$task = null;
if($action == 'edit'){
$id = input('get.id/d');
$task = Db::name('optimizeip')->where('id', $id)->find();
if(empty($task)) return $this->alert('error', '任务不存在');
}
$domains = [];
foreach(Db::name('domain')->alias('A')->join('account B','A.aid = B.id')->field('A.*')->where('B.type', '<>', 'cloudflare')->select() as $row){
$domains[$row['id']] = $row['name'];
}
View::assign('domains', $domains);
View::assign('info', $task);
View::assign('action', $action);
return View::fetch();
}
public function queryapi()
{
if(!checkPermission(2)) return $this->alert('error', '无权限');
$optimize_ip_api = input('post.optimize_ip_api/d');
$optimize_ip_key = input('post.optimize_ip_key', null, 'trim');
if(empty($optimize_ip_key)) return json(['code'=>-1, 'msg'=>'参数不能为空']);
try{
$result = (new OptimizeService())->get_license($optimize_ip_api, $optimize_ip_key);
return json(['code'=>0, 'msg'=>'当前积分余额:'.$result]);
}catch(Exception $e){
return json(['code'=>-1, 'msg'=>$e->getMessage()]);
}
}
public function status()
{
$run_time = Db::name('optimizeip')->where('active', 1)->order('updatetime', 'desc')->value('updatetime');
$run_state = $run_time ? (time()-strtotime($run_time) > 3600 ? 0 : 1) : 0;
return $run_state == 1 ? 'ok' : 'error';
}
}
<?php
namespace app\controller;
use app\BaseController;
use Exception;
use think\facade\Db;
use think\facade\View;
use think\facade\Cache;
use app\lib\OptimizeService;
class Optimizeip extends BaseController
{
public function opipset()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
if ($this->request->isPost()) {
$params = input('post.');
foreach ($params as $key => $value) {
if (empty($key)) {
continue;
}
config_set($key, $value);
Cache::delete('configs');
}
return json(['code' => 0, 'msg' => 'succ']);
}
return View::fetch();
}
public function opiplist()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
return View::fetch();
}
public function opiplist_data()
{
if (!checkPermission(2)) {
return json(['total' => 0, 'rows' => []]);
}
$type = input('post.type/d', 1);
$kw = input('post.kw', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('optimizeip')->alias('A')->join('domain B', 'A.did = B.id');
if (!empty($kw)) {
if ($type == 1) {
$select->whereLike('rr|B.name', '%' . $kw . '%');
} elseif ($type == 2) {
$select->whereLike('remark', '%' . $kw . '%');
}
}
$total = $select->count();
$list = $select->order('A.id', 'desc')->limit($offset, $limit)->field('A.*,B.name domain')->select();
return json(['total' => $total, 'rows' => $list]);
}
public function opipform()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$action = input('param.action');
if ($this->request->isPost()) {
if ($action == 'add') {
$task = [
'did' => input('post.did/d'),
'rr' => input('post.rr', null, 'trim'),
'type' => input('post.type/d'),
'ip_type' => input('post.ip_type', null, 'trim'),
'cdn_type' => input('post.cdn_type/d'),
'recordnum' => input('post.recordnum/d'),
'ttl' => input('post.ttl/d'),
'remark' => input('post.remark', null, 'trim'),
'addtime' => date('Y-m-d H:i:s'),
'active' => 1
];
if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) {
return json(['code' => -1, 'msg' => '必填项不能为空']);
}
if ($task['recordnum'] > 5) {
return json(['code' => -1, 'msg' => '解析数量不能超过5个']);
}
if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->find()) {
return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']);
}
Db::name('optimizeip')->insert($task);
return json(['code' => 0, 'msg' => '添加成功']);
} elseif ($action == 'edit') {
$id = input('post.id/d');
$task = [
'did' => input('post.did/d'),
'rr' => input('post.rr', null, 'trim'),
'type' => input('post.type/d'),
'ip_type' => input('post.ip_type', null, 'trim'),
'cdn_type' => input('post.cdn_type/d'),
'recordnum' => input('post.recordnum/d'),
'ttl' => input('post.ttl/d'),
'remark' => input('post.remark', null, 'trim'),
];
if (empty($task['did']) || empty($task['rr']) || empty($task['ip_type']) || empty($task['recordnum']) || empty($task['ttl'])) {
return json(['code' => -1, 'msg' => '必填项不能为空']);
}
if ($task['recordnum'] > 5) {
return json(['code' => -1, 'msg' => '解析数量不能超过5个']);
}
if (Db::name('optimizeip')->where('did', $task['did'])->where('rr', $task['rr'])->where('id', '<>', $id)->find()) {
return json(['code' => -1, 'msg' => '当前域名的优选IP任务已存在']);
}
Db::name('optimizeip')->where('id', $id)->update($task);
return json(['code' => 0, 'msg' => '修改成功']);
} elseif ($action == 'setactive') {
$id = input('post.id/d');
$active = input('post.active/d');
Db::name('optimizeip')->where('id', $id)->update(['active' => $active]);
return json(['code' => 0, 'msg' => '设置成功']);
} elseif ($action == 'del') {
$id = input('post.id/d');
Db::name('optimizeip')->where('id', $id)->delete();
return json(['code' => 0, 'msg' => '删除成功']);
} elseif ($action == 'run') {
$id = input('post.id/d');
$task = Db::name('optimizeip')->where('id', $id)->find();
if (empty($task)) {
return json(['code' => -1, 'msg' => '任务不存在']);
}
try {
$result = (new OptimizeService())->execute_one($task);
Db::name('optimizeip')->where('id', $id)->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]);
return json(['code' => 0, 'msg' => '优选任务执行成功:' . $result]);
} catch (Exception $e) {
Db::name('optimizeip')->where('id', $id)->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]);
return json(['code' => -1, 'msg' => '优选任务执行失败:' . $e->getMessage(), 'stack' => $e->__toString()]);
}
} else {
return json(['code' => -1, 'msg' => '参数错误']);
}
}
$task = null;
if ($action == 'edit') {
$id = input('get.id/d');
$task = Db::name('optimizeip')->where('id', $id)->find();
if (empty($task)) {
return $this->alert('error', '任务不存在');
}
}
$domains = [];
foreach (Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->field('A.*')->where('B.type', '<>', 'cloudflare')->select() as $row) {
$domains[$row['id']] = $row['name'];
}
View::assign('domains', $domains);
View::assign('info', $task);
View::assign('action', $action);
return View::fetch();
}
public function queryapi()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$optimize_ip_api = input('post.optimize_ip_api/d');
$optimize_ip_key = input('post.optimize_ip_key', null, 'trim');
if (empty($optimize_ip_key)) {
return json(['code' => -1, 'msg' => '参数不能为空']);
}
try {
$result = (new OptimizeService())->get_license($optimize_ip_api, $optimize_ip_key);
return json(['code' => 0, 'msg' => '当前积分余额:' . $result]);
} catch (Exception $e) {
return json(['code' => -1, 'msg' => $e->getMessage()]);
}
}
public function status()
{
$run_time = Db::name('optimizeip')->where('active', 1)->order('updatetime', 'desc')->value('updatetime');
$run_state = $run_time ? (time() - strtotime($run_time) > 3600 ? 0 : 1) : 0;
return $run_state == 1 ? 'ok' : 'error';
}
}

View File

@ -1,164 +1,196 @@
<?php
namespace app\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\View;
use think\facade\Request;
class User extends BaseController
{
public function user(){
if(!checkPermission(2)) return $this->alert('error', '无权限');
$list = Db::name('domain')->select();
$domains = [];
foreach($list as $row){
$domains[] = $row['name'];
}
View::assign('domains', $domains);
return view();
}
public function user_data(){
if(!checkPermission(2)) return json(['total'=>0, 'rows'=>[]]);
$kw = input('post.kw', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('user');
if(!empty($kw)){
$select->whereLike('id|username', $kw);
}
$total = $select->count();
$rows = $select->order('id','desc')->limit($offset, $limit)->select();
return json(['total'=>$total, 'rows'=>$rows]);
}
public function user_op(){
if(!checkPermission(2)) return $this->alert('error', '无权限');
$act = input('param.act');
if($act == 'get'){
$id = input('post.id/d');
$row = Db::name('user')->where('id', $id)->find();
if(!$row) return json(['code'=>-1, 'msg'=>'用户不存在']);
$row['permission'] = Db::name('permission')->where('uid', $id)->column('domain');
return json(['code'=>0, 'data'=>$row]);
}elseif($act == 'add'){
$username = input('post.username', null, 'trim');
$password = input('post.password', null, 'trim');
$is_api = input('post.is_api/d');
$apikey = input('post.apikey', null, 'trim');
$level = input('post.level/d');
if(empty($username) || empty($password)) return json(['code'=>-1, 'msg'=>'用户名或密码不能为空']);
if($is_api ==1 && empty($apikey)) return json(['code'=>-1, 'msg'=>'API密钥不能为空']);
if(Db::name('user')->where('username', $username)->find()){
return json(['code'=>-1, 'msg'=>'用户名已存在']);
}
$uid = Db::name('user')->insertGetId([
'username' => $username,
'password' => password_hash($password, PASSWORD_DEFAULT),
'is_api' => $is_api,
'apikey' => $apikey,
'level' => $level,
'regtime' => date('Y-m-d H:i:s'),
'status' => 1,
]);
if($level == 1){
$permission = input('post.permission/a');
if(!empty($permission)){
$data = [];
foreach($permission as $domain){
$data[] = ['uid'=>$uid, 'domain'=>$domain];
}
Db::name('permission')->insertAll($data);
}
}
return json(['code'=>0, 'msg'=>'添加用户成功!']);
}elseif($act == 'edit'){
$id = input('post.id/d');
$row = Db::name('user')->where('id', $id)->find();
if(!$row) return json(['code'=>-1, 'msg'=>'用户不存在']);
$username = input('post.username', null, 'trim');
$is_api = input('post.is_api/d');
$apikey = input('post.apikey', null, 'trim');
$level = input('post.level/d');
$repwd = input('post.repwd', null, 'trim');
if(empty($username)) return json(['code'=>-1, 'msg'=>'用户名不能为空']);
if($is_api ==1 && empty($apikey)) return json(['code'=>-1, 'msg'=>'API密钥不能为空']);
if(Db::name('user')->where('username', $username)->where('id', '<>', $id)->find()){
return json(['code'=>-1, 'msg'=>'用户名已存在']);
}
if($level == 1 && ($id == 1000 || $id == request()->user['id'])) $level = 2;
Db::name('user')->where('id', $id)->update([
'username' => $username,
'is_api' => $is_api,
'apikey' => $apikey,
'level' => $level,
]);
Db::name('permission')->where(['uid'=>$id])->delete();
if($level == 1){
$permission = input('post.permission/a');
if(!empty($permission)){
$data = [];
foreach($permission as $domain){
$data[] = ['uid'=>$id, 'domain'=>$domain];
}
Db::name('permission')->insertAll($data);
}
}
if(!empty($repwd)){
Db::name('user')->where('id', $id)->update(['password'=>password_hash($repwd, PASSWORD_DEFAULT)]);
}
return json(['code'=>0, 'msg'=>'修改用户成功!']);
}elseif($act == 'set'){
$id = input('post.id/d');
$status = input('post.status/d');
if($id == 1000) return json(['code'=>-1, 'msg'=>'此用户无法修改状态']);
if($id == request()->user['id']) return json(['code'=>-1, 'msg'=>'当前登录用户无法修改状态']);
Db::name('user')->where('id', $id)->update(['status'=>$status]);
return json(['code'=>0]);
}elseif($act == 'del'){
$id = input('post.id/d');
if($id == 1000) return json(['code'=>-1, 'msg'=>'此用户无法删除']);
if($id == request()->user['id']) return json(['code'=>-1, 'msg'=>'当前登录用户无法删除']);
Db::name('user')->where('id', $id)->delete();
return json(['code'=>0]);
}
return json(['code'=>-3]);
}
public function log(){
return view();
}
public function log_data(){
$uid = input('post.uid', null, 'trim');
$kw = input('post.kw', null, 'trim');
$domain = input('post.domain', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('log');
if(request()->user['type'] == 'domain'){
$select->where('domain', request()->user['name']);
}elseif(request()->user['level'] == 1){
$select->where('uid', request()->user['id']);
}elseif(!empty($uid)){
$select->where('uid', $uid);
}
if(!empty($kw)){
$select->whereLike('action|data', '%'.$kw.'%');
}
if(!empty($domain)){
$select->where('domain', $domain);
}
$total = $select->count();
$rows = $select->order('id','desc')->limit($offset, $limit)->select();
return json(['total'=>$total, 'rows'=>$rows]);
}
}
<?php
namespace app\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\View;
use think\facade\Request;
class User extends BaseController
{
public function user()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$list = Db::name('domain')->select();
$domains = [];
foreach ($list as $row) {
$domains[] = $row['name'];
}
View::assign('domains', $domains);
return view();
}
public function user_data()
{
if (!checkPermission(2)) {
return json(['total' => 0, 'rows' => []]);
}
$kw = input('post.kw', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('user');
if (!empty($kw)) {
$select->whereLike('id|username', $kw);
}
$total = $select->count();
$rows = $select->order('id', 'desc')->limit($offset, $limit)->select();
return json(['total' => $total, 'rows' => $rows]);
}
public function user_op()
{
if (!checkPermission(2)) {
return $this->alert('error', '无权限');
}
$act = input('param.act');
if ($act == 'get') {
$id = input('post.id/d');
$row = Db::name('user')->where('id', $id)->find();
if (!$row) {
return json(['code' => -1, 'msg' => '用户不存在']);
}
$row['permission'] = Db::name('permission')->where('uid', $id)->column('domain');
return json(['code' => 0, 'data' => $row]);
} elseif ($act == 'add') {
$username = input('post.username', null, 'trim');
$password = input('post.password', null, 'trim');
$is_api = input('post.is_api/d');
$apikey = input('post.apikey', null, 'trim');
$level = input('post.level/d');
if (empty($username) || empty($password)) {
return json(['code' => -1, 'msg' => '用户名或密码不能为空']);
}
if ($is_api == 1 && empty($apikey)) {
return json(['code' => -1, 'msg' => 'API密钥不能为空']);
}
if (Db::name('user')->where('username', $username)->find()) {
return json(['code' => -1, 'msg' => '用户名已存在']);
}
$uid = Db::name('user')->insertGetId([
'username' => $username,
'password' => password_hash($password, PASSWORD_DEFAULT),
'is_api' => $is_api,
'apikey' => $apikey,
'level' => $level,
'regtime' => date('Y-m-d H:i:s'),
'status' => 1,
]);
if ($level == 1) {
$permission = input('post.permission/a');
if (!empty($permission)) {
$data = [];
foreach ($permission as $domain) {
$data[] = ['uid' => $uid, 'domain' => $domain];
}
Db::name('permission')->insertAll($data);
}
}
return json(['code' => 0, 'msg' => '添加用户成功!']);
} elseif ($act == 'edit') {
$id = input('post.id/d');
$row = Db::name('user')->where('id', $id)->find();
if (!$row) {
return json(['code' => -1, 'msg' => '用户不存在']);
}
$username = input('post.username', null, 'trim');
$is_api = input('post.is_api/d');
$apikey = input('post.apikey', null, 'trim');
$level = input('post.level/d');
$repwd = input('post.repwd', null, 'trim');
if (empty($username)) {
return json(['code' => -1, 'msg' => '用户名不能为空']);
}
if ($is_api == 1 && empty($apikey)) {
return json(['code' => -1, 'msg' => 'API密钥不能为空']);
}
if (Db::name('user')->where('username', $username)->where('id', '<>', $id)->find()) {
return json(['code' => -1, 'msg' => '用户名已存在']);
}
if ($level == 1 && ($id == 1000 || $id == $this->request->user['id'])) {
$level = 2;
}
Db::name('user')->where('id', $id)->update([
'username' => $username,
'is_api' => $is_api,
'apikey' => $apikey,
'level' => $level,
]);
Db::name('permission')->where(['uid' => $id])->delete();
if ($level == 1) {
$permission = input('post.permission/a');
if (!empty($permission)) {
$data = [];
foreach ($permission as $domain) {
$data[] = ['uid' => $id, 'domain' => $domain];
}
Db::name('permission')->insertAll($data);
}
}
if (!empty($repwd)) {
Db::name('user')->where('id', $id)->update(['password' => password_hash($repwd, PASSWORD_DEFAULT)]);
}
return json(['code' => 0, 'msg' => '修改用户成功!']);
} elseif ($act == 'set') {
$id = input('post.id/d');
$status = input('post.status/d');
if ($id == 1000) {
return json(['code' => -1, 'msg' => '此用户无法修改状态']);
}
if ($id == $this->request->user['id']) {
return json(['code' => -1, 'msg' => '当前登录用户无法修改状态']);
}
Db::name('user')->where('id', $id)->update(['status' => $status]);
return json(['code' => 0]);
} elseif ($act == 'del') {
$id = input('post.id/d');
if ($id == 1000) {
return json(['code' => -1, 'msg' => '此用户无法删除']);
}
if ($id == $this->request->user['id']) {
return json(['code' => -1, 'msg' => '当前登录用户无法删除']);
}
Db::name('user')->where('id', $id)->delete();
return json(['code' => 0]);
}
return json(['code' => -3]);
}
public function log()
{
return view();
}
public function log_data()
{
$uid = input('post.uid', null, 'trim');
$kw = input('post.kw', null, 'trim');
$domain = input('post.domain', null, 'trim');
$offset = input('post.offset/d');
$limit = input('post.limit/d');
$select = Db::name('log');
if ($this->request->user['type'] == 'domain') {
$select->where('domain', $this->request->user['name']);
} elseif ($this->request->user['level'] == 1) {
$select->where('uid', $this->request->user['id']);
} elseif (!empty($uid)) {
$select->where('uid', $uid);
}
if (!empty($kw)) {
$select->whereLike('action|data', '%' . $kw . '%');
}
if (!empty($domain)) {
$select->where('domain', $domain);
}
$total = $select->count();
$rows = $select->order('id', 'desc')->limit($offset, $limit)->select();
return json(['total' => $total, 'rows' => $rows]);
}
}

View File

@ -1,4 +1,5 @@
<?php
// 事件定义文件
return [
'bind' => [

View File

@ -1,112 +1,120 @@
<?php
namespace app\lib;
class CheckUtils
{
public static function curl($url, $timeout, $ip = null, $proxy = false)
{
$status = true;
$errmsg = null;
$urlarr = parse_url($url);
if (!empty($ip) && !filter_var($urlarr['host'], FILTER_VALIDATE_IP)) {
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
$ip = gethostbyname($ip);
}
if (!empty($ip) && filter_var($ip, FILTER_VALIDATE_IP)) {
$port = isset($urlarr['port']) ? $urlarr['port'] : ($urlarr['scheme'] == 'https' ? 443 : 80);
$resolve = $urlarr['host'] . ':' . $port . ':' . $ip;
}
}
$ch = curl_init();
if($proxy){
$proxy_server = config_get('proxy_server');
$proxy_port = intval(config_get('proxy_port'));
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
$proxy_type = config_get('proxy_type');
if($proxy_type == 'https'){
$proxy_type = CURLPROXY_HTTPS;
}elseif($proxy_type == 'sock4'){
$proxy_type = CURLPROXY_SOCKS4;
}elseif($proxy_type == 'sock5'){
$proxy_type = CURLPROXY_SOCKS5;
}else{
$proxy_type = CURLPROXY_HTTP;
}
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
if($proxy_userpwd != ':'){
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
}
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$httpheader[] = "Accept: */*";
$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
$httpheader[] = "Connection: close";
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
if(!empty($resolve)){
curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
curl_setopt($ch, CURLOPT_RESOLVE, [$resolve]);
}
curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$status = false;
$errmsg = curl_error($ch);
}
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($status && ($httpcode < 200 || $httpcode >= 400)){
$status = false;
$errmsg = 'http_code='.$httpcode;
}
$usetime = round(curl_getinfo($ch, CURLINFO_TOTAL_TIME) * 1000);
curl_close($ch);
return ['status'=>$status, 'errmsg'=>$errmsg, 'usetime'=>$usetime];
}
public static function tcp($target, $port, $timeout){
if(!filter_var($target,FILTER_VALIDATE_IP) && checkDomain($target)){
$target = gethostbyname($target);
if(!$target)return ['status'=>false, 'error'=>'DNS resolve failed', 'usetime'=>0];
}
$starttime = getMillisecond();
$fp = @fsockopen($target, $port, $errCode, $errStr, $timeout);
if ($fp) {
$status = true;
fclose($fp);
} else {
$status = false;
}
$endtime = getMillisecond();
$usetime = $endtime-$starttime;
return ['status'=>$status, 'errmsg'=>$errStr, 'usetime'=>$usetime];
}
public static function ping($target){
if(!function_exists('exec'))return ['status'=>false, 'error'=>'exec函数不可用', 'usetime'=>0];
if(!filter_var($target,FILTER_VALIDATE_IP) && checkDomain($target)){
$target = gethostbyname($target);
if(!$target)return ['status'=>false, 'error'=>'DNS resolve failed', 'usetime'=>0];
}
if(!filter_var($target,FILTER_VALIDATE_IP)){
return ['status'=>false, 'error'=>'Invalid IP address', 'usetime'=>0];
}
$timeout = 1;
exec('ping -c 1 -w '.$timeout.' '.$target.'', $output, $return_var);
$usetime = !empty($output[1]) ? round(getSubstr($output[1], 'time=', ' ms')) : 0;
$errmsg = null;
if($return_var !== 0){
$usetime = $usetime == 0 ? $timeout*1000 : $usetime;
$errmsg = 'ping timeout';
}
return ['status'=>$return_var===0, 'errmsg'=>$errmsg, 'usetime'=>$usetime];
}
}
<?php
namespace app\lib;
class CheckUtils
{
public static function curl($url, $timeout, $ip = null, $proxy = false)
{
$status = true;
$errmsg = null;
$urlarr = parse_url($url);
if (!empty($ip) && !filter_var($urlarr['host'], FILTER_VALIDATE_IP)) {
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
$ip = gethostbyname($ip);
}
if (!empty($ip) && filter_var($ip, FILTER_VALIDATE_IP)) {
$port = isset($urlarr['port']) ? $urlarr['port'] : ($urlarr['scheme'] == 'https' ? 443 : 80);
$resolve = $urlarr['host'] . ':' . $port . ':' . $ip;
}
}
$ch = curl_init();
if ($proxy) {
$proxy_server = config_get('proxy_server');
$proxy_port = intval(config_get('proxy_port'));
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
$proxy_type = config_get('proxy_type');
if ($proxy_type == 'https') {
$proxy_type = CURLPROXY_HTTPS;
} elseif ($proxy_type == 'sock4') {
$proxy_type = CURLPROXY_SOCKS4;
} elseif ($proxy_type == 'sock5') {
$proxy_type = CURLPROXY_SOCKS5;
} else {
$proxy_type = CURLPROXY_HTTP;
}
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
if ($proxy_userpwd != ':') {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
}
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$httpheader[] = "Accept: */*";
$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
$httpheader[] = "Connection: close";
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
if (!empty($resolve)) {
curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
curl_setopt($ch, CURLOPT_RESOLVE, [$resolve]);
}
curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$status = false;
$errmsg = curl_error($ch);
}
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status && ($httpcode < 200 || $httpcode >= 400)) {
$status = false;
$errmsg = 'http_code='.$httpcode;
}
$usetime = round(curl_getinfo($ch, CURLINFO_TOTAL_TIME) * 1000);
curl_close($ch);
return ['status' => $status, 'errmsg' => $errmsg, 'usetime' => $usetime];
}
public static function tcp($target, $port, $timeout)
{
if (!filter_var($target, FILTER_VALIDATE_IP) && checkDomain($target)) {
$target = gethostbyname($target);
if (!$target) {
return ['status' => false, 'error' => 'DNS resolve failed', 'usetime' => 0];
}
}
$starttime = getMillisecond();
$fp = @fsockopen($target, $port, $errCode, $errStr, $timeout);
if ($fp) {
$status = true;
fclose($fp);
} else {
$status = false;
}
$endtime = getMillisecond();
$usetime = $endtime - $starttime;
return ['status' => $status, 'errmsg' => $errStr, 'usetime' => $usetime];
}
public static function ping($target)
{
if (!function_exists('exec')) {
return ['status' => false, 'error' => 'exec函数不可用', 'usetime' => 0];
}
if (!filter_var($target, FILTER_VALIDATE_IP) && checkDomain($target)) {
$target = gethostbyname($target);
if (!$target) {
return ['status' => false, 'error' => 'DNS resolve failed', 'usetime' => 0];
}
}
if (!filter_var($target, FILTER_VALIDATE_IP)) {
return ['status' => false, 'error' => 'Invalid IP address', 'usetime' => 0];
}
$timeout = 1;
exec('ping -c 1 -w '.$timeout.' '.$target.'', $output, $return_var);
$usetime = !empty($output[1]) ? round(getSubstr($output[1], 'time=', ' ms')) : 0;
$errmsg = null;
if ($return_var !== 0) {
$usetime = $usetime == 0 ? $timeout * 1000 : $usetime;
$errmsg = 'ping timeout';
}
return ['status' => $return_var === 0, 'errmsg' => $errmsg, 'usetime' => $usetime];
}
}

View File

@ -1,145 +1,151 @@
<?php
namespace app\lib;
use think\facade\Db;
class DnsHelper
{
public static $dns_config = [
'aliyun' => [
'name' => '阿里云',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'AccessKeySecret'
],
'remark' => 1, //是否支持备注1单独设置备注2和记录一起设置
'status' => true, //是否支持启用暂停
'redirect' => true, //是否支持域名转发
'log' => true, //是否支持查看日志
'weight' => false, //是否支持权重
],
'dnspod' => [
'name' => '腾讯云',
'config' => [
'ak' => 'SecretId',
'sk' => 'SecretKey'
],
'remark' => 1,
'status' => true,
'redirect' => true,
'log' => true,
'weight' => true,
],
'huawei' => [
'name' => '华为云',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'SecretAccessKey'
],
'remark' => 2,
'status' => true,
'redirect' => false,
'log' => false,
'weight' => true,
],
'baidu' => [
'name' => '百度云',
'config' => [
'ak' => 'AccessKey',
'sk' => 'SecretKey'
],
'remark' => 2,
'status' => false,
'redirect' => false,
'log' => false,
'weight' => false,
],
'west' => [
'name' => '西部数码',
'config' => [
'ak' => '用户名',
'sk' => 'API密码'
],
'remark' => 0,
'status' => true,
'redirect' => false,
'log' => false,
'weight' => false,
],
'huoshan' => [
'name' => '火山引擎',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'SecretAccessKey'
],
'remark' => 2,
'status' => true,
'redirect' => false,
'log' => false,
'weight' => true,
],
'dnsla' => [
'name' => 'DNSLA',
'config' => [
'ak' => 'APIID',
'sk' => 'API密钥'
],
'remark' => 0,
'status' => true,
'redirect' => true,
'log' => false,
'weight' => true,
],
'cloudflare' => [
'name' => 'Cloudflare',
'config' => [
'ak' => '邮箱地址',
'sk' => 'API密钥/令牌'
],
'remark' => 2,
'status' => false,
'redirect' => false,
'log' => false,
'weight' => false,
],
];
public static function getList()
{
return self::$dns_config;
}
private static function getConfig($aid){
$account = Db::name('account')->where('id', $aid)->find();
if(!$account) return false;
return $account;
}
public static function getModel($aid, $domain = null, $domainid = null)
{
$config = self::getConfig($aid);
if(!$config) return false;
$dnstype = $config['type'];
$class = "\\app\\lib\\dns\\{$dnstype}";
if(class_exists($class)){
$config['domain'] = $domain;
$config['domainid'] = $domainid;
$model = new $class($config);
return $model;
}
return false;
}
public static function getModel2($config)
{
$dnstype = $config['type'];
$class = "\\app\\lib\\dns\\{$dnstype}";
if(class_exists($class)){
$config['domain'] = $config['name'];
$config['domainid'] = $config['thirdid'];
$model = new $class($config);
return $model;
}
return false;
}
}
<?php
namespace app\lib;
use think\facade\Db;
class DnsHelper
{
public static $dns_config = [
'aliyun' => [
'name' => '阿里云',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'AccessKeySecret'
],
'remark' => 1, //是否支持备注1单独设置备注2和记录一起设置
'status' => true, //是否支持启用暂停
'redirect' => true, //是否支持域名转发
'log' => true, //是否支持查看日志
'weight' => false, //是否支持权重
],
'dnspod' => [
'name' => '腾讯云',
'config' => [
'ak' => 'SecretId',
'sk' => 'SecretKey'
],
'remark' => 1,
'status' => true,
'redirect' => true,
'log' => true,
'weight' => true,
],
'huawei' => [
'name' => '华为云',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'SecretAccessKey'
],
'remark' => 2,
'status' => true,
'redirect' => false,
'log' => false,
'weight' => true,
],
'baidu' => [
'name' => '百度云',
'config' => [
'ak' => 'AccessKey',
'sk' => 'SecretKey'
],
'remark' => 2,
'status' => false,
'redirect' => false,
'log' => false,
'weight' => false,
],
'west' => [
'name' => '西部数码',
'config' => [
'ak' => '用户名',
'sk' => 'API密码'
],
'remark' => 0,
'status' => true,
'redirect' => false,
'log' => false,
'weight' => false,
],
'huoshan' => [
'name' => '火山引擎',
'config' => [
'ak' => 'AccessKeyId',
'sk' => 'SecretAccessKey'
],
'remark' => 2,
'status' => true,
'redirect' => false,
'log' => false,
'weight' => true,
],
'dnsla' => [
'name' => 'DNSLA',
'config' => [
'ak' => 'APIID',
'sk' => 'API密钥'
],
'remark' => 0,
'status' => true,
'redirect' => true,
'log' => false,
'weight' => true,
],
'cloudflare' => [
'name' => 'Cloudflare',
'config' => [
'ak' => '邮箱地址',
'sk' => 'API密钥/令牌'
],
'remark' => 2,
'status' => false,
'redirect' => false,
'log' => false,
'weight' => false,
],
];
public static function getList()
{
return self::$dns_config;
}
private static function getConfig($aid)
{
$account = Db::name('account')->where('id', $aid)->find();
if (!$account) {
return false;
}
return $account;
}
public static function getModel($aid, $domain = null, $domainid = null): DnsInterface|bool
{
$config = self::getConfig($aid);
if (!$config) {
return false;
}
$dnstype = $config['type'];
$class = "\\app\\lib\\dns\\$dnstype";
if (class_exists($class)) {
$config['domain'] = $domain;
$config['domainid'] = $domainid;
$model = new $class($config);
return $model;
}
return false;
}
public static function getModel2($config)
{
$dnstype = $config['type'];
$class = "\\app\\lib\\dns\\{$dnstype}";
if (class_exists($class)) {
$config['domain'] = $config['name'];
$config['domainid'] = $config['thirdid'];
$model = new $class($config);
return $model;
}
return false;
}
}

View File

@ -1,35 +1,35 @@
<?php
namespace app\lib;
interface DnsInterface
{
function getError();
function check();
function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20);
function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null);
function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null);
function getDomainRecordInfo($RecordId);
function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null);
function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null);
function updateDomainRecordRemark($RecordId, $Remark);
function deleteDomainRecord($RecordId);
function setDomainRecordStatus($RecordId, $Status);
function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null);
function getRecordLine();
function getMinTTL();
}
<?php
namespace app\lib;
interface DnsInterface
{
public function getError();
public function check();
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20);
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = '', $SubDomain = '', $Value = '', $Type = '', $Line = '', $Status = '');
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = '', $Line = '');
public function getDomainRecordInfo($RecordId);
public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null);
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null);
public function updateDomainRecordRemark($RecordId, $Remark);
public function deleteDomainRecord($RecordId);
public function setDomainRecordStatus($RecordId, $Status);
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null);
public function getRecordLine();
public function getMinTTL();
}

View File

@ -1,167 +1,186 @@
<?php
namespace app\lib;
class MsgNotice
{
private static $sitename = '聚合DNS管理系统';
public static function send($action, $task, $result)
{
if($action == 1){
$mail_title = 'DNS容灾切换-发生告警通知';
$mail_content = '尊敬的系统管理员,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录发生了异常';
if($task['type'] == 2){
$mail_content .= ',已自动切换为备用解析记录 '.$task['backup_value'].' ';
}elseif($task['type'] == 1){
$mail_content .= ',已自动暂停解析';
}else{
$mail_content .= ',请及时处理';
}
if(!empty($result['errmsg'])){
$mail_content .= '。<br/>异常信息:'.$result['errmsg'];
}
}else{
$mail_title = 'DNS容灾切换-恢复正常通知';
$mail_content = '尊敬的系统管理员,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录已恢复正常';
if($task['type'] == 2){
$mail_content .= ',已自动切换回当前解析记录';
}elseif($task['type'] == 1){
$mail_content .= ',已自动开启解析';
}
$lasttime = convert_second(time() - $task['switchtime']);
$mail_content .= '。<br/>异常持续时间:'.$lasttime;
}
if(!empty($task['remark'])) $mail_title .= '('.$task['remark'].')';
if(!empty($task['remark'])) $mail_content .= '<br/>备注:'.$task['remark'];
$mail_content .= '<br/>'.self::$sitename.'<br/>'.date('Y-m-d H:i:s');
if(config_get('notice_mail') == 1){
$mail_name = config_get('mail_recv')?config_get('mail_recv'):config_get('mail_name');
self::send_mail($mail_name, $mail_title, $mail_content);
}
if(config_get('notice_wxtpl') == 1){
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
self::send_wechat_tplmsg($mail_title, $content);
}
if(config_get('notice_tgbot') == 1){
$content = str_replace('<br/>', "\n", $mail_content);
$content = "<strong>".$mail_title."</strong>\n".$content;
self::send_telegram_bot($content);
}
}
public static function send_mail($to, $sub, $msg){
$mail_type = config_get('mail_type');
if($mail_type == 1){
$mail = new \app\lib\mail\Sendcloud(config_get('mail_apiuser'), config_get('mail_apikey'));
return $mail->send($to, $sub, $msg, config_get('mail_name'), self::$sitename);
}elseif($mail_type == 2){
$mail = new \app\lib\mail\Aliyun(config_get('mail_apiuser'), config_get('mail_apikey'));
return $mail->send($to, $sub, $msg, config_get('mail_name'), self::$sitename);
}else{
$mail_name = config_get('mail_name');
$mail_port = intval(config_get('mail_port'));
$mail_smtp = config_get('mail_smtp');
$mail_pwd = config_get('mail_pwd');
if(!$mail_name || !$mail_port || !$mail_smtp || !$mail_pwd)return false;
$mail = new \app\lib\mail\PHPMailer\PHPMailer(true);
try{
$mail->SMTPDebug = 0;
$mail->CharSet = 'UTF-8';
$mail->Timeout = 5;
$mail->isSMTP();
$mail->Host = $mail_smtp;
$mail->SMTPAuth = true;
$mail->Username = $mail_name;
$mail->Password = $mail_pwd;
if($mail_port == 587) $mail->SMTPSecure = 'tls';
else if($mail_port >= 465) $mail->SMTPSecure = 'ssl';
else $mail->SMTPAutoTLS = false;
$mail->Port = $mail_port;
$mail->setFrom($mail_name, self::$sitename);
$mail->addAddress($to);
$mail->addReplyTo($mail_name, self::$sitename);
$mail->isHTML(true);
$mail->Subject = $sub;
$mail->Body = $msg;
$mail->send();
return true;
} catch (\Exception $e) {
return $mail->ErrorInfo;
}
}
}
public static function send_wechat_tplmsg($title, $content){
$wechat_apptoken = config_get('wechat_apptoken');
$wechat_appuid = config_get('wechat_appuid');
if(!$wechat_apptoken||!$wechat_appuid)return false;
$url = 'https://wxpusher.zjiecode.com/api/send/message';
$post = ['appToken'=>$wechat_apptoken, 'content'=>$content, 'summary'=>$title, 'contentType'=>3, 'uids'=>[$wechat_appuid]];
$result = get_curl($url, json_encode($post),0,0,0,0,0,['Content-Type: application/json; charset=UTF-8']);
$arr = json_decode($result, true);
if(isset($arr['success']) && $arr['success']==true){
return true;
}else{
return $arr['msg'];
}
}
public static function send_telegram_bot($content){
$tgbot_token = config_get('tgbot_token');
$tgbot_chatid = config_get('tgbot_chatid');
if(!$tgbot_token||!$tgbot_chatid)return false;
$url = 'https://api.telegram.org/bot'.$tgbot_token.'/sendMessage';
$post = ['chat_id'=>$tgbot_chatid, 'text'=>$content, 'parse_mode'=>'HTML'];
$result = self::telegram_curl($url, http_build_query($post));
$arr = json_decode($result, true);
if(isset($arr['ok']) && $arr['ok']==true){
return true;
}else{
return $arr['description'];
}
}
private static function telegram_curl($url, $post){
$ch = curl_init();
if(config_get('tgbot_proxy') == 1){
$proxy_server = config_get('proxy_server');
$proxy_port = intval(config_get('proxy_port'));
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
$proxy_type = config_get('proxy_type');
if($proxy_type == 'https'){
$proxy_type = CURLPROXY_HTTPS;
}elseif($proxy_type == 'sock4'){
$proxy_type = CURLPROXY_SOCKS4;
}elseif($proxy_type == 'sock5'){
$proxy_type = CURLPROXY_SOCKS5;
}else{
$proxy_type = CURLPROXY_HTTP;
}
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
if($proxy_userpwd != ':'){
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
}
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$httpheader[] = "Accept: */*";
$httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
$httpheader[] = "Connection: close";
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0");
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
}
}
<?php
namespace app\lib;
class MsgNotice
{
private static $sitename = '聚合DNS管理系统';
public static function send($action, $task, $result)
{
if ($action == 1) {
$mail_title = 'DNS容灾切换-发生告警通知';
$mail_content = '尊敬的系统管理员,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录发生了异常';
if ($task['type'] == 2) {
$mail_content .= ',已自动切换为备用解析记录 '.$task['backup_value'].' ';
} elseif ($task['type'] == 1) {
$mail_content .= ',已自动暂停解析';
} else {
$mail_content .= ',请及时处理';
}
if (!empty($result['errmsg'])) {
$mail_content .= '。<br/>异常信息:'.$result['errmsg'];
}
} else {
$mail_title = 'DNS容灾切换-恢复正常通知';
$mail_content = '尊敬的系统管理员,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录已恢复正常';
if ($task['type'] == 2) {
$mail_content .= ',已自动切换回当前解析记录';
} elseif ($task['type'] == 1) {
$mail_content .= ',已自动开启解析';
}
$lasttime = convert_second(time() - $task['switchtime']);
$mail_content .= '。<br/>异常持续时间:'.$lasttime;
}
if (!empty($task['remark'])) {
$mail_title .= '('.$task['remark'].')';
}
if (!empty($task['remark'])) {
$mail_content .= '<br/>备注:'.$task['remark'];
}
$mail_content .= '<br/>'.self::$sitename.'<br/>'.date('Y-m-d H:i:s');
if (config_get('notice_mail') == 1) {
$mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
self::send_mail($mail_name, $mail_title, $mail_content);
}
if (config_get('notice_wxtpl') == 1) {
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
self::send_wechat_tplmsg($mail_title, $content);
}
if (config_get('notice_tgbot') == 1) {
$content = str_replace('<br/>', "\n", $mail_content);
$content = "<strong>".$mail_title."</strong>\n".$content;
self::send_telegram_bot($content);
}
}
public static function send_mail($to, $sub, $msg)
{
$mail_type = config_get('mail_type');
if ($mail_type == 1) {
$mail = new \app\lib\mail\Sendcloud(config_get('mail_apiuser'), config_get('mail_apikey'));
return $mail->send($to, $sub, $msg, config_get('mail_name'), self::$sitename);
} elseif ($mail_type == 2) {
$mail = new \app\lib\mail\Aliyun(config_get('mail_apiuser'), config_get('mail_apikey'));
return $mail->send($to, $sub, $msg, config_get('mail_name'), self::$sitename);
} else {
$mail_name = config_get('mail_name');
$mail_port = intval(config_get('mail_port'));
$mail_smtp = config_get('mail_smtp');
$mail_pwd = config_get('mail_pwd');
if (!$mail_name || !$mail_port || !$mail_smtp || !$mail_pwd) {
return false;
}
$mail = new \app\lib\mail\PHPMailer\PHPMailer(true);
try {
$mail->SMTPDebug = 0;
$mail->CharSet = 'UTF-8';
$mail->Timeout = 5;
$mail->isSMTP();
$mail->Host = $mail_smtp;
$mail->SMTPAuth = true;
$mail->Username = $mail_name;
$mail->Password = $mail_pwd;
if ($mail_port == 587) {
$mail->SMTPSecure = 'tls';
} elseif ($mail_port >= 465) {
$mail->SMTPSecure = 'ssl';
} else {
$mail->SMTPAutoTLS = false;
}
$mail->Port = $mail_port;
$mail->setFrom($mail_name, self::$sitename);
$mail->addAddress($to);
$mail->addReplyTo($mail_name, self::$sitename);
$mail->isHTML(true);
$mail->Subject = $sub;
$mail->Body = $msg;
$mail->send();
return true;
} catch (\Exception $e) {
return $mail->ErrorInfo;
}
}
}
public static function send_wechat_tplmsg($title, $content)
{
$wechat_apptoken = config_get('wechat_apptoken');
$wechat_appuid = config_get('wechat_appuid');
if (!$wechat_apptoken || !$wechat_appuid) {
return false;
}
$url = 'https://wxpusher.zjiecode.com/api/send/message';
$post = ['appToken' => $wechat_apptoken, 'content' => $content, 'summary' => $title, 'contentType' => 3, 'uids' => [$wechat_appuid]];
$result = (new \GuzzleHttp\Client())->post($url, ['json' => $post])->getBody()->getContents();
$arr = json_decode($result, true);
if (isset($arr['success']) && $arr['success'] == true) {
return true;
} else {
return $arr['msg'];
}
}
public static function send_telegram_bot($content)
{
$tgbot_token = config_get('tgbot_token');
$tgbot_chatid = config_get('tgbot_chatid');
if (!$tgbot_token || !$tgbot_chatid) {
return false;
}
$url = 'https://api.telegram.org/bot'.$tgbot_token.'/sendMessage';
$post = ['chat_id' => $tgbot_chatid, 'text' => $content, 'parse_mode' => 'HTML'];
$result = self::telegram_curl($url, http_build_query($post));
$arr = json_decode($result, true);
if (isset($arr['ok']) && $arr['ok'] == true) {
return true;
} else {
return $arr['description'];
}
}
private static function telegram_curl($url, $post)
{
$ch = curl_init();
if (config_get('tgbot_proxy') == 1) {
$proxy_server = config_get('proxy_server');
$proxy_port = intval(config_get('proxy_port'));
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
$proxy_type = config_get('proxy_type');
if ($proxy_type == 'https') {
$proxy_type = CURLPROXY_HTTPS;
} elseif ($proxy_type == 'sock4') {
$proxy_type = CURLPROXY_SOCKS4;
} elseif ($proxy_type == 'sock5') {
$proxy_type = CURLPROXY_SOCKS5;
} else {
$proxy_type = CURLPROXY_HTTP;
}
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
if ($proxy_userpwd != ':') {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
}
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$httpheader[] = "Accept: */*";
$httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
$httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
$httpheader[] = "Connection: close";
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0");
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace app\lib;
use think\Facade;

View File

@ -1,5 +1,6 @@
<?php
declare (strict_types = 1);
declare (strict_types=1);
namespace app\lib;

View File

@ -1,214 +1,242 @@
<?php
namespace app\lib;
use Exception;
use think\facade\Db;
class OptimizeService
{
private static $line_name = [
'aliyun' => ['DEF'=>'default', 'CT'=>'telecom', 'CU'=>'unicom', 'CM'=>'mobile', 'AB'=>'oversea'],
'dnspod' => ['DEF'=>'0', 'CT'=>'10=0', 'CU'=>'10=1', 'CM'=>'10=3', 'AB'=>'3=0'],
'huawei' => ['DEF'=>'default_view', 'CT'=>'Dianxin', 'CU'=>'Liantong', 'CM'=>'Yidong', 'AB'=>'Abroad'],
'west' => ['DEF'=>'', 'CT'=>'LTEL', 'CU'=>'LCNC', 'CM'=>'LMOB', 'AB'=>'LFOR'],
'dnsla' => ['DEF'=>'', 'CT'=>'84613316902921216', 'CU'=>'84613316923892736', 'CM'=>'84613316953252864', 'AB'=>''],
'huoshan' => ['DEF'=>'default', 'CT'=>'telecom', 'CU'=>'unicom', 'CM'=>'mobile', 'AB'=>'oversea'],
'baidu' => ['DEF'=>'default', 'CT'=>'ct', 'CU'=>'cnc', 'CM'=>'cmnet', 'AB'=>''],
];
private $ip_address = [];
private $add_num = 0;
private $change_num = 0;
private $del_num = 0;
public static function get_license($api, $key){
if($api == 2){
throw new Exception('当前接口暂不支持');
}elseif($api == 1){
$url = 'https://api.hostmonit.com/get_license?license='.$key;
}else{
$url = 'https://www.wetest.vip/api/cf2dns/get_license?license='.$key;
}
$response = get_curl($url);
$arr = json_decode($response, true);
if(isset($arr['code']) && $arr['code'] == 200 && isset($arr['count'])){
return $arr['count'];
}elseif(isset($arr['info'])){
throw new Exception('获取剩余请求次数失败,'.$arr['info']);
}else{
throw new Exception('获取剩余请求次数失败');
}
}
public function get_ip_address($cdn_type = 1, $ip_type = 'v4'){
$api = config_get('optimize_ip_api', 0);
if($api == 2){
$url = 'https://api.345673.xyz/get_data';
}elseif($api == 1){
$url = 'https://api.hostmonit.com/get_optimization_ip';
}else{
$url = 'https://www.wetest.vip/api/cf2dns/';
if($cdn_type == 1){
$url .= 'get_cloudflare_ip';
}elseif($cdn_type == 2){
$url .= 'get_cloudfront_ip';
}elseif($cdn_type == 3){
$url .= 'get_gcore_ip';
}
}
$params = [
'key' => config_get('optimize_ip_key', 'o1zrmHAF'),
'type' => $ip_type,
];
$response = get_curl($url, json_encode($params), 0, 0, 0, 0, 0, ['Content-Type: application/json; charset=UTF-8']);
$arr = json_decode($response, true);
if(isset($arr['code']) && $arr['code'] == 200){
return $arr['info'];
}elseif(isset($arr['info'])){
throw new Exception('获取优选IP数据失败'.$arr['info']);
}elseif(isset($arr['msg'])){
throw new Exception('获取优选IP数据失败'.$arr['msg']);
}else{
throw new Exception('获取优选IP数据失败原因未知');
}
}
public function get_ip_address2($cdn_type = 1, $ip_type = 'v4'){
$key = $cdn_type.'_'.$ip_type;
if(!isset($this->ip_address[$key])){
$info = $this->get_ip_address($cdn_type, $ip_type);
$res = [];
if(isset($info['DEF'])) $res['DEF'] = $info['DEF'];
if(isset($info['CT'])) $res['CT'] = $info['CT'];
if(isset($info['CU'])) $res['CU'] = $info['CU'];
if(isset($info['CM'])) $res['CM'] = $info['CM'];
$this->ip_address[$key] = $res;
}
return $this->ip_address[$key];
}
//批量执行优选任务
public function execute(){
$list = Db::name('optimizeip')->where('active', 1)->select();
echo '开始执行IP优选任务共获取到'.count($list).'个待执行任务'."\n";
foreach($list as $row){
try{
$result = $this->execute_one($row);
Db::name('optimizeip')->where('id', $row['id'])->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]);
echo '优选任务'.$row['id'].'执行成功:'.$result."\n";
}catch(Exception $e){
Db::name('optimizeip')->where('id', $row['id'])->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]);
echo '优选任务'.$row['id'].'执行失败:'.$e->getMessage()."\n";
}
}
}
//执行单个优选任务
public function execute_one($row){
$this->add_num = 0;
$this->change_num = 0;
$this->del_num = 0;
$ip_types = explode(',', $row['ip_type']);
foreach($ip_types as $ip_type){
if(empty($ip_type)) continue;
$drow = Db::name('domain')->alias('A')->join('account B','A.aid = B.id')->where('A.id', $row['did'])->field('A.*,B.type,B.ak,B.sk,B.ext')->find();
if(!$drow){
throw new Exception('域名不存在ID'.$row['did'].'');
}
if(!isset(self::$line_name[$drow['type']])){
throw new Exception('不支持的DNS服务商');
}
$info = $this->get_ip_address2($row['cdn_type'], $ip_type);
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
$domainRecords = $dns->getSubDomainRecords($row['rr'], 1, 100);
if(!$domainRecords){
throw new Exception('获取记录列表失败,'.$dns->getError());
}
if($row['type'] == 1 && isset($info['DEF']) && !empty($info['DEF'])) $row['type'] = 0;
foreach($info as $line=>$iplist){
if(empty($iplist)) continue;
$get_ips = array_column($iplist, 'ip');
if($drow['type']=='huawei') {sort($get_ips); $get_ips = [implode(',',$get_ips)]; $row['recordnum'] = 1;}
if($row['type'] == 1 && $line == 'CT') $line = 'DEF';
$line_name = self::$line_name[$drow['type']][$line];
$this->process_dns_line($dns, $row, $domainRecords['list'], $get_ips, $line_name, $ip_type);
}
}
return '成功添加'.$this->add_num.'条记录,修改'.$this->change_num.'条记录,删除'.$this->del_num.'条记录';
}
//处理单个线路的解析记录
private function process_dns_line($dns, $row, $record_list, $get_ips, $line_name, $ip_type){
$record_num = $row['recordnum'];
$records = array_filter($record_list, function($v) use($line_name){
return $v['Line'] == $line_name;
});
//删除CNAME记录
$cname_records = array_filter($records, function($v){
return $v['Type'] == 'CNAME';
});
if(!empty($cname_records)){
foreach($cname_records as $record){
$dns->deleteDomainRecord($record['RecordId']);
}
}
//处理A/AAAA记录
$ip_records = array_filter($records, function($v) use ($ip_type){
return $v['Type'] == ($ip_type == 'v6' ? 'AAAA' : 'A');
});
if(!empty($ip_records) && is_array($ip_records[array_key_first($ip_records)]['Value'])){ //处理华为云记录
foreach($ip_records as &$ip_record){
sort($ip_record['Value']);
$ip_record['Value'] = implode(',', $ip_record['Value']);
}
}
$exist_ips = array_column($ip_records, 'Value');
$add_ips = array_diff($get_ips, $exist_ips);
$del_ips = array_diff($exist_ips, $get_ips);
$correct_ips = array_diff($exist_ips, $del_ips);
$correct_count = count($correct_ips);
if(!empty($del_ips)){
foreach($ip_records as $record){
if(in_array($record['Value'], $del_ips)){
$add_ip = array_pop($add_ips);
if($add_ip){
$res = $dns->updateDomainRecord($record['RecordId'], $row['rr'], $ip_type == 'v6' ? 'AAAA' : 'A', $add_ip, $line_name, $row['ttl']);
if(!$res){
throw new Exception('修改解析失败,'.$dns->getError());
}
$this->change_num++;
$correct_count++;
}else{
$res = $dns->deleteDomainRecord($record['RecordId']);
if(!$res){
throw new Exception('删除解析失败,'.$dns->getError());
}
$this->del_num++;
}
}
}
}
if($correct_count < $record_num && !empty($add_ips)){
foreach($add_ips as $add_ip){
$res = $dns->addDomainRecord($row['rr'], $ip_type == 'v6' ? 'AAAA' : 'A', $add_ip, $line_name, $row['ttl']);
if(!$res){
throw new Exception('添加解析失败,'.$dns->getError());
}
$this->add_num++;
$correct_count++;
if($correct_count >= $record_num) break;
}
}
}
}
<?php
namespace app\lib;
use Exception;
use think\facade\Db;
class OptimizeService
{
private static $line_name = [
'aliyun' => ['DEF' => 'default', 'CT' => 'telecom', 'CU' => 'unicom', 'CM' => 'mobile', 'AB' => 'oversea'],
'dnspod' => ['DEF' => '0', 'CT' => '10=0', 'CU' => '10=1', 'CM' => '10=3', 'AB' => '3=0'],
'huawei' => ['DEF' => 'default_view', 'CT' => 'Dianxin', 'CU' => 'Liantong', 'CM' => 'Yidong', 'AB' => 'Abroad'],
'west' => ['DEF' => '', 'CT' => 'LTEL', 'CU' => 'LCNC', 'CM' => 'LMOB', 'AB' => 'LFOR'],
'dnsla' => ['DEF' => '', 'CT' => '84613316902921216', 'CU' => '84613316923892736', 'CM' => '84613316953252864', 'AB' => ''],
'huoshan' => ['DEF' => 'default', 'CT' => 'telecom', 'CU' => 'unicom', 'CM' => 'mobile', 'AB' => 'oversea'],
'baidu' => ['DEF' => 'default', 'CT' => 'ct', 'CU' => 'cnc', 'CM' => 'cmnet', 'AB' => ''],
];
private $ip_address = [];
private $add_num = 0;
private $change_num = 0;
private $del_num = 0;
public static function get_license($api, $key)
{
if ($api == 2) {
throw new Exception('当前接口暂不支持');
} elseif ($api == 1) {
$url = 'https://api.hostmonit.com/get_license?license='.$key;
} else {
$url = 'https://www.wetest.vip/api/cf2dns/get_license?license='.$key;
}
$response = (new \GuzzleHttp\Client())->get($url)->getBody()->getContents();
$arr = json_decode($response, true);
if (isset($arr['code']) && $arr['code'] == 200 && isset($arr['count'])) {
return $arr['count'];
} elseif (isset($arr['info'])) {
throw new Exception('获取剩余请求次数失败,'.$arr['info']);
} else {
throw new Exception('获取剩余请求次数失败');
}
}
public function get_ip_address($cdn_type = 1, $ip_type = 'v4')
{
$api = config_get('optimize_ip_api', 0);
if ($api == 2) {
$url = 'https://api.345673.xyz/get_data';
} elseif ($api == 1) {
$url = 'https://api.hostmonit.com/get_optimization_ip';
} else {
$url = 'https://www.wetest.vip/api/cf2dns/';
if ($cdn_type == 1) {
$url .= 'get_cloudflare_ip';
} elseif ($cdn_type == 2) {
$url .= 'get_cloudfront_ip';
} elseif ($cdn_type == 3) {
$url .= 'get_gcore_ip';
}
}
$params = [
'key' => config_get('optimize_ip_key', 'o1zrmHAF'),
'type' => $ip_type,
];
$response = (new \GuzzleHttp\Client())->post($url, ['json' => $params])->getBody()->getContents();
$arr = json_decode($response, true);
if (isset($arr['code']) && $arr['code'] == 200) {
return $arr['info'];
} elseif (isset($arr['info'])) {
throw new Exception('获取优选IP数据失败'.$arr['info']);
} elseif (isset($arr['msg'])) {
throw new Exception('获取优选IP数据失败'.$arr['msg']);
} else {
throw new Exception('获取优选IP数据失败原因未知');
}
}
public function get_ip_address2($cdn_type = 1, $ip_type = 'v4')
{
$key = $cdn_type.'_'.$ip_type;
if (!isset($this->ip_address[$key])) {
$info = $this->get_ip_address($cdn_type, $ip_type);
$res = [];
if (isset($info['DEF'])) {
$res['DEF'] = $info['DEF'];
}
if (isset($info['CT'])) {
$res['CT'] = $info['CT'];
}
if (isset($info['CU'])) {
$res['CU'] = $info['CU'];
}
if (isset($info['CM'])) {
$res['CM'] = $info['CM'];
}
$this->ip_address[$key] = $res;
}
return $this->ip_address[$key];
}
//批量执行优选任务
public function execute()
{
$list = Db::name('optimizeip')->where('active', 1)->select();
echo '开始执行IP优选任务共获取到'.count($list).'个待执行任务'."\n";
foreach ($list as $row) {
try {
$result = $this->execute_one($row);
Db::name('optimizeip')->where('id', $row['id'])->update(['status' => 1, 'errmsg' => null, 'updatetime' => date('Y-m-d H:i:s')]);
echo '优选任务'.$row['id'].'执行成功:'.$result."\n";
} catch (Exception $e) {
Db::name('optimizeip')->where('id', $row['id'])->update(['status' => 2, 'errmsg' => $e->getMessage(), 'updatetime' => date('Y-m-d H:i:s')]);
echo '优选任务'.$row['id'].'执行失败:'.$e->getMessage()."\n";
}
}
}
//执行单个优选任务
public function execute_one($row)
{
$this->add_num = 0;
$this->change_num = 0;
$this->del_num = 0;
$ip_types = explode(',', $row['ip_type']);
foreach ($ip_types as $ip_type) {
if (empty($ip_type)) {
continue;
}
$drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.id', $row['did'])->field('A.*,B.type,B.ak,B.sk,B.ext')->find();
if (!$drow) {
throw new Exception('域名不存在ID'.$row['did'].'');
}
if (!isset(self::$line_name[$drow['type']])) {
throw new Exception('不支持的DNS服务商');
}
$info = $this->get_ip_address2($row['cdn_type'], $ip_type);
$dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']);
$domainRecords = $dns->getSubDomainRecords($row['rr'], 1, 100);
if (!$domainRecords) {
throw new Exception('获取记录列表失败,'.$dns->getError());
}
if ($row['type'] == 1 && isset($info['DEF']) && !empty($info['DEF'])) {
$row['type'] = 0;
}
foreach ($info as $line => $iplist) {
if (empty($iplist)) {
continue;
}
$get_ips = array_column($iplist, 'ip');
if ($drow['type'] == 'huawei') {
sort($get_ips);
$get_ips = [implode(',', $get_ips)];
$row['recordnum'] = 1;
}
if ($row['type'] == 1 && $line == 'CT') {
$line = 'DEF';
}
$line_name = self::$line_name[$drow['type']][$line];
$this->process_dns_line($dns, $row, $domainRecords['list'], $get_ips, $line_name, $ip_type);
}
}
return '成功添加'.$this->add_num.'条记录,修改'.$this->change_num.'条记录,删除'.$this->del_num.'条记录';
}
//处理单个线路的解析记录
private function process_dns_line($dns, $row, $record_list, $get_ips, $line_name, $ip_type)
{
$record_num = $row['recordnum'];
$records = array_filter($record_list, function ($v) use ($line_name) {
return $v['Line'] == $line_name;
});
//删除CNAME记录
$cname_records = array_filter($records, function ($v) {
return $v['Type'] == 'CNAME';
});
if (!empty($cname_records)) {
foreach ($cname_records as $record) {
$dns->deleteDomainRecord($record['RecordId']);
}
}
//处理A/AAAA记录
$ip_records = array_filter($records, function ($v) use ($ip_type) {
return $v['Type'] == ($ip_type == 'v6' ? 'AAAA' : 'A');
});
if (!empty($ip_records) && is_array($ip_records[array_key_first($ip_records)]['Value'])) { //处理华为云记录
foreach ($ip_records as &$ip_record) {
sort($ip_record['Value']);
$ip_record['Value'] = implode(',', $ip_record['Value']);
}
}
$exist_ips = array_column($ip_records, 'Value');
$add_ips = array_diff($get_ips, $exist_ips);
$del_ips = array_diff($exist_ips, $get_ips);
$correct_ips = array_diff($exist_ips, $del_ips);
$correct_count = count($correct_ips);
if (!empty($del_ips)) {
foreach ($ip_records as $record) {
if (in_array($record['Value'], $del_ips)) {
$add_ip = array_pop($add_ips);
if ($add_ip) {
$res = $dns->updateDomainRecord($record['RecordId'], $row['rr'], $ip_type == 'v6' ? 'AAAA' : 'A', $add_ip, $line_name, $row['ttl']);
if (!$res) {
throw new Exception('修改解析失败,'.$dns->getError());
}
$this->change_num++;
$correct_count++;
} else {
$res = $dns->deleteDomainRecord($record['RecordId']);
if (!$res) {
throw new Exception('删除解析失败,'.$dns->getError());
}
$this->del_num++;
}
}
}
}
if ($correct_count < $record_num && !empty($add_ips)) {
foreach ($add_ips as $add_ip) {
$res = $dns->addDomainRecord($row['rr'], $ip_type == 'v6' ? 'AAAA' : 'A', $add_ip, $line_name, $row['ttl']);
if (!$res) {
throw new Exception('添加解析失败,'.$dns->getError());
}
$this->add_num++;
$correct_count++;
if ($correct_count >= $record_num) {
break;
}
}
}
}
}

View File

@ -1,125 +1,126 @@
<?php
namespace app\lib;
use app\lib\NewDb;
use app\lib\CheckUtils;
use app\lib\DnsHelper;
use app\lib\MsgNotice;
class TaskRunner
{
private $conn;
private function db()
{
if(!$this->conn){
$this->conn = NewDb::connect();
}
return $this->conn;
}
private function closeDb()
{
if($this->conn){
$this->conn->close();
}
}
public function execute($row)
{
if($row['type'] == 3){ //条件开启解析
$action = 0;
$remain = $this->db()->name('dmtask')->where(['did'=>$row['did'], 'rr'=>$row['rr'], 'type'=>1, 'status'=>0])->count();
if($remain<=$row['cycle'] && $row['status']==0){
$action = 2;
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status'=>1, 'errcount'=>0, 'switchtime'=>time()]);
}elseif($remain>$row['cycle'] && $row['status']==1){
$action = 1;
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status'=>0, 'errcount'=>0, 'switchtime'=>time()]);
}
}else{
if($row['checktype'] == 2){
$result = CheckUtils::curl($row['checkurl'], $row['timeout'], $row['main_value'], $row['proxy'] == 1);
}else if($row['checktype'] == 1){
$result = CheckUtils::tcp($row['main_value'], $row['tcpport'], $row['timeout']);
}else{
$result = CheckUtils::ping($row['main_value']);
}
$action = 0;
if($result['status'] && $row['status']==1){
if($row['cycle'] <= 1 || $row['errcount'] >= $row['cycle']){
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status'=>0, 'errcount'=>0, 'switchtime'=>time()]);
$action = 2;
}else{
$this->db()->name('dmtask')->where('id', $row['id'])->inc('errcount')->update();
}
}elseif(!$result['status'] && $row['status']==0){
if($row['cycle'] <= 1 || $row['errcount'] >= $row['cycle']){
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status'=>1, 'errcount'=>0, 'switchtime'=>time()]);
$action = 1;
}else{
$this->db()->name('dmtask')->where('id', $row['id'])->inc('errcount')->update();
}
}elseif($row['errcount'] > 0){
$this->db()->name('dmtask')->where('id', $row['id'])->update(['errcount'=>0]);
}
}
if($action > 0){
$drow = $this->db()->name('domain')->alias('A')->join('account B','A.aid = B.id')->where('A.id', $row['did'])->field('A.*,B.type,B.ak,B.sk,B.ext')->find();
if(!$drow){
echo '域名不存在ID'.$row['did'].''."\n";
$this->closeDb();
return;
}
$row['domain'] = $row['rr'] . '.' . $drow['name'];
}
if($action == 1){
if($row['type'] == 2){
$dns = DnsHelper::getModel2($drow);
$recordinfo = json_decode($row['recordinfo'], true);
$res = $dns->updateDomainRecord($row['recordid'], $row['rr'], getDnsType($row['backup_value']), $row['backup_value'], $recordinfo['Line'], $recordinfo['TTL']);
if(!$res){
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '修改解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
}elseif($row['type'] == 1 || $row['type'] == 3){
$dns = DnsHelper::getModel2($drow);
$res = $dns->setDomainRecordStatus($row['recordid'], '0');
if(!$res){
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '暂停解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
}
}elseif($action == 2){
if($row['type'] == 2){
$dns = DnsHelper::getModel2($drow);
$recordinfo = json_decode($row['recordinfo'], true);
$res = $dns->updateDomainRecord($row['recordid'], $row['rr'], getDnsType($row['main_value']), $row['main_value'], $recordinfo['Line'], $recordinfo['TTL']);
if(!$res){
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '修改解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
}elseif($row['type'] == 1 || $row['type'] == 3){
$dns = DnsHelper::getModel2($drow);
$res = $dns->setDomainRecordStatus($row['recordid'], '1');
if(!$res){
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '启用解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
}
}else{
$this->closeDb();
return;
}
$this->db()->name('dmlog')->insert([
'taskid' => $row['id'],
'action' => $action,
'errmsg' => isset($result) ? ($result['status'] ? null : $result['errmsg']) : null,
'date' => date('Y-m-d H:i:s')
]);
$this->closeDb();
if($row['type'] != 3){
MsgNotice::send($action, $row, $result);
}
}
}
<?php
namespace app\lib;
use app\lib\NewDb;
use app\lib\CheckUtils;
use app\lib\DnsHelper;
use app\lib\MsgNotice;
class TaskRunner
{
private $conn;
private function db()
{
if (!$this->conn) {
$this->conn = NewDb::connect();
}
return $this->conn;
}
private function closeDb()
{
if ($this->conn) {
$this->conn->close();
}
}
public function execute($row)
{
if ($row['type'] == 3) { //条件开启解析
$action = 0;
$remain = $this->db()->name('dmtask')->where(['did' => $row['did'], 'rr' => $row['rr'], 'type' => 1, 'status' => 0])->count();
if ($remain <= $row['cycle'] && $row['status'] == 0) {
$action = 2;
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status' => 1, 'errcount' => 0, 'switchtime' => time()]);
} elseif ($remain > $row['cycle'] && $row['status'] == 1) {
$action = 1;
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status' => 0, 'errcount' => 0, 'switchtime' => time()]);
}
} else {
if ($row['checktype'] == 2) {
$result = CheckUtils::curl($row['checkurl'], $row['timeout'], $row['main_value'], $row['proxy'] == 1);
} elseif ($row['checktype'] == 1) {
$result = CheckUtils::tcp($row['main_value'], $row['tcpport'], $row['timeout']);
} else {
$result = CheckUtils::ping($row['main_value']);
}
$action = 0;
if ($result['status'] && $row['status'] == 1) {
if ($row['cycle'] <= 1 || $row['errcount'] >= $row['cycle']) {
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status' => 0, 'errcount' => 0, 'switchtime' => time()]);
$action = 2;
} else {
$this->db()->name('dmtask')->where('id', $row['id'])->inc('errcount')->update();
}
} elseif (!$result['status'] && $row['status'] == 0) {
if ($row['cycle'] <= 1 || $row['errcount'] >= $row['cycle']) {
$this->db()->name('dmtask')->where('id', $row['id'])->update(['status' => 1, 'errcount' => 0, 'switchtime' => time()]);
$action = 1;
} else {
$this->db()->name('dmtask')->where('id', $row['id'])->inc('errcount')->update();
}
} elseif ($row['errcount'] > 0) {
$this->db()->name('dmtask')->where('id', $row['id'])->update(['errcount' => 0]);
}
}
if ($action > 0) {
$drow = $this->db()->name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.id', $row['did'])->field('A.*,B.type,B.ak,B.sk,B.ext')->find();
if (!$drow) {
echo '域名不存在ID'.$row['did'].''."\n";
$this->closeDb();
return;
}
$row['domain'] = $row['rr'] . '.' . $drow['name'];
}
if ($action == 1) {
if ($row['type'] == 2) {
$dns = DnsHelper::getModel2($drow);
$recordinfo = json_decode($row['recordinfo'], true);
$res = $dns->updateDomainRecord($row['recordid'], $row['rr'], getDnsType($row['backup_value']), $row['backup_value'], $recordinfo['Line'], $recordinfo['TTL']);
if (!$res) {
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '修改解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
} elseif ($row['type'] == 1 || $row['type'] == 3) {
$dns = DnsHelper::getModel2($drow);
$res = $dns->setDomainRecordStatus($row['recordid'], '0');
if (!$res) {
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '暂停解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
}
} elseif ($action == 2) {
if ($row['type'] == 2) {
$dns = DnsHelper::getModel2($drow);
$recordinfo = json_decode($row['recordinfo'], true);
$res = $dns->updateDomainRecord($row['recordid'], $row['rr'], getDnsType($row['main_value']), $row['main_value'], $recordinfo['Line'], $recordinfo['TTL']);
if (!$res) {
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '修改解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
} elseif ($row['type'] == 1 || $row['type'] == 3) {
$dns = DnsHelper::getModel2($drow);
$res = $dns->setDomainRecordStatus($row['recordid'], '1');
if (!$res) {
$this->db()->name('log')->insert(['uid' => 0, 'domain' => $drow['name'], 'action' => '启用解析失败', 'data' => $dns->getError(), 'addtime' => date("Y-m-d H:i:s")]);
}
}
} else {
$this->closeDb();
return;
}
$this->db()->name('dmlog')->insert([
'taskid' => $row['id'],
'action' => $action,
'errmsg' => isset($result) ? ($result['status'] ? null : $result['errmsg']) : null,
'date' => date('Y-m-d H:i:s')
]);
$this->closeDb();
if ($row['type'] != 3) {
MsgNotice::send($action, $row, $result);
}
}
}

View File

@ -1,314 +1,344 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Exception\GuzzleException;
class aliyun implements DnsInterface {
private $AccessKeyId;
private $AccessKeySecret;
private $Endpoint = 'alidns.aliyuncs.com'; //API接入域名
private $Version = '2015-01-09'; //API版本号
private $error;
private $domain;
private $domainid;
private $domainInfo;
class aliyun implements DnsInterface
{
private $AccessKeyId;
private $AccessKeySecret;
private $Endpoint = 'alidns.aliyuncs.com'; //API接入域名
private $Version = '2015-01-09'; //API版本号
private $error;
private $domain;
private $domainid;
private $domainInfo;
function __construct($config){
$this->AccessKeyId = $config['ak'];
$this->AccessKeySecret = $config['sk'];
$this->domain = $config['domain'];
}
public function __construct($config)
{
$this->AccessKeyId = $config['ak'];
$this->AccessKeySecret = $config['sk'];
$this->domain = $config['domain'];
}
public function getError(){
return $this->error;
}
public function getError()
{
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$param = ['Action' => 'DescribeDomains', 'KeyWord' => $KeyWord, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize];
$data = $this->request($param, true);
if($data){
$list = [];
foreach($data['Domains']['Domain'] as $row){
$list[] = [
'DomainId' => $row['DomainId'],
'Domain' => $row['DomainName'],
'RecordCount' => $row['RecordCount'],
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$param = ['Action' => 'DescribeDomains', 'KeyWord' => $KeyWord, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize];
$data = $this->request($param, true);
if ($data) {
$list = [];
foreach ($data['Domains']['Domain'] as $row) {
$list[] = [
'DomainId' => $row['DomainId'],
'Domain' => $row['DomainName'],
'RecordCount' => $row['RecordCount'],
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$param = ['Action' => 'DescribeDomainRecords', 'DomainName' => $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize];
if(!empty($SubDomain) || !empty($Type) || !empty($Line) || !empty($Value)){
$param += ['SearchMode' => 'ADVANCED', 'RRKeyWord' => $SubDomain, 'ValueKeyWord' => $Value, 'Type' => $Type, 'Line' => $Line];
}elseif(!empty($KeyWord)){
$param += ['KeyWord' => $KeyWord];
}
if(!isNullOrEmpty($Status)){
$Status = $Status == '1' ? 'Enable' : 'Disable';
$param += ['Status' => $Status];
}
$data = $this->request($param, true);
if($data){
$list = [];
foreach($data['DomainRecords']['Record'] as $row){
$list[] = [
'RecordId' => $row['RecordId'],
'Domain' => $row['DomainName'],
'Name' => $row['RR'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => isset($row['Priority']) ? $row['Priority'] : null,
'Status' => $row['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => isset($row['Weight']) ? $row['Weight'] : null,
'Remark' => isset($row['Remark']) ? $row['Remark'] : null,
'UpdateTime' => isset($row['UpdateTimestamp']) ? date('Y-m-d H:i:s', $row['UpdateTimestamp']/1000) : null,
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$param = ['Action' => 'DescribeDomainRecords', 'DomainName' => $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize];
if (!empty($SubDomain) || !empty($Type) || !empty($Line) || !empty($Value)) {
$param += ['SearchMode' => 'ADVANCED', 'RRKeyWord' => $SubDomain, 'ValueKeyWord' => $Value, 'Type' => $Type, 'Line' => $Line];
} elseif (!empty($KeyWord)) {
$param += ['KeyWord' => $KeyWord];
}
if (!isNullOrEmpty($Status)) {
$Status = $Status == '1' ? 'Enable' : 'Disable';
$param += ['Status' => $Status];
}
$data = $this->request($param, true);
if ($data) {
$list = [];
foreach ($data['DomainRecords']['Record'] as $row) {
$list[] = [
'RecordId' => $row['RecordId'],
'Domain' => $row['DomainName'],
'Name' => $row['RR'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => isset($row['Priority']) ? $row['Priority'] : null,
'Status' => $row['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => isset($row['Weight']) ? $row['Weight'] : null,
'Remark' => isset($row['Remark']) ? $row['Remark'] : null,
'UpdateTime' => isset($row['UpdateTimestamp']) ? date('Y-m-d H:i:s', $row['UpdateTimestamp'] / 1000) : null,
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
$param = ['Action' => 'DescribeSubDomainRecords', 'SubDomain' => $SubDomain . '.' . $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'Type' => $Type, 'Line' => $Line];
$data = $this->request($param, true);
if($data){
$list = [];
foreach($data['DomainRecords']['Record'] as $row){
$list[] = [
'RecordId' => $row['RecordId'],
'Domain' => $row['DomainName'],
'Name' => $row['RR'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => isset($row['Priority']) ? $row['Priority'] : null,
'Status' => $row['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => isset($row['Weight']) ? $row['Weight'] : null,
'Remark' => isset($row['Remark']) ? $row['Remark'] : null,
'UpdateTime' => isset($row['UpdateTimestamp']) ? date('Y-m-d H:i:s', $row['UpdateTimestamp']/1000) : null,
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
$param = ['Action' => 'DescribeSubDomainRecords', 'SubDomain' => $SubDomain . '.' . $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'Type' => $Type, 'Line' => $Line];
$data = $this->request($param, true);
if ($data) {
$list = [];
foreach ($data['DomainRecords']['Record'] as $row) {
$list[] = [
'RecordId' => $row['RecordId'],
'Domain' => $row['DomainName'],
'Name' => $row['RR'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => isset($row['Priority']) ? $row['Priority'] : null,
'Status' => $row['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => isset($row['Weight']) ? $row['Weight'] : null,
'Remark' => isset($row['Remark']) ? $row['Remark'] : null,
'UpdateTime' => isset($row['UpdateTimestamp']) ? date('Y-m-d H:i:s', $row['UpdateTimestamp'] / 1000) : null,
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
$param = ['Action' => 'DescribeDomainRecordInfo', 'RecordId' => $RecordId];
$data = $this->request($param, true);
if($data){
return [
'RecordId' => $data['RecordId'],
'Domain' => $data['DomainName'],
'Name' => $data['RR'],
'Type' => $data['Type'],
'Value' => $data['Value'],
'Line' => $data['Line'],
'TTL' => $data['TTL'],
'MX' => isset($data['Priority']) ? $data['Priority'] : null,
'Status' => $data['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => isset($data['Weight']) ? $data['Weight'] : null,
'Remark' => isset($data['Remark']) ? $data['Remark'] : null,
'UpdateTime' => isset($row['UpdateTimestamp']) ? date('Y-m-d H:i:s', $data['UpdateTimestamp']/1000) : null,
];
}
return false;
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
$param = ['Action' => 'DescribeDomainRecordInfo', 'RecordId' => $RecordId];
$data = $this->request($param, true);
if ($data) {
return [
'RecordId' => $data['RecordId'],
'Domain' => $data['DomainName'],
'Name' => $data['RR'],
'Type' => $data['Type'],
'Value' => $data['Value'],
'Line' => $data['Line'],
'TTL' => $data['TTL'],
'MX' => isset($data['Priority']) ? $data['Priority'] : null,
'Status' => $data['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => isset($data['Weight']) ? $data['Weight'] : null,
'Remark' => isset($data['Remark']) ? $data['Remark'] : null,
'UpdateTime' => isset($row['UpdateTimestamp']) ? date('Y-m-d H:i:s', $data['UpdateTimestamp'] / 1000) : null,
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = null, $Weight = null, $Remark = null){
$param = ['Action' => 'AddDomainRecord', 'DomainName' => $this->domain, 'RR' => $Name, 'Type' => $Type, 'Value' => $Value, 'Line' => $this->convertLineCode($Line), 'TTL' => intval($TTL)];
if($MX){
$param['Priority'] = intval($MX);
}
$data = $this->request($param, true);
if($data){
return $data['RecordId'];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = null, $Weight = null, $Remark = null)
{
$param = ['Action' => 'AddDomainRecord', 'DomainName' => $this->domain, 'RR' => $Name, 'Type' => $Type, 'Value' => $Value, 'Line' => $this->convertLineCode($Line), 'TTL' => intval($TTL)];
if ($MX) {
$param['Priority'] = intval($MX);
}
$data = $this->request($param, true);
if ($data) {
return $data['RecordId'];
}
return false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = null, $Weight = null, $Remark = null){
$param = ['Action' => 'UpdateDomainRecord', 'RecordId' => $RecordId, 'RR' => $Name, 'Type' => $Type, 'Value' => $Value, 'Line' => $this->convertLineCode($Line), 'TTL' => intval($TTL)];
if($MX){
$param['Priority'] = intval($MX);
}
return $this->request($param);
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = null, $Weight = null, $Remark = null)
{
$param = ['Action' => 'UpdateDomainRecord', 'RecordId' => $RecordId, 'RR' => $Name, 'Type' => $Type, 'Value' => $Value, 'Line' => $this->convertLineCode($Line), 'TTL' => intval($TTL)];
if ($MX) {
$param['Priority'] = intval($MX);
}
return $this->request($param);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
$param = ['Action' => 'UpdateDomainRecordRemark', 'RecordId' => $RecordId, 'Remark' => $Remark];
return $this->request($param);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
$param = ['Action' => 'UpdateDomainRecordRemark', 'RecordId' => $RecordId, 'Remark' => $Remark];
return $this->request($param);
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$param = ['Action' => 'DeleteDomainRecord', 'RecordId' => $RecordId];
return $this->request($param);
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$param = ['Action' => 'DeleteDomainRecord', 'RecordId' => $RecordId];
return $this->request($param);
}
//删除子域名的解析记录
public function deleteSubDomainRecords($SubDomain){
$param = ['Action' => 'DeleteSubDomainRecords', 'DomainName' => $this->domain, 'RR' => $SubDomain];
return $this->request($param);
}
//删除子域名的解析记录
public function deleteSubDomainRecords($SubDomain)
{
$param = ['Action' => 'DeleteSubDomainRecords', 'DomainName' => $this->domain, 'RR' => $SubDomain];
return $this->request($param);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$Status = $Status == '1' ? 'Enable' : 'Disable';
$param = ['Action' => 'SetDomainRecordStatus', 'RecordId' => $RecordId, 'Status' => $Status];
return $this->request($param);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$Status = $Status == '1' ? 'Enable' : 'Disable';
$param = ['Action' => 'SetDomainRecordStatus', 'RecordId' => $RecordId, 'Status' => $Status];
return $this->request($param);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
$param = ['Action' => 'DescribeRecordLogs', 'DomainName' => $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'KeyWord' => $KeyWord, 'StartDate' => $StartDate, 'endDate' => $endDate, 'Lang' => 'zh'];
$data = $this->request($param, true);
if($data){
$list = [];
foreach($data['RecordLogs']['RecordLog'] as $row){
$list[] = ['time'=>date('Y-m-d H:i:s', intval($row['ActionTimestamp']/1000)), 'data'=>$row['Message']];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
$param = ['Action' => 'DescribeRecordLogs', 'DomainName' => $this->domain, 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'KeyWord' => $KeyWord, 'StartDate' => $StartDate, 'endDate' => $endDate, 'Lang' => 'zh'];
$data = $this->request($param, true);
if ($data) {
$list = [];
foreach ($data['RecordLogs']['RecordLog'] as $row) {
$list[] = ['time' => date('Y-m-d H:i:s', intval($row['ActionTimestamp'] / 1000)), 'data' => $row['Message']];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析线路列表
public function getRecordLine(){
$data = $this->getDomainInfo();
if($data){
$list = [];
foreach($data['RecordLines']['RecordLine'] as $row){
$list[$row['LineCode']] = ['name'=>$row['LineDisplayName'], 'parent'=>isset($row['FatherCode']) ? $row['FatherCode'] : null];
}
return $list;
}
return false;
}
//获取解析线路列表
public function getRecordLine()
{
$data = $this->getDomainInfo();
if ($data) {
$list = [];
foreach ($data['RecordLines']['RecordLine'] as $row) {
$list[$row['LineCode']] = ['name' => $row['LineDisplayName'], 'parent' => isset($row['FatherCode']) ? $row['FatherCode'] : null];
}
return $list;
}
return false;
}
//获取域名信息
public function getDomainInfo(){
if(!empty($this->domainInfo)) return $this->domainInfo;
$param = ['Action' => 'DescribeDomainInfo', 'DomainName' => $this->domain, 'NeedDetailAttributes' => 'true'];
$data = $this->request($param, true);
if($data){
$this->domainInfo = $data;
return $data;
}
return false;
}
//获取域名信息
public function getDomainInfo()
{
if (!empty($this->domainInfo)) {
return $this->domainInfo;
}
$param = ['Action' => 'DescribeDomainInfo', 'DomainName' => $this->domain, 'NeedDetailAttributes' => 'true'];
$data = $this->request($param, true);
if ($data) {
$this->domainInfo = $data;
return $data;
}
return false;
}
//获取域名最低TTL
public function getMinTTL(){
$data = $this->getDomainInfo();
if($data){
return $data['MinTtl'];
}
return false;
}
//获取域名最低TTL
public function getMinTTL()
{
$data = $this->getDomainInfo();
if ($data) {
return $data['MinTtl'];
}
return false;
}
private function convertLineCode($line){
$convert_dict = ['0'=>'default', '10=1'=>'unicom', '10=0'=>'telecom', '10=3'=>'mobile', '10=2'=>'edu', '3=0'=>'oversea', '10=22'=>'btvn', '80=0'=>'search', '7=0'=>'internal'];
if(array_key_exists($line, $convert_dict)){
return $convert_dict[$line];
}
return $line;
}
private function convertLineCode($line)
{
$convert_dict = ['0' => 'default', '10=1' => 'unicom', '10=0' => 'telecom', '10=3' => 'mobile', '10=2' => 'edu', '3=0' => 'oversea', '10=22' => 'btvn', '80=0' => 'search', '7=0' => 'internal'];
if (array_key_exists($line, $convert_dict)) {
return $convert_dict[$line];
}
return $line;
}
private function aliyunSignature($parameters, $accessKeySecret, $method)
{
ksort($parameters);
$canonicalizedQueryString = '';
foreach ($parameters as $key => $value) {
if($value === null) continue;
$canonicalizedQueryString .= '&' . $this->percentEncode($key). '=' . $this->percentEncode($value);
}
$stringToSign = $method . '&%2F&' . $this->percentEncode(substr($canonicalizedQueryString, 1));
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret."&", true));
private function aliyunSignature($parameters, $accessKeySecret, $method)
{
ksort($parameters);
$canonicalizedQueryString = '';
foreach ($parameters as $key => $value) {
if ($value === null) {
continue;
}
$canonicalizedQueryString .= '&' . $this->percentEncode($key). '=' . $this->percentEncode($value);
}
$stringToSign = $method . '&%2F&' . $this->percentEncode(substr($canonicalizedQueryString, 1));
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret."&", true));
return $signature;
}
private function percentEncode($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function request($param, $returnData=false){
if(empty($this->AccessKeyId)||empty($this->AccessKeySecret))return false;
$result = $this->request_do($param, $returnData);
if(!$returnData && $result!==true){
usleep(50000);
$result = $this->request_do($param, $returnData);
}
return $result;
}
private function request_do($param, $returnData=false){
if(empty($this->AccessKeyId)||empty($this->AccessKeySecret))return false;
$url='https://'.$this->Endpoint.'/';
$data=array(
'Format' => 'JSON',
'Version' => $this->Version,
'AccessKeyId' => $this->AccessKeyId,
'SignatureMethod' => 'HMAC-SHA1',
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'SignatureVersion' => '1.0',
'SignatureNonce' => random(8));
$data=array_merge($data, $param);
$data['Signature'] = $this->aliyunSignature($data, $this->AccessKeySecret, 'POST');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
$errno = curl_errno($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
return $signature;
}
private function percentEncode($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function request($param, $returnData = false)
{
if (empty($this->AccessKeyId) || empty($this->AccessKeySecret)) {
return false;
}
$result = $this->request_do($param, $returnData);
if (!$returnData && $result !== true) {
usleep(50000);
$result = $this->request_do($param, $returnData);
}
return $result;
}
private function request_do($param, $returnData = false)
{
if (empty($this->AccessKeyId) || empty($this->AccessKeySecret)) {
return false;
}
$url = 'https://'.$this->Endpoint.'/';
$client = new Client([
'base_uri' => $url
]);
$data = [
'Format' => 'JSON',
'Version' => $this->Version,
'AccessKeyId' => $this->AccessKeyId,
'SignatureMethod' => 'HMAC-SHA1',
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'SignatureVersion' => '1.0',
'SignatureNonce' => random(8)
];
$data = array_merge($data, $param);
$data['Signature'] = $this->aliyunSignature($data, $this->AccessKeySecret, 'POST');
try {
$response = $client->post($url, [
'form_params' => $data,
]);
} catch (BadResponseException $e) {
$response = $e->getResponse();
$result = $response->getBody()->getContents();
$data = json_decode($result, true);
$this->setError($data['Message']);
return false;
} catch (\Exception $e) {
$errno = $e->getMessage();
$this->setError('Request error: ' . $errno);
return false;
}
$result = $response->getBody()->getContents();
$data = json_decode($result, true);
return $returnData ? $data : true;
}
$arr = json_decode($response,true);
if($httpCode==200){
return $returnData ? $arr : true;
}elseif($arr){
$this->setError($arr['Message']);
return false;
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,326 +1,366 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class baidu implements DnsInterface {
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "dns.baidubce.com";
private $error;
private $domain;
private $domainid;
function __construct($config){
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$query = ['name' => $KeyWord];
$data = $this->send_reuqest('GET', '/v1/dns/zone', $query);
if($data){
$list = [];
foreach($data['zones'] as $row){
$list[] = [
'DomainId' => $row['id'],
'Domain' => rtrim($row['name'], '.'),
'RecordCount' => 0,
];
}
return ['total' => count($list), 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$query = ['rr' => $KeyWord];
if(!isNullOrEmpty($SubDomain)){
$query['rr'] = $SubDomain;
}
$data = $this->send_reuqest('GET', '/v1/dns/zone/'.$this->domain.'/record', $query);
if($data){
$list = [];
foreach($data['records'] as $row){
$list[] = [
'RecordId' => $row['id'],
'Domain' => $this->domain,
'Name' => $row['rr'],
'Type' => $row['type'],
'Value' => $row['value'],
'Line' => $row['line'],
'TTL' => $row['ttl'],
'MX' => $row['priority'],
'Status' => $row['status'] == 'running' ? '1' : '0',
'Weight' => null,
'Remark' => $row['description'],
'UpdateTime' => null,
];
}
return ['total' => count($list), 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
$query = ['id' => $RecordId];
$data = $this->send_reuqest('GET', '/v1/dns/zone/'.$this->domain.'/record', $query);
if($data && !empty($data['records'])){
$data = $data['records'][0];
return [
'RecordId' => $data['id'],
'Domain' => rtrim($data['zone_name'], '.'),
'Name' => str_replace('.'.$data['zone_name'], '', $data['name']),
'Type' => $data['type'],
'Value' => $data['value'],
'Line' => $data['line'],
'TTL' => $data['ttl'],
'MX' => $data['priority'],
'Status' => $data['status'] == 'running' ? '1' : '0',
'Weight' => null,
'Remark' => $data['description'],
'UpdateTime' => null,
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$params = ['rr' => $Name, 'type' => $this->convertType($Type), 'value' => $Value, 'line'=>$Line, 'ttl' => intval($TTL), 'description' => $Remark];
if($Type == 'MX')$params['priority'] = intval($MX);
$query = ['clientToken' => getSid()];
return $this->send_reuqest('POST', '/v1/dns/zone/'.$this->domain.'/record', $query, $params);
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$params = ['rr' => $Name, 'type' => $this->convertType($Type), 'value' => $Value, 'line'=>$Line, 'ttl' => intval($TTL), 'description' => $Remark];
if($Type == 'MX')$params['priority'] = intval($MX);
$query = ['clientToken' => getSid()];
return $this->send_reuqest('PUT', '/v1/dns/zone/'.$this->domain.'/record/'.$RecordId, $query, $params);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$query = ['clientToken' => getSid()];
return $this->send_reuqest('DELETE', '/v1/dns/zone/'.$this->domain.'/record/'.$RecordId, $query);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$Status = $Status == '1' ? 'enable' : 'disable';
$query = [$Status => '', 'clientToken' => getSid()];
return $this->send_reuqest('PUT', '/v1/dns/zone/'.$this->domain.'/record/'.$RecordId, $query);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
return false;
}
//获取解析线路列表
public function getRecordLine(){
return [
'default'=>['name'=>'默认', 'parent'=>null],
'ct'=>['name'=>'电信', 'parent'=>null],
'cnc'=>['name'=>'联通', 'parent'=>null],
'cmnet'=>['name'=>'移动', 'parent'=>null],
'edu'=>['name'=>'教育网', 'parent'=>null],
'search'=>['name'=>'搜索引擎(百度)', 'parent'=>null],
];
}
//获取域名概览信息
public function getDomainInfo(){
$res = $this->getDomainList($this->domain);
if($res && !empty($res['list'])){
return $res['list'][0];
}
return false;
}
//获取域名最低TTL
public function getMinTTL(){
return false;
}
private function convertType($type){
return $type;
}
private function send_reuqest($method, $path, $query = null, $params = null){
if(!empty($query)){
$query = array_filter($query, function($a){ return $a!==null;});
}
if(!empty($params)){
$params = array_filter($params, function($a){ return $a!==null;});
}
$time = time();
$date = gmdate("Y-m-d\TH:i:s\Z", $time);
$body = !empty($params) ? json_encode($params) : '';
$headers = [
'Host' => $this->endpoint,
'x-bce-date' => $date,
];
if($body){
$headers['Content-Type'] = 'application/json';
}
$authorization = $this->generateSign($method, $path, $query, $headers, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path;
if(!empty($query)){
$url .= '?'.http_build_query($query);
}
$header = [];
foreach($headers as $key => $value){
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $time){
$algorithm = "bce-auth-v1";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $this->getCanonicalUri($path);
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders;
// step 2: calculate signing key
$date = gmdate("Y-m-d\TH:i:s\Z", $time);
$expirationInSeconds = 1800;
$authString = $algorithm . '/' . $this->AccessKeyId . '/' . $date . '/' . $expirationInSeconds;
$signingKey = hash_hmac('sha256', $authString, $this->SecretAccessKey);
// step 3: sign string
$signature = hash_hmac("sha256", $canonicalRequest, $signingKey);
// step 4: build authorization
$authorization = $authString . '/' . $signedHeaders . "/" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalUri($path)
{
if(empty($path)) return '/';
$uri = str_replace('%2F', '/', $this->escape($path));
if(substr($uri, 0, 1) !== '/') $uri = '/'.$uri;
return $uri;
}
private function getCanonicalQueryString($parameters)
{
if(empty($parameters)) return '';
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
if($key == 'authorization') continue;
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders){
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $this->escape($key) . ':' . $this->escape($value) . "\n";
$signedHeaders .= $key . ';';
}
$canonicalHeaders = substr($canonicalHeaders, 0, -1);
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if(!empty($body)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
if(empty($response) && $httpCode == 200){
return true;
}
$arr=json_decode($response,true);
if($arr){
if(isset($arr['code']) && isset($arr['message'])){
$this->setError($arr['message']);
return false;
}else{
return $arr;
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class baidu implements DnsInterface
{
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "dns.baidubce.com";
private $error;
private $domain;
private $domainid;
public function __construct($config)
{
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError()
{
return $this->error;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$query = ['name' => $KeyWord];
$data = $this->send_reuqest('GET', '/v1/dns/zone', $query);
if ($data) {
$list = [];
foreach ($data['zones'] as $row) {
$list[] = [
'DomainId' => $row['id'],
'Domain' => rtrim($row['name'], '.'),
'RecordCount' => 0,
];
}
return ['total' => count($list), 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$query = ['rr' => $KeyWord];
if (!isNullOrEmpty($SubDomain)) {
$query['rr'] = $SubDomain;
}
$data = $this->send_reuqest('GET', '/v1/dns/zone/'.$this->domain.'/record', $query);
if ($data) {
$list = [];
foreach ($data['records'] as $row) {
$list[] = [
'RecordId' => $row['id'],
'Domain' => $this->domain,
'Name' => $row['rr'],
'Type' => $row['type'],
'Value' => $row['value'],
'Line' => $row['line'],
'TTL' => $row['ttl'],
'MX' => $row['priority'],
'Status' => $row['status'] == 'running' ? '1' : '0',
'Weight' => null,
'Remark' => $row['description'],
'UpdateTime' => null,
];
}
return ['total' => count($list), 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
if ($SubDomain == '') {
$SubDomain = '@';
}
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
$query = ['id' => $RecordId];
$data = $this->send_reuqest('GET', '/v1/dns/zone/'.$this->domain.'/record', $query);
if ($data && !empty($data['records'])) {
$data = $data['records'][0];
return [
'RecordId' => $data['id'],
'Domain' => rtrim($data['zone_name'], '.'),
'Name' => str_replace('.'.$data['zone_name'], '', $data['name']),
'Type' => $data['type'],
'Value' => $data['value'],
'Line' => $data['line'],
'TTL' => $data['ttl'],
'MX' => $data['priority'],
'Status' => $data['status'] == 'running' ? '1' : '0',
'Weight' => null,
'Remark' => $data['description'],
'UpdateTime' => null,
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$params = ['rr' => $Name, 'type' => $this->convertType($Type), 'value' => $Value, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark];
if ($Type == 'MX') {
$params['priority'] = intval($MX);
}
$query = ['clientToken' => getSid()];
return $this->send_reuqest('POST', '/v1/dns/zone/'.$this->domain.'/record', $query, $params);
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$params = ['rr' => $Name, 'type' => $this->convertType($Type), 'value' => $Value, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark];
if ($Type == 'MX') {
$params['priority'] = intval($MX);
}
$query = ['clientToken' => getSid()];
return $this->send_reuqest('PUT', '/v1/dns/zone/'.$this->domain.'/record/'.$RecordId, $query, $params);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$query = ['clientToken' => getSid()];
return $this->send_reuqest('DELETE', '/v1/dns/zone/'.$this->domain.'/record/'.$RecordId, $query);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$Status = $Status == '1' ? 'enable' : 'disable';
$query = [$Status => '', 'clientToken' => getSid()];
return $this->send_reuqest('PUT', '/v1/dns/zone/'.$this->domain.'/record/'.$RecordId, $query);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
return false;
}
//获取解析线路列表
public function getRecordLine()
{
return [
'default' => ['name' => '默认', 'parent' => null],
'ct' => ['name' => '电信', 'parent' => null],
'cnc' => ['name' => '联通', 'parent' => null],
'cmnet' => ['name' => '移动', 'parent' => null],
'edu' => ['name' => '教育网', 'parent' => null],
'search' => ['name' => '搜索引擎(百度)', 'parent' => null],
];
}
//获取域名概览信息
public function getDomainInfo()
{
$res = $this->getDomainList($this->domain);
if ($res && !empty($res['list'])) {
return $res['list'][0];
}
return false;
}
//获取域名最低TTL
public function getMinTTL()
{
return false;
}
private function convertType($type)
{
return $type;
}
private function send_reuqest($method, $path, $query = null, $params = null)
{
if (!empty($query)) {
$query = array_filter($query, function ($a) { return $a !== null;});
}
if (!empty($params)) {
$params = array_filter($params, function ($a) { return $a !== null;});
}
$time = time();
$date = gmdate("Y-m-d\TH:i:s\Z", $time);
$body = !empty($params) ? json_encode($params) : '';
$headers = [
'Host' => $this->endpoint,
'x-bce-date' => $date,
];
if ($body) {
$headers['Content-Type'] = 'application/json';
}
$authorization = $this->generateSign($method, $path, $query, $headers, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path;
if (!empty($query)) {
$url .= '?'.http_build_query($query);
}
$header = [];
foreach ($headers as $key => $value) {
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $time)
{
$algorithm = "bce-auth-v1";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $this->getCanonicalUri($path);
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders;
// step 2: calculate signing key
$date = gmdate("Y-m-d\TH:i:s\Z", $time);
$expirationInSeconds = 1800;
$authString = $algorithm . '/' . $this->AccessKeyId . '/' . $date . '/' . $expirationInSeconds;
$signingKey = hash_hmac('sha256', $authString, $this->SecretAccessKey);
// step 3: sign string
$signature = hash_hmac("sha256", $canonicalRequest, $signingKey);
// step 4: build authorization
$authorization = $authString . '/' . $signedHeaders . "/" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalUri($path)
{
if (empty($path)) {
return '/';
}
$uri = str_replace('%2F', '/', $this->escape($path));
if (substr($uri, 0, 1) !== '/') {
$uri = '/'.$uri;
}
return $uri;
}
private function getCanonicalQueryString($parameters)
{
if (empty($parameters)) {
return '';
}
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
if ($key == 'authorization') {
continue;
}
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders)
{
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $this->escape($key) . ':' . $this->escape($value) . "\n";
$signedHeaders .= $key . ';';
}
$canonicalHeaders = substr($canonicalHeaders, 0, -1);
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if (!empty($body)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) {
return false;
}
if (empty($response) && $httpCode == 200) {
return true;
}
$arr = json_decode($response, true);
if ($arr) {
if (isset($arr['code']) && isset($arr['message'])) {
$this->setError($arr['message']);
return false;
} else {
return $arr;
}
} else {
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,256 +1,305 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class dnsla implements DnsInterface {
private $apiid;
private $apisecret;
private $baseUrl = 'https://api.dns.la';
private $typeList = [1 => 'A', 2 => 'NS', 5 => 'CNAME', 15 => 'MX', 16 => 'TXT', 28 => 'AAAA', 33 => 'SRV', 257 => 'CAA', 256 => 'URL转发'];
private $error;
private $domain;
private $domainid;
function __construct($config){
$this->apiid = $config['ak'];
$this->apisecret = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$param = ['pageIndex' => $PageNumber, 'pageSize' => $PageSize];
$data = $this->execute('GET', '/api/domainList', $param);
if($data){
$list = [];
foreach($data['results'] as $row){
$list[] = [
'DomainId' => $row['id'],
'Domain' => rtrim($row['displayDomain'], '.'),
'RecordCount' => 0,
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$param = ['domainId' => $this->domainid, 'pageIndex' => $PageNumber, 'pageSize' => $PageSize];
if(!isNullOrEmpty(($KeyWord))){
$param['host'] = $KeyWord;
}
if(!isNullOrEmpty(($Type))){
$param['type'] = $this->convertType($Type);
}
if(!isNullOrEmpty(($Line))){
$param['lineId'] = $Line;
}
if(!isNullOrEmpty(($SubDomain))){
$param['host'] = $SubDomain;
}
if(!isNullOrEmpty(($Value))){
$param['data'] = $Value;
}
$data = $this->execute('GET', '/api/recordList', $param);
if($data){
$list = [];
foreach($data['results'] as $row){
$list[] = [
'RecordId' => $row['id'],
'Domain' => $this->domain,
'Name' => $row['host'],
'Type' => $this->convertTypeId($row['type'], isset($row['domaint']) ? $row['domaint'] : false),
'Value' => $row['data'],
'Line' => $row['lineId'],
'TTL' => $row['ttl'],
'MX' => isset($row['preference']) ? $row['preference'] : null,
'Status' => $row['disable'] ? '0' : '1',
'Weight' => isset($row['weight']) ? $row['weight'] : null,
'Remark' => null,
'UpdateTime' => date('Y-m-d H:i:s', $row['updatedAt']),
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$param = ['domainId' => $this->domainid, 'type' => $this->convertType($Type), 'host' => $Name, 'data' => $Value, 'ttl' => intval($TTL), 'lineId' => $Line];
if($Type == 'MX')$param['preference'] = intval($MX);
if($Type == 'REDIRECT_URL'){$param['type'] = 256;$param['dominant'] = true;}
elseif($Type == 'FORWARD_URL'){$param['type'] = 256;$param['dominant'] = false;}
if($Weight > 0) $param['weight'] = $Weight;
$data = $this->execute('POST', '/api/record', $param);
return is_array($data) ? $data['id'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$param = ['id' => $RecordId, 'type' => $this->convertType($Type), 'host' => $Name, 'data' => $Value, 'ttl' => intval($TTL), 'lineId' => $Line];
if($Type == 'MX')$param['preference'] = intval($MX);
if($Type == 'REDIRECT_URL'){$param['type'] = 256;$param['dominant'] = true;}
elseif($Type == 'FORWARD_URL'){$param['type'] = 256;$param['dominant'] = false;}
if($Weight > 0) $param['weight'] = $Weight;
$data = $this->execute('PUT', '/api/record', $param);
return $data!==false;
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$param = ['id' => $RecordId];
$data = $this->execute('DELETE', '/api/record', $param);
return $data!==false;
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$param = ['id' => $RecordId, 'disable' => $Status == '0' ? true : false];
$data = $this->execute('PUT', '/api/recordDisable', $param);
return $data!==false;
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
return false;
}
//获取解析线路列表
public function getRecordLine(){
$param = ['domain' => $this->domain];
$data = $this->execute('GET', '/api/availableLine', $param);
if($data){
array_multisort(array_column($data, 'order'), SORT_ASC, $data);
$list = [];
foreach($data as $row){
if($row['id'] == '0') $row['id'] = '';
$list[$row['id']] = ['name'=>$row['value'], 'parent'=>!empty($row['pid']) ? $row['pid'] : null];
}
return $list;
}
return false;
}
//获取域名信息
public function getDomainInfo(){
$param = ['id' => $this->domainid];
$data = $this->execute('GET', '/api/domain', $param);
return $data;
}
//获取域名最低TTL
public function getMinTTL(){
$param = ['id' => $this->domainid];
$data = $this->execute('GET', '/api/dnsMeasures', $param);
if($data && isset($data['minTTL'])){
return $data['minTTL'];
}
return false;
}
private function convertType($type){
$typeList = array_flip($this->typeList);
return $typeList[$type];
}
private function convertTypeId($typeId, $domaint){
if($typeId == 256) return $domaint ? 'REDIRECT_URL' : 'FORWARD_URL';
return $this->typeList[$typeId];
}
private function execute($method, $path, $params = null){
$token = base64_encode($this->apiid.':'.$this->apisecret);
$header = ['Authorization: Basic '.$token, 'Content-Type: application/json; charset=utf-8'];
if($method == 'POST' || $method == 'PUT'){
$response = $this->curl($method, $path, $header, json_encode($params));
}else{
if($params){
$path .= '?'.http_build_query($params);
}
$response = $this->curl($method, $path, $header);
}
if(!$response){
return false;
}
$arr=json_decode($response,true);
if($arr){
if($arr['code'] == 200){
return $arr['data'];
}else{
$this->setError($arr['msg']);
return false;
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function curl($method, $path, $header, $body = null, $isPut = false){
$url = $this->baseUrl . $path;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($body) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($errno) return false;
if($httpCode==200){
return $response;
}elseif($httpCode==401){
$this->setError('认证失败');
return false;
}else{
$this->setError('http code: '.$httpCode);
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class dnsla implements DnsInterface
{
private $apiid;
private $apisecret;
private $baseUrl = 'https://api.dns.la';
private $typeList = [1 => 'A', 2 => 'NS', 5 => 'CNAME', 15 => 'MX', 16 => 'TXT', 28 => 'AAAA', 33 => 'SRV', 257 => 'CAA', 256 => 'URL转发'];
private $error;
private $domain;
private $domainid;
public function __construct($config)
{
$this->apiid = $config['ak'];
$this->apisecret = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError()
{
return $this->error;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$param = ['pageIndex' => $PageNumber, 'pageSize' => $PageSize];
$data = $this->execute('GET', '/api/domainList', $param);
if ($data) {
$list = [];
foreach ($data['results'] as $row) {
$list[] = [
'DomainId' => $row['id'],
'Domain' => rtrim($row['displayDomain'], '.'),
'RecordCount' => 0,
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$param = ['domainId' => $this->domainid, 'pageIndex' => $PageNumber, 'pageSize' => $PageSize];
if (!isNullOrEmpty(($KeyWord))) {
$param['host'] = $KeyWord;
}
if (!isNullOrEmpty(($Type))) {
$param['type'] = $this->convertType($Type);
}
if (!isNullOrEmpty(($Line))) {
$param['lineId'] = $Line;
}
if (!isNullOrEmpty(($SubDomain))) {
$param['host'] = $SubDomain;
}
if (!isNullOrEmpty(($Value))) {
$param['data'] = $Value;
}
$data = $this->execute('GET', '/api/recordList', $param);
if ($data) {
$list = [];
foreach ($data['results'] as $row) {
$list[] = [
'RecordId' => $row['id'],
'Domain' => $this->domain,
'Name' => $row['host'],
'Type' => $this->convertTypeId($row['type'], isset($row['domaint']) ? $row['domaint'] : false),
'Value' => $row['data'],
'Line' => $row['lineId'],
'TTL' => $row['ttl'],
'MX' => isset($row['preference']) ? $row['preference'] : null,
'Status' => $row['disable'] ? '0' : '1',
'Weight' => isset($row['weight']) ? $row['weight'] : null,
'Remark' => null,
'UpdateTime' => date('Y-m-d H:i:s', $row['updatedAt']),
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
if ($SubDomain == '') {
$SubDomain = '@';
}
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$param = ['domainId' => $this->domainid, 'type' => $this->convertType($Type), 'host' => $Name, 'data' => $Value, 'ttl' => intval($TTL), 'lineId' => $Line];
if ($Type == 'MX') {
$param['preference'] = intval($MX);
}
if ($Type == 'REDIRECT_URL') {
$param['type'] = 256;
$param['dominant'] = true;
} elseif ($Type == 'FORWARD_URL') {
$param['type'] = 256;
$param['dominant'] = false;
}
if ($Weight > 0) {
$param['weight'] = $Weight;
}
$data = $this->execute('POST', '/api/record', $param);
return is_array($data) ? $data['id'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$param = ['id' => $RecordId, 'type' => $this->convertType($Type), 'host' => $Name, 'data' => $Value, 'ttl' => intval($TTL), 'lineId' => $Line];
if ($Type == 'MX') {
$param['preference'] = intval($MX);
}
if ($Type == 'REDIRECT_URL') {
$param['type'] = 256;
$param['dominant'] = true;
} elseif ($Type == 'FORWARD_URL') {
$param['type'] = 256;
$param['dominant'] = false;
}
if ($Weight > 0) {
$param['weight'] = $Weight;
}
$data = $this->execute('PUT', '/api/record', $param);
return $data !== false;
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$param = ['id' => $RecordId];
$data = $this->execute('DELETE', '/api/record', $param);
return $data !== false;
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$param = ['id' => $RecordId, 'disable' => $Status == '0' ? true : false];
$data = $this->execute('PUT', '/api/recordDisable', $param);
return $data !== false;
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
return false;
}
//获取解析线路列表
public function getRecordLine()
{
$param = ['domain' => $this->domain];
$data = $this->execute('GET', '/api/availableLine', $param);
if ($data) {
array_multisort(array_column($data, 'order'), SORT_ASC, $data);
$list = [];
foreach ($data as $row) {
if ($row['id'] == '0') {
$row['id'] = '';
}
$list[$row['id']] = ['name' => $row['value'], 'parent' => !empty($row['pid']) ? $row['pid'] : null];
}
return $list;
}
return false;
}
//获取域名信息
public function getDomainInfo()
{
$param = ['id' => $this->domainid];
$data = $this->execute('GET', '/api/domain', $param);
return $data;
}
//获取域名最低TTL
public function getMinTTL()
{
$param = ['id' => $this->domainid];
$data = $this->execute('GET', '/api/dnsMeasures', $param);
if ($data && isset($data['minTTL'])) {
return $data['minTTL'];
}
return false;
}
private function convertType($type)
{
$typeList = array_flip($this->typeList);
return $typeList[$type];
}
private function convertTypeId($typeId, $domaint)
{
if ($typeId == 256) {
return $domaint ? 'REDIRECT_URL' : 'FORWARD_URL';
}
return $this->typeList[$typeId];
}
private function execute($method, $path, $params = null)
{
$token = base64_encode($this->apiid.':'.$this->apisecret);
$header = ['Authorization: Basic '.$token, 'Content-Type: application/json; charset=utf-8'];
if ($method == 'POST' || $method == 'PUT') {
$response = $this->curl($method, $path, $header, json_encode($params));
} else {
if ($params) {
$path .= '?'.http_build_query($params);
}
$response = $this->curl($method, $path, $header);
}
if (!$response) {
return false;
}
$arr = json_decode($response, true);
if ($arr) {
if ($arr['code'] == 200) {
return $arr['data'];
} else {
$this->setError($arr['msg']);
return false;
}
} else {
$this->setError('返回数据解析失败');
return false;
}
}
private function curl($method, $path, $header, $body = null, $isPut = false)
{
$url = $this->baseUrl . $path;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($body) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($errno) {
return false;
}
if ($httpCode == 200) {
return $response;
} elseif ($httpCode == 401) {
$this->setError('认证失败');
return false;
} else {
$this->setError('http code: '.$httpCode);
return false;
}
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,407 +1,458 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class dnspod implements DnsInterface {
private $SecretId;
private $SecretKey;
private $endpoint = "dnspod.tencentcloudapi.com";
private $service = "dnspod";
private $version = "2021-03-23";
private $error;
private $domain;
private $domainid;
private $domainInfo;
function __construct($config){
$this->SecretId = $config['ak'];
$this->SecretKey = $config['sk'];
$this->domain = $config['domain'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$action = 'DescribeDomainList';
$offset = ($PageNumber-1)*$PageSize;
$param = ['Offset' => $offset, 'Limit' => $PageSize, 'Keyword' => $KeyWord];
$data = $this->send_reuqest($action, $param);
if($data){
$list = [];
foreach($data['DomainList'] as $row){
$list[] = [
'DomainId' => $row['DomainId'],
'Domain' => $row['Name'],
'RecordCount' => $row['RecordCount'],
];
}
return ['total' => $data['DomainCountInfo']['DomainTotal'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$offset = ($PageNumber-1)*$PageSize;
if(!isNullOrEmpty($Status) || !isNullOrEmpty($Value)){
$action = 'DescribeRecordFilterList';
$param = ['Domain' => $this->domain, 'Offset' => $offset, 'Limit' => $PageSize, 'RecordValue' => $Value];
if(!isNullOrEmpty($SubDomain)) $param['SubDomain'] = $SubDomain;
if(!isNullOrEmpty($KeyWord)) $param['Keyword'] = $KeyWord;
if(!isNullOrEmpty($Value)) $param['RecordValue'] = $Value;
if(!isNullOrEmpty($Status)){
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$param['RecordStatus'] = [$Status];
}
if(!isNullOrEmpty($Type)) $param['RecordType'] = [$this->convertType($Type)];
if(!isNullOrEmpty($Line)) $param['RecordLine'] = [$Line];
}else{
$action = 'DescribeRecordList';
$param = ['Domain' => $this->domain, 'Subdomain' => $SubDomain, 'RecordType' => $this->convertType($Type), 'RecordLineId' => $Line, 'Keyword' => $KeyWord, 'Offset' => $offset, 'Limit' => $PageSize];
}
$data = $this->send_reuqest($action, $param);
if($data){
$list = [];
foreach($data['RecordList'] as $row){
//if($row['Name'] == '@' && $row['Type'] == 'NS') continue;
$list[] = [
'RecordId' => $row['RecordId'],
'Domain' => $this->domain,
'Name' => $row['Name'],
'Type' => $this->convertTypeId($row['Type']),
'Value' => $row['Value'],
'Line' => $row['LineId'],
'TTL' => $row['TTL'],
'MX' => $row['MX'],
'Status' => $row['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => $row['Weight'],
'Remark' => $row['Remark'],
'UpdateTime' => $row['UpdatedOn'],
];
}
return ['total' => $data['RecordCountInfo']['TotalCount'], 'list' => $list];
}elseif($this->error == '记录列表为空。' || $this->error == 'No records on the list.'){
return ['total' => 0, 'list' => []];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
$action = 'DescribeRecord';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId)];
$data = $this->send_reuqest($action, $param);
if($data){
return [
'RecordId' => $data['RecordInfo']['Id'],
'Domain' => $this->domain,
'Name' => $data['RecordInfo']['SubDomain'],
'Type' => $this->convertTypeId($data['RecordInfo']['RecordType']),
'Value' => $data['RecordInfo']['Value'],
'Line' => $data['RecordInfo']['RecordLineId'],
'TTL' => $data['RecordInfo']['TTL'],
'MX' => $data['RecordInfo']['MX'],
'Status' => $data['RecordInfo']['Enabled'] == 1 ? '1' : '0',
'Weight' => $data['RecordInfo']['Weight'],
'Remark' => $data['RecordInfo']['Remark'],
'UpdateTime' => $data['RecordInfo']['UpdatedOn'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$action = 'CreateRecord';
$param = ['Domain' => $this->domain, 'SubDomain' => $Name, 'RecordType' => $this->convertType($Type), 'Value' => $Value, 'RecordLine'=>$Line, 'RecordLineId' => $this->convertLineCode($Line), 'TTL' => intval($TTL), 'Weight' => $Weight];
if($Type == 'MX')$param['MX'] = intval($MX);
$data = $this->send_reuqest($action, $param);
return is_array($data) ? $data['RecordId'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$action = 'ModifyRecord';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId), 'SubDomain' => $Name, 'RecordType' => $this->convertType($Type), 'Value' => $Value, 'RecordLine'=>$Line, 'RecordLineId' => $this->convertLineCode($Line), 'TTL' => intval($TTL), 'Weight' => $Weight];
if($Type == 'MX')$param['MX'] = intval($MX);
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
$action = 'ModifyRecordRemark';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId), 'Remark' => $Remark];
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$action = 'DeleteRecord';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId)];
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$action = 'ModifyRecordStatus';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId), 'Status' => $Status];
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
$action = 'DescribeDomainLogList';
$offset = ($PageNumber-1)*$PageSize;
$param = ['Domain' => $this->domain, 'Offset' => $offset, 'Limit' => $PageSize];
$data = $this->send_reuqest($action, $param);
if($data){
$list = [];
foreach($data['LogList'] as $row){
$list[] = ['time'=>substr($row, 0, strpos($row,'(')), 'ip'=>substr($row, strpos($row,'(')+1, strpos($row,')')-strpos($row,'(')-1), 'data'=>substr($row, strpos($row,')')+1, strpos($row,' Uin:')-strpos($row,')')-1)];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析线路列表
public function getRecordLine(){
$action = 'DescribeRecordLineCategoryList';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if($data){
$list = [];
$this->processLineList($list, $data['LineList'], null);
return $list;
}else{
$data = $this->getRecordLineByGrade();
if($data){
$list = [];
foreach($data as $row){
$list[$row['LineId']] = ['name'=>$row['Name'], 'parent'=>null];
}
return $list;
}
}
return false;
}
private function processLineList(&$list, $line_list, $parent){
foreach($line_list as $row){
if(isNullOrEmpty($row['LineId'])) $row['LineId'] = 'N.'.$row['LineName'];
if($row['Useful'] && !isset($list[$row['LineId']])){
$list[$row['LineId']] = ['name'=>$row['LineName'], 'parent'=>$parent];
if($row['SubGroup']){
$this->processLineList($list, $row['SubGroup'], $row['LineId']);
}
}
}
}
//获取域名概览信息
public function getDomainInfo(){
$action = 'DescribeDomain';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if($data){
$this->domainInfo = $data['DomainInfo'];
return $data['DomainInfo'];
}
return false;
}
//获取域名权限
public function getDomainPurview(){
$action = 'DescribeDomainPurview';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if($data){
return $data['PurviewList'];
}
return false;
}
//获取域名最低TTL
public function getMinTTL(){
if($this->domainInfo){
return $this->domainInfo['TTL'];
}
$PurviewList = $this->getDomainPurview();
if($PurviewList){
foreach($PurviewList as $row){
if($row['Name'] == '记录 TTL 最低' || $row['Name'] == 'Min TTL value'){
return intval($row['Value']);
}
}
}
return false;
}
//获取等级允许的线路
public function getRecordLineByGrade(){
$action = 'DescribeRecordLineList';
$param = ['Domain' => $this->domain, 'DomainGrade' => ''];
$data = $this->send_reuqest($action, $param);
if($data){
$line_list = $data['LineList'];
if(!empty($data['LineGroupList'])){
foreach($data['LineGroupList'] as $row){
$line_list[] = ['Name' => $row['Name'], 'LineId' => $row['LineId']];
}
}
return $line_list;
}
return false;
}
//获取用户信息
public function getAccountInfo(){
$action = 'DescribeUserDetail';
$param = [];
$data = $this->send_reuqest($action, $param);
if($data){
return $data['UserInfo'];
}
return false;
}
private function convertLineCode($line){
$convert_dict = ['default'=>'0', 'unicom'=>'10=1', 'telecom'=>'10=0', 'mobile'=>'10=3', 'edu'=>'10=2', 'oversea'=>'3=0', 'btvn'=>'10=22', 'search'=>'80=0', 'internal'=>'7=0'];
if(array_key_exists($line, $convert_dict)){
return $convert_dict[$line];
}
return $line;
}
private function convertType($type){
$convert_dict = ['REDIRECT_URL'=>'显性URL', 'FORWARD_URL'=>'隐性URL'];
if(array_key_exists($type, $convert_dict)){
return $convert_dict[$type];
}
return $type;
}
private function convertTypeId($type){
$convert_dict = ['显性URL'=>'REDIRECT_URL', '隐性URL'=>'FORWARD_URL'];
if(array_key_exists($type, $convert_dict)){
return $convert_dict[$type];
}
return $type;
}
private function send_reuqest($action, $param){
$param = array_filter($param, function($a){ return $a!==null;});
if(!$param) $param = (object)[];
$payload = json_encode($param);
$time = time();
$authorization = $this->generateSign($payload, $time);
$header = [
'Authorization: '.$authorization,
'Content-Type: application/json; charset=utf-8',
'X-TC-Action: '.$action,
'X-TC-Timestamp: '.$time,
'X-TC-Version: '.$this->version,
];
return $this->curl_post($payload, $header);
}
private function generateSign($payload, $time){
$algorithm = "TC3-HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json; charset=utf-8\n"."host:".$this->endpoint."\n";
$signedHeaders = "content-type;host";
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Y-m-d", $time);
$credentialScope = $date."/".$this->service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$time."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$this->SecretKey, true);
$secretService = hash_hmac("SHA256", $this->service, $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
// step 4: build authorization
$authorization = $algorithm
." Credential=".$this->SecretId."/".$credentialScope
.", SignedHeaders=content-type;host, Signature=".$signature;
return $authorization;
}
private function curl_post($payload, $header){
$url = 'https://'.$this->endpoint.'/';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
$arr=json_decode($response,true);
if($arr){
if(isset($arr['Response']['Error'])){
$this->setError($arr['Response']['Error']['Message']);
return false;
}else{
return $arr['Response'];
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class dnspod implements DnsInterface
{
private $SecretId;
private $SecretKey;
private $endpoint = "dnspod.tencentcloudapi.com";
private $service = "dnspod";
private $version = "2021-03-23";
private $error;
private $domain;
private $domainid;
private $domainInfo;
public function __construct($config)
{
$this->SecretId = $config['ak'];
$this->SecretKey = $config['sk'];
$this->domain = $config['domain'];
}
public function getError()
{
return $this->error;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$action = 'DescribeDomainList';
$offset = ($PageNumber - 1) * $PageSize;
$param = ['Offset' => $offset, 'Limit' => $PageSize, 'Keyword' => $KeyWord];
$data = $this->send_reuqest($action, $param);
if ($data) {
$list = [];
foreach ($data['DomainList'] as $row) {
$list[] = [
'DomainId' => $row['DomainId'],
'Domain' => $row['Name'],
'RecordCount' => $row['RecordCount'],
];
}
return ['total' => $data['DomainCountInfo']['DomainTotal'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$offset = ($PageNumber - 1) * $PageSize;
if (!isNullOrEmpty($Status) || !isNullOrEmpty($Value)) {
$action = 'DescribeRecordFilterList';
$param = ['Domain' => $this->domain, 'Offset' => $offset, 'Limit' => $PageSize, 'RecordValue' => $Value];
if (!isNullOrEmpty($SubDomain)) {
$param['SubDomain'] = $SubDomain;
}
if (!isNullOrEmpty($KeyWord)) {
$param['Keyword'] = $KeyWord;
}
if (!isNullOrEmpty($Value)) {
$param['RecordValue'] = $Value;
}
if (!isNullOrEmpty($Status)) {
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$param['RecordStatus'] = [$Status];
}
if (!isNullOrEmpty($Type)) {
$param['RecordType'] = [$this->convertType($Type)];
}
if (!isNullOrEmpty($Line)) {
$param['RecordLine'] = [$Line];
}
} else {
$action = 'DescribeRecordList';
$param = ['Domain' => $this->domain, 'Subdomain' => $SubDomain, 'RecordType' => $this->convertType($Type), 'RecordLineId' => $Line, 'Keyword' => $KeyWord, 'Offset' => $offset, 'Limit' => $PageSize];
}
$data = $this->send_reuqest($action, $param);
if ($data) {
$list = [];
foreach ($data['RecordList'] as $row) {
//if($row['Name'] == '@' && $row['Type'] == 'NS') continue;
$list[] = [
'RecordId' => $row['RecordId'],
'Domain' => $this->domain,
'Name' => $row['Name'],
'Type' => $this->convertTypeId($row['Type']),
'Value' => $row['Value'],
'Line' => $row['LineId'],
'TTL' => $row['TTL'],
'MX' => $row['MX'],
'Status' => $row['Status'] == 'ENABLE' ? '1' : '0',
'Weight' => $row['Weight'],
'Remark' => $row['Remark'],
'UpdateTime' => $row['UpdatedOn'],
];
}
return ['total' => $data['RecordCountInfo']['TotalCount'], 'list' => $list];
} elseif ($this->error == '记录列表为空。' || $this->error == 'No records on the list.') {
return ['total' => 0, 'list' => []];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
if ($SubDomain == '') {
$SubDomain = '@';
}
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
$action = 'DescribeRecord';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId)];
$data = $this->send_reuqest($action, $param);
if ($data) {
return [
'RecordId' => $data['RecordInfo']['Id'],
'Domain' => $this->domain,
'Name' => $data['RecordInfo']['SubDomain'],
'Type' => $this->convertTypeId($data['RecordInfo']['RecordType']),
'Value' => $data['RecordInfo']['Value'],
'Line' => $data['RecordInfo']['RecordLineId'],
'TTL' => $data['RecordInfo']['TTL'],
'MX' => $data['RecordInfo']['MX'],
'Status' => $data['RecordInfo']['Enabled'] == 1 ? '1' : '0',
'Weight' => $data['RecordInfo']['Weight'],
'Remark' => $data['RecordInfo']['Remark'],
'UpdateTime' => $data['RecordInfo']['UpdatedOn'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$action = 'CreateRecord';
$param = ['Domain' => $this->domain, 'SubDomain' => $Name, 'RecordType' => $this->convertType($Type), 'Value' => $Value, 'RecordLine' => $Line, 'RecordLineId' => $this->convertLineCode($Line), 'TTL' => intval($TTL), 'Weight' => $Weight];
if ($Type == 'MX') {
$param['MX'] = intval($MX);
}
$data = $this->send_reuqest($action, $param);
return is_array($data) ? $data['RecordId'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$action = 'ModifyRecord';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId), 'SubDomain' => $Name, 'RecordType' => $this->convertType($Type), 'Value' => $Value, 'RecordLine' => $Line, 'RecordLineId' => $this->convertLineCode($Line), 'TTL' => intval($TTL), 'Weight' => $Weight];
if ($Type == 'MX') {
$param['MX'] = intval($MX);
}
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
$action = 'ModifyRecordRemark';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId), 'Remark' => $Remark];
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$action = 'DeleteRecord';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId)];
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$action = 'ModifyRecordStatus';
$param = ['Domain' => $this->domain, 'RecordId' => intval($RecordId), 'Status' => $Status];
$data = $this->send_reuqest($action, $param);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
$action = 'DescribeDomainLogList';
$offset = ($PageNumber - 1) * $PageSize;
$param = ['Domain' => $this->domain, 'Offset' => $offset, 'Limit' => $PageSize];
$data = $this->send_reuqest($action, $param);
if ($data) {
$list = [];
foreach ($data['LogList'] as $row) {
$list[] = ['time' => substr($row, 0, strpos($row, '(')), 'ip' => substr($row, strpos($row, '(') + 1, strpos($row, ')') - strpos($row, '(') - 1), 'data' => substr($row, strpos($row, ')') + 1, strpos($row, ' Uin:') - strpos($row, ')') - 1)];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取解析线路列表
public function getRecordLine()
{
$action = 'DescribeRecordLineCategoryList';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if ($data) {
$list = [];
$this->processLineList($list, $data['LineList'], null);
return $list;
} else {
$data = $this->getRecordLineByGrade();
if ($data) {
$list = [];
foreach ($data as $row) {
$list[$row['LineId']] = ['name' => $row['Name'], 'parent' => null];
}
return $list;
}
}
return false;
}
private function processLineList(&$list, $line_list, $parent)
{
foreach ($line_list as $row) {
if (isNullOrEmpty($row['LineId'])) {
$row['LineId'] = 'N.'.$row['LineName'];
}
if ($row['Useful'] && !isset($list[$row['LineId']])) {
$list[$row['LineId']] = ['name' => $row['LineName'], 'parent' => $parent];
if ($row['SubGroup']) {
$this->processLineList($list, $row['SubGroup'], $row['LineId']);
}
}
}
}
//获取域名概览信息
public function getDomainInfo()
{
$action = 'DescribeDomain';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if ($data) {
$this->domainInfo = $data['DomainInfo'];
return $data['DomainInfo'];
}
return false;
}
//获取域名权限
public function getDomainPurview()
{
$action = 'DescribeDomainPurview';
$param = ['Domain' => $this->domain];
$data = $this->send_reuqest($action, $param);
if ($data) {
return $data['PurviewList'];
}
return false;
}
//获取域名最低TTL
public function getMinTTL()
{
if ($this->domainInfo) {
return $this->domainInfo['TTL'];
}
$PurviewList = $this->getDomainPurview();
if ($PurviewList) {
foreach ($PurviewList as $row) {
if ($row['Name'] == '记录 TTL 最低' || $row['Name'] == 'Min TTL value') {
return intval($row['Value']);
}
}
}
return false;
}
//获取等级允许的线路
public function getRecordLineByGrade()
{
$action = 'DescribeRecordLineList';
$param = ['Domain' => $this->domain, 'DomainGrade' => ''];
$data = $this->send_reuqest($action, $param);
if ($data) {
$line_list = $data['LineList'];
if (!empty($data['LineGroupList'])) {
foreach ($data['LineGroupList'] as $row) {
$line_list[] = ['Name' => $row['Name'], 'LineId' => $row['LineId']];
}
}
return $line_list;
}
return false;
}
//获取用户信息
public function getAccountInfo()
{
$action = 'DescribeUserDetail';
$param = [];
$data = $this->send_reuqest($action, $param);
if ($data) {
return $data['UserInfo'];
}
return false;
}
private function convertLineCode($line)
{
$convert_dict = ['default' => '0', 'unicom' => '10=1', 'telecom' => '10=0', 'mobile' => '10=3', 'edu' => '10=2', 'oversea' => '3=0', 'btvn' => '10=22', 'search' => '80=0', 'internal' => '7=0'];
if (array_key_exists($line, $convert_dict)) {
return $convert_dict[$line];
}
return $line;
}
private function convertType($type)
{
$convert_dict = ['REDIRECT_URL' => '显性URL', 'FORWARD_URL' => '隐性URL'];
if (array_key_exists($type, $convert_dict)) {
return $convert_dict[$type];
}
return $type;
}
private function convertTypeId($type)
{
$convert_dict = ['显性URL' => 'REDIRECT_URL', '隐性URL' => 'FORWARD_URL'];
if (array_key_exists($type, $convert_dict)) {
return $convert_dict[$type];
}
return $type;
}
private function send_reuqest($action, $param)
{
$param = array_filter($param, function ($a) { return $a !== null;});
if (!$param) {
$param = (object)[];
}
$payload = json_encode($param);
$time = time();
$authorization = $this->generateSign($payload, $time);
$header = [
'Authorization: '.$authorization,
'Content-Type: application/json; charset=utf-8',
'X-TC-Action: '.$action,
'X-TC-Timestamp: '.$time,
'X-TC-Version: '.$this->version,
];
return $this->curl_post($payload, $header);
}
private function generateSign($payload, $time)
{
$algorithm = "TC3-HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json; charset=utf-8\n"."host:".$this->endpoint."\n";
$signedHeaders = "content-type;host";
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Y-m-d", $time);
$credentialScope = $date."/".$this->service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$time."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$this->SecretKey, true);
$secretService = hash_hmac("SHA256", $this->service, $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
// step 4: build authorization
$authorization = $algorithm
." Credential=".$this->SecretId."/".$credentialScope
.", SignedHeaders=content-type;host, Signature=".$signature;
return $authorization;
}
private function curl_post($payload, $header)
{
$url = 'https://'.$this->endpoint.'/';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) {
return false;
}
$arr = json_decode($response, true);
if ($arr) {
if (isset($arr['Response']['Error'])) {
$this->setError($arr['Response']['Error']['Message']);
return false;
} else {
return $arr['Response'];
}
} else {
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,360 +1,415 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class huawei implements DnsInterface {
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "dns.myhuaweicloud.com";
private $error;
private $domain;
private $domainid;
function __construct($config){
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$offset = ($PageNumber-1)*$PageSize;
$query = ['offset' => $offset, 'limit' => $PageSize, 'name' => $KeyWord];
$data = $this->send_reuqest('GET', '/v2/zones', $query);
if($data){
$list = [];
foreach($data['zones'] as $row){
$list[] = [
'DomainId' => $row['id'],
'Domain' => rtrim($row['name'], '.'),
'RecordCount' => $row['record_num'],
];
}
return ['total' => $data['metadata']['total_count'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$offset = ($PageNumber-1)*$PageSize;
$query = ['type' => $Type, 'line_id' => $Line, 'name' => $KeyWord, 'offset' => $offset, 'limit' => $PageSize];
if(!isNullOrEmpty($Status)){
$Status = $Status == '1' ? 'ACTIVE' : 'DISABLE';
$query['status'] = $Status;
}
if(!isNullOrEmpty($SubDomain)){
$SubDomain = $this->getHost($SubDomain);
$query['name'] = $SubDomain;
$query['search_mode'] = 'equal';
}
$data = $this->send_reuqest('GET', '/v2.1/zones/'.$this->domainid.'/recordsets', $query);
if($data){
$list = [];
foreach($data['recordsets'] as $row){
if($row['name'] == $row['zone_name']) $row['name'] = '@';
if($row['type'] == 'MX') list($row['mx'], $row['records']) = explode(' ', $row['records'][0]);
$list[] = [
'RecordId' => $row['id'],
'Domain' => rtrim($row['zone_name'], '.'),
'Name' => str_replace('.'.$row['zone_name'], '', $row['name']),
'Type' => $row['type'],
'Value' => $row['records'],
'Line' => $row['line'],
'TTL' => $row['ttl'],
'MX' => isset($row['mx']) ? $row['mx'] : null,
'Status' => $row['status'] == 'ACTIVE' ? '1' : '0',
'Weight' => $row['weight'],
'Remark' => $row['description'],
'UpdateTime' => $row['updated_at'],
];
}
return ['total' => $data['metadata']['total_count'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
$data = $this->send_reuqest('GET', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId);
if($data){
if($data['name'] == $data['zone_name']) $data['name'] = '@';
if($data['type'] == 'MX') list($data['mx'], $data['records']) = explode(' ', $data['records'][0]);
return [
'RecordId' => $data['id'],
'Domain' => rtrim($data['zone_name'], '.'),
'Name' => str_replace('.'.$data['zone_name'], '', $data['name']),
'Type' => $data['type'],
'Value' => $data['records'],
'Line' => $data['line'],
'TTL' => $data['ttl'],
'MX' => isset($data['mx']) ? $data['mx'] : null,
'Status' => $data['status'] == 'ACTIVE' ? '1' : '0',
'Weight' => $data['weight'],
'Remark' => $data['description'],
'UpdateTime' => $data['updated_at'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$Name = $this->getHost($Name);
if($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"'.$Value.'"';
$records = explode(',', $Value);
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line'=>$Line, 'ttl' => intval($TTL), 'description' => $Remark];
if($Type == 'MX') $params['records'][0] = intval($MX) . ' ' . $Value;
if($Weight > 0) $params['weight'] = intval($Weight);
$data = $this->send_reuqest('POST', '/v2.1/zones/'.$this->domainid.'/recordsets', null, $params);
return is_array($data) ? $data['id'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$Name = $this->getHost($Name);
if($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"'.$Value.'"';
$records = explode(',', $Value);
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line'=>$Line, 'ttl' => intval($TTL), 'description' => $Remark];
if($Type == 'MX') $params['records'][0] = intval($MX) . ' ' . $Value;
if($Weight > 0) $params['weight'] = intval($Weight);
$data = $this->send_reuqest('PUT', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId, null, $params);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$data = $this->send_reuqest('DELETE', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId);
return is_array($data);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$params = ['status' => $Status];
$data = $this->send_reuqest('PUT', '/v2.1/recordsets/'.$RecordId.'/statuses/set', null, $params);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
return false;
}
//获取解析线路列表
public function getRecordLine(){
$file_path = app()->getBasePath().'data'.DIRECTORY_SEPARATOR.'huawei_line.json';
$content = file_get_contents($file_path);
$data = json_decode($content, true);
if($data){
return $data;
$list = [$data['DEFAULT']['id'] => ['name'=>$data['DEFAULT']['zh'], 'parent'=>null]];
$this->processLineList($list, $data['ISP'], null, 1, 1);
$this->processLineList($list, $data['REGION'], null, null, 1);
//file_put_contents($file_path, json_encode($list, JSON_UNESCAPED_UNICODE));
return $list;
}
return false;
}
private function processLineList(&$list, $line_list, $parent, $rootId = null, $rootName = null){
foreach($line_list as $row){
if($rootId && $rootId!==1){
$row['id'] = $rootId.'_'.$row['id'];
}
if($rootName && $rootName!==1){
$row['zh'] = $rootName.'_'.$row['zh'];
}
$list[$row['id']] = ['name'=>$row['zh'], 'parent'=>$parent];
if(isset($row['children']) && !empty($row['children'])){
$this->processLineList($list, $row['children'], $row['id'], $rootId === 1 ? $row['id'] : $rootId, $rootName === 1 ? $row['zh'] : $rootName);
}
}
}
//获取域名概览信息
public function getDomainInfo(){
return $this->send_reuqest('GET', '/v2/zones/'.$this->domainid);
}
//获取域名最低TTL
public function getMinTTL(){
return false;
}
private function convertType($type){
return $type;
}
private function getHost($Name){
if($Name == '@') $Name = '';
else $Name .= '.';
$Name .= $this->domain . '.';
return $Name;
}
private function send_reuqest($method, $path, $query = null, $params = null){
if(!empty($query)){
$query = array_filter($query, function($a){ return $a!==null;});
}
if(!empty($params)){
$params = array_filter($params, function($a){ return $a!==null;});
}
$time = time();
$date = gmdate("Ymd\THis\Z", $time);
$body = !empty($params) ? json_encode($params) : '';
$headers = [
'Host' => $this->endpoint,
'X-Sdk-Date' => $date,
];
if($body){
$headers['Content-Type'] = 'application/json';
}
$authorization = $this->generateSign($method, $path, $query, $headers, $body, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path;
if(!empty($query)){
$url .= '?'.http_build_query($query);
}
$header = [];
foreach($headers as $key => $value){
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $body, $time){
$algorithm = "SDK-HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $path;
if(substr($canonicalUri, -1) != "/") $canonicalUri .= "/";
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$hashedRequestPayload = hash("sha256", $body);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Ymd\THis\Z", $time);
$hashedCanonicalRequest = hash("sha256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$date."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$signature = hash_hmac("sha256", $stringToSign, $this->SecretAccessKey);
// step 4: build authorization
$authorization = $algorithm . ' Access=' . $this->AccessKeyId . ", SignedHeaders=" . $signedHeaders . ", Signature=" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalQueryString($parameters)
{
if(empty($parameters)) return '';
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders){
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $key . ':' . $value . "\n";
$signedHeaders .= $key . ';';
}
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if(!empty($body)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
$arr=json_decode($response,true);
if($arr){
if(isset($arr['error_msg'])){
$this->setError($arr['error_msg']);
return false;
}elseif(isset($arr['message'])){
$this->setError($arr['message']);
return false;
}else{
return $arr;
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class huawei implements DnsInterface
{
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "dns.myhuaweicloud.com";
private $error;
private $domain;
private $domainid;
public function __construct($config)
{
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError()
{
return $this->error;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$offset = ($PageNumber - 1) * $PageSize;
$query = ['offset' => $offset, 'limit' => $PageSize, 'name' => $KeyWord];
$data = $this->send_reuqest('GET', '/v2/zones', $query);
if ($data) {
$list = [];
foreach ($data['zones'] as $row) {
$list[] = [
'DomainId' => $row['id'],
'Domain' => rtrim($row['name'], '.'),
'RecordCount' => $row['record_num'],
];
}
return ['total' => $data['metadata']['total_count'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$offset = ($PageNumber - 1) * $PageSize;
$query = ['type' => $Type, 'line_id' => $Line, 'name' => $KeyWord, 'offset' => $offset, 'limit' => $PageSize];
if (!isNullOrEmpty($Status)) {
$Status = $Status == '1' ? 'ACTIVE' : 'DISABLE';
$query['status'] = $Status;
}
if (!isNullOrEmpty($SubDomain)) {
$SubDomain = $this->getHost($SubDomain);
$query['name'] = $SubDomain;
$query['search_mode'] = 'equal';
}
$data = $this->send_reuqest('GET', '/v2.1/zones/'.$this->domainid.'/recordsets', $query);
if ($data) {
$list = [];
foreach ($data['recordsets'] as $row) {
if ($row['name'] == $row['zone_name']) {
$row['name'] = '@';
}
if ($row['type'] == 'MX') {
list($row['mx'], $row['records']) = explode(' ', $row['records'][0]);
}
$list[] = [
'RecordId' => $row['id'],
'Domain' => rtrim($row['zone_name'], '.'),
'Name' => str_replace('.'.$row['zone_name'], '', $row['name']),
'Type' => $row['type'],
'Value' => $row['records'],
'Line' => $row['line'],
'TTL' => $row['ttl'],
'MX' => isset($row['mx']) ? $row['mx'] : null,
'Status' => $row['status'] == 'ACTIVE' ? '1' : '0',
'Weight' => $row['weight'],
'Remark' => $row['description'],
'UpdateTime' => $row['updated_at'],
];
}
return ['total' => $data['metadata']['total_count'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
$data = $this->send_reuqest('GET', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId);
if ($data) {
if ($data['name'] == $data['zone_name']) {
$data['name'] = '@';
}
if ($data['type'] == 'MX') {
list($data['mx'], $data['records']) = explode(' ', $data['records'][0]);
}
return [
'RecordId' => $data['id'],
'Domain' => rtrim($data['zone_name'], '.'),
'Name' => str_replace('.'.$data['zone_name'], '', $data['name']),
'Type' => $data['type'],
'Value' => $data['records'],
'Line' => $data['line'],
'TTL' => $data['ttl'],
'MX' => isset($data['mx']) ? $data['mx'] : null,
'Status' => $data['status'] == 'ACTIVE' ? '1' : '0',
'Weight' => $data['weight'],
'Remark' => $data['description'],
'UpdateTime' => $data['updated_at'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$Name = $this->getHost($Name);
if ($Type == 'TXT' && substr($Value, 0, 1) != '"') {
$Value = '"'.$Value.'"';
}
$records = explode(',', $Value);
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark];
if ($Type == 'MX') {
$params['records'][0] = intval($MX) . ' ' . $Value;
}
if ($Weight > 0) {
$params['weight'] = intval($Weight);
}
$data = $this->send_reuqest('POST', '/v2.1/zones/'.$this->domainid.'/recordsets', null, $params);
return is_array($data) ? $data['id'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$Name = $this->getHost($Name);
if ($Type == 'TXT' && substr($Value, 0, 1) != '"') {
$Value = '"'.$Value.'"';
}
$records = explode(',', $Value);
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark];
if ($Type == 'MX') {
$params['records'][0] = intval($MX) . ' ' . $Value;
}
if ($Weight > 0) {
$params['weight'] = intval($Weight);
}
$data = $this->send_reuqest('PUT', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId, null, $params);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$data = $this->send_reuqest('DELETE', '/v2.1/zones/'.$this->domainid.'/recordsets/'.$RecordId);
return is_array($data);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$Status = $Status == '1' ? 'ENABLE' : 'DISABLE';
$params = ['status' => $Status];
$data = $this->send_reuqest('PUT', '/v2.1/recordsets/'.$RecordId.'/statuses/set', null, $params);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
return false;
}
//获取解析线路列表
public function getRecordLine()
{
$file_path = app()->getBasePath().'data'.DIRECTORY_SEPARATOR.'huawei_line.json';
$content = file_get_contents($file_path);
$data = json_decode($content, true);
if ($data) {
return $data;
$list = [$data['DEFAULT']['id'] => ['name' => $data['DEFAULT']['zh'], 'parent' => null]];
$this->processLineList($list, $data['ISP'], null, 1, 1);
$this->processLineList($list, $data['REGION'], null, null, 1);
//file_put_contents($file_path, json_encode($list, JSON_UNESCAPED_UNICODE));
return $list;
}
return false;
}
private function processLineList(&$list, $line_list, $parent, $rootId = null, $rootName = null)
{
foreach ($line_list as $row) {
if ($rootId && $rootId !== 1) {
$row['id'] = $rootId.'_'.$row['id'];
}
if ($rootName && $rootName !== 1) {
$row['zh'] = $rootName.'_'.$row['zh'];
}
$list[$row['id']] = ['name' => $row['zh'], 'parent' => $parent];
if (isset($row['children']) && !empty($row['children'])) {
$this->processLineList($list, $row['children'], $row['id'], $rootId === 1 ? $row['id'] : $rootId, $rootName === 1 ? $row['zh'] : $rootName);
}
}
}
//获取域名概览信息
public function getDomainInfo()
{
return $this->send_reuqest('GET', '/v2/zones/'.$this->domainid);
}
//获取域名最低TTL
public function getMinTTL()
{
return false;
}
private function convertType($type)
{
return $type;
}
private function getHost($Name)
{
if ($Name == '@') {
$Name = '';
} else {
$Name .= '.';
}
$Name .= $this->domain . '.';
return $Name;
}
private function send_reuqest($method, $path, $query = null, $params = null)
{
if (!empty($query)) {
$query = array_filter($query, function ($a) { return $a !== null;});
}
if (!empty($params)) {
$params = array_filter($params, function ($a) { return $a !== null;});
}
$time = time();
$date = gmdate("Ymd\THis\Z", $time);
$body = !empty($params) ? json_encode($params) : '';
$headers = [
'Host' => $this->endpoint,
'X-Sdk-Date' => $date,
];
if ($body) {
$headers['Content-Type'] = 'application/json';
}
$authorization = $this->generateSign($method, $path, $query, $headers, $body, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path;
if (!empty($query)) {
$url .= '?'.http_build_query($query);
}
$header = [];
foreach ($headers as $key => $value) {
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $body, $time)
{
$algorithm = "SDK-HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $path;
if (substr($canonicalUri, -1) != "/") {
$canonicalUri .= "/";
}
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$hashedRequestPayload = hash("sha256", $body);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Ymd\THis\Z", $time);
$hashedCanonicalRequest = hash("sha256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$date."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$signature = hash_hmac("sha256", $stringToSign, $this->SecretAccessKey);
// step 4: build authorization
$authorization = $algorithm . ' Access=' . $this->AccessKeyId . ", SignedHeaders=" . $signedHeaders . ", Signature=" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalQueryString($parameters)
{
if (empty($parameters)) {
return '';
}
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders)
{
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $key . ':' . $value . "\n";
$signedHeaders .= $key . ';';
}
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if (!empty($body)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) {
return false;
}
$arr = json_decode($response, true);
if ($arr) {
if (isset($arr['error_msg'])) {
$this->setError($arr['error_msg']);
return false;
} elseif (isset($arr['message'])) {
$this->setError($arr['message']);
return false;
} else {
return $arr;
}
} else {
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,387 +1,440 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class huoshan implements DnsInterface {
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "open.volcengineapi.com";
private $service = "DNS";
private $version = "2018-08-01";
private $region = "cn-north-1";
private $error;
private $domain;
private $domainid;
private $domainInfo;
private static $trade_code_list = [
'free_inner' => ['level' => 1, 'name' => '免费版', 'ttl' => 600],
'professional_inner' => ['level' => 2, 'name' => '专业版', 'ttl' => 300],
'enterprise_inner' => ['level' => 3, 'name' => '企业版', 'ttl' => 60],
'ultimate_inner' => ['level' => 4, 'name' => '旗舰版', 'ttl' => 1],
'ultimate_exclusive_inner' => ['level' => 5, 'name' => '尊享版', 'ttl' => 1],
];
function __construct($config){
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$query = ['PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'Key' => $KeyWord];
$data = $this->send_reuqest('GET', 'ListZones', $query);
if($data){
$list = [];
if(!empty($data['Zones'])){
foreach($data['Zones'] as $row){
$list[] = [
'DomainId' => $row['ZID'],
'Domain' => $row['ZoneName'],
'RecordCount' => $row['RecordCount'],
];
}
}
return ['total' => $data['Total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$query = ['ZID' => intval($this->domainid), 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'SearchOrder' => 'desc'];
if(!empty($SubDomain) || !empty($Type) || !empty($Line) || !empty($Value)){
$query += ['Host' => $SubDomain, 'Value' => $Value, 'Type' => $Type, 'Line' => $Line];
}elseif(!empty($KeyWord)){
$query += ['Host' => $KeyWord];
}
$data = $this->send_reuqest('GET', 'ListRecords', $query);
if($data){
$list = [];
foreach($data['Records'] as $row){
if($row['Type'] == 'MX') list($row['MX'], $row['Value']) = explode(' ', $row['Value']);
$list[] = [
'RecordId' => $row['RecordID'],
'Domain' => $this->domain,
'Name' => $row['Host'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => isset($row['MX']) ? $row['MX'] : null,
'Status' => $row['Enable'] ? '1' : '0',
'Weight' => $row['Weight'],
'Remark' => $row['Remark'],
'UpdateTime' => $row['UpdatedAt'],
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
$data = $this->send_reuqest('GET', 'QueryRecord', ['RecordID' => $RecordId]);
if($data){
if($data['name'] == $data['zone_name']) $data['name'] = '@';
if($data['Type'] == 'MX') list($data['MX'], $data['Value']) = explode(' ', $data['Value']);
return [
'RecordId' => $data['RecordID'],
'Domain' => $this->domain,
'Name' => $data['Host'],
'Type' => $data['Type'],
'Value' => $data['Value'],
'Line' => $data['Line'],
'TTL' => $data['TTL'],
'MX' => isset($data['MX']) ? $data['MX'] : null,
'Status' => $data['Enable'] ? '1' : '0',
'Weight' => $data['Weight'],
'Remark' => $data['Remark'],
'UpdateTime' => $data['UpdatedAt'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$params = ['ZID' => intval($this->domainid), 'Host' => $Name, 'Type' => $this->convertType($Type), 'Value' => $Value, 'Line'=>$Line, 'TTL' => intval($TTL), 'Remark' => $Remark];
if($Type == 'MX') $params['Value'] = intval($MX) . ' ' . $Value;
if($Weight > 0) $params['Weight'] = $Weight;
$data = $this->send_reuqest('POST', 'CreateRecord', $params);
return is_array($data) ? $data['RecordID'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$params = ['RecordID' => $RecordId, 'Host' => $Name, 'Type' => $this->convertType($Type), 'Value' => $Value, 'Line'=>$Line, 'TTL' => intval($TTL), 'Remark' => $Remark];
if($Type == 'MX') $params['Value'] = intval($MX) . ' ' . $Value;
if($Weight > 0) $params['Weight'] = $Weight;
$data = $this->send_reuqest('POST', 'UpdateRecord', $params);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$data = $this->send_reuqest('POST', 'DeleteRecord', ['RecordID' => $RecordId]);
return $data;
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$params = ['RecordID' => $RecordId, 'Enable' => $Status == '1'];
$data = $this->send_reuqest('POST', 'UpdateRecordStatus', $params);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
return false;
}
//获取解析线路列表
public function getRecordLine(){
$domainInfo = $this->getDomainInfo();
if(!$domainInfo) return false;
$level = $this->getTradeInfo($domainInfo['TradeCode'])['level'];
$data = $this->send_reuqest('GET', 'ListLines', []);
if($data){
$list = [];
$list['default'] = ['name' => '默认', 'parent' => null];
foreach($data['Lines'] as $row){
if($row['Value'] == 'default') continue;
if($row['Level'] > $level) continue;
$list[$row['Value']] = ['name' => $row['Name'], 'parent' => isset($row['FatherValue']) ? $row['FatherValue'] : null];
}
$data = $this->send_reuqest('GET', 'ListCustomLines', []);
if($data && $data['TotalCount'] > 0){
$list['N.customer_lines'] = ['name' => '自定义线路', 'parent' => null];
foreach($data['CustomerLines'] as $row){
$list[$row['Line']] = ['name' => $row['NameCN'], 'parent' => 'N.customer_lines'];
}
}
return $list;
}
return false;
}
//获取域名概览信息
public function getDomainInfo(){
if(!empty($this->domainInfo)) return $this->domainInfo;
$query = ['ZID' => intval($this->domainid)];
$data = $this->send_reuqest('GET', 'QueryZone', $query);
if($data){
$this->domainInfo = $data;
return $data;
}
return false;
}
//获取域名最低TTL
public function getMinTTL(){
$domainInfo = $this->getDomainInfo();
if($domainInfo){
$ttl = $this->getTradeInfo($domainInfo['TradeCode'])['ttl'];
return $ttl;
}
return false;
}
private function convertType($type){
return $type;
}
private function getTradeInfo($trade_code){
if(array_key_exists($trade_code, self::$trade_code_list)){
$trade_code = $trade_code;
}else{
$trade_code = 'free_inner';
}
return self::$trade_code_list[$trade_code];
}
private function send_reuqest($method, $action, $params = []){
if(!empty($params)){
$params = array_filter($params, function($a){ return $a!==null;});
}
$query = [
'Action' => $action,
'Version' => $this->version,
];
$body = '';
if($method == 'GET'){
$query = array_merge($query, $params);
}else{
$body = !empty($params) ? json_encode($params) : '';
}
$time = time();
$headers = [
'Host' => $this->endpoint,
'X-Date' => gmdate("Ymd\THis\Z", $time),
//'X-Content-Sha256' => hash("sha256", $body),
];
if($body){
$headers['Content-Type'] = 'application/json';
}
$path = '/';
$authorization = $this->generateSign($method, $path, $query, $headers, $body, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path.'?'.http_build_query($query);
$header = [];
foreach($headers as $key => $value){
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $body, $time){
$algorithm = "HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $path;
if(substr($canonicalUri, -1) != "/") $canonicalUri .= "/";
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$hashedRequestPayload = hash("sha256", $body);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Ymd\THis\Z", $time);
$shortDate = substr($date, 0, 8);
$credentialScope = $shortDate . '/' .$this->region . '/' . $this->service . '/request';
$hashedCanonicalRequest = hash("sha256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$date."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$kDate = hash_hmac("sha256", $shortDate, $this->SecretAccessKey, true);
$kRegion = hash_hmac("sha256", $this->region, $kDate, true);
$kService = hash_hmac("sha256", $this->service, $kRegion, true);
$kSigning = hash_hmac("sha256", "request", $kService, true);
$signature = hash_hmac("sha256", $stringToSign, $kSigning);
// step 4: build authorization
$credential = $this->AccessKeyId . '/' . $shortDate . '/' . $this->region . '/' . $this->service . '/request';
$authorization = $algorithm . ' Credential=' . $credential . ", SignedHeaders=" . $signedHeaders . ", Signature=" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalQueryString($parameters)
{
if(empty($parameters)) return '';
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders){
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $key . ':' . $value . "\n";
$signedHeaders .= $key . ';';
}
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if(!empty($body)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
$arr=json_decode($response,true);
if($arr){
if(isset($arr['ResponseMetadata']['Error']['MessageCN'])){
$this->setError($arr['ResponseMetadata']['Error']['MessageCN']);
return false;
}elseif(isset($arr['ResponseMetadata']['Error']['Message'])){
$this->setError($arr['ResponseMetadata']['Error']['Message']);
return false;
}elseif(isset($arr['Result'])){
return $arr['Result'];
}else{
return true;
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
class huoshan implements DnsInterface
{
private $AccessKeyId;
private $SecretAccessKey;
private $endpoint = "open.volcengineapi.com";
private $service = "DNS";
private $version = "2018-08-01";
private $region = "cn-north-1";
private $error;
private $domain;
private $domainid;
private $domainInfo;
private static $trade_code_list = [
'free_inner' => ['level' => 1, 'name' => '免费版', 'ttl' => 600],
'professional_inner' => ['level' => 2, 'name' => '专业版', 'ttl' => 300],
'enterprise_inner' => ['level' => 3, 'name' => '企业版', 'ttl' => 60],
'ultimate_inner' => ['level' => 4, 'name' => '旗舰版', 'ttl' => 1],
'ultimate_exclusive_inner' => ['level' => 5, 'name' => '尊享版', 'ttl' => 1],
];
public function __construct($config)
{
$this->AccessKeyId = $config['ak'];
$this->SecretAccessKey = $config['sk'];
$this->domain = $config['domain'];
$this->domainid = $config['domainid'];
}
public function getError()
{
return $this->error;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$query = ['PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'Key' => $KeyWord];
$data = $this->send_reuqest('GET', 'ListZones', $query);
if ($data) {
$list = [];
if (!empty($data['Zones'])) {
foreach ($data['Zones'] as $row) {
$list[] = [
'DomainId' => $row['ZID'],
'Domain' => $row['ZoneName'],
'RecordCount' => $row['RecordCount'],
];
}
}
return ['total' => $data['Total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$query = ['ZID' => intval($this->domainid), 'PageNumber' => $PageNumber, 'PageSize' => $PageSize, 'SearchOrder' => 'desc'];
if (!empty($SubDomain) || !empty($Type) || !empty($Line) || !empty($Value)) {
$query += ['Host' => $SubDomain, 'Value' => $Value, 'Type' => $Type, 'Line' => $Line];
} elseif (!empty($KeyWord)) {
$query += ['Host' => $KeyWord];
}
$data = $this->send_reuqest('GET', 'ListRecords', $query);
if ($data) {
$list = [];
foreach ($data['Records'] as $row) {
if ($row['Type'] == 'MX') {
list($row['MX'], $row['Value']) = explode(' ', $row['Value']);
}
$list[] = [
'RecordId' => $row['RecordID'],
'Domain' => $this->domain,
'Name' => $row['Host'],
'Type' => $row['Type'],
'Value' => $row['Value'],
'Line' => $row['Line'],
'TTL' => $row['TTL'],
'MX' => isset($row['MX']) ? $row['MX'] : null,
'Status' => $row['Enable'] ? '1' : '0',
'Weight' => $row['Weight'],
'Remark' => $row['Remark'],
'UpdateTime' => $row['UpdatedAt'],
];
}
return ['total' => $data['TotalCount'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
$data = $this->send_reuqest('GET', 'QueryRecord', ['RecordID' => $RecordId]);
if ($data) {
if ($data['name'] == $data['zone_name']) {
$data['name'] = '@';
}
if ($data['Type'] == 'MX') {
list($data['MX'], $data['Value']) = explode(' ', $data['Value']);
}
return [
'RecordId' => $data['RecordID'],
'Domain' => $this->domain,
'Name' => $data['Host'],
'Type' => $data['Type'],
'Value' => $data['Value'],
'Line' => $data['Line'],
'TTL' => $data['TTL'],
'MX' => isset($data['MX']) ? $data['MX'] : null,
'Status' => $data['Enable'] ? '1' : '0',
'Weight' => $data['Weight'],
'Remark' => $data['Remark'],
'UpdateTime' => $data['UpdatedAt'],
];
}
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$params = ['ZID' => intval($this->domainid), 'Host' => $Name, 'Type' => $this->convertType($Type), 'Value' => $Value, 'Line' => $Line, 'TTL' => intval($TTL), 'Remark' => $Remark];
if ($Type == 'MX') {
$params['Value'] = intval($MX) . ' ' . $Value;
}
if ($Weight > 0) {
$params['Weight'] = $Weight;
}
$data = $this->send_reuqest('POST', 'CreateRecord', $params);
return is_array($data) ? $data['RecordID'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$params = ['RecordID' => $RecordId, 'Host' => $Name, 'Type' => $this->convertType($Type), 'Value' => $Value, 'Line' => $Line, 'TTL' => intval($TTL), 'Remark' => $Remark];
if ($Type == 'MX') {
$params['Value'] = intval($MX) . ' ' . $Value;
}
if ($Weight > 0) {
$params['Weight'] = $Weight;
}
$data = $this->send_reuqest('POST', 'UpdateRecord', $params);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$data = $this->send_reuqest('POST', 'DeleteRecord', ['RecordID' => $RecordId]);
return $data;
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$params = ['RecordID' => $RecordId, 'Enable' => $Status == '1'];
$data = $this->send_reuqest('POST', 'UpdateRecordStatus', $params);
return is_array($data);
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
return false;
}
//获取解析线路列表
public function getRecordLine()
{
$domainInfo = $this->getDomainInfo();
if (!$domainInfo) {
return false;
}
$level = $this->getTradeInfo($domainInfo['TradeCode'])['level'];
$data = $this->send_reuqest('GET', 'ListLines', []);
if ($data) {
$list = [];
$list['default'] = ['name' => '默认', 'parent' => null];
foreach ($data['Lines'] as $row) {
if ($row['Value'] == 'default') {
continue;
}
if ($row['Level'] > $level) {
continue;
}
$list[$row['Value']] = ['name' => $row['Name'], 'parent' => isset($row['FatherValue']) ? $row['FatherValue'] : null];
}
$data = $this->send_reuqest('GET', 'ListCustomLines', []);
if ($data && $data['TotalCount'] > 0) {
$list['N.customer_lines'] = ['name' => '自定义线路', 'parent' => null];
foreach ($data['CustomerLines'] as $row) {
$list[$row['Line']] = ['name' => $row['NameCN'], 'parent' => 'N.customer_lines'];
}
}
return $list;
}
return false;
}
//获取域名概览信息
public function getDomainInfo()
{
if (!empty($this->domainInfo)) {
return $this->domainInfo;
}
$query = ['ZID' => intval($this->domainid)];
$data = $this->send_reuqest('GET', 'QueryZone', $query);
if ($data) {
$this->domainInfo = $data;
return $data;
}
return false;
}
//获取域名最低TTL
public function getMinTTL()
{
$domainInfo = $this->getDomainInfo();
if ($domainInfo) {
$ttl = $this->getTradeInfo($domainInfo['TradeCode'])['ttl'];
return $ttl;
}
return false;
}
private function convertType($type)
{
return $type;
}
private function getTradeInfo($trade_code)
{
if (array_key_exists($trade_code, self::$trade_code_list)) {
$trade_code = $trade_code;
} else {
$trade_code = 'free_inner';
}
return self::$trade_code_list[$trade_code];
}
private function send_reuqest($method, $action, $params = [])
{
if (!empty($params)) {
$params = array_filter($params, function ($a) { return $a !== null;});
}
$query = [
'Action' => $action,
'Version' => $this->version,
];
$body = '';
if ($method == 'GET') {
$query = array_merge($query, $params);
} else {
$body = !empty($params) ? json_encode($params) : '';
}
$time = time();
$headers = [
'Host' => $this->endpoint,
'X-Date' => gmdate("Ymd\THis\Z", $time),
//'X-Content-Sha256' => hash("sha256", $body),
];
if ($body) {
$headers['Content-Type'] = 'application/json';
}
$path = '/';
$authorization = $this->generateSign($method, $path, $query, $headers, $body, $time);
$headers['Authorization'] = $authorization;
$url = 'https://'.$this->endpoint.$path.'?'.http_build_query($query);
$header = [];
foreach ($headers as $key => $value) {
$header[] = $key.': '.$value;
}
return $this->curl($method, $url, $body, $header);
}
private function generateSign($method, $path, $query, $headers, $body, $time)
{
$algorithm = "HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = $method;
$canonicalUri = $path;
if (substr($canonicalUri, -1) != "/") {
$canonicalUri .= "/";
}
$canonicalQueryString = $this->getCanonicalQueryString($query);
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
$hashedRequestPayload = hash("sha256", $body);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// step 2: build string to sign
$date = gmdate("Ymd\THis\Z", $time);
$shortDate = substr($date, 0, 8);
$credentialScope = $shortDate . '/' .$this->region . '/' . $this->service . '/request';
$hashedCanonicalRequest = hash("sha256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$date."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// step 3: sign string
$kDate = hash_hmac("sha256", $shortDate, $this->SecretAccessKey, true);
$kRegion = hash_hmac("sha256", $this->region, $kDate, true);
$kService = hash_hmac("sha256", $this->service, $kRegion, true);
$kSigning = hash_hmac("sha256", "request", $kService, true);
$signature = hash_hmac("sha256", $stringToSign, $kSigning);
// step 4: build authorization
$credential = $this->AccessKeyId . '/' . $shortDate . '/' . $this->region . '/' . $this->service . '/request';
$authorization = $algorithm . ' Credential=' . $credential . ", SignedHeaders=" . $signedHeaders . ", Signature=" . $signature;
return $authorization;
}
private function escape($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
private function getCanonicalQueryString($parameters)
{
if (empty($parameters)) {
return '';
}
ksort($parameters);
$canonicalQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalQueryString .= '&' . $this->escape($key). '=' . $this->escape($value);
}
return substr($canonicalQueryString, 1);
}
private function getCanonicalHeaders($oldheaders)
{
$headers = array();
foreach ($oldheaders as $key => $value) {
$headers[strtolower($key)] = trim($value);
}
ksort($headers);
$canonicalHeaders = '';
$signedHeaders = '';
foreach ($headers as $key => $value) {
$canonicalHeaders .= $key . ':' . $value . "\n";
$signedHeaders .= $key . ';';
}
$signedHeaders = substr($signedHeaders, 0, -1);
return [$canonicalHeaders, $signedHeaders];
}
private function curl($method, $url, $body, $header)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if (!empty($body)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) {
return false;
}
$arr = json_decode($response, true);
if ($arr) {
if (isset($arr['ResponseMetadata']['Error']['MessageCN'])) {
$this->setError($arr['ResponseMetadata']['Error']['MessageCN']);
return false;
} elseif (isset($arr['ResponseMetadata']['Error']['Message'])) {
$this->setError($arr['ResponseMetadata']['Error']['Message']);
return false;
} elseif (isset($arr['Result'])) {
return $arr['Result'];
} else {
return true;
}
} else {
$this->setError('返回数据解析失败');
return false;
}
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,209 +1,235 @@
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
/**
* @see http://apipost.west.cn/
*/
class west implements DnsInterface {
private $username;
private $api_password;
private $baseUrl = 'https://api.west.cn/api/v2';
private $error;
private $domain;
private $domainid;
function __construct($config){
$this->username = $config['ak'];
$this->api_password = $config['sk'];
$this->domain = $config['domain'];
}
public function getError(){
return $this->error;
}
public function check(){
if($this->getDomainList() != false){
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord=null, $PageNumber=1, $PageSize=20){
$param = ['act' => 'getdomains', 'page' => $PageNumber, 'limit' => $PageSize, 'domain' => $KeyWord];
$data = $this->execute('/domain/', $param);
if($data){
$list = [];
foreach($data['items'] as $row){
$list[] = [
'DomainId' => $row['domain'],
'Domain' => $row['domain'],
'RecordCount' => 0,
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber=1, $PageSize=20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null){
$param = ['act' => 'getdnsrecord', 'domain' => $this->domain, 'type' => $Type, 'line' => $Line, 'host' => $KeyWord, 'value' => $Value, 'pageno' => $PageNumber, 'limit' => $PageSize];
if(!isNullOrEmpty(($SubDomain))){
$param['host'] = $SubDomain;
}
$data = $this->execute('/domain/', $param);
if($data){
$list = [];
foreach($data['items'] as $row){
$list[] = [
'RecordId' => $row['id'],
'Domain' => $this->domain,
'Name' => $row['item'],
'Type' => $row['type'],
'Value' => $row['value'],
'Line' => $row['line'],
'TTL' => $row['ttl'],
'MX' => $row['level'],
'Status' => $row['pause'] == 1 ? '0' : '1',
'Weight' => null,
'Remark' => null,
'UpdateTime' => null,
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber=1, $PageSize=20, $Type = null, $Line = null){
if($SubDomain == '')$SubDomain='@';
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId){
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$param = ['act' => 'adddnsrecord', 'domain' => $this->domain, 'host' => $Name, 'type' => $this->convertType($Type), 'value' => $Value, 'level' => $MX, 'ttl' => intval($TTL), 'line' => $Line];
$data = $this->execute('/domain/', $param);
return is_array($data) ? $data['id'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null){
$param = ['act' => 'moddnsrecord', 'domain' => $this->domain, 'id' => $RecordId, 'type' => $this->convertType($Type), 'value' => $Value, 'level' => $MX, 'ttl' => intval($TTL), 'line' => $Line];
$data = $this->execute('/domain/', $param);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark){
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId){
$param = ['act' => 'deldnsrecord', 'domain' => $this->domain, 'id' => $RecordId];
$data = $this->execute('/domain/', $param);
return is_array($data);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status){
$param = ['act' => 'pause', 'domain' => $this->domain, 'id' => $RecordId, 'val' => $Status == '1' ? '0' : '1'];
$data = $this->execute('/domain/', $param);
return $data !== false;
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null){
return false;
}
//获取解析线路列表
public function getRecordLine(){
return [
''=>['name'=>'默认', 'parent'=>null],
'LTEL'=>['name'=>'电信', 'parent'=>null],
'LCNC'=>['name'=>'联通', 'parent'=>null],
'LMOB'=>['name'=>'移动', 'parent'=>null],
'LEDU'=>['name'=>'教育网', 'parent'=>null],
'LSEO'=>['name'=>'搜索引擎', 'parent'=>null],
'LFOR'=>['name'=>'境外', 'parent'=>null],
];
}
//获取域名信息
public function getDomainInfo(){
return false;
}
//获取域名最低TTL
public function getMinTTL(){
return false;
}
private function convertType($type){
return $type;
}
private function execute($path, $params){
$params['username'] = $this->username;
$params['time'] = $this->getMillisecond();
$params['token'] = md5($this->username.$this->api_password.$params['time']);
$response = $this->curl($path, $params);
$response = mb_convert_encoding($response, 'UTF-8', 'GBK');
$arr=json_decode($response,true);
if($arr){
if($arr['result'] == 200){
return isset($arr['data']) ? $arr['data'] : [];
}else{
$this->setError($arr['msg']);
return false;
}
}else{
$this->setError('返回数据解析失败');
return false;
}
}
private function curl($path, $params = null){
$url = $this->baseUrl . $path;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
if ($params) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) return false;
return $response;
}
private function getMillisecond()
{
list($s1, $s2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
private function setError($message){
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}
<?php
namespace app\lib\dns;
use app\lib\DnsInterface;
/**
* @see http://apipost.west.cn/
*/
class west implements DnsInterface
{
private $username;
private $api_password;
private $baseUrl = 'https://api.west.cn/api/v2';
private $error;
private $domain;
private $domainid;
public function __construct($config)
{
$this->username = $config['ak'];
$this->api_password = $config['sk'];
$this->domain = $config['domain'];
}
public function getError()
{
return $this->error;
}
public function check()
{
if ($this->getDomainList() != false) {
return true;
}
return false;
}
//获取域名列表
public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20)
{
$param = ['act' => 'getdomains', 'page' => $PageNumber, 'limit' => $PageSize, 'domain' => $KeyWord];
$data = $this->execute('/domain/', $param);
if ($data) {
$list = [];
foreach ($data['items'] as $row) {
$list[] = [
'DomainId' => $row['domain'],
'Domain' => $row['domain'],
'RecordCount' => 0,
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取解析记录列表
public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null)
{
$param = ['act' => 'getdnsrecord', 'domain' => $this->domain, 'type' => $Type, 'line' => $Line, 'host' => $KeyWord, 'value' => $Value, 'pageno' => $PageNumber, 'limit' => $PageSize];
if (!isNullOrEmpty(($SubDomain))) {
$param['host'] = $SubDomain;
}
$data = $this->execute('/domain/', $param);
if ($data) {
$list = [];
foreach ($data['items'] as $row) {
$list[] = [
'RecordId' => $row['id'],
'Domain' => $this->domain,
'Name' => $row['item'],
'Type' => $row['type'],
'Value' => $row['value'],
'Line' => $row['line'],
'TTL' => $row['ttl'],
'MX' => $row['level'],
'Status' => $row['pause'] == 1 ? '0' : '1',
'Weight' => null,
'Remark' => null,
'UpdateTime' => null,
];
}
return ['total' => $data['total'], 'list' => $list];
}
return false;
}
//获取子域名解析记录列表
public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null)
{
if ($SubDomain == '') {
$SubDomain = '@';
}
return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line);
}
//获取解析记录详细信息
public function getDomainRecordInfo($RecordId)
{
return false;
}
//添加解析记录
public function addDomainRecord($Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$param = ['act' => 'adddnsrecord', 'domain' => $this->domain, 'host' => $Name, 'type' => $this->convertType($Type), 'value' => $Value, 'level' => $MX, 'ttl' => intval($TTL), 'line' => $Line];
$data = $this->execute('/domain/', $param);
return is_array($data) ? $data['id'] : false;
}
//修改解析记录
public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = '0', $TTL = 600, $MX = 1, $Weight = null, $Remark = null)
{
$param = ['act' => 'moddnsrecord', 'domain' => $this->domain, 'id' => $RecordId, 'type' => $this->convertType($Type), 'value' => $Value, 'level' => $MX, 'ttl' => intval($TTL), 'line' => $Line];
$data = $this->execute('/domain/', $param);
return is_array($data);
}
//修改解析记录备注
public function updateDomainRecordRemark($RecordId, $Remark)
{
return false;
}
//删除解析记录
public function deleteDomainRecord($RecordId)
{
$param = ['act' => 'deldnsrecord', 'domain' => $this->domain, 'id' => $RecordId];
$data = $this->execute('/domain/', $param);
return is_array($data);
}
//设置解析记录状态
public function setDomainRecordStatus($RecordId, $Status)
{
$param = ['act' => 'pause', 'domain' => $this->domain, 'id' => $RecordId, 'val' => $Status == '1' ? '0' : '1'];
$data = $this->execute('/domain/', $param);
return $data !== false;
}
//获取解析记录操作日志
public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null)
{
return false;
}
//获取解析线路列表
public function getRecordLine()
{
return [
'' => ['name' => '默认', 'parent' => null],
'LTEL' => ['name' => '电信', 'parent' => null],
'LCNC' => ['name' => '联通', 'parent' => null],
'LMOB' => ['name' => '移动', 'parent' => null],
'LEDU' => ['name' => '教育网', 'parent' => null],
'LSEO' => ['name' => '搜索引擎', 'parent' => null],
'LFOR' => ['name' => '境外', 'parent' => null],
];
}
//获取域名信息
public function getDomainInfo()
{
return false;
}
//获取域名最低TTL
public function getMinTTL()
{
return false;
}
private function convertType($type)
{
return $type;
}
private function execute($path, $params)
{
$params['username'] = $this->username;
$params['time'] = $this->getMillisecond();
$params['token'] = md5($this->username.$this->api_password.$params['time']);
$response = $this->curl($path, $params);
$response = mb_convert_encoding($response, 'UTF-8', 'GBK');
$arr = json_decode($response, true);
if ($arr) {
if ($arr['result'] == 200) {
return isset($arr['data']) ? $arr['data'] : [];
} else {
$this->setError($arr['msg']);
return false;
}
} else {
$this->setError('返回数据解析失败');
return false;
}
}
private function curl($path, $params = null)
{
$url = $this->baseUrl . $path;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
if ($params) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
}
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
$this->setError('Curl error: ' . curl_error($ch));
}
curl_close($ch);
if ($errno) {
return false;
}
return $response;
}
private function getMillisecond()
{
list($s1, $s2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
private function setError($message)
{
$this->error = $message;
//file_put_contents('logs.txt',date('H:i:s').' '.$message."\r\n", FILE_APPEND);
}
}

View File

@ -1,72 +1,77 @@
<?php
namespace app\lib\mail;
class Aliyun
{
private $AccessKeyId;
private $AccessKeySecret;
private $AccessKeyId;
private $AccessKeySecret;
function __construct($AccessKeyId, $AccessKeySecret)
{
$this->AccessKeyId = $AccessKeyId;
$this->AccessKeySecret = $AccessKeySecret;
}
private function aliyunSignature($parameters, $accessKeySecret, $method)
{
ksort($parameters);
$canonicalizedQueryString = '';
foreach ($parameters as $key => $value) {
if($value === null) continue;
$canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
}
$stringToSign = $method . '&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&", true));
public function __construct($AccessKeyId, $AccessKeySecret)
{
$this->AccessKeyId = $AccessKeyId;
$this->AccessKeySecret = $AccessKeySecret;
}
private function aliyunSignature($parameters, $accessKeySecret, $method)
{
ksort($parameters);
$canonicalizedQueryString = '';
foreach ($parameters as $key => $value) {
if ($value === null) {
continue;
}
$canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
}
$stringToSign = $method . '&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&", true));
return $signature;
}
private function percentEncode($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
public function send($to, $sub, $msg, $from, $from_name)
{
if (empty($this->AccessKeyId) || empty($this->AccessKeySecret)) return false;
$url = 'https://dm.aliyuncs.com/';
$data = array(
'Action' => 'SingleSendMail',
'AccountName' => $from,
'ReplyToAddress' => 'false',
'AddressType' => 1,
'ToAddress' => $to,
'FromAlias' => $from_name,
'Subject' => $sub,
'HtmlBody' => $msg,
'Format' => 'JSON',
'Version' => '2015-11-23',
'AccessKeyId' => $this->AccessKeyId,
'SignatureMethod' => 'HMAC-SHA1',
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'SignatureVersion' => '1.0',
'SignatureNonce' => random(8)
);
$data['Signature'] = $this->aliyunSignature($data, $this->AccessKeySecret, 'POST');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$arr = json_decode($json, true);
if ($httpCode == 200) {
return true;
} else {
return $arr['Message'];
}
}
}
return $signature;
}
private function percentEncode($str)
{
$search = ['+', '*', '%7E'];
$replace = ['%20', '%2A', '~'];
return str_replace($search, $replace, urlencode($str));
}
public function send($to, $sub, $msg, $from, $from_name)
{
if (empty($this->AccessKeyId) || empty($this->AccessKeySecret)) {
return false;
}
$url = 'https://dm.aliyuncs.com/';
$data = array(
'Action' => 'SingleSendMail',
'AccountName' => $from,
'ReplyToAddress' => 'false',
'AddressType' => 1,
'ToAddress' => $to,
'FromAlias' => $from_name,
'Subject' => $sub,
'HtmlBody' => $msg,
'Format' => 'JSON',
'Version' => '2015-11-23',
'AccessKeyId' => $this->AccessKeyId,
'SignatureMethod' => 'HMAC-SHA1',
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'SignatureVersion' => '1.0',
'SignatureNonce' => random(8)
);
$data['Signature'] = $this->aliyunSignature($data, $this->AccessKeySecret, 'POST');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$arr = json_decode($json, true);
if ($httpCode == 200) {
return true;
} else {
return $arr['Message'];
}
}
}

View File

@ -1,2 +1,11 @@
<?php
namespace app\lib\mail\PHPMailer; class Exception extends \Exception { public function errorMessage() { return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n"; } }
namespace app\lib\mail\PHPMailer;
class Exception extends \Exception
{
public function errorMessage()
{
return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n";
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,37 +1,43 @@
<?php
namespace app\lib\mail;
class Sendcloud {
private $apiUser;
private $apiKey;
class Sendcloud
{
private $apiUser;
private $apiKey;
function __construct($apiUser, $apiKey){
public function __construct($apiUser, $apiKey)
{
$this->apiUser = $apiUser;
$this->apiKey = $apiKey;
}
public function send($to, $sub, $msg, $from, $from_name){
if(empty($this->apiUser)||empty($this->apiKey))return false;
$url='http://api.sendcloud.net/apiv2/mail/send';
$data=array(
'apiUser' => $this->apiUser,
'apiKey' => $this->apiKey,
'from' => $from,
'fromName' => $from_name,
'to' => $to,
'subject' => $sub,
'html' => $msg);
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$json=curl_exec($ch);
curl_close($ch);
$arr=json_decode($json,true);
if($arr['statusCode']==200){
return true;
}else{
return implode("\n",$arr['message']);
}
}
public function send($to, $sub, $msg, $from, $from_name)
{
if (empty($this->apiUser) || empty($this->apiKey)) {
return false;
}
$url = 'http://api.sendcloud.net/apiv2/mail/send';
$data = array(
'apiUser' => $this->apiUser,
'apiKey' => $this->apiKey,
'from' => $from,
'fromName' => $from_name,
'to' => $to,
'subject' => $sub,
'html' => $msg);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$json = curl_exec($ch);
curl_close($ch);
$arr = json_decode($json, true);
if ($arr['statusCode'] == 200) {
return true;
} else {
return implode("\n", $arr['message']);
}
}
}

View File

@ -1,4 +1,5 @@
<?php
// 全局中间件定义文件
return [
// 全局请求缓存

View File

@ -1,40 +1,47 @@
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\Db;
class AuthApi
{
public function handle($request, \Closure $next)
{
$uid = input('post.uid/d');
$timestamp = input('post.timestamp');
$sign = input('post.sign');
if(!$uid || empty($timestamp) || empty($sign)){
return json(['code'=>-1, 'msg'=>'认证参数不能为空'])->code(403);
}
if($timestamp < time()-300 || $timestamp > time()+300){
return json(['code'=>-1, 'msg'=>'时间戳不合法'])->code(403);
}
$user = Db::name('user')->where('id', $uid)->find();
if(!$user) return json(['code'=>-1, 'msg'=>'用户不存在'])->code(403);
if($user['status'] == 0) return json(['code'=>-1, 'msg'=>'该用户已被封禁'])->code(403);
if($user['is_api'] == 0) return json(['code'=>-1, 'msg'=>'该用户未开启API权限'])->code(403);
if(md5($uid.$timestamp.$user['apikey']) !== $sign){
return json(['code'=>-1, 'msg'=>'签名错误'])->code(403);
}
$user['type'] = 'user';
$user['permission'] = [];
if($user['level'] == 1){
$user['permission'] = Db::name('permission')->where('uid', $uid)->column('domain');
}
$request->islogin = true;
$request->isApi = true;
$request->user = $user;
return $next($request);
}
}
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\Db;
class AuthApi
{
public function handle($request, \Closure $next)
{
$uid = input('post.uid/d');
$timestamp = input('post.timestamp');
$sign = input('post.sign');
if (!$uid || empty($timestamp) || empty($sign)) {
return json(['code' => -1, 'msg' => '认证参数不能为空'])->code(403);
}
if ($timestamp < time() - 300 || $timestamp > time() + 300) {
return json(['code' => -1, 'msg' => '时间戳不合法'])->code(403);
}
$user = Db::name('user')->where('id', $uid)->find();
if (!$user) {
return json(['code' => -1, 'msg' => '用户不存在'])->code(403);
}
if ($user['status'] == 0) {
return json(['code' => -1, 'msg' => '该用户已被封禁'])->code(403);
}
if ($user['is_api'] == 0) {
return json(['code' => -1, 'msg' => '该用户未开启API权限'])->code(403);
}
if (md5($uid.$timestamp.$user['apikey']) !== $sign) {
return json(['code' => -1, 'msg' => '签名错误'])->code(403);
}
$user['type'] = 'user';
$user['permission'] = [];
if ($user['level'] == 1) {
$user['permission'] = Db::name('permission')->where('uid', $uid)->column('domain');
}
$request->islogin = true;
$request->isApi = true;
$request->user = $user;
return $next($request);
}
}

View File

@ -1,52 +1,53 @@
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\Db;
class AuthUser
{
public function handle($request, \Closure $next)
{
$islogin = false;
$cookie = cookie('user_token');
$user = null;
if($cookie && config_get('sys_key')){
$token=authcode($cookie, 'DECODE', config_get('sys_key'));
if($token){
list($type, $uid, $sid, $expiretime) = explode("\t", $token);
if($type == 'user'){
$user = Db::name('user')->where('id', $uid)->find();
if($user && $user['status']==1){
$session=md5($user['id'].$user['password']);
if($session==$sid && $expiretime>time()) {
$islogin = true;
}
$user['type'] = 'user';
$user['permission'] = [];
if($user['level'] == 1){
$user['permission'] = Db::name('permission')->where('uid', $uid)->column('domain');
}
}
}elseif($type == 'domain'){
$user = Db::name('domain')->where('id', $uid)->find();
if($user && $user['is_sso']==1){
$session=md5($user['id'].$user['name']);
if($session==$sid && $expiretime>time()) {
$islogin = true;
}
$user['username'] = $user['name'];
$user['regtime'] = $user['addtime'];
$user['type'] = 'domain';
$user['level'] = 0;
$user['permission'] = [$user['name']];
}
}
}
}
$request->islogin = $islogin;
$request->user = $user;
return $next($request);
}
}
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\Db;
class AuthUser
{
public function handle($request, \Closure $next)
{
$islogin = false;
$cookie = cookie('user_token');
$user = null;
if ($cookie && config_get('sys_key')) {
$token = authcode($cookie, 'DECODE', config_get('sys_key'));
if ($token) {
list($type, $uid, $sid, $expiretime) = explode("\t", $token);
if ($type == 'user') {
$user = Db::name('user')->where('id', $uid)->find();
if ($user && $user['status'] == 1) {
$session = md5($user['id'].$user['password']);
if ($session == $sid && $expiretime > time()) {
$islogin = true;
}
$user['type'] = 'user';
$user['permission'] = [];
if ($user['level'] == 1) {
$user['permission'] = Db::name('permission')->where('uid', $uid)->column('domain');
}
}
} elseif ($type == 'domain') {
$user = Db::name('domain')->where('id', $uid)->find();
if ($user && $user['is_sso'] == 1) {
$session = md5($user['id'].$user['name']);
if ($session == $sid && $expiretime > time()) {
$islogin = true;
}
$user['username'] = $user['name'];
$user['regtime'] = $user['addtime'];
$user['type'] = 'domain';
$user['level'] = 0;
$user['permission'] = [$user['name']];
}
}
}
}
$request->islogin = $islogin;
$request->user = $user;
return $next($request);
}
}

View File

@ -1,19 +1,19 @@
<?php
declare (strict_types=1);
namespace app\middleware;
class CheckLogin
{
public function handle($request, \Closure $next)
{
if (!request()->islogin) {
if ($request->isAjax() || !$request->isGet()) {
return json(['code'=>-1, 'msg'=>'未登录'])->code(401);
}
return redirect((string)url('/login'));
}
return $next($request);
}
}
<?php
declare (strict_types=1);
namespace app\middleware;
class CheckLogin
{
public function handle($request, \Closure $next)
{
if (!$request->islogin) {
if ($request->isAjax() || !$request->isGet()) {
return json(['code' => -1, 'msg' => '未登录'])->code(401);
}
return redirect((string)url('/login'));
}
return $next($request);
}
}

View File

@ -1,5 +1,6 @@
<?php
declare (strict_types = 1);
declare (strict_types=1);
namespace app\middleware;
@ -19,27 +20,27 @@ class LoadConfig
*/
public function handle($request, \Closure $next)
{
if (!file_exists(app()->getRootPath().'.env')){
if(strpos(request()->url(),'/install')===false){
if (!file_exists(app()->getRootPath().'.env')) {
if (strpos($this->request->url(), '/install') === false) {
return redirect((string)url('/install'))->header([
'Cache-Control' => 'no-store, no-cache, must-revalidate',
'Pragma' => 'no-cache',
]);
}else{
} else {
return $next($request);
}
}
try{
$res = Db::name('config')->cache('configs',0)->column('value','key');
if(empty($res['sys_key']) && !empty(env('app.sys_key'))){
try {
$res = Db::name('config')->cache('configs', 0)->column('value', 'key');
if (empty($res['sys_key']) && !empty(env('app.sys_key'))) {
config_set('sys_key', env('app.sys_key'));
Cache::delete('configs');
$res['sys_key'] = env('app.sys_key');
}
Config::set($res, 'sys');
}catch(Exception $e){
if(!strpos($e->getMessage(), 'doesn\'t exist')){
} catch (Exception $e) {
if (!strpos($e->getMessage(), 'doesn\'t exist')) {
throw $e;
}
}

View File

@ -1,24 +1,25 @@
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\View;
class RefererCheck
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
if(!checkRefererHost()){
return response('Access Denied', 403);
}
return $next($request);
}
}
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\View;
class RefererCheck
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
if (!checkRefererHost()) {
return response('Access Denied', 403);
}
return $next($request);
}
}

View File

@ -1,25 +1,26 @@
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\View;
class ViewOutput
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
View::assign('islogin', $request->islogin);
View::assign('user', $request->user);
View::assign('cdnpublic', 'https://s4.zstatic.net/ajax/libs/');
View::assign('skin', getAdminSkin());
return $next($request);
}
}
<?php
declare (strict_types=1);
namespace app\middleware;
use think\facade\View;
class ViewOutput
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
View::assign('islogin', $request->islogin);
View::assign('user', $request->user);
View::assign('cdnpublic', 'https://s4.zstatic.net/ajax/libs/');
View::assign('skin', getAdminSkin());
return $next($request);
}
}

View File

@ -1,4 +1,5 @@
<?php
use app\ExceptionHandle;
use app\Request;

View File

@ -56,7 +56,7 @@ a{color:#444}
<div class="input-group-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></div>
<input type="text" class="form-control input-lg" placeholder="验证码" name="code" autocomplete="off" required="required"/>
<span class="input-group-addon" style="padding: 0">
<img id="verifycode" src="/verifycode" height="45" onclick="this.src='/verifycode?r='+Math.random();" title="点击更换验证码">
<img id="verifycode" src="{:captcha_src()}" height="45" onclick="this.src='{:captcha_src()}?r='+Math.random();" title="点击更换验证码">
</span>
</div>
<div class="form-group">

View File

@ -34,8 +34,8 @@ tbody tr>td:nth-child(4){overflow: hidden;text-overflow: ellipsis;white-space: n
<script src="{$cdnpublic}bootstrap-table/1.21.4/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
<script src="/static/js/custom.js"></script>
<script>
var action_name = {$info.action_name|json_encode|raw};
$(document).ready(function(){
const action_name = {$info.action_name | json_encode | raw};
$(document).ready(function(){
updateToolbar();
const defaultPageSize = 15;
const pageNumber = typeof window.$_GET['pageNumber'] != 'undefined' ? parseInt(window.$_GET['pageNumber']) : 1;

View File

@ -22,16 +22,21 @@
"require": {
"php": ">=8.0.0",
"ext-pdo": "*",
"ext-gd": "*",
"ext-curl": "*",
"topthink/framework": "^8.0",
"topthink/think-orm": "^3.0",
"topthink/think-filesystem": "^2.0",
"topthink/think-view": "^2.0",
"cccyun/think-captcha": "^3.0"
"topthink/think-captcha": "^3.0",
"guzzlehttp/guzzle": "^7.9",
"coolxitech/cloudflare-sdk": "dev-master"
},
"require-dev": {
"symfony/var-dumper": "^4.2",
"topthink/think-trace":"^1.0",
"swoole/ide-helper": "^5.1"
"swoole/ide-helper": "^5.1",
"friendsofphp/php-cs-fixer": "^3.64.0"
},
"autoload": {
"psr-4": {
@ -50,10 +55,12 @@
"@php think vendor:publish"
]
},
"repositories": {
"packagist": {
"repositories": [
{
"description": "阿里云镜像",
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
"url": "https://mirrors.aliyun.com/composer/",
"canonical": false
}
}
]
}

View File

@ -7,7 +7,7 @@ return [
//验证码位数
'length' => 4,
// 验证码字符集合
'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
'codeSet' => '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
// 验证码过期时间
'expire' => 1800,
// 是否使用中文验证码
@ -30,7 +30,8 @@ return [
'imageH' => 0,
// 验证码图片宽度
'imageW' => 0,
// 验证成功后是否重置
'reset' => true,
// 添加额外的验证码设置
// verify => [
// 'length'=>4,

View File

@ -8,19 +8,23 @@
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use app\middleware\AuthApi;
use app\middleware\CheckLogin;
use app\middleware\ViewOutput;
use think\facade\Route;
use think\middleware\SessionInit;
Route::pattern([
'id' => '\d+',
]);
Route::any('/install', 'install/index')
->middleware(\app\middleware\ViewOutput::class);
->middleware(ViewOutput::class);
Route::get('/verifycode', 'auth/verifycode')->middleware(\think\middleware\SessionInit::class)
->middleware(\app\middleware\ViewOutput::class);
Route::any('/login', 'auth/login')->middleware(\think\middleware\SessionInit::class)
->middleware(\app\middleware\ViewOutput::class);
Route::get('/verifycode', 'auth/verifycode')->middleware(SessionInit::class)
->middleware(ViewOutput::class);
Route::any('/login', 'auth/login')->middleware(SessionInit::class)
->middleware(ViewOutput::class);
Route::get('/logout', 'auth/logout');
Route::any('/quicklogin', 'auth/quicklogin');
Route::any('/dmtask/status', 'dmonitor/status');
@ -80,8 +84,8 @@ Route::group(function () {
Route::get('/optimizeip/opiplist', 'optimizeip/opiplist');
Route::any('/optimizeip/opipform/:action', 'optimizeip/opipform');
})->middleware(\app\middleware\CheckLogin::class)
->middleware(\app\middleware\ViewOutput::class);
})->middleware(CheckLogin::class)
->middleware(ViewOutput::class);
Route::group('api', function () {
Route::post('/domain/:id', 'domain/domain_info');
@ -95,7 +99,7 @@ Route::group('api', function () {
Route::post('/record/remark/:id', 'domain/record_remark');
Route::post('/record/batch/:id', 'domain/record_batch');
})->middleware(\app\middleware\AuthApi::class);
})->middleware(AuthApi::class);
Route::miss(function() {
return response('404 Not Found')->code(404);