<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */


require_once dirname(__FILE__).'/../../../newedge/classes/NE_Observable_Loggers.php';
require_once 'classes/RegistrarPlugin.php';

/**
* @package Plugins
* @todo PUNY encoding
*/
class PluginEnom extends RegistrarPlugin
{

    // insert credentials and uncomment to update registrars table
    //$gSettingsArray['plugin_enom_Use testing server'] = true;
    //_plugin_enom_updateRegistrarsTable(array('uid' => '', 'pw' => ''));
    
    function getVariables()
    {
        $variables = array(
            /*T*/'Plugin Name'/*/T*/ => array (
                                'type'          =>'hidden', 
                                'description'   =>/*T*/'How CE sees this plugin (not to be confused with the Signup Name)'/*/T*/,
                                'value'         =>/*T*/'Enom'/*/T*/
                               ),
            /*T*/'Use testing server'/*/T*/ => array(
                                'type'          =>'yesno',
                                'description'   =>/*T*/'Select Yes if you wish to use Enom\'s testing environment, so that transactions are not actually made. For this to work, you must first register you server\'s ip in Enom\'s testing environment, and your server\'s name servers must be registered there as well.'/*/T*/,
                                'value'         =>0
                               ),
            /*T*/'Login'/*/T*/ => array(
                                'type'          =>'text',
                                'description'   =>/*T*/'Enter your username for your Enom reseller account.'/*/T*/,
                                'value'         =>''
                               ),
            /*T*/'Password'/*/T*/  => array(
                                'type'          =>'password',
                                'description'   =>/*T*/'Enter the password for your Enom reseller account.'/*/T*/,
                                'value'         =>'',
                                ),
            /*T*/'Actions'/*/T*/ => array (
                                'type'          => 'hidden',
                                'description'   => /*T*/'Current actions that are active for this plugin'/*/T*/,
                                'value'         => 'CheckDomain, CheckNS, DeleteNS, DisableRenewal, EditNS, GetContact, GetInfo, GetNS, Register, RegisterNS, SetContact, SetNS, FetchDomains, SendTransferKey, GetDNS, SetDNS, ToggleAutorenew',
                                )
        );
    
        return $variables;
    }
    
    function _getSupportedTLDs($params)
    {
        $arguments = array(
            'command'       => 'gettldlist',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
        );
        $response = $this->_makeRequest($params, $arguments);
    
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#'], 130);
        }
    
        $tlds = array();
        foreach ($response['interface-response']['#']['tldlist'][0]['#']['tld'] as $value) {
            $tlds[] = $value['#']['tld'][0]['#'];
        }
    
        return $tlds;
    }
    
    // returns array(code [,message]), where code is:
    // 0:       Domain available
    // 1:       Domain already registered
    // 2:       Registrar Error, domain extension not recognized or supported
    // 3:       Domain invalid
    // 5:       Could not contact registry to lookup domain
    function checkDomain($params)
    {
        $arguments = array(
            'command'       => 'check',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'tld'           => $params['tld'],
            'sld'           => $params['sld'],
        );
        $response = $this->_makeRequest($params, $arguments);
    
        if (!$response) return array(5);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err > 0) return array(5, $response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#']);
    
        if (isset($response['interface-response']['#']['RRPCode'][0]['#'])) {
            $RRPCode = $response['interface-response']['#']['RRPCode'][0]['#'];
        } else {
            $RRPCode = '';
        }
        if ($RRPCode == 210) return array(0);
        if ($RRPCode == 211) return array(1);
        if ($RRPCode == 723) return array(2);
        else return array(1);
    }
    
    
    // possible return values: array(code [,message])
    // -1:  error trying to purchase domain
    // 0:   domain not available
    // >0:  Operation successfull, returns orderid
    function registerDomain($params)
    {
        $arguments = array(
            'command'                       => 'purchase',
            'uid'                           => $params['Login'],
            'pw'                            => $params['Password'],
            'tld'                           => $params['tld'],
            'sld'                           => $params['sld'],
            'NumYears'                      => $params['NumYears'],
            'Renewname'                     => '1', // automatically renew domain
            'RegistrantOrganizationName'    => $params['RegistrantOrganizationName'],
            'RegistrantFirstName'           => $params['RegistrantFirstName'],
            'RegistrantLastName'            => $params['RegistrantLastName'],
            'RegistrantEmailAddress'        => $params['RegistrantEmailAddress'],
            'RegistrantPhone'               => $this->_validatePhone($params['RegistrantPhone'], $params['RegistrantCountry']),
            'RegistrantAddress1'            => $params['RegistrantAddress1'],
            'RegistrantCity'                => $params['RegistrantCity'],
            //'RegistrantStateProvinceChoice' => $params['RegistrantStateProvinceChoice'],
            'RegistrantStateProvince'       => $params['RegistrantStateProvince'],
            'RegistrantPostalCode'          => $params['RegistrantPostalCode'],
            'RegistrantCountry'             => $params['RegistrantCountry'],
        );
    
        if (is_array($params['ExtendedAttributes'])) {
            foreach ($params['ExtendedAttributes'] as $name => $value) {
                $arguments[$name] = $value;
            }
        }
    
        if (isset($params['NS1'])) {
            // maximum 12 name servers are allowed by Enom
            for ($i = 1; $i <= 12; $i++) {
                if (isset($params["NS$i"])) {
                    $arguments["NS$i"] = $params["NS$i"]['hostname'];
                } else {
                    break;
                }
            }
        } else {
            // use Enom's default name servers
            $arguments['usedns'] = 'default';
        }
    
        $response = $this->_makeRequest($params, $arguments);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];

        // RRPCode not set when there's an error (except for case 540), thus the @
        $RRPCode = @$response['interface-response']['#']['RRPCode'][0]['#'];

        if ($err >0) {
            switch ($RRPCode) {
                case 540:
                    return array(0);
                    break;
                default:
                    $messages = array();
                    for ($i = 1; $i <= $err; $i++) {
                        $messages[] = $response['interface-response']['#']['errors'][0]['#']["Err$i"][0]['#'];
                    }
                    if (isset($response['interface-response']['#']['MinPeriod'][0]['#'])) {
                        $messages[] = "Minimum registration period is {$response['interface-response']['#']['MinPeriod'][0]['#']} year(s)";
                    }
                    if (isset($response['interface-response']['#']['MaxPeriod'][0]['#'])) {
                        $messages[] = "Maximum registration period is {$response['interface-response']['#']['MaxPeriod'][0]['#']} year(s)";
                    }
                    return array(-1, $messages);
            }
        }
    
        if ($RRPCode == 200 || $RRPCode == 1300) {
            $order_id = $response['interface-response']['#']['OrderID'][0]['#'];
            return array($order_id);
        }
    }
    
    function disableRenewal($params)
    {
        $arguments = array(
            'command'   => 'SetRenew',
            'uid'       => $params['Login'],
            'pw'        => $params['Password'],
            'tld'       => $params['tld'],
            'sld'       => $params['sld'],
            'RenewFlag' => '0',
        );
    
        $response = $this->_makeRequest($params, $arguments);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err >0) {
            $messages = array();
            for ($i = 1; $i <= $err; $i++) {
                $messages[] = $response['interface-response']['#']['errors'][0]['#']["Err$i"][0]['#'];
            }
            return array(-1, $messages);
        }
    
        return array(1);
    }
    
    // called from outside CE once in a while
    function _plugin_enom_updateRegistrarsTable($params)
    {
        require_once dirname(__FILE__) . '/../../../config.php';
        $connection = mysql_connect($hostname, $dbuser, $dbpass) or die("Couldn't establish database connection");
        mysql_select_db($database, $connection) or die("Can not select database: $database");
    
        $supportedTLDs = $this->_getSupportedTLDs($params);
        echo "This plugin supports ".count($supportedTLDs)." tlds\n\n";
        foreach ($supportedTLDs as $tld) {
            echo "Checking $tld\n";
            $arguments = array(
                'command'   => 'getExtAttributes',
                'uid'       => $params['Login'],
                'pw'        => $params['Password'],
                'tld'       => $tld,
            );
            $response = $this->_makeRequest($params, $arguments);
            $err = $response['interface-response']['#']['ErrCount'][0]['#'];
            if ($err > 0) return array(5, $response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#']);
    
            if (!isset($response['interface-response']['#']['Attributes'][0]['#']['Attribute'])) {
                continue;
            }
    
            $extraAttributes = array();
            foreach ($response['interface-response']['#']['Attributes'][0]['#']['Attribute'] as $attribute) {
                if ($attribute['#']['Required'][0]['#'] == '0') {
                    continue;
                }
                if ($attribute['#']['Description'][0]['#'] == 'Country') {
                    // We're already sending the country in another field
                    continue;
                }
                $attributeName = $attribute['#']['Name'][0]['#'];
                $extraAttributes[$attributeName]['ID']           = $attribute['#']['ID'][0]['#'];
                $extraAttributes[$attributeName]['description']  = $attribute['#']['Description'][0]['#'];
    
                $extraAttributes[$attributeName]['options'] = array();
                if (is_array($attribute['#']['Options'][0]['#']['Option'])) {
                    foreach ($attribute['#']['Options'][0]['#']['Option'] as $option) {
                        $extraAttributes[$attributeName]['options'][$option['#']['Title'][0]['#']] = array(
                                                                'description'  => $option['#']['Description'][0]['#'],
                                                                'value'        => $option['#']['Value'][0]['#'],
                                                            );
                        if (isset($option['#']['Requires'])) {
                            $extraAttributes[$attributeName]['options'][$option['#']['Title'][0]['#']]['requires'] = array();
                            foreach ($option['#']['Requires'] as $requirement) {
                                $extraAttributes[$attributeName]['options'][$option['#']['Title'][0]['#']]['requires'][] = $requirement['#']['Attribute'][0]['#']['ID'][0]['#'];
                            }
                        }
                    }
                }
            }
    
            //print_r($extraAttributes);
            if (!$extraAttributes) {
                continue;
            }
            $extraAttributes = serialize($extraAttributes);
            $extraAttributes = mysql_real_escape_string(($extraAttributes));
            $query = "REPLACE INTO registrars SET plugin='enom', tld='$tld', extra_attributes='$extraAttributes'";
            mysql_query($query) or die("Error in query $query");
        }
    
        return $extraAttributes;
    }
    
    function _makeRequest($params, $arguments)
    {
        require_once 'newedge/classes/XmlFunctions.php';
        require_once 'newedge/classes/NE_Network.php';

        // default paramters
        if (!isset($params['secure'])) $params['secure'] = true;
        if (!isset($params['test'])) $params['test'] = false;
    
        if ($params['secure']) $request = 'https://';
        else $request= 'http://';
    
        if (@$this->settings->get('plugin_enom_Use testing server')) $request .= 'resellertest.enom.com/interface.asp';
        else $request .= 'reseller.enom.com/interface.asp';
    
        $arguments['responsetype'] = 'XML';
    
        $i = 0; 
        foreach ($arguments as $name => $value) {
            $value = urlencode($value);
            if (!$i) $request .= "?$name=$value";
            else $request .= "&$name=$value";
            $i++;
        }
    
        if ($params['test']) echo "$request\n";
        $this->logger->log(4, 'Enom Params: '.$request);
    
        //echo "$request\n";
        // certificate validation doesn't work well under windows
        $response = NE_Network::curlRequest($this->settings, $request, false, false, true);
        //echo $response;
    
        if (is_a($response, 'NE_Error')) return $response;
        if (!$response) return false;   // don't want xmlize an empty array
    
        $response = XmlFunctions::xmlize($response);
    
        return $response;
    }
    
    function _validatePhone($phone, $country)
    {
        // strip all non numerical values
        $phone = preg_replace('/[^\d]/', '', $phone);
    
        $query = "SELECT phone_code FROM country WHERE iso=? AND phone_code != ''";
        $result = $this->db->query($query, $country);
        if (!$row = $result->fetch()) {
            return $phone;
        }
    
        // check if code is already there
        $code = $row['phone_code'];
        $phone = preg_replace("/^($code)(\\d+)/", '+\1.\2', $phone);
        if ($phone[0] == '+') {
            return $phone;
        }
    
        // if not, prepend it
        return "+$code.$phone";
    }
    
    function getContactInformation($params)
    {
        
        $arguments = array(
            'command'       => 'getcontacts',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld']
        );
        $response = $this->_makeRequest($params, $arguments);
        if (is_a($response, 'NE_Error')) return $response;
    
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        $info = array();
        foreach (array('Registrant', 'AuxBilling', 'Admin', 'Tech') as $type) {
            $data =  $response['interface-response']['#']['GetContacts'][0]['#'][$type][0]['#'];
            if (is_array($data)) {
                $info[$type]['OrganizationName']  = array($this->user->lang('Organization'), $data[$type.'OrganizationName'][0]['#']);
                $info[$type]['JobTitle']  = array($this->user->lang('Job Title'), $data[$type.'JobTitle'][0]['#']);
                $info[$type]['FirstName'] = array($this->user->lang('First Name'), $data[$type.'FirstName'][0]['#']);
                $info[$type]['LastName']  = array($this->user->lang('Last Name'), $data[$type.'LastName'][0]['#']);
                $info[$type]['Address1']  = array($this->user->lang('Address').' 1', $data[$type.'Address1'][0]['#']);
                $info[$type]['Address2']  = array($this->user->lang('Address').' 2', $data[$type.'Address2'][0]['#']);
                $info[$type]['City']      = array($this->user->lang('City'), $data[$type.'City'][0]['#']);
                $info[$type]['StateProvChoice']  = array($this->user->lang('State or Province'), $data[$type.'StateProvinceChoice'][0]['#']);
                $info[$type]['StateProv']  = array($this->user->lang('Province').'/'.$this->user->lang('State'), $data[$type.'StateProvince'][0]['#']);
                $info[$type]['Country']   = array($this->user->lang('Country'), $data[$type.'Country'][0]['#']);
                $info[$type]['PostalCode']  = array($this->user->lang('Postal Code'), $data[$type.'PostalCode'][0]['#']);
                $info[$type]['EmailAddress']     = array($this->user->lang('E-mail'), $data[$type.'EmailAddress'][0]['#']);
                $info[$type]['Phone']  = array($this->user->lang('Phone'), $data[$type.'Phone'][0]['#']);
                $info[$type]['PhoneExt']  = array($this->user->lang('Phone Ext'), $data[$type.'PhoneExt'][0]['#']);
                $info[$type]['Fax']       = array($this->user->lang('Fax'), $data[$type.'Fax'][0]['#']);
            } else {
                $info[$type] = array(
                    'OrganizationName'  => array($this->user->lang('Organization'), ''),
                    'JobTitle'          => array($this->user->lang('Job Title'), ''),
                    'FirstName'         => array($this->user->lang('First Name'), ''),
                    'LastName'          => array($this->user->lang('Last Name'), ''),
                    'Address1'          => array($this->user->lang('Address').' 1', ''),
                    'Address2'          => array($this->user->lang('Address').' 2', ''),
                    'City'              => array($this->user->lang('City'), ''),
                    'StateProvChoice'   => array($this->user->lang('State or Province'), ''),
                    'StateProv'         => array($this->user->lang('Province').'/'.$this->user->lang('State'), ''),
                    'Country'           => array($this->user->lang('Country'), ''),
                    'PostalCode'        => array($this->user->lang('Postal Code'), ''),
                    'EmailAddress'      => array($this->user->lang('E-mail'), ''),
                    'Phone'             => array($this->user->lang('Phone'), ''),
                    'PhoneExt'          => array($this->user->lang('Phone Ext'), ''),
                    'Fax'               => array($this->user->lang('Fax'), ''),
                );
            }
        }
        return $info;
    }
    
    function setContactInformation($params)
    {
        $arguments = array(
            'command'       => 'contacts',
            'ContactType'   => strtoupper($params['type']),
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld']
        );
        foreach ($params as $key => $value) {
            if (strpos($key, $params['type']) !== false) {
                $arguments[str_replace('_', '', $key)] = $value;
            }
        }
        $response = $this->_makeRequest($params, $arguments);
        NE_Lib::printR($response, true);
    }
    
    function getNameServers($params)
    {
        
        $arguments = array(
            'command'       => 'getdns',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld']
        );
        $response = $this->_makeRequest($params, $arguments);
        if (is_a($response, 'NE_Error')) return $response;
    
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        
        $info = array();
        if ($response['interface-response']['#']['UseDNS'][0]['#'] == 'default') {
            $info['usesDefault'] = true;
        } else {
            $info['usesDefault'] = false;
        }
        $info['hasDefault'] = true;
        
        if (!isset($response['interface-response']['#']['dns'])) {
            return $info;
        }
        
        $data =  $response['interface-response']['#']['dns'];
        if (is_array($data)) {
            foreach ($data as $ns) {
                $info[] = $ns['#'];
            }
        }
        return $info;
    }
    
    function setNameServers($params)
    {
        $arguments = array(
            'command'       => 'modifyns',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld'],
        );
        if ($params['default'] == true) {
            $arguments['usedns'] = 'Default';
        } else {
            $arguments['usedns'] = '';
        }
        foreach ($params['ns'] as $key => $value) {
            $arguments['ns'.$key] = $value;
        }
        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        
        $response = $response['interface-response']['#'];
    
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
    }
    
    function checkNSStatus($params)
    {
        $arguments = array(
            'command'       => 'checknsstatus',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'checknsname'   => $params['check_ns']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        
        $response = $response['interface-response']['#'];
    
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        if ($response['NsCheckSuccess'][0]['#'] == 1) {
            $data = $response['CheckNsStatus'][0]['#'];
            return $this->_traverseStatus($data);
        } else {
            // Couldn't find any information about this domain.
            return $this->user->lang('No Results Found.');
        }
    }
    
    function registerNS($params)
    {
        $arguments = array(
            'command'       => 'registernameserver',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'add'           => 'true',
            'nsname'        => $params['nsname'],
            'ip'            => $params['nsip']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        
        $response = $response['interface-response']['#'];
    
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        return $this->user->lang('Name Server registered successfully.');
    }
    
    function editNS($params)
    {
        $arguments = array(
            'command'       => 'updatenameserver',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'NS'            => $params['nsname'],
            'OldIP'         => $params['nsoldip'],
            'NewIP'         => $params['nsnewip']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        
        $response = $response['interface-response']['#'];
    
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        return $this->user->lang('Name Server edited successfully.');
    }
    
    function deleteNS($params)
    {
        $arguments = array(
            'command'       => 'deletenameserver',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'ns'            => $params['nsname']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        
        $response = $response['interface-response']['#'];
    
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        return $this->user->lang('Name Server deleted successfully.');
    }
    
    function getGeneralInfo($params)
    {
        $arguments = array(
            'command'       => 'GetDomainInfo',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        
        $response = $response['interface-response']['#'];
    
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        $response = $response['GetDomainInfo'][0]['#'];
        $data = array();
        $data['id'] = $response['domainname'][0]['@']['domainnameid'];
        $data['domain'] = $response['domainname'][0]['#'];
        $data['expiration'] = $response['status'][0]['#']['expiration'][0]['#'];
        $data['registrationstatus'] = $this->user->lang($response['status'][0]['#']['registrationstatus'][0]['#']);
        $data['purchasestatus'] = $this->user->lang($response['status'][0]['#']['purchase-status'][0]['#']);
        
        $arguments['command'] = 'GetRenew';
        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) {
            $data['autorenew'] = 0;
        } else {
            
            $response = $response['interface-response']['#'];
        
            $err = $response['ErrCount'][0]['#'];
            if ($err > 0) {
                return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
            }
            $data['autorenew'] = $response['auto-renew'][0]['#'];
        }
        return $data;
    }
    
    function fetchDomains($params)
    {
        $arguments = array(
            'command'       => 'GetDomains',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'Start'         => 1 + ($params['page'] - 1) * 25
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Error contacting Enom', 131);
        
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        
        $domainsList = array();
        if ($response['interface-response']['#']['GetDomains'][0]['#']['DomainCount'][0]['#'] > 0) {
            foreach ($response['interface-response']['#']['GetDomains'][0]['#']['domain-list'][0]['#']['domain'] as $domain) {
                $domain = $domain['#'];
                
                $data['id'] = $domain['DomainNameID'][0]['#']; 
                $data['sld'] = $domain['sld'][0]['#']; 
                $data['tld'] = $domain['tld'][0]['#'];
                $data['exp'] = isset($domain['expiration-date'][0]['#'])? $domain['expiration-date'][0]['#']: 'n/a';
                $domainsList[] = $data;
            }
        }
        $metaData = array();
        $metaData['total'] = $response['interface-response']['#']['GetDomains'][0]['#']['DomainCount'][0]['#'];
        $metaData['start'] = $response['interface-response']['#']['GetDomains'][0]['#']['StartPosition'][0]['#'];
        $metaData['end'] = $response['interface-response']['#']['GetDomains'][0]['#']['EndPosition'][0]['#'];
        $metaData['numPerPage'] = 25;
        return array($domainsList, $metaData);
        
    }
    
    function setAutorenew($params)
    {
        $arguments = array(
            'command'       => 'SetRenew',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld'],
            'RenewFlag'     => $params['autorenew']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        $response = $response['interface-response']['#'];
        
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
    }
    
    function getRegistrarLock($params)
    {
        $arguments = array(
            'command'       => 'GetRegLock',
            'uid'           => $params['Login'],
            'pw'            => $params['Password'],
            'sld'           => $params['sld'],
            'tld'           => $params['tld']
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        $response = $response['interface-response']['#'];
        
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        return $response['reg-lock'][0]['#'];
    }
    
    function setRegistrarLock($params)
    {
        $arguments = array(
            'command'           => 'SetRegLock',
            'uid'               => $params['Login'],
            'pw'                => $params['Password'],
            'sld'               => $params['sld'],
            'tld'               => $params['tld'],
            'UnlockRegistrar'   => $params['lock']? 0 : 1 // opposite of what we store
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        $response = $response['interface-response']['#'];
        
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
    }
    
    function sendTransferKey($params)
    {
        $arguments = array(
            'command'           => 'SynchAuthInfo',
            'uid'               => $params['Login'],
            'pw'                => $params['Password'],
            'sld'               => $params['sld'],
            'tld'               => $params['tld'],
            'EmailEPP'          => 'True',
            'RunSynchAutoInfo'  => 'True'
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        $response = $response['interface-response']['#'];
        
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
    }
    
    function getDNS($params)
    {
        $arguments = array(
            'command'           => 'GetRegHosts',
            'uid'               => $params['Login'],
            'pw'                => $params['Password'],
            'sld'               => $params['sld'],
            'tld'               => $params['tld'],
        );

        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        $response = $response['interface-response']['#'];
        
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        
        $records = array();
        foreach ($response['host'] as $value) {
            // enom returns blank results (why?)
            if ($value['#']['hostID'][0]['#'] == '') continue;
            $record = array(
                            'id'            =>  $value['#']['hostID'][0]['#'],
                            'hostname'      =>  trim(preg_replace('(\(.*\))', '', $value['#']['HostName'][0]['#'])), // enom adds (all) and (none) which causes problems
                            'address'       =>  $value['#']['Address'][0]['#'],
                            'type'          =>  $value['#']['RecordType'][0]['#']);
            $records[] = $record;
        }
        $types = array('A', 'MXE', 'MX', 'CNAME', 'URL', 'FRAME', 'TXT');
        
        $arguments['command'] = 'getdns';
        $response = $this->_makeRequest($params, $arguments);
        if (is_a($response, 'NE_Error')) return $response;
    
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
    
        $err = $response['interface-response']['#']['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['interface-response']['#']['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        
        if ($response['interface-response']['#']['UseDNS'][0]['#'] == 'default') {
            $default = true;
        } else {
            $default = false;
        }
        return array('records' => $records, 'types' => $types, 'default' => $default);
    }
    
    function setDNS($params)
    {
        $arguments = array(
            'command'           => 'SetHosts',
            'uid'               => $params['Login'],
            'pw'                => $params['Password'],
            'sld'               => $params['sld'],
            'tld'               => $params['tld'],
        );
        
        // build data to send to enom
        foreach ($params['records'] as $index => $record) {
            $index++; // enom starts at 1
            $arguments['HostName'.$index] = $record['hostname'];
            $arguments['RecordType'.$index] = $record['type'];
            $arguments['Address'.$index] = $record['address'];
        }
        
        $response = $this->_makeRequest($params, $arguments);
        if (!is_array($response)) return new NE_Error('Failed to communicate with Enom', 132);
        $response = $response['interface-response']['#'];
        
        $err = $response['ErrCount'][0]['#'];
        if ($err > 0) {
            return new NE_Error($response['errors'][0]['#']['Err1'][0]['#'], 130);
        }
        return true;
    }
    
    /**
     * Internal recursive function for iterating over the name server status array.
     *
     * @param mixed $arr The data to iterate over
     * @return String The stringified version of the status.
     */
    function _traverseStatus($arr)
    {
        if (!is_array($arr)) return $arr.'<br />';
        $str = '';
        foreach ($arr as $key => $val) {
            if (is_array($val[0]['#'])) $str .= $this->_traverseStatus($val[0]['#']);
            else $str .= $key.' = '.$val[0]['#'].'<br />';
        }
        return $str;
    }
    
}

?>
