<?php

use Module\Ssl\Opensrs as Lib;

require_once 'lib-mbapi/include/modules/sslmodule/sslmodule.php';

// require OpenSRS module library
$moduleDirectory = dirname(__FILE__);
require_once $moduleDirectory . '/opensrs/lib/Registry.php';
require_once $moduleDirectory . '/opensrs/lib/Service.php';
require_once $moduleDirectory . '/opensrs/lib/ServicesDescriptor.php';
require_once $moduleDirectory . '/opensrs/lib/Api.php';
require_once $moduleDirectory . '/opensrs/lib/Command.php';
require_once $moduleDirectory . '/opensrs/lib/Response.php';
require_once $moduleDirectory . '/opensrs/lib/response/Attributes.php';
require_once $moduleDirectory . '/opensrs/lib/response/Error.php';
require_once $moduleDirectory . '/opensrs/lib/Negotiator.php';
require_once $moduleDirectory . '/opensrs/lib/Exception.php';

class OpensrsSsl extends SSLModule
{
	const SERVICE_GEOTRUST_QUICKSSL					= 'GeoTrust QuickSSL';
	const SERVICE_GEOTRUST_QUICKSSLPREMIUM			= 'GeoTrust QuickSSL Premium';
	const SERVICE_GEOTRUST_TRUEBUSINESSID			= 'GeoTrust TrueBusinessID';
	const SERVICE_GEOTRUST_TRUEBUSINESSIDEV			= 'GeoTrust TrueBusinessID with EV';
	const SERVICE_GEOTRUST_TRUEBUSINESSIDWILDCARD	= 'GeoTrust TrueBusinessID Wildcard';
	
	const SERVICE_THAWTE_SGCSUPERCERTS				= 'Thawte SGC SuperCerts';
	const SERVICE_THAWTE_SSL123						= 'Thawte SSL123';
	const SERVICE_THAWTE_SSLWEBSERVER				= 'Thawte SSL Web Server Certificates';
	const SERVICE_THAWTE_SSLWEBSERVEREV				= 'Thawte SSL Web Server Certificates with EV';
	const SERVICE_THAWTE_SSLWEBSERVERWILDCARD		= 'Thawte SSL Web Server Certificates Wildcard';
	
	const SERVICE_TRUSTWAVE_DV						= 'Trustwave Domain-Vetted';
	const SERVICE_TRUSTWAVE_EV						= 'Trustwave Extended Validation SSL';
	const SERVICE_TRUSTWAVE_PREMIUMSSL				= 'Trustwave Premium 256-Bit SSL';
	const SERVICE_TRUSTWAVE_PREMIUMSSL_WILDCARD		= 'Trustwave Premium Wildcard 256-Bit SSL';
	
	const SERVICE_VERISIGN_SECURESITE				= 'VeriSign Secure Site';
	const SERVICE_VERISIGN_SECURESITEEV				= 'VeriSign Secure Site with EV';
	const SERVICE_VERISIGN_SECURESITEPRO			= 'VeriSign Secure Site Pro';
	const SERVICE_VERISIGN_SECURESITEPROEV			= 'VeriSign Secure Site Pro with EV';
	
	const SERVICE_COMODO_SSL						= 'Comodo SSL';
	const SERVICE_COMODO_INSTANTSSL					= 'Comodo Instant SSL';
	const SERVICE_COMODO_PREMIUMSSL					= 'Comodo Premium SSL';
	const SERVICE_COMODO_EV							= 'Comodo EV';
	const SERVICE_COMODO_WILDCARD					= 'Comodo Wildcard';
	const SERVICE_COMODO_PREMIUMWILDCARD			= 'Comodo Premium Wildcard';
	
	const CONTACT_ORGANIZATION						= 'organization';
	const CONTACT_ADMIN								= 'admin';
	const CONTACT_BILLING							= 'billing';
	const CONTACT_TECH								= 'tech';
	const CONTACT_SIGNER							= 'signer';
	
	const PREFIX_ATTRIBUTES							= 'opensrsssl-';
	
	public function __construct($input)
	{
		parent::__construct($input);
		$this->capabilities = array(
			SSLModule::CAPABILITY_USER_PARAMS
		);
		Lib\Regisrty::getInstance()->servicesDescriptor = new Lib\ServicesDescriptor($servicesDescriptorPath = dirname(__FILE__) . '/opensrs/config/services_descriptor.php');
		$config = $this->getConfig();
		Lib\Regisrty::getInstance()->api = new Lib\Api(new Lib\Negotiator(
			$config['username'],
			$config['key'],
			$config['host'],
			$config['port']
		));
	}
	
	public function getModuleInfo()
	{
		return array(
			"type"			=> "sslmodule",
			"version"		=> "1.0.0",
			"displayName"	=> "OpenSRS",
			"author"		=> "Parallels",
		);
	}
	
	public function getCertificates()
	{
		$certificates = array();
		foreach (Lib\Regisrty::getInstance()->servicesDescriptor->getNames() as $name) {
			$certificates[$name] = false;
		}
		return $certificates;
	}
	
	public function getPeriod($certificate)
	{
		$service = new Lib\Service($certificate);
		return $service->period;
	}
	
	public function getCertificateAttributeName()
	{
		return self::PREFIX_ATTRIBUTES . 'certificate';
	}
	
	public function getPeriodAttributeName()
	{
		return self::PREFIX_ATTRIBUTES . 'period';
	}

	public function cryptedConfigParams()
	{
		return array("key");
	}
	
	/**
	 * This defines how the module is configured in the application.
	 * This section should contain any piece of data needed to connect with the cert provider.
	 * These will be used to build a form the admin will use to configure their account
	 * settings given to them by the cert provider.
	 * 
	 * Поддерживаются следующие типы полей:
	 * 
	 * CIT_TEXT			text
	 * CIT_TEXT_AREA	textarea
	 * CIT_RADIO		radio group
	 * CIT_SELECT		drop down list
	 * CIT_BOOL			true/false radio group
	 * CIT_PASSWORD		password
	 * 
	 * @param	$ui_form	объект формы, в которую слеудет добавить
	 * 						необходимые поля ввода
	 * @param	$config		ассоциативный массив текущих параметров конфигурации провайдера,
	 * 						пустой в случае создания нового провайдера
	 */
	protected function drawConfigParams(UIForm $form, array $config)
	{
		$form->addInputPanel(
			$panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_CONFIG_CONNECTION"))
		);
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> 'host',
			'type'		=> SSLModule::CIT_TEXT,
			'default'	=> isset($config['host']) ? $config['host'] : 'ssl://horizon.opensrs.net',
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_CONFIG_HOST',
		)));
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> 'port',
			'type'		=> SSLModule::CIT_TEXT,
			'default'	=> isset($config['port']) ? $config['port'] : '55443',
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_CONFIG_PORT',
		)));
		$panel->addInputControl(UIFactory()->InputConfig(array(
			"id"		=> "username",
			"type"		=> SSLModule::CIT_TEXT,
			"default"	=> isset($config["username"]) ? $config["username"] : "",
			"required"	=> true,
			"title"		=> "TRANS_SSL_MODULE_INTERNAL_OPENSRS_CONFIG_USERNAME",
		)));
		$panel->addInputControl(UIFactory()->InputConfig(array(
			"id"		=> "key",
			"type"		=> SSLModule::CIT_PASSWORD,
			"default"	=> isset($config["key"]) ? $config["key"] : "",
			"required"	=> true,
			"title"		=> "TRANS_SSL_MODULE_INTERNAL_OPENSRS_CONFIG_KEY",
		)));
	}
	
	
	protected function getCollectedConfigParams(UIForm $form, array $config)
	{
		$values = array();
		$form->storeValues($values);
		return array(
			'host'		=> $values['host'],
			'port'		=> $values['port'],
			'username'	=> $values['username'],
			'key'		=> $values['key']
		);
	}

	protected function drawUserParams(UIForm $form, array $config, array $attributes)
	{
		$service = new Lib\Service($attributes[$this->getCertificateAttributeName()]);
		
		if ($service->isAllowedValidationSettings) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS")));
			
			// domain name
			if ($service->isAllowedDomain) {
				$panel->addInputControl(UIFactory()->InputConfig(array(
					'id'		=> 'domain',
					'type'		=> SSLModule::CIT_TEXT,
					'checker'	=> '/^.{0,64}$/',
					'default'	=> (
						isset($attributes[self::PREFIX_ATTRIBUTES . 'domain']) ?
						$attributes[self::PREFIX_ATTRIBUTES . 'domain'] :
						(isset($attributes['commonName']) ? $attributes['commonName'] : '')
					),
					'required'	=> $service->isRequiredDomain,
					'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_DOMAIN_NAME',
				)));
			}
			
			// approrev email
			if ($service->isAllowedApproverEmail) {
				$domain = isset($attributes['commonName']) ? $attributes['commonName'] : null;
				if (is_null($domain)) {
					throw new ProductException(ProductException::E_FAIL_OPERATION, 'Unable to process certificate registration: domain name not specified. Please go to subscription details page and add property with name "commonName" to this subscription.');
				}
				$items = array();
				foreach (Lib\Regisrty::getInstance()->api->queryApproverList($service->code, $domain) as $email) {
					$items[] = array($email, $email);
				}
				$panel->addInputControl(UIFactory()->InputConfig(array(
					'id'		=> 'approver_email',
					'type'		=> SSLModule::CIT_SELECT,
					'default'	=> isset($attributes[self::PREFIX_ATTRIBUTES . 'approver_email']) ? $attributes[self::PREFIX_ATTRIBUTES . 'approver_email'] : '',
					'required'	=> $service->isRequiredApproverEmail,
					'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_APPROVER_EMAIL',
					'items'		=> $items
				)));
			}
			
			// server type
			if ($service->isAllowedServerType) {
				$items = array();
				foreach ($service->serverTypes as $type) {
					$items[] = array($type, $type);
				}
				$panel->addInputControl(UIFactory()->InputConfig(array(
					'id'		=> 'server_type',
					'type'		=> SSLModule::CIT_SELECT,
					'default'	=> (
						isset($attributes[self::PREFIX_ATTRIBUTES . 'server_type']) ?
						$attributes[self::PREFIX_ATTRIBUTES . 'server_type'] :
						(isset($attributes['WebServerType']) ? $attributes['WebServerType'] : '')
					),
					'required'	=> $service->isRequiredServerType,
					'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_SERVER_TYPE',
					'items'		=> $items
				)));
			}
			
			// server count
			if ($service->isAllowedServerCount) {
				$items = array();
				for ($i = 1; $i < 500; $i++) {
					$items[] = array($i, $i);
				}
				$panel->addInputControl(UIFactory()->InputConfig(array(
					'id'		=> 'server_count',
					'type'		=> SSLModule::CIT_SELECT,
					'default'	=> isset($attributes[self::PREFIX_ATTRIBUTES . 'server_count']) ? $attributes[self::PREFIX_ATTRIBUTES . 'server_count'] : '',
					'required'	=> $service->isRequiredServerCount,
					'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_SERVER_COUNT',
					'items'		=> $items
				)));
			}
		}
		
		if ($service->isRequiredContactOrganization) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ORGANIZATION")));
			$this->_drawContact($panel, self::CONTACT_ORGANIZATION, $attributes, $service);
		}
		if ($service->isRequiredContactAdmin) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADMIN")));
			$this->_drawContact($panel, self::CONTACT_ADMIN, $attributes, $service);
		}
		if ($service->isRequiredContactBilling) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_BILLING")));
			$this->_drawContact($panel, self::CONTACT_BILLING, $attributes, $service);
		}
		if ($service->isRequiredContactTech) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_TECH")));
			$this->_drawContact($panel, self::CONTACT_TECH, $attributes, $service);
		}
		if ($service->isRequiredContactSigner) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_SIGNER")));
			$this->_drawContact($panel, self::CONTACT_SIGNER, $attributes, $service);
		}
		
		if ($service->isAllowedCertificateSettings) {
			$form->addInputPanel($panel = UIFactory()->InputPanel(blmsg("TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CERTIFICATE_SETTINGS")));
			
			// CSR
			if ($service->isAllowedCSR) {
				$panel->addInputControl(UIFactory()->InputConfig(array(
					'id'		=> 'csr',
					'type'		=> SSLModule::CIT_TEXT_AREA,
					'default'	=> (
						isset($attributes[self::PREFIX_ATTRIBUTES . 'csr']) ?
						$attributes[self::PREFIX_ATTRIBUTES . 'csr'] :
						(isset($attributes['CSR']) ? $attributes['CSR'] : '')
					),
					'required'	=> $service->isRequiredCSR,
					'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CERTIFICATE_SETTINGS_CSR',
				)));
			}
			// special instructions
			if ($service->isAllowedSpecialInstructions) {
				$panel->addInputControl(UIFactory()->InputConfig(array(
					'id'		=> 'special_instructions',
					'type'		=> SSLModule::CIT_TEXT_AREA,
					'default'	=> isset($attributes[self::PREFIX_ATTRIBUTES . 'special_instructions']) ? $attributes[self::PREFIX_ATTRIBUTES . 'special_instructions'] : '',
					'required'	=> $service->isRequiredSpecialInstructions,
					'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CERTIFICATE_SETTINGS_SPECIAL_INSTRUCTIONS',
				)));
			}
		}
	}
	
	protected function getCollectedUserParamsFromUIForm(UIForm $form, array $config, array $attributes)
	{
		$values = array();
		$form->storeValues($values);
		$result = array();
		foreach ($values as $key => $value) {
			$result[self::PREFIX_ATTRIBUTES . $key] = $value;
		}
		return $result;
	}
	
	public function getParamGroupsMap()
	{
		return array(
			'validation_settings' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS',
			'contact_organization' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ORGANIZATION',
			'contact_admin' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADMIN',
			'contact_billing' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_BILLING',
			'contact_tech' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_TECH',
			'contact_signer' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_SIGNER',
			'certificate_settings' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CERTIFICATE_SETTINGS'
		); 
	}
	
	protected function getUserParamsDescriptor(array $config, array $attributes)
	{
		$service = new Lib\Service($attributes[$this->getCertificateAttributeName()]);
		$descriptor = array();
		if ($service->isAllowedValidationSettings) {
			$descriptor['validation_settings'] = array();
			// domain name
			if ($service->isAllowedDomain) {
				$descriptor['validation_settings'][] = array(
					'id'		=> 'domain',
					'type'		=> SSLModule::CIT_TEXT,
					'checker'	=> '/^.{0,64}$/',
					'title'		=> blmsg('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_DOMAIN_NAME'),
					'required'	=> $service->isRequiredDomain,
					'default'	=> (
						isset($attributes[self::PREFIX_ATTRIBUTES . 'domain']) ?
						$attributes[self::PREFIX_ATTRIBUTES . 'domain'] :
						(isset($attributes['commonName']) ? $attributes['commonName'] : '')
					)
				);
			}
			// approver email
			if ($service->isAllowedApproverEmail) {
				$domain = isset($attributes['commonName']) ? $attributes['commonName'] : null;
				if (is_null($domain)) {
					throw new ProductException(ProductException::E_FAIL_OPERATION, 'Unable to process certificate registration: domain name not specified. Please add attribute "commonName" to this subscription.');
				}
				$items = array();
				foreach (Lib\Regisrty::getInstance()->api->queryApproverList($service->code, $domain) as $email) {
					$items[] = array($email, $email);
				}
				$descriptor['validation_settings'][] = array(
					'id'		=> 'approver_email',
					'class'		=> '',
					'type'		=> SSLModule::CIT_SELECT,
					'title'		=> blmsg('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_APPROVER_EMAIL'),
					'required'	=> $service->isRequiredApproverEmail,
					'default'	=> isset($attributes[self::PREFIX_ATTRIBUTES . 'approver_email']) ? $attributes[self::PREFIX_ATTRIBUTES . 'approver_email'] : '',
					'items'		=> $items
				);
			}
			// server type
			if ($service->isAllowedServerType) {
				$items = array();
				foreach ($service->serverTypes as $type) {
					$items[] = array($type, $type);
				}
				$descriptor['validation_settings'][] = array(
					'id'		=> 'server_type',
					'class'		=> '',
					'type'		=> SSLModule::CIT_SELECT,
					'title'		=> blmsg('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_SERVER_TYPE'),
					'required'	=> $service->isRequiredServerType,
					'default'	=> (
						isset($attributes[self::PREFIX_ATTRIBUTES . 'server_type']) ?
						$attributes[self::PREFIX_ATTRIBUTES . 'server_type'] :
						(isset($attributes['WebServerType']) ? $attributes['WebServerType'] : '')
					),
					'items'		=> $items
				);
			}
			// server count
			if ($service->isAllowedServerCount) {
				$items = array();
				for ($i = 1; $i < 500; $i++) {
					$items[] = array($i, $i);
				}
				$descriptor['validation_settings'][] = array(
					'id'		=> 'server_count',
					'class'		=> '',
					'type'		=> SSLModule::CIT_SELECT,
					'title'		=> blmsg('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_VALIDATION_SETTINGS_SERVER_COUNT'),
					'required'	=> $service->isRequiredServerCount,
					'default'	=> isset($attributes[self::PREFIX_ATTRIBUTES . 'server_count']) ? $attributes[self::PREFIX_ATTRIBUTES . 'server_count'] : '',
					'items'		=> $items
				);
			}
		}
		if ($service->isRequiredContactOrganization) {
			$descriptor['contact_organization'] = $this->_getContactDescriptor(self::CONTACT_ORGANIZATION, $attributes, $service);
		}
		if ($service->isRequiredContactAdmin) {
			$descriptor['contact_admin'] = $this->_getContactDescriptor(self::CONTACT_ADMIN, $attributes, $service);
		}
		if ($service->isRequiredContactBilling) {
			$descriptor['contact_billing'] = $this->_getContactDescriptor(self::CONTACT_BILLING, $attributes, $service);
		}
		if ($service->isRequiredContactTech) {
			$descriptor['contact_tech'] = $this->_getContactDescriptor(self::CONTACT_TECH, $attributes, $service);
		}
		if ($service->isRequiredContactSigner) {
			$descriptor['contact_signer'] = $this->_getContactDescriptor(self::CONTACT_SIGNER, $attributes, $service);
		}
		if ($service->isAllowedCertificateSettings) {
			$descriptor['certificate_settings'] = array();
			// CSR
			if ($service->isAllowedCSR) {
				$descriptor['certificate_settings'][] = array(
					'id'		=> 'csr',
					'style'		=> 'width: 98%; height: 160px;',
					'type'		=> SSLModule::CIT_TEXT_AREA,
					'title'		=> blmsg('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CERTIFICATE_SETTINGS_CSR'),
					'required'	=> $service->isRequiredCSR,
					'default'	=> (
						isset($attributes[self::PREFIX_ATTRIBUTES . 'csr']) ?
						$attributes[self::PREFIX_ATTRIBUTES . 'csr'] :
						(isset($attributes['CSR']) ? $attributes['CSR'] : '')
					)
				);
			}
			// special instructions
			if ($service->isAllowedSpecialInstructions) {
				$descriptor['certificate_settings'][] = array(
					'id'		=> 'special_instructions',
					'style'		=> 'width: 98%; height: 160px;',
					'type'		=> SSLModule::CIT_TEXT_AREA,
					'title'		=> blmsg('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CERTIFICATE_SETTINGS_SPECIAL_INSTRUCTIONS'),
					'required'	=> $service->isRequiredSpecialInstructions,
					'default'	=> isset($attributes[self::PREFIX_ATTRIBUTES . 'special_instructions']) ? $attributes[self::PREFIX_ATTRIBUTES . 'special_instructions'] : ''
				);
			}
		}
		return $descriptor;
	}
	
	protected function getCollectedUserParamsFromArray(array $config, array $attributes, array $values)
	{
		$result = array();
		foreach ($values as $key => $value) {
			$result[self::PREFIX_ATTRIBUTES . $key] = $value;
		}
		return $result;
	}
	
	protected function drawProductParams(UIForm $ui_form, array $config, array $product)
	{
	}

	protected function getCollectedProductParams(UIForm $ui_form, array $config, array $product)
	{
	}
	
	protected function pluginCheckAttributes(array $config, array $attributes, $action)
	{
		$service = new Lib\Service($attributes[$this->getCertificateAttributeName()]);
		$errors = array();
		switch ($action) {
			case "add":
				if (!$this->_isRequiredDataCollected($service, $attributes)) {
					$errors["NotEnoughData"] = "Not enough data to place order. Customer should to fill this data to continue certificate registration.";
				}
		}
		return $errors;
	}

	protected function pluginAdd(array $config, array $attributes)
	{
		$service = new Lib\Service($attributes[$this->getCertificateAttributeName()]);
		try {
			$orderId = isset($attributes[self::PREFIX_ATTRIBUTES . 'order_id']) ? $attributes[self::PREFIX_ATTRIBUTES . 'order_id'] : null;
			
			// check required data for new orders
			if (!$orderId && !$this->_isRequiredDataCollected($service, $attributes)) {
				return array(
					"status" => SSLModule::ACTION_STATUS_PENDING,
					"status_reason" => "TRANS_SSL_MODULE_INTERNAL_OPENSRS_STATUS_WAITING_FOR_ADDITIONAL_DATA"
				);
			}
			
			// create order, if it does not created already
			if (!$orderId) {
				dbg('OpenSRS: Perform certificate registration');
				$service = new Lib\Service($attributes[$this->getCertificateAttributeName()]);
				$orderId = Lib\Regisrty::getInstance()->api->register(
					$service->code,
					$attributes,
					$service->isRequiredContactOrganization,
					$service->isRequiredContactAdmin,
					$service->isRequiredContactBilling,
					$service->isRequiredContactTech,
					$service->isRequiredContactSigner
				);
				if (!$orderId || $orderId < 0) {
					$message = 'OpenSRS Error: Unable to register SSL certificate.';
					throw new Lib\Exception($message);
				}
				return array(
					'status' => SSLModule::ACTION_STATUS_PENDING,
					'status_reason' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_STATUS_WAITING_FOR_COMPLETE_PURCHASE',
					'data' => array(
						self::PREFIX_ATTRIBUTES . 'order_id' => $orderId
					)
				);
			}
			
			// check status of order
			if ($orderId) {
				dbg('OpenSRS: Retrieve product identifier');
				if ($productId = Lib\Regisrty::getInstance()->api->getOrderInfo($orderId)) {
					return array(
						"status" => SSLModule::ACTION_STATUS_COMPLETED,
						"data" => array(
							self::PREFIX_ATTRIBUTES . 'product_id' => $productId,
							'CSR' => $attributes['CSR'],
							'SSLCertificate' => ''
						)
					);
				}
			}
			
			return array(
				'status' => SSLModule::ACTION_STATUS_PENDING,
				'status_reason' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_STATUS_WAITING_FOR_COMPLETE_PURCHASE'
			);
		} catch (Exception $exception) {
			$this->pushErrorToAdminsToDo($exception->getMessage());
			return array(
				"status" => SSLModule::ACTION_STATUS_ERROR,
				"error" => $exception->getMessage()
			);
		}
	}

	protected function pluginRenew(array $config, array $attributes)
	{
		$data = array();
		if (isset($attributes[self::PREFIX_ATTRIBUTES . 'product_id'])) {
			$data["SSLCertificate"] = $attributes["SSLCertificate"] = null;
			$csrData = $this->generateCSR();
			$data["CSR"] = $attributes["CSR"] = $csrData["csr"];
			$data["PVT"] = $attributes["PVT"] = $csrData["pvt"];
			$data[self::PREFIX_ATTRIBUTES . 'csr'] = $attributes[self::PREFIX_ATTRIBUTES . 'csr'] = $csrData["csr"];
			$data[self::PREFIX_ATTRIBUTES . 'product_id'] = $attributes[self::PREFIX_ATTRIBUTES . 'product_id'] = null;
			$data[self::PREFIX_ATTRIBUTES . 'order_id'] = $attributes[self::PREFIX_ATTRIBUTES . 'order_id'] = null;
		}
		$response = $this->pluginAdd($config, $attributes);
		$response["data"] = isset($response["data"]) ? array_merge($data, $response["data"]) : $data;
		return $response;
	}

	protected function pluginGetIssuedCert(array $config, array $attributes)
	{
	}

	protected function pluginGetCSR(array $config, array $attributes)
	{
	}
	
	protected function pluginDelete(array $config, array $attributes)
	{
	}

	public static function webServerTypes($attributes)
	{
		$service = new Lib\Service($attributes[self::PREFIX_ATTRIBUTES . 'certificate']);
		$items = array();
		foreach ($service->serverTypes as $type) {
			$items[$type] = $type;
		}
		return array('plesk', $items);
	}
	
	private function createOrder($config, $certificate, $period) {
		return $config['login'] . '-' . $certificate . '-' . $period . '-' . time();
	}
	
	private function uploadAdditionalData($config, $orderId, $approverEmail) {
		return true;
	}
	
	private function downloadCertificate($config, $orderId) {
		return 'certificate-body';
	}
	
	private function _isRequiredDataCollected(Lib\Service $service, $attributes)
	{
		if ($service->isRequiredCSR && !isset($attributes[self::PREFIX_ATTRIBUTES . 'csr'])) {
			return false;
		}
		if ($service->isRequiredSpecialInstructions && !isset($attributes[self::PREFIX_ATTRIBUTES . 'special_instructions'])) {
			return false;
		}
		if ($service->isRequiredDomain && !isset($attributes[self::PREFIX_ATTRIBUTES . 'domain'])) {
			return false;
		}
		if ($service->isRequiredApproverEmail && !isset($attributes[self::PREFIX_ATTRIBUTES . 'approver_email'])) {
			return false;
		}
		if ($service->isRequiredServerType && !isset($attributes[self::PREFIX_ATTRIBUTES . 'server_type'])) {
			return false;
		}
		if ($service->isRequiredServerCount && !isset($attributes[self::PREFIX_ATTRIBUTES . 'server_count'])) {
			return false;
		}
		if ($service->isRequiredContactOrganization && !$this->_isRequiredContactDataCollected($service, $attributes, self::CONTACT_ORGANIZATION)) {
			return false;
		}
		if ($service->isRequiredContactAdmin && !$this->_isRequiredContactDataCollected($service, $attributes, self::CONTACT_ADMIN)) {
			return false;
		}
		if ($service->isRequiredContactBilling && !$this->_isRequiredContactDataCollected($service, $attributes, self::CONTACT_BILLING)) {
			return false;
		}
		if ($service->isRequiredContactTech && !$this->_isRequiredContactDataCollected($service, $attributes, self::CONTACT_TECH)) {
			return false;
		}
		if ($service->isRequiredContactSigner && !$this->_isRequiredContactDataCollected($service, $attributes, self::CONTACT_SIGNER)) {
			return false;
		}
		return true;
	}
	
	private function _isRequiredContactDataCollected(Lib\Service $service, $attributes, $type) {
		if (self::CONTACT_ORGANIZATION != $type && !isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_first_name'])) {
			return false;
		}
		if (self::CONTACT_ORGANIZATION != $type && !isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_last_name'])) {
			return false;
		}
		if (self::CONTACT_ORGANIZATION != $type && $service->isRequiredTitle && !isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_title'])) {
			return false;
		}
		if (self::CONTACT_ORGANIZATION == $type && !isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_org_name'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address1'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_city'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_state'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_postal_code'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_country'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_phone'])) {
			return false;
		}
		if (!isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_email'])) {
			return false;
		}
		return true;
	}
	
	private function _drawContact($panel, $type, $attributes, $service)
	{
		// first name
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_first_name',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,64}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_first_name']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_first_name'] :
				(isset($attributes['BillingFName']) ? $attributes['BillingFName'] : '')
			),
			'required'	=> self::CONTACT_ORGANIZATION != $type,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_FIRST_NAME',
		)));
		
		// last name
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_last_name',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,64}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_last_name']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_last_name'] :
				(isset($attributes['BillingLName']) ? $attributes['BillingLName'] : '')
			),
			'required'	=> self::CONTACT_ORGANIZATION != $type,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_LAST_NAME',
		)));
		
		// title
		if (self::CONTACT_ORGANIZATION != $type && $service->isAllowedTitle) {
			$panel->addInputControl(UIFactory()->InputConfig(array(
				'id'		=> $type . '_title',
				'type'		=> SSLModule::CIT_TEXT,
				'checker'	=> '/^.{0,64}$/',
				'default'	=> (
					isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_title']) ?
					$attributes[self::PREFIX_ATTRIBUTES . $type . '_title'] :
					''
				),
				'required'	=> $service->isRequiredTitle,
				'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_TITLE',
			)));
		}
		
		// organization
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_org_name',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,64}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_org_name']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_org_name'] :
				(isset($attributes['BillingOrgName']) ? $attributes['BillingOrgName'] : '')
			),
			'required'	=> self::CONTACT_ORGANIZATION == $type,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ORGANIZATION',
		)));
		
		// address 1
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_address1',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,100}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address1']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_address1'] :
				(isset($attributes['BillingAddress1']) ? $attributes['BillingAddress1'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADDRESS1',
		)));
		
		// address 2
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_address2',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,100}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address2']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_address2'] :
				(isset($attributes['BillingAddress2']) ? $attributes['BillingAddress2'] : '')
			),
			'required'	=> false,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADDRESS2',
		)));
		
		// address 3
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_address3',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,100}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address3']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_address3'] :
				''
			),
			'required'	=> false,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADDRESS3',
		)));
		
		// city
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_city',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,64}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_city']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_city'] :
				(isset($attributes['BillingCity']) ? $attributes['BillingCity'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_CITY',
		)));
		
		// state
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_state',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,32}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_state']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_state'] :
				(isset($attributes['BillingState']) ? $attributes['BillingState'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_STATE',
		)));
		
		// postal code
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_postal_code',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,32}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_postal_code']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_postal_code'] :
				(isset($attributes['BillingPostalCode']) ? $attributes['BillingPostalCode'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_POSTAL_CODE',
		)));
		
		// country
		$countries = array();
		foreach ($this->getCountries() as $code => $name) {
			$countries[] = array($code, $name);
		}
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_country',
			'type'		=> SSLModule::CIT_SELECT,
			'items'		=> $countries,
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_country']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_country'] :
				(isset($attributes['BillingCountry']) ? $attributes['BillingCountry'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_COUNTRY',
		)));
		
		// phone
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'			=> $type . '_phone',
			'type'			=> SSLModule::CIT_TEXT,
			'checker'		=> '/^\+\d{1,3}\.\d{1,10}(x\d{1,4})?$/',
			'description'	=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_PHONE_DESCRIPTION',
			'default'		=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_phone']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_phone'] :
				(isset($attributes['BillingPhone']) ? $attributes['BillingPhone'] : '')
			),
			'required'		=> true,
			'title'			=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_PHONE',
		)));
		
		// fax
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_fax',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.{0,20}$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_fax']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_fax'] :
				(isset($attributes['BillingFax']) ? $attributes['BillingFax'] : '')
			),
			'required'	=> false,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_FAX',
		)));
		
		// email
		$panel->addInputControl(UIFactory()->InputConfig(array(
			'id'		=> $type . '_email',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> '/^.+@.+\..+$/',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_email']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_email'] :
				(isset($attributes['BillingEmailAddress']) ? $attributes['BillingEmailAddress'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_EMAIL',
		)));
	}
	
	private function _getContactDescriptor($type, $attributes, $service)
	{
		$result = array();
		
		// first name
		$result[] = array(
			'id'		=> $type . '_first_name',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,64}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 64))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_first_name']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_first_name'] :
				(isset($attributes['BillingFName']) ? $attributes['BillingFName'] : '')
			),
			'required'	=> self::CONTACT_ORGANIZATION != $type,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_FIRST_NAME',
		);
		
		// last name
		$result[] = array(
			'id'		=> $type . '_last_name',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,64}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 64))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_last_name']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_last_name'] :
				(isset($attributes['BillingLName']) ? $attributes['BillingLName'] : '')
			),
			'required'	=> self::CONTACT_ORGANIZATION != $type,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_LAST_NAME',
		);
		
		// title
		if (self::CONTACT_ORGANIZATION != $type && $service->isAllowedTitle) {
			$result[] = array(
				'id'		=> $type . '_title',
				'type'		=> SSLModule::CIT_TEXT,
				'checker'	=> array('pattern' => '/^.{0,64}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 64))),
				'default'	=> (
					isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_title']) ?
					$attributes[self::PREFIX_ATTRIBUTES . $type . '_title'] :
					''
				),
				'required'	=> $service->isRequiredTitle,
				'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_TITLE',
			);
		}
		
		// organization
		$result[] = array(
			'id'		=> $type . '_org_name',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,64}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 64))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_org_name']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_org_name'] :
				(isset($attributes['BillingOrgName']) ? $attributes['BillingOrgName'] : '')
			),
			'required'	=> self::CONTACT_ORGANIZATION == $type,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ORGANIZATION',
		);
		
		// address 1
		$result[] = array(
			'id'		=> $type . '_address1',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,100}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 100))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address1']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_address1'] :
				(isset($attributes['BillingAddress1']) ? $attributes['BillingAddress1'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADDRESS1',
		);
		
		// address 2
		$result[] = array(
			'id'		=> $type . '_address2',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,100}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 100))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address2']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_address2'] :
				(isset($attributes['BillingAddress2']) ? $attributes['BillingAddress2'] : '')
			),
			'required'	=> false,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADDRESS2',
		);
		
		// address 3
		$result[] = array(
			'id'		=> $type . '_address3',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,100}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 100))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_address3']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_address3'] :
				''
			),
			'required'	=> false,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_ADDRESS3',
		);
		
		// city
		$result[] = array(
			'id'		=> $type . '_city',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,64}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 64))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_city']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_city'] :
				(isset($attributes['BillingCity']) ? $attributes['BillingCity'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_CITY',
		);
		
		// state
		$result[] = array(
			'id'		=> $type . '_state',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,32}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 32))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_state']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_state'] :
				(isset($attributes['BillingState']) ? $attributes['BillingState'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_STATE',
		);
		
		// postal code
		$result[] = array(
			'id'		=> $type . '_postal_code',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,32}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 32))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_postal_code']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_postal_code'] :
				(isset($attributes['BillingPostalCode']) ? $attributes['BillingPostalCode'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_POSTAL_CODE',
		);
		
		// country
		$countries = array();
		foreach ($this->getCountries() as $code => $name) {
			$countries[] = array($code, $name);
		}
		$result[] = array(
			'id'		=> $type . '_country',
			'class'		=> '',
			'type'		=> SSLModule::CIT_SELECT,
			'items'		=> $countries,
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_country']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_country'] :
				(isset($attributes['BillingCountry']) ? $attributes['BillingCountry'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_COUNTRY',
		);
		
		// phone
		$result[] = array(
			'id'		=> $type . '_phone',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^\+\d{1,3}\.\d{1,10}(x\d{1,4})?$/', 'message' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_PHONE'),
			'desc'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_PHONE_DESCRIPTION',
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_phone']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_phone'] :
				(isset($attributes['BillingPhone']) ? $attributes['BillingPhone'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_PHONE',
		);
		
		// fax
		$result[] = array(
			'id'		=> $type . '_fax',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.{0,20}$/', 'message' => array('TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_MAX_LENGTH', array('LENGTH' => 20))),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_fax']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_fax'] :
				(isset($attributes['BillingFax']) ? $attributes['BillingFax'] : '')
			),
			'required'	=> false,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_FAX',
		);
		
		// email
		$result[] = array(
			'id'		=> $type . '_email',
			'type'		=> SSLModule::CIT_TEXT,
			'checker'	=> array('pattern' => '/^.+@.+\..+$/', 'message' => 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_INVALID_EMAIL'),
			'default'	=> (
				isset($attributes[self::PREFIX_ATTRIBUTES . $type . '_email']) ?
				$attributes[self::PREFIX_ATTRIBUTES . $type . '_email'] :
				(isset($attributes['BillingEmailAddress']) ? $attributes['BillingEmailAddress'] : '')
			),
			'required'	=> true,
			'title'		=> 'TRANS_SSL_MODULE_INTERNAL_OPENSRS_DATA_CONTACT_EMAIL',
		);
		
		return $result;
	}
}