3 |
4 | ENV HOST_KEY=e9e4498f0584b7098692512db0c62b48 \
5 | HOST_MAIL=ze3kr@example.com \
6 | TITLE=TlOxygen
7 |
8 | COPY . /app
9 | RUN apk --no-cache --virtual runtimes add curl \
10 | nginx \
11 | php7 \
12 | php7-fpm \
13 | php7-cli \
14 | php7-json \
15 | php7-gettext \
16 | php7-curl \
17 | php7-apcu \
18 | php7-phar \
19 | php7-iconv \
20 | php7-mbstring \
21 | php7-openssl && \
22 | rm /etc/nginx/conf.d/default.conf && \
23 | mkdir -p /run/nginx && ln -s /var/run/nginx.pid /run/nginx/nginx.pid && \
24 | cp /app/.docker/nginx.conf /etc/nginx/conf.d/cloudflare.conf && \
25 | cp /app/.docker/php-fpm.conf /etc/php7/php-fpm.conf && \
26 | cd app && curl -s https://getcomposer.org/installer | php && \
27 | php composer.phar install --no-dev -o
28 |
29 | WORKDIR /app
30 | EXPOSE 80
31 |
32 | CMD cp /app/config.example.php /app/config.php && nginx && \
33 | sed -i "s|e9e4498f0584b7098692512db0c62b48|${HOST_KEY}|g" /app/config.php && \
34 | sed -i "s|ze3kr@example.com|${HOST_MAIL}|g" /app/config.php && \
35 | sed -i "s|// \$page_title = \"TlOxygen\"|\$page_title = \"${TITLE}\"|g" /app/config.php && \
36 | sed -i "s|// \$tlo_path = \"/\"|\$tlo_path = \"/\"|g" /app/config.php && \
37 | php-fpm7 --nodaemonize --fpm-config /etc/php7/php-fpm.conf -c /etc/php7/php.ini
38 |
--------------------------------------------------------------------------------
/actions/login2.php:
--------------------------------------------------------------------------------
1 | ' . $msg . '';}
9 | ?>
10 |
11 | ' . _('No Host API key found. You cannot add new domain to this service.') . '';
16 | }
17 | } ?>
18 |
34 |
37 |
--------------------------------------------------------------------------------
/actions/add.php:
--------------------------------------------------------------------------------
1 | zoneSet_full($zone_name);
14 | } catch (Exception $e) {
15 | exit('' . $e->getMessage() . '
');
16 | }
17 | if ($res['result'] == 'success') {
18 | $msg = _('Success') . ', ' . _('Go to console') . '. ';
19 | exit('' . $msg . '
');
20 | } elseif (isset($res['msg'])) {
21 | $msg = $res['msg'];
22 | } else {
23 | print_r($res);
24 | }
25 | }
26 |
27 | $zones = new \Cloudflare\API\Endpoints\Zones($adapter);
28 | try {
29 | $zoneID = $zones->getZoneID($zone_name);
30 | } catch (Exception $e) {
31 | if ($e->getMessage() == 'Could not find zones with specified name.') {
32 | $add_domain = true;
33 | }
34 | }
35 |
36 | if (isset($add_domain) && $add_domain) {
37 | try {
38 | $res = $cloudflare->zoneSet($zone_name, 'example.com', 'www');
39 | } catch (Exception $e) {
40 | exit('' . $e->getMessage() . '
');
41 | }
42 | } else {
43 | exit('' . _('Cannot add a existing domain.') . '
');
44 | }
45 |
46 | if ($res['result'] == 'success') {
47 | $zones = new \Cloudflare\API\Endpoints\Zones($adapter);
48 | try {
49 | $zoneID = $zones->getZoneID($zone_name);
50 | } catch (Exception $e) {
51 | exit('' . $e->getMessage() . '
');
52 | }
53 |
54 | try {
55 | $dns = new \Cloudflare\API\Endpoints\DNS($adapter);
56 | $dnsresult = $dns->listRecords($zoneID)->result;
57 | /*
58 | * Delete @ and `www` record to make this zone fresh.
59 | */
60 | foreach ($dnsresult as $record) {
61 | if ($record->name == $zone_name) {
62 | $dns->deleteRecord($zoneID, $record->id);
63 | } elseif ($record->name == 'www.' . $zone_name) {
64 | $dns->deleteRecord($zoneID, $record->id);
65 | }
66 | }
67 | } catch (Exception $e) {
68 | exit('' . $e->getMessage() . '
');
69 | }
70 |
71 | $msg = _('Success') . ', ' . _('Go to console') . '. ';
72 | exit('' . $msg . '
');
73 | } elseif (isset($res['msg'])) {
74 | $msg = $res['msg'];
75 | } else {
76 | print_r($res);
77 | exit;
78 | }
79 | }
80 | if (isset($msg) && $msg != '') {
81 | echo '' . $msg . '
';
82 | }
83 |
84 | ?>
85 |
90 |
--------------------------------------------------------------------------------
/README.zh.md:
--------------------------------------------------------------------------------
1 | # Cloudflare CNAME 接入
2 |
3 | [](https://hub.docker.com/r/ze3kr/cloudflare)
4 | [](https://github.com/ZE3kr/Cloudflare-CNAME-Setup)
5 | [](https://packagist.org/packages/ze3kr/cloudflare-cname-setup)
6 |
7 | [](https://github.com/ZE3kr/Cloudflare-CNAME-Setup/releases)
8 | [](https://hub.docker.com/r/ze3kr/cloudflare/builds)
9 | [](https://github.com/ZE3kr/Cloudflare-CNAME-Setup/releases/latest)
10 |
11 | [Cloudflare Hosting Partner][1] 可以使用此项目为用户提供一个可视化的面板,可以让用户免费的使用 [CNAME 接入][2]。
12 |
13 | [cf.tlo.xyz][3] 是安装了这个面板的最新稳定版的网站,值得你的信任。
14 |
15 | 
16 | 
17 | 
18 |
19 |
20 | 注意: cf.tlo.xyz 的 Host API key 已经被 Cloudflare 停用了。
21 |
22 | 现在,所有 cf.tlo.xyz 用户都需要使用 Global API Key 进行登录。
23 |
24 |
25 | ## 安装
26 |
27 | 如果你不想使用上述已经安装好了的面板,你可以在自己的服务器上安装。现有多种方式将其安装到服务器,[详情请参见 Wiki 中的安装方法][5]。
28 |
29 | ## 此面板的特性
30 |
31 | + 管理你的所有 DNS 记录。此面板使用了 [Cloudflare API v4][6],所以支持各种格式的 DNS 记录。
32 | + 高级统计。你可以查看**过去一整年的统计信息**,而不仅仅是一个月。
33 | + 同时支持 NS 接入。此面板提供了 NS 接入信息,所以你可以随时切换到 Cloudflare DNS。此外,这个面板也支持 DNSSEC。
34 | + 同时支持 IP 接入。你可以看到 DNS 的 Anycast IPv4 和 IPv6 信息,这样你可以安全地在根域名下使用第三方 DNS。
35 | + 适配移动设备。
36 | + 支持多种语言。
37 |
38 | ## 如何从 NS 接入转成从这个面板接入?
39 |
40 | 1. 备份现有域名的 DNS 记录。
41 | 2. 从备份中恢复,切换到另一个 DNS 解析商。(可选的)
42 | 3. 在 Cloudflare 上删除你的域名 (如果你没有完成第二部则可能会导致你的网站在一段时间内无法访问)
43 | 4. 在这个面板上重新添加域名。
44 | 5. 在这个面板上配置 DNS 记录。
45 | 6. 删除已有的 DNS 记录然后重新添加 CDN 的记录。(如果你在步骤二中切换到了另一个 DNS 解析商)
46 |
47 | ## CNAME 接入的好处
48 |
49 | + 更加灵活,因为你可以使用任何一个 DNS 提供商。
50 | + 将 Cloudflare 作为一个备份服务器,或者使用多个 CDN。
51 | + 可以免费支持四级域名下的 SSL!例如像 `dev.project.example.com` 这样的域名,Cloudflare 也会自动签发 SSL 证书,这是因为 CNAME 接入签发的是 [SSL for SaaS][7],它会自动地为每一个子域名签发证书。
52 |
53 | ## 使用 Cloudflare 的好处
54 |
55 | **你不需要在服务器端安装任何软件**。只需要在这个面板配置好源站服务器信息,删除已有记录并 CNAME 到 Cloudflare 的服务器,或者直接使用 Cloudflare DNS 即可!
56 |
57 | + 无限 DDOS 防御
58 | + 全球 CDN。你的网站会因此变得更快。
59 | + I'm Under Attack™ 模式可以自动清洗恶意流量。
60 | + Always Online ™ 让你的网站永远在线。
61 | + 支持 Page Rules. 你可以自定义缓存规则,配置 301 或 302 跳转以及更多。
62 |
63 | ## 屏幕截图
64 |
65 |
66 |
67 |
68 | ## Open sourced software used in this project
69 |
70 | This project was based on a [HOSTLOC topic][8].
71 |
72 | + jQuery | MIT License
73 | + popper.js | MIT License
74 | + Bootstrap | MIT License
75 | + Chart.js by Nick Downie | MIT License
76 | + Guzzle by Michael Dowling [mtdowling@gmail.com][9] | MIT License
77 | + PSR Http Message by Framework Interoperability Group | MIT License
78 | + Composer | MIT License
79 | + Net\_DNS2 by Mike Pultz [mike@mikepultz.com][10] | BSD-3-Clause License
80 | + Cloudflare SDK by Cloudflare | BSD-3-Clause
81 |
82 | [1]: https://www.cloudflare.com/partners/hosting-provider/
83 | [2]: https://support.cloudflare.com/hc/en-us/articles/200168706-How-do-I-do-CNAME-setup-
84 | [3]: https://cf.tlo.xyz
85 | [4]: https://beta.cf.tlo.xyz
86 | [5]: https://github.com/ZE3kr/Cloudflare-CNAME-Setup/wiki/%E5%AE%89%E8%A3%85
87 | [6]: https://api.cloudflare.com/
88 | [7]: https://www.cloudflare.com/ssl-for-saas-providers/
89 | [8]: http://www.hostloc.com/thread-386441-1-1.html
90 | [9]: mailto:mtdowling@gmail.com
91 | [10]: mailto:mike@mikepultz.com
92 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this
15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
17 | do not have permission to do that, you may request the second reviewer to merge it for you.
18 |
19 | ## Code of Conduct
20 |
21 | ### Our Pledge
22 |
23 | In the interest of fostering an open and welcoming environment, we as
24 | contributors and maintainers pledge to making participation in our project and
25 | our community a harassment-free experience for everyone, regardless of age, body
26 | size, disability, ethnicity, gender identity and expression, level of experience,
27 | nationality, personal appearance, race, religion, or sexual identity and
28 | orientation.
29 |
30 | ### Our Standards
31 |
32 | Examples of behavior that contributes to creating a positive environment
33 | include:
34 |
35 | * Using welcoming and inclusive language
36 | * Being respectful of differing viewpoints and experiences
37 | * Gracefully accepting constructive criticism
38 | * Focusing on what is best for the community
39 | * Showing empathy towards other community members
40 |
41 | Examples of unacceptable behavior by participants include:
42 |
43 | * The use of sexualized language or imagery and unwelcome sexual attention or
44 | advances
45 | * Trolling, insulting/derogatory comments, and personal or political attacks
46 | * Public or private harassment
47 | * Publishing others' private information, such as a physical or electronic
48 | address, without explicit permission
49 | * Other conduct which could reasonably be considered inappropriate in a
50 | professional setting
51 |
52 | ### Our Responsibilities
53 |
54 | Project maintainers are responsible for clarifying the standards of acceptable
55 | behavior and are expected to take appropriate and fair corrective action in
56 | response to any instances of unacceptable behavior.
57 |
58 | Project maintainers have the right and responsibility to remove, edit, or
59 | reject comments, commits, code, wiki edits, issues, and other contributions
60 | that are not aligned to this Code of Conduct, or to ban temporarily or
61 | permanently any contributor for other behaviors that they deem inappropriate,
62 | threatening, offensive, or harmful.
63 |
64 | ### Scope
65 |
66 | This Code of Conduct applies both within project spaces and in public spaces
67 | when an individual is representing the project or its community. Examples of
68 | representing a project or community include using an official project e-mail
69 | address, posting via an official social media account, or acting as an appointed
70 | representative at an online or offline event. Representation of a project may be
71 | further defined and clarified by project maintainers.
72 |
73 | ### Enforcement
74 |
75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
76 | reported by contacting the project team at [ze3kr@icloud.com](mailto:ze3kr@icloud.com). All
77 | complaints will be reviewed and investigated and will result in a response that
78 | is deemed necessary and appropriate to the circumstances. The project team is
79 | obligated to maintain confidentiality with regard to the reporter of an incident.
80 | Further details of specific enforcement policies may be posted separately.
81 |
82 | Project maintainers who do not follow or enforce the Code of Conduct in good
83 | faith may face temporary or permanent repercussions as determined by other
84 | members of the project's leadership.
85 |
86 | ### Attribution
87 |
88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
89 | available at [http://contributor-covenant.org/version/1/4][version]
90 |
91 | [homepage]: http://contributor-covenant.org
92 | [version]: http://contributor-covenant.org/version/1/4/
--------------------------------------------------------------------------------
/settings.php:
--------------------------------------------------------------------------------
1 | 'zh_CN.UTF-8',
34 | ];
35 | $lan = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 5);
36 | $lan = strtolower($lan);
37 | $short_lan = substr($lan, 0, 2);
38 | $dir = __DIR__ . '/languages';
39 | $domain = 'messages';
40 | if (isset($language_supported[$short_lan])) {
41 | $locale = $language_supported[$short_lan];
42 | $iso_language = $short_lan;
43 | } else {
44 | $locale = 'en';
45 | $iso_language = 'en';
46 | }
47 | putenv('LANG=' . $locale);
48 | setlocale(LC_MESSAGES, $locale);
49 | bindtextdomain($domain, $dir);
50 | bind_textdomain_codeset($domain, "UTF-8");
51 | textdomain($domain);
52 | require_once 'languages/translates.php';
53 | header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
54 | header("Content-Type: text/html; charset=UTF-8");
55 |
56 | if (isset($is_debug) && $is_debug) {
57 | ini_set('display_errors', 1);
58 | ini_set('display_startup_errors', 1);
59 | error_reporting(E_ALL);
60 | }
61 |
62 | if(file_exists(dirname(__FILE__) . '/vendor/autoload.php')){
63 | require_once dirname(__FILE__) . '/vendor/autoload.php';
64 | } else { ?>
65 | >
66 |
67 |
68 |
69 |
70 |
71 |
72 |
75 |
76 |
77 |
78 |
79 |
80 |
94 |
95 |
96 | '.dirname(__FILE__). '/vendor/autoload.php';?>
97 |
98 | '._('It probably means that composer dependencies are not installed properly.').'
';
100 | echo ''._('You will need to run the following codes to install the dependencies:').'
'.
101 | 'cd '.dirname(__FILE__)."\n".
102 | 'composer install --no-dev -o
';
103 | echo ''._('If you do not have the composer, install it first (you may need to run it with sudo):').'
'.
104 | 'curl -sS https://getcomposer.org/installer | php'."\n".
105 | 'mv composer.phar /usr/local/bin/composer
';
106 | ?>
107 |
108 |
109 |
112 |
113 |
114 |
13 |
14 |
15 |
16 | ' . _('No Host API key found. You cannot add new domain to this service.') . '';
21 | }
22 | } ?>
23 |
24 |
25 |
26 | |
27 | |
28 | |
29 |
30 |
31 |
32 | listZones(false, false, intval($_GET['page']));
36 | } catch (Exception $e) {
37 | exit('' . $e->getMessage() . '
');
38 | }
39 |
40 | foreach ($zones_data->result as $zone) {
41 | echo '';
42 | $_translate_analytics = _('Advanced Analytics');
43 | $_translate_manage = _('Manage');
44 | $_translate_manage_dns = _('Manage DNS');
45 | $_translate_security = _('Security');
46 | if (property_exists($zone, 'name_servers')) {
47 | echo <<
49 |
50 |
53 |
56 |
57 | {$zone->name}
58 | {$status_translate[$zone->status]}
59 |
60 | HTML;
61 | } else {
62 | echo <<
64 |
65 |
68 |
72 |
73 | {$zone->name}
74 | {$status_translate[$zone->status]}
75 |
76 |
77 | HTML;
78 |
79 | }
80 |
81 | echo <<{$status_translate[$zone->status]}
83 |
84 | HTML;
85 | if (property_exists($zone, 'name_servers')) {
86 | echo '' . _('Manage DNS') . '';
87 | } else {
88 | echo <<{$_translate_manage_dns}
90 | HTML;
91 | echo <<{$_translate_security}
93 | HTML;
94 |
95 | }
96 | echo ' | ';
97 | }
98 | ?>
99 |
100 |
101 | result_info->total_pages)) {
103 | $previous_page = '';
104 | $next_page = '';
105 | if ($zones_data->result_info->page < $zones_data->result_info->total_pages) {
106 | $page_link = $zones_data->result_info->page + 1;
107 | $next_page = ' | ' . _('Next') . '';
108 | }
109 | if ($zones_data->result_info->page > 1) {
110 | $page_link = $zones_data->result_info->page - 1;
111 | $previous_page = '' . _('Previous') . ' | ';
112 | }
113 | echo '' . $previous_page . _('Page') . ' ' . $zones_data->result_info->page . '/' . $zones_data->result_info->total_pages . $next_page . '
';
114 | }
115 | if($no_api_key && isset($tlo_promotion_footer)){
116 | echo $tlo_promotion_footer;
117 | }
118 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cloudflare CNAME Setup
2 |
3 | [](https://hub.docker.com/r/ze3kr/cloudflare)
4 | [](https://github.com/ZE3kr/Cloudflare-CNAME-Setup)
5 | [](https://packagist.org/packages/ze3kr/cloudflare-cname-setup)
6 |
7 | [](https://github.com/ZE3kr/Cloudflare-CNAME-Setup/releases)
8 | [](https://hub.docker.com/r/ze3kr/cloudflare/builds)
9 | [](https://github.com/ZE3kr/Cloudflare-CNAME-Setup/releases/latest)
10 |
11 | This project allows [Cloudflare Hosting Partner][1] to provide a panel for customers, which allows customers to have [CNAME setup][2] for **free**.
12 |
13 | [查看中文版本][3]
14 |
15 | [cf.tlo.xyz][4] is the site installed the stable version of this panel. The software is up-to-date, and you can trust.
16 |
17 | [](https://stats.uptimerobot.com/NL3ERtNVwY)
18 | [](https://stats.uptimerobot.com/NL3ERtNVwY)
19 | [](https://hstspreload.org/?domain=cf.tlo.xyz)
20 |
21 |
22 | Notice: The Host API key of cf.tlo.xyz was disabled by Cloudflare.
23 |
24 | For now, all users of cf.tlo.xyz are required to log in with the Global API Key.
25 |
26 |
27 | ## Installation
28 |
29 | If you don’t want to use the preinstalled panel above, you can install this panel on your server. [For more information, please see the Wiki][6].
30 |
31 | ## Features of this panel
32 |
33 | + Manage all your DNS records in one place. Using the [Cloudflare API v4][7], this project supports various types of DNS records.
34 | + Advanced Analytics. You can see the analytics report for a whole **previous year**, rather than a month.
35 | + Supports NS setup. This panel provides NS setup information so you can switch to Cloudflare DNS at any time. You can also find your DNSSEC feature is also supported.
36 | + Supports IP setup. This service provides the anycast IPv4 and IPv6 of the CDN. You can safely use this service on the root domain.
37 | + Supports mobile devices.
38 | + Supports multi-languages.
39 |
40 | ## How to switch to this panel from NS setup
41 |
42 | 1. Backup your existing record
43 | 2. Switch your domain to another DNS services and restore the DNS record (Optional)
44 | 3. Delete your domain on Cloudflare (Might have downtime if you have not done step 2)
45 | 4. Re-add your domain on the panel
46 | 5. Setup the DNS records on this panel
47 | 6. Delete the existing DNS record and CNAME to Cloudflare (Only if you have done step 2)
48 |
49 | ## Advantages for CNAME setup
50 |
51 | + You can use any DNS provider you like, which is much more flexible.
52 | + Use Cloudflare CDN as a backup server or use multiple CDNs.
53 | + Support fourth-level subdomain SSL for free! For example, the domain like `dev.project.example.com` is ready for HTTPS. This is because, for CNAME setup, the Cloudflare issues the [SSL for SaaS][8], which is an SSL separately for each sub-domain immediately.
54 |
55 | ## Advantages when you use Cloudflare
56 |
57 | **You don’t need to install any software on your origin**. Just configure your origin server information on the panel, delete the existing DNS record and CNAME to Cloudflare or switch to Cloudflare DNS, and you are done!
58 |
59 | + Unmetered Mitigation of DDoS
60 | + Global CDN. Your website will be much faster.
61 | + I’m Under Attack™ mode
62 | + Always Online ™
63 | + Page Rules included. You can customize the cache behavior, set up 301/302 redirect, and much more.
64 |
65 | ## Screenshot
66 |
67 |
68 |
69 |
70 | ## Open-sourced software used in this project
71 |
72 | This project was based on a [HOSTLOC topic][9].
73 |
74 | + jQuery | MIT License
75 | + popper.js | MIT License
76 | + Bootstrap | MIT License
77 | + Chart.js by Nick Downie | MIT License
78 | + Guzzle by Michael Dowling [mtdowling@gmail.com][10] | MIT License
79 | + PSR Http Message by Framework Interoperability Group | MIT License
80 | + Composer | MIT License
81 | + Net\_DNS2 by Mike Pultz [mike@mikepultz.com][11] | BSD-3-Clause License
82 | + Cloudflare SDK by Cloudflare | BSD-3-Clause
83 |
84 | [1]: https://www.cloudflare.com/partners/hosting-provider/
85 | [2]: https://support.cloudflare.com/hc/en-us/articles/200168706-How-do-I-do-CNAME-setup-
86 | [3]: https://github.com/ZE3kr/Cloudflare-CNAME-Setup/blob/master/README.zh.md
87 | [4]: https://cf.tlo.xyz
88 | [6]: https://github.com/ZE3kr/Cloudflare-CNAME-Setup/wiki/Installation
89 | [7]: https://api.cloudflare.com/
90 | [8]: https://www.cloudflare.com/ssl-for-saas-providers/
91 | [9]: http://www.hostloc.com/thread-386441-1-1.html
92 | [10]: mailto:mtdowling@gmail.com
93 | [11]: mailto:mike@mikepultz.com
94 |
--------------------------------------------------------------------------------
/actions/security.php:
--------------------------------------------------------------------------------
1 |
18 | ' . strtoupper($zone_name) . ''; ?>
19 |
20 |
21 |
get('zones/' . $zoneID . '/ssl/verification?retry=true');
24 | $sslverify = json_decode($sslverify->getBody(), true)['result'];
25 | } catch (Exception $e) {
26 | $sslverify[0]['validation_method'] = 'http';
27 | }
28 |
29 | foreach ($sslverify as $sslv) {
30 | /*
31 | * We need `_tlo-wildcard` subdomain to support anycast IP information.
32 | */
33 | if (substr($sslv['hostname'], 0, 14) != '_tlo-wildcard.') {
34 | if ($sslv['validation_method'] == 'http' && isset($sslv['verification_info']['http_url']) && $sslv['verification_info']['http_url'] != '') {?>
35 |
36 |
URL:
37 |
Body:
' . _('SSL Status') . ': ' . $sslv['certificate_status'] . '';
40 | if ($sslv['verification_status']) {
41 | echo '
' . _('Verify') . ': ' . _('Success') . '
';
42 | } else {
43 | echo '
' . _('Verify') . ': ' . _('Failed') . '
';
44 | }
45 | }
46 | } elseif ($sslv['validation_method'] == 'cname' || isset($sslv['verification_info']['record_name'])) {?>
47 |
48 |
49 |
50 |
51 | |
52 | CNAME |
53 |
54 |
55 |
56 |
57 |
58 | ' . $sslv['verification_info']['record_name'] . ' |
59 | ' . $sslv['verification_info']['record_target'] . ' |
60 | ';
61 | ?>
62 |
63 |
' . _('SSL Status') . ': ' . $sslv['certificate_status'] . '';
66 | if ($sslv['verification_status']) {
67 | echo '
' . _('Verify') . ': ' . _('Success') . '
';
68 | } else {
69 | echo '
' . _('Verify') . ': ' . _('Failed') . '
';
70 | }
71 | }
72 | } elseif ($sslv['validation_method'] == 'http') {
73 | if (isset($sslv['hostname'])) {echo '
' . $sslv['hostname'] . '
';}
74 | echo _('
No error for SSL.
Just point the record(s) to Cloudflare and the SSL certificate will be issued and renewed automatically.
');
75 | } else {
76 | echo '
Unknown Verification
';
77 | print_r($sslv['verification_info']);
78 | echo '
';
79 | if ($sslv['certificate_status'] != 'active') {
80 | echo '
' . _('SSL Status') . ': ' . $sslv['certificate_status'] . '
';
81 | if ($sslv['verification_status']) {
82 | echo '
' . _('Verify') . ': ' . _('Success') . '
';
83 | } else {
84 | echo '
' . _('Verify') . ': ' . _('Failed') . '
';
85 | }
86 | }
87 | }
88 | }
89 | }
90 | ?>
91 |
(Only for NS setup)'); ?>
' . _('This feature is designed for users who use Cloudflare DNS setup. If you are using third-party DNS services, do not turn it on nor add DS record, otherwise your domain may become inaccessible.') . '';
94 |
95 | try {
96 | $dnssec = $adapter->get('zones/' . $zoneID . '/dnssec');
97 | $dnssec = json_decode($dnssec->getBody());
98 | } catch (Exception $e) {
99 | exit('
' . $e->getMessage() . '
');
100 | }
101 |
102 | if ($dnssec->result->status == 'active') {
103 | echo '
' . _('Activated') . '
DS:' . $dnssec->result->ds . '
Public Key:' . $dnssec->result->public_key . '
';
104 | echo '
' . _('Deactivate') . '
';
105 | } elseif ($dnssec->result->status == 'pending') {
106 | echo '
' . _('Pending') . '
DS:' . $dnssec->result->ds . '
Public Key:' . $dnssec->result->public_key . '
';
107 | echo '
' . _('Deactivate') . '
';
108 | } else {
109 | echo '
' . _('Not Activated') . '
';
110 | echo '
' . _('Activate') . '
';
111 | } ?>
112 |
113 |
--------------------------------------------------------------------------------
/actions/edit_record.php:
--------------------------------------------------------------------------------
1 |
8 | <- ' . _('Back') . ''; ?>
9 | getRecordDetails($_GET['zoneid'], $_GET['recordid']);
12 | if (isset($_POST['submit'])) {
13 | if (isset($_POST['proxied']) && $_POST['proxied'] == 'true') {
14 | $_POST['proxied'] = true;
15 | } else {
16 | $_POST['proxied'] = false;
17 | }
18 | $_POST['ttl'] = intval($_POST['ttl']);
19 | $_POST['type'] = $dns_details->type;
20 | if (isset($_POST['priority']) && $_POST['type'] == 'MX') {
21 | $_POST['priority'] = intval($_POST['priority']);
22 | } else {
23 | $_POST['priority'] = 10;
24 | }
25 | if (!isset($_POST['content'])) {
26 | $_POST['content'] = "";
27 | }
28 |
29 | $options = [
30 | 'type' => $dns_details->type,
31 | 'name' => $_POST['name'],
32 | 'content' => $_POST['content'],
33 | 'ttl' => intval($_POST['ttl']),
34 | 'priority' => $_POST['priority'],
35 | 'proxied' => $_POST['proxied']
36 | ];
37 |
38 | include "record_data.php";
39 |
40 | try {
41 | if ($dns->updateRecordDetails($_GET['zoneid'], $_GET['recordid'], $options)) {
42 | exit('' . _('Success') . '
');
43 | } else {
44 | echo '' . _('Failed') . '
';
45 | }
46 | } catch (Exception $e) {
47 | echo '' . _('Failed') . '
';
48 | echo '' . $e->getMessage() . '
';
49 | }
50 | }
51 | if (isset($msg)) {echo $msg;}
52 | ?>
53 |
150 |
--------------------------------------------------------------------------------
/actions/add_record.php:
--------------------------------------------------------------------------------
1 | $_POST['type'],
20 | 'name' => $_POST['name'],
21 | 'content' => $_POST['content'],
22 | 'proxied' => $_POST['proxied'],
23 | 'ttl' => intval($_POST['ttl'])
24 | ];
25 |
26 | include "record_data.php";
27 |
28 | if ($_POST['type'] == 'MX') {
29 | $options['priority'] = intval($_POST['priority']);
30 | }
31 | try {
32 | $dns = $adapter->post('zones/' . $_GET['zoneid'] . '/dns_records', $options);
33 | $dns = json_decode($dns->getBody());
34 | if (isset($dns->result->id)) {
35 | exit(
36 | '' . _('Success') .
37 | ', ' .
38 | _('Add New Record') . ', ' . _('Or') .
39 | '' .
40 | _('Go to console') . '
'
41 | );
42 | } else {
43 | exit(
44 | '' . _('Failed') .
45 | ', ' .
46 | _('Add New Record') . ', ' . _('Or') .
47 | '' .
48 | _('Go to console') . '
'
49 | );
50 | }
51 | } catch (Exception $e) {
52 | echo '' . _('Failed') . '
';
53 | echo '' . $e->getMessage() . '
';
54 | }
55 | }
56 | ?>
57 | <- ' . _('Back') . ''; ?>
58 |
161 |
--------------------------------------------------------------------------------
/cloudflare.class.php:
--------------------------------------------------------------------------------
1 | postData($data);
38 | return $res;
39 | }
40 |
41 | /**
42 | * "user_lookup" - Lookup a user's Cloudflare account information
43 | * @see https://www.cloudflare.com/docs/host-api/#s3.2.4
44 | *
45 | * @return mixed
46 | */
47 | public function userLookup() {
48 | $data['act'] = 'user_lookup';
49 | $data['cloudflare_email'] = $_COOKIE['cloudflare_email'];
50 | $res = $this->postData($data);
51 | return $res;
52 | }
53 |
54 | /**
55 | * "zone_lookup" - lookup a specific user's zone
56 | * @see https://www.cloudflare.com/docs/host-api/#s3.2.6
57 | *
58 | * @param string $zone_name
59 | * @return mixed
60 | */
61 | public function zoneLookup(string $zone_name) {
62 | $data['act'] = 'zone_lookup';
63 | $data['user_key'] = $_COOKIE['user_key'];
64 | $data['zone_name'] = $zone_name;
65 | $res = $this->postData($data);
66 | if ($res['response']['zone_exists'] == true) {
67 | return $res;
68 | } else {
69 | die(_('Error, please confirm your domain.'));
70 | }
71 | }
72 |
73 | /**
74 | * "zone_set" - Setup a User's zone for CNAME hosting
75 | * Use this to add a domain for CNAME setup or modify the existing CNAME domain's records.
76 | * @see https://www.cloudflare.com/docs/host-api/#s3.2.2
77 | *
78 | * @param string $zone_name The zone you'd like to run CNAMES through Cloudflare for, e.g. "example.com".
79 | * @param string $resolve_to The CNAME to origin server
80 | * @param string $subdomains
81 | * @return mixed
82 | */
83 | public function zoneSet(string $zone_name, string $resolve_to, string $subdomains) {
84 | $data['act'] = 'zone_set';
85 | $data['user_key'] = $_COOKIE['user_key'];
86 | $data['zone_name'] = $zone_name;
87 | $data['resolve_to'] = $resolve_to;
88 | $data['subdomains'] = $subdomains;
89 | $res = $this->postData($data);
90 | return $res;
91 | }
92 |
93 | /**
94 | * "full_zone_set" - Add a zone using the full setup method.
95 | * Full setup is just like the domain added on the cloudflare.com. But it has ability to enable partner's Railgun.
96 | * @see https://www.cloudflare.com/docs/host-api/#s3.2.3
97 | *
98 | * @param string $zone_name
99 | * @return mixed
100 | */
101 | public function zoneSet_full(string $zone_name) {
102 | $data['act'] = 'full_zone_set';
103 | $data['user_key'] = $_COOKIE['user_key'];
104 | $data['zone_name'] = $zone_name;
105 | $res = $this->postData($data);
106 | return $res;
107 | }
108 |
109 | /**
110 | * "zone_delete" - delete a specific zone on behalf of a user
111 | * @see https://www.cloudflare.com/docs/host-api/#s3.2.2
112 | *
113 | * @param $zone_name
114 | * @return mixed
115 | */
116 | public function zoneDelete($zone_name) {
117 | $data['act'] = 'zone_delete';
118 | $data['user_key'] = $_COOKIE['user_key'];
119 | $data['zone_name'] = $zone_name;
120 | $res = $this->postData($data);
121 | return $res;
122 |
123 | }
124 | }
125 |
126 | /**
127 | * Bulk edit a domain's DNS record.
128 | *
129 | * @param $zoneID
130 | * @param $subdomains
131 | * @param $zone_name
132 | * @return string
133 | */
134 | function update_bind($zoneID, $subdomains, $zone_name) {
135 | file_put_contents('/var/www/tmp/' . $zoneID . 'txt', $subdomains);
136 | $ch = curl_init();
137 | curl_setopt($ch, CURLOPT_URL, 'https://api.cloudflare.com/client/v4/zones/' . $zoneID . '/dns_records/import');
138 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
139 | curl_setopt($ch, CURLOPT_POST, 1);
140 | curl_setopt($ch, CURLOPT_HTTPHEADER, array(
141 | 'Content-Type: multipart/form-data',
142 | 'X-Auth-Email: ' . $_COOKIE['cloudflare_email'],
143 | 'X-Auth-Key: ' . $_COOKIE['user_api_key'],
144 | ));
145 | $postdata = [
146 | 'file' => new \CurlFile('/var/www/tmp/' . $zoneID . 'txt', 'text/plain', 'bind_config.txt'),
147 | ];
148 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
149 | $data = curl_exec($ch);
150 | $dataarray = json_decode($data);
151 | if (curl_error($ch)) {
152 | echo 'error:' . curl_error($ch);
153 | }
154 | curl_close($ch);
155 | unlink('/var/www/tmp/' . $zoneID . 'txt');
156 | if ($dataarray->success == true) {
157 | return _('Updated successful.') . '' . _('Back to domain') . '';
158 | } else {
159 | return $data . '
' . _('Back to domain') . '';
160 | }
161 | }
162 |
163 | /**
164 | * Convert bytes to a human readable text (B, KB, MB, GB, etc.).
165 | *
166 | * @param $bytes
167 | * @param int $precision
168 | * @return string
169 | */
170 | function formatBytes($bytes, $precision = 2) {
171 | $units = array('B', 'KB', 'MB', 'GB', 'TB');
172 |
173 | $bytes = max($bytes, 0);
174 | $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
175 | $pow = min($pow, count($units) - 1);
176 |
177 | // Uncomment one of the following alternatives
178 | $bytes /= pow(1024, $pow);
179 | // $bytes /= (1 << (10 * $pow));
180 |
181 | return round($bytes, $precision) . ' ' . $units[$pow];
182 | }
183 |
184 | /**
185 | * Convert bytes to a human readable array.
186 | * [0] is an integer.
187 | * [1] is the unit (B, KB, MB, etc.).
188 | * [2] is the unit number (0, 1, 2, etc.).
189 | *
190 | * @param $bytes
191 | * @param int $precision
192 | * @return array
193 | */
194 | function formatBytes_array($bytes, $precision = 2) {
195 | $units = array('B', 'KB', 'MB', 'GB', 'TB');
196 |
197 | $bytes = max($bytes, 0);
198 | $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
199 | $pow = min($pow, count($units) - 1);
200 |
201 | // Uncomment one of the following alternatives
202 | $bytes /= pow(1024, $pow);
203 | // $bytes /= (1 << (10 * $pow));
204 |
205 | return [round($bytes, $precision), $units[$pow], $pow];
206 | }
207 |
208 | /**
209 | * Add resources hint header for HTTP/2 Push.
210 | *
211 | * @param string $uri the relative URI for the file to push
212 | * @param string $as the file type (script, style, image, etc)
213 | */
214 | function h2push(string $uri, string $as) {
215 | global $tlo_path, $is_debug;
216 | if (isset($tlo_path) && !$is_debug) {
217 | header("Link: <{$tlo_path}{$uri}>; rel=preload; as={$as}", false);
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | */
10 |
11 | $starttime = microtime(true);
12 | $page_title = '';
13 | $version = $version ?? '';
14 |
15 | require_once 'settings.php';
16 | require_once 'cloudflare.class.php';
17 |
18 | if (!isset($_COOKIE['cloudflare_email']) || !isset($_COOKIE['user_api_key'])) {
19 | $_GET['action'] = 'login';
20 | if (isset($_POST['cloudflare_email']) && isset($_POST['cloudflare_pass'])) {
21 | $cloudflare_email = $_POST['cloudflare_email'];
22 | $cloudflare_pass = $_POST['cloudflare_pass'];
23 | $times = apcu_fetch('login_' . date("Y-m-d H") . $cloudflare_email);
24 | if ($times > 5) {
25 | $msg = '' . _('You have been blocked since you have too many fail logins. You can try it in next hour.') . '
';
26 | exit;
27 | }
28 | $cloudflare = new CloudFlare;
29 | $res = $cloudflare->userCreate($cloudflare_email, $cloudflare_pass);
30 | if ($res['result'] == 'success') {
31 | if (isset($_POST['remember'])) {
32 | $cookie_time = time() + 31536000; // Expired in 365 days.
33 | } else {
34 | $cookie_time = 0;
35 | }
36 | setcookie('cloudflare_email', $res['response']['cloudflare_email'], $cookie_time);
37 | setcookie('user_key', $res['response']['user_key'], $cookie_time);
38 | setcookie('user_api_key', $res['response']['user_api_key'], $cookie_time);
39 |
40 | header('location: ./');
41 | exit;
42 | } else {
43 | $times = $times + 1;
44 | apcu_store('login_' . date("Y-m-d H") . $cloudflare_email, $times, 7200);
45 | $msg = $res['msg'];
46 | }
47 | } else if(isset($_POST['cloudflare_api'])) {
48 | if (isset($_POST['remember'])) {
49 | $cookie_time = time() + 31536000; // Expired in 365 days.
50 | } else {
51 | $cookie_time = 0;
52 | }
53 | $key = new \Cloudflare\API\Auth\APIKey($_POST['cloudflare_email'], $_POST['cloudflare_api']);
54 | $adapter = new Cloudflare\API\Adapter\Guzzle($key);
55 | $user = new \Cloudflare\API\Endpoints\User($adapter);
56 |
57 | $times = apcu_fetch('login_' . date("Y-m-d H") . $_POST['cloudflare_email']);
58 | if ($times > 5) {
59 | $msg = '' . _('You have been blocked since you have too many fail logins. You can try it in next hour.') . '
';
60 | exit;
61 | }
62 |
63 | $success = true;
64 | try {
65 | $user_details = $user->getUserDetails();
66 | } catch (Exception $e) {
67 | echo '' . _('An error occurred. You might have provided an error email and API key pair.') . '
';
68 | echo '' . $e->getMessage() . '
';
69 | $times = $times + 1;
70 | apcu_store('login_' . date("Y-m-d H") . $_POST['cloudflare_email'], $times, 7200);
71 | $success = false;
72 | }
73 |
74 | if($success){
75 | setcookie('cloudflare_email', $_POST['cloudflare_email'], $cookie_time);
76 | setcookie('user_api_key', $_POST['cloudflare_api'], $cookie_time);
77 | header('location: ./');
78 | exit;
79 | }
80 | }
81 | } else {
82 | $key = new \Cloudflare\API\Auth\APIKey($_COOKIE['cloudflare_email'], $_COOKIE['user_api_key']);
83 | $adapter = new Cloudflare\API\Adapter\Guzzle($key);
84 | }
85 |
86 | if (!isset($_COOKIE['tlo_cached_main'])) {
87 | h2push('css/bootstrap.min.css', 'style');
88 | h2push('css/tlo.css?ver=' . urlencode($version), 'style');
89 | h2push('js/jquery-3.3.1.slim.min.js', 'script');
90 | h2push('js/bootstrap.bundle.min.js', 'script');
91 | h2push('js/main.js?ver=' . urlencode($version), 'script');
92 | setcookie('tlo_cached_main', 1);
93 | }
94 |
95 | if (isset($_GET['action']) && $_GET['action'] == 'zone' && !isset($_COOKIE['tlo_cached_cloud'])) {
96 | h2push('images/cloud_on.png', 'script');
97 | h2push('images/cloud_off.png', 'script');
98 | setcookie('tlo_cached_cloud', 1);
99 | }
100 | ?>
101 | >
102 |
103 |
104 |
105 |
106 |
107 |
108 |
126 |
127 |
128 |
129 |
130 |
131 |
150 |
151 |
199 |
200 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/actions/analytics.php:
--------------------------------------------------------------------------------
1 |
14 | /
15 |
16 |
17 |
18 |
19 |
20 | get('zones/' . $zoneID . '/analytics/dashboard', ['since' => $analytics_time]);
23 | $analytics = json_decode($analytics->getBody());
24 |
25 | $max_bandwidth = 0;
26 | foreach ($analytics->result->timeseries as $key) {
27 | if ($key->bandwidth->all > $max_bandwidth) {
28 | $max_bandwidth = $key->bandwidth->all;
29 | }
30 | }
31 | $formatBytes_array = formatBytes_array($max_bandwidth);
32 | ?>
33 |
275 |
276 |
277 |
278 | |
279 | |
280 | |
281 | |
282 | |
283 | |
284 | |
285 | |
286 |
287 |
288 |
289 |
291 | ' . _('Total (Last year)') . ' |
292 | ' . number_format($analytics->result->totals->uniques->all) . ' |
293 | ' . number_format($analytics->result->totals->pageviews->all) . ' |
294 | ' . number_format($analytics->result->totals->requests->all) . ' |
295 | ' . round($analytics->result->totals->requests->cached * 100 / $analytics->result->totals->requests->all, 1) . '% |
296 | ' . formatBytes($analytics->result->totals->bandwidth->all) . ' |
297 | ' . round($analytics->result->totals->bandwidth->cached * 100 / $analytics->result->totals->bandwidth->all, 1) . '% |
298 | ' . number_format($analytics->result->totals->threats->all) . ' |
299 | ';
300 | foreach ($analytics->result->timeseries as $key) {
301 | if ($key->requests->all != 0 && $key->bandwidth->all != 0) {
302 | echo '
303 | | ' . explode('T', $key->since)[0] . ' |
304 | ' . number_format($key->uniques->all) . ' |
305 | ' . number_format($key->pageviews->all) . ' |
306 | ' . number_format($key->requests->all) . ' |
307 | ' . round($key->requests->cached * 100 / $key->requests->all, 1) . '% |
308 | ' . formatBytes($key->bandwidth->all) . ' |
309 | ' . round($key->bandwidth->cached * 100 / $key->bandwidth->all, 1) . '% |
310 | ' . number_format($key->threats->all) . ' |
311 |
';
312 | }
313 | }
314 | ?>
315 |
316 |
317 |
--------------------------------------------------------------------------------
/actions/zone.php:
--------------------------------------------------------------------------------
1 | listRecords($zoneID, false, false, false, intval($_GET['page']));
17 | } catch (Exception $e) {
18 | exit('' . $e->getMessage() . '
');
19 | }
20 |
21 | $dnsresult = $dnsresult_data->result;
22 | $zone_name = htmlspecialchars($_GET['domain']);
23 |
24 | foreach ($dnsresult as $record) {
25 | $zone_name = $record->zone_name;
26 | $dnsids[$record->id] = true;
27 | $dnsproxyied[$record->id] = $record->proxied;
28 | $dnstype[$record->id] = $record->type;
29 | $dnscontent[$record->id] = $record->content;
30 | $dnsname[$record->id] = $record->name;
31 | $dnscheck[$record->name] = true;
32 | }
33 | ?>
34 | ' . strtoupper($zone_name) . ''; ?>
35 |
updateRecordDetails($zoneID, $_GET['enable'], ['type' => $dnstype[$_GET['enable']], 'content' => $dnscontent[$_GET['enable']], 'name' => $dnsname[$_GET['enable']], 'proxied' => true])->success == true) {
39 | echo '' . _('Success') . '!
';
40 | } else {
41 | echo '' . _('Failed') . '!
' . _('Go to console') . '
';
42 | exit();
43 | }
44 | } else {
45 | $_GET['enable'] = 1;
46 | if (isset($_GET['disable']) && $dnsproxyied[$_GET['disable']]) {
47 | if ($dns->updateRecordDetails($zoneID, $_GET['disable'], ['type' => $dnstype[$_GET['disable']], 'content' => $dnscontent[$_GET['disable']], 'name' => $dnsname[$_GET['disable']], 'proxied' => false])->success == true) {
48 | echo '' . _('Success!') . '
';
49 | } else {
50 | echo '' . _('Failed') . '!
' . _('Go to console') . '
';
51 | exit();
52 | }
53 | } else {
54 | $_GET['disable'] = 1;
55 | }
56 | }
57 | ?>
58 |
59 |
62 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | |
78 | |
79 | |
80 | |
81 | |
82 |
83 |
84 |
85 | proxiable) {
89 | if ($record->proxied) {
90 | $proxiable = '
';
91 | } else {
92 | $proxiable = '
';
93 | }
94 | } else {
95 | $proxiable = '
';
96 | }
97 | if (isset($_GET['enable']) && $record->id === $_GET['enable']) {
98 | $proxiable = '
';
99 | } elseif (isset($_GET['disable']) && $record->id === $_GET['disable']) {
100 | $proxiable = '
';
101 | }
102 | if ($record->type == 'MX') {
103 | $priority = '' . $record->priority . ' ';
104 | } else {
105 | $priority = '';
106 | }
107 | if (isset($ttl_translate[$record->ttl])) {
108 | $ttl = $ttl_translate[$record->ttl];
109 | } else {
110 | $ttl = $record->ttl . ' s';
111 | }
112 | $no_record_yet = false;
113 | echo '
114 | ' . $record->type . ' |
115 |
116 | ' . $proxiable . '
117 | ' . $record->type . ' ' . _('record') . '
118 | ' . htmlspecialchars($record->name) . '
119 | ' . _('points to') . ' ' . '' . htmlspecialchars($record->content) . '
120 |
121 |
124 |
128 |
129 | ' . _('TTL') . ' ' . $ttl . '
130 | |
131 | ' . $priority . '' . htmlspecialchars($record->content) . ' |
132 | ' . $ttl . ' |
133 | ' . $proxiable . ' |
134 |
138 | |
139 |
';
140 |
141 | }
142 | ?>
143 |
144 |
' . _('There is no record in this zone yet. Please add some!') . '';
148 | }
149 |
150 | if (isset($dnsresult_data->result_info->total_pages)) {
151 | $previous_page = '';
152 | $next_page = '';
153 | if ($dnsresult_data->result_info->page < $dnsresult_data->result_info->total_pages) {
154 | $page_link = $dnsresult_data->result_info->page + 1;
155 | $next_page = ' | ' . _('Next') . '';
156 | }
157 | if ($dnsresult_data->result_info->page > 1) {
158 | $page_link = $dnsresult_data->result_info->page - 1;
159 | $previous_page = '' . _('Previous') . ' | ';
160 | }
161 | echo '' . $previous_page . _('Page') . ' ' . $dnsresult_data->result_info->page . '/' . $dnsresult_data->result_info->total_pages . $next_page . '
';
162 | }
163 | ?>
164 |
165 |
166 |
167 |
168 |
169 |
170 | |
171 | CNAME |
172 |
173 |
174 |
175 | name])) {
180 | $last_subdomain = $record->name;
181 | echo '
182 | ' . $record->name . '
183 | ' . _('points to') . ' ' . $record->name . '.cdn.cloudflare.net
184 | |
185 | ' . $record->name . '.cdn.cloudflare.net |
186 |
';
187 | $avoid_cname_duplicated[$record->name] = true;
188 | }
189 | }
190 | ?>
191 |
192 |
' . _('There is no record in this zone yet. Please add some!') . '';
196 | }
197 |
198 | if (isset($dnsresult_data->result_info->total_pages)) {
199 | $previous_page = '';
200 | $next_page = '';
201 | if ($dnsresult_data->result_info->page < $dnsresult_data->result_info->total_pages) {
202 | $page_link = $dnsresult_data->result_info->page + 1;
203 | $next_page = ' | ' . _('Next') . '';
204 | }
205 | if ($dnsresult_data->result_info->page > 1) {
206 | $page_link = $dnsresult_data->result_info->page - 1;
207 | $previous_page = '' . _('Previous') . ' | ';
208 | }
209 | echo '' . $previous_page . _('Page') . ' ' . $dnsresult_data->result_info->page . '/' . $dnsresult_data->result_info->total_pages . $next_page . '
';
210 | }
211 |
212 | $resp_cache = apcu_fetch('tlo_cf_'.$zone_name);
213 | if ($last_subdomain != '' && !$resp_cache) {
214 | try {
215 | $resolver = new Net_DNS2_Resolver(array('nameservers' => array('173.245.59.31', '2400:cb00:2049:1::adf5:3b1f')));
216 | $resp = $resolver->query($zone_name, 'NS');
217 | $resp_a = $resolver->query($last_subdomain . '.cdn.cloudflare.net', 'A');
218 | $resp_aaaa = $resolver->query($last_subdomain . '.cdn.cloudflare.net', 'AAAA');
219 | } catch (Net_DNS2_Exception $e) {
220 | // echo $e->getMessage();
221 | }
222 | } else {
223 | $resp = $resp_cache['ns'];
224 | $resp_a = $resp_cache['a'];
225 | $resp_aaaa = $resp_cache['aaaa'];
226 | }
227 |
228 | if ($last_subdomain != '' && (isset($resp_a->answer[0]->address) && isset($resp_a->answer[1]->address)) ||
229 | (isset($resp_aaaa->answer[0]->address) && isset($resp_aaaa->answer[1]->address))) {
230 | ?>
231 |
232 | answer[0]->address) && isset($resp_a->answer[1]->address)) { ?>
233 | Anycast IPv4
234 |
235 | answer[0]->address; ?>
236 | answer[1]->address; ?>
237 |
238 | answer[0]->address) && isset($resp_aaaa->answer[1]->address)) { ?>
239 | Anycast IPv6
240 |
241 | answer[0]->address; ?>
242 | answer[1]->address; ?>
243 |
244 | answer[0]->nsdname) && isset($resp->answer[1]->nsdname)) {
248 | apcu_store('tlo_cf_'.$zone_name, [
249 | 'a' => $resp_a,
250 | 'aaaa' => $resp_aaaa,
251 | 'ns' => $resp,
252 | ], 172800); // Two days
253 | ?>
254 |
255 |
256 |
257 |
258 | |
259 | NS |
260 |
261 |
262 |
263 |
264 |
265 | ' . $resp->answer[0]->nsdname . '' ?>
266 | |
267 | answer[0]->nsdname; ?> |
268 |
269 |
270 |
271 | ' . $resp->answer[1]->nsdname . '' ?>
272 | |
273 | answer[1]->nsdname; ?> |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
--------------------------------------------------------------------------------
/languages/zh_CN.UTF-8/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: \n"
4 | "POT-Creation-Date: 2020-04-29 20:27+0800\n"
5 | "PO-Revision-Date: 2020-04-29 20:30+0800\n"
6 | "Last-Translator: \n"
7 | "Language-Team: \n"
8 | "Language: zh_CN\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "X-Generator: Poedit 2.3\n"
13 | "X-Poedit-Basepath: ../../..\n"
14 | "Plural-Forms: nplurals=1; plural=0;\n"
15 | "X-Poedit-SearchPath-0: .\n"
16 |
17 | #: actions/add.php:18 actions/add.php:73 actions/add_record.php:35
18 | #: actions/delete_record.php:11 actions/dnssec.php:16
19 | #: actions/edit_record.php:42 actions/logout.php:12 actions/security.php:41
20 | #: actions/security.php:67 actions/security.php:82 actions/zone.php:52
21 | msgid "Success"
22 | msgstr "成功"
23 |
24 | #: actions/add.php:18 actions/add.php:73 actions/add_record.php:35
25 | #: actions/add_record.php:37 actions/delete_record.php:11
26 | #: actions/delete_record.php:13 actions/dnssec.php:16 actions/dnssec.php:18
27 | #: actions/logout.php:12 actions/zone.php:54 actions/zone.php:63
28 | msgid "Go to console"
29 | msgstr "前往管理中心"
30 |
31 | #: actions/add.php:45
32 | msgid "Cannot add a existing domain."
33 | msgstr "无法添加已经存在的域名."
34 |
35 | #: actions/add.php:88 actions/list_zones.php:26
36 | msgid "Domain"
37 | msgstr "域名"
38 |
39 | #: actions/add.php:89
40 | msgid "Please enter your domain"
41 | msgstr "请输入你的域名"
42 |
43 | #: actions/add.php:90 actions/add_record.php:143 actions/edit_record.php:147
44 | msgid "Submit"
45 | msgstr "提交"
46 |
47 | #: actions/add_record.php:35 actions/add_record.php:37 actions/zone.php:85
48 | msgid "Add New Record"
49 | msgstr "添加新记录"
50 |
51 | #: actions/add_record.php:35 actions/add_record.php:37
52 | msgid "Or"
53 | msgstr "或者"
54 |
55 | #: actions/add_record.php:37 actions/add_record.php:40
56 | #: actions/delete_record.php:13 actions/dnssec.php:18
57 | #: actions/edit_record.php:44 actions/edit_record.php:47
58 | #: actions/security.php:43 actions/security.php:69 actions/security.php:84
59 | #: actions/zone.php:54 actions/zone.php:63
60 | msgid "Failed"
61 | msgstr "失败"
62 |
63 | #: actions/add_record.php:45 actions/edit_record.php:8
64 | msgid "Back"
65 | msgstr "返回"
66 |
67 | #: actions/add_record.php:48
68 | msgid "Add DNS Record"
69 | msgstr "添加 DNS 记录"
70 |
71 | #: actions/add_record.php:50 actions/edit_record.php:57
72 | msgid "Record Name (e.g. “@”, “www”, etc.)"
73 | msgstr "记录名 (例 “@”, “www”, etc.)"
74 |
75 | #: actions/add_record.php:54 actions/edit_record.php:61 actions/zone.php:90
76 | msgid "Record Type"
77 | msgstr "记录类型"
78 |
79 | #: actions/add_record.php:70 actions/edit_record.php:116
80 | msgid "Record Content"
81 | msgstr "记录内容"
82 |
83 | #: actions/add_record.php:75 actions/add_record.php:109
84 | #: actions/edit_record.php:99 actions/edit_record.php:121
85 | msgid "Priority"
86 | msgstr "权重 (Priority)"
87 |
88 | #: actions/add_record.php:81 actions/edit_record.php:69
89 | msgid "Tag"
90 | msgstr "标签 (Tag)"
91 |
92 | #: actions/add_record.php:83 actions/edit_record.php:71
93 | msgid "Only allow specific hostnames"
94 | msgstr "仅允许特定主机名"
95 |
96 | #: actions/add_record.php:84 actions/edit_record.php:72
97 | msgid "Only allow wildcards"
98 | msgstr "仅允许通配符"
99 |
100 | #: actions/add_record.php:85 actions/edit_record.php:73
101 | msgid "Send violation reports to URL (http:, https:, or mailto:)"
102 | msgstr "发送违规报告到 URL (http:, https:, 或 mailto:)"
103 |
104 | #: actions/add_record.php:89 actions/edit_record.php:77
105 | msgid "Value"
106 | msgstr "值 (Value)"
107 |
108 | #: actions/add_record.php:97 actions/edit_record.php:83
109 | msgid "Service"
110 | msgstr "服务 (Service)"
111 |
112 | #: actions/add_record.php:101 actions/edit_record.php:87
113 | msgid "Proto"
114 | msgstr "协议 (Proto)"
115 |
116 | #: actions/add_record.php:113 actions/edit_record.php:103
117 | msgid "Weight"
118 | msgstr "权重 (Weight)"
119 |
120 | #: actions/add_record.php:117 actions/edit_record.php:107
121 | msgid "Port"
122 | msgstr "端口 (Port)"
123 |
124 | #: actions/add_record.php:121 actions/edit_record.php:111
125 | msgid "Target"
126 | msgstr "目标 (Target)"
127 |
128 | #: actions/add_record.php:139 actions/edit_record.php:141
129 | msgid "On"
130 | msgstr "开启"
131 |
132 | #: actions/add_record.php:140 actions/edit_record.php:142
133 | msgid "Off"
134 | msgstr "关闭"
135 |
136 | #: actions/analytics.php:14 actions/list_zones.php:42
137 | msgid "Advanced Analytics"
138 | msgstr "高级统计"
139 |
140 | #: actions/analytics.php:15
141 | msgid "Loading failed. Please refresh the page to retry."
142 | msgstr "加载失败,请刷新页面重试。"
143 |
144 | #: actions/analytics.php:58 actions/analytics.php:204
145 | msgid "Cached"
146 | msgstr "已缓存"
147 |
148 | #: actions/analytics.php:70 actions/analytics.php:216
149 | msgid "All"
150 | msgstr "全部"
151 |
152 | #: actions/analytics.php:88 actions/analytics.php:110 actions/analytics.php:161
153 | #: actions/analytics.php:183 actions/analytics.php:281
154 | msgid "Requests"
155 | msgstr "请求"
156 |
157 | #: actions/analytics.php:103 actions/analytics.php:176
158 | #: actions/analytics.php:249 actions/analytics.php:278
159 | msgid "Date"
160 | msgstr "日期"
161 |
162 | #: actions/analytics.php:131 actions/analytics.php:279
163 | msgid "Unique Visitors"
164 | msgstr "独立访客数"
165 |
166 | #: actions/analytics.php:143 actions/analytics.php:280
167 | msgid "Page Views"
168 | msgstr "页面浏览量"
169 |
170 | #: actions/analytics.php:234 actions/analytics.php:256
171 | msgid "Bandwidth (Unit: "
172 | msgstr "流量 (单位: "
173 |
174 | #: actions/analytics.php:282
175 | msgid "Requests Hit Ratio"
176 | msgstr "缓存命中率"
177 |
178 | #: actions/analytics.php:283
179 | msgid "Bandwidth"
180 | msgstr "流量"
181 |
182 | #: actions/analytics.php:284
183 | msgid "Saved Bandwidth"
184 | msgstr "节省流量"
185 |
186 | #: actions/analytics.php:285
187 | msgid "Threats"
188 | msgstr "攻击拦截"
189 |
190 | #: actions/analytics.php:291
191 | msgid "Total (Last year)"
192 | msgstr "总计 (最近一年)"
193 |
194 | #: actions/edit_record.php:55
195 | msgid "Edit DNS Record"
196 | msgstr "编辑 DNS 记录"
197 |
198 | #: actions/edit_record.php:95
199 | msgid "Name"
200 | msgstr "主机名"
201 |
202 | #: actions/list_zones.php:13 languages/translates.php:30
203 | msgid "Add Domain"
204 | msgstr "添加域名"
205 |
206 | #: actions/list_zones.php:15
207 | msgid "Home"
208 | msgstr "主页"
209 |
210 | #: actions/list_zones.php:20 actions/login2.php:15
211 | msgid "No Host API key found. You cannot add new domain to this service."
212 | msgstr "没有找到 Host API key。你不能添加新域名。"
213 |
214 | #: actions/list_zones.php:27
215 | msgid "Status"
216 | msgstr "状态"
217 |
218 | #: actions/list_zones.php:28 actions/zone.php:94
219 | msgid "Operation"
220 | msgstr "操作"
221 |
222 | #: actions/list_zones.php:43 actions/zone.php:136
223 | msgid "Manage"
224 | msgstr "管理"
225 |
226 | #: actions/list_zones.php:44 actions/list_zones.php:86
227 | msgid "Manage DNS"
228 | msgstr "管理 DNS"
229 |
230 | #: actions/list_zones.php:45 languages/translates.php:25
231 | msgid "Security"
232 | msgstr "安全"
233 |
234 | #: actions/list_zones.php:86
235 | msgid ""
236 | "This domain only supports NS setup. And you should manage DNS records on "
237 | "Cloudflare.com."
238 | msgstr "这个域名只支持 NS 接入. 你应该在 Cloudflare.com 上管理 DNS 记录."
239 |
240 | #: actions/list_zones.php:107 actions/zone.php:169 actions/zone.php:216
241 | msgid "Next"
242 | msgstr "下一页"
243 |
244 | #: actions/list_zones.php:111 actions/zone.php:173 actions/zone.php:220
245 | msgid "Previous"
246 | msgstr "上一页"
247 |
248 | #: actions/list_zones.php:113 actions/zone.php:175 actions/zone.php:222
249 | msgid "Page"
250 | msgstr "页码"
251 |
252 | #: actions/login.php:10 actions/login2.php:10
253 | msgid "Cloudflare CNAME/IP/NS Setup"
254 | msgstr "Cloudflare CNAME/IP/NS 接入"
255 |
256 | #: actions/login.php:12 actions/login2.php:19
257 | msgid "Please sign in"
258 | msgstr "请先登录"
259 |
260 | #: actions/login.php:13 actions/login.php:14 actions/login2.php:20
261 | #: actions/login2.php:21
262 | msgid "Your email address on cloudflare.com"
263 | msgstr "你在 cloudflare.com 上的邮箱"
264 |
265 | #: actions/login.php:15 actions/login.php:16
266 | msgid "Your password on cloudflare.com"
267 | msgstr "你在 cloudflare.com 上的密码"
268 |
269 | #: actions/login.php:19 actions/login2.php:27
270 | msgid "Remember me"
271 | msgstr "下次自动登录"
272 |
273 | #: actions/login.php:22 actions/login2.php:30
274 | msgid "Sign in"
275 | msgstr "登录"
276 |
277 | #: actions/login.php:23
278 | msgid "Use your existing account or create a new account here."
279 | msgstr "在这里登录你已有的账号或者注册新账号."
280 |
281 | #: actions/login.php:24 actions/login2.php:32
282 | msgid "We will not store any of your Cloudflare data"
283 | msgstr "我们不会存储你的任何 Cloudflare 数据"
284 |
285 | #: actions/login2.php:22 actions/login2.php:24
286 | msgid "Your global API key on cloudflare.com"
287 | msgstr "你在 cloudflare.com 上的 Global API key"
288 |
289 | #: actions/login2.php:24
290 | msgid "Your global API key. NOT your password."
291 | msgstr "请输入 Global API Key,而不是你的账户密码."
292 |
293 | #: actions/login2.php:31
294 | msgid "How to get my global API key?"
295 | msgstr "如何获取我的 Global API Key?"
296 |
297 | #: actions/security.php:21
298 | msgid "SSL Verify"
299 | msgstr "SSL 验证"
300 |
301 | #: actions/security.php:35
302 | #, php-format
303 | msgid "HTTP File Verify for %s"
304 | msgstr "%s 下的 HTTP 文件验证"
305 |
306 | #: actions/security.php:39 actions/security.php:65 actions/security.php:80
307 | msgid "SSL Status"
308 | msgstr "SSL 状态"
309 |
310 | #: actions/security.php:41 actions/security.php:43 actions/security.php:67
311 | #: actions/security.php:69 actions/security.php:82 actions/security.php:84
312 | msgid "Verify"
313 | msgstr "验证"
314 |
315 | #: actions/security.php:47
316 | msgid "CNAME Verify"
317 | msgstr "CNAME 验证"
318 |
319 | #: actions/security.php:51
320 | msgid "SSL Verification Record Name"
321 | msgstr "SSL 验证记录名"
322 |
323 | #: actions/security.php:74
324 | msgid ""
325 | "No error for SSL.
Just point the record(s) "
326 | "to Cloudflare and the SSL certificate will be issued and renewed "
327 | "automatically.
"
328 | msgstr ""
329 | "SSL 正常。
你只需要将默认/海外记录指向 "
330 | "Cloudflare, SSL 证书便会自动签发和续期。
"
331 |
332 | #: actions/security.php:91
333 | msgid "DNSSEC (Only for NS setup)"
334 | msgstr "DNSSEC (仅限 NS 接入)"
335 |
336 | #: actions/security.php:93 actions/security.php:110
337 | msgid ""
338 | "This feature is designed for users who use Cloudflare DNS setup. If you are "
339 | "using third-party DNS services, do not turn it on nor add DS record, "
340 | "otherwise your domain may become inaccessible."
341 | msgstr ""
342 | "此功能仅限配置了 Cloudflare DNS 的用户使用, 如果你使用的是第三方 DNS 服务,请"
343 | "不要开启此功能,也不要配置 DS 记录, 否则可能会导致域名无法访问。"
344 |
345 | #: actions/security.php:103
346 | msgid "Activated"
347 | msgstr "已激活"
348 |
349 | #: actions/security.php:104 actions/security.php:107
350 | msgid "Deactivate"
351 | msgstr "关闭"
352 |
353 | #: actions/security.php:106 languages/translates.php:17
354 | msgid "Pending"
355 | msgstr "等待中"
356 |
357 | #: actions/security.php:109
358 | msgid "Not Activated"
359 | msgstr "未激活"
360 |
361 | #: actions/security.php:110
362 | msgid "Activate"
363 | msgstr "开启"
364 |
365 | #: actions/zone.php:61
366 | msgid "Success!"
367 | msgstr "成功!"
368 |
369 | #: actions/zone.php:73
370 | msgid "Contents"
371 | msgstr "目录"
372 |
373 | #: actions/zone.php:76 actions/zone.php:84
374 | msgid "DNS Management"
375 | msgstr "DNS 管理"
376 |
377 | #: actions/zone.php:77 actions/zone.php:180
378 | msgid "CNAME Setup"
379 | msgstr "CNAME 接入"
380 |
381 | #: actions/zone.php:78 actions/zone.php:235
382 | msgid "IP Setup"
383 | msgstr "IP 接入"
384 |
385 | #: actions/zone.php:79 actions/zone.php:251
386 | msgid "NS Setup"
387 | msgstr "NS 接入"
388 |
389 | #: actions/zone.php:81 actions/zone.php:277 actions/zone.php:278
390 | msgid "More Settings"
391 | msgstr "更多设置"
392 |
393 | #: actions/zone.php:91 actions/zone.php:184 actions/zone.php:255
394 | msgid "Host Name"
395 | msgstr "主机名"
396 |
397 | #: actions/zone.php:92
398 | msgid "Content"
399 | msgstr "内容"
400 |
401 | #: actions/zone.php:93 actions/zone.php:143
402 | msgid "TTL"
403 | msgstr "TTL"
404 |
405 | #: actions/zone.php:131
406 | msgid "record"
407 | msgstr "记录"
408 |
409 | #: actions/zone.php:133 actions/zone.php:196 actions/zone.php:262
410 | #: actions/zone.php:268
411 | msgid "points to"
412 | msgstr "指向"
413 |
414 | #: actions/zone.php:139 actions/zone.php:149
415 | msgid "Edit"
416 | msgstr "编辑"
417 |
418 | #: actions/zone.php:140 actions/zone.php:150
419 | msgid "Are you sure to delete"
420 | msgstr "你确认要删除"
421 |
422 | #: actions/zone.php:140 actions/zone.php:150
423 | msgid "Delete"
424 | msgstr "删除"
425 |
426 | #: actions/zone.php:161 actions/zone.php:208
427 | msgid "There is no record in this zone yet. Please add some!"
428 | msgstr "该域名还没有任何记录, 请添加!"
429 |
430 | #: actions/zone.php:178
431 | msgid "You can use CNAME, IP or NS to set it up."
432 | msgstr "你可以使用 CNAME, IP 和 NS 任意一种方式接入。"
433 |
434 | #: actions/zone.php:278
435 | msgid ""
436 | "This site only provides configurations that the official does not have. For "
437 | "more settings, such as Page Rules, Crypto, Firewall, Cache, etc., please use "
438 | "the same account to login Cloudflare.com to setup. "
439 | msgstr ""
440 | "本站只提供官网之外的配置。更多设置,如 Page Rules、SSL 回源配置、防火墙、缓存"
441 | "配置等,请使用相同账号登录 Cloudflare.com 查看. "
442 |
443 | #: cloudflare.class.php:69
444 | msgid "Error, please confirm your domain."
445 | msgstr "错误,请检查你的域名."
446 |
447 | #: cloudflare.class.php:157
448 | msgid "Updated successful."
449 | msgstr "更新成功."
450 |
451 | #: cloudflare.class.php:157 cloudflare.class.php:159
452 | msgid "Back to domain"
453 | msgstr "返回到域名"
454 |
455 | #: index.php:25 index.php:59
456 | msgid ""
457 | "You have been blocked since you have too many fail logins. You can try it in "
458 | "next hour."
459 | msgstr "由于你多次登录失败,已经被屏蔽,请在下一个小时再试。"
460 |
461 | #: index.php:67
462 | msgid ""
463 | "An error occurred. You might have provided an error email and API key pair."
464 | msgstr "发生了一个错误。你可能提供了一组错误的邮箱和 API 对。"
465 |
466 | #: index.php:121 index.php:159
467 | msgid "Console"
468 | msgstr "面板"
469 |
470 | #: index.php:124 settings.php:73
471 | msgid "Cloudflare CNAME/IP Advanced Setup"
472 | msgstr "Cloudflare CNAME/IP 高级接入"
473 |
474 | #: index.php:163 languages/translates.php:24
475 | msgid "Logout"
476 | msgstr "退出登录"
477 |
478 | #: index.php:220
479 | msgid "Cloudflare Support"
480 | msgstr "Cloudflare 支持"
481 |
482 | #: index.php:221 settings.php:110
483 | msgid "View on GitHub"
484 | msgstr "在 GitHub 上查看"
485 |
486 | #: languages/translates.php:3
487 | msgid "Automatic"
488 | msgstr "自动"
489 |
490 | #: languages/translates.php:4
491 | msgid "2 mins"
492 | msgstr "2 分钟"
493 |
494 | #: languages/translates.php:5
495 | msgid "5 mins"
496 | msgstr "5 分钟"
497 |
498 | #: languages/translates.php:6
499 | msgid "10 mins"
500 | msgstr "10 分钟"
501 |
502 | #: languages/translates.php:7
503 | msgid "15 mins"
504 | msgstr "15 分钟"
505 |
506 | #: languages/translates.php:8
507 | msgid "30 mins"
508 | msgstr "30 分钟"
509 |
510 | #: languages/translates.php:9
511 | msgid "1 hour"
512 | msgstr "1 小时"
513 |
514 | #: languages/translates.php:10
515 | msgid "2 hours"
516 | msgstr "2 小时"
517 |
518 | #: languages/translates.php:11
519 | msgid "5 hours"
520 | msgstr "5 小时"
521 |
522 | #: languages/translates.php:12
523 | msgid "12 hours"
524 | msgstr "12 小时"
525 |
526 | #: languages/translates.php:13
527 | msgid "1 day"
528 | msgstr "1 天"
529 |
530 | #: languages/translates.php:16
531 | msgid "Active"
532 | msgstr "已激活"
533 |
534 | #: languages/translates.php:18
535 | msgid "Initializing"
536 | msgstr "初始化中"
537 |
538 | #: languages/translates.php:19
539 | msgid "Moved"
540 | msgstr "已移动"
541 |
542 | #: languages/translates.php:21
543 | msgid "Deactivated"
544 | msgstr "未激活"
545 |
546 | #: languages/translates.php:26
547 | msgid "Add Record"
548 | msgstr "添加记录"
549 |
550 | #: languages/translates.php:27
551 | msgid "Edit Record"
552 | msgstr "编辑记录"
553 |
554 | #: languages/translates.php:28
555 | msgid "Delete Record"
556 | msgstr "删除记录"
557 |
558 | #: languages/translates.php:29
559 | msgid "Analytics"
560 | msgstr "统计"
561 |
562 | #: languages/translates.php:31
563 | msgid "Manage Zone"
564 | msgstr "管理域名"
565 |
566 | #: languages/translates.php:32
567 | msgid "DNSSEC"
568 | msgstr "DNSSEC"
569 |
570 | #: languages/translates.php:33
571 | msgid "Login"
572 | msgstr "登录"
573 |
574 | #: settings.php:73 settings.php:89
575 | msgid "Error"
576 | msgstr "错误"
577 |
578 | #: settings.php:96
579 | msgid "Cannot find the file:"
580 | msgstr "找不到文件:"
581 |
582 | #: settings.php:99
583 | msgid ""
584 | "It probably means that composer dependencies are not installed "
585 | "properly."
586 | msgstr "或许 composer 依赖没有被正确安装。"
587 |
588 | #: settings.php:100
589 | msgid "You will need to run the following codes to install the dependencies:"
590 | msgstr "你需要运行下方代码以安装这些依赖:"
591 |
592 | #: settings.php:103
593 | msgid ""
594 | "If you do not have the composer, install it first (you may need "
595 | "to run it with sudo):"
596 | msgstr ""
597 | "如果你还没有 composer,请先安装 (你可能需要使用 sudo"
598 | "code>):"
599 |
600 | #~ msgid "No HOST_KEY or HOST_MAIL defined in config.php ."
601 | #~ msgstr "没有在 config.php 中设置 HOST_KEY 或 HOST_MAIL ."
602 |
603 | #~ msgid "Please set up your own HOST_KEY and HOST_MAIL in config.php ."
604 | #~ msgstr "请在 config.php 中设置你自己的 HOST_KEY 和 HOST_MAIL."
605 |
--------------------------------------------------------------------------------