From 1bc9e594e261b66cdf607818b13d2f9ea98cf71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Mon, 27 Apr 2026 13:18:55 +0900 Subject: [PATCH] =?UTF-8?q?=E6=B2=A2=E5=B1=B1=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + config/config.sample.php | 3 +- public/static/style-openprovider.css | 25 ++ route.php | 12 + src/Site/Controller/Mods.php | 7 + src/Site/Controller/Op.php | 341 ++++++++++++++++++++++++ src/Site/Controller/Page.php | 12 +- src/Std/Lib/Curl.php | 102 ++----- src/Std/Lib/Openprovider.php | 310 +++++++++++++++------ view/404.maron | 2 +- view/openprovider/checkdomain.maron | 53 ++++ view/openprovider/editdns.maron | 34 +++ view/openprovider/getdns.maron | 150 +++++++++++ view/openprovider/getdomainprices.maron | 3 + view/openprovider/gettld.maron | 3 + view/openprovider/index.maron | 20 ++ view/openprovider/listdnszones.maron | 32 +++ view/openprovider/listtlds.maron | 3 + view/openprovider/nopermission.maron | 3 + view/openprovider/registerdomain.maron | 0 view/openprovider/searchcustomer.maron | 29 ++ 21 files changed, 971 insertions(+), 175 deletions(-) create mode 100644 public/static/style-openprovider.css create mode 100644 src/Site/Controller/Op.php create mode 100644 view/openprovider/checkdomain.maron create mode 100644 view/openprovider/editdns.maron create mode 100644 view/openprovider/getdns.maron create mode 100644 view/openprovider/getdomainprices.maron create mode 100644 view/openprovider/gettld.maron create mode 100644 view/openprovider/index.maron create mode 100644 view/openprovider/listdnszones.maron create mode 100644 view/openprovider/listtlds.maron create mode 100644 view/openprovider/nopermission.maron create mode 100644 view/openprovider/registerdomain.maron create mode 100644 view/openprovider/searchcustomer.maron diff --git a/.gitignore b/.gitignore index d47b847..c578c40 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ data/*.pem data/*.txt +data/*.json +data/cache/*.json data/user/*.json log/*.txt public/static/user diff --git a/config/config.sample.php b/config/config.sample.php index c4404d6..10966c8 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -25,7 +25,7 @@ define('OPENPROVIDER', [ 'username' => '', 'password' => '', 'ip' => '0.0.0.0', - 'owner_handle' => 'HK912631-JP', + 'owner_handle' => '', ]); define('MAILER_ENABLED', false); @@ -34,6 +34,7 @@ define('ATOM_ENABLED', true); define('ACTIVITYPUB_ENABLED', false); define('CURL_ENABLED', true); define('AUTH_ENABLED', false); +define('OPENPROVIDER_ENABLED', false); define('AUTH_REGISTER_ENABLED', false); define('COPYRIGHT_YEAR', '2018-'.date('Y')); define('DEBUG_MODE', false); \ No newline at end of file diff --git a/public/static/style-openprovider.css b/public/static/style-openprovider.css new file mode 100644 index 0000000..de192ff --- /dev/null +++ b/public/static/style-openprovider.css @@ -0,0 +1,25 @@ +textarea { + background: #232023; + color: #fcfcfc; + width: 100%; + max-width: 1260px; + height: 300px; +} + +button { + border: 1px solid #ea79d8; + color: #fcfcfc; + border-radius: 4px; + background: #ea79d8; + font-size: 16px; + transition: background-color 0.2s ease-in-out; +} + +button:hover { + background-color: #b421f8; +} + +tr.status-free { background-color: #34860e; color: #fff; } +tr.status-reserved { background-color: #c59e1d; color: #fff; } +tr.status-use { background-color: #850000; color: #fff; } +tr.status-fumei { background-color: #888; color: #000; } \ No newline at end of file diff --git a/route.php b/route.php index 2f5140c..a490938 100644 --- a/route.php +++ b/route.php @@ -8,6 +8,7 @@ use Site\Controller\Atom; use Site\Controller\Fediverse; use Site\Controller\Home; use Site\Controller\Notfound; +use Site\Controller\Op; use Site\Controller\Page; use Site\Controller\User; @@ -57,6 +58,17 @@ if (ATOM_ENABLED) { $routes[] = Route::add('GET', 'blog.atom', Atom::class.'@feed'); } +if (OPENPROVIDER_ENABLED) { + $routes[] = Route::add('GET', 'openprovider', Op::class.'@index'); + $routes[] = Route::add('GET', 'openprovider/searchcustomer', Op::class.'@opSearchCustomers'); + $routes[] = Route::add('GET', 'openprovider/listtlds', Op::class.'@opListTlds'); + $routes[] = Route::add('GET', 'openprovider/gettld/{tld}', Op::class.'@opGetTld'); + $routes[] = Route::add('GET', 'openprovider/checkdomain', Op::class.'@opCheckDomainAvailable'); + $routes[] = Route::add('GET', 'openprovider/getdomainprices', Op::class.'@opGetDomainPrices'); + $routes[] = Route::add('GET', 'openprovider/listdnszones', Op::class.'@opListDns'); + $routes[] = Route::add('GET', 'openprovider/getdns/{domain}', Op::class.'@opGetDns'); +} + $routes[] = Route::add('GET', '', Home::class.'@show'); Route::init($routes); diff --git a/src/Site/Controller/Mods.php b/src/Site/Controller/Mods.php index 950948f..1c065e8 100644 --- a/src/Site/Controller/Mods.php +++ b/src/Site/Controller/Mods.php @@ -46,6 +46,13 @@ trait Mods { 'text' => 'スタッフ限定', 'show' => true, ], + [ + 'class' => 'menu-item', + 'href' => '/openprovider', + 'page' => 'openprovider', + 'text' => 'OpenProvider管理', + 'show' => true, + ], ]; } } diff --git a/src/Site/Controller/Op.php b/src/Site/Controller/Op.php new file mode 100644 index 0000000..3864c50 --- /dev/null +++ b/src/Site/Controller/Op.php @@ -0,0 +1,341 @@ +getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $tmpl->addCss('table'); + $tmpl->render('index'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opSearchCustomers(array $params): void { + try { + $tmpl = new Template('/openprovider/'); + $pagetit = 'OpenProvider管理 - 顧客様検索'; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', true); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = $op->searchCustomers(); + $tmpl->assign('data', $data); + + $tmpl->addCss('table'); + $tmpl->render('searchcustomer'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opListTlds(array $params): void { + try { + $tmpl = new Template('/openprovider/'); + $pagetit = 'OpenProvider管理 - TLD一覧'; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = $op->listTlds(); + $tmpl->assign('data', $data); + + $tmpl->addCss('table'); + $tmpl->render('listtlds'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opGetTld(array $params): void { + try { + $tld = ''; + if (isset($params['tld'])) $tld = $params['tld']; + if ($tld === '') { + header('Location: /'); + exit(); + } + $tmpl = new Template('/openprovider/'); + $pagetit = "OpenProvider管理 - .{$tld}の表示"; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = $op->getTld($tld); + $tmpl->assign('data', $data); + + $tmpl->addCss('table'); + $tmpl->render('gettld'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opListDomains(array $params): void { + try { + $tmpl = new Template('/openprovider/'); + $pagetit = 'OpenProvider管理 - ドメイン確認'; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = $op->listDomains($domains, true); + $tmpl->assign('data', $data); + + $tmpl->assign('saved', $saved); + + $tmpl->addCss('table'); + $tmpl->addCss('openprovider'); + $tmpl->render('checkdomain'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opCheckDomainAvailable(array $params): void { + try { + $domains = isset($_GET['domains']) ? explode("\n", $_GET['domains']) : []; + $saved = ''; + + $tmpl = new Template('/openprovider/'); + $pagetit = 'OpenProvider管理 - ドメイン確認'; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + if (!empty($domains)) { + $data = $op->checkDomainAvailable($domains, true); + $tmpl->assign('data', $data); + $saved = $_GET['domains']; + } + + $tmpl->assign('saved', $saved); + + $tmpl->addCss('table'); + $tmpl->addCss('openprovider'); + $tmpl->render('checkdomain'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opGetDomainPrices(array $params): void { + try { + $domainname = $_GET['domain_name'] ?? ''; + $domainext = $_GET['domain_extension'] ?? ''; + + $tmpl = new Template('/openprovider/'); + $pagetit = 'OpenProvider管理 - ドメイン値段一覧'; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = $op->getDomainPrices(['domain.name' => $domainname, 'domain.extension' => $domainext]); + $tmpl->assign('data', $data); + + $tmpl->addCss('table'); + $tmpl->render('getdomainprices'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opListDns(array $params): void { + try { + $tmpl = new Template('/openprovider/'); + $pagetit = "OpenProvider管理 - DNS一覧"; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', true); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = $op->listDnsZones(); + $tmpl->assign('data', $data); + + $tmpl->addCss('table'); + if ($user && $user->role & (\Roles::ADMIN)) $tmpl->render('listdnszones'); + else goto noaccess; + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } + + public function opGetDns(array $params): void { + try { + $domain = ''; + if (isset($params['domain'])) $domain = $params['domain']; + if ($domain === '') { + header('Location: /'); + exit(); + } + $tmpl = new Template('/openprovider/'); + $pagetit = "OpenProvider管理 - {$domain}のDNS管理"; + $description = ''; + + // ユーザー + $auth = new Auth(); + $user = $auth->getLoggedInUser(); + $tmpl->assign('user', $user); + + $tmpl->assign('pagetit', $pagetit); + $tmpl->assign('curPage', 'openprovider'); + $tmpl->assign('custCss', false); + $tmpl->assign('menu', $this->getMenu()); + $tmpl->assign('description', $description); + + if (!$user || $user->role !== \Roles::ADMIN) goto noaccess; + $op = new Openprovider(); + $op->login(); + $data = ['rec' => $op->listZoneRecords($domain), 'zone' => $op->getDnsZone($domain)]; + $tmpl->assign('data', $data); + + $tmpl->addCss('table'); + $tmpl->render('getdns'); + exit(); + + noaccess: + $tmpl->render('nopermission'); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/src/Site/Controller/Page.php b/src/Site/Controller/Page.php index dd94c46..e885431 100644 --- a/src/Site/Controller/Page.php +++ b/src/Site/Controller/Page.php @@ -5,20 +5,11 @@ use Site\Controller\Mods; use Std\Lib\Auth; use Std\Lib\Template; - -use Std\Lib\Openprovider; - class Page { use Mods; public function about(array $params): void { try { - $op = new OpenProvider(); - $op->login(); - // kys($op->getToken()); - // kys($op->checkDomainAvailable(['076.moe', '076.xxx', '076.nigger'])); - // kys($op->listTlds()); - kys($op->searchCustomers()); $tmpl = new Template('/'); $pagetit = '新ページ'; $description = 'PHPフレームワークについて'; @@ -121,7 +112,6 @@ class Page { // ユーザー $auth = new Auth(); $user = $auth->getLoggedInUser(); - $tmpl->assign('user', $user); $tmpl->assign('pagetit', $pagetit); @@ -136,4 +126,4 @@ class Page { throw new \Exception($e->getMessage()); } } -} +} \ No newline at end of file diff --git a/src/Std/Lib/Curl.php b/src/Std/Lib/Curl.php index f33f0bf..e3a9fe0 100644 --- a/src/Std/Lib/Curl.php +++ b/src/Std/Lib/Curl.php @@ -456,80 +456,43 @@ class Curl { $headersComplete = false; // ヘッダーとボディを分けて読み込む - while (!feof($socket)) { - $line = fgets($socket); - if ($line === false) { - break; - } - - $rawResponse .= $line; - - if (!$headersComplete) { - if (trim($line) === '') { - $headersComplete = true; - } else { - $headers .= $line; - } - } else { - $body .= $line; - } - } - + while (!feof($socket)) $rawResponse .= fread($socket, 8192); fclose($socket); - // レスポンスヘッダーを解析 - $headerLines = explode("\r\n", $headers); + if ($rawResponse === '') { + $this->responseError = 'リスポンスエラー'; + return \Result::Error($this->responseError); + } - // ステータスコードを取得 - $statusLine = isset($headerLines[0]) ? $headerLines[0] : ''; - $statusParts = explode(' ', $statusLine, 3); - $this->responseCode = isset($statusParts[1]) ? (int)$statusParts[1] : 0; - $this->info['http_code'] = $this->responseCode; + list($headerLines, $body) = $this->parseResponse($rawResponse); // ヘッダーを解析 $this->responseHeaders = []; - $redirectUrl = ''; + $this->responseCode = 0; foreach ($headerLines as $index => $header) { - if ($index === 0) continue; + if ($index === 0) { + if (preg_match('#HTTP/\d\.\d (\d+)#', $header, $m)) + $this->responseCode = (int)$m[1]; + continue; + } if (strpos($header, ':') !== false) { - list($name, $value) = explode(':', $header, 2); + [$name, $value] = explode(':', $header, 2); $name = trim($name); $value = trim($value); $this->responseHeaders[$name] = $value; - - if (strtolower($name) === 'content-type') { - $this->info['content_type'] = $value; - } - - // リダイレクトをチェック - if ($this->followRedirects && - strtolower($name) === 'location' && - $this->responseCode >= 300 && - $this->responseCode < 400) { - - $redirectUrl = $value; - - // 相対URLを絶対URLに変換 - if (strpos($redirectUrl, 'http') !== 0) { - if ($redirectUrl[0] === '/') { - $redirectUrl = "{$scheme}://{$host}" - .($port != 80 && $port != 443 ? ":{$port}" : '').$redirectUrl; - } else { - $redirectUrl = "{$scheme}://{$host}" - .($port != 80 && $port != 443 ? ":{$port}" : '') - .dirname($path).'/'.$redirectUrl; - } - } - - $this->info['redirect_url'] = $redirectUrl; - } } } + $this->info['http_code'] = $this->responseCode; + if (isset($this->responseHeaders['Transfer-Encoding']) + && stripos($this->responseHeaders['Transfer-Encoding'], 'chunked') !== false) { + $body = $this->decodeChunkedBody($body); + } + $this->info['header_size'] += strlen($headers); - $this->responseBody .= $body; + $this->responseBody = $body; if ($this->verbose && $this->stderr) { fwrite($this->stderr, "* レスポンスコード: {$this->responseCode}\n"); @@ -688,20 +651,11 @@ class Curl { */ private function parseResponse(string $response): array { $parts = explode("\r\n\r\n", $response, 2); - - if (count($parts) < 2) { - return [[], '']; - } - + if (count($parts) < 2) return [explode("\r\n", $response), '']; + $headers = explode("\r\n", $parts[0]); $body = $parts[1]; - - // チャンク転送エンコーディングを処理 - if (isset($this->responseHeaders['Transfer-Encoding']) && - strtolower($this->responseHeaders['Transfer-Encoding']) === 'chunked') { - $body = $this->decodeChunkedBody($body); - } - + return [$headers, $body]; } @@ -717,15 +671,9 @@ class Curl { while ($position < strlen($body)) { $lineEnd = strpos($body, "\r\n", $position); - if ($lineEnd === false) { - break; - } - + if ($lineEnd === false) break; $chunkSize = hexdec(substr($body, $position, $lineEnd - $position)); - - if ($chunkSize === 0) { - break; - } + if ($chunkSize === 0) break; $position = $lineEnd + 2; $decodedBody .= substr($body, $position, $chunkSize); diff --git a/src/Std/Lib/Openprovider.php b/src/Std/Lib/Openprovider.php index 51a9a66..6fe6fd1 100644 --- a/src/Std/Lib/Openprovider.php +++ b/src/Std/Lib/Openprovider.php @@ -4,13 +4,17 @@ namespace Std\Lib; use Std\Lib\Curl; class Openprovider { - private string $user; - private string $pass; - private string $token; - private string $ip; - private int $reseller_id; - private string $BASEURL = 'https://api.openprovider.eu/v1beta'; - // private Curl $curl; + protected string $dataFile = ROOT."/data/session.json"; + protected int $tokenDuration = 172800; // 48時間 + + private string $user = ''; + private string $pass = ''; + private string $token = ''; + private string $ip = ''; + private int $reseller_id = 0; + private int $last_auth = 0; + private string $BASEURL = DEBUG_MODE ? 'http://api.sandbox.openprovider.nl:8480/v1beta' + : 'https://api.openprovider.eu/v1beta'; public function __construct() { if (!OPENPROVIDER_ENABLED) return; @@ -22,10 +26,13 @@ class Openprovider { /*** * トークンの受け取り。 * このライブリリーを使ったら、一回「login()」を実行する事が必須となります。 - * - * @return Result 結果 + * + * @return Result|false 結果 */ - public function login(): \Result { + public function login(): \Result|false { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + $this->getCache(); + if (time() < ($this->last_auth + $this->tokenDuration)) return false; $curl = new Curl("{$this->BASEURL}/auth/login"); $payload = [ @@ -58,7 +65,10 @@ class Openprovider { $data = json_decode($body, true); if (isset($data['data']['token'])) { $this->token = $data['data']['token']; + $this->last_auth = time(); $this->reseller_id = $data['data']['reseller_id']; + $this->mkCache(); + return \Result::Success(); } @@ -71,14 +81,82 @@ class Openprovider { //// ドメイン + /*** + * ドメイン一覧。 + * + * @return Result|array 結果。 + */ + public function listDomains(array $query = []): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + $curl = $this->setupCurl('/domains'); + $data = $this->curlResult($curl); + if (isset($data['data']['results'])) return $data['data']['results']; + + return \Result::Error("ドメインの確認に失敗。"); + } + + /** + * ドメイン名の登録。 + * + * @param string $name 登録したいドメイン名(例:"076studio.jp") + * @param array $info カスタマー情報等 + * @param int $period 年間(デフォルト=1年) + * @return Result|array 結果。配列の場合:'activation_date'(リアルタイムで成功したのみ), 'auth_code'(TLDが対応している場合のみ), 'expiration_date', 'id', 'renewal_date', 'status'(ACT又はREQ) + */ + public function createDomain(string $name, array $info, int $period = 1): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + if (!isset($info['owner_handle']) || $info['owner_handle'] === '') $info['owner_handle'] = OPENPROVIDER['owner_handle']; + if (!isset($info['admin_handle']) || $info['admin_handle'] === '') $info['admin_handle'] = OPENPROVIDER['owner_handle']; + if (!isset($info['tech_handle']) || $info['tech_handle'] === '') $info['tech_handle'] = OPENPROVIDER['owner_handle']; + if (!isset($info['billing_handle']) || $info['billing_handle'] === '') $info['billing_handle'] = OPENPROVIDER['owner_handle']; + if (!isset($info['reseller_handle']) || $info['reseller_handle'] === '') $info['reseller_handle'] = OPENPROVIDER['owner_handle']; + if (!isset($info['name_servers']) || empty($info['name_servers'])) $info['name_servers'] = ['ns1.openprovider.nl', 'ns2.openprovider.be', 'ns3.openprovider.eu']; + if (!isset($info['autorenew']) || $info['autorenew'] === '') $info['autorenew'] = 'default'; + + // 新しい顧客の場合 + + $parts = explode('.', $name, 2); + assert_exists($parts[0]); + assert_exists($parts[1]); + $domain = [ + 'name' => $parts[0], + 'extension' => $parts[1], + ]; + + $ns = []; + foreach ($info['name_servers'] as $n) { + $ns[] = ['name' => $n]; + } + + $payload = [ + 'name' => $domain, + 'period' => $period, + 'owner_handle' => $owner_handle, + 'admin_handle' => $admin_handle, + 'tech_handle' => $tech_handle, + 'billing_handle' => $billing_handle, + 'reseller_handle' => $reseller_handle, + 'name_servers' => $ns, + 'autorenew' => $autorenew, + ]; + + $curl = $this->setupCurl('/domains/', 'POST', $payload); + kys('TODO'); + $data = $this->curlResult($curl); + if (isset($data['data'])) return $data['data']; + + return \Result::Error("ドメインの確認に失敗。"); + } + /*** * ドメインを登録可能かどうかの確認。 - * + * * @param array $domains ドメイン名リスト。例:['076.moe', '076.co.jp', '076.com'] * @param bool $with_price 値段を表示するかどうか。デフォルトは「false」 * @return Result|array 結果。配列の場合:'domain'と'status'はいつでもあり、'reason', 'premium', 'is_premium'が多分あり、そして'price'が「with_price」が「true」の場合のみ。 */ public function checkDomainAvailable(array $domains, bool $with_price = false): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); $domainList = []; foreach ($domains as $d) { $domain = explode('.', $d); @@ -106,80 +184,23 @@ class Openprovider { return \Result::Error("ドメインの確認に失敗。"); } - /** - * ドメイン名の登録。 - * - * @param string $name 登録したいドメイン名(例:"076studio.jp") - * @param int $period 年間(デフォルト=1年) - * @param string $owner_handle - * @param string $admin_handle - * @param string $tech_handle - * @param string $billing_handle - * @param string $reseller_handle - * @param array $name_servers ネームサーバー(4つまで、デフォルトはOpenProviderさんのネームサーバー) - * @param string $autorenew 自動的に更新するかどうか(可能な値:on|off|default、デフォルト=default) - * @return Result|array 結果。配列の場合:'activation_date'(リアルタイムで成功したのみ), 'auth_code'(TLDが対応している場合のみ), 'expiration_date', 'id', 'renewal_date', 'status'(ACT又はREQ) - */ - public function registerDomain(string $name, int $period = 1, string $owner_handle = '', - string $admin_handle = '', string $tech_handle = '', - string $billing_handle = '', string $reseller_handle = '', - array $name_servers = [], string $autorenew = 'default'): \Result|array { - if ($owner_handle === '') $owner_handle = OPENPROVIDER['owner_handle']; - if ($admin_handle === '') $admin_handle = $owner_handle; - if ($tech_handle === '') $tech_handle = $owner_handle; - if ($billing_handle === '') $billing_handle = $owner_handle; - if ($reseller_handle === '') $reseller_handle = $owner_handle; - - $parts = explode('.', $name, 2); - assert_exists($parts[0]); - assert_exists($parts[1]); - $domain = [ - 'name' => $parts[0], - 'extension' => $parts[1], - ]; - - $ns = []; - if (empty($name_servers)) $name_servers = ['ns1.openprovider.nl', 'ns2.openprovider.be', 'ns3.openprovider.eu']; - foreach ($name_servers as $n) { - $ns[] = ['name' => $n]; - } - - $payload = [ - 'name' => $domain, - 'period' => $period, - 'owner_handle' => $owner_handle, - 'admin_handle' => $admin_handle, - 'tech_handle' => $tech_handle, - 'billing_handle' => $billing_handle, - 'reseller_handle' => $reseller_handle, - 'name_servers' => $ns, - 'autorenew' => $autorenew, - ]; - - $curl = $this->setupCurl('/domains/', 'POST', $payload); - kys('TODO'); - $data = $this->curlResult($curl); - if (isset($data['data'])) return $data['data']; - - return \Result::Error("ドメインの確認に失敗。"); - } - //// 追加データ //// 顧客様の追加データ /** * 顧客様の検索 - * @param array $query 検索クエリー(可能:handle_pattern (string), email_pattern (string), first_name_pattern (string), last_name_pattern (string), company_name_pattern (string), comment_pattern (string), with_additional_data (bool), limit (int = 100、最大=1000), offset (int = 0) + * + * @param array $query 検索クエリー + * @return Result|array */ public function searchCustomers(array $query = []): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); foreach ($query as $k => $v) { if (is_bool($v)) $query[$k] = $v ? '1' : '0'; } $uri = '/customers?'.http_build_query($query, '', '&', PHP_QUERY_RFC3986); $curl = $this->setupCurl($uri); - kys("TODO: 問題"); $data = $this->curlResult($curl); - kys($data); if (isset($data['data'])) return $data['data']; return \Result::Error("TLD一覧の受け取りに失敗。"); @@ -187,16 +208,34 @@ class Openprovider { //// ドメイン値段 + /** + * ドメイン値段一覧 + * + * @param array $query 検索クエリー + * @return Result|array + */ + public function getDomainPrices(array $query): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + $uri = "/domains/prices?".http_build_query($query, '', '&', PHP_QUERY_RFC3986); + $curl = $this->setupCurl($uri); + $data = $this->curlResult($curl); + if (isset($data['data'])) return $data['data']; + + return \Result::Error("TLD一覧の受け取りに失敗。"); + } + //// 認証コード //// TLD /** * TLD一覧 - * - * @param array $query 検索クエリー(可能:limit (int),offset (int),order (string),order_by (string),extensions(array), name_pattern (string), only_names (bool), with_description (bool),with_restrictions (bool)with_usage_count (bool)with_application_mode (bool),with_price (bool),with_level_prices (bool)is_active (bool)is_new_gtld (bool),status (string),application_mode (string)) + * + * @param array $query 検索クエリー + * @return Result|array */ public function listTlds(array $query = []): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); if (empty($query)) $query = [ 'limit' => 10, 'offset' => 0, 'order' => 'ASC' ]; foreach ($query as $k => $v) { @@ -204,11 +243,31 @@ class Openprovider { } $uri = '/tlds?'.http_build_query($query, '', '&', PHP_QUERY_RFC3986); - // kys($uri); $curl = $this->setupCurl($uri); - kys("TODO: JSONの問題"); $data = $this->curlResult($curl); - kys($data); + if (isset($data['data'])) return $data['data']; + + return \Result::Error("TLD一覧の受け取りに失敗。"); + } + + /** + * TLDの表示 + * + * @param string $tld TLD + * @param array $query 検索クエリー + * @return Result|array + */ + public function getTld(string $tld, array $query = []): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + if (empty($query)) $query = [ 'limit' => 10, 'offset' => 0 ]; + + foreach ($query as $k => $v) { + if (is_bool($v)) $query[$k] = $v ? '1' : '0'; + } + + $uri = "/tlds/{$tld}?".http_build_query($query, '', '&', PHP_QUERY_RFC3986); + $curl = $this->setupCurl($uri); + $data = $this->curlResult($curl); if (isset($data['data'])) return $data['data']; return \Result::Error("TLD一覧の受け取りに失敗。"); @@ -229,8 +288,66 @@ class Openprovider { //// NSグループ //// テンプレート //// ゾーン + + /** + * DNSゾーン一覧 + * + * @param array $query + * @return Result|array + */ + public function listDnsZones(array $query = []): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + if (empty($query)) $query = [ 'limit' => 25, 'offset' => 0, 'order_by.name' => 'asc' ]; + + foreach ($query as $k => $v) { + if (is_bool($v)) $query[$k] = $v ? '1' : '0'; + } + + $uri = "/dns/zones?".http_build_query($query, '', '&', PHP_QUERY_RFC3986); + $curl = $this->setupCurl($uri); + $data = $this->curlResult($curl); + if (isset($data['data'])) return $data['data']; + + return \Result::Error("TLD一覧の受け取りに失敗。"); + } + + /** + * DNSゾーン一覧 + * + * @param string $domain ドメイン名 + * @param array $query 検索クエリー + * @return Result|array + */ + public function getDnsZone(string $domain, array $query = []): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + if (empty($query)) $query = [ 'limit' => 100, 'offset' => 0, 'order_by.name' => 'asc' ]; + foreach ($query as $k => $v) if (is_bool($v)) $query[$k] = $v ? '1' : '0'; + + $uri = "/dns/zones/{$domain}?".http_build_query($query, '', '&', PHP_QUERY_RFC3986); + $curl = $this->setupCurl($uri); + $data = $this->curlResult($curl); + if (isset($data['data'])) return $data['data']; + + return \Result::Error("TLD一覧の受け取りに失敗。"); + } + //// ゾーンレコード + /** + * DNSレコード一覧 + * + * @param string $domain + * @return Result|array + */ + public function listZoneRecords(string $domain): \Result|array { + if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。'); + $curl = $this->setupCurl("/dns/zones/{$domain}/records"); + $data = $this->curlResult($curl); + if (isset($data['data'])) return $data['data']; + + return \Result::Error("TLD一覧の受け取りに失敗。"); + } + // Easydmarc // ライセンス @@ -245,19 +362,21 @@ class Openprovider { /** * トークンの受け取り。 - * + * * @return string トークン */ public function getToken(): string { + if (!OPENPROVIDER_ENABLED) return ''; return $this->token; } /** * リセラーIDの受け取り。 - * + * * @return int リセラーID */ public function getResellerId(): int { + if (!OPENPROVIDER_ENABLED) return 0; return $this->reseller_id; } @@ -277,7 +396,6 @@ class Openprovider { private function curlResult(Curl &$curl): \Result|array { $res = $curl->execute(); - // kys($curl->getRequestHeader()); if (!$res->isSuccess) { $err = "CURL実行に失敗: {$curl->message}"; assert_unless_success($res, $err); @@ -285,18 +403,40 @@ class Openprovider { } $body = $curl->getResponseBody(); - // kys($body); - // kys($curl->getResponseHeaders()); if ($curl->getResponseCode() != 200) { $err = json_decode($body, true); assert_not_null($err, "エラーの受け取りに失敗。"); assert($curl->getResponseCode() == 200, $err['desc']); - return \Result::Error(); + return \Result::Error($err['desc']); } assert_not_null($body, "返事ボディーは空です。"); - // $body = str_ - kys($body); return json_decode($body, true); } + + private function mkCache(): \Result { + $session = new \stdClass; + $session->lastAuth = $this->last_auth; + $session->token = $this->token; + $session->resellerId = $this->reseller_id; + + $json = json_encode($session, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if (file_put_contents($this->dataFile, $json) === false) return \Result::Error('エラー:ユーザーデータの保存に失敗。'); + + return \Result::Success(); + } + + private function getCache(): void { + if (!file_exists($this->dataFile)) return; + + $content = file_get_contents($this->dataFile); + if ($content === false) return; + + $data = json_decode($content, true); + if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) return; + + $this->token = $data['token'] ?? null; + $this->reseller_id = $data['resellerId'] ?? null; + $this->last_auth = $data['lastAuth'] ?? null; + } } \ No newline at end of file diff --git a/view/404.maron b/view/404.maron index ead8ffd..7ce685b 100644 --- a/view/404.maron +++ b/view/404.maron @@ -1,3 +1,3 @@ {@ include(common/header) @}

見つけられません。ごめんなしゃーい!!

-{@ include(common/footer) @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/checkdomain.maron b/view/openprovider/checkdomain.maron new file mode 100644 index 0000000..2e51500 --- /dev/null +++ b/view/openprovider/checkdomain.maron @@ -0,0 +1,53 @@ +{@ include(common/header) @} +

ドメイン確認

+
+ 各行列で1つのドメイン名をご入力下さい。
+
+ +
+{@ if (isset($data) && !empty($data)) @} +
+

結果

+ + + + + + + + + + +{@ foreach ($data as $d) @} +{$ $status = '不明' $} +{$ $statusClass = 'status-fumei' $} +{@ if ($d['status'] === 'free') @} +{$ $status = '登録可能' $} +{$ $statusClass = 'status-free' $} +{@ elif ($d['status'] === 'reserved') @} +{$ $status = '予約済み' $} +{$ $statusClass = 'status-reserved' $} +{@ elif ($d['status'] === 'active') @} +{$ $status = '登録済み' $} +{$ $statusClass = 'status-use' $} +{@ endif @} + + + + + + +{@ endforeach @} + +
ドメイン名状況理由値段
{{ $d['domain'] }}{{ isset($d['is_premium']) && $d['is_premium'] ? '(プレミアム)' : '' }}{{ $status }}{{ $d['reason'] ?? '' }} +{@ if (isset($d['price'])) @} +{@ if (isset($d['price']['product'])) @} + 商品: {{ $d['price']['product']['price'] }} {{ $d['price']['product']['currency'] }} +{@ endif @} +{@ if (isset($d['price']['reseller'])) @} +
リセラー: {{ $d['price']['reseller']['price'] }} {{ $d['price']['reseller']['currency'] }} +{@ endif @} +{@ endif @} +
+{@ endif @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/editdns.maron b/view/openprovider/editdns.maron new file mode 100644 index 0000000..26990d4 --- /dev/null +++ b/view/openprovider/editdns.maron @@ -0,0 +1,34 @@ +{@ include(common/header) @} + DNSゾーンの追加ボタン
+{@ if (isset($data['results'])) @} + 検索バー
+

編集

+ + + + + + + + + + + +{@ foreach ($data['results'] as $d) @} + + + + + + + +{@ endforeach @} + +
名前種類内容プライオリティTTL
{{ $d['name'] }}{{ $d['type'] }}{{ substr($d['value'], 0, 40) }}{{ $d['prio'] ?? '' }}{{ $d['ttl'] }}
+ +{@ else @} +

何も見つけられませんでした。

+{@ endif @} + + {@ kys($data) @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/getdns.maron b/view/openprovider/getdns.maron new file mode 100644 index 0000000..0d48df5 --- /dev/null +++ b/view/openprovider/getdns.maron @@ -0,0 +1,150 @@ +{@ include(common/header) @} + + + DNSレコードの追加ボタン
+ DNSゾーンの削除ボタン
+{@ if (isset($data['rec']['results']) || isset($data['zone'])) @} + 検索バー
+
+ + + + + +
+ + + + +
+ +
+

レコード

+ + + + + + + + + + + +{@ foreach ($data['rec']['results'] as $d) @} + + + + + + + +{@ endforeach @} + +
名前種類内容プライオリティTTL
{{ $d['name'] }}{{ $d['type'] }}{{ substr($d['value'], 0, 40) }}{{ $d['prio'] ?? '' }}{{ $d['ttl'] }}
+
+ +
+

詳細

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ドメイン名{{ $data['zone']['name'] }}
種類{{ $data['zone']['type'] }}
DNSゾーンプロバイダーOpenprovider
追加日{{ $data['zone']['creation_date'] }}
最終更新日{{ $data['zone']['modification_date'] }}
レコード数{{ $data['rec']['total'] }}
DNSSEC有効
SpamExperts{{ $data['zone']['is_spamexperts_enabled'] ? '有' : '無' }}
+
+ +
+

DNSSEC鍵

+

ささ

+
+ +
+

履歴

+

ささ

+
+
+{@ else @} +

何も見つけられませんでした。

+{@ endif @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/getdomainprices.maron b/view/openprovider/getdomainprices.maron new file mode 100644 index 0000000..15d68d8 --- /dev/null +++ b/view/openprovider/getdomainprices.maron @@ -0,0 +1,3 @@ +{@ include(common/header) @} + {@ kys($data) @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/gettld.maron b/view/openprovider/gettld.maron new file mode 100644 index 0000000..15d68d8 --- /dev/null +++ b/view/openprovider/gettld.maron @@ -0,0 +1,3 @@ +{@ include(common/header) @} + {@ kys($data) @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/index.maron b/view/openprovider/index.maron new file mode 100644 index 0000000..847c19e --- /dev/null +++ b/view/openprovider/index.maron @@ -0,0 +1,20 @@ +{@ include(common/header) @} +

{{ $description }}

+ +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/listdnszones.maron b/view/openprovider/listdnszones.maron new file mode 100644 index 0000000..f888949 --- /dev/null +++ b/view/openprovider/listdnszones.maron @@ -0,0 +1,32 @@ +{@ include(common/header) @} + 検索バー
+ DNSゾーンの追加ボタン +{@ if (isset($data['results'])) @} + + + + + + + + + + + + +{@ foreach ($data['results'] as $d) @} + + + + + + + + +{@ endforeach @} + +
Domain nameTypeDNS providerRenewal dateDate addedLast change
{{ $d['name'] }}{{ $d['type'] }}{{ $d['provider'] }}{{ $d['creation_date'] }}{{ $d['modification_date'] }}
+{@ else @} +

何も見つけられませんでした。

+{@ endif @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/listtlds.maron b/view/openprovider/listtlds.maron new file mode 100644 index 0000000..15d68d8 --- /dev/null +++ b/view/openprovider/listtlds.maron @@ -0,0 +1,3 @@ +{@ include(common/header) @} + {@ kys($data) @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/nopermission.maron b/view/openprovider/nopermission.maron new file mode 100644 index 0000000..b1fd7b3 --- /dev/null +++ b/view/openprovider/nopermission.maron @@ -0,0 +1,3 @@ +{@ include(common/header) @} +

表示許可却下。失礼。

+{@ include(common/footer) @} \ No newline at end of file diff --git a/view/openprovider/registerdomain.maron b/view/openprovider/registerdomain.maron new file mode 100644 index 0000000..e69de29 diff --git a/view/openprovider/searchcustomer.maron b/view/openprovider/searchcustomer.maron new file mode 100644 index 0000000..48c60f8 --- /dev/null +++ b/view/openprovider/searchcustomer.maron @@ -0,0 +1,29 @@ +{@ include(common/header) @} + 検索
+{@ if (isset($data['results'])) @} + + + + + + + + + + + +{@ foreach ($data['results'] as $d) @} + + + + + + + +{@ endforeach @} + +
NameCompanyE-mail addressHandleNotes
{{ $d['name']['full_name'] }}{{ $d['company_name'] }}{{ $d['email'] }}{{ $d['handle'] }}
+{@ else @} +

何も見つけられませんでした。

+{@ endif @} +{@ include(common/footer) @} \ No newline at end of file