Skip to content

Commit ae73fd9

Browse files
committed
Fixed #9
1 parent 0c3bf1e commit ae73fd9

File tree

1 file changed

+134
-102
lines changed

1 file changed

+134
-102
lines changed

epp.php

Lines changed: 134 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
<?php
22
/**
3-
* Indera EPP registrar module for FOSSBilling (https://fossbilling.org/)
3+
* EPP RFC Registrar Module for FOSSBilling (https://fossbilling.org/)
44
*
5-
* Written in 2023 by Taras Kondratyuk (https://getpinga.com)
6-
* Based on Generic EPP with DNSsec Registrar Module for WHMCS written in 2019 by Lilian Rudenco ([email protected])
7-
* Work of Lilian Rudenco is under http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
5+
* Developed in 2024 by the Namingo Team (https://namingo.org, [email protected])
6+
*
7+
* This project is based on:
8+
* - The "Generic EPP with DNSsec Registrar Module for WHMCS," originally developed in 2019 by Lilian Rudenco ([email protected])
9+
* and licensed under the Academic Free License (AFL 3.0) - http://opensource.org/licenses/afl-3.0.php
810
*
911
* @license MIT
1012
*/
13+
14+
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
15+
1116
class Registrar_Adapter_EPP extends Registrar_AdapterAbstract
1217
{
1318
public $config = array();
@@ -40,6 +45,11 @@ public function __construct($options)
4045
if(isset($options['ssl_ca'])) {
4146
$this->config['ssl_ca'] = $options['ssl_ca'];
4247
}
48+
if(isset($options['min_data_set'])) {
49+
$this->config['min_data_set'] = (bool)$options['min_data_set'];
50+
} else {
51+
$this->config['min_data_set'] = false;
52+
}
4353
if(isset($options['use_tls_12'])) {
4454
$this->config['use_tls_12'] = (bool)$options['use_tls_12'];
4555
} else {
@@ -98,11 +108,16 @@ public static function getConfig()
98108
'required' => false,
99109
),
100110
),
111+
'min_data_set' => array('radio', array(
112+
'multiOptions' => array('1'=>'Yes', '0'=>'No'),
113+
'label' => 'Enable Minimum Data Set',
114+
),
115+
),
101116
'use_tls_12' => array('radio', array(
102-
'multiOptions' => array('1'=>'Yes', '0'=>'No'),
103-
'label' => 'Use TLS 1.2 instead of 1.3',
104-
),
105-
),
117+
'multiOptions' => array('1'=>'Yes', '0'=>'No'),
118+
'label' => 'Use TLS 1.2 instead of 1.3',
119+
),
120+
),
106121
),
107122
);
108123
}
@@ -264,6 +279,7 @@ public function modifyNs(Registrar_Domain $domain)
264279
$return = array(
265280
'error' => $e->getMessage()
266281
);
282+
throw new Registrar_Exception('Error: ' . $e->getMessage());
267283
}
268284

269285
if (!empty($s)) {
@@ -479,73 +495,75 @@ public function registerDomain(Registrar_Domain $domain)
479495
}
480496

481497
if (0 == (int)$r->cd[0]->name->attributes()->avail) {
482-
throw new exception($r->cd[0]->name . ' ' . $reason);
498+
throw new Registrar_Exception($r->cd[0]->name . ' ' . $reason);
483499
}
484500

485-
// contact:create
486-
$from = $to = array();
487-
$from[] = '/{{ id }}/';
488-
$c_id = strtoupper($this->generateRandomString());
489-
$to[] = $c_id;
490-
$from[] = '/{{ name }}/';
491-
$to[] = htmlspecialchars($client->getFirstName() . ' ' . $client->getLastName());
492-
$from[] = '/{{ org }}/';
493-
$to[] = htmlspecialchars($client->getCompany());
494-
$from[] = '/{{ street1 }}/';
495-
$to[] = htmlspecialchars($client->getAddress1());
496-
$from[] = '/{{ city }}/';
497-
$to[] = htmlspecialchars($client->getCity());
498-
$from[] = '/{{ state }}/';
499-
$to[] = htmlspecialchars($client->getState());
500-
$from[] = '/{{ postcode }}/';
501-
$to[] = htmlspecialchars($client->getZip());
502-
$from[] = '/{{ country }}/';
503-
$to[] = htmlspecialchars($client->getCountry());
504-
$from[] = '/{{ phonenumber }}/';
505-
$to[] = htmlspecialchars('+'.$client->getTelCc().'.'.$client->getTel());
506-
$from[] = '/{{ email }}/';
507-
$to[] = htmlspecialchars($client->getEmail());
508-
$from[] = '/{{ authInfo }}/';
509-
$to[] = htmlspecialchars($this->generateObjectPW());
510-
$from[] = '/{{ clTRID }}/';
511-
$clTRID = str_replace('.', '', round(microtime(1), 3));
512-
$to[] = htmlspecialchars($this->config['registrarprefix'] . '-contact-create-' . $clTRID);
513-
$xml = preg_replace($from, $to, '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
514-
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
515-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
516-
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
517-
<command>
518-
<create>
519-
<contact:create
520-
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
521-
<contact:id>{{ id }}</contact:id>
522-
<contact:postalInfo type="int">
523-
<contact:name>{{ name }}</contact:name>
524-
<contact:org>{{ org }}</contact:org>
525-
<contact:addr>
526-
<contact:street>{{ street1 }}</contact:street>
527-
<contact:street></contact:street>
528-
<contact:street></contact:street>
529-
<contact:city>{{ city }}</contact:city>
530-
<contact:sp>{{ state }}</contact:sp>
531-
<contact:pc>{{ postcode }}</contact:pc>
532-
<contact:cc>{{ country }}</contact:cc>
533-
</contact:addr>
534-
</contact:postalInfo>
535-
<contact:voice>{{ phonenumber }}</contact:voice>
536-
<contact:fax></contact:fax>
537-
<contact:email>{{ email }}</contact:email>
538-
<contact:authInfo>
539-
<contact:pw>{{ authInfo }}</contact:pw>
540-
</contact:authInfo>
541-
</contact:create>
542-
</create>
543-
<clTRID>{{ clTRID }}</clTRID>
544-
</command>
545-
</epp>');
546-
$r = $this->write($xml, __FUNCTION__);
547-
$r = $r->response->resData->children('urn:ietf:params:xml:ns:contact-1.0')->creData;
548-
$contacts = $r->id;
501+
if ($this->config['min_data_set'] === false) {
502+
// contact:create
503+
$from = $to = array();
504+
$from[] = '/{{ id }}/';
505+
$c_id = strtoupper($this->generateRandomString());
506+
$to[] = $c_id;
507+
$from[] = '/{{ name }}/';
508+
$to[] = htmlspecialchars($client->getFirstName() . ' ' . $client->getLastName());
509+
$from[] = '/{{ org }}/';
510+
$to[] = htmlspecialchars($client->getCompany());
511+
$from[] = '/{{ street1 }}/';
512+
$to[] = htmlspecialchars($client->getAddress1());
513+
$from[] = '/{{ city }}/';
514+
$to[] = htmlspecialchars($client->getCity());
515+
$from[] = '/{{ state }}/';
516+
$to[] = htmlspecialchars($client->getState());
517+
$from[] = '/{{ postcode }}/';
518+
$to[] = htmlspecialchars($client->getZip());
519+
$from[] = '/{{ country }}/';
520+
$to[] = htmlspecialchars($client->getCountry());
521+
$from[] = '/{{ phonenumber }}/';
522+
$to[] = htmlspecialchars('+'.$client->getTelCc().'.'.$client->getTel());
523+
$from[] = '/{{ email }}/';
524+
$to[] = htmlspecialchars($client->getEmail());
525+
$from[] = '/{{ authInfo }}/';
526+
$to[] = htmlspecialchars($this->generateObjectPW());
527+
$from[] = '/{{ clTRID }}/';
528+
$clTRID = str_replace('.', '', round(microtime(1), 3));
529+
$to[] = htmlspecialchars($this->config['registrarprefix'] . '-contact-create-' . $clTRID);
530+
$xml = preg_replace($from, $to, '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
531+
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
532+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
533+
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
534+
<command>
535+
<create>
536+
<contact:create
537+
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
538+
<contact:id>{{ id }}</contact:id>
539+
<contact:postalInfo type="int">
540+
<contact:name>{{ name }}</contact:name>
541+
<contact:org>{{ org }}</contact:org>
542+
<contact:addr>
543+
<contact:street>{{ street1 }}</contact:street>
544+
<contact:street></contact:street>
545+
<contact:street></contact:street>
546+
<contact:city>{{ city }}</contact:city>
547+
<contact:sp>{{ state }}</contact:sp>
548+
<contact:pc>{{ postcode }}</contact:pc>
549+
<contact:cc>{{ country }}</contact:cc>
550+
</contact:addr>
551+
</contact:postalInfo>
552+
<contact:voice>{{ phonenumber }}</contact:voice>
553+
<contact:fax></contact:fax>
554+
<contact:email>{{ email }}</contact:email>
555+
<contact:authInfo>
556+
<contact:pw>{{ authInfo }}</contact:pw>
557+
</contact:authInfo>
558+
</contact:create>
559+
</create>
560+
<clTRID>{{ clTRID }}</clTRID>
561+
</command>
562+
</epp>');
563+
$r = $this->write($xml, __FUNCTION__);
564+
$r = $r->response->resData->children('urn:ietf:params:xml:ns:contact-1.0')->creData;
565+
$contacts = $r->id;
566+
}
549567

550568
//host create
551569
foreach (['ns1', 'ns2', 'ns3', 'ns4'] as $ns) {
@@ -635,21 +653,33 @@ public function registerDomain(Registrar_Domain $domain)
635653
$from[] = '/{{ ns4 }}/';
636654
$to[] = '';
637655
}
638-
$from[] = '/{{ cID_1 }}/';
639-
$to[] = htmlspecialchars($contacts);
640-
$from[] = '/{{ cID_2 }}/';
641-
$to[] = htmlspecialchars($contacts);
642-
$from[] = '/{{ cID_3 }}/';
643-
$to[] = htmlspecialchars($contacts);
644-
$from[] = '/{{ cID_4 }}/';
645-
$to[] = htmlspecialchars($contacts);
656+
if ($this->config['min_data_set'] === false) {
657+
$from[] = '/{{ cID_1 }}/';
658+
$to[] = htmlspecialchars($contacts);
659+
$from[] = '/{{ cID_2 }}/';
660+
$to[] = htmlspecialchars($contacts);
661+
$from[] = '/{{ cID_3 }}/';
662+
$to[] = htmlspecialchars($contacts);
663+
$from[] = '/{{ cID_4 }}/';
664+
$to[] = htmlspecialchars($contacts);
665+
}
646666
$from[] = '/{{ authInfo }}/';
647667
$to[] = htmlspecialchars($this->generateObjectPW());
648668
$from[] = '/{{ clTRID }}/';
649669
$clTRID = str_replace('.', '', round(microtime(1), 3));
650670
$to[] = htmlspecialchars($this->config['registrarprefix'] . '-domain-create-' . $clTRID);
651671
$from[] = "/<\w+:\w+>\s*<\/\w+:\w+>\s+/ims";
652672
$to[] = '';
673+
674+
$contact_section = '';
675+
if ($this->config['min_data_set'] === false) {
676+
$contact_section = '
677+
<domain:registrant>{{ cID_1 }}</domain:registrant>
678+
<domain:contact type="admin">{{ cID_2 }}</domain:contact>
679+
<domain:contact type="tech">{{ cID_3 }}</domain:contact>
680+
<domain:contact type="billing">{{ cID_4 }}</domain:contact>';
681+
}
682+
653683
$xml = preg_replace($from, $to, '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
654684
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
655685
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -665,11 +695,7 @@ public function registerDomain(Registrar_Domain $domain)
665695
<domain:hostObj>{{ ns2 }}</domain:hostObj>
666696
<domain:hostObj>{{ ns3 }}</domain:hostObj>
667697
<domain:hostObj>{{ ns4 }}</domain:hostObj>
668-
</domain:ns>
669-
<domain:registrant>{{ cID_1 }}</domain:registrant>
670-
<domain:contact type="admin">{{ cID_2 }}</domain:contact>
671-
<domain:contact type="tech">{{ cID_3 }}</domain:contact>
672-
<domain:contact type="billing">{{ cID_4 }}</domain:contact>
698+
</domain:ns>' . $contact_section . '
673699
<domain:authInfo>
674700
<domain:pw>{{ authInfo }}</domain:pw>
675701
</domain:authInfo>
@@ -685,6 +711,7 @@ public function registerDomain(Registrar_Domain $domain)
685711
$return = array(
686712
'error' => $e->getMessage()
687713
);
714+
throw new Registrar_Exception('Error: ' . $e->getMessage());
688715
}
689716

690717
if (!empty($s)) {
@@ -769,6 +796,11 @@ public function renewDomain(Registrar_Domain $domain)
769796
public function modifyContact(Registrar_Domain $domain)
770797
{
771798
$this->getLog()->debug('Updating contact info: ' . $domain->getName());
799+
800+
if ($this->config['min_data_set'] === true) {
801+
throw new Registrar_Exception("Contact update not possible as the Minimum Data Set is enabled.");
802+
}
803+
772804
$client = $domain->getContactRegistrar();
773805
$return = array();
774806
try {
@@ -1330,7 +1362,7 @@ public function connect()
13301362
$this->socket = stream_socket_client($tls."://{$host}:{$port}", $errno, $errmsg, $timeout, STREAM_CLIENT_CONNECT, $context);
13311363

13321364
if (!$this->socket) {
1333-
throw new exception("Cannot connect to server '{$host}': {$errmsg}");
1365+
throw new Registrar_Exception("Cannot connect to server '{$host}': {$errmsg}");
13341366
}
13351367

13361368
return $this->read();
@@ -1403,10 +1435,10 @@ public function read()
14031435
{
14041436
$hdr = stream_get_contents($this->socket, 4);
14051437
if ($hdr === false) {
1406-
throw new exception('Connection appears to have closed.');
1438+
throw new Registrar_Exception('Connection appears to have closed.');
14071439
}
14081440
if (strlen($hdr) < 4) {
1409-
throw new exception('Failed to read header from the connection.');
1441+
throw new Registrar_Exception('Failed to read header from the connection.');
14101442
}
14111443
$unpacked = unpack('N', $hdr);
14121444
$xml = fread($this->socket, ($unpacked[1] - 4));
@@ -1417,24 +1449,24 @@ public function read()
14171449
public function write($xml)
14181450
{
14191451
if (fwrite($this->socket, pack('N', (strlen($xml) + 4)) . $xml) === false) {
1420-
throw new exception('Error writing to the connection.');
1452+
throw new Registrar_Exception('Error writing to the connection.');
14211453
}
14221454
$xml_string = $this->read();
14231455
libxml_use_internal_errors(true);
14241456

14251457
$r = simplexml_load_string($xml_string, 'SimpleXMLElement', LIBXML_DTDLOAD | LIBXML_NOENT);
1426-
if ($r instanceof SimpleXMLElement) {
1427-
$r->registerXPathNamespace('e', 'urn:ietf:params:xml:ns:epp-1.0');
1428-
$r->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance');
1429-
$r->registerXPathNamespace('domain', 'urn:ietf:params:xml:ns:domain-1.0');
1430-
$r->registerXPathNamespace('contact', 'urn:ietf:params:xml:ns:contact-1.0');
1431-
$r->registerXPathNamespace('host', 'urn:ietf:params:xml:ns:host-1.0');
1432-
$r->registerXPathNamespace('rgp', 'urn:ietf:params:xml:ns:rgp-1.0');
1433-
}
1458+
if ($r instanceof SimpleXMLElement) {
1459+
$r->registerXPathNamespace('e', 'urn:ietf:params:xml:ns:epp-1.0');
1460+
$r->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance');
1461+
$r->registerXPathNamespace('domain', 'urn:ietf:params:xml:ns:domain-1.0');
1462+
$r->registerXPathNamespace('contact', 'urn:ietf:params:xml:ns:contact-1.0');
1463+
$r->registerXPathNamespace('host', 'urn:ietf:params:xml:ns:host-1.0');
1464+
$r->registerXPathNamespace('rgp', 'urn:ietf:params:xml:ns:rgp-1.0');
1465+
}
14341466

1435-
if (isset($r->response) && $r->response->result->attributes()->code >= 2000) {
1436-
throw new exception($r->response->result->msg);
1437-
}
1467+
if (isset($r->response) && $r->response->result->attributes()->code >= 2000) {
1468+
throw new Registrar_Exception($r->response->result->msg);
1469+
}
14381470
return $r;
14391471
}
14401472

@@ -1443,7 +1475,7 @@ public function disconnect()
14431475
{
14441476
$result = fclose($this->socket);
14451477
if (!$result) {
1446-
throw new exception('Error closing the connection.');
1478+
throw new Registrar_Exception('Error closing the connection.');
14471479
}
14481480
$this->socket = null;
14491481
return $result;

0 commit comments

Comments
 (0)