Unverified Commit 2a3d0db0 authored by Gavin Brown's avatar Gavin Brown
Browse files

enhancements. implements domain update!

parent e33eeecb
......@@ -47,7 +47,7 @@ sub request {
my $response = $self->SUPER::request($frame);
if (!$response) {
$self->{'outfh'}->print(sprintf("%04d %s\n", $Net::EPP::Simple::Code, $Net::EPP::Simple::Error));
$self->{'outfh'}->print(sprintf("%s%04d%s %s\n", color($Net::EPP::Simple::Code < 2000 ? 'green' : 'red'), $Net::EPP::Simple::Code, color('reset'), $Net::EPP::Simple::Message));
} else {
return $response;
......@@ -92,6 +92,7 @@ sub EndDocument {
}
package main;
use Term::ANSIColor;
use Term::ReadLine;
use Net::EPP::Simple;
use Getopt::Long;
......@@ -227,7 +228,7 @@ while (1) {
$term->WriteHistory($histfile);
$epp->logout if ($epp->connected && $epp->authenticated);
handle_logout() if ($epp->connected && $epp->authenticated);
$epp->disconnect if ($epp->connected);
note('bye!');
......@@ -255,7 +256,10 @@ sub handle_timeout {
}
sub handle_ssl {
if ($_[0] eq 'on') {
if ($epp->connected) {
return error("Already connected");
} elsif ($_[0] eq 'on') {
$epp->{'ssl'} = 1;
note('SSL enabled');
......@@ -271,19 +275,32 @@ sub handle_ssl {
}
sub handle_host {
if ($epp->connected) {
return error("Already connected");
} else {
$epp->{'host'} = $_[0];
note("Host set to %s", $_[0]);
return 1;
}
}
sub handle_port {
if ($epp->connected) {
return error("Already connected");
} else {
$epp->{'port'} = int($_[0]);
note("Port set to %d", $_[0]);
return 1;
}
}
sub handle_connect {
if ($epp->{'host'} eq '') {
if ($epp->connected) {
return error("Already connected");
} elsif ($epp->{'host'} eq '') {
return error('No host specified');
} else {
......@@ -312,44 +329,53 @@ sub handle_credentials {
return error('Missing password');
} else {
handle_id($_[0]);
handle_pw($_[1]);
handle_id($_[0]) && handle_pw($_[1]);
return 1;
}
}
sub handle_id {
if ($epp->authenticated) {
return error("Already authenticated");
} else {
$epp->{'user'} = shift;
note("User ID set to '%s'", $epp->{'user'});
}
}
sub handle_pw {
if ($epp->authenticated) {
return error("Already authenticated");
} else {
$epp->{'pass'} = shift;
note("Password set to '%s'", ('*' x length($epp->{'pass'})));
}
}
sub handle_login {
my $verbose = shift;
if ($epp->{'host'} eq '') {
return error('No host specified');
} elsif ($epp->{'user'} eq '' || $epp->{'pass'} eq '') {
return error('No credentials specified');
} elsif (!$epp->connected) {
if (!$epp->connected) {
return handle_connect() && handle_login();
} elsif ($epp->authenticated) {
return error('Already logged in');
} elsif ($epp->{'host'} eq '') {
return error('No host specified');
} elsif ($epp->{'user'} eq '' || $epp->{'pass'} eq '') {
return error('No credentials specified');
} else {
$epp->{'quiet'} = ($verbose ? 0 : 1);
my $result = $epp->_login;
$epp->{'quiet'} = 0;
note("%04d %s", $Net::EPP::Simple::Code, $Net::EPP::Simple::Message);
note("%s%04d%s %s", color($Net::EPP::Simple::Code < 2000 ? 'green' : 'red'), $Net::EPP::Simple::Code, color('reset'), $Net::EPP::Simple::Message);
return $result;
}
}
......@@ -362,16 +388,26 @@ sub handle_logout {
$epp->{'quiet'} = 1;
my $result = $epp->logout;
$epp->{'quiet'} = 0;
note("%04d %s", $Net::EPP::Simple::Code, $Net::EPP::Simple::Message);
note("%s%04d%s %s", color($Net::EPP::Simple::Code < 2000 ? 'green' : 'red'), $Net::EPP::Simple::Code, color('reset'), $Net::EPP::Simple::Message);
return $result;
}
}
sub handle_hello {
if (!$epp->connected) {
return error('Not connected');
} else {
return $epp->ping;
}
}
sub handle_check {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($type, $id, @extra) = @_;
if ($type eq 'domain') {
return $epp->check_domain($id);
......@@ -392,6 +428,7 @@ sub handle_check {
return error("Unsupported object type '$type'");
}
}
}
sub handle_claims_check {
......@@ -453,6 +490,10 @@ sub handle_fee_check {
}
sub handle_info {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($type, $id, $authInfo, $opt) = @_;
if ($type eq 'domain') {
$opt = $opt || 'all';
......@@ -468,9 +509,14 @@ sub handle_info {
return error("Unsupported object type '$type'");
}
}
}
sub handle_poll {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($op, $id) = @_;
if ($op eq 'req') {
my $frame = Net::EPP::Frame::Command::Poll::Req->new;
......@@ -485,13 +531,24 @@ sub handle_poll {
error("Unsupported poll op '$op'");
}
}
}
sub handle_send {
if (!$epp->connected) {
return error('Not connected');
} else {
$epp->request($_[0]);
}
}
sub handle_begin {
if (!$epp->connected) {
return error('Not connected');
} else {
my $buffer = '';
while (my $line = <STDIN>) {
if ($line =~ /^END/) {
......@@ -503,6 +560,7 @@ sub handle_begin {
}
}
$epp->request($buffer);
}
}
sub handle_help {
......@@ -521,15 +579,24 @@ sub handle_exit {
}
sub handle_transfer {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($type, $object, $cmd, $authinfo, $period) = @_;
return error("invalid object type '%s'", $type) if ($type ne 'domain' && $type ne 'contact');
return error("invalid command '%s'", $cmd) if ($cmd ne 'query' && $cmd ne 'request' && $cmd ne 'cancel' && $cmd ne 'approve' && $cmd ne 'reject');
return $epp->_transfer_request($cmd, $type, $object, $authinfo, $period);
}
}
sub handle_clone {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($type, $old, $new) = @_;
if (lc($type) eq 'contact') {
......@@ -542,6 +609,7 @@ sub handle_clone {
error("Unsupported object type '$type'");
}
}
}
sub handle_contact_clone {
......@@ -576,6 +644,10 @@ sub generate_authinfo {
}
sub handle_delete {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($type, $id) = @_;
if ($type eq 'domain') {
return $epp->delete_domain($id);
......@@ -590,25 +662,37 @@ sub handle_delete {
return error("Unsupported object type '$type'");
}
}
}
sub handle_renew {
my ($domain, $period) = @_;
if (!$epp->authenticated) {
return error('Not connected');
} else {
my ($domain, $period, $date) = @_;
$period = 1 if (!$period);
if (!$date) {
my $info = $epp->domain_info($domain);
return undef if (!$info);
my ($date, undef) = split(/T/, $info->{'exDate'}, 2);
($date, undef) = split(/T/, $info->{'exDate'}, 2);
}
return $epp->renew_domain({
'name' => $domain,
'period' => $period,
'cur_exp_date' => $date,
});
}
}
sub handle_create {
if (!$epp->authenticated) {
return error('Not connected');
} else {
my $type = lc(shift);
if ($type eq 'host') {
......@@ -618,6 +702,7 @@ sub handle_create {
return error("invalid type '%s'", $type);
}
}
}
sub create_host {
......@@ -634,6 +719,10 @@ sub create_host {
}
sub handle_edit {
if (!$epp->connected) {
return error('Not connected');
} else {
my $file = tmpnam();
if (0 != system(sprintf("%s %s", $ENV{'EDITOR'}, quotemeta($file)))) {
error("$ENV{'EDITOR'} exited abnormally");
......@@ -651,22 +740,37 @@ sub handle_edit {
$epp->request($frame);
}
}
}
}
sub handle_key {
if ($epp->connected) {
return error('Already connected');
} else {
my ($key, $pass) = @_;
$epp->{'key'} = $key;
$epp->{'passphrase'} = $pass;
note("Using '$key' as private key");
}
}
sub handle_cert {
if ($epp->connected) {
return error('Already connected');
} else {
my $cert = shift;
$epp->{'cert'} = $cert;
note("Using '$cert' as certificate");
}
}
sub handle_restore {
if (!$epp->connected) {
return error('Not connected');
} else {
my $domain = shift;
my $frame = Net::EPP::Frame::Command::Update::Domain->new;
......@@ -685,9 +789,14 @@ sub handle_restore {
$restore->setAttribute('op', 'request');
return $epp->request($frame);
}
}
sub handle_update {
if (!$epp->connected) {
return error('Not connected');
} else {
my $type = shift;
if ($type eq 'domain') {
return domain_update(@_);
......@@ -702,10 +811,89 @@ sub handle_update {
return error("Unsupported object type '$type'");
}
}
}
sub domain_update {
error("Domain update not supported yet");
my $frame = Net::EPP::Frame::Command::Update::Domain->new;
$frame->setDomain(shift(@_));
my $changes = {
'ns' => [],
'contact' => [],
'status' => [],
};
for (my $i = 0 ; $i < scalar(@_) ; $i++) {
my $action = lc($_[$i]);
my $type = lc($_[++$i]);
my $value = $_[++$i];
return error("Invalid parameter '$action'") if ($action !~ /^(add|rem|chg)$/);
return error("Missing parameter") if (!$type || !$value);
return error("Invalid property '$type'") if ($type !~ /^(ns|admin|tech|billing|status|registrant|authinfo)$/);
if ($type eq 'ns') {
push(@{$changes->{'ns'}}, [ $action, $value ]);
} elsif ($type =~ /^(admin|tech|billing)$/) {
push(@{$changes->{'contact'}}, [ $action, $type, $value ]);
} elsif ($type eq 'status') {
push(@{$changes->{'status'}}, [ $action, $value ]);
} elsif ($action eq 'chg') {
if ('registrant' eq $type) {
$frame->chgRegistrant($value);
} elsif ('authinfo' eq $type) {
$frame->chgAuthinfo($value);
} else {
}
} else {
return error("Don't know what to do with '$action $type $value'");
}
}
foreach my $change (@{$changes->{'ns'}}) {
my ($action, $value) = @{$change};
if ($action eq 'add') {
$frame->addNS($value);
} else {
$frame->remNS($value);
}
}
foreach my $change (@{$changes->{'contact'}}) {
my ($action, $type, $value) = @{$change};
if ($action eq 'add') {
$frame->addContact($type, $value);
} else {
$frame->remContact($type, $value);
}
}
foreach my $change (@{$changes->{'status'}}) {
my ($action, $value) = @{$change};
if ($action eq 'add') {
$frame->addStatus($value);
} else {
$frame->remStatus($value);
}
}
return $epp->request($frame);
}
sub host_update {
......@@ -741,6 +929,10 @@ sub host_update {
$frame->chgName($value);
}
} else {
return error("Don't know what to do with '$action $type $value'");
}
}
......@@ -783,13 +975,13 @@ sub note {
sub error {
my ($fmt, @args) = @_;
note("Error: ".$fmt, @args);
note(color('red')."Error: ".color('reset').$fmt, @args);
return undef;
}
sub fatal {
my ($fmt, @args) = @_;
note("Fatal Error: ".$fmt, @args);
note(color('red')."Fatal Error: ".color('reset').$fmt, @args);
exit(1);
}
......@@ -933,9 +1125,9 @@ clone a domain or contact object C<OLD> into a new object identified by C<NEW> (
delete an object (C<TYPE> is one of C<domain>, C<host>, C<contact>)
=item C<renew DOMAIN PERIOD>
=item C<renew DOMAIN PERIOD [EXPDATE]>
renew a domain (1 year by default)
renew a domain (1 year by default). If you do not provide the C<CUREXPDATE> argument, pepper will perform an C<E<lt>infoE<gt>> command to get it from the server.
=item C<restore DOMAIN>
......@@ -955,27 +1147,55 @@ quit the program (logging out if necessary)
Objects may be updated using the C<update> command.
=head3 Host updates
=head3 Domain Updates
update domain HOSTNAME CHANGES
The C<CHANGES> argument consists of groups of three values: an action (ie C<add>, C<rem> or C<chg>), followed by a property name (e.g. C<ns>, a contact type (such as C<admin>, C<tech> or C<billing>) or C<status>), followed by a value.
Example:
update domain example.com add ns ns0.example.com
update domain example.com rem ns ns0.example.com
update domain example.com add status clientUpdateProhibited
update domain example.com rem status clientHold
update domain example.com add admin H12345
update domain example.com rem tech H54321
update domain example.com chg registrant H54321
update domain example.cm chg authinfo foo2bar
Multiple changes can be combined in a single command:
update domain example.com add status clientUpdateProhibited rem ns ns0.example.com chg registrant H54321
=head3 Host Updates
Syntax:
update host HOSTNAME CHANGES
The C<CHANGES> argument consists of groups of three values: an action (ie C<add>, C<rem> or C<chg>) followed by a property name (ie C<addr>, C<status> or C<name>) followed by a value.
The C<CHANGES> argument consists of groups of three values: an action (ie C<add>, C<rem> or C<chg>), followed by a property name (ie C<addr>, C<status> or C<name>), followed by a value.
Examples:
update ns0.example.com add status clientUpdateProhibited
update host ns0.example.com add status clientUpdateProhibited
update ns0.example.com rem addr 10.0.0.1
update host ns0.example.com rem addr 10.0.0.1
update ns0.example.com chg name ns0.example.net
update host ns0.example.com chg name ns0.example.net
Multiple changes can be combined in a single command:
update host ns0.example.com add status clientUpdateProhibited rem addr 10.0.0.1 add addr 1::1 chg name ns0.example.net
=head3 Domain and Contact updates
=head3 Contact Updates
Not currently implemented.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment