metaregistrar / php-epp-client

Object-oriented PHP EPP Client
https://www.metaregistrar.com/docs/
MIT License
216 stars 160 forks source link

nic.at only partly working #400

Open fsaber opened 2 weeks ago

fsaber commented 2 weeks ago

hi!

i try to connect to nic.at but i'm not really able implement the nicAtEpp specified parts. do i have to load it as an extension?

also under "Registries" i find nicatEppConnection and then a subfolder with atEppConnection...

thanks for help!

part of the script:

<?php
require('../autoloader.php');

use Metaregistrar\EPP\eppConnection;
use Metaregistrar\EPP\eppException;
use Metaregistrar\EPP\eppDomain;
use Metaregistrar\EPP\eppInfoDomainRequest;
use Metaregistrar\EPP\eppContactHandle;
use Metaregistrar\EPP\eppHost;
use Metaregistrar\EPP\eppInfoContactRequest;
use Metaregistrar\EPP\eppInfoContactResponse;
use Metaregistrar\EPP\eppContactPostalInfo;
use Metaregistrar\EPP\eppContact;
use Metaregistrar\EPP\eppUpdateContactRequest;

try {
    // Please enter your own settings file here under before using this example
    if ($conn = eppConnection::create('settings_nicat.ini')) {
        // Connect to the EPP server
        if ($conn->login()) {
            $result = infodomain($conn, $domainname);
            $conn->logout();
        }
    }
} catch (eppException $e) {
    echo "ERROR: " . $e->getMessage() . "\n\n";
}

part of the ini file:

interface=nicatEppConnection
hostname=ssl://epptest.nic.at
port=700
userid=*******
password=******
verifypeer=false
verifypeername=false
allowselfsigned=false
esurov commented 1 week ago

Hi @fsaber !

Perhaps you can use the code below as an example to interact with nic.at epp:

#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\eppInfoDomainRequest;
use Metaregistrar\EPP\eppDomain;
use Metaregistrar\EPP\eppStatus;
use Metaregistrar\EPP\eppException;

$opts = [
    'server:',
    'domain:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$domain = $params['domain'] ?? '';

// Ensure required parameters are there
if (!($serverstring && $domain)) {
    usage();
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    $eppDomain = new eppDomain($domain);

    $request = new eppInfoDomainRequest($eppDomain);
    if ($cltrid = ($params['cltrid'] ?? '')) {
        if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
            fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
            exit -1;
        }
        $request->sessionid = $cltrid;
        $request->addSessionId();
    }

    $response = $connection->request($request);
    $connection->logout();
    $connection->disconnect();

    if ($response->Success()) {
        echo 'SUCCESS: ' . $response->getResultCode() . "\n";
    } else {
        echo 'FAILED: ' . $response->getResultCode() . "\n";
        echo 'Domain info failed: ' . $response->getResultMessage() . "\n\n";
    }

    if ($name = $response->getDomainName()) {
        echo "ATTR: name: $name\n";
    }
    if ($roid = $response->getDomainRoid()) {
        echo "ATTR: roid: $roid\n";
    }
    if ($clid = $response->getDomainClientId()) {
        echo "ATTR: clID: $clid\n";
    }
    if ($crid = $response->getDomainCreateClientId()) {
        echo "ATTR: crID: $crid\n";
    }
    if ($upid = $response->getDomainUpdateClientId()) {
        echo "ATTR: upID: $upid\n";
    }
    if ($date = $response->getDomainCreateDate()) {
        if ($time = strtotime($date)) {
            $date = date('c', $time);
        }
        echo "ATTR: crDate: {$date}\n";
    }
    if ($date = $response->getDomainUpdateDate()) {
        if ($time = strtotime($date)) {
            $date = date('c', $time);
        }
        echo "ATTR: upDate: {$date}\n";
    }
    if ($date = $response->getDomainExpirationDate()) {
        if ($time = strtotime($date)) {
            $date = date('c', $time);
        }
        echo "ATTR: exDate: {$date}\n";
    }
    if ($auth = $response->getDomainAuthInfo()) {
        echo "ATTR: authInfo: $auth\n";
    }
    foreach ($response->getDomainStatuses() as $status) {
        if ($status instanceof eppStatus) {
            $statusDesc = $status->getStatusname();
            if ($statusMessage = $status->getMessage()) {
                $statusDesc .= " // $statusMessage";
            }
            echo "ATTR: status: {$statusDesc}\n";
        } else if (is_string($status)) {
            echo "ATTR: status: $status\n";
        }
    }

    echo "\n"; # separate output channels
    echo "ATTR: registrant: " . $response->getDomainRegistrant() . "\n";
    foreach ($response->getDomainContacts() as $contact) {
        if ($contact->getContactType() == 'tech') {
            echo "ATTR: tech: " . $contact->getContactHandle() . "\n";
        }
    }

    if ($ns = $response->getDomainNameservers()) {
        echo "\n"; # separate output channels
        foreach ($ns as $host) {
            echo "ATTR: hostName: " . $host->getHostname() . "\n";
            foreach (($host->getIpAddresses() ?? []) as $ip => $proto) {
                echo "ATTR: hostAddr: {$ip}\n";
            }
        }
    }

    echo "\n"; # separate output channels
    if ($secdns = $response->getKeydata()) {
        echo "  --- DNSSEC ---\n";
        foreach ($secdns as $n) {
            echo "ATTR: keyTag: " . $n->getKeytag() . "\n";
            echo "ATTR: digestType: " . $n->getDigestType() . "\n";
            echo "ATTR: alg: " . $n->getAlgorithm() . "\n";
            echo "ATTR: digest: " . $n->getDigest() . "\n\n";
        }
    }

    echo "\nATTR: clTRID: " . $response->getClientTransactionId() . "\n";
    echo "ATTR: svTRID: " . $response->getServerTransactionId() . "\n";

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

 infodomain   --server <user>:<pass>@<host>:<port>
              --domain <domain>
              [--cltrid <cltrid>]
              [--logdir <directory>]

END;

    exit -1;
}
esurov commented 1 week ago

You may run it like this: infodomain.php --server 'user:pass@epptest.nic.at:700' --domain=example.at --logdir='/tmp'

fsaber commented 1 week ago

thanks!

it works now! i get a stable connection. the next issue i run into is that i can't update contacts and domains. e.g. i want to update the nameservers:

`try { // Please enter your own settings file here under before using this example if ($conn = atEppConnection::create('settings.ini')) {

    // Connect to the EPP server
    if ($conn->login()) {
        modifydomain($conn, $domainname, null, null, null, null, array('ns1.metaregistrar.nl', 'ns2.metaregistrar.nl'));
        $conn->logout();
    }
}

} catch (eppException $e) { echo $e->getMessage() . "\n"; }

/**

i constantly get the Error 2306: Parameter value policy error return...

any ideas?

esurov commented 1 week ago

hi @fsaber ,

the thing you need to use the extension object for this, but please find updatecontact.php and updatedomain.php below:


#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\atEppContact;
use Metaregistrar\EPP\atEppUpdateContactExtension;
use Metaregistrar\EPP\atEppUpdateContactRequest;
use Metaregistrar\EPP\eppException;
use Metaregistrar\EPP\atEppContactHandle;
use Metaregistrar\EPP\eppContactPostalInfo;
use Metaregistrar\EPP\eppInfoContactRequest;

$opts = [
    'server:',
    'id:',
    'name:',
    'org::',
    'street:',
    'city:',
    'postalcode:',
    'country:',
    'voice:',
    'fax:',
    'email:',
    'disclose-phone:',
    'disclose-fax:',
    'disclose-email:',
    'type:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$id = $params['id'] ?? '';
$name = $params['name'] ?? null;
$org = $params['org'] ?? null;
$street = $params['street'] ?? null;
$city = $params['city'] ?? null;
$country = $params['country'] ?? null;
$postalcode = $params['postalcode'] ?? null;
$phone = $params['voice'] ?? null;
$fax = $params['fax'] ?? null;
$email = $params['email'] ?? null;
$type = $params['type'] ?? null;

$uniqueargs = ['name', 'org', 'city', 'postalcode', 'country', 'phone', 'voice', 'fax', 'email', 'type'];

foreach ($uniqueargs as $uarg) {
    if (is_array($params[$uarg] ?? null)) {
        echo "\nError: only one --$uarg argument allowed\n";
        usage();
    }
}

// Ensure required parameters are there
if (!($serverstring && $id)) {
    usage();
}

// Validate the contact type
if ($type && !in_array($type, ['privateperson', 'organisation', 'role'])) {
    fwrite(STDERR, "--type must be one Parameter out off \"privateperson, organisation, role\"\n");
    exit -1;
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Validate the disclose flags
foreach (['email', 'fax', 'phone'] as $disclose) {
    if (!in_array($params["disclose-{$disclose}"] ?? 0, [0, 1])) {
        fwrite(STDERR, "--disclose-{$disclose} has to be set to 0 or 1\n");
        exit -1;
    }
}

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    // Fetch the existing contact
    $handle = new atEppContactHandle($id);
    $request = new eppInfoContactRequest($handle);
    $response = $connection->request($request);
    $contact = $response->getContact();
    $postal = $contact->getPostalInfo(0);

    if (is_null($name)) $name = $postal->getName();
    if (is_null($org)) $org = $postal->getOrganisationName();
    if (is_null($street)) {
        $street = [];
        for ($i = 0; $i < $postal->getStreetCount(); $i++) {
            $street[] = $postal->getStreet($i);
        }
    }
    if (is_null($city)) $city = $postal->getCity();
    if (is_null($postalcode)) $postalcode = $postal->getZipcode();
    if (is_null($country)) $country = $postal->getCountrycode();

    if (is_null($type)) $type = $response->getPersonType();
    if (is_null($email)) $email = $contact->getEmail();
    if (is_null($phone)) $phone = $contact->getVoice();
    if (is_null($fax)) $fax = $contact->getFax();

    $hideEmail = isset($params['disclose-email']) ? (0 == ($params['disclose-email'] ?? 1)) : $response->getWhoisHideEmail();
    $hidePhone = isset($params['disclose-phone']) ? (0 == ($params['disclose-phone'] ?? 1)) : $response->getWhoisHidePhone();
    $hideFax = isset($params['disclose-fax']) ? (0 == ($params['disclose-fax'] ?? 1)) : $response->getWhoisHideFax();

    $postalInfo = new eppContactPostalInfo($name, $city, $country, $org, $street, null, $postalcode);
    $contact = new atEppContact($postalInfo, $type, $email, $phone, $fax, $hideEmail, $hidePhone, $hideFax);

    // Registry default behaviour disclose=1
    // is something is hidden set the disclose-policy
    $contact->setDisclose(($hideEmail || $hidePhone || $hideFax) ? 0 : 1);

    $ext = new atEppUpdateContactExtension($contact);
    $request = new atEppUpdateContactRequest($handle, null, null, $contact, $ext);
    if ($cltrid = ($params['cltrid'] ?? '')) {
        if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
            fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
            exit -1;
        }
        $request->sessionid = $cltrid;
        $request->addSessionId();
    }

    $response = $connection->request($request);
    $connection->logout();
    $connection->disconnect();

    if ($response->Success()) {
        echo 'SUCCESS: ' . $response->getResultCode() . "\n";
    } else {
        echo 'FAILED: ' . $response->getResultCode() . "\n";
        echo 'Contact update failed: ' . $response->getResultMessage() . "\n\n";
    }

    check_and_print_conditions($response->getExtensionResult());

    echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
    echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

updatecontact  --server <user>:<pass>@<host>:<port> \
               --id <id>
               [--name <name>]
               [--org <org>]
               [--street <street>]
               [--street <street>]
               [--city  <city>]
               [--postalcode <postalcode>]
               [--country <country>]
               [--voice <voice>]
               [--fax <fax>]
               [--email <email>]
               [--disclose-phone <0|1>]
               [--disclose-fax <0|1>]
               [--disclose-email <0|1>]
               [--type=(privateperson|organisation|role)]
               [--cltrid <cltrid>]
               [--logdir <directory>]

    Use --<option> "" do delete the specific value,
    eg. --org "" deletes the stored organisation .

END;

    exit -1;
}

and update_domain.php:

#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\atEppUpdateDomainRequest;
use Metaregistrar\EPP\atEppUndeleteRequest;
use Metaregistrar\EPP\eppInfoDomainRequest;
use Metaregistrar\EPP\atEppContactHandle;
use Metaregistrar\EPP\atEppDomain;
use Metaregistrar\EPP\eppHost;
use Metaregistrar\EPP\eppSecdns;
use Metaregistrar\EPP\eppException;

$opts = [
    'server:',
    'domain:',
    'addns:',
    'delns:',
    'registrant:',
    'addtechc:',
    'deltechc:',
    'addsecdns:',
    'delsecdns:',
    'delsecdns-all',
    'restore',
    'authinfo:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$domain = $params['domain'] ?? '';
$addns = (array) ($params['addns'] ?? []);
$delns = (array) ($params['delns'] ?? []);
$registrant = $params['registrant'] ?? null;
$addtechc = (array) ($params['addtechc'] ?? []);
$deltechc = (array) ($params['deltechc'] ?? []);
$addsecdns = (array) ($params['addsecdns'] ?? []);
$delsecdns = (array) ($params['delsecdns'] ?? []);
$delallsecdns = isset($params['delsecdns-all']);
$restore = isset($params['restore']);
$auth = $params['authinfo'] ?? null;

// Ensure required parameters are there
if (!($serverstring && $domain)) {
    usage();
}

// Check delsecdns
if ($delallsecdns && $delsecdns) {
    fwrite(STDERR, "\nEither --delsecdns-all or --delsecdns \"...\" allowed, not both of them\n");
    usage();
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    // Run undelete request if restore is called
    if ($restore) {
        $request = new atEppUndeleteRequest(new atEppDomain($domain));
        if ($cltrid = ($params['cltrid'] ?? '')) {
            if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
                fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
                exit -1;
            }
            $request->sessionid = $cltrid;
            $request->addSessionId();
        }
        $response = $connection->request($request);

        if ($response->Success()) {
            echo 'SUCCESS: ' . $response->getResultCode() . "\n";
        } else {
            echo 'FAILED: ' . $response->getResultCode() . "\n";
            echo 'Domain restore failed: ' . $response->getResultMessage() . "\n\n";
        }

        check_and_print_conditions($response->getExtensionResult());

        echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
        echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";
    }

    if ($addns || $delns || $registrant || $addtechc || $deltechc || $addsecdns || $delsecdns || $delallsecdns || $auth) {

        $chg = new atEppDomain($domain);
        $add = $rem = null;

        if ($registrant) {
            $chg->setRegistrant(new atEppContactHandle($registrant, 'reg'));
        }

        if ($auth) {
            $chg->setAuthorisationCode($auth);
        }

        // Handle nameserver
        foreach ($delns as $ns) {
            if (!$rem) $rem = new atEppDomain($domain);
            $rem->addHost(new eppHost($ns));
        }

        foreach ($addns as $ns) {
            if (!$add) $add = new atEppDomain($domain);
            $host = explode('/', $ns);
            if (count($host) == 1) {
                $add->addHost(new eppHost($host[0]));
            } else {
                for ($i = 1; $i < count($host); $i++) {
                    if ($host[$i] && !filter_var($host[$i], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && !filter_var($host[$i], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        fwrite(STDERR, $host[$i] . " is not a valid IPv4/IPv6 Address\n");
                        exit -1;
                    }
                    $add->addHost(new eppHost($host[0], $host[$i]));
                }
            }
        }

        // Handle techc
        foreach ($deltechc as $handle) {
            if (!$rem) $rem = new atEppDomain($domain);
            $rem->addContact(new atEppContactHandle($handle, 'tech'));
        }

        foreach ($addtechc as $handle) {
            if (!$add) $add = new atEppDomain($domain);
            $add->addContact(new atEppContactHandle($handle, 'tech'));
        }

        // Check secdns
        foreach ($addsecdns as $secdns) {
            $secdnsarray = array_reduce(explode(',', $secdns), function($carry, $item) {
                [$key, $value] = array_map('trim', explode('=>', $item));
                $carry[$key] = trim($value, "'\"");
                return $carry;
            }, []);
            if (!empty($secdnsarray['keyTag']) && !empty($secdnsarray['digestType']) && !empty($secdnsarray['digest']) && !empty($secdnsarray['alg'])) {
                $eppSecdns = new eppSecdns();
                $eppSecdns->setKeytag($secdnsarray['keyTag']);
                $eppSecdns->setDigestType($secdnsarray['digestType']);
                $eppSecdns->setDigest($secdnsarray['digest']);
                $eppSecdns->setAlgorithm($secdnsarray['alg']);
                if (!$add) $add = new atEppDomain($domain);
                $add->addSecdns($eppSecdns);
            }
        }

        foreach ($delsecdns as $secdns) {
            $secdnsarray = array_reduce(explode(',', $secdns), function($carry, $item) {
                [$key, $value] = array_map('trim', explode('=>', $item));
                $carry[$key] = trim($value, "'\"");
                return $carry;
            }, []);
            if (!empty($secdnsarray['keyTag']) && !empty($secdnsarray['digestType']) && !empty($secdnsarray['digest']) && !empty($secdnsarray['alg'])) {
                $eppSecdns = new eppSecdns();
                $eppSecdns->setKeytag($secdnsarray['keyTag']);
                $eppSecdns->setDigestType($secdnsarray['digestType']);
                $eppSecdns->setDigest($secdnsarray['digest']);
                $eppSecdns->setAlgorithm($secdnsarray['alg']);
                if (!$rem) $rem = new atEppDomain($domain);
                $rem->addSecdns($eppSecdns);
            }
        }

        if ($delallsecdns) {
            // In order to delete all the secdns we need to fetch them first
            $request = new eppInfoDomainRequest(new atEppDomain($domain));
            $response = $connection->request($request);

            if ($secdns = $response->getKeydata()) {
                if (!$rem) $rem = new atEppDomain($domain);
                foreach ($secdns as $n) {
                    $rem->addSecdns($n);
                }
            }
        }

        $request = new atEppUpdateDomainRequest($domain, $add, $rem, $chg, true);
        if ($cltrid = ($params['cltrid'] ?? '')) {
            if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
                fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
                exit -1;
            }
            $request->sessionid = $cltrid;
            $request->addSessionId();
        }

        $response = $connection->request($request);

        if ($response->Success()) {
            echo 'SUCCESS: ' . $response->getResultCode() . "\n";
        } else {
            echo 'FAILED: ' . $response->getResultCode() . "\n";
            echo 'Domain update failed: ' . $response->getResultMessage() . "\n\n";
        }

        check_and_print_conditions($response->getExtensionResult());

        echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
        echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";

    }

    $connection->logout();
    $connection->disconnect();

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

 updatedomain   --server <user>:<pass>@<host>:<port> \
                --domain <domain>
                [--addns <nsname>[/<ipaddr>[/<ipaddr>]]]
                [--delns <nsname>]
                [--registrant <registrant>]
                [--addtechc <tech-c>]
                [--deltechc <tech-c>]
                [--addsecdns "keyTag=>'12346', alg=>3, digestType=>1, digest=>'49FD46E6C4B45C55D4DD'"]
                [--delsecdns "keyTag=>'12346', alg=>3, digestType=>1, digest=>'49FD46E6C4B45C55D4DD'"]
                [--delsecdns-all]
                [--restore]
                [--authinfo \$'<authinfo>']
                [--cltrid <cltrid>]
                [--logdir <directory>]

Note: The Unix shell intercepts some special characters and tries to
      interpret them (f.e. \$). To pass an authInfo string with special
      characters to the EPP toolkit please encode the authInfo in the format
      \$'<authinfo>'. If you want to use a single quote within the authinfo
      string please escape it with a backslash (\\')

END;

    exit -1;
}
fsaber commented 1 week ago

thank you so much! they work perfectly!

do you also have such examples for createdomain and createcontact?

thanks!!!

esurov commented 1 week ago

here you go:

createdomain.php:

#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\atEppCreateDomainRequest;
use Metaregistrar\EPP\atEppContactHandle;
use Metaregistrar\EPP\atEppDomain;
use Metaregistrar\EPP\eppHost;
use Metaregistrar\EPP\eppSecdns;
use Metaregistrar\EPP\eppException;

$opts = [
    'server:',
    'domain:',
    'nameserver:',
    'registrant:',
    'techc:',
    'authinfo:',
    'secdns:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$domain = $params['domain'] ?? '';
$nameserver = (array) ($params['nameserver'] ?? []);
$registrant = $params['registrant'] ?? '';
$techc = (array) ($params['techc'] ?? []);
$secdns = $params['secdns'] ?? '';
$auth = $params['authinfo'] ?? '';

// Ensure required parameters are there
if (!($serverstring && $domain && $nameserver && $registrant && $techc && $auth)) {
    usage();
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    $eppDomain = new atEppDomain($domain);
    $eppDomain->setRegistrant(new atEppContactHandle($registrant, 'reg'));
    foreach ($techc as $handle) {
        $eppDomain->addContact(new atEppContactHandle($handle, 'tech'));
    }
    $eppDomain->setAuthorisationCode($auth);
    foreach ($nameserver as $ns) {
        $host = explode('/', $ns);
        if (count($host) == 1) {
            $eppDomain->addHost(new eppHost($host[0]));
        } else {
            for ($i = 1; $i < count($host); $i++) {
                if ($host[$i] && !filter_var($host[$i], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && !filter_var($host[$i], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                    fwrite(STDERR, $host[$i] . " is not a valid IPv4/IPv6 Address\n");
                    exit -1;
                }
                $eppDomain->addHost(new eppHost($host[0], $host[$i]));
            }
        }
    }

    // Check secdns
    if ($secdns) {
        $secdnsarray = array_reduce(explode(',', $secdns), function($carry, $item) {
            [$key, $value] = array_map('trim', explode('=>', $item));
            $carry[$key] = trim($value, "'\"");
            return $carry;
        }, []);
        if (!empty($secdnsarray['keyTag']) && !empty($secdnsarray['digestType']) && !empty($secdnsarray['digest']) && !empty($secdnsarray['alg'])) {
            $eppSecdns = new eppSecdns();
            $eppSecdns->setKeytag($secdnsarray['keyTag']);
            $eppSecdns->setDigestType($secdnsarray['digestType']);
            $eppSecdns->setDigest($secdnsarray['digest']);
            $eppSecdns->setAlgorithm($secdnsarray['alg']);
            $eppDomain->addSecdns($eppSecdns);
        }
    }

    $request = new atEppCreateDomainRequest($eppDomain);
    if ($cltrid = ($params['cltrid'] ?? '')) {
        if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
            fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
            exit -1;
        }
        $request->sessionid = $cltrid;
        $request->addSessionId();
    }

    $response = $connection->request($request);
    $connection->logout();
    $connection->disconnect();

    if ($response->Success()) {
        echo 'SUCCESS: ' . $response->getResultCode() . "\n";
    } else {
        echo 'FAILED: ' . $response->getResultCode() . "\n";
        echo 'Domain create failed: ' . $response->getResultMessage() . "\n\n";
    }

    check_and_print_conditions($response->getExtensionResult());

    echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
    echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";

    if ($name = $response->getDomainCreated()) {
        echo "ATTR: name: $name\n";
    }
    if ($date = $response->getDomainCreateDate()) {
        if ($time = strtotime($date)) {
            $date = date('c', $time);
        }
        echo "ATTR: crDate: {$date}\n";
    }

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

 createdomain   --server <user>:<pass>@<host>:<port> \
                --domain <domain>
                --nameserver <nsname>[/<ipaddr>[/<ipaddr>]]
                --nameserver <nsname>[/<ipaddr>[/<ipaddr>]]
                [--nameserver <nsname>[/<ipaddr>[/<ipaddr>]]
                --registrant <registrant>
                --techc <tech-c>
                --authinfo \$'<authinfo>'
                [--secdns "keyTag=>'12346', alg=>3, digestType=>1, digest=>'49FD46E6C4B45C55D4DD'"]
        [--cltrid <cltrid>]
        [--logdir <directory>]

Note: The Unix shell intercepts some special characters and tries to 
      interpret them (f.e. \$). To pass an authInfo string with special
      characters to the EPP toolkit please encode the authInfo in the format 
      \$'<authinfo>'. If you want to use a single quote within the authinfo 
      string please escape it with a backslash (\\')

END;

    exit -1;
}

and createcontact.php:


#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\atEppContact;
use Metaregistrar\EPP\atEppCreateContactExtension;
use Metaregistrar\EPP\atEppCreateContactRequest;
use Metaregistrar\EPP\eppException;
use Metaregistrar\EPP\eppContactPostalInfo;

$opts = [
    'server:',
    'name:',
    'org:',
    'street:',
    'city:',
    'postalcode:',
    'country:',
    'voice:',
    'fax:',
    'email:',
    'disclose-phone:',
    'disclose-fax:',
    'disclose-email:',
    'type:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$name = $params['name'] ?? '';
$org = $params['org'] ?? null;
$street = $params['street'] ?? '';
$city = $params['city'] ?? '';
$country = $params['country'] ?? '';
$postalcode = $params['postalcode'] ?? '';
$phone = $params['voice'] ?? '';
$fax = $params['fax'] ?? null;
$email = $params['email'] ?? '';
$type = $params['type'] ?? '';

$uniqueargs = ['name', 'org', 'city', 'postalcode', 'country', 'phone', 'voice', 'fax', 'email', 'type'];

foreach ($uniqueargs as $uarg) {
    if (is_array($params[$uarg] ?? null)) {
        echo "\nError: only one --$uarg argument allowed\n";
        usage();
    }
}

// Ensure required parameters are there
if (!($serverstring && $name && $city && $postalcode && $country && $email && $type)) {
    usage();
}

// Validate the contact type
if (!in_array($type, ['privateperson', 'organisation', 'role'])) {
    fwrite(STDERR, "--type must be one Parameter out off \"privateperson, organisation, role\"\n");
    exit -1;
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Validate the disclose flags
foreach (['email', 'fax', 'phone'] as $disclose) {
    if (!in_array($params["disclose-{$disclose}"] ?? 0, [0, 1])) {
        fwrite(STDERR, "--disclose-{$disclose} has to be set to 0 or 1\n");
        exit -1;
    }
}

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    $hideEmail = 0 == ($params['disclose-email'] ?? 1);
    $hidePhone = 0 == ($params['disclose-phone'] ?? 1);
    $hideFax = 0 == ($params['disclose-fax'] ?? 1);

    $postalInfo = new eppContactPostalInfo($name, $city, $country, $org, $street, null, $postalcode);
    $contact = new atEppContact($postalInfo, $type, $email, $phone, $fax, $hideEmail, $hidePhone, $hideFax);

    // Registry default behaviour disclose=1
    // is something is hidden set the disclose-policy
    if ($hideEmail || $hidePhone || $hideFax) {
        $contact->setDisclose(0);
    }

    $ext = new atEppCreateContactExtension($contact);

    $request = new atEppCreateContactRequest($contact, $ext);
    if ($cltrid = ($params['cltrid'] ?? '')) {
        if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
            fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
            exit -1;
        }
        $request->sessionid = $cltrid;
        $request->addSessionId();
    }

    $response = $connection->request($request);
    $connection->logout();
    $connection->disconnect();

    if ($response->Success()) {
        echo 'SUCCESS: ' . $response->getResultCode() . "\n";
    } else {
        echo 'FAILED: ' . $response->getResultCode() . "\n";
        echo 'Contact create failed: ' . $response->getResultMessage() . "\n\n";
    }

    check_and_print_conditions($response->getExtensionResult());

    echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
    echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";

    if ($id = $response->getContactId()) {
        echo "ATTR: ID: $id\n";
    }

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

createcontact   --server <user>:<pass>@<host>:<port> \
                --name <name>
                [--org <org>]
                --street <street>
                [--street <street>]
                --city  <city>
                --postalcode <postalcode>
                --country <country>
                [--voice <voice>]
                [--fax <fax>]
                --email <email>
                [--disclose-phone <0|1>]
                [--disclose-fax <0|1>]
                [--disclose-email <0|1>]
                --type=(privateperson|organisation|role)
                [--cltrid <cltrid>]
                [--logdir <directory>]

END;

    exit -1;
}

Can I ask you which registrar you're working with? :)

fsaber commented 1 week ago

Thanks again! Works also perfectly!

And i guess... you would also have the examples of deleteDomain and deleteContact? :)

Thanks!!

esurov commented 1 week ago

deletedomain.php:

#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\atEppDeleteRequest;
use Metaregistrar\EPP\atEppDomain;
use Metaregistrar\EPP\eppException;
use Metaregistrar\EPP\atEppDomainDeleteExtension;

$opts = [
    'server:',
    'domain:',
    'scheduledate:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$domain = $params['domain'] ?? '';
$scheduledate = $params['scheduledate'] ?? 'now';

// Ensure required parameters are there
if (!($serverstring && $domain)) {
    usage();
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

if ($scheduledate) {
    if (!in_array($scheduledate, ['now', 'expiration'])) {
        fwrite(STDERR, "--scheduledate must be one Parameter out off \"now, expiration\"\n");
        exit -1;
    }
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    $arg = ['pure_delete' => 1];
    if ($scheduledate) {
        $arg['schedule_date'] = $scheduledate;
    }
    $ext = new atEppDomainDeleteExtension($arg);
    $request = new atEppDeleteRequest(new atEppDomain($domain), $ext);
    if ($cltrid = ($params['cltrid'] ?? '')) {
        if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
            fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
            exit -1;
        }
        $request->sessionid = $cltrid;
        $request->addSessionId();
    }

    $response = $connection->request($request);

    if ($response->Success()) {
        echo 'SUCCESS: ' . $response->getResultCode() . "\n";
    } else {
        echo 'FAILED: ' . $response->getResultCode() . "\n";
        echo 'Domain delete failed: ' . $response->getResultMessage() . "\n\n";
    }

    check_and_print_conditions($response->getExtensionResult());

    echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
    echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";

    $connection->logout();
    $connection->disconnect();

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

 deletedomain  --server <user>:<pass>@<host>:<port> \
               --domain <domain>
               [--scheduledate <now|expiration>]
               [--cltrid <cltrid>]
               [--logdir <directory>]

END;

    exit -1;
}

and deletecontact.php:


#!/usr/bin/env php
<?php

require_once dirname(__DIR__) . '/vendor/autoload.php';

use Metaregistrar\EPP\atEppConnection;
use Metaregistrar\EPP\atEppDeleteRequest;
use Metaregistrar\EPP\atEppContactHandle;
use Metaregistrar\EPP\eppException;

$opts = [
    'server:',
    'id:',
    'cltrid:',
    'logdir:',
    'logfile',
    'nossl',
];

$params = getopt('', $opts);

$serverstring = $params['server'] ?? '';
$id = $params['id'] ?? '';

// Ensure required parameters are there
if (!($serverstring && $id)) {
    usage();
}

// Parsing the server string
if (!preg_match('/^([\w\d]+):([\S:@]+)@(\S+):(\d+)$/', $serverstring, $matches)) {
    fwrite(STDERR, "could not parse server string '$serverstring'\n");
    exit -1;
}
[, $username, $password, $hostname, $port] = $matches;

// Check nossl
if (isset($params['nossl'])) {
    echo "Warning: --nossl is deprecated and will be ignored ...\n";
}

try {
    $logging = false;

    // Check logfile
    if (isset($params['logfile'])) {
        fwrite(STDERR, "The option --logfile is deprecated\n");
        fwrite(STDERR, "use --logdir <directory> instead\n");
        exit -1;
    }

    if ($logdir = ($params['logdir'] ?? '')) {
        $logging = true;
    }

    $connection = new atEppConnection($logging);
    $connection->setHostname('ssl://' . $hostname);
    $connection->setPort($port);
    $connection->setTimeout(10);

    if ($logging) {
        $connection->setLogFile(rtrim($logdir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log');
    }
    $connected = $connection->connect();
    $connection->setUsername($username);
    $connection->setPassword($password);
    $logged_in = $connection->login();

    $request = new atEppDeleteRequest(new atEppContactHandle($id));
    if ($cltrid = ($params['cltrid'] ?? '')) {
        if (strlen($cltrid) > 64 || strlen($cltrid) < 4 ) {
            fwrite(STDERR, "--cltrid must be between 3 and 64 characters\n");
            exit -1;
        }
        $request->sessionid = $cltrid;
        $request->addSessionId();
    }

    $response = $connection->request($request);

    if ($response->Success()) {
        echo 'SUCCESS: ' . $response->getResultCode() . "\n";
    } else {
        echo 'FAILED: ' . $response->getResultCode() . "\n";
        echo 'Contact delete failed: ' . $response->getResultMessage() . "\n\n";
    }

    check_and_print_conditions($response->getExtensionResult());

    echo "\nATTR: clTRID: " . $response->getClTrId() . "\n";
    echo "ATTR: svTRID: " . $response->getSvTrId() . "\n";

    $connection->logout();
    $connection->disconnect();

} catch (eppException $e) {
    echo $e->getMessage() . "\n";
    check_and_print_conditions(json_decode($e->getReason(), true));
    exit -1;
}

function check_and_print_conditions($conditions) {
    if (!is_array($conditions)) return false;
    foreach ($conditions as $condition) {
        if (!empty($condition['message'])) {
            echo "Msg: {$condition['message']}\n";
        }
        if (!empty($condition['details'])) {
            echo "Details: {$condition['details']}\n";
        }
        echo "\n";
    }
}

function usage() {
    echo <<<END

usage:

 deletecontact  --server <user>:<pass>@<host>:<port> \
                --id <id>
                [--cltrid <cltrid>]
                [--logdir <directory>]

END;

    exit -1;
}