<?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'),
	);

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

	// Required abstract functions
	public function username_value() {} // Not used
	public function password_value() {} // Not used

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

	public function expire() {
		return $this->valid_to();
	}

	public function name() {
		if ($this->cert) {
			return sprintf('%s:%s',$this->ssl_ca->subject(),$this->display('cert'));
		} else
			return $this->display('csr');
	}

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

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

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

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

	// @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 details() {
		return SSL::details($this->cert);
	}

	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();
				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->status OR ! preg_match('/client/',$this->service->product->plugin()->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');
		// @todo change this so an admin can force this.
		$force = TRUE;

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

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

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

			return TRUE;
		} else {
			print_r(array(
				'csr'=>$this->csr,
				'ca'=>$this->ssl_ca->sign_cert,
				'capk'=>$this->ssl_ca->sign_pk,
				'days'=>$this->service->product->plugin()->days,
				'ssl'=>$ssl_conf,
				'x509e'=>$this->service->product->plugin()->extensions
			));

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