diff --git a/apis/commands/opensrs_domains_dnssec.php b/apis/commands/opensrs_domains_dnssec.php new file mode 100644 index 0000000..ef1beb7 --- /dev/null +++ b/apis/commands/opensrs_domains_dnssec.php @@ -0,0 +1,77 @@ + 'dnssec'. + * + * @copyright Copyright (c) 2021, Phillips Data, Inc. + * @license http://opensource.org/licenses/mit-license.php MIT License + * @package opensrs.commands + */ +class OpensrsDomainsDnssec +{ + /** + * @var OpensrsApi + */ + private $api; + + /** + * Sets the API to use for communication + * + * @param OpensrsApi $api The API to use for communication + */ + public function __construct(OpensrsApi $api) + { + $this->api = $api; + } + + /** + * Gets the DNSSEC DS records for a domain. + * + * @param array $vars An array of input params including: + * - domain The domain name + * @return OpensrsResponse The response object + */ + public function getDnssecRecords(array $vars) : OpensrsResponse + { + return $this->api->submit('get', array_merge($vars, [ + 'type' => 'dnssec' + ])); + } + + /** + * Adds a DNSSEC DS record to a domain. + * + * @param array $vars An array of input params including: + * - domain The domain name + * - dnssec Array of DS records, each containing: + * - key_tag The key tag + * - algorithm The algorithm number + * - digest_type The digest type + * - digest The digest value + * @return OpensrsResponse The response object + */ + public function addDnssecRecord(array $vars) : OpensrsResponse + { + return $this->api->submit('modify', array_merge($vars, [ + 'data' => 'dnssec', + 'affect_domains' => '0' + ])); + } + + /** + * Removes DNSSEC DS records from a domain. + * + * @param array $vars An array of input params including: + * - domain The domain name + * - dnssec Empty array to clear all DS records + * @return OpensrsResponse The response object + */ + public function removeDnssecRecord(array $vars) : OpensrsResponse + { + return $this->api->submit('modify', array_merge($vars, [ + 'data' => 'dnssec', + 'affect_domains' => '0' + ])); + } +} diff --git a/apis/commands/opensrs_domains_forwarding.php b/apis/commands/opensrs_domains_forwarding.php new file mode 100644 index 0000000..d07efc7 --- /dev/null +++ b/apis/commands/opensrs_domains_forwarding.php @@ -0,0 +1,80 @@ +api = $api; + } + + /** + * Gets domain forwarding settings for the specified domain. + * + * @param array $vars An array of input params including: + * - domain The domain name + * @return OpensrsResponse The response object + */ + public function getDomainForwarding(array $vars) : OpensrsResponse + { + return $this->api->submit('get', array_merge($vars, ['type' => 'forwarding_email'])); + } + + /** + * Sets URL forwarding for the specified domain. + * + * @param array $vars An array of input params including: + * - domain The domain name + * - forwarding_uri The destination URL + * @return OpensrsResponse The response object + */ + public function setDomainForwarding(array $vars) : OpensrsResponse + { + return $this->api->submit('modify', array_merge($vars, [ + 'data' => 'forwarding_email', + 'affect_domains' => '0' + ])); + } + + /** + * Creates URL forwarding for the specified domain via DNS zone. + * + * @param array $vars An array of input params including: + * - source The source subdomain or @ for root + * - destination The destination URL + * - type The redirect type (301, 302, or frame) + * - domain The domain name + * @return OpensrsResponse The response object + */ + public function createDomainForwarding(array $vars) : OpensrsResponse + { + return $this->api->submit('set_dns_zone', $vars); + } + + /** + * Deletes URL forwarding for the specified domain. + * + * @param array $vars An array of input params including: + * - domain The domain name + * @return OpensrsResponse The response object + */ + public function deleteDomainForwarding(array $vars) : OpensrsResponse + { + return $this->api->submit('set_dns_zone', $vars); + } +} diff --git a/apis/opensrs_api.php b/apis/opensrs_api.php index 246d36b..d536b26 100644 --- a/apis/opensrs_api.php +++ b/apis/opensrs_api.php @@ -9,6 +9,10 @@ . DIRECTORY_SEPARATOR . 'opensrs_domains_provisioning.php'; require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'commands' . DIRECTORY_SEPARATOR . 'opensrs_domains_transfer.php'; +require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'commands' + . DIRECTORY_SEPARATOR . 'opensrs_domains_forwarding.php'; +require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'commands' + . DIRECTORY_SEPARATOR . 'opensrs_domains_dnssec.php'; require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'commands' . DIRECTORY_SEPARATOR . 'opensrs_ssl.php'; require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'commands' . DIRECTORY_SEPARATOR . 'opensrs_users.php'; @@ -44,6 +48,11 @@ class OpensrsApi */ private $sandbox; + /** + * @var mixed The logger instance + */ + private $logger; + /** * @var array An array representing the last request made */ @@ -87,11 +96,11 @@ public function submit(string $command, array $args = [], string $object = 'doma } // Build signature - $siganture = md5($xml_request . $this->key); + $signature = md5($xml_request . $this->key); $headers = [ 'Content-Type: text/xml', 'X-Username: ' . trim($this->username), - 'X-Signature: ' . md5($siganture . $this->key), + 'X-Signature: ' . md5($signature . $this->key), 'Content-Length: ' . strlen($xml_request) ]; @@ -109,6 +118,8 @@ public function submit(string $command, array $args = [], string $object = 'doma curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_request); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); + curl_setopt($ch, CURLOPT_TIMEOUT, 60); if (Configure::get('Blesta.curl_verify_ssl')) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); @@ -120,8 +131,11 @@ public function submit(string $command, array $args = [], string $object = 'doma $response = curl_exec($ch); - if ($response == false) { + if ($response === false) { $this->logger->error(curl_error($ch)); + curl_close($ch); + + return new OpensrsResponse(''); } curl_close($ch); @@ -182,11 +196,11 @@ private function buildRecursiveAttributes(SimpleXMLElement &$dt_assoc, array $ar if (is_array($value)) { $assoc = $dt_assoc->addChild('item'); $assoc->addAttribute('key', $key); - $assoc = $assoc->addChild(isset($value[0]) ? 'dt_array' : 'dt_assoc'); + $assoc = $assoc->addChild((empty($value) || isset($value[0])) ? 'dt_array' : 'dt_assoc'); $this->buildRecursiveAttributes($assoc, $value); } else { - $dt_assoc->addChild('item', $value) + $dt_assoc->addChild('item', htmlspecialchars((string) $value, ENT_XML1, 'UTF-8')) ->addAttribute('key', $key); } } diff --git a/apis/opensrs_response.php b/apis/opensrs_response.php index f89293d..9b89d24 100755 --- a/apis/opensrs_response.php +++ b/apis/opensrs_response.php @@ -53,13 +53,13 @@ public function response() : ?object * * @return string The status (OK = success, ERROR = error, null = invalid responses) */ - public function status() : ?string + public function status() : string { if ($this->xml && $this->xml instanceof SimpleXMLElement) { return ($this->formatResponse($this->xml->body->data_block)->is_success ?? false) ? 'OK' : 'ERROR'; } - return null; + return 'ERROR'; } /** @@ -70,18 +70,32 @@ public function status() : ?string public function errors() : ?object { if ($this->xml && $this->xml instanceof SimpleXMLElement) { - $error = 'Internal Server Error'; + $data = $this->formatResponse($this->xml->body->data_block); + + $error_msg = $data->attributes['error'] + ?? $data->response_text + ?? 'Internal Server Error'; + + // Extract detailed per-domain error messages from attributes.details + $details = []; + if (isset($data->attributes['details']) && is_array($data->attributes['details'])) { + foreach ($data->attributes['details'] as $domain => $info) { + if (is_array($info) && !empty($info['response_text'])) { + $details[] = trim($info['response_text']); + } + } + } - $error_msg = $this->formatResponse($this->xml->body->data_block)->attributes['error'] - ?? $this->formatResponse($this->xml->body->data_block)->response_text - ?? $error; + if (!empty($details)) { + $error_msg = implode('; ', $details); + } return (object)[ 'response_text' => $error_msg, - 'response_code' => $this->formatResponse($this->xml->body->data_block)->response_code ?? 500 + 'response_code' => $data->response_code ?? 500 ]; } - + return null; } @@ -92,7 +106,7 @@ public function errors() : ?object */ public function raw() : string { - return $this->raw; + return $this->raw ?? ''; } /** diff --git a/config/opensrs.php b/config/opensrs.php index c8a348e..8153c1a 100755 --- a/config/opensrs.php +++ b/config/opensrs.php @@ -1,4 +1,256 @@ "Afghanistan", +"AX" => "Åland Islands", +"AL" => "Albania", +"DZ" => "Algeria", +"AS" => "American Samoa", +"AD" => "Andorra", +"AO" => "Angola", +"AI" => "Anguilla", +"AQ" => "Antarctica", +"AG" => "Antigua and Barbuda", +"AR" => "Argentina", +"AM" => "Armenia", +"AW" => "Aruba", +"AU" => "Australia", +"AT" => "Austria", +"AZ" => "Azerbaijan", +"BS" => "Bahamas", +"BH" => "Bahrain", +"BD" => "Bangladesh", +"BB" => "Barbados", +"BY" => "Belarus", +"BE" => "Belgium", +"BZ" => "Belize", +"BJ" => "Benin", +"BM" => "Bermuda", +"BT" => "Bhutan", +"BO" => "Bolivia, Plurinational State of", +"BQ" => "Bonaire, Sint Eustatius and Saba", +"BA" => "Bosnia and Herzegovina", +"BW" => "Botswana", +"BV" => "Bouvet Island", +"BR" => "Brazil", +"IO" => "British Indian Ocean Territory", +"BN" => "Brunei Darussalam", +"BG" => "Bulgaria", +"BF" => "Burkina Faso", +"BI" => "Burundi", +"CV" => "Cabo Verde", +"KH" => "Cambodia", +"CM" => "Cameroon", +"CA" => "Canada", +"KY" => "Cayman Islands", +"CF" => "Central African Republic", +"TD" => "Chad", +"CL" => "Chile", +"CN" => "China", +"CX" => "Christmas Island", +"CC" => "Cocos (Keeling) Islands", +"CO" => "Colombia", +"KM" => "Comoros", +"CG" => "Congo", +"CD" => "Congo, Democratic Republic of the", +"CK" => "Cook Islands", +"CR" => "Costa Rica", +"CI" => "Côte d'Ivoire", +"HR" => "Croatia", +"CU" => "Cuba", +"CW" => "Curaçao", +"CY" => "Cyprus", +"CZ" => "Czechia", +"DK" => "Denmark", +"DJ" => "Djibouti", +"DM" => "Dominica", +"DO" => "Dominican Republic", +"EC" => "Ecuador", +"EG" => "Egypt", +"SV" => "El Salvador", +"GQ" => "Equatorial Guinea", +"ER" => "Eritrea", +"EE" => "Estonia", +"SZ" => "Eswatini", +"ET" => "Ethiopia", +"FK" => "Falkland Islands (Malvinas)", +"FO" => "Faroe Islands", +"FJ" => "Fiji", +"FI" => "Finland", +"FR" => "France", +"GF" => "French Guiana", +"PF" => "French Polynesia", +"TF" => "French Southern Territories", +"GA" => "Gabon", +"GM" => "Gambia", +"GE" => "Georgia", +"DE" => "Germany", +"GH" => "Ghana", +"GI" => "Gibraltar", +"GR" => "Greece", +"GL" => "Greenland", +"GD" => "Grenada", +"GP" => "Guadeloupe", +"GU" => "Guam", +"GT" => "Guatemala", +"GG" => "Guernsey", +"GN" => "Guinea", +"GW" => "Guinea-Bissau", +"GY" => "Guyana", +"HT" => "Haiti", +"HM" => "Heard Island and McDonald Islands", +"VA" => "Holy See", +"HN" => "Honduras", +"HK" => "Hong Kong", +"HU" => "Hungary", +"IS" => "Iceland", +"IN" => "India", +"ID" => "Indonesia", +"IR" => "Iran, Islamic Republic of", +"IQ" => "Iraq", +"IE" => "Ireland", +"IM" => "Isle of Man", +"IL" => "Israel", +"IT" => "Italy", +"JM" => "Jamaica", +"JP" => "Japan", +"JE" => "Jersey", +"JO" => "Jordan", +"KZ" => "Kazakhstan", +"KE" => "Kenya", +"KI" => "Kiribati", +"KP" => "Korea, Democratic People's Republic of", +"KR" => "Korea, Republic of", +"KW" => "Kuwait", +"KG" => "Kyrgyzstan", +"LA" => "Lao People's Democratic Republic", +"LV" => "Latvia", +"LB" => "Lebanon", +"LS" => "Lesotho", +"LR" => "Liberia", +"LY" => "Libya", +"LI" => "Liechtenstein", +"LT" => "Lithuania", +"LU" => "Luxembourg", +"MO" => "Macao", +"MG" => "Madagascar", +"MW" => "Malawi", +"MY" => "Malaysia", +"MV" => "Maldives", +"ML" => "Mali", +"MT" => "Malta", +"MH" => "Marshall Islands", +"MQ" => "Martinique", +"MR" => "Mauritania", +"MU" => "Mauritius", +"YT" => "Mayotte", +"MX" => "Mexico", +"FM" => "Micronesia, Federated States of", +"MD" => "Moldova, Republic of", +"MC" => "Monaco", +"MN" => "Mongolia", +"ME" => "Montenegro", +"MS" => "Montserrat", +"MA" => "Morocco", +"MZ" => "Mozambique", +"MM" => "Myanmar", +"NA" => "Namibia", +"NR" => "Nauru", +"NP" => "Nepal", +"NL" => "Netherlands, Kingdom of the", +"NC" => "New Caledonia", +"NZ" => "New Zealand", +"NI" => "Nicaragua", +"NE" => "Niger", +"NG" => "Nigeria", +"NU" => "Niue", +"NF" => "Norfolk Island", +"MK" => "North Macedonia", +"MP" => "Northern Mariana Islands", +"NO" => "Norway", +"OM" => "Oman", +"PK" => "Pakistan", +"PW" => "Palau", +"PS" => "Palestine, State of", +"PA" => "Panama", +"PG" => "Papua New Guinea", +"PY" => "Paraguay", +"PE" => "Peru", +"PH" => "Philippines", +"PN" => "Pitcairn", +"PL" => "Poland", +"PT" => "Portugal", +"PR" => "Puerto Rico", +"QA" => "Qatar", +"RE" => "Réunion", +"RO" => "Romania", +"RU" => "Russian Federation", +"RW" => "Rwanda", +"BL" => "Saint Barthélemy", +"SH" => "Saint Helena, Ascension and Tristan da Cunha", +"KN" => "Saint Kitts and Nevis", +"LC" => "Saint Lucia", +"MF" => "Saint Martin (French part)", +"PM" => "Saint Pierre and Miquelon", +"VC" => "Saint Vincent and the Grenadines", +"WS" => "Samoa", +"SM" => "San Marino", +"ST" => "Sao Tome and Principe", +"SA" => "Saudi Arabia", +"SN" => "Senegal", +"RS" => "Serbia", +"SC" => "Seychelles", +"SL" => "Sierra Leone", +"SG" => "Singapore", +"SX" => "Sint Maarten (Dutch part)", +"SK" => "Slovakia", +"SI" => "Slovenia", +"SB" => "Solomon Islands", +"SO" => "Somalia", +"ZA" => "South Africa", +"GS" => "South Georgia and the South Sandwich Islands", +"SS" => "South Sudan", +"ES" => "Spain", +"LK" => "Sri Lanka", +"SD" => "Sudan", +"SR" => "Suriname", +"SJ" => "Svalbard and Jan Mayen", +"SE" => "Sweden", +"CH" => "Switzerland", +"SY" => "Syrian Arab Republic", +"TW" => "Taiwan", +"TJ" => "Tajikistan", +"TZ" => "Tanzania, United Republic of", +"TH" => "Thailand", +"TL" => "Timor-Leste", +"TG" => "Togo", +"TK" => "Tokelau", +"TO" => "Tonga", +"TT" => "Trinidad and Tobago", +"TN" => "Tunisia", +"TR" => "Türkiye", +"TM" => "Turkmenistan", +"TC" => "Turks and Caicos Islands", +"TV" => "Tuvalu", +"UG" => "Uganda", +"UA" => "Ukraine", +"AE" => "United Arab Emirates", +"GB" => "United Kingdom of Great Britain and Northern Ireland", +"US" => "United States of America", +"UM" => "United States Minor Outlying Islands", +"UY" => "Uruguay", +"UZ" => "Uzbekistan", +"VU" => "Vanuatu", +"VE" => "Venezuela", +"VN" => "Viet Nam", +"VG" => "Virgin Islands (British)", +"VI" => "Virgin Islands (U.S.)", +"WF" => "Wallis and Futuna", +"EH" => "Western Sahara", +"YE" => "Yemen", +"ZM" => "Zambia", +"ZW" => "Zimbabwe", +]); // All available TLDs Configure::set('Opensrs.tlds', [ '.abogado', @@ -844,7 +1096,8 @@ ], 'contact_set[owner][country]' => [ 'label' => Language::_('Opensrs.whois.owner.country', true), - 'type' => 'text' + 'type' => 'select', + 'options' => Configure::get('Opensrs.countries') ], 'contact_set[owner][phone]' => [ 'label' => Language::_('Opensrs.whois.owner.phone', true), @@ -888,7 +1141,8 @@ ], 'contact_set[tech][country]' => [ 'label' => Language::_('Opensrs.whois.tech.country', true), - 'type' => 'text' + 'type' => 'select', + 'options' => Configure::get('Opensrs.countries') ], 'contact_set[tech][phone]' => [ 'label' => Language::_('Opensrs.whois.tech.phone', true), @@ -932,7 +1186,8 @@ ], 'contact_set[admin][country]' => [ 'label' => Language::_('Opensrs.whois.admin.country', true), - 'type' => 'text' + 'type' => 'select', + 'options' => Configure::get('Opensrs.countries') ], 'contact_set[admin][phone]' => [ 'label' => Language::_('Opensrs.whois.admin.phone', true), @@ -976,7 +1231,8 @@ ], 'contact_set[billing][country]' => [ 'label' => Language::_('Opensrs.whois.billing.country', true), - 'type' => 'text' + 'type' => 'select', + 'options' => Configure::get('Opensrs.countries') ], 'contact_set[billing][phone]' => [ 'label' => Language::_('Opensrs.whois.billing.phone', true), @@ -1136,11 +1392,11 @@ // .FR Configure::set('Opensrs.domain_fields.fr', [ 'tld_data[registrant_extra_info][registrant_type]' => [ - 'label' => Language::_('Opensrs.domain.registrant_type', true), + 'label' => Language::_('Opensrs.domain.fr_registrant_type', true), 'type' => 'select', 'options' => [ - 'individual' => Language::_('Opensrs.domain.registrant_type.individual', true), - 'organization' => Language::_('Opensrs.domain.registrant_type.company', true), + 'individual' => Language::_('Opensrs.domain.fr_registrant_type.individual', true), + 'organization' => Language::_('Opensrs.domain.fr_registrant_type.organization', true), ] ], 'tld_data[registrant_extra_info][registrant_vat_id]' => [ @@ -1190,7 +1446,8 @@ ], 'tld_data[registrant_extra_info][qli_jurisdiction_country]' => [ 'label' => Language::_('Opensrs.domain.qli_jurisdiction_country', true), - 'type' => 'text' + 'type' => 'select', + 'options' => Configure::get('Opensrs.countries') ], 'tld_data[registrant_extra_info][qli_jurisdiction_state]' => [ 'label' => Language::_('Opensrs.domain.qli_jurisdiction_state', true), @@ -1224,4 +1481,4 @@

Domain: {service.domain}

Thank you for your business!

' ] -]); \ No newline at end of file +]); diff --git a/language/en_us/opensrs.php b/language/en_us/opensrs.php index 122de8b..4b73ef0 100755 --- a/language/en_us/opensrs.php +++ b/language/en_us/opensrs.php @@ -59,6 +59,39 @@ $lang['Opensrs.tab_nameservers.field_submit'] = 'Update Name Servers'; $lang['Opensrs.tab_settings.title'] = 'Settings'; + +$lang['Opensrs.tab_dns.title'] = 'DNS Records'; +$lang['Opensrs.tab_dns.field_type'] = 'Type'; +$lang['Opensrs.tab_dns.field_subdomain'] = 'Host'; +$lang['Opensrs.tab_dns.field_ip_address'] = 'Value'; +$lang['Opensrs.tab_dns.field_priority'] = 'Priority'; +$lang['Opensrs.tab_dns.field_ttl'] = 'TTL'; +$lang['Opensrs.tab_dns.field_options'] = 'Options'; +$lang['Opensrs.tab_dns.field_add'] = 'Add Record'; +$lang['Opensrs.tab_dns.field_delete'] = 'Delete'; +$lang['Opensrs.tab_dns.field_reset'] = 'Reset DNS Zone'; +$lang['Opensrs.tab_dns.add_record'] = 'Add DNS Record'; +$lang['Opensrs.tab_dns.no_records'] = 'There are no DNS records.'; + +$lang['Opensrs.tab_url_forwarding.title'] = 'URL Forwarding'; +$lang['Opensrs.tab_url_forwarding.field_subdomain'] = 'Subdomain'; +$lang['Opensrs.tab_url_forwarding.field_destination'] = 'Destination URL'; +$lang['Opensrs.tab_url_forwarding.field_redirect_type'] = 'Redirect Type'; +$lang['Opensrs.tab_url_forwarding.redirect_301'] = 'Permanent (301)'; +$lang['Opensrs.tab_url_forwarding.redirect_302'] = 'Temporary (302)'; +$lang['Opensrs.tab_url_forwarding.redirect_frame'] = 'Frame (Masked)'; +$lang['Opensrs.tab_url_forwarding.field_add'] = 'Add Forwarding Rule'; +$lang['Opensrs.tab_url_forwarding.add_record'] = 'Add URL Forwarding Rule'; +$lang['Opensrs.tab_url_forwarding.no_records'] = 'There are no URL forwarding rules.'; + +$lang['Opensrs.tab_dnssec.title'] = 'DNSSEC'; +$lang['Opensrs.tab_dnssec.field_key_tag'] = 'Key Tag'; +$lang['Opensrs.tab_dnssec.field_algorithm'] = 'Algorithm'; +$lang['Opensrs.tab_dnssec.field_digest_type'] = 'Digest Type'; +$lang['Opensrs.tab_dnssec.field_digest'] = 'Digest'; +$lang['Opensrs.tab_dnssec.field_add'] = 'Add DS Record'; +$lang['Opensrs.tab_dnssec.add_record'] = 'Add DS Record'; +$lang['Opensrs.tab_dnssec.no_records'] = 'There are no DNSSEC DS records.'; $lang['Opensrs.tab_settings.field_registrar_lock'] = 'Registrar Lock'; $lang['Opensrs.tab_settings.field_registrar_lock_yes'] = 'Set the registrar lock. Recommended to prevent unauthorized transfer.'; $lang['Opensrs.tab_settings.field_registrar_lock_no'] = 'Release the registrar lock so the domain can be transferred.'; @@ -73,6 +106,11 @@ $lang['Opensrs.!error.user.valid'] = 'Please enter a user'; $lang['Opensrs.!error.key.valid'] = 'Please enter a key'; $lang['Opensrs.!error.key.valid_connection'] = 'The user and key combination appear to be invalid, or your Opensrs account may not be configured to allow API access.'; +$lang['Opensrs.!error.module_row.missing'] = 'The module row could not be found. Please reconfigure the module.'; +$lang['Opensrs.!error.cancel.failed'] = 'Failed to disable auto-renewal for this domain.'; +$lang['Opensrs.!error.suspend.failed'] = 'Failed to suspend this domain.'; +$lang['Opensrs.!error.unsuspend.failed'] = 'Failed to unsuspend this domain.'; +$lang['Opensrs.!error.restore.failed'] = 'Failed to restore this domain from redemption.'; $lang['Opensrs.!error.registrant_type.format'] = 'Please select a registrant type'; $lang['Opensrs.!error.registrant_vat_id.format'] = 'Please enter a VAT ID'; $lang['Opensrs.!error.siren_siret.format'] = 'Please enter a SIREN/SIRET Number'; @@ -219,9 +257,9 @@ $lang['Opensrs.domain.id_number'] = 'Identity Number'; // .FR domain fields -$lang['Opensrs.domain.registrant_type'] = 'Legal Type'; -$lang['Opensrs.domain.registrant_type.individual'] = 'Individual'; -$lang['Opensrs.domain.registrant_type.organization'] = 'Company'; +$lang['Opensrs.domain.fr_registrant_type'] = 'Legal Type'; +$lang['Opensrs.domain.fr_registrant_type.individual'] = 'Individual'; +$lang['Opensrs.domain.fr_registrant_type.organization'] = 'Company'; $lang['Opensrs.domain.registrant_vat_id'] = 'VAT ID'; $lang['Opensrs.domain.siren_siret'] = 'SIREN/SIRET Number'; $lang['Opensrs.domain.trademark_number'] = 'Trademark Number'; diff --git a/opensrs.php b/opensrs.php index ab0c33a..38897f0 100644 --- a/opensrs.php +++ b/opensrs.php @@ -82,7 +82,10 @@ public function getFilteredTldPricing($module_row_id = null, $filters = []) // Fetch pricing from the registrar - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return []; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -106,9 +109,7 @@ public function getFilteredTldPricing($module_row_id = null, $filters = []) if ($register_response->status() != 'OK') { continue; } - foreach (range(1, 10) as $years) { - $pricing[$tld]['register'] = $register_response->response(); - } + $pricing[$tld]['register'] = $register_response->response(); // Set the renewal prices $renew_response = $domains->getPrice(array_merge($vars, ['reg_type' => 'renewal'])); @@ -116,9 +117,7 @@ public function getFilteredTldPricing($module_row_id = null, $filters = []) if ($renew_response->status() != 'OK') { continue; } - foreach (range(1, 10) as $years) { - $pricing[$tld]['renew'] = $renew_response->response(); - } + $pricing[$tld]['renew'] = $renew_response->response(); // Set the transfer prices $transfer_response = $domains->getPrice(array_merge($vars, ['reg_type' => 'transfer'])); @@ -126,9 +125,7 @@ public function getFilteredTldPricing($module_row_id = null, $filters = []) if ($transfer_response->status() != 'OK') { continue; } - foreach (range(1, 10) as $years) { - $pricing[$tld]['transfer'] = $transfer_response->response(); - } + $pricing[$tld]['transfer'] = $transfer_response->response(); } unset($tld); @@ -214,7 +211,7 @@ public function getFilteredTldPricing($module_row_id = null, $filters = []) * @param array $vars An array of user supplied info to satisfy the request * @return bool True if the service validates, false otherwise. Sets Input errors when false. */ - public function validateService($package, array $vars = null) + public function validateService($package, ?array $vars = null) { $this->Input->setRules($this->getServiceRules($vars)); @@ -228,7 +225,7 @@ public function validateService($package, array $vars = null) * @param array $vars An array of user-supplied info to satisfy the request * @return bool True if the service update validates or false otherwise. Sets Input errors when false. */ - public function validateServiceEdit($service, array $vars = null) + public function validateServiceEdit($service, ?array $vars = null) { $this->Input->setRules($this->getServiceRules($vars, true)); @@ -242,7 +239,7 @@ public function validateServiceEdit($service, array $vars = null) * @param bool $edit True to get the edit rules, false for the add rules * @return array Service rules */ - private function getServiceRules(array $vars = null, $edit = false) + private function getServiceRules(?array $vars = null, $edit = false) { // Validate .fr TLD rules $fr_fields = Configure::get('Opensrs.domain_fields.fr'); @@ -291,7 +288,7 @@ private function getServiceRules(array $vars = null, $edit = false) 'tld_data[registrant_extra_info][trademark_number]' ]; - if ($vars['tld_data']['registrant_extra_info']['registrant_type'] == 'organization') { + if ($vars['tld_data']['registrant_extra_info']['registrant_type'] == 'individual') { foreach ($company_fields as $field) { unset($rules[$field]); } @@ -326,7 +323,7 @@ private function getServiceRules(array $vars = null, $edit = false) */ public function addService( $package, - array $vars = null, + ?array $vars = null, $parent_package = null, $parent_service = null, $status = 'pending' @@ -364,12 +361,18 @@ public function addService( Loader::loadModels($this, ['Contacts']); } - $client = $this->Clients->get($vars['client_id']); + $client = $this->Clients->get($vars['client_id'] ?? null); if ($client) { $contact_numbers = $this->Contacts->getNumbers($client->contact_id); + } else { + $contact_numbers = []; } foreach ($whois_fields as $key => $value) { + if (!$client) { + $vars[$key] = 'NA'; + continue; + } if (str_contains($key, 'first_name')) { $vars[$key] = $client->first_name; } elseif (str_contains($key, 'last_name')) { @@ -437,15 +440,20 @@ public function addService( } // Set nameservers - $this->setDomainNameservers($vars['domain'], $package->module_row, [ + $this->setDomainNameservers($vars['domain'], $package->module_row, array_filter([ $fields['nameserver_list'][0]['name'] ?? '', $fields['nameserver_list'][1]['name'] ?? '', $fields['nameserver_list'][2]['name'] ?? '', $fields['nameserver_list'][3]['name'] ?? '', - ]); + ])); - // Ignore nameserver errors - $this->Input->setErrors([]); + // Clear nameserver errors only (registration already succeeded) + if ($this->Input->errors()) { + $errors = $this->Input->errors(); + if (isset($errors['errors']) && count($errors) === 1) { + $this->Input->setErrors([]); + } + } return [['key' => 'domain', 'value' => $vars['domain'], 'encrypted' => 0]]; } @@ -507,6 +515,156 @@ public function renewService($package, $service, $parent_package = null, $parent return null; } + /** + * Cancels the service on the remote server. Sets Input errors on failure, + * preventing the service from being canceled. + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param stdClass $parent_package A stdClass object representing the parent + * service's selected package (if the current service is an addon service) + * @param stdClass $parent_service A stdClass object representing the parent + * service of the service being canceled (if the current service is an addon service) + * @return mixed null to maintain the existing meta fields or a numerically + * indexed array of meta fields to be stored for this service containing: + * - key The key for this meta field + * - value The value for this key + * - encrypted Whether or not this field should be encrypted (default 0, not encrypted) + * @see Module::getModule() + * @see Module::getModuleRow() + */ + public function cancelService($package, $service, $parent_package = null, $parent_service = null) + { + $row = $this->getModuleRowOrFail($package->module_row); + if (!$row) { + return null; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $fields = $this->serviceFieldsToObject($service->fields); + + $domains_provisioning = new OpensrsDomainsProvisioning($api); + $response = $domains_provisioning->modify([ + 'domain' => $fields->domain, + 'data' => 'expire_action', + 'affect_domains' => '0', + 'auto_renew' => '0', + 'let_expire' => '1' + ]); + $this->processResponse($api, $response); + + return null; + } + + /** + * Suspends the service on the remote server. Sets Input errors on failure, + * preventing the service from being suspended. + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param stdClass $parent_package A stdClass object representing the parent + * service's selected package (if the current service is an addon service) + * @param stdClass $parent_service A stdClass object representing the parent + * service of the service being suspended (if the current service is an addon service) + * @return mixed null to maintain the existing meta fields or a numerically + * indexed array of meta fields to be stored for this service containing: + * - key The key for this meta field + * - value The value for this key + * - encrypted Whether or not this field should be encrypted (default 0, not encrypted) + * @see Module::getModule() + * @see Module::getModuleRow() + */ + public function suspendService($package, $service, $parent_package = null, $parent_service = null) + { + return $this->cancelService($package, $service, $parent_package, $parent_service); + } + + /** + * Unsuspends the service on the remote server. Sets Input errors on failure, + * preventing the service from being unsuspended. + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param stdClass $parent_package A stdClass object representing the parent + * service's selected package (if the current service is an addon service) + * @param stdClass $parent_service A stdClass object representing the parent + * service of the service being unsuspended (if the current service is an addon service) + * @return mixed null to maintain the existing meta fields or a numerically + * indexed array of meta fields to be stored for this service containing: + * - key The key for this meta field + * - value The value for this key + * - encrypted Whether or not this field should be encrypted (default 0, not encrypted) + * @see Module::getModule() + * @see Module::getModuleRow() + */ + public function unsuspendService($package, $service, $parent_package = null, $parent_service = null) + { + $row = $this->getModuleRowOrFail($package->module_row); + if (!$row) { + return null; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $fields = $this->serviceFieldsToObject($service->fields); + + $domains_provisioning = new OpensrsDomainsProvisioning($api); + $response = $domains_provisioning->modify([ + 'domain' => $fields->domain, + 'data' => 'expire_action', + 'affect_domains' => '0', + 'auto_renew' => '1', + 'let_expire' => '0' + ]); + $this->processResponse($api, $response); + + return null; + } + + /** + * Edits the service on the remote server. + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $vars An array of user supplied info to satisfy the request + * @param stdClass $parent_package A stdClass object representing the parent + * service's selected package (if the current service is an addon service) + * @param stdClass $parent_service A stdClass object representing the parent + * service of the service being edited (if the current service is an addon service) + * @return mixed null to maintain the existing meta fields or a numerically + * indexed array of meta fields to be stored for this service containing: + * - key The key for this meta field + * - value The value for this key + * - encrypted Whether or not this field should be encrypted (default 0, not encrypted) + * @see Module::getModule() + * @see Module::getModuleRow() + */ + public function editService($package, $service, array $vars = [], $parent_package = null, $parent_service = null) + { + return null; + } + + /** + * Restores a domain in the redemption grace period + * + * @param string $domain The domain to restore + * @param int $module_row_id The ID of the module row to fetch for the current module + * @return bool True if the domain was successfully restored, false otherwise + */ + public function restoreDomain($domain, $module_row_id = null, array $vars = []) + { + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $domains = new OpensrsDomainsProvisioning($api); + $response = $domains->redeem(['domain' => $domain]); + $this->processResponse($api, $response); + + return $response->status() == 'OK'; + } + /** * Validates input data when attempting to add a package, returns the meta * data to save when adding a package. Performs any action required to add @@ -521,7 +679,7 @@ public function renewService($package, $service, $parent_package = null, $parent * @see Module::getModule() * @see Module::getModuleRow() */ - public function addPackage(array $vars = null) + public function addPackage(?array $vars = null) { $meta = []; if (isset($vars['meta']) && is_array($vars['meta'])) { @@ -553,7 +711,7 @@ public function addPackage(array $vars = null) * @see Module::getModule() * @see Module::getModuleRow() */ - public function editPackage($package, array $vars = null) + public function editPackage($package, ?array $vars = null) { $meta = []; if (isset($vars['meta']) && is_array($vars['meta'])) { @@ -964,12 +1122,26 @@ public function getAdminServiceTabs($service) { Loader::loadModels($this, ['Packages']); + $package = null; + if (isset($service->package) && $service->package) { + $package = $service->package; + } elseif (isset($service->pricing_id)) { + $package = $this->Packages->getByPricingId($service->pricing_id); + } + $tabs = [ 'tabWhois' => Language::_('Opensrs.tab_whois.title', true), 'tabNameservers' => Language::_('Opensrs.tab_nameservers.title', true), 'tabSettings' => Language::_('Opensrs.tab_settings.title', true) ]; + if ($this->featureServiceEnabled('dns_management', $service)) { + $tabs['tabDns'] = Language::_('Opensrs.tab_dns.title', true); + $tabs['tabUrlForwarding'] = Language::_('Opensrs.tab_url_forwarding.title', true); + } + + $tabs['tabDnssec'] = Language::_('Opensrs.tab_dnssec.title', true); + return $tabs; } @@ -1005,6 +1177,22 @@ public function getClientServiceTabs($service) ] ]; + if ($this->featureServiceEnabled('dns_management', $service)) { + $tabs['tabClientDns'] = [ + 'name' => Language::_('Opensrs.tab_dns.title', true), + 'icon' => 'fas fa-globe' + ]; + $tabs['tabClientUrlForwarding'] = [ + 'name' => Language::_('Opensrs.tab_url_forwarding.title', true), + 'icon' => 'fas fa-share' + ]; + } + + $tabs['tabClientDnssec'] = [ + 'name' => Language::_('Opensrs.tab_dnssec.title', true), + 'icon' => 'fas fa-shield-alt' + ]; + return $tabs; } @@ -1018,7 +1206,7 @@ public function getClientServiceTabs($service) * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - public function tabWhois($package, $service, array $get = null, array $post = null, array $files = null) + public function tabWhois($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { return $this->manageWhois('tab_whois', $package, $service, $get, $post, $files); } @@ -1033,7 +1221,7 @@ public function tabWhois($package, $service, array $get = null, array $post = nu * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - public function tabClientWhois($package, $service, array $get = null, array $post = null, array $files = null) + public function tabClientWhois($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { return $this->manageWhois('tab_client_whois', $package, $service, $get, $post, $files); } @@ -1048,7 +1236,7 @@ public function tabClientWhois($package, $service, array $get = null, array $pos * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - public function tabNameservers($package, $service, array $get = null, array $post = null, array $files = null) + public function tabNameservers($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { return $this->manageNameservers('tab_nameservers', $package, $service, $get, $post, $files); } @@ -1063,7 +1251,7 @@ public function tabNameservers($package, $service, array $get = null, array $pos * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - public function tabClientNameservers($package, $service, array $get = null, array $post = null, array $files = null) + public function tabClientNameservers($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { return $this->manageNameservers('tab_client_nameservers', $package, $service, $get, $post, $files); } @@ -1078,7 +1266,7 @@ public function tabClientNameservers($package, $service, array $get = null, arra * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - public function tabSettings($package, $service, array $get = null, array $post = null, array $files = null) + public function tabSettings($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { return $this->manageSettings('tab_settings', $package, $service, $get, $post, $files); } @@ -1093,11 +1281,106 @@ public function tabSettings($package, $service, array $get = null, array $post = * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - public function tabClientSettings($package, $service, array $get = null, array $post = null, array $files = null) + public function tabClientSettings($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { return $this->manageSettings('tab_client_settings', $package, $service, $get, $post, $files); } + /** + * Admin DNS tab + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + public function tabDns($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) + { + return $this->manageDns('tab_dns', $package, $service, $get, $post, $files); + } + + /** + * Client DNS tab + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + public function tabClientDns($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) + { + return $this->manageDns('tab_client_dns', $package, $service, $get, $post, $files); + } + + /** + * Admin URL Forwarding tab + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + public function tabUrlForwarding($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) + { + return $this->manageUrlForwarding('tab_url_forwarding', $package, $service, $get, $post, $files); + } + + /** + * Client URL Forwarding tab + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + public function tabClientUrlForwarding( + $package, + $service, + ?array $get = null, + ?array $post = null, + ?array $files = null + ) { + return $this->manageUrlForwarding('tab_client_url_forwarding', $package, $service, $get, $post, $files); + } + + /** + * Admin DNSSEC tab + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + public function tabDnssec($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) + { + return $this->manageDnssec('tab_dnssec', $package, $service, $get, $post, $files); + } + + /** + * Client DNSSEC tab + * + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + public function tabClientDnssec($package, $service, ?array $get = null, ?array $post = null, ?array $files = null) + { + return $this->manageDnssec('tab_client_dnssec', $package, $service, $get, $post, $files); + } + /** * Handle updating whois information * @@ -1109,7 +1392,7 @@ public function tabClientSettings($package, $service, array $get = null, array $ * @param array $files Any FILES parameters * @return string The string representing the contents of this tab */ - private function manageWhois($view, $package, $service, array $get = null, array $post = null, array $files = null) + private function manageWhois($view, $package, $service, ?array $get = null, ?array $post = null, ?array $files = null) { $this->view = new View($view, 'default'); @@ -1184,9 +1467,9 @@ private function manageNameservers( $view, $package, $service, - array $get = null, - array $post = null, - array $files = null + ?array $get = null, + ?array $post = null, + ?array $files = null ) { $this->view = new View($view, 'default'); @@ -1234,16 +1517,19 @@ private function manageSettings( $view, $package, $service, - array $get = null, - array $post = null, - array $files = null + ?array $get = null, + ?array $post = null, + ?array $files = null ) { $this->view = new View($view, 'default'); // Load the helpers required for this view Loader::loadHelpers($this, ['Form', 'Html']); - $row = $this->getModuleRow($package->module_row); + $row = $this->getModuleRowOrFail($package->module_row); + if (!$row) { + return ''; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $vars = new stdClass(); @@ -1257,7 +1543,7 @@ private function manageSettings( if (!empty($post)) { // Set domain status - if ($post['registrar_lock'] == 'true') { + if (($post['registrar_lock'] ?? 'false') == 'true') { $this->lockDomain($fields->domain, $package->module_row); } else { $this->unlockDomain($fields->domain, $package->module_row); @@ -1269,7 +1555,7 @@ private function manageSettings( 'domain' => $fields->domain, 'data' => 'whois_privacy_state', 'affect_domains' => '0', - 'state' => $post['whois_privacy_state'] == 'true' ? 'Y' : 'N' + 'state' => ($post['whois_privacy_state'] ?? 'false') == 'true' ? 'Y' : 'N' ]); $this->processResponse($api, $response); @@ -1298,6 +1584,381 @@ private function manageSettings( return $this->view->fetch(); } + /** + * Handle DNS zone management + * + * @param string $view The view to use + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + private function manageDns( + $view, + $package, + $service, + ?array $get = null, + ?array $post = null, + ?array $files = null + ) { + $this->view = new View($view, 'default'); + + // Load the helpers required for this view + Loader::loadHelpers($this, ['Form', 'Html']); + + $row = $this->getModuleRowOrFail($package->module_row); + if (!$row) { + return ''; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $vars = new stdClass(); + $fields = $this->serviceFieldsToObject($service->fields); + $dns = new OpensrsDomainsDns($api); + + if (!empty($post)) { + if (isset($post['action'])) { + if ($post['action'] == 'add_record') { + // Get existing records, add new one, set zone + $zone_response = $dns->getDnsZone(['domain' => $fields->domain]); + $this->processResponse($api, $zone_response); + + if ($zone_response->status() == 'OK') { + $zone = $zone_response->response(); + $records = $zone->attributes['records'] ?? []; + + // Add the new record + $new_record = [ + 'type' => $post['type'] ?? 'A', + 'subdomain' => $post['subdomain'] ?? '', + 'ip_address' => $post['ip_address'] ?? '', + 'priority' => $post['priority'] ?? '', + 'ttl' => $post['ttl'] ?? '3600' + ]; + + // Build the records for setDnsZone + $type_key = strtolower($new_record['type']); + if (!isset($records[$type_key]) || !is_array($records[$type_key])) { + $records[$type_key] = []; + } + $records[$type_key][] = $new_record; + + $response = $dns->setDnsZone([ + 'domain' => $fields->domain, + 'records' => $records + ]); + $this->processResponse($api, $response); + } + } elseif ($post['action'] == 'delete_record') { + // Get existing records, remove specified one, set zone + $zone_response = $dns->getDnsZone(['domain' => $fields->domain]); + $this->processResponse($api, $zone_response); + + if ($zone_response->status() == 'OK') { + $zone = $zone_response->response(); + $records = $zone->attributes['records'] ?? []; + + $delete_type = strtolower($post['record_type'] ?? ''); + $delete_index = (int)($post['record_index'] ?? -1); + + if (isset($records[$delete_type][$delete_index])) { + unset($records[$delete_type][$delete_index]); + $records[$delete_type] = array_values($records[$delete_type]); + } + + $response = $dns->setDnsZone([ + 'domain' => $fields->domain, + 'records' => $records + ]); + $this->processResponse($api, $response); + } + } elseif ($post['action'] == 'reset_zone') { + $response = $dns->resetDnsZone([ + 'domain' => $fields->domain + ]); + $this->processResponse($api, $response); + } + } + } + + // Fetch current zone records + $zone_response = $dns->getDnsZone(['domain' => $fields->domain]); + $records = []; + if ($zone_response->status() == 'OK') { + $zone = $zone_response->response(); + $raw_records = $zone->attributes['records'] ?? []; + + // Flatten records into a single array for display + foreach ($raw_records as $type => $type_records) { + if (is_array($type_records)) { + foreach ($type_records as $index => $record) { + if (is_array($record)) { + $record['record_type'] = strtoupper($type); + $record['record_index'] = $index; + $records[] = $record; + } + } + } + } + } else { + $this->Input->setErrors([]); + } + + $this->view->set('records', $records); + $this->view->set('vars', $vars); + $this->view->set('record_types', [ + 'A' => 'A', + 'AAAA' => 'AAAA', + 'CNAME' => 'CNAME', + 'MX' => 'MX', + 'TXT' => 'TXT', + 'SRV' => 'SRV', + 'NS' => 'NS' + ]); + $this->view->setDefaultView('components' . DS . 'modules' . DS . 'opensrs' . DS); + + return $this->view->fetch(); + } + + /** + * Handle URL forwarding management + * + * @param string $view The view to use + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + private function manageUrlForwarding( + $view, + $package, + $service, + ?array $get = null, + ?array $post = null, + ?array $files = null + ) { + $this->view = new View($view, 'default'); + + // Load the helpers required for this view + Loader::loadHelpers($this, ['Form', 'Html']); + + $row = $this->getModuleRowOrFail($package->module_row); + if (!$row) { + return ''; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $vars = new stdClass(); + $fields = $this->serviceFieldsToObject($service->fields); + $dns = new OpensrsDomainsDns($api); + + if (!empty($post)) { + if (isset($post['action'])) { + if ($post['action'] == 'set_forwarding') { + // Build URL forwarding record via DNS A/CNAME + URL forwarding + $zone_response = $dns->getDnsZone(['domain' => $fields->domain]); + $this->processResponse($api, $zone_response); + + if ($zone_response->status() == 'OK') { + $zone = $zone_response->response(); + $records = $zone->attributes['records'] ?? []; + + // Add forwarding record + if (!isset($records['url_forwarding']) || !is_array($records['url_forwarding'])) { + $records['url_forwarding'] = []; + } + $records['url_forwarding'][] = [ + 'subdomain' => $post['subdomain'] ?? '@', + 'ip_address' => $post['destination'] ?? '', + 'type' => $post['redirect_type'] ?? '301' + ]; + + $response = $dns->setDnsZone([ + 'domain' => $fields->domain, + 'records' => $records + ]); + $this->processResponse($api, $response); + } + } elseif ($post['action'] == 'delete_forwarding') { + $zone_response = $dns->getDnsZone(['domain' => $fields->domain]); + $this->processResponse($api, $zone_response); + + if ($zone_response->status() == 'OK') { + $zone = $zone_response->response(); + $records = $zone->attributes['records'] ?? []; + + $delete_index = (int)($post['record_index'] ?? -1); + if (isset($records['url_forwarding'][$delete_index])) { + unset($records['url_forwarding'][$delete_index]); + $records['url_forwarding'] = array_values($records['url_forwarding']); + } + + $response = $dns->setDnsZone([ + 'domain' => $fields->domain, + 'records' => $records + ]); + $this->processResponse($api, $response); + } + } + } + } + + // Fetch current forwarding records + $forwarding_records = []; + $zone_response = $dns->getDnsZone(['domain' => $fields->domain]); + if ($zone_response->status() == 'OK') { + $zone = $zone_response->response(); + $raw_records = $zone->attributes['records']['url_forwarding'] ?? []; + foreach ($raw_records as $index => $record) { + if (is_array($record)) { + $record['record_index'] = $index; + $forwarding_records[] = $record; + } + } + } else { + $this->Input->setErrors([]); + } + + $this->view->set('forwarding_records', $forwarding_records); + $this->view->set('vars', $vars); + $this->view->set('redirect_types', [ + '301' => Language::_('Opensrs.tab_url_forwarding.redirect_301', true), + '302' => Language::_('Opensrs.tab_url_forwarding.redirect_302', true), + 'frame' => Language::_('Opensrs.tab_url_forwarding.redirect_frame', true) + ]); + $this->view->setDefaultView('components' . DS . 'modules' . DS . 'opensrs' . DS); + + return $this->view->fetch(); + } + + /** + * Handle DNSSEC management + * + * @param string $view The view to use + * @param stdClass $package A stdClass object representing the current package + * @param stdClass $service A stdClass object representing the current service + * @param array $get Any GET parameters + * @param array $post Any POST parameters + * @param array $files Any FILES parameters + * @return string The string representing the contents of this tab + */ + private function manageDnssec( + $view, + $package, + $service, + ?array $get = null, + ?array $post = null, + ?array $files = null + ) { + $this->view = new View($view, 'default'); + + // Load the helpers required for this view + Loader::loadHelpers($this, ['Form', 'Html']); + + $row = $this->getModuleRowOrFail($package->module_row); + if (!$row) { + return ''; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $vars = new stdClass(); + $fields = $this->serviceFieldsToObject($service->fields); + $dnssec = new OpensrsDomainsDnssec($api); + + if (!empty($post)) { + if (isset($post['action'])) { + if ($post['action'] == 'add_ds_record') { + // Get existing records, add new one + $info_response = $dnssec->getDnssecRecords(['domain' => $fields->domain]); + $this->logRequest($api, $info_response); + $existing_records = []; + if ($info_response->status() == 'OK') { + $info = $info_response->response(); + $existing_records = $info->attributes['dnssec'] ?? []; + } + + $new_record = [ + 'key_tag' => $post['key_tag'] ?? '', + 'algorithm' => $post['algorithm'] ?? '', + 'digest_type' => $post['digest_type'] ?? '', + 'digest' => $post['digest'] ?? '' + ]; + + $existing_records[] = $new_record; + + $response = $dnssec->addDnssecRecord([ + 'domain' => $fields->domain, + 'dnssec' => $existing_records + ]); + $this->processResponse($api, $response); + } elseif ($post['action'] == 'delete_ds_record') { + // Get existing records, remove specified one + $info_response = $dnssec->getDnssecRecords(['domain' => $fields->domain]); + $this->logRequest($api, $info_response); + $existing_records = []; + if ($info_response->status() == 'OK') { + $info = $info_response->response(); + $existing_records = $info->attributes['dnssec'] ?? []; + } + + $delete_index = (int)($post['record_index'] ?? -1); + if (isset($existing_records[$delete_index])) { + unset($existing_records[$delete_index]); + $existing_records = array_values($existing_records); + } + + $response = $dnssec->addDnssecRecord([ + 'domain' => $fields->domain, + 'dnssec' => $existing_records + ]); + $this->processResponse($api, $response); + } + } + } + + // Fetch current DS records + $ds_records = []; + $info_response = $dnssec->getDnssecRecords(['domain' => $fields->domain]); + $this->logRequest($api, $info_response); + if ($info_response->status() == 'OK') { + $info = $info_response->response(); + $raw_records = $info->attributes['dnssec'] ?? []; + foreach ($raw_records as $index => $record) { + if (is_array($record)) { + $record['record_index'] = $index; + $ds_records[] = $record; + } + } + } + + $this->view->set('ds_records', $ds_records); + $this->view->set('vars', $vars); + $this->view->set('algorithms', [ + '3' => '3 - DSA/SHA-1', + '5' => '5 - RSA/SHA-1', + '6' => '6 - DSA-NSEC3-SHA1', + '7' => '7 - RSASHA1-NSEC3-SHA1', + '8' => '8 - RSA/SHA-256', + '10' => '10 - RSA/SHA-512', + '13' => '13 - ECDSA/SHA-256', + '14' => '14 - ECDSA/SHA-384', + '15' => '15 - Ed25519', + '16' => '16 - Ed448' + ]); + $this->view->set('digest_types', [ + '1' => '1 - SHA-1', + '2' => '2 - SHA-256', + '4' => '4 - SHA-384' + ]); + $this->view->setDefaultView('components' . DS . 'modules' . DS . 'opensrs' . DS); + + return $this->view->fetch(); + } + /** * Verifies that the provided domain name is available * @@ -1307,7 +1968,10 @@ private function manageSettings( */ public function checkAvailability($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1332,8 +1996,24 @@ public function checkAvailability($domain, $module_row_id = null) */ public function checkTransferAvailability($domain, $module_row_id = null) { - // Prevent users from transferring an unregistered domain - return !$this->checkAvailability($domain, $module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } + $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); + + $transfers = new OpensrsDomainsTransfer($api); + $result = $transfers->checkTransfer(['domain' => $domain]); + $this->logRequest($api, $result); + + if ($result->status() != 'OK') { + // Fall back to inverse availability check + return !$this->checkAvailability($domain, $module_row_id); + } + + $response = $result->response(); + + return ($response->attributes['transferrable'] ?? '0') == '1'; } /** @@ -1357,7 +2037,10 @@ public function checkTransferAvailability($domain, $module_row_id = null) */ public function getDomainContacts($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return []; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1366,6 +2049,10 @@ public function getDomainContacts($domain, $module_row_id = null) 'type' => 'all_info' ]); $this->processResponse($api, $response); + + if ($response->status() != 'OK') { + return []; + } $response = $response->response(); $contacts = $response->attributes['contact_set'] ?? []; @@ -1402,7 +2089,10 @@ public function getDomainContacts($domain, $module_row_id = null) */ public function setDomainContacts($domain, array $vars = [], $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains_provisioning = new OpensrsDomainsProvisioning($api); @@ -1411,7 +2101,7 @@ public function setDomainContacts($domain, array $vars = [], $module_row_id = nu $contact_set = []; foreach ($vars as $contact) { $contact['phone'] = $this->formatPhone($contact['phone'], $contact['country']); - $contact['postal_code'] = $contact['zip'] ?? '00000'; + $contact['postal_code'] = $contact['postal_code'] ?? $contact['zip'] ?? '00000'; $contact_set[$contact['external_id'] ?? 'owner'] = $contact; } @@ -1438,7 +2128,10 @@ public function setDomainContacts($domain, array $vars = [], $module_row_id = nu */ public function getDomainInfo($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return []; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1447,6 +2140,10 @@ public function getDomainInfo($domain, $module_row_id = null) 'type' => 'all_info' ]); $this->processResponse($api, $response); + + if ($response->status() != 'OK') { + return []; + } $response = $response->response(); return $response->attributes ?? []; @@ -1461,7 +2158,10 @@ public function getDomainInfo($domain, $module_row_id = null) */ public function getDomainIsLocked($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1470,9 +2170,13 @@ public function getDomainIsLocked($domain, $module_row_id = null) 'type' => 'status' ]); $this->processResponse($api, $response); + + if ($response->status() != 'OK') { + return false; + } $response = $response->response(); - return $response->attributes['lock_state'] == '1'; + return ($response->attributes['lock_state'] ?? '0') == '1'; } /** @@ -1484,7 +2188,10 @@ public function getDomainIsLocked($domain, $module_row_id = null) */ private function getDomainIsPrivate($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1493,9 +2200,13 @@ private function getDomainIsPrivate($domain, $module_row_id = null) 'type' => 'whois_privacy_state' ]); $this->processResponse($api, $response); + + if ($response->status() != 'OK') { + return false; + } $response = $response->response(); - return $response->attributes['state'] == 'enabled'; + return ($response->attributes['state'] ?? 'disabled') == 'enabled'; } /** @@ -1513,10 +2224,10 @@ public function getDomainNameServers($domain, $module_row_id = null) $domain_info = $this->getDomainInfo($domain, $module_row_id); $nameservers = []; - foreach ($domain_info['nameserver_list'] as $nameserver) { + foreach ($domain_info['nameserver_list'] ?? [] as $nameserver) { $nameservers[] = [ 'url' => $nameserver['name'] ?? '', - 'ips' => [$nameserver['ipaddress'] ?? gethostbyname($nameserver['name'] ?? '')] + 'ips' => [$nameserver['ipaddress'] ?? ''] ]; } @@ -1533,10 +2244,13 @@ public function getDomainNameServers($domain, $module_row_id = null) */ public function setDomainNameservers($domain, $module_row_id = null, array $vars = []) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); - $domains_provisioning = new OpensrsDomainsNs($api); + $domains_ns = new OpensrsDomainsNs($api); // Remove empty nameservers foreach ($vars as $key => $ns) { @@ -1546,7 +2260,7 @@ public function setDomainNameservers($domain, $module_row_id = null, array $vars } // Update domain - $response = $domains_provisioning->advancedUpdateNameserver([ + $response = $domains_ns->advancedUpdateNameserver([ 'domain' => $domain, 'op_type' => 'assign', 'assign_ns' => array_values($vars) @@ -1565,7 +2279,10 @@ public function setDomainNameservers($domain, $module_row_id = null, array $vars */ public function lockDomain($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains_provisioning = new OpensrsDomainsProvisioning($api); @@ -1591,7 +2308,10 @@ public function lockDomain($domain, $module_row_id = null) */ public function unlockDomain($domain, $module_row_id = null) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains_provisioning = new OpensrsDomainsProvisioning($api); @@ -1620,7 +2340,10 @@ public function unlockDomain($domain, $module_row_id = null) */ public function registerDomain($domain, $module_row_id = null, array $vars = []) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); // Set all whois info from client @@ -1636,7 +2359,7 @@ public function registerDomain($domain, $module_row_id = null, array $vars = []) 'auto_renew' => 0, 'reg_type' => isset($vars['auth_info']) ? 'transfer' : 'new', 'reg_username' => 'usr' . ($client->id_value ?? $client->id ?? rand(10000, 99999)), - 'reg_password' => substr(base64_encode(md5($client->id_value)), 0, 15), + 'reg_password' => substr(bin2hex(random_bytes(10)), 0, 15), 'handle' => 'process' ]; $fields = array_merge($params, $vars); @@ -1694,7 +2417,10 @@ public function transferDomain($domain, $module_row_id = null, array $vars = []) */ public function renewDomain($domain, $module_row_id = null, array $vars = []) { - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $params = [ @@ -1727,7 +2453,10 @@ public function getExpirationDate($service, $format = 'Y-m-d H:i:s') $domain = $this->getServiceDomain($service); $module_row_id = $service->module_row_id ?? null; - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1761,7 +2490,10 @@ public function getRegistrationDate($service, $format = 'Y-m-d H:i:s') $domain = $this->getServiceDomain($service); $module_row_id = $service->module_row_id ?? null; - $row = $this->getModuleRow($module_row_id); + $row = $this->getModuleRowOrFail($module_row_id); + if (!$row) { + return false; + } $api = $this->getApi($row->meta->user, $row->meta->key, $row->meta->sandbox == 'true'); $domains = new OpensrsDomains($api); @@ -1855,11 +2587,42 @@ private function getRowRules(&$vars) */ public function validateConnection($key, $user, $sandbox) { - $api = $this->getApi($user, $key, $sandbox == 'true'); - $domains = new OpensrsDomains($api); - $response = $domains->lookup(['domain' => 'blesta.com'])->response(); + try { + $api = $this->getApi($user, $key, $sandbox == 'true'); + $domains = new OpensrsDomains($api); + $result = $domains->lookup(['domain' => 'blesta.com']); + + if ($result->status() != 'OK') { + return false; + } + + $response = $result->response(); + + return ($response->is_success ?? '0') == '1'; + } catch (Exception $e) { + return false; + } + } + + /** + * Gets a module row, setting errors if not found + * + * @param int|null $module_row_id The module row ID + * @return stdClass|null The module row, or null if not found + */ + private function getModuleRowOrFail($module_row_id) + { + $row = $this->getModuleRow($module_row_id); + + if (!$row) { + $this->Input->setErrors(['errors' => [ + Language::_('Opensrs.!error.module_row.missing', true) + ]]); + + return null; + } - return $response->is_success == '1'; + return $row; } /** @@ -1889,7 +2652,8 @@ private function processResponse(OpensrsApi $api, OpensrsResponse $response) // Set errors, if any if ($response->status() != 'OK') { - $errors = isset($response->errors()->response_text) ? $response->errors()->response_text : ''; + $error_obj = $response->errors(); + $errors = $error_obj->response_text ?? 'An unknown error occurred'; $this->Input->setErrors(['errors' => [$errors]]); } } diff --git a/views/default/add_row.pdt b/views/default/add_row.pdt index 2ebcf97..e70d4d9 100644 --- a/views/default/add_row.pdt +++ b/views/default/add_row.pdt @@ -20,7 +20,7 @@
  • Form->label($this->_('Opensrs.row_meta.key', true), 'key'); - $this->Form->fieldText('key', ($vars->key ?? null), ['id' => 'key']); + $this->Form->fieldPassword('key', ['id' => 'key', 'value' => ($vars->key ?? null)]); ?>
  • diff --git a/views/default/edit_row.pdt b/views/default/edit_row.pdt index 4fe3300..febc204 100644 --- a/views/default/edit_row.pdt +++ b/views/default/edit_row.pdt @@ -20,7 +20,7 @@
  • Form->label($this->_('Opensrs.row_meta.key', true), 'key'); - $this->Form->fieldText('key', ($vars->key ?? null), ['id' => 'key']); + $this->Form->fieldPassword('key', ['id' => 'key', 'value' => ($vars->key ?? null)]); ?>
  • diff --git a/views/default/manage.pdt b/views/default/manage.pdt index 80cca40..2f4c684 100644 --- a/views/default/manage.pdt +++ b/views/default/manage.pdt @@ -28,7 +28,7 @@ ?> > rows[$i]->meta->user) ? $this->Html->safe($module->rows[$i]->meta->user) : null);?> - rows[$i]->meta->key) ? $this->Html->safe($module->rows[$i]->meta->key) : null);?> + rows[$i]->meta->key) ? $this->Html->safe(str_repeat('*', max(0, strlen($module->rows[$i]->meta->key) - 4)) . substr($module->rows[$i]->meta->key, -4)) : null);?> _('Opensrs.row_meta.sandbox_' . (isset($module->rows[$i]->meta->sandbox) ? $module->rows[$i]->meta->sandbox : 'false'));?> _('Opensrs.manage.module_rows.edit');?> diff --git a/views/default/tab_client_dns.pdt b/views/default/tab_client_dns.pdt new file mode 100644 index 0000000..a9758c0 --- /dev/null +++ b/views/default/tab_client_dns.pdt @@ -0,0 +1,102 @@ + +
    +
    +

    _('Opensrs.tab_dns.title');?>

    + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    _('Opensrs.tab_dns.field_type');?>_('Opensrs.tab_dns.field_subdomain');?>_('Opensrs.tab_dns.field_ip_address');?>_('Opensrs.tab_dns.field_priority');?>_('Opensrs.tab_dns.field_ttl');?>
    Html->safe($record['record_type'] ?? '');?>Html->safe($record['subdomain'] ?? '');?>Html->safe($record['ip_address'] ?? '');?>Html->safe($record['priority'] ?? '');?>Html->safe($record['ttl'] ?? '');?> + Form->create(); + $this->Form->fieldHidden('action', 'delete_record'); + $this->Form->fieldHidden('record_type', strtolower($record['record_type'] ?? '')); + $this->Form->fieldHidden('record_index', $record['record_index'] ?? ''); + ?> + + Form->end(); + ?> +
    +
    + +
    _('Opensrs.tab_dns.no_records');?>
    + + +

    _('Opensrs.tab_dns.add_record');?>

    + Form->create(); + $this->Form->fieldHidden('action', 'add_record'); + ?> +
    + Form->label($this->_('Opensrs.tab_dns.field_type', true), 'type'); + $this->Form->fieldSelect('type', ($record_types ?? []), ($vars->type ?? 'A'), ['id' => 'type', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dns.field_subdomain', true), 'subdomain'); + $this->Form->fieldText('subdomain', ($vars->subdomain ?? null), ['id' => 'subdomain', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dns.field_ip_address', true), 'ip_address'); + $this->Form->fieldText('ip_address', ($vars->ip_address ?? null), ['id' => 'ip_address', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dns.field_priority', true), 'priority'); + $this->Form->fieldText('priority', ($vars->priority ?? null), ['id' => 'priority', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dns.field_ttl', true), 'ttl'); + $this->Form->fieldText('ttl', ($vars->ttl ?? '3600'), ['id' => 'ttl', 'class' => 'form-control']); + ?> +
    + + Form->end(); + ?> +
    +
    diff --git a/views/default/tab_client_dnssec.pdt b/views/default/tab_client_dnssec.pdt new file mode 100644 index 0000000..c3497d8 --- /dev/null +++ b/views/default/tab_client_dnssec.pdt @@ -0,0 +1,93 @@ + +
    +
    +

    _('Opensrs.tab_dnssec.title');?>

    + + +
    + + + + + + + + + + + + + + + + + + + + + +
    _('Opensrs.tab_dnssec.field_key_tag');?>_('Opensrs.tab_dnssec.field_algorithm');?>_('Opensrs.tab_dnssec.field_digest_type');?>_('Opensrs.tab_dnssec.field_digest');?>
    Html->safe($record['key_tag'] ?? '');?>Html->safe($record['algorithm'] ?? '');?>Html->safe($record['digest_type'] ?? '');?>Html->safe(substr($record['digest'] ?? '', 0, 32) . (strlen($record['digest'] ?? '') > 32 ? '...' : ''));?> + Form->create(); + $this->Form->fieldHidden('action', 'delete_ds_record'); + $this->Form->fieldHidden('record_index', $record['record_index'] ?? ''); + ?> + + Form->end(); + ?> +
    +
    + +
    _('Opensrs.tab_dnssec.no_records');?>
    + + +

    _('Opensrs.tab_dnssec.add_record');?>

    + Form->create(); + $this->Form->fieldHidden('action', 'add_ds_record'); + ?> +
    + Form->label($this->_('Opensrs.tab_dnssec.field_key_tag', true), 'key_tag'); + $this->Form->fieldText('key_tag', ($vars->key_tag ?? null), ['id' => 'key_tag', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dnssec.field_algorithm', true), 'algorithm'); + $this->Form->fieldSelect('algorithm', ($algorithms ?? []), ($vars->algorithm ?? '13'), ['id' => 'algorithm', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dnssec.field_digest_type', true), 'digest_type'); + $this->Form->fieldSelect('digest_type', ($digest_types ?? []), ($vars->digest_type ?? '2'), ['id' => 'digest_type', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_dnssec.field_digest', true), 'digest'); + $this->Form->fieldText('digest', ($vars->digest ?? null), ['id' => 'digest', 'class' => 'form-control']); + ?> +
    + + Form->end(); + ?> +
    +
    diff --git a/views/default/tab_client_url_forwarding.pdt b/views/default/tab_client_url_forwarding.pdt new file mode 100644 index 0000000..782396a --- /dev/null +++ b/views/default/tab_client_url_forwarding.pdt @@ -0,0 +1,85 @@ + +
    +
    +

    _('Opensrs.tab_url_forwarding.title');?>

    + + +
    + + + + + + + + + + + + + + + + + + + +
    _('Opensrs.tab_url_forwarding.field_subdomain');?>_('Opensrs.tab_url_forwarding.field_destination');?>_('Opensrs.tab_url_forwarding.field_redirect_type');?>
    Html->safe($record['subdomain'] ?? '@');?>Html->safe($record['ip_address'] ?? '');?>Html->safe($record['type'] ?? '301');?> + Form->create(); + $this->Form->fieldHidden('action', 'delete_forwarding'); + $this->Form->fieldHidden('record_index', $record['record_index'] ?? ''); + ?> + + Form->end(); + ?> +
    +
    + +
    _('Opensrs.tab_url_forwarding.no_records');?>
    + + +

    _('Opensrs.tab_url_forwarding.add_record');?>

    + Form->create(); + $this->Form->fieldHidden('action', 'set_forwarding'); + ?> +
    + Form->label($this->_('Opensrs.tab_url_forwarding.field_subdomain', true), 'subdomain'); + $this->Form->fieldText('subdomain', ($vars->subdomain ?? '@'), ['id' => 'subdomain', 'class' => 'form-control']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_url_forwarding.field_destination', true), 'destination'); + $this->Form->fieldText('destination', ($vars->destination ?? null), ['id' => 'destination', 'class' => 'form-control', 'placeholder' => 'https://example.com']); + ?> +
    +
    + Form->label($this->_('Opensrs.tab_url_forwarding.field_redirect_type', true), 'redirect_type'); + $this->Form->fieldSelect('redirect_type', ($redirect_types ?? []), ($vars->redirect_type ?? '301'), ['id' => 'redirect_type', 'class' => 'form-control']); + ?> +
    + + Form->end(); + ?> +
    +
    diff --git a/views/default/tab_client_whois.pdt b/views/default/tab_client_whois.pdt index a43e003..dd24e36 100644 --- a/views/default/tab_client_whois.pdt +++ b/views/default/tab_client_whois.pdt @@ -16,7 +16,6 @@
    $key) { ?>
    diff --git a/views/default/tab_dns.pdt b/views/default/tab_dns.pdt new file mode 100644 index 0000000..a42f18b --- /dev/null +++ b/views/default/tab_dns.pdt @@ -0,0 +1,117 @@ + +
    +

    _('Opensrs.tab_dns.title');?>

    +
    + + + + + + + + + + + + $record) { + ?> + > + + + + + + + + +
    _('Opensrs.tab_dns.field_type');?>_('Opensrs.tab_dns.field_subdomain');?>_('Opensrs.tab_dns.field_ip_address');?>_('Opensrs.tab_dns.field_priority');?>_('Opensrs.tab_dns.field_ttl');?>_('Opensrs.tab_dns.field_options');?>
    Html->safe($record['record_type'] ?? '');?>Html->safe($record['subdomain'] ?? '');?>Html->safe($record['ip_address'] ?? '');?>Html->safe($record['priority'] ?? '');?>Html->safe($record['ttl'] ?? '');?> + Form->create(); + $this->Form->fieldHidden('action', 'delete_record'); + $this->Form->fieldHidden('record_type', strtolower($record['record_type'] ?? '')); + $this->Form->fieldHidden('record_index', $record['record_index'] ?? ''); + ?> + + Form->end(); + ?> +
    + +
    +
    _('Opensrs.tab_dns.no_records');?>
    +
    + + +
    +

    _('Opensrs.tab_dns.add_record');?>

    +
    + Form->create(); + $this->Form->fieldHidden('action', 'add_record'); + ?> +
    +
      +
    • + Form->label($this->_('Opensrs.tab_dns.field_type', true), 'type'); + $this->Form->fieldSelect('type', ($record_types ?? []), ($vars->type ?? 'A'), ['id' => 'type']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dns.field_subdomain', true), 'subdomain'); + $this->Form->fieldText('subdomain', ($vars->subdomain ?? null), ['id' => 'subdomain']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dns.field_ip_address', true), 'ip_address'); + $this->Form->fieldText('ip_address', ($vars->ip_address ?? null), ['id' => 'ip_address']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dns.field_priority', true), 'priority'); + $this->Form->fieldText('priority', ($vars->priority ?? null), ['id' => 'priority']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dns.field_ttl', true), 'ttl'); + $this->Form->fieldText('ttl', ($vars->ttl ?? '3600'), ['id' => 'ttl']); + ?> +
    • +
    +
    +
    + Form->fieldSubmit('save', $this->_('Opensrs.tab_dns.field_add', true), ['class' => 'btn btn-primary float-right']); + ?> +
    + Form->end(); + ?> + +
    + Form->create(); + $this->Form->fieldHidden('action', 'reset_zone'); + ?> + + Form->end(); + ?> +
    diff --git a/views/default/tab_dnssec.pdt b/views/default/tab_dnssec.pdt new file mode 100644 index 0000000..2734aa6 --- /dev/null +++ b/views/default/tab_dnssec.pdt @@ -0,0 +1,95 @@ + +
    +

    _('Opensrs.tab_dnssec.title');?>

    +
    + + + + + + + + + + + $record) { + ?> + > + + + + + + + +
    _('Opensrs.tab_dnssec.field_key_tag');?>_('Opensrs.tab_dnssec.field_algorithm');?>_('Opensrs.tab_dnssec.field_digest_type');?>_('Opensrs.tab_dnssec.field_digest');?>_('Opensrs.tab_dns.field_options');?>
    Html->safe($record['key_tag'] ?? '');?>Html->safe($record['algorithm'] ?? '');?>Html->safe($record['digest_type'] ?? '');?>Html->safe(substr($record['digest'] ?? '', 0, 32) . (strlen($record['digest'] ?? '') > 32 ? '...' : ''));?> + Form->create(); + $this->Form->fieldHidden('action', 'delete_ds_record'); + $this->Form->fieldHidden('record_index', $record['record_index'] ?? ''); + ?> + + Form->end(); + ?> +
    + +
    +
    _('Opensrs.tab_dnssec.no_records');?>
    +
    + + +
    +

    _('Opensrs.tab_dnssec.add_record');?>

    +
    + Form->create(); + $this->Form->fieldHidden('action', 'add_ds_record'); + ?> +
    +
      +
    • + Form->label($this->_('Opensrs.tab_dnssec.field_key_tag', true), 'key_tag'); + $this->Form->fieldText('key_tag', ($vars->key_tag ?? null), ['id' => 'key_tag']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dnssec.field_algorithm', true), 'algorithm'); + $this->Form->fieldSelect('algorithm', ($algorithms ?? []), ($vars->algorithm ?? '13'), ['id' => 'algorithm']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dnssec.field_digest_type', true), 'digest_type'); + $this->Form->fieldSelect('digest_type', ($digest_types ?? []), ($vars->digest_type ?? '2'), ['id' => 'digest_type']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_dnssec.field_digest', true), 'digest'); + $this->Form->fieldText('digest', ($vars->digest ?? null), ['id' => 'digest']); + ?> +
    • +
    +
    +
    + Form->fieldSubmit('save', $this->_('Opensrs.tab_dnssec.field_add', true), ['class' => 'btn btn-primary float-right']); + ?> +
    + Form->end(); + ?> diff --git a/views/default/tab_url_forwarding.pdt b/views/default/tab_url_forwarding.pdt new file mode 100644 index 0000000..897c084 --- /dev/null +++ b/views/default/tab_url_forwarding.pdt @@ -0,0 +1,87 @@ + +
    +

    _('Opensrs.tab_url_forwarding.title');?>

    +
    + + + + + + + + + + $record) { + ?> + > + + + + + + +
    _('Opensrs.tab_url_forwarding.field_subdomain');?>_('Opensrs.tab_url_forwarding.field_destination');?>_('Opensrs.tab_url_forwarding.field_redirect_type');?>_('Opensrs.tab_dns.field_options');?>
    Html->safe($record['subdomain'] ?? '@');?>Html->safe($record['ip_address'] ?? '');?>Html->safe($record['type'] ?? '301');?> + Form->create(); + $this->Form->fieldHidden('action', 'delete_forwarding'); + $this->Form->fieldHidden('record_index', $record['record_index'] ?? ''); + ?> + + Form->end(); + ?> +
    + +
    +
    _('Opensrs.tab_url_forwarding.no_records');?>
    +
    + + +
    +

    _('Opensrs.tab_url_forwarding.add_record');?>

    +
    + Form->create(); + $this->Form->fieldHidden('action', 'set_forwarding'); + ?> +
    +
      +
    • + Form->label($this->_('Opensrs.tab_url_forwarding.field_subdomain', true), 'subdomain'); + $this->Form->fieldText('subdomain', ($vars->subdomain ?? '@'), ['id' => 'subdomain']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_url_forwarding.field_destination', true), 'destination'); + $this->Form->fieldText('destination', ($vars->destination ?? null), ['id' => 'destination', 'placeholder' => 'https://example.com']); + ?> +
    • +
    • + Form->label($this->_('Opensrs.tab_url_forwarding.field_redirect_type', true), 'redirect_type'); + $this->Form->fieldSelect('redirect_type', ($redirect_types ?? []), ($vars->redirect_type ?? '301'), ['id' => 'redirect_type']); + ?> +
    • +
    +
    +
    + Form->fieldSubmit('save', $this->_('Opensrs.tab_url_forwarding.field_add', true), ['class' => 'btn btn-primary float-right']); + ?> +
    + Form->end(); + ?>