#!/usr/bin/perl
# .Copyright (C) 1999-2000 TUCOWS.com Inc.
# .Created: 11/19/1999
# .Contactid:
);
} else {
$HTML{MESSAGE} = "";
}
print_form("$path_templates/login.html",\%HTML,'single');
}
# show main page for secure users
sub main_menu {
my (%HTML, $key);
my $message = shift;
# build front page per user's permissions
my %GRANT = (
f_modify_nameservers => "Manage Name Servers",
f_modify_owner => "Organization Contact",
f_modify_admin => "Admin Contact",
f_modify_billing => "Billing Contact",
f_modify_tech => "Technical Contact",
sub_user => "Manage Profile",
f_modify_whois_rsp_info => "Reseller Contact",
domain_locking => "Domain Locking",
f_modify_domain_extras => "Domain Extras",
);
my %DENY = (
f_modify_nameservers => "Manage Name Servers",
f_modify_owner => "Organization Contact",
f_modify_admin => "Admin Contact",
f_modify_billing => "Billing Contact",
f_modify_tech => "Technical Contact",
sub_user => "Manage Profile",
f_modify_whois_rsp_info => "Reseller Contact",
domain_locking => "Domain Locking",
f_modify_domain_extras => "Domain Extras",
);
# if user is the owner of the domain, give them full permissions
if ($reg_f_owner) {
foreach $key (keys %GRANT) {
$HTML{$key} = $GRANT{$key};
}
# otherwise, check their permission level against %PERMISSIONS
} else {
foreach $key (keys %GRANT) {
if ($reg_f_owner or ($reg_permission & $PERMISSIONS{$key})) {
$HTML{$key} = $GRANT{$key};
} else {
$HTML{$key} = $DENY{$key};
}
}
}
$HTML{whois_rsp_info} = $GRANT{whois_rsp_info};
$HTML{domain_locking} = $GRANT{domain_locking};
#
# .ca domains don't have a billing contact.
#
if ($reg_domain =~ /ca$/)
{
$HTML{f_modify_billing} = "$DENY{f_modify_billing} (CIRA uses the Administrative Contact for Billing)";
}
# if no extra domain info. to be displayed, do not show the link
if ( ! $capabilities->{domain_extras} ) {
$HTML{ f_modify_domain_extras } = "$DENY{ f_modify_domain_extras }";
}
# not all TLDs support locking
if ( not $reg_domain =~ /$OPENSRS{ TLDS_SUPPORTING_LOCKING }/i) {
$HTML{ domain_locking } = "$DENY{ domain_locking } (TLD does not support locking)";
} elsif ( not $reg_f_owner ) {
$HTML{ domain_locking } = "$DENY{ domain_locking } (Can only be modified by the owner of the domain)";
}
# .uk domains can't have their owner information changed,
# so only show the organization paragraph if the domain
# is not .uk
if ( $reg_domain !~ /uk$/ )
{
$HTML{f_modify_owner} = <
EOF
}
else
{
$HTML{f_modify_owner} = <
EOF
}
if ( $reg_domain !~ /uk$/ ) {
$HTML{f_modify_owner} .= <
EOF
}
else
{
$HTML{f_modify_owner} .= <
EOF
}
if ($last_access_time) {
my $human_time = scalar localtime($last_access_time);
$HTML{LAST_ACCESS} = "
Last login: $human_time";
if ($last_ip) {
$HTML{LAST_ACCESS} .= " from $last_ip";
}
}
if ( not $reg_f_owner and not ($reg_permission & $PERMISSIONS{f_modify_owner}) ) {
$HTML{SUB_USER} = "
Logged in as Sub User. Ownership changes disabled.";
}
$HTML{MESSAGE} = $message ? "
$message
\n" : "";
$HTML{CGI} = $cgi;
$HTML{reg_username} = $reg_username;
print_form("$path_templates/main_menu.html",\%HTML);
}
# show subuser info
sub manage_subuser {
my (%HTML,$perm);
my ($sub_id,$sub_username,$sub_permission) = get_subuser();
$HTML{CGI} = $cgi;
$HTML{sub_id} = $sub_id;
$HTML{sub_username} = $sub_username;
foreach $perm (keys %PERMISSIONS) {
if ($sub_permission & $PERMISSIONS{$perm}) {
$HTML{"${perm}_1"} = "CHECKED";
} else {
$HTML{"${perm}_0"} = "CHECKED";
}
}
print_form("$path_templates/manage_subuser.html",\%HTML);
}
# process data for subuser modifications
sub do_manage_subuser {
my ($response,$perm);
my $sub_username = $in{sub_username};
my $sub_password = $in{sub_password};
my $sub_password2 = $in{sub_password2};
my $sub_id = $in{sub_id};
if (not $sub_username) {
error_out("No username supplied.
\n");
exit;
} elsif ($sub_password ne $sub_password2) {
error_out("Password mismatch.
\n");
exit;
} elsif (not $sub_password and not $sub_id) {
error_out("No password supplied.
\n");
exit;
}
my $sub_permission = 0;
foreach $perm (keys %PERMISSIONS) {
if ($in{$perm}) {
$sub_permission |= $PERMISSIONS{$perm};
}
}
my $xcp_request = {
action => ( $sub_id ? "modify" : "add" ),
object => "subuser",
cookie => $cookie,
attributes => {
sub_id => $sub_id,
sub_username => $sub_username,
sub_password => $sub_password,
sub_permission => $sub_permission,
}
};
$response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Command failed: $response->{response_text}\n");
exit;
}
main_menu("Subuser Changes Successful");
}
sub delete_subuser {
my $sub_id = $in{sub_id};
if (not $reg_f_owner) {
error_out("Only domain owner can delete subuser.
\n");
exit;
} elsif (not $sub_id) {
error_out("Subuser's id not supplied.
\n");
exit;
}
my $xcp_request = {
action => "delete",
object => "subuser",
cookie => $cookie,
attributes => {
sub_id => $sub_id,
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Command failed: $response->{response_text}\n");
exit;
}
main_menu("Subuser deleted");
}
sub change_password {
my (%HTML);
if (not $reg_f_owner) {
error_out("Permission denied: not owner.\n");
exit;
}
$HTML{CGI} = $cgi;
print_form("$path_templates/change_password.html",\%HTML);
}
sub do_change_password {
my $password = $in{password};
my $confirm_password = $in{confirm_password};
if ($password ne $confirm_password) {
error_out("Password mismatch.
\n");
exit;
} elsif ($password =~ /^\s*$/) {
error_out("You must supply a valid password.
\n");
exit;
}
my $xcp_request = {
action => "change",
object => "password",
cookie => $cookie,
attributes => {
reg_password => $password,
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Failed attempt: $response->{response_text}\n");
exit;
}
main_menu("Password successfully changed.");
}
sub revoke_registrant_changes{
my ($error);
my $xcp_request = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "contact_info",
contact_set => {
'owner' => {"revoke_registrant_changes"=>1},
},
},
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
$error = "Failed attempt: $response->{response_text}
\n";
error_out($error);
exit;
}
main_menu($response->{response_text});
}
# show contact info for specified domain and contact type
sub modify_contact {
my ($error);
my $type = $in{type};
my $xcp_request = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => $type,
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
$error = "Failed attempt: $response->{response_text}
\n";
error_out($error);
exit;
}
# process this through escape() to account for " and ' in the data
escape_hash_values( $response );
my %HTML = ();
# put the contact keys/values into %HTML
foreach my $aKey ( keys %{$response->{attributes}->{contact_set}->{$type}} ) {
next unless exists $contact_keys{$aKey};
$HTML{$aKey} = $response->{attributes}->{contact_set}->{$type}->{$aKey};
}
#
# If the change is for the Org and the ccTLD is .ca
# then we need only display a wee little bit of info.
#
if (($type =~ /owner/i) && ($reg_domain =~ /ca$/))
{
my %short_way = %{$response->{attributes}->{contact_set}->{$type}};
if ((defined $short_way{member}) && ($short_way{member} eq "Y"))
{
$HTML{member_field} = "Yes\n
No\n";
}
else
{
$HTML{member_field} = "Yes\n
No\n";
}
$HTML{legal_type_field} = build_ca_domain_legal_types ($short_way{legal_type});
$HTML{reg_domain} = $reg_domain;
$HTML{contact_type} = $contact_types{$type};
$HTML{type} = $type;
$HTML{description} = $short_way{description};
$HTML{CGI} = $cgi;
print_form("$path_templates/modify_ca_org_contact.html",\%HTML);
return;
}
#
# .ca is, as always, different....
#
if ($reg_domain =~ /ca$/)
{
foreach my $item (@CA_EXTRA_FIELDS)
{
$HTML{$item} = $response->{attributes}->{contact_set}->{$type}->{$item};
}
$HTML{language_type_field} = build_ca_language_preferences ($HTML{language});
$HTML{nationality_field} = build_ca_nationality_pulldown ($HTML{nationality});
if ( $in{ type } eq 'admin' ) {
$HTML{ cc_warning } = <
Note: Modifications to the admin contact info has been
deemed a 'critical change' by CIRA, and any changes to the contact information
will not take affect unless also confirmed at the CIRA site.
EOF
} elsif ( $in{ type } eq 'tech' ) {
$HTML{ cc_warning } = <
Note: If the technical contact info is the same as
that for the admin contact, changes to the information below will be deemed
a 'critical change' by CIRA, and will not take affect unless the changes are
also confirmed at the CIRA site.
EOF
}
}
else
{
$HTML{language_type} = "";
$HTML{middle_name} = "";
$HTML{job_title} = "";
$HTML{nationality} = "";
}
$HTML{org_comment} = '';
$HTML{org_comment_close} = '';
$HTML{uk_org_comment} = '!--';
$HTML{uk_org_comment_close} = '--';
# uk domains don't have 'Organization'. Not a very nice way of hiding
# the org name, but better to keep the template whole. Turn the
# organization line into an HTML comment.
# the exception is uk domain owner contact, we use the Organization as registrant
if ( $reg_domain =~ /\.uk$/ ) {
$HTML{org_comment} = '!--';
$HTML{org_comment_close} = '--';
}
if ( $reg_domain =~ /\.uk$/ && $type =~ /owner/i ) {
$HTML{uk_org_comment} = '';
$HTML{uk_org_comment_close} = '';
}
$HTML{reg_domain} = $reg_domain;
$HTML{contact_type} = $contact_types{$type};
$HTML{type} = $type;
$HTML{CGI} = $cgi;
$HTML{COUNTRY_LIST} = build_country_list($HTML{country});
my $template="modify_contact.html";
if ($reg_domain =~ /ca$/) {
$template="modify_contact_ca.html";
$HTML{GLOBAL_CHANGE_MENU} =
make_global_menu($reg_f_owner,$reg_permission,$type)."
Only .ca will be affected
\n";
} else {
$HTML{GLOBAL_CHANGE_MENU} =
make_global_menu($reg_f_owner,$reg_permission,$type);
}
if ($type eq 'owner' and
$response->{attributes}->{contact_set}->{'owner'}->{ownership_changes_request}){
my $shortcut=$response->{attributes}->{contact_set}->{'owner'}->{ownership_changes_request};
$HTML{revoke_registrant_changes}=<
Click Here if you want to revoke this request.
EOF
}
print_form("$path_templates/$template",\%HTML);
}
# process data to modify contact info
sub do_modify_contact {
my ($key, $error, $type);
my $result_domain_race_obj;
my $resultString;
if ($in{submit} =~ /cancel/i) {
main_menu("Changes cancelled");
exit;
}
$type = $in{type};
delete $in{type};
my $xcp_request = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "contact_info",
affect_domains => $in{affect_domains},
contact_set => {
$type => {},
also_apply_to => [],
},
}
};
foreach $key ( keys %in ) {
next unless exists $contact_keys{$key};
$xcp_request->{attributes}->{contact_set}->{$type}->{$key} = $in{$key};
}
if ($reg_domain =~ /ca$/)
{
foreach $key (@CA_EXTRA_FIELDS)
{
$xcp_request->{attributes}->{contact_set}->{$type}->{$key} = $in{$key} if defined $in{$key};
}
}
# basic error checking on request vs user permissions
my $affect_domains = $in{affect_domains};
foreach $key (keys %contact_types) {
if ($in{"affect_$key"}) {
if ((not $reg_f_owner) and (not $reg_permission & $PERMISSIONS{"F_MODIFY_$key"})) {
error_out("No permission to modify contact type: $contact_types{$key}.
\n");
exit;
}
push @{$xcp_request->{attributes}->{contact_set}->{also_apply_to}}, $key;
}
}
if ($affect_domains and (not $reg_f_owner)) {
error_out("Only the domain owner can apply changes to multiple domains.
\n");
exit;
}
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
$error .= "Failed attempt: $response->{response_text}.
\n";
if ($response->{attributes}->{error}) {
$response->{attributes}->{error} =~ s/\n/
\n/g;
$error .= $response->{attributes}->{error};
}
error_out($error);
exit;
}
# response_code of 250 indicates that an asynchronous registry has
# received the request and the modification completion will
# occur later.
if ( $response->{response_code} == 250 )
{
$waiting_request = $response->{attributes}->{waiting_request};
main_menu($resultString."Contact modification submitted, could take up to ".time_to_wait().".");
}
else
{
my $domainResult;
if ( exists $response->{attributes} &&
exists $response->{attributes}->{details} )
{
$resultString .= $response->{attributes}->{response_text};
$resultString .= "
";
my $tempDetailHash;
foreach $domainResult ( keys %{$response->{attributes}->{details}} )
{
$tempDetailHash = $response->{attributes}->{details}->{$domainResult};
$result_domain_race_obj = RACE::UndoRACE(Domain => pack('A*',$domainResult),
EncodingType => $UNIVERSAL_ENCODING_TYPE);
$resultString = sprintf( '%s%s : %s
',
$resultString,
$result_domain_race_obj->{OriginalDomain},
$tempDetailHash->{response_text} );
if ( $domainResult eq $reg_domain &&
exists $tempDetailHash->{waiting_request})
{
$waiting_request = $tempDetailHash->{waiting_request};
}
}
}
else
{
$resultString .= $response->{response_text};
}
main_menu($resultString);
}
}
# show domain tld-specific info
sub modify_domain_extras {
my ($error);
my $rsp_auth_info;
if ($capabilities->{domain_auth_info}) {
my $xcp_auth_info = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => "domain_auth_info",
}
};
$rsp_auth_info = $XML_Client->send_cmd( $xcp_auth_info );
if (not $rsp_auth_info->{is_success}) {
$error = "Failed attempt: $rsp_auth_info->{response_text}
\n";
error_out($error);
exit;
}
escape_hash_values( $rsp_auth_info );
}
my $rsp_forwarding_email;
if ($capabilities->{forwarding_email}) {
my $xcp_forwarding_email = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => "forwarding_email",
}
};
$rsp_forwarding_email = $XML_Client->send_cmd( $xcp_forwarding_email );
if (not $rsp_forwarding_email->{is_success}) {
$error = "Failed attempt: $rsp_forwarding_email->{response_text}
\n";
error_out($error);
exit;
}
escape_hash_values( $rsp_forwarding_email );
}
my $rsp_nexus_info;
if ($capabilities->{nexus_info}) {
my $xcp_nexus_info = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => "nexus_info",
}
};
$rsp_nexus_info = $XML_Client->send_cmd( $xcp_nexus_info );
if (not $rsp_nexus_info->{is_success}) {
$error = "Failed attempt: $rsp_nexus_info->{response_text}
\n";
error_out($error);
exit;
}
escape_hash_values( $rsp_nexus_info );
}
my %HTML = ();
$HTML{domain_auth_info} = $rsp_auth_info->{attributes}->{domain_auth_info} if ($rsp_auth_info);
$HTML{forwarding_email} = $rsp_forwarding_email->{attributes}->{forwarding_email} if ($rsp_forwarding_email);
if ($rsp_nexus_info) {
$HTML{old_app_purpose} = $rsp_nexus_info->{attributes}->{nexus}->{app_purpose};
$HTML{old_nexus_category} = $rsp_nexus_info->{attributes}->{nexus}->{category};
$HTML{old_nexus_validator} = $rsp_nexus_info->{attributes}->{nexus}->{validator};
$HTML{old_app_purpose} =~ tr/a-z/A-Z/;
$HTML{old_nexus_category} =~ tr/a-z/A-Z/;
$HTML{old_nexus_validator} =~ tr/a-z/A-Z/;
$HTML{"category_" . $HTML{old_nexus_category}} = "checked";
}
if ($HTML{forwarding_email}) {
$HTML{text_comment} = '!--';
$HTML{text_comment_close} = '--';
} else {
$HTML{email_comment} = '!--';
$HTML{email_comment_close} = '--';
}
$HTML{CGI} = $cgi;
# include domain auth code form in the main html page if domain auth code is avaliable
if ($rsp_auth_info) {
$HTML{domain_auth_code_form} = get_content("$path_templates/domain_auth_code_form.html", \%HTML);
}
# include forwarding email form in the main html page if it is capable for forwarding email modification
if ($rsp_forwarding_email) {
$HTML{forwarding_email_form} = get_content("$path_templates/forwarding_email_form.html", \%HTML);
}
# include nexus data form in the main html page if it is capable for .us nexus data modification
if ($rsp_nexus_info) {
$HTML{app_purpose_menu} = build_app_purpose_menu($HTML{old_app_purpose});
$HTML{citizen_country_list} = build_country_list($HTML{old_nexus_validator}?$HTML{old_nexus_validator}:'--');
$HTML{us_nexus_form} = get_content("$path_templates/us_nexus_form.html", \%HTML);
}
my $template="modify_domain_extras.html";
print_form("$path_templates/$template",\%HTML);
}
# process data to modify domain extras
sub do_modify_domain_extras {
my ($ok_flag, $do_flag, $resultString);
if ($in{submit} =~ /cancel/i) {
main_menu("Changes cancelled");
exit;
}
if ($in{domain_auth_info} && $in{domain_auth_info} ne $in{old_domain_auth}) {
$do_flag = 1;
my $xcp_auth_info = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "domain_auth_info",
domain_auth_info => $in{domain_auth_info},
}
};
my $rsp_auth_info = $XML_Client->send_cmd( $xcp_auth_info );
if (not $rsp_auth_info->{is_success}) {
$resultString .= "Failed to modify domain auth code for $reg_domain : $rsp_auth_info->{response_text}
";
} else {
$resultString .= "Domain auth code modification successful for $reg_domain
";
$ok_flag = 1;
}
}
if ($in{forwarding_email} && $in{forwarding_email} ne $in{old_forwarding_email}) {
$do_flag = 1;
my $xcp_forwarding_email = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "forwarding_email",
forwarding_email => $in{forwarding_email},
}
};
my $rsp_forwarding_email = $XML_Client->send_cmd( $xcp_forwarding_email );
if (not $rsp_forwarding_email->{is_success}) {
$resultString .= "Failed to modify forwarding email for $reg_domain : $rsp_forwarding_email->{response_text}
";
} elsif ($rsp_forwarding_email->{response_code} == 250) {
$resultString .= "Forwarding email modification successfully submitted, could take up to ".time_to_wait().".
";
$ok_flag = 1;
} else {
$resultString .= "Forwarding email modification successful for $reg_domain
";
$ok_flag = 1;
}
}
if ($capabilities->{nexus_info}) {
my $xcp_nexus_info = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "nexus_info",
nexus => {
app_purpose => $in{app_purpose},
category => $in{nexus_category},
}
}
};
my $mod_flag = 0;
$mod_flag =1 if ($in{app_purpose} ne $in{old_app_purpose});
$mod_flag =1 if ($in{nexus_category} ne $in{old_nexus_category});
if ($in{nexus_category} =~ /^C3/) {
$xcp_nexus_info->{attributes}->{nexus}->{validator} = $in{nexus_validator};
$mod_flag =1 if ($in{nexus_validator} ne $in{old_nexus_validator});
}
if ($mod_flag) {
$do_flag = 1;
my $rsp_nexus_info = $XML_Client->send_cmd( $xcp_nexus_info );
if (not $rsp_nexus_info->{is_success}) {
$resultString .= "Failed to modify nexus info for $reg_domain : $rsp_nexus_info->{response_text}
";
} else {
$resultString .= "Nexus info modification successful for $reg_domain
";
$ok_flag = 1;
}
}
}
if (not $do_flag) {
main_menu("Domain Extras Data modification successful
");
} elsif ($ok_flag == 1) {
main_menu($resultString);
} else {
error_out($resultString);
}
}
# display domains a user owns
sub view_domains {
my (%HTML,$domain_name,$domain_html,$next_page,$previous_page);
my $page = $in{page};
if (not $page) { $page = 0 }
# get domains for a given user
my $xcp_request = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
page => $page,
type => "list",
with_encoding_types => 1,
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Failed attempt: $response->{response_text}\n");
exit;
}
my $remainder = $response->{attributes}->{remainder}; # are there more domains to show?
my %domains = map { %{ $_ } } @{ $response->{ attributes }{ ext_results } };
foreach my $domain ( keys %domains ) {
my $domain_name_race_obj = RACE::UndoRACE(
Domain => pack('A*', $domain ),
EncodingType => $UNIVERSAL_ENCODING_TYPE
);
$domains{ $domain }{ RACE } = $domain_name_race_obj->{ OriginalDomain };
$domains{ $domain }{ auto_renew } = $domains{ $domain }{ auto_renew } ? "Y" : "N";
$domains{ $domain }{ expiredate } =~ s/\s.*//; # get rid of the time
}
my $domain_html = '';
foreach my $domain ( sort { $domains{ $a }{RACE} cmp $domains{ $b }{RACE} } keys %domains ) {
my $domain_link;
if ( $reg_domain eq $domain ) {
$domain_link = $domains{ $domain }{ RACE };
} else {
$domain_link = qq($domains{$domain}{RACE});
}
$domain_html .= <$domain_link
$domains{ $domain }{ expiredate }
$domains{ $domain }{ auto_renew }
EOROW
}
# make navbar
my $navbar = "";
if ($page > 0 or $remainder) {
if ($page > 0) {
$previous_page = $page-1;
$navbar .= <
soon as possible.
If need to make emergency nameserver changes to your domain, please contact
support\@opensrs.org.
EOF
error_out($message);
exit;
}
my $xcp_request = {
action => "update",
object => "cookie",
cookie => $cookie,
attributes => {
reg_username => $reg_username,
reg_password => $reg_password,
domain => $reg_domain,
domain_new => $local_domain_race_obj->{ConvertedDomain},
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Failed attempt: $response->{response_text}\n");
exit;
}
$reg_domain = $domain;
$reg_f_owner = $response->{attributes}->{f_owner};
$reg_permission = $response->{attributes}->{permission};
$domain_count = $response->{attributes}->{domain_count};
$expiredate = $response->{attributes}->{expiredate};
$waiting_request = $response->{attributes}->{waiting_request};
my $managed_domain;
{
my $race_obj = RACE::UndoRACE(
Domain => pack("A*",$reg_domain),
EncodingType => $UNIVERSAL_ENCODING_TYPE
);
$managed_domain = $race_obj->{OriginalDomain};
}
validate();
main_menu("Now managing $managed_domain.");
}
# generaste menu for applying contact changes to other types/domains
sub make_global_menu {
my ($type,$html);
my ($f_owner,$permission,$current_type) = @_;
my $table_start = <
Also Apply these changes to:
EOF
foreach $type (sort keys %contact_types) {
if ((($type =~ /owner/i ) && ( $reg_domain =~ /ca$/ || $reg_domain =~ /uk$/ )) ||
(($type =~ /billing/i ) && ( $reg_domain =~ /ca$/ )))
{
next;
}
if (($f_owner or $permission & $PERMISSIONS{"F_MODIFY_$type"}) and ($type ne $current_type)) {
$html .= <
YES
NO
$contact_types{$type} Contact
EOF
}
}
#
# We can't normalize the data with .ca domains so we don't allow
# for universal changes with .ca domains.
#
# If it is in the organization contact page and if it is .uk domains,
# we do not allow for universal changes with .uk domains right now.
if ($reg_f_owner && ($domain_count > 1) && ! ($reg_domain =~ /uk$/ && $current_type=~ /owner/i) )
{
$html .= <All Domains ($domain_count)
EOF
}
my $table_end = "\n";
my ($menu);
if ($html) {
$menu = <
" : "";
print_form("$path_templates/manage_nameservers.html",\%HTML);
}
# change ip address for a given nameserver
sub do_manage_nameserver {
my $fqdn = $in{fqdn};
my $fqdn_race_obj = RACE::UndoRACE(Domain => pack('A*',$fqdn), EncodingType => $UNIVERSAL_ENCODING_TYPE);
my $new_fqdn = $in{new_fqdn};
my $new_fqdn_race_obj = RACE::DoRACE(Domain => $new_fqdn, EncodingType => $UNIVERSAL_ENCODING_TYPE);
if ( ( not $new_fqdn_race_obj ) || ($new_fqdn_race_obj->{Error}))
{
error_out("Could not encode the new nameserver name [". $new_fqdn_race_obj->{Error} ."]");
exit;
}
my $ip = $in{ip};
my $xcp_request = {
action => "",
object => "nameserver",
cookie => $cookie,
attributes => {
name => $fqdn,
ipaddress => $ip,
}
};
if ($in{submit} =~ /delete/i) {
$xcp_request->{action} = "delete";
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to delete nameserver: $response->{response_text}\n");
exit;
}
# response_code of 250 indicates that an asynchronous registry has
# received the request and the completion of the request will
# occur later.
if ( $response->{response_code} == 250 )
{
$waiting_request = $response->{attributes}->{waiting_request};
manage_nameservers("Nameserver deletion submitted, could take up to ".time_to_wait().".");
}
else
{
manage_nameservers("Nameserver $fqdn_race_obj->{OriginalDomain} deleted");
}
} else {
# only pass the new_fqdn param if it is changing
if ($fqdn ne $new_fqdn_race_obj->{ConvertedDomain})
{
$xcp_request->{attributes}->{new_name} = $new_fqdn_race_obj->{ConvertedDomain};
}
$xcp_request->{action} = "modify";
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to modify nameserver: $response->{response_text}\n");
exit;
}
# response_code of 250 indicates that an asynchronous registry has
# received the request and the completion of the request will
# occur later.
if ( $response->{response_code} == 250 )
{
$waiting_request = $response->{attributes}->{waiting_request};
if ($fqdn ne $new_fqdn_race_obj->{ConvertedDomain}) {
manage_nameservers("Nameserver rename modification submitted, could take up to ".time_to_wait().".");
} else {
manage_nameservers("Nameserver modification submitted to registry for processing.");
}
}
else
{
if ($fqdn ne $new_fqdn_race_obj->{ConvertedDomain} ) {
manage_nameservers("Nameserver $fqdn_race_obj->{OriginalDomain} renamed to $new_fqdn");
} else {
manage_nameservers("Nameserver $fqdn_race_obj->{OriginalDomain} successfully modified");
}
}
}
}
# display nameserver information for the current domain
sub modify_nameservers {
my (%fqdns,$fqdn,$ip,$key,$num,$ns_html,%HTML,$title,$add_ns,$fqdn_race_obj);
my $message = shift;
# retrieve nameserver info
my $xcp_request = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => 'nameservers',
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to retrieve nameserver information: $response->{response_text}\n");
exit;
}
$HTML{CGI} = $cgi;
foreach $key ( @{$response->{attributes}->{nameserver_list}} ) {
$fqdns{$key->{sortorder}} = 1;
}
my $count = 1;
foreach $key ( @{$response->{attributes}->{nameserver_list}} ) {
if ($count == 1) {
$title = "Primary";
} elsif ($count == 2) {
$title = "Secondary";
} else {
$title = "Nameserver $count";
}
$fqdn = $key->{name};
$ip = $key->{ipaddress};
$num = $key->{sortorder};
$fqdn_race_obj = RACE::UndoRACE(Domain => pack('A*',$fqdn), EncodingType => $UNIVERSAL_ENCODING_TYPE);
$ns_html .= <
$title:
EOF
# Add blanks to line up the 'remove checkbox' beside this ip
my $ip_nice = $ip . ' ' x (16 - length($ip));
$ns_html .= <
If you want to create or modify a nameserver which is based on $reg_domain_race_obj->{OriginalDomain} click here.
EOF
}
$HTML{NAMESERVERS} = $ns_html;
$HTML{MESSAGE} = $message ? "$message" : "";
print_form("$path_templates/modify_nameservers.html",\%HTML);
}
# process data to modify nameservers for the current domain
sub do_modify_nameservers {
my ($sortorder,$key,%remove_ids,$ns_data,$response,$fqdn_race_obj);
if ($in{submit} =~ /cancel/i) {
modify_nameservers("Changes cancelled\n");
exit;
}
$ns_data = [];
foreach $key (keys %in) {
if ($key =~ /^fqdn(\d+)$/) {
if (not exists $remove_ids{$1}) {
# remove blank nameserver entries
if (not $in{$key}) {
$remove_ids{$1} = 1;
next;
}
# don't include this fqdn if it's begin removed
next if $in{"remove_".$1};
$fqdn_race_obj = RACE::DoRACE (
Domain => $in{$key},
EncodingType => $UNIVERSAL_ENCODING_TYPE
);
push @{$ns_data}, { name => $fqdn_race_obj->{ConvertedDomain},
sortorder => $1,
action => "update" };
}
} elsif ($key =~ /^remove_(\d+)$/) {
push @{$ns_data}, { sortorder => $1,
action => "remove" };
}
}
my $xcp_request = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "nameserver_list",
nameserver_list => [ ],
},
};
if ( scalar @{$ns_data} )
{
# need to set the actio and object to lower case because
# send_cmd() transforms them up.
$xcp_request->{action} = lc $xcp_request->{action};
$xcp_request->{object} = lc $xcp_request->{object};
$xcp_request->{attributes}->{nameserver_list} = $ns_data;
$response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to update nameservers: $response->{response_text}\n");
exit;
}
}
# response_code of 250 indicates that an asynchronous registry has
# received the request and the completion of the request will
# occur later.
if ( $response->{response_code} == 250 ) {
$waiting_request = $response->{attributes}->{waiting_request};
modify_nameservers("Nameservers update for $reg_domain_race_obj->{OriginalDomain} successfully submitted, could take up to ".time_to_wait().".");
} elsif ( $response->{response_code} == 251 ) {
# removing a nameserver from a UK domain which is based upon that
# domain will cause any other domains using that nameserver to not
# function properly. In this case, send back a message to that affect.
# This applies at the moment to .uk nameservers, due to the way
# Nominet handles glue records.
modify_nameserver( $response->{ response_text } );
} else {
modify_nameservers("Nameservers for $reg_domain_race_obj->{OriginalDomain} updated successfully");
}
}
# add a nameserver for the current domain
sub add_nameserver {
my $fqdn = $in{fqdn};
my $fqdn_race_obj;
if (not $fqdn) {
error_out("Invalid hostname.
\n");
exit;
}
$fqdn_race_obj = RACE::DoRACE (Domain => $fqdn,
EncodingType => $UNIVERSAL_ENCODING_TYPE);
# add nameserver to domain
my $xcp_request = {
action => "modify",
object => "domain",
cookie => $cookie,
attributes => {
data => "nameserver_list",
nameserver_list => [
{ name => $fqdn_race_obj->{ConvertedDomain}, action => "add" },
]
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to add nameserver: $response->{response_text}\n");
exit;
}
# response_code of 250 indicates that an asynchronous registry has
# received the request and the completion of the request will
# occur later.
if ( $response->{response_code} == 250 )
{
$waiting_request = $response->{attributes}->{waiting_request};
modify_nameservers("Nameserver addition successfully submitted, could take up to ".time_to_wait().".");
}
else
{
modify_nameservers("Nameserver added.");
}
}
sub do_create_nameserver {
my $domain = $in{domain};
my $hostname = $in{hostname};
my $ip = $in{ip};
my $fqdn = "$hostname.$domain";
my $new_fqdn_race_obj = RACE::DoRACE( Domain => $fqdn,
EncodingType => $UNIVERSAL_ENCODING_TYPE );
if ( not $new_fqdn_race_obj || $new_fqdn_race_obj->{Error})
{
error_out("Could not RACE nameserver [". $new_fqdn_race_obj->{Error} ."]");
exit;
}
my $xcp_request = {
action => "create",
object => "nameserver",
cookie => $cookie,
attributes => {
name => $new_fqdn_race_obj->{ConvertedDomain},
ipaddress => $ip,
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to create nameserver: $response->{response_text}\n");
exit;
}
# response_code of 250 indicates that an asynchronous registry has
# received the request and the completion of the request will
# occur later.
#
# A response_code of 251 indicated that the nameserver has been created
# in the OSRS database, but will not be usable by other domains until it
# is attached to the parent domain.
if ( $response->{response_code} == 250 ) {
$waiting_request = $response->{attributes}->{waiting_request};
manage_nameservers("Name Server Creation successfully submitted, could take up to ".time_to_wait().".");
} elsif ( $response->{ response_code } == 251 ) {
manage_nameservers( $response->{ response_text } );
} else {
manage_nameservers("Name Server Created");
}
}
sub manage_profile {
my (%HTML);
# only allow the domain owner to access this routine
if (not $reg_f_owner) {
error_out("You do not have permission to access this feature.\n");
exit;
}
$HTML{CGI} = $cgi;
print_form("$path_templates/manage_profile.html",\%HTML);
}
sub change_ownership {
my (%HTML);
# only allow the domain owner to access this routine
if (not $reg_f_owner) {
error_out("You do not have permission to access this feature.\n");
exit;
}
$HTML{CGI} = $cgi;
print_form("$path_templates/change_ownership.html",\%HTML);
}
sub do_change_ownership {
# only allow the domain owner to access this routine
if (not $reg_f_owner) {
error_out("You do not have permission to access this feature.\n");
exit;
}
my $username = lc $in{reg_username};
my $password = $in{reg_password};
my $confirm_password = $in{confirm_password};
my $flag_use_profile = $in{flag_use_profile};
my $flag_move_all_domains = $in{flag_move_all_domains};
my $domain = $in{domain};
my ($xcp_request, $response);
if (not $username) {
error_out("Please provide a username.\n");
exit;
} elsif ($username !~ /^[a-z0-9]+$/) {
error_out("Invalid syntax for new username.\n");
exit;
} elsif ($password ne $confirm_password) {
error_out("Password mismatch.\n");
exit;
} elsif (not $password) {
error_out("Please provide a password.\n");
exit;
} elsif ($flag_use_profile and not $domain) {
error_out("Please provide a domain to match the profile with.\n");
exit;
}
my $domain_race_obj = RACE::DoRACE( Domain => $domain,
EncodingType => $UNIVERSAL_ENCODING_TYPE );
if ( ( not $domain_race_obj ) ||
( $domain_race_obj->{Error} ) )
{
error("Could not race encode the domain [".
$domain_race_obj->{Error}."]");
exit;
}
$xcp_request = {
action => "change",
object => "ownership",
cookie => $cookie,
attributes => {
username => $username,
password => $password,
}
};
if ($flag_move_all_domains) {
$xcp_request->{attributes}->{move_all} = 1;
}
if ($flag_use_profile) {
$xcp_request->{attributes}->{reg_domain} = $domain_race_obj->{ConvertedDomain};
}
$response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to change domain's ownership: $response->{response_text}.\n");
exit;
}
# make them logout
# note that the cookie here is both needed for authentication and
# for the command itself, hence why it appears twice in the request data
$XML_Client->send_cmd( {
action => "delete",
object => "cookie",
cookie => $cookie,
attributes => {
cookie => $cookie,
},
} );
# make them login again so they are managing the domain under the new
# profile
$in{reg_domain} = $reg_domain;
login("Ownership change successful. Now logged in as new owner.\n");
}
# retrieve subuser information
sub get_subuser {
my ($sub_id,$sub_username,$sub_permission);
# get subuser for a given user
my $xcp_request = {
action => "get",
object => "subuser",
cookie => $cookie,
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Unable to retrieve subuser information: $response->{response_text}\n");
exit;
}
$sub_id = $response->{attributes}->{id};
$sub_username = $response->{attributes}->{username};
$sub_permission = $response->{attributes}->{permission};
return($sub_id,$sub_username,$sub_permission);
}
# display waiting request history for this domain
sub view_waiting_history {
my (%HTML,$record);
my $waiting_actions = {
enhanced_update_nameservers => "Nameserver Update",
update_nameservers => "Nameserver Update",
add_nameserver => "Nameserver Update",
remove_nameserver => "Nameserver Update",
modify_contact_info => "Modify Contact Info",
sw_register => "Registration",
register_domain => "Registration",
process_sw_order => "Registration",
ukstatus => "Transfer",
renew_domain => "Renewal",
};
my $stati = {
};
my $page = $in{page};
if (not $page) { $page = 0 }
# get domains for a given user
my $xcp_request = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => "waiting_history",
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
if (not $response->{is_success}) {
error_out("Failed attempt: $response->{response_text}\n");
exit;
}
my $record_count = $response->{attributes}->{record_count};
my @records = @{$response->{attributes}->{waiting_history}};
$HTML{waiting_history} = "";
if ( not scalar @records )
{
$HTML{waiting_history} .= <No history found
EOF
}
else
{
foreach $record (@records) {
my $w_action = $waiting_actions->{$record->{action}};
$w_action||=$record->{action}; # if undefined or new action
$HTML{waiting_history} .= <$w_action
$record->{request_status}
$record->{response_time}
$record->{response_code}
$record->{response_text}
EOF
}
}
$HTML{CGI} = $cgi;
print_form("$path_templates/waiting_history.html",\%HTML);
}
###########################################################################
# print a html header
sub print_header {
if (not $flag_header_sent) {
print "Content-type: text/html\n\n";
$flag_header_sent = 1;
}
}
##########################################################################
# substitute values on the specified template and print it to the client
# an optional 'type' arg can be passed: 'framed' specifies to pull in base.html
# as the outer frame and the given template as the inner frame
# 'single' specifies to use the given template alone
# the default behavior is 'framed'
sub print_form {
my ($type,$content,$template_html);
print_header();
my @args = @_;
my ($template,$HTML) = @args[0,1];
if ($args[2]) { $type = $args[2] }
else { $type = 'framed' }
if (not $domain_count) {
$domain_count = 0;
}
# show domain search box if they have multiple domains
if ($reg_f_owner and $domain_count > 1) {
my $link;
if ( $MANAGE{ allow_renewals } ) {
$link = qq($domain_count Total);
} else {
$link = qq($domain_count Total
);
}
$HTML->{SEARCH_BOX} = <
EOF
}
$reg_domain_race_obj = RACE::UndoRACE (Domain => pack('A*',$reg_domain),
EncodingType => $UNIVERSAL_ENCODING_TYPE);
$HTML->{DOMAIN_NAME} = $reg_domain_race_obj->{OriginalDomain};
$HTML->{EXPIREDATE} = $expiredate;
$HTML->{WAITING_REQUEST} = $waiting_request;
$HTML->{TOP_NAVBAR} = make_top_navbar();
if ($type eq 'framed') {
$HTML->{AUTORENDATA} = "";
if ($MANAGE{allow_auto_renewal_message}){
my $xcp_request = {
action => "get",
object => "domain",
cookie => $cookie,
attributes => {
type => "auto_renew_flag",
}
};
my $response = $XML_Client->send_cmd( $xcp_request );
my $flag = $response->{attributes}->{auto_renew};
if($flag){
my $expiry_epoch = get_expiry_epoch_time($expiredate);
my $new_epoch = $expiry_epoch - 30 * 86400;
$HTML->{AUTORENDATA} = get_date_from_epoch($new_epoch, "stripped");
$HTML->{AUTORENDATA} = get_content("$path_templates/base_autoren.html", $HTML);
}
}
$HTML->{CONTENT} = get_content("$template",$HTML);
if($MANAGE{allow_renewals}){ get_warning_type(); }
if ((defined $t_mode) and $t_mode) {
$template_html = "base2.html";
if (($t_mode == $T_EXPIRED) || ($t_mode == ($T_EXPIRED + $T_EXPIRING))) {
$HTML->{EXPIRED} = "Click here to see the list of names that will be deleted if not renewed.";
}
if (($t_mode == $T_EXPIRING) || ($t_mode == ($T_EXPIRED + $T_EXPIRING))) {
$HTML->{EXPIRING} = "Click here to see the list of names expiring within the next $notice_days days.";
}
} else {
$template_html = "base.html";
}
$content .= get_content("$path_templates/$template_html",$HTML);
} else {
$content .= get_content("$template", $HTML);
}
print $content;
}
sub make_top_navbar {
my ($navbar);
if ($reg_f_owner) {
$navbar = "Profile";
$navbar .= <
Domain Locking
| Logout
EOF
} else {
$navbar .= <
Domain Locking
| Logout
EOF
}
$navbar =~ /(.+Name Servers<\/a>)(.*)/s;
if ($capabilities->{domain_extras}) {
$navbar = $1 . " | Domain Extras<\/a>\n" . $2;
} else {
$navbar = $1 . " | Domain Extras\n" . $2;
}
return $navbar;
} else {
# these first two are never available for sub-users
$navbar .= "Profile\n";
# The owner contact type cannot be modified if the
# domain ends with uk
# if ( ( $reg_permission & $PERMISSIONS{f_modify_owner} ) &&
# ( $reg_domain !~ /uk$/ ) ) {
if ($reg_permission & $PERMISSIONS{f_modify_owner}) {
$navbar .= <
soon as possible.