<?php
/**
 * OpenSRS Domain Registrar Plugin Communication Class
 *
 * Expanded from the orginal class written by Mike Mallinson
 *
 * @category Plugin
 * @package  ClientExec
 * @author   Jason Yates <jason@clientexec.com>
 * @license  ClientExec License
 * @version  2
 * @link     http://www.clientexec.com
 */

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

/**
 * OpenSRS Class
 *
 * @category Plugin
 * @package  ClientExec
 * @author   Jason Yates <jason@clientexec.com>
 * @license  ClientExec License
 * @version  2
 * @link     http://www.clientexec.com
 */
class OpenSRS
{
    var $apiVersion = '0.9';

    var $port;
    var $host;
    var $user;
    var $key;
    var $logger;

    /**
     * Constructs a new OpenSRS object.
     *
     * @return OpenSRS An OpenSRS object
     */
    function OpenSRS($host, $port, $user, $key, $logger)
    {
        $this->host = $host;
        $this->port = $port;
        $this->user = $user;
        $this->key = $key;
        $this->logger = $logger;
    }
    
    /**
     * Checks the availibility of a domain.
     *
     * UPDATED: To use name_suggest as OpenSRS say it is faster
     *
     * @param string $domain The domain name to lookup
     * @return an xmlized array result - use print_r() to view the structure
     */
    function lookup_domain($domain, $tld)
    {
        // Build the request
        $request = "<data_block>
                      <dt_assoc>
                        <item key='protocol'>XCP</item>
                        <item key='action'>name_suggest</item>
                        <item key='object'>domain</item>
                        <item key='attributes'>
                          <dt_assoc>
                            <item key='searchstring'>".$domain."</item>
                            <item key='tlds'>
                              <dt_array>
                                <item key='0'>".$tld."</item>
                              </dt_array>
                            </item>
                          </dt_assoc>
                        </item>
                      </dt_assoc>
                    </data_block>";

        // Send the request to OpenSRS
        $response = $this->_buildAndSendRequest($request);

        // Check the response
        if ($response == null) {
            return null;
        }

        // XMLize the reply
        $response = XmlFunctions::xmlize($response);

        // Get the response
        $response = $response['OPS_envelope']['#']['body'][0]['#']['data_block'][0]['#']['dt_assoc'][0]['#']['item'][5]['#']['dt_assoc'][0]['#']['item'][0]['#']['dt_assoc'][0]['#']['item'];

        $finalArray = array();
        $finalArray['status'] = array("response_text" => $response[1]['#'], "response_code" => $response[2]['#']);

        // Loop it
        foreach ($response[3]['#']['dt_array'][0]['#']['item'] AS $key) {

            // Make a working array
            $workingArray = array();
            $key = $key['#']['dt_assoc'][0]['#']['item'];

            // Add the domain
            $workingArray['domain'] = $key[0]['#'];
            $workingArray['status'] = $key[1]['#'];

            $finalArray['result'][] = $workingArray;
        }

        //return the final array of checked domains
        return $finalArray;
    }
    
    /**
     * Registers a domain name with OpenSRS.
     *
     * @param array $params An array of parameters.
     * @return an xmlized array result - use print_r() to view the structure
     */
    function register_domain($params)
    {
        $contactblock = "  <dt_assoc>
                            <item key='state'>".$params['RegistrantStateProvince']."</item>
                            <item key='first_name'>".$params['RegistrantFirstName']."</item>
                            <item key='country'>".$params['RegistrantCountry']."</item>
                            <item key='address1'>".$params['RegistrantAddress1']."</item>
                            <item key='last_name'>".$params['RegistrantLastName']."</item>
                            <item key='address2'></item>
                            <item key='address3'></item>
                            <item key='postal_code'>".$params['RegistrantPostalCode']."</item>
                            <item key='fax'></item>
                            <item key='city'>".$params['RegistrantCity']."</item>
                            <item key='phone'>".$params['RegistrantPhone']."</item>
                            <item key='email'>".$params['RegistrantEmailAddress']."</item>
                            <item key='org_name'>".$params['RegistrantOrganizationName']."</item>
                            <item key='lang_pref'>".$params['RegistrantLanguage']."</item>
                           </dt_assoc>";
        
        /* tld specific items */
        switch($params['tld']) {
            case 'ca':
                $tldspecific = "<item key='isa_trademark'>".$params['ExtendedAttributes']['cira-isa-trademark']."</item>
                 <item key='legal_type'>".$params['ExtendedAttributes']['cira_legal_type']."</item>";
                break;
            case 'us':
                $tldspecific = "<item key='tld_data'>
                        <dt_assoc>
                          <item key='nexus'>
                           <dt_assoc>
                            <item key='category'>".$params['ExtendedAttributes']['us_nexus']."</item>
                            <item key='app_purpose'>".$params['ExtendedAttributes']['us_purpose']."</item>
                            <item key='validator'>".$params['RegistrantCountry']."</item>
                           </dt_assoc>
                          </item>
                         </dt_assoc>
                        </item>";
                break;
            case 'name':
                $tldspecific = "<item key='tld_data'>
                      <dt_assoc>
                       <item key='forwarding_email'>".$params['RegistrantEmailAddress']."</item>
                      </dt_assoc>
                     </item>";
                break;
            default:
                $tldspecific = "";
                break;
        }
        
        /* custom name servers */
        $ns = "";
        if ($params['Custom NS']) {
            $ns = "<item key='nameserver_list'>
                    <dt_array>";
            for ($i = 1; $i <= 12; $i++) {
                if (isset($params["NS$i"])) {
                    $ns.= "<item key='".($i-1)."'>
                          <dt_assoc>
                           <item key='sortorder'>".$i."</item>
                           <item key='name'>".$params['NS'.$i]['hostname']."</item>
                          </dt_assoc>
                         </item>";
                } else {
                    break;
                }
            }
            $ns .= " </dt_array>
                    </item>";
        }

        $request = "<data_block>
                     <dt_assoc>
                      <item key='action'>SW_REGISTER</item>
                      <item key='object'>DOMAIN</item>
                      <item key='protocol'>XCP</item>
                      <item key='attributes'>
                       <dt_assoc>
                        <item key='auto_renew'>".$params['renewname']."</item>
                        <item key='contact_set'>
                         <dt_assoc>
                          <item key='admin'>
                           ".$contactblock."
                          </item>
                          <item key='billing'>
                           ".$contactblock."
                          </item>
                          <item key='owner'>
                           ".$contactblock."
                          </item>
                          <item key='tech'>
                           ".$contactblock."
                          </item>
                         </dt_assoc>
                        </item>
                        <item key='custom_nameservers'>".$params['Custom NS']."</item>
                        <item key='custom_tech_contact'>1</item>
                        <item key='domain'>".$params['domain']."</item>
                        <item key='f_lock_domain'>1</item>
                        <item key='handle'>process</item>
                        ".$tldspecific."
                        ".$ns."
                        <item key='period'>".$params['NumYears']."</item>
                        <item key='reg_username'>".$params['domainUsername']."</item>
                        <item key='reg_password'>".$params['domainPassword']."</item>
                        <item key='type'>new</item>
                       </dt_assoc>
                      </item>
                     </dt_assoc>
                    </data_block>";
        
        $response = $this->_buildAndSendRequest($request);
        if ($response == null) {
            return null;
        }
        $response = XmlFunctions::xmlize($response);
        return $response['OPS_envelope']['#']['body'][0]['#']['data_block'][0]['#']['dt_assoc'][0]['#']['item'];
    }


    /**
     * Sets the renew status of a domain
     *
     * @param string $domain The domain name to lookup
     * @return an xmlized array result - use print_r() to view the structure
     */
    function set_autorenew($domain, $tld, $autorenew, $cookie)
    {
        // Build the request
        $request = "<data_block>
                      <dt_assoc>
                        <item key='protocol'>XCP</item>
                        <item key='action'>modify</item>
                        <item key='object'>domain</item>
                        <item key='cookie'>".$cookie."</item>
                        <item key='attributes'>
                          <dt_assoc>
                            <item key='affect_domains'>0</item>
                            <item key='auto_renew'>".$autorenew."</item>
                            <item key='let_expire'>0</item>
                            <item key='data'>expire_action</item>
                          </dt_assoc>
                        </item>
                      </dt_assoc>
                    </data_block>";

        // Send the request to OpenSRS
        $response = $this->_buildAndSendRequest($request);

        // Check the response
        if ($response == null) {
            return null;
        }

        // XMLize the reply
        $response = XmlFunctions::xmlize($response);

        // Get the response
        $response = $response['OPS_envelope']['#']['body'][0]['#']['data_block'][0]['#']['dt_assoc'][0]['#']['item'];

        // Process the response
        $finalArray = array();
        $finalArray['status'] = array("response_text" => $response[2]['#'], "response_code" => $response[4]['#']);

        return $finalArray;
    }


    /**
     * Sets the renew status of a domain
     *
     * @param string $domain The domain name to lookup
     * @return an xmlized array result - use print_r() to view the structure
     */
    function get_domain_info($domain, $tld, $cookie)
    {
        // Build the request
        $request = "<data_block>
                      <dt_assoc>
                        <item key='protocol'>XCP</item>
                        <item key='action'>get</item>
                        <item key='object'>domain</item>
                        <item key='cookie'>".$cookie."</item>
                        <item key='attributes'>
                          <dt_assoc>
                            <item key='type'>all_info</item>
                            <item key='limit'>1</item>>
                          </dt_assoc>
                        </item>
                      </dt_assoc>
                    </data_block>";

        // Send the request to OpenSRS
        $response = $this->_buildAndSendRequest($request);

        // Check the response
        if ($response == null) {
            return null;
        }

        // XMLize the reply
        $response = XmlFunctions::xmlize($response);

        // Get the first part of the response
        $response = $response['OPS_envelope']['#']['body'][0]['#']['data_block'][0]['#']['dt_assoc'][0]['#']['item'];

        // Process the response
        $finalArray = array();
        $finalArray['status'] = array("response_text" => $response[2]['#'], "response_code" => $response[5]['#']);

        // Set the next block of the response
        $response = $response[4]['#']['dt_assoc'][0]['#']['item'];

        // Process the standard info
        $finalArray['generalInfo'] = array('auto_renew' => $response[0]['#'],
                                           'registry_createdate' => $response[4]['#'],
                                           'registry_expiredate' => $response[5]['#']);

        return $finalArray;
    }

    /**
     * Sets the renew status of a domain
     *
     * @param string $domain The domain name to lookup
     * @return an xmlized array result - use print_r() to view the structure
     */

    function get_cookie($params) {

        // Build the request
        $request = "<data_block>
                      <dt_assoc>
                        <item key='protocol'>XCP</item>
                        <item key='action'>set</item>
                        <item key='object'>cookie</item>
                        <item key='attributes'>
                          <dt_assoc>
                            <item key='reg_username'>".$params['DomainUsername']."</item>
                            <item key='reg_password'>".$params['DomainPassword']."</item>
                            <item key='domain'>".$params['sld'].".".$params['tld']."</item>
                          </dt_assoc>
                        </item>
                      </dt_assoc>
                    </data_block>";

        // Send the request to OpenSRS
        $response = $this->_buildAndSendRequest($request);

        // Check the response
        if ($response == null) {
            throw new Exception("OpenSRS API Error: Unable to communicate with OpenSRS.");
        }

        // XMLize the reply
        $response = XmlFunctions::xmlize($response);

        // Get the response
        $response = $response['OPS_envelope']['#']['body'][0]['#']['data_block'][0]['#']['dt_assoc'][0]['#']['item'];

        // Check the response code
        if(@$response[4]['#'] == '415') {

            // Throw error
            throw new Exception("OpenSRS API Error: Unable to authenticate using the Domain Username & Password.");
        }

        // Get the cookie
        $response = $response[4]['#']['dt_assoc'][0]['#']['item'][1]['#'];

        // return it
        return $response;
    }

    /**
     * Private function used for building the xml request and sending it.
     *
     * @param String $request The xml request body
     * @return The xml string response
     */
    function _buildAndSendRequest($request)
    {
        // Make the start of the XML request
        $request = '<?xml version=\'1.0\' encoding="UTF-8" standalone="no" ?>
                    <!DOCTYPE OPS_envelope SYSTEM "ops.dtd">
                    <OPS_envelope>
                     <header>
                      <version>'.$this->apiVersion.'</version>
                     </header>
                     <body>
                       '.$request.'
                     </body>
                    </OPS_envelope>';

        // Generate the signature
        $signature = md5(md5($request.$this->key).$this->key);

        // Contruct the headers
        $header = "POST ".$this->host." HTTP/1.0\r\n";
        $header .= "Content-Type: text/xml\r\n";
        $header .= "X-Username: " . $this->user . "\r\n";
        $header .= "X-Signature: " . $signature . "\r\n";
        $header .= "Content-Length: " . strlen($request) . "\r\n\r\n";

        // Open the connection
        $fp = @fsockopen ("ssl://$this->host", $this->port, $errno, $errstr, 30);
        if (!$fp) {
            $this->logger->log(4, "Couldn't connect to OpenSRS: $errno, $errstr");
            throw new Exception("OpenSRS API Error: Unable to communicate with OpenSRS. Please check your settings.");
        }

        // Send the request
        fputs ($fp, $header . $request);
        $response = "";

        // Gather the reply
        while (!feof($fp)) 
        {
            $response .= fgets ($fp, 1024);
        }

        // Close the file
        fclose($fp);

        // Log the reply
        $this->logger->log(4, "OpenSRS response: " . $response);

        // drop the headers so we can xmlize it
        $arrResponse = explode("\n", $response);
        $response = "";
        $flag = false;
        foreach ($arrResponse as $line)
        {
            if ($flag) $response .= $line."\n";
            else if (trim($line) == "") $flag = true;
        }

        // Return the final reply
        return $response;
    }
}

?>
