<?php
/**
 * OpenSRS Domain Registrar Plugin
 *
 * @category Plugin
 * @package  ClientExec
 * @author   Jason Yates <jason@clientexec.com>
 * @license  ClientExec License
 * @version  2
 * @link     http://www.clientexec.com
 */

require_once 'modules/admin/models/RegistrarPlugin.php';
require_once 'modules/domains/models/ICanImportDomains.php';
require_once dirname(__FILE__).'/class.opensrs.php';

/**
 * PluginOpensrs RegistrarPlugin Class
 *
 * VALID FUNCTIONS
 * getVariables - Config vars for plugin
 * checkDomain - check if given domain is available
 * registerDomain - register a given domain with OpenSRS
 * setAutorenew - change the Auto Renew status of a domain
 *
 * TODO FUNCTIONS
 *
 * @category Plugin
 * @package  ClientExec
 * @author   Jason Yates <jason@clientexec.com>
 * @license  ClientExec License
 * @version  2
 * @link     http://www.clientexec.com
 */
class PluginOpensrs extends RegistrarPlugin implements ICanImportDomains
{

    var $liveHost = "rr-n1-tor.opensrs.net";
    var $testHost = "horizon.opensrs.net";
    var $connPort = "55443";

    // Set a var for support of name suggest
    var $supportsNamesuggest = true;

    /**
     * Function to return a list of configurable variables for the class
     *
     * @return array
     */
    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*/'OpenSRS'/*/T*/
                ),
                /*T*/'Use testing server'/*/T*/ => array(
                        'type'          =>'yesno',
                        'description'   =>/*T*/'Select Yes if you wish to use OpenSRS\'s testing environment, so that transactions are not actually made.'/*/T*/,
                        'value'         => 0
                ),
                /*T*/'Username'/*/T*/ => array(
                        'type'          => 'text',
                        'description'   => /*T*/'Enter your username for your OpenSRS reseller account.<br/>'/*/T*/,
                        'value'         => '',
                ),
                /*T*/'Private Key'/*/T*/  => array(
                        'type'          => 'text',
                        'description'   => /*T*/'Enter your OpenSRS reseller private key.'/*/T*/,
                        'value'         => '',
                ),
                /*T*/'Supported Features'/*/T*/  => array(
                        'type'          => 'label',
                        'description'   => /*T*/'
                                                * TLD Lookup - Including NameSuggest<br>
                                                * Domain Registration <br>
                                                * Existing Domain Importing <b>- NEW</b> <br>
                                                * Change AutoRenew Status of a domain <b>- NEW</b> <br>
                                                <br/><span class="notice notice-red"><b>NOTE:</b> In order to use the full functions of this plugin you must contact the OpenSRS sales office and request that your account be enabled for "No Credentials" mode. This will not affect existing or future domain registrations.</span>
                                                '/*/T*/,
                        'value'         => ''
                ),
               /*T*/'Actions'/*/T*/ => array (
                                'type'          => 'hidden',
                                'description'   => /*T*/'Current actions that are active for this plugin (when a domain isn\'t registered)'/*/T*/,
                                'value'         => 'Register'
                                ),
            /*T*/'Registered Actions'/*/T*/ => array (
                                'type'          => 'hidden',
                                'description'   => /*T*/'Current actions that are active for this plugin (when a domain is registered)'/*/T*/,
                                'value'         => '',
                                )
        );

        return $variables;
    }

    function doDelete() {

    }


    /**
     * Function to check if the given domain is available to be registered.
     *
     * This will eventually allow support for the name lookup command to return an array of available domains by suggestion
     *
     * @return array
     */
    function checkDomain($params)
    {
        // Calculate the host
        $host = ($params['Use testing server'])? $this->testHost:$this->liveHost;

        // Start the connection
        $opensrs = new OpenSRS($host, $this->connPort, $params['Username'], $params['Private Key'], $this->logger);

        // Check if we were passed any additional TLD's
        if(!@$params['namesuggest']) {
            $params['namesuggest'] = array();
            $namesuggest = false;
        }

        // Perform the lookup
        $return = $opensrs->lookup_domain(strtolower($params['sld']), strtolower($params['tld']), $params['namesuggest']);

        // Check the reply
        if ($return == null) {
            $this->logger->log(4, "OpenSRS Error: Ensure port 55443 is open and PHP is compiled with OpenSSL.");
            return array(5);
        }

        // Check we had a succcess code
        if ($return['status']['response_code'] != 200) {
            $this->logger->log(4, "OpenSRS Lookup Failed: ".$return['status']['response_text']);
            return array(5);
        }
        return $return;
    }

    
    /**
     * Register domain name
     * 
     * @param array $params 
     */
    function doRegister($params)
    {
        $userPackage = new UserPackage($params['userPackageId']);
        $orderid = $this->registerDomain($this->buildRegisterParams($userPackage,$params));
        $userPackage->setCustomField("Registrar Order Id",$userPackage->getCustomField("Registrar").'-'.$orderid);
        return $userPackage->getCustomField('Domain Name') . ' has been registered.';
    }
    
    /**
     * Function to register the given domain. This needs tidying up
     *
     * @return array
     */
    function registerDomain($params)
    {
        if ($params['Use testing server']) {
            $host = 'horizon.opensrs.net';
            $params['NS1']['hostname'] = "default.opensrs.org";
            $params['NS2']['hostname'] = "default1.opensrs.org";
            $params['Custom NS'] = 1;
            for ($i = 3; $i <= 12; $i++) {
                unset($params['NS'.$i]);
            }
        } else {
            $host = 'rr-n1-tor.opensrs.net';
            if (isset($params['NS1'])) {
                $params['Custom NS'] = 1;
            } else {
                $params['Custom NS'] = 0;
            }
        }

        if(!@$params['renewname'] == 0) {
            $params['renewname'] = 1;
        }

        $opensrs = new OpenSRS($host, $this->connPort,
                $params['Username'],
                $params['Private Key'],
                $this->logger);


        $params['domain'] = strtolower($params['sld'].".".$params['tld']);
        $params['RegistrantPhone'] = $this->_plugin_opensrs_validatePhone($params['RegistrantPhone'],$params['RegistrantCountry']);
        if ($params['RegistrantOrganizationName'] == "") $params['RegistrantOrganizationName'] = $params['RegistrantFirstName']." ".$params['RegistrantLastName'];

        // Process the extended attributes
        if (is_array($params['ExtendedAttributes'])) {
            foreach ($params['ExtendedAttributes'] as $name => $value) {
                $params[$name] = $value;
            }
        }

        /* Grab some information that isn't passed by default */
        $query = "SELECT id from customuserfields where type='8'";
        $result = $this->db->query($query);
        list($fieldid) = $result->fetch();

        $query = "SELECT id FROM users WHERE email=?";
        $result = $this->db->query($query, $params['RegistrantEmailAddress']);
        list($userid) = $result->fetch();

        $query = "SELECT value FROM user_customuserfields WHERE customid=? AND userid=?";
        $result = $this->db->query($query, $fieldid, $userid);
        list($lang) = $result->fetch();
        if (strtolower($lang) == 'french') $params['RegistrantLanguage'] = 'FR';
        else $params['RegistrantLanguage'] = 'EN';


        $return = $opensrs->register_domain($params);

        //print_r($return);

        if ($return == null) {
            $this->logger->log(4, "OpenSRS Error: Ensure port 55443 is open and PHP is compiled with OpenSSL.");
            throw new Exception ("OpenSRS Error: Ensure port 55443 is open and PHP is compiled with OpenSSL.");
        }
        foreach ($return as $key=>$val) {
            if ($val['@']['key'] == 'response_code') $status_key = $key;
            if ($val['@']['key'] == 'is_success') $success_key = $key;
            if ($val['@']['key'] == 'response_text') $status_text = $key;
            if ($val['@']['key'] == 'attributes') $attributes_key = $key;
        }

        $this->logger->log(4, "OpenSRS Registration Response: ".$return[$status_text]['#']);

        if (isset($attributes_key)) {
            $attributes = $return[$attributes_key]['#']['dt_assoc'][0]['#']['item'];
            if ($return[$success_key]['#'] == 1) {
                foreach ($attributes as $key=>$val) {
                    if ($val['@']['key'] == 'id') $regId = $val['#'];
                }
            }
        }
        $code = $return[$status_key]['#'];
        if ($code == 210 || $code == 200 || $code == 250) {
            // Registration was fine
            return $regId;
        }
        if ($code == 485) {
            // Domain is already registered
            throw new Exception('OpenSRS Error: Domain Name already registered.');
        }
        // Something went very wrong

        throw new Exception("<b>Domain registration failed:</b> ".$return[$status_text]['#']." <br> <br> ".@$attributes[0]['#']);
    }


    /**
     * Function to change the auto renew status of a given domain.
     *
     * First gets a "cookie" from OpenSRS to edit the given domain
     *
     * @return array
     */
    function setAutorenew($params)
    {
        //$userPackage = $params['userPackage'];
        
        // Calculate the host
        $host = ($params['Use testing server'])? $this->testHost:$this->liveHost;

        // Start the connection
        $opensrs = new OpenSRS($host, $this->connPort, $params['Username'], $params['Private Key'], $this->logger);

        // Get the cookie
        //requires username and password so lets send
        //$params = array_merge($params,$this->getUsernamePassword($userPackage));

        // DOn't get the cookie as we're using no credentials
        //$cookie = $opensrs->get_cookie($params);

        // Run the command
        $return = $opensrs->set_autorenew(strtolower($params['sld']), strtolower($params['tld']), $params['autorenew']);

        // Check for an error
        if ($return['status']['response_code'] != 200) {
            $this->logger->log(4, "OpenSRS API Call Failed: ".$return['status']['response_text']);
            throw new Exception("OpenSRS API Error - setAutorenew: ".$return['status']['response_text']);
        }
    }

    /**
     * Function to get the general information of a given domain
     *
     * First gets a "cookie" from OpenSRS to edit the given domain
     *
     * @return array
     */
    function getGeneralInfo($params)
    {
        // Calculate the host
        $host = ($params['Use testing server'])? $this->testHost:$this->liveHost;

        // Start the connection
        $opensrs = new OpenSRS($host, $this->connPort, $params['Username'], $params['Private Key'], $this->logger);

        // Get the domain info
        $return = $opensrs->get_domain_info(strtolower($params['sld']), strtolower($params['tld']), 'general');

        if($return == null) {
            // This function can break some domains in admin panel. For example, transfer's that aren't yet in the account.
            // So if the response is null, then don't show an error
            return null;
        }

        // Check for an error
        if ($return['status']['response_code'] != 200) {
            $this->logger->log(4, "OpenSRS API Call Failed: ".$return['status']['response_text']);
            throw new Exception("OpenSRS API Error - getGeneralInfo: ".$return['status']['response_text']);
        }

        // Build the standard CE response
        $data = array();
        $data['id'] = -1;
        $data['domain'] = strtolower($params['sld']).".".strtolower($params['tld']);
        $data['expiration'] = $return['generalInfo']['registry_expiredate'];
        $data['registrationstatus'] = 'Registered';
        $data['purchasestatus'] = 'Purcahsed on '.$return['generalInfo']['registry_createdate'];
        $data['autorenew'] = $return['generalInfo']['auto_renew'];

        return $data;
 
    }


    /**
     * Function to import domains from OpenSRS
     * @param <type> $params 
     */
    function fetchDomains($params)
    {

        // Calculate the host
        $host = ($params['Use testing server'])? $this->testHost:$this->liveHost;

        // Start the connection
        $opensrs = new OpenSRS($host, $this->connPort, $params['Username'], $params['Private Key'], $this->logger);

        $return = $opensrs->get_domains_list($params['next']);

        return $return;
    }

    // @access private
    function _plugin_opensrs_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 (isset($phone[0]) && $phone[0] == '+') {
            return $phone;
        }

        // if not, prepend it
        return "+$code.$phone";
    }

    function getContactInformation ($params)
    {
        // Calculate the host
        $host = ($params['Use testing server'])? $this->testHost:$this->liveHost;

        // Start the connection
        $opensrs = new OpenSRS($host, $this->connPort, $params['Username'], $params['Private Key'], $this->logger);

        // Get the domain info
        $return = $opensrs->get_domain_info(strtolower($params['sld']), strtolower($params['tld']), 'contact');

        return $return;
    }

    function setContactInformation ($params)
    {
        throw new Exception('Method setContactInformation() has not been implemented yet.');
    }

    function getNameServers ($params)
    {
        throw new Exception('Getting Name Server Records is not supported in this plugin.');
    }

    function setNameServers ($params)
    {
        throw new Exception('Method setNameServers() has not been implemented yet.');
    }

    function checkNSStatus ($params)
    {
        throw new Exception('Method checkNSStatus() has not been implemented yet.');
    }

    function registerNS ($params)
    {
        throw new Exception('Method registerNS() has not been implemented yet.');
    }

    function editNS ($params)
    {
        throw new Exception('Method editNS() has not been implemented yet.');
    }

    function deleteNS ($params)
    {
        throw new Exception('Method deleteNS() has not been implemented yet.');
    }

    function getRegistrarLock ($params)
    {
        throw new Exception('Method getRegistrarLock() has not been implemented yet.');
    }

    function setRegistrarLock ($params)
    {
        throw new Exception('Method setRegistrarLock() has not been implemented yet.');
    }

    function sendTransferKey ($params)
    {
        throw new Exception('Method sendTransferKey() has not been implemented yet.');
    }
    function getDNS ($params)
    {
        throw new Exception('Getting DNS Records is not supported in this plugin.');
    }
    function setDNS ($params)
    {
        throw new Exception('Method setDNS() has not been implemented yet.');
    }

}

?>
