<?php
# Copyright (c) 2012-2013, AllWorldIT
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# Official Website:
# http://devlabs.linuxassist.net/projects/whmcs-coza-epp

# Lead developer: 
# Nigel Kukard <nkukard@lbsd.net>


# ! ! P L E A S E   N O T E  ! !

# * If you make changes to this file, please consider contributing 
#   anything useful back to the community. Don't be a sour prick.

# * If you find this module useful please consider making a 
#   donation to support modules like this.


# WHMCS hosting, theming, module development, payment gateway 
# integration, customizations and consulting all available from 
# http://allworldit.com



# Configuration array
function cozaepp_getConfigArray() {
	$configarray = array(
		"Username" => array( "Type" => "text", "Size" => "20", "Description" => "Enter your username here" ),
		"Password" => array( "Type" => "password", "Size" => "20", "Description" => "Enter your password here" ),
		"Server" => array( "Type" => "text", "Size" => "20", "Description" => "Enter EPP Server Address" ),
		"Port" => array( "Type" => "text", "Size" => "20", "Description" => "Enter EPP Server Port" ),
		"SSL" => array( "Type" => "yesno" ),
		"Certificate" => array( "Type" => "text", "Description" => "Path of certificate .pem" )
	);
	return $configarray;
}



# Function to return current nameservers
function cozaepp_GetNameservers($params) {
	# Grab variables	
	$sld = $params["sld"];
	$tld = $params["tld"];
	$domain = "$sld.$tld";


	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'GetNameservers/EPP: '.$client->toString();
		return $values;
	}

	# Get list of nameservers for domain
	$result = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:info>
			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name hosts="all">'.$domain.'</domain:name>
			</domain:info>
		</epp:info>
	</epp:command>
</epp:epp>
');
	# Parse XML result
	$doc = new DOMDocument();
	$doc->preserveWhiteSpace = false;
	$doc->loadXML($result);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check the result is ok
	if($coderes != '1000') {
		$values["error"] = "GetNameservers/domain-info($domain): Code ($coderes) $msg";
		return $values;
	}

	# Grab hostname array
	$ns = $doc->getElementsByTagName('hostName');
	# Extract nameservers & build return result
	$i = 1;	$values = array();
	foreach ($ns as $nn) {
		$values["ns{$i}"] = $nn->nodeValue;
		$i++;
	}

	$values["status"] = $msg;

	return $values;
}



# Function to save set of nameservers
function cozaepp_SaveNameservers($params) {
	# Grab variables
	$sld = $params["sld"];
	$tld = $params["tld"];


	# Generate XML for nameservers
	if ($nameserver1 = $params["ns1"]) { 
		$add_hosts = '
<domain:hostAttr>
	<domain:hostName>'.$nameserver1.'</domain:hostName>
</domain:hostAttr>
';
	}
	if ($nameserver2 = $params["ns2"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver2.'</domain:hostName>
</domain:hostAttr>
';
	}
	if ($nameserver3 = $params["ns3"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver3.'</domain:hostName>
</domain:hostAttr>
';
	}
	if ($nameserver4 = $params["ns4"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver4.'</domain:hostName>
</domain:hostAttr>';
	}
	if ($nameserver5 = $params["ns5"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver5.'</domain:hostName>
</domain:hostAttr>';
	}
	
	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'SaveNameservers/EPP: '.$client->toString();
		return $values;
	}

	# Grab list of current nameservers
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" 
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:info>
			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name hosts="all">'.$sld.'.'.$tld.'</domain:name>
			</domain:info>
		</epp:info>
	</epp:command>
</epp:epp>
');
	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check if result is ok
	if($coderes != '1000') {
		$values["error"] = "SaveNameservers/domain-info($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	# Generate list of nameservers to remove
	$hostlist = $doc->getElementsByTagName('hostName');
	foreach ($hostlist as $host) {
		$rem_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$host->nodeValue.'</domain:hostName>
</domain:hostAttr>
';
	}

	# Build request
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" 
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:cozadomain="http://co.za/epp/extensions/cozadomain-1-0"
		xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:update>
			<domain:update>
				<domain:name>'.$sld.'.'.$tld.'</domain:name>
				<domain:add>
					<domain:ns>'.$add_hosts.' </domain:ns>
				</domain:add>								  
				<domain:rem>
					<domain:ns>'.$rem_hosts.'</domain:ns>
				</domain:rem>
			</domain:update>
		</epp:update>
		<epp:extension>
			<cozadomain:update xsi:schemaLocation="http://co.za/epp/extensions/cozadomain-1-0 coza-domain-1.0.xsd">
			<cozadomain:chg><cozadomain:autorenew>false</cozadomain:autorenew></cozadomain:chg></cozadomain:update>
		</epp:extension>
	</epp:command>
</epp:epp>
');

	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check if result is ok
	if($coderes != '1001') {
		$values["error"] = "SaveNameservers/domain-update($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values['status'] = "Domain update Pending. Based on .co.za policy, the estimated time taken is around 5 days.";

	return $values;
}



# NOT IMPLEMENTED
function cozaepp_GetRegistrarLock($params) {
	# Grab variables
	$sld = $params["sld"];
	$tld = $params["tld"];


	# Get lock status
	$lock = 0;
	if ($lock=="1") {
		$lockstatus="locked";
	} else {
		$lockstatus="unlocked";
	}
	return $lockstatus;
}



# NOT IMPLEMENTED
function cozaepp_SaveRegistrarLock($params) {
	$values["error"] = "SaveRegistrarLock: Current co.za policy does not allow for the addition of client-side statuses on domains.";
	return $values;
}



# Function to register domain
function cozaepp_RegisterDomain($params) {
	# Grab varaibles
	$sld = $params["sld"];
	$tld = $params["tld"];
	$regperiod = $params["regperiod"];

	# Get registrant details	
	$RegistrantFirstName = $params["firstname"];
	$RegistrantLastName = $params["lastname"];
	$RegistrantAddress1 = $params["address1"];
	$RegistrantAddress2 = $params["address2"];
	$RegistrantCity = $params["city"];
	$RegistrantStateProvince = $params["state"];
	$RegistrantPostalCode = $params["postcode"];
	$RegistrantCountry = $params["country"];
	$RegistrantEmailAddress = $params["email"];
	$RegistrantPhone = $params["phonenumber"];
	# Get admin details
	$AdminFirstName = $params["adminfirstname"];
	$AdminLastName = $params["adminlastname"];
	$AdminAddress1 = $params["adminaddress1"];
	$AdminAddress2 = $params["adminaddress2"];
	$AdminCity = $params["admincity"];
	$AdminStateProvince = $params["adminstate"];
	$AdminPostalCode = $params["adminpostcode"];
	$AdminCountry = $params["admincountry"];
	$AdminEmailAddress = $params["adminemail"];
	$AdminPhone = $params["adminphonenumber"];
	# Our details
	$contactid = $RegistrantFirstName.$params['userid'];


	# Generate XML for namseverss
	if ($nameserver1 = $params["ns1"]) { 
		$add_hosts = '
<domain:hostAttr>
	<domain:hostName>'.$nameserver1.'</domain:hostName>
</domain:hostAttr>
';
	}
	if ($nameserver2 = $params["ns2"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver2.'</domain:hostName>
</domain:hostAttr>
';
	}
	if ($nameserver3 = $params["ns3"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver3.'</domain:hostName>
</domain:hostAttr>
';
	}
	if ($nameserver4 = $params["ns4"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver4.'</domain:hostName>
</domain:hostAttr>';
	}
	if ($nameserver5 = $params["ns5"]) { 
		$add_hosts .= '
<domain:hostAttr>
	<domain:hostName>'.$nameserver5.'</domain:hostName>
</domain:hostAttr>';
	}

	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'RegisterDomain/EPP: '.$client->toString();
		return $values;
	}

	# Send registration
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
		xmlns:contact="urn:ietf:params:xml:ns:contact-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:create>
			<contact:create xsi:schemaLocation="urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd">
				<contact:id>'.$contactid.'</contact:id>
				<contact:postalInfo type="loc">
					<contact:name>'.$RegistrantFirstName.' '.$RegistrantLastName.'</contact:name>
					<contact:addr>
						<contact:street>'.$RegistrantAddress1.'</contact:street>
						<contact:street>'.$RegistrantAddress2.'</contact:street>
						<contact:city>'.$RegistrantCity.'</contact:city>
						<contact:sp>'.$RegistrantStateProvince.'</contact:sp>
						<contact:pc>'.$RegistrantPostalCode.'</contact:pc>
						<contact:cc>'.$RegistrantCountry.'</contact:cc>
					</contact:addr>
				</contact:postalInfo>
				<contact:voice>'.$params["phonenumber"].'</contact:voice>
				<contact:fax></contact:fax>
				<contact:email>'.$RegistrantEmailAddress.'</contact:email>
				<contact:authInfo>
					<contact:pw>AxA8AjXbAH'.rand().rand().'</contact:pw>
				</contact:authInfo>
			</contact:create>
		</epp:create>
	</epp:command>
</epp:epp>
');

	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes == '1000') {
		$values['contact'] = 'Contact Created';
	} else if($coderes == '2302') { 
		$values['contact'] = 'Contact Already exists';
	} else { 
		$values["error"] = "RegisterDomain/contact-create($contactid): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" 
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:cozadomain="http://co.za/epp/extensions/cozadomain-1-0"
		xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:create>
			<domain:create xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name>'.$sld.'.'.$tld.'</domain:name>
				<domain:ns>'.$add_hosts.'</domain:ns>
				<domain:registrant>'.$contactid.'</domain:registrant>
				<domain:authInfo>
					<domain:pw>coza</domain:pw>
				</domain:authInfo>
			</domain:create>
		</epp:create>
		<epp:extension>
			<cozadomain:create>
				<cozadomain:autorenew>false</cozadomain:autorenew>
			</cozadomain:create>
		</epp:extension>
	</epp:command>
</epp:epp>
');
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes != '1000') {
		$values["error"] = "RegisterDomain/domain-create($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	return $values;
}



# Function to transfer a domain
function cozaepp_TransferDomain($params) {
	# Grab variables
	$testmode = $params["TestMode"];
	$sld = $params["sld"];
	$tld = $params["tld"];

	# Domain info	
	$regperiod = $params["regperiod"];
	$transfersecret = $params["transfersecret"];
	$nameserver1 = $params["ns1"];
	$nameserver2 = $params["ns2"];
	# Registrant Details
	$RegistrantFirstName = $params["firstname"];
	$RegistrantLastName = $params["lastname"];
	$RegistrantAddress1 = $params["address1"];
	$RegistrantAddress2 = $params["address2"];
	$RegistrantCity = $params["city"];
	$RegistrantStateProvince = $params["state"];
	$RegistrantPostalCode = $params["postcode"];
	$RegistrantCountry = $params["country"];
	$RegistrantEmailAddress = $params["email"];
	$RegistrantPhone = $params["phonenumber"];
	# Admin details
	$AdminFirstName = $params["adminfirstname"];
	$AdminLastName = $params["adminlastname"];
	$AdminAddress1 = $params["adminaddress1"];
	$AdminAddress2 = $params["adminaddress2"];
	$AdminCity = $params["admincity"];
	$AdminStateProvince = $params["adminstate"];
	$AdminPostalCode = $params["adminpostcode"];
	$AdminCountry = $params["admincountry"];
	$AdminEmailAddress = $params["adminemail"];
	$AdminPhone = $params["adminphonenumber"];
	# Our details
	$contactid = $RegistrantFirstName.$params['userid'];


	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'TransferDomain/EPP: '.$client->toString();
		return $values;
	}

	# Initiate transfer
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
	<epp:command>
		<epp:transfer op="request">
			<domain:transfer>
				<domain:name>'.$sld.'.'.$tld.'</domain:name>
			</domain:transfer>
		</epp:transfer>
	</epp:command>
</epp:epp>');

	# Parse XML result	
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# We should get a 1001 back
	if($coderes != '1001') {
		$values["error"] = "TransferDomain/domain-transfer($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	# Create contact details
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
		xmlns:contact="urn:ietf:params:xml:ns:contact-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:create>
			<contact:create xsi:schemaLocation="urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd">
				<contact:id>'.$contactid.'</contact:id>
				<contact:postalInfo type="loc">
					<contact:name>'.$RegistrantFirstName.' '.$RegistrantLastName.'</contact:name>
					<contact:addr>
						<contact:street>'.$RegistrantAddress1.'</contact:street>
						<contact:street>'.$RegistrantAddress2.'</contact:street>
						<contact:city>'.$RegistrantCity.'</contact:city>
						<contact:sp>'.$RegistrantStateProvince.'</contact:sp>
						<contact:pc>'.$RegistrantPostalCode.'</contact:pc>
						<contact:cc>'.$RegistrantCountry.'</contact:cc>
					</contact:addr>
				</contact:postalInfo>
				<contact:voice>'.$params["phonenumber"].'</contact:voice>
				<contact:fax></contact:fax>
				<contact:email>'.$RegistrantEmailAddress.'</contact:email>
				<contact:authInfo>
					<contact:pw>AxA8AjXbAH'.rand().rand().'</contact:pw>
				</contact:authInfo>
			</contact:create>
		</epp:create>
	</epp:command>
</epp:epp>
');
	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes == '1000') {
		$contactid = $RegistrantFirstName.$params['userid'];
		$values['contact'] = 'Contact Created';
	} else if($coderes == '2302') {
		$contactid = $RegistrantFirstName.$params['userid'];
		$values['contact'] = 'Contact Already exists';
	} else {
		$values["error"] = "TransferDomain/contact-create($contactid): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	return $values;
}



# Function to renew domain
function cozaepp_RenewDomain($params) {
	# Grab variables
	$sld = $params["sld"];
	$tld = $params["tld"];
	$regperiod = $params["regperiod"];


	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'RenewDomain/EPP: '.$client->toString();
		return $values;
	}

	# Send renewal request
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" 
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:info>
			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name hosts="all">'.$sld.'.'.$tld.'</domain:name>
			</domain:info>
		</epp:info>
	</epp:command>
</epp:epp>
');

	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes != '1000') {
		$values["error"] = "RenewDomain/domain-info($sld.$tld)): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	# Sanitize expiry date
	$expdate = substr($doc->getElementsByTagName('exDate')->item(0)->nodeValue,0,10);
	if (empty($expdate)) {
		$values["error"] = "RenewDomain/domain-info($sld.$tld): Domain info not available";
		return $values;
	}

	# Send request to renew
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
	<epp:command>
		<epp:renew>
			<domain:renew>
				<domain:name>'.$sld.'.'.$tld.'</domain:name>
				<domain:curExpDate>'.$expdate.'</domain:curExpDate>
			</domain:renew>
		</epp:renew>
	</epp:command>
</epp:epp>
');

	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes != '1000') {
		$values["error"] = "RenewDomain/domain-renew($sld.$tld,$expdate): Code (".$coderes.") ".$msg;
		return $values;
	}

	$values["status"] = $msg;

	# If error, return the error message in the value below
	return $values;
}



# Function to grab contact details
function cozaepp_GetContactDetails($params) {
	# Grab variables	
	$sld = $params["sld"];
	$tld = $params["tld"];


	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'GetContactDetails/EPP: '.$client->toString();
		return $values;
	}

	# Grab domain info
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" 
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:info>
			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name hosts="all">'.$sld.'.'.$tld.'</domain:name>
			</domain:info>
		</epp:info>
	</epp:command>
</epp:epp>
');

	# Parse XML result		
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check result
	if($coderes != '1000') {
		$values["error"] = "GetContactDetails/domain-info($sld.$tld): Code (".$coderes.") ".$msg;
		return $values;
	}

	# Grab contact info
	$registrant = $doc->getElementsByTagName('registrant')->item(0)->nodeValue;
	if (empty($registrant)) {
		$values["error"] = "GetContactDetails/domain-info($sld.$tld): Registrant info not available";
		return $values;
	}

	# Grab contact info
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
	<epp:command>
		<epp:info>
			<contact:info>
				<contact:id>'.$registrant.'</contact:id>
			</contact:info>
		</epp:info>
	</epp:command>
</epp:epp>
');
	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check result
	if($coderes != '1000') {
		$values["error"] = "GetContactDetails/contact-info($registrant): Code (".$coderes.") ".$msg;
		return $values;
	}

	# Setup return values
	$values["Registrant"]["Contact Name"] = $doc->getElementsByTagName('name')->item(0)->nodeValue;
	$values["Registrant"]["Organisation"] = $doc->getElementsByTagName('org')->item(0)->nodeValue;
	$values["Registrant"]["Address line 1"] = $doc->getElementsByTagName('street')->item(0)->nodeValue;
	$values["Registrant"]["Address line 2"] = $doc->getElementsByTagName('street')->item(1)->nodeValue;
	$values["Registrant"]["TownCity"] = $doc->getElementsByTagName('city')->item(0)->nodeValue;
	$values["Registrant"]["State"] = $doc->getElementsByTagName('sp')->item(0)->nodeValue;
	$values["Registrant"]["Zip code"] = $doc->getElementsByTagName('pc')->item(0)->nodeValue;
	$values["Registrant"]["Country Code"] = $doc->getElementsByTagName('cc')->item(0)->nodeValue;
	$values["Registrant"]["Phone"] = $doc->getElementsByTagName('voice')->item(0)->nodeValue;
	$values["Registrant"]["Email"] = $doc->getElementsByTagName('email')->item(0)->nodeValue;

	return $values;
}



# Function to save contact details
function cozaepp_SaveContactDetails($params) {
	# Grab variables
	$tld = $params["tld"];
	$sld = $params["sld"];
	# Registrant details
	$registrant_name = $params["contactdetails"]["Registrant"]["Contact Name"];
	$registrant_org = $params["contactdetails"]["Registrant"]["Organisation"];
	$registrant_address1 =  $params["contactdetails"]["Registrant"]["Address line 1"];
	$registrant_address2 = $params["contactdetails"]["Registrant"]["Address line 2"];
	$registrant_town = $params["contactdetails"]["Registrant"]["TownCity"];
	$registrant_state = $params["contactdetails"]["Registrant"]["State"];
	$registrant_zipcode = $params["contactdetails"]["Registrant"]["Zip code"];
	$registrant_countrycode = $params["contactdetails"]["Registrant"]["Country Code"];
	$registrant_phone = $params["contactdetails"]["Registrant"]["Phone"];
	#$registrant_fax = '',
	$registrant_email = $params["contactdetails"]["Registrant"]["Email"];


	# Get client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'SaveContactDetails/EPP: '.$client->toString();
		return $values;
	}

	# Grab domain info
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" 
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:info>
			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name hosts="all">'.$sld.'.'.$tld.'</domain:name>
			</domain:info>
		</epp:info>
	</epp:command>
</epp:epp>
');
	# Parse XML	result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes != '1000') {
		$values["error"] = "SaveContactDetails/domain-info($sld.$tld): Code (".$coderes.") ".$msg;
		return $values;
	}

	$values["status"] = $msg;

	# Time to do the update
	$registrant = $doc->getElementsByTagName('registrant')->item(0)->nodeValue;

	# Save contact details
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
	<epp:command>
		<epp:update>
			<contact:update>
				<contact:id>'.$registrant.'</contact:id>
				<contact:chg>
					<contact:postalInfo type="loc">
						<contact:name>'.$registrant_name.'</contact:name>
						<contact:org>'.$registrant_org.'</contact:org>
						<contact:addr>
							<contact:street>'.$registrant_address1.'</contact:street>
							<contact:street>'.$registrant_address2.'</contact:street>
							<contact:city>'.$registrant_town.'</contact:city>
							<contact:sp>'.$registrant_state.'</contact:sp>
							<contact:pc>'.$registrant_zipcode.'</contact:pc>
							<contact:cc>'.$registrant_countrycode.'</contact:cc>
						</contact:addr>
						</contact:postalInfo>
						<contact:voice>'.$registrant_phone.'</contact:voice>
						<contact:fax></contact:fax>
						<contact:email>'.$registrant_email.'</contact:email>
				</contact:chg>
			</contact:update>
		</epp:update>
	</epp:command>
</epp:epp>
');

	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	if($coderes != '1001') {
		$values["error"] = "SaveContactDetails/contact-update($registrant): Code ($coderes) $msg";
		return $values;
	}

	$values["status"] = $msg;

	return $values;
}



# NOT IMPLEMENTED
function cozaepp_GetEPPCode($params) {
	# Grab variables
	$username = $params["Username"];
	$password = $params["Password"];
	$testmode = $params["TestMode"];
	$sld = $params["sld"];
	$tld = $params["tld"];

	$values["eppcode"] = '';

	# If error, return the error message in the value below
	//$values["error"] = 'error';
	return $values;
}



# Function to register nameserver
function cozaepp_RegisterNameserver($params) {
	# Grab varaibles
	$username = $params["Username"];
	$password = $params["Password"];
	$testmode = $params["TestMode"];
	$sld = $params["sld"];
	$tld = $params["tld"];
	$nameserver = $params["nameserver"];
	$ipaddress = $params["ipaddress"];


	# Grab client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'SaveNameservers/EPP: '.$client->toString();
		return $values;
	}

	# Register nameserver
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <epp:command>
    <epp:update>
      <domain:update>
		<domain:name>'.$sld.'.'.$tld.'</domain:name>
        <domain:add>
          <domain:ns>
            <domain:hostAttr>
              <domain:hostName>'.$nameserver.'</domain:hostName>
              <domain:hostAddr ip="v4">'.$ipaddress.'</domain:hostAddr>
            </domain:hostAttr>
          </domain:ns>
        </domain:add>
      </domain:update>
    </epp:update>
  </epp:command>
</epp:epp>
');
	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check if result is ok
	if($coderes != '1001') {
		$values["error"] = "RegisterNameserver/domain-update($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values['status'] = $msg;

	return $values;
}



# Modify nameserver
function cozaepp_ModifyNameserver($params) {
	# Grab variables
	$username = $params["Username"];
	$password = $params["Password"];
	$testmode = $params["TestMode"];
	$tld = $params["tld"];
	$sld = $params["sld"];
	$nameserver = $params["nameserver"];
	$currentipaddress = $params["currentipaddress"];
	$newipaddress = $params["newipaddress"];


	# Grab client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'SaveNameservers/EPP: '.$client->toString();
		return $values;
	}

	# Modify nameserver
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <epp:command>
    <epp:update>
      <domain:update>
		<domain:name>'.$sld.'.'.$tld.'</domain:name>
        <domain:add>
          <domain:ns>
            <domain:hostAttr>
              <domain:hostName>'.$nameserver.'</domain:hostName>
              <domain:hostAddr ip="v4">'.$newipaddress.'</domain:hostAddr>
            </domain:hostAttr>
          </domain:ns>
        </domain:add>
      </domain:update>
    </epp:update>
  </epp:command>
</epp:epp>
');
	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check if result is ok
	if($coderes != '1001') {
		$values["error"] = "ModifyNameserver/domain-update($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values['status'] = $msg;

	return $values;
}


# Delete nameserver
function cozaepp_DeleteNameserver($params) {
	# Grab variables
	$username = $params["Username"];
	$password = $params["Password"];
	$testmode = $params["TestMode"];
	$tld = $params["tld"];
	$sld = $params["sld"];
	$nameserver = $params["nameserver"];


	# Grab client instance
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'SaveNameservers/EPP: '.$client->toString();
		return $values;
	}

	# If we were given   hostname.  blow away all of the stuff behind it and allow us to remove hostname
	$nameserver = preg_replace('/\.\.\S+/','',$nameserver);

	# Delete nameserver
	$request = $client->request('
<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
  <epp:command>
    <epp:update>
      <domain:update>
		<domain:name>'.$sld.'.'.$tld.'</domain:name>
        <domain:rem>
          <domain:ns>
            <domain:hostAttr>
              <domain:hostName>'.$nameserver.'</domain:hostName>
            </domain:hostAttr>
          </domain:ns>
        </domain:rem>
      </domain:update>
    </epp:update>
  </epp:command>
</epp:epp>
');
	# Parse XML result
	$doc= new DOMDocument();
	$doc->loadXML($request);
	# Pull off status
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check if result is ok
	if($coderes != '1001') {
		$values["error"] = "DeleteNameserver/domain-update($sld.$tld): Code ($coderes) $msg";
		return $values;
	}

	$values['status'] = $msg;

	return $values;
}


# Function to return meaningful message from response code
function _cozaepp_message($code) {

	return "Code $code";

}


# Ack a POLL message
function _cozaepp_ackpoll($client,$msgid) {
	# Ack poll message
	$request = $client->request('
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
	<command>
		<poll op="ack" msgID="'.$msgid.'"/>
	</command>
</epp>
');
	# Check for error
	if (PEAR::isError($output)) {
		return $output;
	}

	# Decipher XML
	$doc = new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;

	# Check result
	if($coderes != '1301' && $coderes != '1300') {
		return new PEAR_Error("ackpoll/poll-ack($id): Code ($coderes) $msg");
	}
}


# Function to create internal COZA EPP request
function _cozaepp_Client() {
	# Setup include dir
	$include_path = ROOTDIR . '/modules/registrars/cozaepp';
	set_include_path($include_path . PATH_SEPARATOR . get_include_path());
	# Include EPP stuff we need
	require_once 'Net/EPP/Client.php';
	require_once 'Net/EPP/Protocol.php';


	# Grab module parameters
	$params = getregistrarconfigoptions('cozaepp');

	# Are we using ssl?
	$use_ssl = false;
	if (isset($params['SSL']) && $params['SSL'] == 'on') {
		$use_ssl = true;
	}
	# Set certificate if we have one
 	if ($use_ssl && !empty($params['Certificate'])) {
		if (!file_exists($params['Certificate'])) {
			return PEAR_Error("Certificate file does not exist");
		}

		# Create SSL context
		$context = stream_context_create();
		stream_context_set_option($context, 'ssl', 'local_cert', $params['Certificate']);
	}

	# Create EPP client
	$client = new Net_EPP_Client();
	# Connect
	$res = $client->connect($params['Server'], $params['Port'], 30, $use_ssl, $context);
	# Check for error
	if (PEAR::isError($res)) {
		return $res;
	}

	# Perform login
	$request = $client->request('
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
	<command>
		<login>
			<clID>'.$params['Username'].'</clID>
			<pw>'.$params['Password'].'</pw>
			<options>
			<version>1.0</version>
			<lang>en</lang>
			</options>
			<svcs>
				<objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>
				<objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>
			</svcs>
		</login>
	</command>
</epp>
');

	return $client;
}

function cozaepp_Sync($params) {
	$domainid = $params['domainid'];
	$domain = $params['domain'];
	$sld = $params['sld'];
	$tld = $params['tld'];
	$registrar = $params['registrar'];
	$regperiod = $params['regperiod'];
	$status = $params['status'];
	$dnsmanagement = $params['dnsmanagement'];
	$emailforwarding = $params['emailforwarding'];
	$idprotection = $params['idprotection'];

	# Other parameters used in your _getConfigArray() function would also be available for use in this function

	# Grab domain info
	$client = _cozaepp_Client();
	if (PEAR::isError($client)) {
		$values["error"] = 'Sync/EPP: '.$client->toString();
		return $values;
	}

	# Grab domain info
	$request = $client->request('
<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
	<epp:command>
		<epp:info>
			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
				<domain:name hosts="all">'.$domain.'</domain:name>
			</domain:info>
		</epp:info>
	</epp:command>
</epp:epp>
');

	$doc= new DOMDocument();
	$doc->loadXML($request);
	$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
	$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
	# Check result
	if($coderes != '1000') {
		$values['error'] = "Sync/domain-info($domain): Code("._cozaepp_message($coderes).") $msg";
		return $values;
	}

	# Check if we can get a status back
	if($doc->getElementsByTagName('status')->item(0)) {
		$statusres = $doc->getElementsByTagName('status')->item(0)->getAttribute('s');
		$createdate = substr($doc->getElementsByTagName('crDate')->item(0)->nodeValue,0,10);
		$nextduedate = substr($doc->getElementsByTagName('exDate')->item(0)->nodeValue,0,10);
	} else {
		$values['error'] = "Sync/domain-info($domain): Domain not found";
		return $values;
	}

	$values['status'] = $msg;

	# Check status and update
	if ($statusres == "ok") {
		$values['active'] = true;

	} elseif ($statusres == "serverHold") {

	} elseif ($statusres == "expired") {
		$values['expired'] = true;

	} else {
		$values['error'] = "Sync/domain-info($domain): Unknown status code '$statusres' (File a bug report here: http://devlabs.linuxassist.net/projects/whmcs-coza-epp/issues/new)";
	}

	$values['expirydate'] = $nextduedate;

	return $values;
}

?>