<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class supports Services
 *
 * @package    OSB
 * @subpackage SSL
 * @category   Models
 * @author     Deon George
 * @copyright  (c) 2010 Open Source Billing
 * @license    http://dev.osbill.net/license.html
 */
class Model_Service_Plugin_SSL extends Model_Service_Plugin {
	protected $_table_name = 'service__ssl';
	protected $_updated_column = FALSE;

	// Relationships
	protected $_belongs_to = array(
		'service'=>array(),
	);
	protected $_has_one = array(
		'ssl_ca'=>array('far_key'=>'ssl_ca_id','foreign_key'=>'id'),
		'ssl'=>array('far_key'=>'ssl_id','foreign_key'=>'id'),
	);

	protected $_display_filters = array(
		'csr'=>array(
			array('SSL::csrsubject',array(':value')),
		),
		'cert'=>array(
			array('SSL::subject',array(':value')),
		),
	);

	// Required abstract functions
	public function service_view() {
		return View::factory('service/user/plugin/ssl/view')
			->set('so',$this);
	}

	public function name() {
		return $this->display($this->cert ? 'cert' : 'csr');
	}

	// @todo This needs to be validated for this model
	public function product() {
		if ($this->provided_adsl_plan_id)
			return $this->adsl_plan;
		else
			return $this->service->product->plugin();
	}

	public function valid_from($format=FALSE) {
		return SSL::from($this->cert,$format);
	}

	public function valid_to($format=FALSE) {
		return SSL::expire($this->cert,$format);
	}

	public function serial_num() {
		return SSL::serial($this->cert);
	}

	public function hash() {
		return SSL::hash($this->cert);
	}

	public function version() {
		return SSL::version($this->cert);
	}

	/**
	 * Get specific service details for use in other modules
	 * For Example: Invoice
	 *
	 * @todo Make the rendered items configurable
	 * @todo Change this method name, now that it is public
	 */
	// @todo This needs to be validated for this model
	public function _details($type) {
		switch ($type) {
			case 'invoice_detail_items':
				return array(
					_('Service Address')=>$this->service_address ? $this->display('service_address') : '>NotSet<',
					_('Contract Until')=>$this->contract_date_end(),
				);
				break;
			default:
				return parent::$_details($type);
		}
	}

	// @todo This needs to be validated for this model
	public function admin_update() {
		return View::factory('service/admin/plugin/ssl/update')
			->set('mediapath',Route::get('default/media'))
			->set('so',$this);
	}

	public function download_button() {
		if (! $this->service->active OR ! preg_match('/client/',$this->ssl->extensions) OR $this->valid_to() < time())
			return '';

		// @todo Do some password validation
		$output = Form::open('user/ssl/download');
		$output .= Form::hidden('sid',$this->service->id);
		$output .= _('Choose a password').': '.Form::password('passwd','').'<br/><br/>';
		$output .= Form::submit('download','Download',array('class'=>'form_button'));
		return $output;
	}

	public function cacerts() {
		$return = array();

		$x = $this->ssl_ca_id;
		while ($x) {
			$sco = ORM::factory('ssl_ca',$x);
			array_push($return,$sco->sign_cert);
			$x = $sco->parent_ssl_ca_id;
		}

		return $return;
	}

	public function renew() {
		$d = SSL::details($this->cert);
		$ssl_conf = Kohana::config('ssl');

		// If our certificate is not old enough skip
		if ($d['validTo_time_t'] > time()+$ssl_conf['min_renew_days']*86400)
			return FALSE;

		$res = openssl_csr_sign($this->csr,$this->ssl_ca->sign_cert,$this->ssl_ca->sign_pk,$this->ssl->days,array(
			'config'=>$ssl_conf['config'],
			'x509_extensions'=>$this->ssl->extensions,
		),time());

		if (openssl_x509_export($res,$cert)) {
			$this->cert = $cert;
			$this->save();

			return TRUE;
		} else
			throw new Kohana_Exception('Error Creating SSL Certificate :error',array(':error'=>openssl_error_string()));
	}
}
?>