<?php
  function dd ($val) {
    echo '<pre>';
    var_dump($val);
    echo '</pre>';
    die();
  }

  function uuid () {
    return sprintf(
      '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
      mt_rand(0, 0xffff), mt_rand(0, 0xffff), // 32bitlow
      mt_rand(0, 0xffff), // 16bitmid
      mt_rand(0, 0x0fff) | 0x4000, // 16bithigh
      mt_rand(0, 0x3fff) | 0x8000, // 16bit|8bithigh|low
      mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) // 48bitnode
    );
  }

  function isdomainexist (string $url): bool {
    return inet_pton(gethostbyname(get_domain($url))) !== false;
  }

  function isurl (string $url): bool {
    return $url && is_string($url) && preg_match('/^http(s)?:\/\/[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(\/.*)?$/i', $url) && $url === parse_url($url, PHP_URL_SCHEME).'://'.parse_url($url, PHP_URL_HOST);
  }

  function domainsecuritycheck (string $url): array {
    $err = [];

    // ホスト名のみかどうかチェック
    if (!isurl($url)) {
      $err[] = 'URLは「http」又は「https」からTLDまでのみではありません。ご変更下さい。<br />URL is not limited to "http" or "https" to TLD. Please change.';
      return $err;
    }

    // ドメインは存在するかどうかチェック
    if (!isdomainexist($url)) {
      $err[] = 'このドメイン名は未登録みたいです。<br />This domain name seems to be unregistered.';
      return $err;
    }

    // ブラフレを使っているかどうかチェック
    if (!is_null(shell_exec('whois '.get_domain($url).' | grep -i "cloudflare" 2>&1'))) {
      $err[] = 'ウェブサイトはCloudFlareを使っているみたいです。追加依頼拒否。<br />The website seems to be using CloudFlare. Rejection of additional request.';
    }

    // Torブロックのチェック
    if (execcurl($url, 'code', true) >= 400) {
      $err[] = 'ウェブサイトはTorで接続出来ないみたいです。追加依頼拒否。<br />The website doesn\'t seem to be able to connect with Tor. Rejection of additional request.';
    }

    // DOCTYPE htmlタグがあるかどうかチェック
    $out = execcurl($url, 'cout', false, false, false);
    if (strpos($out, '<!DOCTYPE html') === false) {
      $err[] = 'ウェブサイトは「!DOCTYPE html」タグを含めていません。<br />The website does not include the "! DOCTYPE html" tag.';
    }

    // titleタグがあるかどうかチェック
    if (strpos($out, '<title>') === false) {
      $err[] = 'ウェブサイトは「title」タグを含めていません。<br />The website does not include the "title" tag.';
    }

    return $err;
  }

  function execcurl (string $url, string $return='code', bool $proxy=false, bool $header=true, bool $nobody=true): string|int|bool {
    // return = code → HTTPステータスコード
    // return = cout → curl_exec
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HEADER, $header);
    curl_setopt($ch, CURLOPT_NOBODY, $nobody);
    curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, $proxy);
    if ($proxy) {
      curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:9050');
      curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
    }
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    $output = curl_exec($ch);
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return $return == 'code' ? $httpcode : $output;
  }

  // 下記の機能性は https://newbedev.com/get-domain-name-not-subdomain-in-php より
  function tld_list ($cache_dir=null) {
    $cache_dir = isset($cache_dir) ? $cache_dir : sys_get_temp_dir();
    $lock_dir = $cache_dir . '/public_suffix_list_lock/';
    $list_dir = $cache_dir . '/public_suffix_list/';
    if (file_exists($list_dir) && @filemtime($list_dir) + 2592000 > time()) return $list_dir;
    if (!file_exists($lock_dir) && @mkdir($lock_dir)) {
      $list = @fopen('https://publicsuffix.org/list/public_suffix_list.dat', 'r');
      if ($list) {
        if (file_exists($list_dir)) {
          foreach (glob($list_dir . '*') as $filename) unlink($filename);
          rmdir($list_dir);
        }
        mkdir($list_dir);
        while ($line = fgets($list)) {
          if ($line[0] == '/' || !$line) continue;
          if ($line[0] . $line[1] == '*.') $line = substr($line, 2);
          if ($line[0] == '!') $line = substr($line, 1);
          $line = implode('.', array_reverse(explode('.', (trim($line)))));
          touch($list_dir . $line);
        }
        fclose($list);
      }
      @rmdir($lock_dir);
    }
    if (file_exists($lock_dir) && mt_rand(0, 100) == 0 && @filemtime($lock_dir) + 86400 < time()) @rmdir($lock_dir);
    return $list_dir;
  }

  function get_domain ($url=null) {
    $tld_dir = tld_list();
    $url = isset($url) ? $url : $_SERVER['SERVER_NAME'];
    $url = !isset($url[5]) || ($url[3] != ':' && $url[4] != ':' && $url[5] != ':') ? 'http://' . $url : $url;
    $url = parse_url($url, PHP_URL_HOST);
    $url = trim($url, '.');
    $url = explode('.', $url);
    $parts = array_reverse($url);
    foreach ($parts as $key => $part) {
      $tld = implode('.', $parts);
      if (file_exists($tld_dir.$tld)) return !$key ? '' : implode('.', array_slice($url, $key - 1));
      array_pop($parts);
    }
    return '';
  }
?>
