mirror of
https://github.com/getnamingo/registry.git
synced 2025-05-20 11:29:22 +02:00
New EPP server structure
This commit is contained in:
parent
bf1de16332
commit
6663fca314
9 changed files with 8 additions and 8 deletions
935
epp/src/EppWriter.php
Normal file
935
epp/src/EppWriter.php
Normal file
|
@ -0,0 +1,935 @@
|
|||
<?php
|
||||
|
||||
namespace EPP;
|
||||
|
||||
use XMLWriter;
|
||||
|
||||
class EppWriter {
|
||||
|
||||
// Properties
|
||||
private $command_handler_map = [
|
||||
'greeting' => '_greeting',
|
||||
'login' => '_common',
|
||||
'logout' => '_common',
|
||||
'check_contact' => '_check_contact',
|
||||
'info_contact' => '_info_contact',
|
||||
'transfer_contact' => '_transfer_contact',
|
||||
'create_contact' => '_create_contact',
|
||||
'delete_contact' => '_common',
|
||||
'update_contact' => '_common',
|
||||
'check_domain' => '_check_domain',
|
||||
'create_domain' => '_create_domain',
|
||||
'delete_domain' => '_common',
|
||||
'info_domain' => '_info_domain',
|
||||
'renew_domain' => '_renew_domain',
|
||||
'transfer_domain' => '_transfer_domain',
|
||||
'update_domain' => '_common',
|
||||
'check_host' => '_check_host',
|
||||
'create_host' => '_create_host',
|
||||
'delete_host' => '_common',
|
||||
'info_host' => '_info_host',
|
||||
'info_funds' => '_info_funds',
|
||||
'update_host' => '_common',
|
||||
'poll' => '_poll',
|
||||
'error' => '_common',
|
||||
'unknown' => '_common',
|
||||
];
|
||||
|
||||
// Methods
|
||||
public function epp_writer($resp) {
|
||||
$writer = new XMLWriter();
|
||||
$writer->openMemory();
|
||||
$writer->setIndent(true);
|
||||
$writer->setIndentString(' ');
|
||||
$writer->startDocument('1.0', 'UTF-8', 'no');
|
||||
$writer->startElement('epp');
|
||||
$writer->writeAttribute('xmlns', 'urn:ietf:params:xml:ns:epp-1.0');
|
||||
$writer->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd');
|
||||
|
||||
// Dynamic method call based on the command
|
||||
$handler = $this->command_handler_map[$resp['command']];
|
||||
$this->$handler($writer, $resp);
|
||||
|
||||
$writer->endElement(); // Ending the 'epp' tag
|
||||
$writer->endDocument();
|
||||
return $writer->outputMemory();
|
||||
}
|
||||
|
||||
private function epp_result_totext($code, $lang = 'en-US') {
|
||||
$resultTexts = [
|
||||
1000 => [
|
||||
'code' => 'EPP_RS_SUCCESS',
|
||||
'en-US' => 'Command completed successfully',
|
||||
'fr-FR' => "la commande terminée avec succès"
|
||||
],
|
||||
1001 => [
|
||||
'code' => 'EPP_RS_PENDING',
|
||||
'en-US' => 'Command completed successfully; action pending',
|
||||
'fr-FR' => "la commande terminée avec succès ; l;'action est en suspens"
|
||||
],
|
||||
1300 => [
|
||||
'code' => 'EPP_RS_NOMSG',
|
||||
'en-US' => 'Command completed successfully; no messages',
|
||||
'fr-FR' => "la commande terminée avec succès ; il n'ya acun message"
|
||||
],
|
||||
1301 => [
|
||||
'code' => 'EPP_RS_ACK',
|
||||
'en-US' => 'Command completed successfully; ack to dequeue',
|
||||
'fr-FR' => "la commande terminé avec succès ; ack à retirer de la file d'attente"
|
||||
],
|
||||
1500 => [
|
||||
'code' => 'EPP_RS_END',
|
||||
'en-US' => 'Command completed successfully; ending session',
|
||||
'fr-FR' => "la commande terminé avec succès ; la session termine"
|
||||
],
|
||||
2000 => [
|
||||
'code' => 'EPP_RF_UNKCMD',
|
||||
'en-US' => 'Unknown command',
|
||||
'fr-FR' => "la commande est inconnue"
|
||||
],
|
||||
2001 => [
|
||||
'code' => 'EPP_RF_SYNTAX',
|
||||
'en-US' => 'Command syntax error',
|
||||
'fr-FR' => "erreur de syntaxe à la commande"
|
||||
],
|
||||
2002 => [
|
||||
'code' => 'EPP_RF_CMDUSE',
|
||||
'en-US' => 'Command use error',
|
||||
'fr-FR' => "erreur d'utilisation à la commande"
|
||||
],
|
||||
2003 => [
|
||||
'code' => 'EPP_RF_PARAM',
|
||||
'en-US' => 'Required parameter missing',
|
||||
'fr-FR' => "paramètre exigé est manquant"
|
||||
],
|
||||
2004 => [
|
||||
'code' => 'EPP_RF_VALRANGE',
|
||||
'en-US' => 'Parameter value range error',
|
||||
'fr-FR' => "la valeur de paramètre est hors d'intervalle"
|
||||
],
|
||||
2005 => [
|
||||
'code' => 'EPP_RF_VALSYNTAX',
|
||||
'en-US' => 'Parameter value syntax error',
|
||||
'fr-FR' => "erreur de syntaxe en valeur de paramètre"
|
||||
],
|
||||
2100 => [
|
||||
'code' => 'EPP_RF_PROTVERS',
|
||||
'en-US' => 'Unimplemented protocol version',
|
||||
'fr-FR' => "la version de protocole n'est pas mise en application"
|
||||
],
|
||||
2101 => [
|
||||
'code' => 'EPP_RF_UNIMPCMD',
|
||||
'en-US' => 'Unimplemented command',
|
||||
'fr-FR' => "la commande n'est pas mise en application"
|
||||
],
|
||||
2102 => [
|
||||
'code' => 'EPP_RF_UNIMPOPT',
|
||||
'en-US' => 'Unimplemented option',
|
||||
'fr-FR' => "l'option n'est pas mise en application"
|
||||
],
|
||||
2103 => [
|
||||
'code' => 'EPP_RF_UNIMPEXT',
|
||||
'en-US' => 'Unimplemented extension',
|
||||
'fr-FR' => "l'extension n'est pas mise en application"
|
||||
],
|
||||
2104 => [
|
||||
'code' => 'EPP_RF_BILLING',
|
||||
'en-US' => 'Billing failure',
|
||||
'fr-FR' => "panne de facturation"
|
||||
],
|
||||
2105 => [
|
||||
'code' => 'EPP_RF_NORENEW',
|
||||
'en-US' => 'Object is not eligible for renewal',
|
||||
'fr-FR' => "l'objet n'est pas habilité au renouvellement"
|
||||
],
|
||||
2106 => [
|
||||
'code' => 'EPP_RF_NOTRANSFER',
|
||||
'en-US' => 'Object is not eligible for transfer',
|
||||
'fr-FR' => "l'objet n'est pas éligible pour être transféré"
|
||||
],
|
||||
2200 => [
|
||||
'code' => 'EPP_RF_AUTHENTICATION',
|
||||
'en-US' => 'Authentication error',
|
||||
'fr-FR' => "erreur d'authentification"
|
||||
],
|
||||
2201 => [
|
||||
'code' => 'EPP_RF_AUTHORIZATION',
|
||||
'en-US' => 'Authorization error',
|
||||
'fr-FR' => "erreur d'autorisation"
|
||||
],
|
||||
2202 => [
|
||||
'code' => 'EPP_RF_INVAUTHOR',
|
||||
'en-US' => 'Invalid authorization information',
|
||||
'fr-FR' => "l'information d'autorisation est incorrecte"
|
||||
],
|
||||
2300 => [
|
||||
'code' => 'EPP_RF_PENDINGTRANSFER',
|
||||
'en-US' => 'Object pending transfer',
|
||||
'fr-FR' => "l'objet est transfert en suspens"
|
||||
],
|
||||
2301 => [
|
||||
'code' => 'EPP_RF_NOTPENDINGTRANSFER',
|
||||
'en-US' => 'Object not pending transfer',
|
||||
'fr-FR' => "l'objet n'est pas transfert en suspens"
|
||||
],
|
||||
2302 => [
|
||||
'code' => 'EPP_RF_EXISTS',
|
||||
'en-US' => 'Object exists',
|
||||
'fr-FR' => "l'objet existe"
|
||||
],
|
||||
2303 => [
|
||||
'code' => 'EPP_RF_NOTEXISTS',
|
||||
'en-US' => 'Object does not exist',
|
||||
'fr-FR' => "l'objet n'existe pas"
|
||||
],
|
||||
2304 => [
|
||||
'code' => 'EPP_RF_STATUS',
|
||||
'en-US' => 'Object status prohibits operation',
|
||||
'fr-FR' => "le statut de l'objet interdit cette exécution"
|
||||
],
|
||||
2305 => [
|
||||
'code' => 'EPP_RF_INUSE',
|
||||
'en-US' => 'Object association prohibits operation',
|
||||
'fr-FR' => "l'assocation de l'objet interdit cette exécution"
|
||||
],
|
||||
2306 => [
|
||||
'code' => 'EPP_RF_POLICYPARAM',
|
||||
'en-US' => 'Parameter value policy error',
|
||||
'fr-FR' => "erreur de politique en valeur du paramètre"
|
||||
],
|
||||
2307 => [
|
||||
'code' => 'EPP_RF_UNIMPLSERVICE',
|
||||
'en-US' => 'Unimplemented object service',
|
||||
'fr-FR' => "le service d'objet n'est pas mis en application"
|
||||
],
|
||||
2308 => [
|
||||
'code' => 'EPP_RF_DATAMGT',
|
||||
'en-US' => 'Data management policy violation',
|
||||
'fr-FR' => "violation de la politique de gestion des données"
|
||||
],
|
||||
2400 => [
|
||||
'code' => 'EPP_RF_FAIL',
|
||||
'en-US' => 'Command failed',
|
||||
'fr-FR' => "la commande a échoué"
|
||||
],
|
||||
2500 => [
|
||||
'code' => 'EPP_RF_CLOSING',
|
||||
'en-US' => 'Command failed; server closing connection',
|
||||
'fr-FR' => "la commande a échoué ; le serveur ferme la connexion"
|
||||
],
|
||||
2501 => [
|
||||
'code' => 'EPP_RF_AUTHCLOSING',
|
||||
'en-US' => 'Authentiction error; server closing connection',
|
||||
'fr-FR' => "erreur d'authentification ; le serveur ferme la connexion"
|
||||
],
|
||||
2502 => [
|
||||
'code' => 'EPP_RF_SESSIONLIMIT',
|
||||
'en-US' => 'Session limit exceeded; server closing connection',
|
||||
'fr-FR' => "la limite de session a été dépassée ; le serveur ferme la connexion"
|
||||
]
|
||||
];
|
||||
|
||||
if (isset($resultTexts[$code][$lang])) {
|
||||
return $resultTexts[$code][$lang];
|
||||
}
|
||||
|
||||
// Fallback to English if the specified language text doesn't exist
|
||||
if (isset($resultTexts[$code]['en-US'])) {
|
||||
return $resultTexts[$code]['en-US'];
|
||||
}
|
||||
|
||||
// Return a default message if the code is not found
|
||||
return 'Unknown response code';
|
||||
}
|
||||
|
||||
private function epp_success($resultCode) {
|
||||
// Typically, EPP result codes for successful commands are in the range of 1000-1999.
|
||||
// But you might need to adjust this range based on your specific EPP server responses.
|
||||
return $resultCode >= 1000 && $resultCode <= 1999;
|
||||
}
|
||||
|
||||
private function _greeting($writer, $resp) {
|
||||
$writer->startElement('greeting');
|
||||
|
||||
// Server ID and Server Date
|
||||
$writer->writeElement('svID', $resp['svID']);
|
||||
$writer->writeElement('svDate', $resp['svDate']);
|
||||
|
||||
// Services
|
||||
$writer->startElement('svcMenu');
|
||||
$writer->writeElement('version', $resp['version']);
|
||||
|
||||
// Check if 'lang' is an array and handle accordingly
|
||||
if (is_array($resp['lang'])) {
|
||||
foreach ($resp['lang'] as $language) {
|
||||
$writer->writeElement('lang', $language);
|
||||
}
|
||||
} else {
|
||||
$writer->writeElement('lang', $resp['lang']);
|
||||
}
|
||||
|
||||
foreach ($resp['services'] as $service) {
|
||||
$writer->writeElement('objURI', $service);
|
||||
}
|
||||
|
||||
// Optional extensions
|
||||
if (isset($resp['extensions'])) {
|
||||
$writer->startElement('svcExtension');
|
||||
foreach ($resp['extensions'] as $extension) {
|
||||
$writer->writeElement('extURI', $extension);
|
||||
}
|
||||
$writer->endElement(); // End of 'svcExtension'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'svcMenu'
|
||||
|
||||
// Optional Data Collection Policy (dcp)
|
||||
if (isset($resp['dcp'])) {
|
||||
$writer->startElement('dcp');
|
||||
|
||||
// Handle the access element
|
||||
if (isset($resp['dcp']['access'])) {
|
||||
$writer->startElement('access');
|
||||
foreach ($resp['dcp']['access'] as $accessType) {
|
||||
$writer->startElement($accessType);
|
||||
$writer->endElement();
|
||||
}
|
||||
$writer->endElement(); // End of 'access'
|
||||
}
|
||||
|
||||
// Handle the statement element
|
||||
if (isset($resp['dcp']['statement'])) {
|
||||
$writer->startElement('statement');
|
||||
|
||||
// Handle purpose
|
||||
if (isset($resp['dcp']['statement']['purpose'])) {
|
||||
$writer->startElement('purpose');
|
||||
foreach ($resp['dcp']['statement']['purpose'] as $purposeType) {
|
||||
$writer->startElement($purposeType);
|
||||
$writer->endElement();
|
||||
}
|
||||
$writer->endElement(); // End of 'purpose'
|
||||
}
|
||||
|
||||
// Handle recipient
|
||||
if (isset($resp['dcp']['statement']['recipient'])) {
|
||||
$writer->startElement('recipient');
|
||||
foreach ($resp['dcp']['statement']['recipient'] as $recipientType) {
|
||||
$writer->startElement($recipientType);
|
||||
$writer->endElement();
|
||||
}
|
||||
$writer->endElement(); // End of 'recipient'
|
||||
}
|
||||
|
||||
// Handle retention
|
||||
if (isset($resp['dcp']['statement']['retention'])) {
|
||||
$writer->startElement('retention');
|
||||
foreach ($resp['dcp']['statement']['retention'] as $retentionType) {
|
||||
$writer->startElement($retentionType);
|
||||
$writer->endElement();
|
||||
}
|
||||
$writer->endElement(); // End of 'retention'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'statement'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'dcp'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'greeting'
|
||||
}
|
||||
|
||||
private function _preamble($writer, $resp) {
|
||||
$lang = 'en-US';
|
||||
if (isset($resp['lang'])) {
|
||||
$lang = $resp['lang'];
|
||||
}
|
||||
|
||||
$code = $resp['resultCode'];
|
||||
|
||||
$writer->startElement('response');
|
||||
$writer->startElement('result');
|
||||
$writer->writeAttribute('code', $code);
|
||||
|
||||
$msg = $this->epp_result_totext($code, $lang);
|
||||
if (isset($resp['human_readable_message'])) {
|
||||
$msg = $this->epp_result_totext($code, $lang) . ' : ' . $resp['human_readable_message'];
|
||||
}
|
||||
|
||||
$writer->writeElement('msg', $msg);
|
||||
|
||||
if (isset($resp['optionalValue'])) {
|
||||
$writer->startElement('value');
|
||||
if (isset($resp['xmlns_obj']) && isset($resp['xmlns_obj_value'])) {
|
||||
$writer->writeAttribute($resp['xmlns_obj'], $resp['xmlns_obj_value']);
|
||||
}
|
||||
if (isset($resp['obj_elem']) && isset($resp['obj_elem_value'])) {
|
||||
$writer->writeElement($resp['obj_elem'], $resp['obj_elem_value']);
|
||||
}
|
||||
$writer->endElement(); // End of 'value'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'result'
|
||||
}
|
||||
|
||||
private function _postamble($writer, $resp) {
|
||||
if (isset($resp['clTRID']) || isset($resp['svTRID'])) {
|
||||
$writer->startElement('trID');
|
||||
$writer->writeElement('clTRID', $resp['clTRID']);
|
||||
$writer->writeElement('svTRID', $resp['svTRID']);
|
||||
$writer->endElement(); // End of 'trID'
|
||||
}
|
||||
$writer->endElement(); // End of 'response'
|
||||
}
|
||||
|
||||
private function _common($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _poll($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($resp['resultCode'] == 1000) {
|
||||
$writer->startElement('msgQ');
|
||||
$writer->writeAttribute('count', $resp['count']);
|
||||
$writer->writeAttribute('id', $resp['id']);
|
||||
$writer->endElement(); // End of 'msgQ'
|
||||
}
|
||||
elseif ($resp['resultCode'] == 1301) {
|
||||
$writer->startElement('msgQ');
|
||||
$writer->writeAttribute('count', $resp['count']);
|
||||
$writer->writeAttribute('id', $resp['id']);
|
||||
$writer->writeElement('qDate', $resp['qDate']);
|
||||
$writer->writeElement('msg', $resp['msg'], ['lang' => $resp['lang']]);
|
||||
$writer->endElement(); // End of 'msgQ'
|
||||
if ($resp['poll_msg_type'] === 'lowBalance') {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('lowbalance-poll:pollData');
|
||||
$writer->writeAttribute('xmlns:lowbalance-poll', 'http://www.verisign.com/epp/lowbalance-poll-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'http://www.verisign.com/epp/lowbalance-poll-1.0 lowbalance-poll-1.0.xsd');
|
||||
$writer->writeElement('lowbalance-poll:registrarName', $resp['registrarName']);
|
||||
$writer->writeElement('lowbalance-poll:creditLimit', $resp['creditLimit']);
|
||||
$writer->writeElement('lowbalance-poll:creditThreshold', $resp['creditThreshold'], ['type' => $resp['creditThresholdType']]);
|
||||
$writer->writeElement('lowbalance-poll:availableCredit', $resp['availableCredit']);
|
||||
$writer->endElement(); // End of 'lowbalance-poll:pollData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
} elseif ($resp['poll_msg_type'] === 'domainTransfer') {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('domain:trnData');
|
||||
$writer->writeAttribute('xmlns:domain', 'urn:ietf:params:xml:ns:domain-1.0');
|
||||
$writer->writeElement('domain:name', $resp['name']);
|
||||
$writer->writeElement('domain:trStatus', $resp['obj_trStatus']);
|
||||
$writer->writeElement('domain:reID', $resp['obj_reID']);
|
||||
$writer->writeElement('domain:reDate', $resp['obj_reDate']);
|
||||
$writer->writeElement('domain:acID', $resp['obj_acID']);
|
||||
$writer->writeElement('domain:acDate', $resp['obj_acDate']);
|
||||
if (isset($resp['obj_exDate'])) {
|
||||
$writer->writeElement('domain:exDate', $resp['obj_exDate']);
|
||||
}
|
||||
$writer->endElement(); // End of 'domain:trnData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
} elseif ($resp['poll_msg_type'] === 'contactTransfer') {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('contact:trnData');
|
||||
$writer->writeAttribute('xmlns:contact', 'urn:ietf:params:xml:ns:contact-1.0');
|
||||
$writer->writeElement('contact:id', $resp['identifier']);
|
||||
$writer->writeElement('contact:trStatus', $resp['obj_trStatus']);
|
||||
$writer->writeElement('contact:reID', $resp['obj_reID']);
|
||||
$writer->writeElement('contact:reDate', $resp['obj_reDate']);
|
||||
$writer->writeElement('contact:acID', $resp['obj_acID']);
|
||||
$writer->writeElement('contact:acDate', $resp['obj_acDate']);
|
||||
$writer->endElement(); // End of 'contact:trnData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
|
||||
}
|
||||
|
||||
private function _check_contact($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('contact:chkData');
|
||||
$writer->writeAttribute('xmlns:contact', 'urn:ietf:params:xml:ns:contact-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd');
|
||||
|
||||
foreach ($resp['ids'] as $ids) {
|
||||
$writer->startElement('contact:cd');
|
||||
$writer->startElement('contact:id');
|
||||
$writer->writeAttribute('avail', $ids[1]);
|
||||
$writer->text($ids[0]);
|
||||
$writer->endElement(); // End of 'contact:id'
|
||||
|
||||
if (isset($ids[2])) {
|
||||
$writer->writeElement('contact:reason', $ids[2]);
|
||||
}
|
||||
$writer->endElement(); // End of 'contact:cd'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'contact:chkData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _info_contact($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('contact:infData');
|
||||
$writer->writeAttribute('xmlns:contact', 'urn:ietf:params:xml:ns:contact-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd');
|
||||
$writer->writeElement('contact:id', $resp['id']);
|
||||
$writer->writeElement('contact:roid', $resp['roid']);
|
||||
// Handle 'contact:status'
|
||||
if (isset($resp['status']) && is_array($resp['status'])) {
|
||||
foreach ($resp['status'] as $s) {
|
||||
if (isset($s[1]) && isset($s[2])) {
|
||||
$writer->writeElement('contact:status', $s[2], ['s' => $s[0], 'lang' => $s[1]]);
|
||||
} else {
|
||||
$writer->startElement('contact:status');
|
||||
$writer->writeAttribute('s', $s[0]);
|
||||
$writer->endElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle 'contact:postalInfo'
|
||||
foreach ($resp['postal'] as $t => $postalData) {
|
||||
$writer->startElement('contact:postalInfo');
|
||||
$writer->writeAttribute('type', $t);
|
||||
$writer->writeElement('contact:name', $postalData['name']);
|
||||
$writer->writeElement('contact:org', $postalData['org']);
|
||||
$writer->startElement('contact:addr');
|
||||
foreach ($postalData['street'] as $s) {
|
||||
if ($s) {
|
||||
$writer->writeElement('contact:street', $s);
|
||||
}
|
||||
}
|
||||
$writer->writeElement('contact:city', $postalData['city']);
|
||||
if (isset($postalData['sp'])) {
|
||||
$writer->writeElement('contact:sp', $postalData['sp']);
|
||||
}
|
||||
if (isset($postalData['pc'])) {
|
||||
$writer->writeElement('contact:pc', $postalData['pc']);
|
||||
}
|
||||
$writer->writeElement('contact:cc', $postalData['cc']);
|
||||
$writer->endElement(); // End of 'contact:addr'
|
||||
$writer->endElement(); // End of 'contact:postalInfo'
|
||||
}
|
||||
|
||||
// Handling 'contact:voice' and its optional attribute
|
||||
if (isset($resp['voice_x'])) {
|
||||
$writer->writeElement('contact:voice', $resp['voice'], ['x' => $resp['voice_x']]);
|
||||
} else {
|
||||
$writer->writeElement('contact:voice', $resp['voice']);
|
||||
}
|
||||
|
||||
// Handling 'contact:fax' and its optional attribute
|
||||
if (isset($resp['fax_x'])) {
|
||||
$writer->writeElement('contact:fax', $resp['fax'], ['x' => $resp['fax_x']]);
|
||||
} else {
|
||||
$writer->writeElement('contact:fax', $resp['fax']);
|
||||
}
|
||||
|
||||
$writer->writeElement('contact:email', $resp['email']);
|
||||
$writer->writeElement('contact:clID', $resp['clID']);
|
||||
$writer->writeElement('contact:crID', $resp['crID']);
|
||||
$writer->writeElement('contact:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||
if (isset($resp['upID'])) {
|
||||
$writer->writeElement('contact:upID', $resp['upID']);
|
||||
}
|
||||
if (isset($resp['upDate'])) {
|
||||
$writer->writeElement('contact:upDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['upDate'])));
|
||||
}
|
||||
if (isset($resp['trDate'])) {
|
||||
$writer->writeElement('contact:trDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['trDate'])));
|
||||
}
|
||||
|
||||
// Handling 'contact:authInfo'
|
||||
if ($resp['authInfo'] === 'valid') {
|
||||
$writer->startElement('contact:authInfo');
|
||||
if ($resp['authInfo_type'] === 'pw') {
|
||||
$writer->writeElement('contact:pw', $resp['authInfo_val']);
|
||||
} elseif ($resp['authInfo_type'] === 'ext') {
|
||||
$writer->writeElement('contact:ext', $resp['authInfo_val']);
|
||||
}
|
||||
$writer->endElement(); // End of 'contact:authInfo'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'contact:infData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
|
||||
// Handling the extension part
|
||||
if (isset($resp['nin']) && isset($resp['nin_type'])) {
|
||||
$writer->startElement('extension');
|
||||
$writer->startElement('identExt:infData');
|
||||
$writer->writeAttribute('xmlns:identExt', 'http://www.nic.xx/XXNIC-EPP/identExt-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'http://www.nic.xx/XXNIC-EPP/identExt-1.0 identExt-1.0.xsd');
|
||||
|
||||
$writer->startElement('identExt:nin');
|
||||
$writer->writeAttribute('type', $resp['nin_type']);
|
||||
$writer->text($resp['nin']);
|
||||
$writer->endElement(); // End of 'identExt:nin'
|
||||
|
||||
$writer->endElement(); // End of 'identExt:infData'
|
||||
$writer->endElement(); // End of 'extension'
|
||||
}
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _transfer_contact($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('contact:trnData');
|
||||
$writer->writeAttribute('xmlns:contact', 'urn:ietf:params:xml:ns:contact-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd');
|
||||
$writer->writeElement('contact:id', $resp['id']);
|
||||
$writer->writeElement('contact:trStatus', $resp['trStatus']);
|
||||
$writer->writeElement('contact:reID', $resp['reID']);
|
||||
$writer->writeElement('contact:reDate', $resp['reDate']);
|
||||
$writer->writeElement('contact:acID', $resp['acID']);
|
||||
$writer->writeElement('contact:acDate', $resp['acDate']);
|
||||
$writer->endElement(); // End of 'contact:trnData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _create_contact($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('contact:creData');
|
||||
$writer->writeAttribute('xmlns:contact', 'urn:ietf:params:xml:ns:contact-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd');
|
||||
$writer->writeElement('contact:id', $resp['id']);
|
||||
$writer->writeElement('contact:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||
$writer->endElement(); // End of 'contact:creData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _check_domain($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('domain:chkData');
|
||||
$writer->writeAttribute('xmlns:domain', 'urn:ietf:params:xml:ns:domain-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd');
|
||||
foreach ($resp['names'] as $names) {
|
||||
$writer->startElement('domain:cd');
|
||||
$writer->startElement('domain:name');
|
||||
$writer->writeAttribute('avail', $names[1]);
|
||||
$writer->text($names[0]);
|
||||
$writer->endElement(); // End of 'domain:name'
|
||||
if (isset($names[2])) {
|
||||
$writer->writeElement('domain:reason', $names[2]);
|
||||
}
|
||||
$writer->endElement(); // End of 'domain:cd'
|
||||
}
|
||||
$writer->endElement(); // End of 'domain:chkData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _create_domain($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('domain:creData');
|
||||
$writer->writeAttribute('xmlns:domain', 'urn:ietf:params:xml:ns:domain-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd');
|
||||
$writer->writeElement('domain:name', $resp['name']);
|
||||
$writer->writeElement('domain:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||
$writer->writeElement('domain:exDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['exDate'])));
|
||||
$writer->endElement(); // End of 'domain:creData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _info_domain($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('domain:infData');
|
||||
$writer->writeAttribute('xmlns:domain', 'urn:ietf:params:xml:ns:domain-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd');
|
||||
$writer->writeElement('domain:name', $resp['name']);
|
||||
$writer->writeElement('domain:roid', $resp['roid']);
|
||||
foreach ($resp['status'] as $s) {
|
||||
if (isset($s[1]) && isset($s[2])) {
|
||||
$writer->writeElement('domain:status', $s[2], ['s' => $s[0], 'lang' => $s[1]]);
|
||||
} else {
|
||||
$writer->startElement('domain:status');
|
||||
$writer->writeAttribute('s', $s[0]);
|
||||
$writer->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($resp['registrant'])) {
|
||||
$writer->writeElement('domain:registrant', $resp['registrant']);
|
||||
}
|
||||
foreach ($resp['contact'] as $t) {
|
||||
$writer->startElement('domain:contact');
|
||||
$writer->writeAttribute('type', $t[0]);
|
||||
$writer->text($t[1]);
|
||||
$writer->endElement();
|
||||
}
|
||||
if (isset($resp['hostObj']) && is_array($resp['hostObj'])) {
|
||||
$writer->startElement('domain:ns');
|
||||
foreach ($resp['hostObj'] as $host) {
|
||||
$writer->writeElement('domain:hostObj', (string)$host[0]);
|
||||
}
|
||||
$writer->endElement(); // End of 'domain:ns'
|
||||
}
|
||||
if (isset($resp['return_host'])) {
|
||||
if ($resp['return_host']) {
|
||||
foreach ($resp['host'] as $h) {
|
||||
$writer->writeElement('domain:host', $h);
|
||||
}
|
||||
}
|
||||
}
|
||||
$writer->writeElement('domain:clID', $resp['clID']);
|
||||
if (isset($resp['crID'])) {
|
||||
$writer->writeElement('domain:crID', $resp['crID']);
|
||||
}
|
||||
if (isset($resp['crDate'])) {
|
||||
$writer->writeElement('domain:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||
}
|
||||
if (isset($resp['exDate'])) {
|
||||
$writer->writeElement('domain:exDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['exDate'])));
|
||||
}
|
||||
if (isset($resp['upID'])) {
|
||||
$writer->writeElement('domain:upID', $resp['upID']);
|
||||
}
|
||||
if (isset($resp['upDate'])) {
|
||||
$writer->writeElement('domain:upDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['upDate'])));
|
||||
}
|
||||
if (isset($resp['trDate'])) {
|
||||
$writer->writeElement('domain:trDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['trDate'])));
|
||||
}
|
||||
if ($resp['authInfo'] == 'valid') {
|
||||
$writer->startElement('domain:authInfo');
|
||||
if ($resp['authInfo_type'] == 'pw') {
|
||||
$writer->writeElement('domain:pw', $resp['authInfo_val']);
|
||||
} elseif ($resp['authInfo_type'] == 'ext') {
|
||||
$writer->writeElement('domain:ext', $resp['authInfo_val']);
|
||||
}
|
||||
$writer->endElement(); // End of 'domain:authInfo'
|
||||
}
|
||||
|
||||
$writer->endElement(); // End of 'domain:infData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
|
||||
// Handling the extension part
|
||||
// Check if the 'rgpstatus' key is set in $resp
|
||||
if (isset($resp['rgpstatus'])) {
|
||||
// Handling the extension part
|
||||
$writer->startElement('extension');
|
||||
$writer->startElement('rgp:infData');
|
||||
$writer->writeAttribute('xmlns:rgp', 'urn:ietf:params:xml:ns:rgp-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:rgp-1.0 rgp-1.0.xsd');
|
||||
$writer->startElement('rgp:rgpStatus');
|
||||
$writer->writeAttribute('s', $resp['rgpstatus']);
|
||||
$writer->endElement(); // End of 'rgp:rgpStatus'
|
||||
$writer->endElement(); // End of 'rgp:infData'
|
||||
$writer->endElement(); // End of 'extension'
|
||||
}
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _renew_domain($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('domain:renData');
|
||||
$writer->writeAttribute('xmlns:domain', 'urn:ietf:params:xml:ns:domain-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd');
|
||||
$writer->writeElement('domain:name', $resp['name']);
|
||||
$writer->writeElement('domain:exDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['exDate'])));
|
||||
$writer->endElement(); // End of 'domain:renData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _transfer_domain($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('domain:trnData');
|
||||
$writer->writeAttribute('xmlns:domain', 'urn:ietf:params:xml:ns:domain-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd');
|
||||
$writer->writeElement('domain:name', $resp['name']);
|
||||
$writer->writeElement('domain:trStatus', $resp['trStatus']);
|
||||
$writer->writeElement('domain:reID', $resp['reID']);
|
||||
$writer->writeElement('domain:reDate', $resp['reDate']);
|
||||
$writer->writeElement('domain:acID', $resp['acID']);
|
||||
$writer->writeElement('domain:acDate', $resp['acDate']);
|
||||
if (isset($resp['exDate'])) {
|
||||
$writer->writeElement('domain:exDate', $resp['exDate']);
|
||||
}
|
||||
$writer->endElement(); // End of 'domain:trnData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
|
||||
private function _check_host($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('host:chkData');
|
||||
$writer->writeAttribute('xmlns:host', 'urn:ietf:params:xml:ns:host-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:host-1.0 host-1.0.xsd');
|
||||
foreach ($resp['names'] as $n) {
|
||||
$writer->startElement('host:cd');
|
||||
$writer->startElement('host:name');
|
||||
$writer->writeAttribute('avail', $n[1]);
|
||||
$writer->text($n[0]);
|
||||
$writer->endElement();
|
||||
if (isset($n[2])) {
|
||||
$writer->writeElement('host:reason', $n[2]);
|
||||
}
|
||||
$writer->endElement(); // End of 'host:cd'
|
||||
}
|
||||
$writer->endElement(); // End of 'host:chkData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _create_host($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('host:creData');
|
||||
$writer->writeAttribute('xmlns:host', 'urn:ietf:params:xml:ns:host-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:host-1.0 host-1.0.xsd');
|
||||
$writer->writeElement('host:name', $resp['name']);
|
||||
$writer->writeElement('host:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||
$writer->endElement(); // End of 'host:creData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _info_host($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('host:infData');
|
||||
$writer->writeAttribute('xmlns:host', 'urn:ietf:params:xml:ns:host-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'urn:ietf:params:xml:ns:host-1.0 host-1.0.xsd');
|
||||
$writer->writeElement('host:name', $resp['name']);
|
||||
$writer->writeElement('host:roid', $resp['roid']);
|
||||
if (isset($resp['status']) && count($resp['status'])) {
|
||||
foreach ($resp['status'] as $s) {
|
||||
if (isset($s[1]) && isset($s[2])) {
|
||||
$writer->startElement('host:status');
|
||||
$writer->writeAttribute('s', $s[0]);
|
||||
$writer->writeAttribute('lang', $s[1]);
|
||||
$writer->text($s[2]);
|
||||
$writer->endElement();
|
||||
} else {
|
||||
$writer->startElement('host:status');
|
||||
$writer->writeAttribute('s', $s[0]);
|
||||
$writer->endElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($resp['addr']) && !empty($resp['addr'])) {
|
||||
foreach ($resp['addr'] as $a) {
|
||||
$writer->startElement('host:addr');
|
||||
$writer->writeAttribute('ip', 'v' . $a[0]);
|
||||
$writer->text($a[1]);
|
||||
$writer->endElement();
|
||||
}
|
||||
}
|
||||
$writer->writeElement('host:clID', $resp['clID']);
|
||||
$writer->writeElement('host:crID', $resp['crID']);
|
||||
$writer->writeElement('host:crDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['crDate'])));
|
||||
if (isset($resp['upID'])) {
|
||||
$writer->writeElement('host:upID', $resp['upID']);
|
||||
}
|
||||
if (isset($resp['upDate'])) {
|
||||
$writer->writeElement('host:upDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['upDate'])));
|
||||
}
|
||||
if (isset($resp['trDate'])) {
|
||||
$writer->writeElement('host:trDate', gmdate('Y-m-d\TH:i:s\.0\Z', strtotime($resp['trDate'])));
|
||||
}
|
||||
$writer->endElement(); // End of 'host:infData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
private function _info_funds($writer, $resp) {
|
||||
$this->_preamble($writer, $resp);
|
||||
|
||||
if ($this->epp_success($resp['resultCode'])) {
|
||||
$writer->startElement('resData');
|
||||
$writer->startElement('funds:infData');
|
||||
$writer->writeAttribute('xmlns:funds', 'https://namingo.org/epp/funds-1.0');
|
||||
$writer->writeAttribute('xsi:schemaLocation', 'https://namingo.org/epp/funds-1.0 funds-1.0.xsd');
|
||||
|
||||
$writer->writeElement('funds:balance', $resp['funds']);
|
||||
$writer->writeElement('funds:currency', $resp['currency']);
|
||||
$writer->writeElement('funds:availableCredit', $resp['availableCredit']);
|
||||
$writer->writeElement('funds:creditLimit', $resp['creditLimit']);
|
||||
|
||||
$writer->startElement('funds:creditThreshold');
|
||||
if ($resp['thresholdType'] === 'fixed') {
|
||||
$writer->writeElement('funds:fixed', $resp['creditThreshold']);
|
||||
} elseif ($resp['thresholdType'] === 'percent') {
|
||||
$writer->writeElement('funds:percent', $resp['creditThreshold']);
|
||||
}
|
||||
$writer->endElement(); // End of 'funds:creditThreshold'
|
||||
|
||||
$writer->endElement(); // End of 'funds:infData'
|
||||
$writer->endElement(); // End of 'resData'
|
||||
}
|
||||
|
||||
$this->_postamble($writer, $resp);
|
||||
}
|
||||
|
||||
}
|
148
epp/src/epp-check.php
Normal file
148
epp/src/epp-check.php
Normal file
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
function processContactCheck($conn, $db, $xml) {
|
||||
$contactIDs = $xml->command->check->children('urn:ietf:params:xml:ns:contact-1.0')->check->{'id'};
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
$results = [];
|
||||
foreach ($contactIDs as $contactID) {
|
||||
$contactID = (string)$contactID;
|
||||
|
||||
$stmt = $db->prepare("SELECT 1 FROM contact WHERE identifier = :id");
|
||||
$stmt->execute(['id' => $contactID]);
|
||||
|
||||
$results[$contactID] = $stmt->fetch() ? '0' : '1'; // 0 if exists, 1 if not
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
foreach ($results as $id => $available) {
|
||||
$invalid_identifier = validate_identifier($contactID);
|
||||
$entry = [$id];
|
||||
|
||||
// Check if the contact ID is Invalid
|
||||
if ($invalid_identifier) {
|
||||
$entry[] = 0; // Set status to unavailable
|
||||
$entry[] = $invalid_identifier;
|
||||
} else {
|
||||
$entry[] = $available;
|
||||
|
||||
// Check if the contact is unavailable
|
||||
if (!$available) {
|
||||
$entry[] = "In use";
|
||||
}
|
||||
}
|
||||
|
||||
$ids[] = $entry;
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'check_contact',
|
||||
'resultCode' => 1000,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully',
|
||||
'ids' => $ids,
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
||||
|
||||
function processHostCheck($conn, $db, $xml) {
|
||||
$hosts = $xml->command->check->children('urn:ietf:params:xml:ns:host-1.0')->check->{'name'};
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
$results = [];
|
||||
foreach ($hosts as $host) {
|
||||
$host = (string)$host;
|
||||
|
||||
// Validation for host name
|
||||
if (!preg_match('/^([A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9]){0,1}\\.){1,125}[A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9])$/i', $host) && strlen($host) > 254) {
|
||||
sendEppError($conn, 2005, 'Invalid host name');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT 1 FROM host WHERE name = :name");
|
||||
$stmt->execute(['name' => $host]);
|
||||
|
||||
$results[$host] = $stmt->fetch() ? '0' : '1'; // 0 if exists, 1 if not
|
||||
}
|
||||
|
||||
$names = [];
|
||||
foreach ($results as $id => $available) {
|
||||
$entry = [$id, $available];
|
||||
// Check if the host is unavailable
|
||||
if (!$available) {
|
||||
$entry[] = "In use";
|
||||
}
|
||||
$names[] = $entry;
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'check_host',
|
||||
'resultCode' => 1000,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully',
|
||||
'names' => $names,
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
||||
|
||||
function processDomainCheck($conn, $db, $xml) {
|
||||
$domains = $xml->command->check->children('urn:ietf:params:xml:ns:domain-1.0')->check->name;
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
$names = [];
|
||||
foreach ($domains as $domain) {
|
||||
$domainName = (string) $domain;
|
||||
$stmt = $db->prepare("SELECT name FROM domain WHERE name = :domainName");
|
||||
$stmt->bindParam(':domainName', $domainName, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$availability = $stmt->fetchColumn();
|
||||
|
||||
// Convert the DB result into a boolean '0' or '1'
|
||||
$availability = $availability ? '0' : '1';
|
||||
|
||||
$invalid_label = validate_label($domainName, $db);
|
||||
|
||||
// Initialize a new domain entry with the domain name and its availability
|
||||
$domainEntry = [$domainName];
|
||||
|
||||
// Check if the domain is Invalid
|
||||
if ($invalid_label) {
|
||||
$domainEntry[] = 0; // Set status to unavailable
|
||||
$domainEntry[] = $invalid_label;
|
||||
} else {
|
||||
$domainEntry[] = $availability;
|
||||
|
||||
// Check if the domain is unavailable
|
||||
if ($availability === '0') {
|
||||
$domainEntry[] = 'In use';
|
||||
}
|
||||
}
|
||||
|
||||
// Append this domain entry to names
|
||||
$names[] = $domainEntry;
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'check_domain',
|
||||
'resultCode' => 1000,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully',
|
||||
'names' => $names,
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
1207
epp/src/epp-create.php
Normal file
1207
epp/src/epp-create.php
Normal file
File diff suppressed because it is too large
Load diff
388
epp/src/epp-delete.php
Normal file
388
epp/src/epp-delete.php
Normal file
|
@ -0,0 +1,388 @@
|
|||
<?php
|
||||
|
||||
function processContactDelete($conn, $db, $xml, $clid, $database_type) {
|
||||
$contactID = (string) $xml->command->delete->children('urn:ietf:params:xml:ns:contact-1.0')->delete->{'id'};
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
if (!$contactID) {
|
||||
sendEppError($conn, 2003, 'Required parameter missing');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id, clid FROM contact WHERE identifier = ? LIMIT 1");
|
||||
$stmt->execute([$contactID]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$contact_id = $row['id'] ?? null;
|
||||
$registrar_id_contact = $row['clid'] ?? null;
|
||||
|
||||
if (!$contact_id) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM registrar WHERE clid = :clid LIMIT 1");
|
||||
$stmt->bindParam(':clid', $clid, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$clid = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$clid = $clid['id'];
|
||||
|
||||
if ($clid !== $registrar_id_contact) {
|
||||
sendEppError($conn, 2201, 'Authorization error');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM domain WHERE registrant = ? LIMIT 1");
|
||||
$stmt->execute([$contact_id]);
|
||||
$registrantExists = $stmt->fetchColumn();
|
||||
|
||||
if ($registrantExists) {
|
||||
sendEppError($conn, 2305, 'Object association prohibits operation');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM domain_contact_map WHERE contact_id = ? LIMIT 1");
|
||||
$stmt->execute([$contact_id]);
|
||||
$contactInUse = $stmt->fetchColumn();
|
||||
|
||||
if ($contactInUse) {
|
||||
sendEppError($conn, 2305, 'Object association prohibits operation');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT status FROM contact_status WHERE contact_id = ?");
|
||||
$stmt->execute([$contact_id]);
|
||||
|
||||
while ($status = $stmt->fetchColumn()) {
|
||||
if (preg_match('/.*(UpdateProhibited|DeleteProhibited)$/', $status) || preg_match('/^pending/', $status)) {
|
||||
sendEppError($conn, 2304, 'Object status prohibits operation');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete associated records
|
||||
$db->prepare("DELETE FROM contact_postalInfo WHERE contact_id = ?")->execute([$contact_id]);
|
||||
$db->prepare("DELETE FROM contact_authInfo WHERE contact_id = ?")->execute([$contact_id]);
|
||||
$db->prepare("DELETE FROM contact_status WHERE contact_id = ?")->execute([$contact_id]);
|
||||
|
||||
$stmt = $db->prepare("DELETE FROM contact WHERE id = ?");
|
||||
$stmt->execute([$contact_id]);
|
||||
|
||||
if ($stmt->errorCode() != '00000') {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'delete_contact',
|
||||
'resultCode' => 1000,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
||||
|
||||
function processHostDelete($conn, $db, $xml, $clid, $database_type) {
|
||||
$hostName = $xml->command->delete->children('urn:ietf:params:xml:ns:host-1.0')->delete->name;
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
if (!$hostName) {
|
||||
sendEppError($conn, 2003, 'Required parameter missing');
|
||||
return;
|
||||
}
|
||||
|
||||
$query = "SELECT id, clid FROM host WHERE name = :name LIMIT 1";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute([':name' => $hostName]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$host_id = $result['id'] ?? null;
|
||||
$registrar_id_host = $result['clid'] ?? null;
|
||||
|
||||
if (!$host_id) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM registrar WHERE clid = :clid LIMIT 1");
|
||||
$stmt->bindParam(':clid', $clid, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$clid = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$clid = $clid['id'];
|
||||
|
||||
if ($clid !== $registrar_id_host) {
|
||||
sendEppError($conn, 2201, 'Authorization error');
|
||||
return;
|
||||
}
|
||||
|
||||
$query = "SELECT domain_id FROM domain_host_map WHERE host_id = :host_id LIMIT 1";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute([':host_id' => $host_id]);
|
||||
$nameserver_inuse = $stmt->fetchColumn();
|
||||
|
||||
if ($nameserver_inuse) {
|
||||
sendEppError($conn, 2305, 'Object association prohibits operation');
|
||||
return;
|
||||
}
|
||||
|
||||
$query = "DELETE FROM host_addr WHERE host_id = :host_id";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute([':host_id' => $host_id]);
|
||||
|
||||
$query = "DELETE FROM host_status WHERE host_id = :host_id";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute([':host_id' => $host_id]);
|
||||
|
||||
$query = "DELETE FROM host WHERE id = :host_id";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute([':host_id' => $host_id]);
|
||||
|
||||
if ($stmt->errorCode() != '00000') {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'delete_host',
|
||||
'resultCode' => 1000,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
||||
|
||||
function processDomainDelete($conn, $db, $xml, $clid, $database_type) {
|
||||
$domainName = $xml->command->delete->children('urn:ietf:params:xml:ns:domain-1.0')->delete->name;
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
if (!$domainName) {
|
||||
sendEppError($conn, 2003, 'Required parameter missing');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id, tldid, registrant, crdate, exdate, `update`, clid, crid, upid, trdate, trstatus, reid, redate, acid, acdate, rgpstatus, addPeriod, autoRenewPeriod, renewPeriod, renewedDate, transferPeriod FROM domain WHERE name = :name LIMIT 1");
|
||||
$stmt->execute([':name' => $domainName]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$result) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
$domain_id = $result['id'];
|
||||
$tldid = $result['tldid'];
|
||||
$registrant = $result['registrant'];
|
||||
$crdate = $result['crdate'];
|
||||
$exdate = $result['exdate'];
|
||||
$update = $result['update'];
|
||||
$registrar_id_domain = $result['clid'];
|
||||
$crid = $result['crid'];
|
||||
$upid = $result['upid'];
|
||||
$trdate = $result['trdate'];
|
||||
$trstatus = $result['trstatus'];
|
||||
$reid = $result['reid'];
|
||||
$redate = $result['redate'];
|
||||
$acid = $result['acid'];
|
||||
$acdate = $result['acdate'];
|
||||
$rgpstatus = $result['rgpstatus'];
|
||||
$addPeriod = $result['addPeriod'];
|
||||
$autoRenewPeriod = $result['autoRenewPeriod'];
|
||||
$renewPeriod = $result['renewPeriod'];
|
||||
$renewedDate = $result['renewedDate'];
|
||||
$transferPeriod = $result['transferPeriod'];
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM registrar WHERE clid = :clid LIMIT 1");
|
||||
$stmt->bindParam(':clid', $clid, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$clid = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$clid = $clid['id'];
|
||||
|
||||
if ($clid != $registrar_id_domain) {
|
||||
sendEppError($conn, 2201, 'Authorization error');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT status FROM domain_status WHERE domain_id = :domain_id");
|
||||
$stmt->execute([':domain_id' => $domain_id]);
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$status = $row['status'];
|
||||
if (preg_match('/.*(UpdateProhibited|DeleteProhibited)$/', $status) || preg_match('/^pending/', $status)) {
|
||||
sendEppError($conn, 2304, 'Object status prohibits operation');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$grace_period = 30;
|
||||
|
||||
// DELETE FROM `domain_status`
|
||||
$stmt = $db->prepare("DELETE FROM domain_status WHERE domain_id = ?");
|
||||
$stmt->execute([$domain_id]);
|
||||
|
||||
// UPDATE domain
|
||||
$stmt = $db->prepare("UPDATE domain SET rgpstatus = 'redemptionPeriod', delTime = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL ? DAY) WHERE id = ?");
|
||||
$stmt->execute([$grace_period, $domain_id]);
|
||||
|
||||
// INSERT INTO domain_status
|
||||
$stmt = $db->prepare("INSERT INTO domain_status (domain_id, status) VALUES(?, 'pendingDelete')");
|
||||
$stmt->execute([$domain_id]);
|
||||
|
||||
if ($rgpstatus) {
|
||||
if ($rgpstatus === 'addPeriod') {
|
||||
$stmt = $db->prepare("SELECT id FROM domain WHERE id = ? AND (CURRENT_TIMESTAMP < DATE_ADD(crdate, INTERVAL 5 DAY)) LIMIT 1");
|
||||
$stmt->execute([$domain_id]);
|
||||
$addPeriod_id = $stmt->fetchColumn();
|
||||
|
||||
if ($addPeriod_id) {
|
||||
$stmt = $db->prepare("SELECT m$addPeriod FROM domain_price WHERE tldid = ? AND command = 'create' LIMIT 1");
|
||||
$stmt->execute([$tldid]);
|
||||
$price = $stmt->fetchColumn();
|
||||
|
||||
if (!isset($price)) {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update registrar
|
||||
$stmt = $db->prepare("UPDATE registrar SET accountBalance = (accountBalance + ?) WHERE id = ?");
|
||||
$stmt->execute([$price, $registrar_id]);
|
||||
|
||||
// Insert into payment_history
|
||||
$description = "domain name is deleted by the registrar during grace addPeriod, the registry provides a credit for the cost of the registration domain $name for period $addPeriod MONTH";
|
||||
$stmt = $db->prepare("INSERT INTO payment_history (registrar_id, date, description, amount) VALUES(?, CURRENT_TIMESTAMP, ?, ?)");
|
||||
$stmt->execute([$registrar_id, $description, $price]);
|
||||
|
||||
// Fetch host ids
|
||||
$stmt = $db->prepare("SELECT id FROM host WHERE domain_id = ?");
|
||||
$stmt->execute([$domain_id]);
|
||||
|
||||
while ($host_id = $stmt->fetchColumn()) {
|
||||
$db->exec("DELETE FROM host_addr WHERE host_id = $host_id");
|
||||
$db->exec("DELETE FROM host_status WHERE host_id = $host_id");
|
||||
$db->exec("DELETE FROM domain_host_map WHERE host_id = $host_id");
|
||||
}
|
||||
|
||||
// Delete domain related records
|
||||
$db->exec("DELETE FROM domain_contact_map WHERE domain_id = $domain_id");
|
||||
$db->exec("DELETE FROM domain_host_map WHERE domain_id = $domain_id");
|
||||
$db->exec("DELETE FROM domain_authInfo WHERE domain_id = $domain_id");
|
||||
$db->exec("DELETE FROM domain_status WHERE domain_id = $domain_id");
|
||||
$db->exec("DELETE FROM host WHERE domain_id = $domain_id");
|
||||
|
||||
$stmt = $db->prepare("DELETE FROM domain WHERE id = ?");
|
||||
$stmt->execute([$domain_id]);
|
||||
|
||||
if ($stmt->errorCode() != "00000") {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle statistics
|
||||
$curdate_id = $db->query("SELECT id FROM statistics WHERE date = CURDATE()")->fetchColumn();
|
||||
|
||||
if (!$curdate_id) {
|
||||
$db->exec("INSERT IGNORE INTO statistics (date) VALUES(CURDATE())");
|
||||
}
|
||||
|
||||
$db->exec("UPDATE statistics SET deleted_domains = deleted_domains + 1 WHERE date = CURDATE()");
|
||||
}
|
||||
} elseif ($rgpstatus === 'autoRenewPeriod') {
|
||||
$stmt = $db->prepare("SELECT id FROM domain WHERE id = ? AND (CURRENT_TIMESTAMP < DATE_ADD(renewedDate, INTERVAL 45 DAY)) LIMIT 1");
|
||||
$stmt->execute([$domain_id]);
|
||||
$autoRenewPeriod_id = $stmt->fetchColumn();
|
||||
|
||||
if ($autoRenewPeriod_id) {
|
||||
$stmt = $db->prepare("SELECT m$autoRenewPeriod FROM domain_price WHERE tldid = ? AND command = 'renew' LIMIT 1");
|
||||
$stmt->execute([$tldid]);
|
||||
$price = $stmt->fetchColumn();
|
||||
|
||||
if (!isset($price)) {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update registrar
|
||||
$stmt = $db->prepare("UPDATE registrar SET accountBalance = (accountBalance + ?) WHERE id = ?");
|
||||
$stmt->execute([$price, $registrar_id]);
|
||||
|
||||
// Insert into payment_history
|
||||
$description = "domain name is deleted by the registrar during grace autoRenewPeriod, the registry provides a credit for the cost of the renewal domain $name for period $autoRenewPeriod MONTH";
|
||||
$stmt = $db->prepare("INSERT INTO payment_history (registrar_id, date, description, amount) VALUES(?, CURRENT_TIMESTAMP, ?, ?)");
|
||||
$stmt->execute([$registrar_id, $description, $price]);
|
||||
}
|
||||
} elseif ($rgpstatus === 'renewPeriod') {
|
||||
$stmt = $db->prepare("SELECT id FROM domain WHERE id = ? AND (CURRENT_TIMESTAMP < DATE_ADD(renewedDate, INTERVAL 5 DAY)) LIMIT 1");
|
||||
$stmt->execute([$domain_id]);
|
||||
$renewPeriod_id = $stmt->fetchColumn();
|
||||
|
||||
if ($renewPeriod_id) {
|
||||
$stmt = $db->prepare("SELECT m$renewPeriod FROM domain_price WHERE tldid = ? AND command = 'renew' LIMIT 1");
|
||||
$stmt->execute([$tldid]);
|
||||
$price = $stmt->fetchColumn();
|
||||
|
||||
if (!isset($price)) {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update registrar
|
||||
$stmt = $db->prepare("UPDATE registrar SET accountBalance = (accountBalance + ?) WHERE id = ?");
|
||||
$stmt->execute([$price, $registrar_id]);
|
||||
|
||||
// Insert into payment_history
|
||||
$description = "domain name is deleted by the registrar during grace renewPeriod, the registry provides a credit for the cost of the renewal domain $name for period $renewPeriod MONTH";
|
||||
$stmt = $db->prepare("INSERT INTO payment_history (registrar_id, date, description, amount) VALUES(?, CURRENT_TIMESTAMP, ?, ?)");
|
||||
$stmt->execute([$registrar_id, $description, $price]);
|
||||
}
|
||||
} elseif ($rgpstatus === 'transferPeriod') {
|
||||
$stmt = $db->prepare("SELECT id FROM domain WHERE id = ? AND (CURRENT_TIMESTAMP < DATE_ADD(trdate, INTERVAL 5 DAY)) LIMIT 1");
|
||||
$stmt->execute([$domain_id]);
|
||||
$transferPeriod_id = $stmt->fetchColumn();
|
||||
|
||||
if ($transferPeriod_id) {
|
||||
// Return money if a transfer was also a renew
|
||||
if ($transferPeriod > 0) {
|
||||
$stmt = $db->prepare("SELECT m$transferPeriod FROM domain_price WHERE tldid = ? AND command = 'renew' LIMIT 1");
|
||||
$stmt->execute([$tldid]);
|
||||
$price = $stmt->fetchColumn();
|
||||
|
||||
if (!isset($price)) {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update registrar
|
||||
$stmt = $db->prepare("UPDATE registrar SET accountBalance = (accountBalance + ?) WHERE id = ?");
|
||||
$stmt->execute([$price, $registrar_id]);
|
||||
|
||||
// Insert into payment_history
|
||||
$description = "domain name is deleted by the registrar during grace transferPeriod, the registry provides a credit for the cost of the transfer domain $name for period $transferPeriod MONTH";
|
||||
$stmt = $db->prepare("INSERT INTO payment_history (registrar_id, date, description, amount) VALUES(?, CURRENT_TIMESTAMP, ?, ?)");
|
||||
$stmt->execute([$registrar_id, $description, $price]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'delete_domain',
|
||||
'resultCode' => 1001,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully; action pending',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
300
epp/src/epp-info.php
Normal file
300
epp/src/epp-info.php
Normal file
|
@ -0,0 +1,300 @@
|
|||
<?php
|
||||
|
||||
function processContactInfo($conn, $db, $xml) {
|
||||
$contactID = (string) $xml->command->info->children('urn:ietf:params:xml:ns:contact-1.0')->info->{'id'};
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
// Validation for contact ID
|
||||
$invalid_identifier = validate_identifier($contactID);
|
||||
if ($invalid_identifier) {
|
||||
sendEppError($conn, 2005, 'Invalid contact ID');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("SELECT * FROM contact WHERE identifier = :id");
|
||||
$stmt->execute(['id' => $contactID]);
|
||||
|
||||
$contact = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$contact) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch authInfo
|
||||
$stmt = $db->prepare("SELECT * FROM contact_authInfo WHERE contact_id = :id");
|
||||
$stmt->execute(['id' => $contact['id']]);
|
||||
$authInfo = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// Fetch status
|
||||
$stmt = $db->prepare("SELECT * FROM contact_status WHERE contact_id = :id");
|
||||
$stmt->execute(['id' => $contact['id']]);
|
||||
$statuses = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$statusArray = [];
|
||||
foreach($statuses as $status) {
|
||||
$statusArray[] = [$status['status']];
|
||||
}
|
||||
|
||||
// Fetch postal_info
|
||||
$stmt = $db->prepare("SELECT * FROM contact_postalInfo WHERE contact_id = :id");
|
||||
$stmt->execute(['id' => $contact['id']]);
|
||||
$postals = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$postalArray = [];
|
||||
foreach ($postals as $postal) {
|
||||
$postalType = $postal['type']; // 'int' or 'loc'
|
||||
$postalArray[$postalType] = [
|
||||
'name' => $postal['name'],
|
||||
'org' => $postal['org'],
|
||||
'street' => [$postal['street1'], $postal['street2'], $postal['street3']],
|
||||
'city' => $postal['city'],
|
||||
'sp' => $postal['sp'],
|
||||
'pc' => $postal['pc'],
|
||||
'cc' => $postal['cc']
|
||||
];
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'info_contact',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
'resultCode' => 1000,
|
||||
'msg' => 'Command completed successfully',
|
||||
'id' => $contact['id'],
|
||||
'roid' => 'C_'.$contact['identifier'],
|
||||
'status' => $statusArray,
|
||||
'postal' => $postalArray,
|
||||
'voice' => $contact['voice'],
|
||||
'fax' => $contact['fax'],
|
||||
'email' => $contact['email'],
|
||||
'clID' => getRegistrarClid($db, $contact['clid']),
|
||||
'crID' => getRegistrarClid($db, $contact['crid']),
|
||||
'crDate' => $contact['crdate'],
|
||||
'upID' => getRegistrarClid($db, $contact['upid']),
|
||||
'upDate' => $contact['update'],
|
||||
'authInfo' => 'valid',
|
||||
'authInfo_type' => $authInfo['authtype'],
|
||||
'authInfo_val' => $authInfo['authinfo']
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
sendEppError($conn, 2400, 'Database error');
|
||||
}
|
||||
}
|
||||
|
||||
function processHostInfo($conn, $db, $xml) {
|
||||
$hostName = $xml->command->info->children('urn:ietf:params:xml:ns:host-1.0')->info->name;
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
// Validation for host name
|
||||
if (!preg_match('/^([A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9]){0,1}\\.){1,125}[A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9])$/i', $hostName) && strlen($hostName) > 254) {
|
||||
sendEppError($conn, 2005, 'Invalid host name');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("SELECT * FROM host WHERE name = :name");
|
||||
$stmt->execute(['name' => $hostName]);
|
||||
|
||||
$host = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$host) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch addresses
|
||||
$stmt3 = $db->prepare("SELECT `addr`, `ip` FROM `host_addr` WHERE `host_id` = :id");
|
||||
$stmt3->execute(['id' => $host['id']]);
|
||||
$addresses = $stmt3->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$addrArray = [];
|
||||
foreach($addresses as $addr) {
|
||||
$addrArray[] = [$addr['ip'] === 'v4' ? 4 : 6, $addr['addr']];
|
||||
}
|
||||
|
||||
// Fetch status
|
||||
$stmt = $db->prepare("SELECT * FROM host_status WHERE host_id = :id");
|
||||
$stmt->execute(['id' => $host['id']]);
|
||||
$statuses = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$statusArray = [];
|
||||
foreach($statuses as $status) {
|
||||
$statusArray[] = [$status['status']];
|
||||
}
|
||||
|
||||
// Check for 'linked' status
|
||||
$stmt2 = $db->prepare("SELECT domain_id FROM domain_host_map WHERE host_id = :id LIMIT 1");
|
||||
$stmt2->execute(['id' => $host['id']]);
|
||||
$domainData = $stmt2->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($domainData) {
|
||||
$statusArray[] = ['linked'];
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'info_host',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
'resultCode' => 1000,
|
||||
'msg' => 'Command completed successfully',
|
||||
'name' => $host['name'],
|
||||
'roid' => 'H_'.$host['id'],
|
||||
'status' => $statusArray,
|
||||
'addr' => $addrArray,
|
||||
'clID' => getRegistrarClid($db, $host['clid']),
|
||||
'crID' => getRegistrarClid($db, $host['crid']),
|
||||
'crDate' => $host['crdate'],
|
||||
'upID' => getRegistrarClid($db, $host['upid']),
|
||||
'upDate' => $host['update'],
|
||||
'trDate' => $host['trdate']
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
} catch (PDOException $e) {
|
||||
sendEppError($conn, 2400, 'Database error');
|
||||
}
|
||||
}
|
||||
|
||||
function processDomainInfo($conn, $db, $xml) {
|
||||
$domainName = $xml->command->info->children('urn:ietf:params:xml:ns:domain-1.0')->info->name;
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
// Validation for domain name
|
||||
$invalid_label = validate_label($domainName, $db);
|
||||
if ($invalid_label) {
|
||||
sendEppError($conn, 2005, 'Invalid domain name');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filter_var($domainName, FILTER_VALIDATE_DOMAIN)) {
|
||||
sendEppError($conn, 2005, 'Invalid domain name');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("SELECT * FROM domain WHERE name = :name");
|
||||
$stmt->execute(['name' => $domainName]);
|
||||
|
||||
$domain = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$domain) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch contacts
|
||||
$stmt = $db->prepare("SELECT * FROM domain_contact_map WHERE domain_id = :id");
|
||||
$stmt->execute(['id' => $domain['id']]);
|
||||
$contacts = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$transformedContacts = [];
|
||||
foreach ($contacts as $contact) {
|
||||
$transformedContacts[] = [$contact['type'], getContactIdentifier($db, $contact['contact_id'])];
|
||||
}
|
||||
|
||||
// Fetch hosts
|
||||
$stmt = $db->prepare("SELECT * FROM domain_host_map WHERE domain_id = :id");
|
||||
$stmt->execute(['id' => $domain['id']]);
|
||||
$hosts = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$transformedHosts = [];
|
||||
foreach ($hosts as $host) {
|
||||
$transformedHosts[] = [getHost($db, $host['host_id'])];
|
||||
}
|
||||
|
||||
// Fetch authInfo
|
||||
$stmt = $db->prepare("SELECT * FROM domain_authInfo WHERE domain_id = :id");
|
||||
$stmt->execute(['id' => $domain['id']]);
|
||||
$authInfo = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// Fetch status
|
||||
$stmt = $db->prepare("SELECT * FROM domain_status WHERE domain_id = :id");
|
||||
$stmt->execute(['id' => $domain['id']]);
|
||||
$statuses = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$statusArray = [];
|
||||
foreach($statuses as $status) {
|
||||
$statusArray[] = [$status['status']];
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'info_domain',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
'resultCode' => 1000,
|
||||
'msg' => 'Command completed successfully',
|
||||
'name' => $domain['name'],
|
||||
'roid' => 'D_'.$domain['id'],
|
||||
'status' => $statusArray,
|
||||
'registrant' => $domain['registrant'],
|
||||
'contact' => $transformedContacts,
|
||||
'hostObj' => $transformedHosts,
|
||||
'clID' => getRegistrarClid($db, $domain['clid']),
|
||||
'crID' => getRegistrarClid($db, $domain['crid']),
|
||||
'crDate' => $domain['crdate'],
|
||||
'upID' => getRegistrarClid($db, $domain['upid']),
|
||||
'upDate' => $domain['update'],
|
||||
'exDate' => $domain['exdate'],
|
||||
'trDate' => $domain['trdate'],
|
||||
'authInfo' => 'valid',
|
||||
'authInfo_type' => $authInfo['authtype'],
|
||||
'authInfo_val' => $authInfo['authinfo']
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
} catch (PDOException $e) {
|
||||
sendEppError($conn, 2400, 'Database error');
|
||||
}
|
||||
}
|
||||
|
||||
function processFundsInfo($conn, $db, $xml, $clid) {
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("SELECT accountBalance, creditLimit, creditThreshold, thresholdType, currency FROM registrar WHERE clid = :id");
|
||||
$stmt->execute(['id' => $clid]);
|
||||
|
||||
$funds = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$creditBalance = ($funds['accountBalance'] < 0) ? -$funds['accountBalance'] : 0;
|
||||
$availableCredit = $funds['creditLimit'] - $creditBalance;
|
||||
$availableCredit = number_format($availableCredit, 2, '.', '');
|
||||
|
||||
if (!$funds) {
|
||||
sendEppError($conn, 2303, 'Registrar does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
$response = [
|
||||
'command' => 'info_funds',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
'resultCode' => 1000,
|
||||
'msg' => 'Command completed successfully',
|
||||
'funds' => $funds['accountBalance'],
|
||||
'currency' => $funds['currency'],
|
||||
'availableCredit' => $availableCredit,
|
||||
'creditLimit' => $funds['creditLimit'],
|
||||
'creditThreshold' => $funds['creditThreshold'],
|
||||
'thresholdType' => $funds['thresholdType']
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
sendEppError($conn, 2400, 'Database error');
|
||||
}
|
||||
}
|
94
epp/src/epp-poll.php
Normal file
94
epp/src/epp-poll.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
function processPoll($conn, $db, $xml, $clid) {
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
$node = $xml->command->poll;
|
||||
$op = (string) $node['op'];
|
||||
|
||||
if ($op === 'ack') {
|
||||
$id = (string)$node['msgID'];
|
||||
$stmt = $db->prepare("SELECT id FROM poll WHERE registrar_id = :registrar_id AND id = :id LIMIT 1");
|
||||
$stmt->execute([':registrar_id' => $clid, ':id' => $id]);
|
||||
$ack_id = $stmt->fetchColumn();
|
||||
|
||||
if (!$ack_id) {
|
||||
$response['resultCode'] = 2303; // Object does not exist
|
||||
} else {
|
||||
$stmt = $db->prepare("DELETE FROM poll WHERE registrar_id = :registrar_id AND id = :id");
|
||||
$stmt->execute([':registrar_id' => $clid, ':id' => $id]);
|
||||
$response['resultCode'] = 1000;
|
||||
}
|
||||
} else {
|
||||
$stmt = $db->prepare("SELECT id, qdate, msg, msg_type, obj_name_or_id, obj_trStatus, obj_reID, obj_reDate, obj_acID, obj_acDate, obj_exDate, registrarName, creditLimit, creditThreshold, creditThresholdType, availableCredit FROM poll WHERE registrar_id = :registrar_id ORDER BY id ASC LIMIT 1");
|
||||
$stmt->execute([':registrar_id' => $clid]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$id = $result['id'] ?? null;
|
||||
$response['resultCode'] = $id ? 1301 : 1300;
|
||||
}
|
||||
|
||||
if ((int) $response['resultCode'] === 1300) {
|
||||
$response = [
|
||||
'command' => 'poll',
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
'resultCode' => $response['resultCode'],
|
||||
'msg' => 'Command completed successfully; no messages',
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT COUNT(id) AS counter FROM poll WHERE registrar_id = :registrar_id");
|
||||
$stmt->execute([':registrar_id' => $clid]);
|
||||
$counter = $stmt->fetchColumn();
|
||||
|
||||
$response = [];
|
||||
$response['command'] = 'poll';
|
||||
$response['count'] = $counter;
|
||||
$response['id'] = $id;
|
||||
$response['msg'] = $result['msg'] ?? null;
|
||||
$response['poll_msg_type'] = $result['msg_type'] ?? null;
|
||||
$response['lang'] = 'en-US';
|
||||
$qdate = str_replace(' ', 'T', $result['qdate'] ?? '') . '.0Z';
|
||||
$response['qDate'] = $qdate;
|
||||
|
||||
if ($poll_msg_type === 'lowBalance') {
|
||||
$response['registrarName'] = $registrarName;
|
||||
$response['creditLimit'] = $creditLimit;
|
||||
$response['creditThreshold'] = $creditThreshold;
|
||||
$response['creditThresholdType'] = $creditThresholdType;
|
||||
$response['availableCredit'] = $availableCredit;
|
||||
} elseif ($poll_msg_type === 'domainTransfer') {
|
||||
$response['name'] = $obj_name_or_id;
|
||||
$response['obj_trStatus'] = $obj_trStatus;
|
||||
$response['obj_reID'] = $obj_reID;
|
||||
$response['obj_reDate'] = str_replace(' ', 'T', $obj_reDate) . '.0Z';
|
||||
$response['obj_acID'] = $obj_acID;
|
||||
$response['obj_acDate'] = str_replace(' ', 'T', $obj_acDate) . '.0Z';
|
||||
if ($obj_exDate) {
|
||||
$response['obj_exDate'] = str_replace(' ', 'T', $obj_exDate) . '.0Z';
|
||||
}
|
||||
$response['obj_type'] = 'domain';
|
||||
$response['obj_id'] = $obj_name_or_id;
|
||||
} elseif ($poll_msg_type === 'contactTransfer') {
|
||||
$response['identifier'] = $obj_name_or_id;
|
||||
$response['obj_trStatus'] = $obj_trStatus;
|
||||
$response['obj_reID'] = $obj_reID;
|
||||
$response['obj_reDate'] = str_replace(' ', 'T', $obj_reDate) . '.0Z';
|
||||
$response['obj_acID'] = $obj_acID;
|
||||
$response['obj_acDate'] = str_replace(' ', 'T', $obj_acDate) . '.0Z';
|
||||
$response['obj_type'] = 'contact';
|
||||
$response['obj_id'] = $obj_name_or_id;
|
||||
}
|
||||
|
||||
$response['clTRID'] = $clTRID;
|
||||
$response['svTRID'] = generateSvTRID();
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
204
epp/src/epp-renew.php
Normal file
204
epp/src/epp-renew.php
Normal file
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
function processDomainRenew($conn, $db, $xml, $clid, $database_type) {
|
||||
$domainName = (string) $xml->command->renew->children('urn:ietf:params:xml:ns:domain-1.0')->renew->name;
|
||||
$curExpDate = (string) $xml->command->renew->children('urn:ietf:params:xml:ns:domain-1.0')->renew->curExpDate;
|
||||
$periodElements = $xml->xpath("//domain:renew/domain:period");
|
||||
$periodElement = $periodElements[0];
|
||||
$period = (int) $periodElement;
|
||||
$periodUnit = (string) $periodElement['unit'];
|
||||
$clTRID = (string) $xml->command->clTRID;
|
||||
|
||||
if (!$domainName) {
|
||||
sendEppError($conn, 2003, 'Required parameter missing <domain:name>');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($period) {
|
||||
if ($period < 1 || $period > 99) {
|
||||
sendEppError($conn, 2004, "domain:period minLength value='1', maxLength value='99'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($periodUnit) {
|
||||
if (!preg_match("/^(m|y)$/", $periodUnit)) {
|
||||
sendEppError($conn, 2004, "domain:period unit m|y");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT id FROM registrar WHERE clid = :clid LIMIT 1");
|
||||
$stmt->bindParam(':clid', $clid, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$clid = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$stmt = $db->prepare("SELECT id, tldid, exdate, clid FROM domain WHERE name = :domainName LIMIT 1");
|
||||
$stmt->bindParam(':domainName', $domainName, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$domainData = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$domainData) {
|
||||
sendEppError($conn, 2303, 'Object does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($clid['id'] != $domainData['clid']) {
|
||||
sendEppError($conn, 2201, 'Authorization error');
|
||||
return;
|
||||
}
|
||||
|
||||
// The domain name must not be subject to clientRenewProhibited, serverRenewProhibited.
|
||||
$stmt = $db->prepare("SELECT status FROM domain_status WHERE domain_id = :domainId");
|
||||
$stmt->bindParam(':domainId', $domainData['id'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$status = $row['status'];
|
||||
if (preg_match('/.*(RenewProhibited)$/', $status) || preg_match('/^pending/', $status)) {
|
||||
sendEppError($conn, 2304, 'Object status prohibits operation');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$expiration_date = explode(" ", $domainData['exdate'])[0]; // remove time, keep only date
|
||||
|
||||
if ($curExpDate !== $expiration_date) {
|
||||
sendEppError($conn, 2306, 'Parameter value policy error');
|
||||
return;
|
||||
}
|
||||
|
||||
$date_add = 0;
|
||||
if ($periodUnit === 'y') {
|
||||
$date_add = ($period * 12);
|
||||
} elseif ($periodUnit === 'm') {
|
||||
$date_add = $period;
|
||||
}
|
||||
|
||||
if ($date_add > 0) {
|
||||
// The number of units available MAY be subject to limits imposed by the server.
|
||||
if (!in_array($date_add, [12, 24, 36, 48, 60, 72, 84, 96, 108, 120])) {
|
||||
sendEppError($conn, 2306, 'Parameter value policy error');
|
||||
return;
|
||||
}
|
||||
|
||||
$after_10_years = $db->query("SELECT YEAR(DATE_ADD(CURDATE(),INTERVAL 10 YEAR))")->fetchColumn();
|
||||
$stmt = $db->prepare("SELECT YEAR(DATE_ADD(:exdate, INTERVAL :date_add MONTH))");
|
||||
$stmt->bindParam(':exdate', $domainData['exdate'], PDO::PARAM_STR);
|
||||
$stmt->bindParam(':date_add', $date_add, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$after_renew = $stmt->fetchColumn();
|
||||
|
||||
// Domains can be renewed at any time, but the expire date cannot be more than 10 years in the future.
|
||||
if ($after_renew > $after_10_years) {
|
||||
sendEppError($conn, 2306, 'Parameter value policy error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check registrar account balance
|
||||
$stmt = $db->prepare("SELECT accountBalance, creditLimit FROM registrar WHERE id = :registrarId LIMIT 1");
|
||||
$stmt->bindParam(':registrarId', $clid['id'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$registrar_balance = $row['accountBalance'];
|
||||
$creditLimit = $row['creditLimit'];
|
||||
|
||||
$columnName = "m$date_add";
|
||||
$stmt = $db->prepare("SELECT $columnName FROM domain_price WHERE tldid = :tldid AND command = 'renew' LIMIT 1");
|
||||
$stmt->bindParam(':tldid', $domainData['tldid'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$price = $stmt->fetchColumn();
|
||||
|
||||
if (($registrar_balance + $creditLimit) < $price) {
|
||||
sendEppError($conn, 2104, 'Billing failure');
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT exdate FROM domain WHERE id = :domain_id LIMIT 1");
|
||||
$stmt->bindParam(':domain_id', $domainData['id'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$from = $stmt->fetchColumn();
|
||||
|
||||
$rgpstatus = 'renewPeriod';
|
||||
$stmt = $db->prepare("UPDATE domain SET exdate = DATE_ADD(exdate, INTERVAL :date_add MONTH), rgpstatus = :rgpstatus, renewPeriod = :renewPeriod, renewedDate = CURRENT_TIMESTAMP WHERE id = :domain_id");
|
||||
$stmt->bindParam(':date_add', $date_add, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':rgpstatus', $rgpstatus, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':renewPeriod', $date_add, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':domain_id', $domainData['id'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
// Error check
|
||||
$errorInfo = $stmt->errorInfo();
|
||||
if (isset($errorInfo[2])) {
|
||||
sendEppError($conn, 2400, 'Command failed');
|
||||
return;
|
||||
} else {
|
||||
// Update registrar's account balance:
|
||||
$stmt = $db->prepare("UPDATE registrar SET accountBalance = (accountBalance - :price) WHERE id = :registrar_id");
|
||||
$stmt->bindParam(':price', $price, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':registrar_id', $clid['id'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
// Insert into payment_history:
|
||||
$description = "renew domain $domainName for period $date_add MONTH";
|
||||
$negative_price = -$price;
|
||||
$stmt = $db->prepare("INSERT INTO payment_history (registrar_id, date, description, amount) VALUES (:registrar_id, CURRENT_TIMESTAMP, :description, :amount)");
|
||||
$stmt->bindParam(':registrar_id', $clid['id'], PDO::PARAM_INT);
|
||||
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':amount', $negative_price, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
// Fetch `exdate`:
|
||||
$stmt = $db->prepare("SELECT exdate FROM domain WHERE id = :domain_id LIMIT 1");
|
||||
$stmt->bindParam(':domain_id', $domainData['id'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$to = $stmt->fetchColumn();
|
||||
|
||||
// Insert into statement:
|
||||
if ($database_type === "mysql") {
|
||||
$stmt = $db->prepare("INSERT INTO statement (registrar_id, date, command, domain_name, length_in_months, `from`, `to`, amount) VALUES (?, CURRENT_TIMESTAMP, ?, ?, ?, ?, ?, ?)");
|
||||
} elseif ($database_type === "pgsql") {
|
||||
$stmt = $db->prepare('INSERT INTO statement (registrar_id, date, command, domain_name, length_in_months, "from", "to", amount) VALUES (?, CURRENT_TIMESTAMP, ?, ?, ?, ?, ?, ?)');
|
||||
} else {
|
||||
throw new Exception("Unsupported database type: $database_type");
|
||||
}
|
||||
$stmt->execute([$clid['id'], 'renew', $domainName, $date_add, $from, $to, $price]);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch exdate for the given domain name
|
||||
$stmt = $db->prepare("SELECT exdate FROM domain WHERE name = :name LIMIT 1");
|
||||
$stmt->bindParam(':name', $domainName, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$exdateUpdated = $stmt->fetchColumn();
|
||||
|
||||
// Check for an existing entry in `statistics` for the current date
|
||||
$stmt = $db->prepare("SELECT id FROM statistics WHERE date = CURDATE()");
|
||||
$stmt->execute();
|
||||
$curdate_id = $stmt->fetchColumn();
|
||||
|
||||
// If there's no entry for the current date, insert one
|
||||
if (!$curdate_id) {
|
||||
$stmt = $db->prepare("INSERT IGNORE INTO statistics (date) VALUES(CURDATE())");
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
// Update the `renewed_domains` count for the current date
|
||||
$stmt = $db->prepare("UPDATE statistics SET renewed_domains = renewed_domains + 1 WHERE date = CURDATE()");
|
||||
$stmt->execute();
|
||||
|
||||
$response = [
|
||||
'command' => 'renew_domain',
|
||||
'resultCode' => 1000,
|
||||
'lang' => 'en-US',
|
||||
'message' => 'Command completed successfully',
|
||||
'name' => $domainName,
|
||||
'exDate' => $exdateUpdated,
|
||||
'clTRID' => $clTRID,
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
204
epp/src/helpers.php
Normal file
204
epp/src/helpers.php
Normal file
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
function checkLogin($db, $clID, $pw) {
|
||||
$stmt = $db->prepare("SELECT pw FROM registrar WHERE clid = :username");
|
||||
$stmt->execute(['username' => $clID]);
|
||||
$hashedPassword = $stmt->fetchColumn();
|
||||
|
||||
return password_verify($pw, $hashedPassword);
|
||||
}
|
||||
|
||||
function sendGreeting($conn) {
|
||||
global $c;
|
||||
$currentDate = gmdate('Y-m-d\TH:i:s\Z');
|
||||
|
||||
$response = [
|
||||
'command' => 'greeting',
|
||||
'svID' => $c['epp_greeting'],
|
||||
'svDate' => $currentDate,
|
||||
'version' => '1.0',
|
||||
'lang' => 'en',
|
||||
'services' => [
|
||||
'urn:ietf:params:xml:ns:domain-1.0',
|
||||
'urn:ietf:params:xml:ns:contact-1.0',
|
||||
'urn:ietf:params:xml:ns:host-1.0'
|
||||
],
|
||||
'extensions' => [
|
||||
'https://namingo.org/epp/funds-1.0',
|
||||
'http://www.namingo.org/epp/nIdent-1.0',
|
||||
'urn:ietf:params:xml:ns:secDNS-1.1',
|
||||
'urn:ietf:params:xml:ns:rgp-1.0',
|
||||
'urn:ietf:params:xml:ns:launch-1.0',
|
||||
'urn:ietf:params:xml:ns:idn-1.0',
|
||||
'urn:ietf:params:xml:ns:epp:fee-1.0',
|
||||
'urn:ar:params:xml:ns:price-1.1'
|
||||
],
|
||||
'dcp' => [ // Data Collection Policy (optional)
|
||||
'access' => ['all'],
|
||||
'statement' => [
|
||||
'purpose' => ['admin', 'prov'],
|
||||
'recipient' => ['ours'],
|
||||
'retention' => ['stated']
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
||||
|
||||
function sendEppError($conn, $code, $msg) {
|
||||
$response = [
|
||||
'command' => 'error',
|
||||
'resultCode' => $code,
|
||||
'msg' => $msg,
|
||||
'clTRID' => '1',
|
||||
'svTRID' => generateSvTRID(),
|
||||
];
|
||||
|
||||
$epp = new EPP\EppWriter();
|
||||
$xml = $epp->epp_writer($response);
|
||||
sendEppResponse($conn, $xml);
|
||||
}
|
||||
|
||||
function sendEppResponse($conn, $response) {
|
||||
$length = strlen($response) + 4; // Total length including the 4-byte header
|
||||
$lengthData = pack('N', $length); // Pack the length into 4 bytes
|
||||
|
||||
$conn->send($lengthData . $response);
|
||||
}
|
||||
|
||||
function generateSvTRID($prefix = "Namingo") {
|
||||
// Get current timestamp
|
||||
$timestamp = time();
|
||||
|
||||
// Generate a random 5-character alphanumeric string
|
||||
$randomString = bin2hex(random_bytes(5));
|
||||
|
||||
// Combine the prefix, timestamp, and random string to form the svTRID
|
||||
$svTRID = "{$prefix}-{$timestamp}-{$randomString}";
|
||||
|
||||
return $svTRID;
|
||||
}
|
||||
|
||||
function getRegistrarClid(PDO $db, $id) {
|
||||
$stmt = $db->prepare("SELECT clid FROM registrar WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $result['clid'] ?? null; // Return the clid if found, otherwise return null
|
||||
}
|
||||
|
||||
function getContactIdentifier(PDO $db, $id) {
|
||||
$stmt = $db->prepare("SELECT identifier FROM contact WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $result['identifier'] ?? null; // Return the identifier if found, otherwise return null
|
||||
}
|
||||
|
||||
function getHost(PDO $db, $id) {
|
||||
$stmt = $db->prepare("SELECT name FROM host WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $result['name'] ?? null; // Return the name if found, otherwise return null
|
||||
}
|
||||
|
||||
function validate_identifier($identifier) {
|
||||
if (!$identifier) {
|
||||
return 'Abstract client and object identifier type minLength value=3';
|
||||
}
|
||||
|
||||
if (strlen($identifier) < 3) {
|
||||
return 'Abstract client and object identifier type minLength value=3';
|
||||
}
|
||||
|
||||
if (strlen($identifier) > 16) {
|
||||
return 'Abstract client and object identifier type maxLength value=16';
|
||||
}
|
||||
|
||||
if (preg_match('/[^A-Z0-9\-]/', $identifier)) {
|
||||
return 'The ID of the contact must contain letters (A-Z) (ASCII) hyphen (-), and digits (0-9). Registry assigns each registrar a unique prefix with which that registrar must create contact IDs.';
|
||||
}
|
||||
}
|
||||
|
||||
function validate_label($label, $pdo) {
|
||||
if (!$label) {
|
||||
return 'You must enter a domain name';
|
||||
}
|
||||
if (strlen($label) > 63) {
|
||||
return 'Total lenght of your domain must be less then 63 characters';
|
||||
}
|
||||
if (strlen($label) < 2) {
|
||||
return 'Total lenght of your domain must be greater then 2 characters';
|
||||
}
|
||||
if (preg_match("/(^-|^\.|-\.|\.-|--|\.\.|-$|\.$)/", $label)) {
|
||||
return 'Invalid domain name format, cannot begin or end with a hyphen (-)';
|
||||
}
|
||||
|
||||
// Extract TLD from the domain and prepend a dot
|
||||
$parts = explode('.', $label);
|
||||
$tld = "." . end($parts);
|
||||
|
||||
// Check if the TLD exists in the domain_tld table
|
||||
$stmtTLD = $pdo->prepare("SELECT COUNT(*) FROM domain_tld WHERE tld = :tld");
|
||||
$stmtTLD->bindParam(':tld', $tld, PDO::PARAM_STR);
|
||||
$stmtTLD->execute();
|
||||
$tldExists = $stmtTLD->fetchColumn();
|
||||
|
||||
if (!$tldExists) {
|
||||
return 'Zone is not supported';
|
||||
}
|
||||
|
||||
// Fetch the IDN regex for the given TLD
|
||||
$stmtRegex = $pdo->prepare("SELECT idn_table FROM domain_tld WHERE tld = :tld");
|
||||
$stmtRegex->bindParam(':tld', $tld, PDO::PARAM_STR);
|
||||
$stmtRegex->execute();
|
||||
$idnRegex = $stmtRegex->fetchColumn();
|
||||
|
||||
if (!$idnRegex) {
|
||||
return 'Failed to fetch domain IDN table';
|
||||
}
|
||||
|
||||
// Check for invalid characters using fetched regex
|
||||
if (!preg_match($idnRegex, $label)) {
|
||||
$server->send($fd, "Domain name invalid format");
|
||||
return 'Invalid domain name format, please review registry policy about accepted labels';
|
||||
}
|
||||
}
|
||||
|
||||
function normalize_v4_address($v4) {
|
||||
// Remove leading zeros from the first octet
|
||||
$v4 = preg_replace('/^0+(\d)/', '$1', $v4);
|
||||
|
||||
// Remove leading zeros from successive octets
|
||||
$v4 = preg_replace('/\.0+(\d)/', '.$1', $v4);
|
||||
|
||||
return $v4;
|
||||
}
|
||||
|
||||
function normalize_v6_address($v6) {
|
||||
// Upper case any alphabetics
|
||||
$v6 = strtoupper($v6);
|
||||
|
||||
// Remove leading zeros from the first word
|
||||
$v6 = preg_replace('/^0+([\dA-F])/', '$1', $v6);
|
||||
|
||||
// Remove leading zeros from successive words
|
||||
$v6 = preg_replace('/:0+([\dA-F])/', ':$1', $v6);
|
||||
|
||||
// Introduce a :: if there isn't one already
|
||||
if (strpos($v6, '::') === false) {
|
||||
$v6 = preg_replace('/:0:0:/', '::', $v6);
|
||||
}
|
||||
|
||||
// Remove initial zero word before a ::
|
||||
$v6 = preg_replace('/^0+::/', '::', $v6);
|
||||
|
||||
// Remove other zero words before a ::
|
||||
$v6 = preg_replace('/(:0)+::/', '::', $v6);
|
||||
|
||||
// Remove zero words following a ::
|
||||
$v6 = preg_replace('/:(:0)+/', ':', $v6);
|
||||
|
||||
return $v6;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue