<?php
class Admin_SecurityController extends Zend_Controller_Action 
{
	
	public function init()
	{
	    $this->view->addHelperPath('library/Atmail/View/Helper/', 'Atmail_View_Helper');
	    $this->_helper->pluginCall('initAdminController', $this);
		//TODO: extend authentication to support multiple user levels/roles/groups
		
		$this->request = $this->getRequest();
		$this->requestParams = $this->request->getParams();
		 
		$this->view->baseUrl = $this->_request->getBaseUrl();
		$this->view->appBaseUrl = $this->_request->getBaseUrl() . (strpos($this->_request->getBaseUrl(),'index.php')?'':DIRECTORY_SEPARATOR . 'index.php');
		$this->view->siteBaseUrl = Zend_Registry::get('siteBaseUrl');
		$this->view->moduleBaseUrl = $this->view->appBaseUrl . ($this->_request->module == 'default'?'':'/' . $this->_request->module);
		$this->view->global = Zend_Registry::get('config')->global;
		
		require_once 'application/models/admin.php';
		
		$this->admin = new admin();
		
		// check is an XML request or not only allow index to be rendered normally (i.e. full page load)
		if ($this->request->action == 'index' )
		{
			return;
			
		}
			
		if( !isset($this->view->errors) )
		{
			    
			$this->view->errors = array();
			
		}
		if( !isset($this->view->notices) )    
		{
			
			$this->view->notices = array();
			
		}
	 	if( !isset($this->view->jsonIdsToRender) )    
		{
			
			$this->view->jsonIdsToRender = array();
			
		}
		require_once 'library/jQuery/jQuery.php';
		
	}
	
	public function preDispatch() 
	{
		
		// Check the session is active, otherwise redirect to the login page
		$this->view->userData = $this->admin->getCurrentAdminData();
		
		if( empty($this->view->userData) ) 
		{

			$this->_forward( 'timeout', 'index', 'default' );
			return;			

		}
		
		Atmail_Locale::setupLocaleAndTranslation( $this->view->userData['Language'] );
		
	}
	
	public function indexAction() 
	{
		
		$this->view->licenseType = strtoupper(chr(Zend_Registry::get('w4m70Yt0hYrduM2r2lUrIuY0zgKG4A3vvftl4NbbCWfW')));
		
	}

	public function subadminaddAction() 
	{
		
		$this->view->domains = $this->admin->domainList();
		$configExim = Zend_Registry::get('config')->exim;
		if( 
			isset($configExim['smtp_archivevault_enable']) && 
			$configExim['smtp_archivevault_enable'] == '1'
		)
		{
			
			$this->view->archiveVaultAPIEnabled = true;
			
		}                                              
		else
		{
			
			$this->view->archiveVaultAPIEnabled = false;
			
		}
		
		
	}
	
	public function subadmincreateAction() 
	{
		
		if( $this->view->global['demo'] == 1 )
		{
			throw new Exception('Disabled in online demo');
		}
		
		if( $this->view->userData['UMasterAdmin'] != '1')
		{
			throw new Exception('MasterAdmin rights required.');
		}
		
		if( !array_key_exists('save', $this->requestParams) || $this->requestParams['save'] != 1 )
		{
			throw new Exception('Invalid call to Subadmin Create');
		}
			
		$errorYet = false;
		//first try add ArchiveVault user
		//Prep and call the request to ArchiveVault API if enabled in main config and subadmin
		$configArchiveVault = Zend_Registry::get('config')->archiveVault;
		$configExim = Zend_Registry::get('config')->exim;
		
		if( 
			isset($configExim['smtp_archivevault_enable']) && 
			$configExim['smtp_archivevault_enable'] == '1' && 
			isset($this->requestParams['UArchiveVault']) && 
			$this->requestParams['UArchiveVault'] == '1' 
		)
		{
		
			$args = archiveVaultAPIClient::splitUrl( $configArchiveVault['archiveVaultURL'] );
		
			$args['apiKey'] = $configArchiveVault['archiveVaultAPIKey'];
			$archiveVaultAPIClient = new archiveVaultAPIClient( $args );
			$result = $archiveVaultAPIClient->validateSettings();
			
			if( $result['status'] == 'failed' )
			{
				
				jQuery::addError('Failed adding new Subadmin user to ArchiveVault: ' . $result['response']['message']); 
				$errorYet = true;
				
			}
			else
			{   
				
				$newArchiveVaultRecord = array();
				$newArchiveVaultRecord['username'] = $this->requestParams['Username'];
				$newArchiveVaultRecord['password'] = $this->requestParams['Password'];
				$newArchiveVaultRecord['restriction'] = $this->requestParams['Domains'];
				$result = $archiveVaultAPIClient->usercreate( $newArchiveVaultRecord );
				if( $result['status'] == 'failed' )
				{

					jQuery::addError('Failed adding new Subadmin user to ArchiveVault: ' . $result['response']['message'] ); 
					$errorYet = true;

				}
				
			}
			
		
		}
		
		if( $errorYet )
		{
			
			$this->render('global/jsonresponse', null, true);
			return;
			
		}
		
		//clean up supplied data.
		//strip the --none-- from Domains
		if( $this->requestParams['Domains'][0] == '' )
			unset($this->requestParams['Domains'][0]);
		
		// Num User quota
		if( $this->requestParams['NumUsersA'] > 0 )
			$this->requestParams['NumUsers'] = $this->requestParams['NumUsersA'];
		elseif($this->requestParams['NumUsersB'] > 0)
			$this->requestParams['NumUsers'] = $this->requestParams['NumUsersB'];
		else
			$this->requestParams['NumUsers'] = 0;

		// NumQuota for storage
		if( $this->requestParams['NumQuotaA'] > 0 )
			$this->requestParams['NumQuota'] = $this->requestParams['NumQuotaA'];
		elseif( $this->requestParams['NumQuotaB'] > 0)
			$this->requestParams['NumQuota'] = $this->requestParams['NumQuotaB'];
		else
			$this->requestParams['NumQuota'] = 0;

		$result = $this->admin->subadminCreate( $this->requestParams );
		
		if( $result['status'] != 'failed' )
		{
			jQuery::addMessage('Successfully added new Subadmin');
		}
		else
		{				
			jQuery::addError('Failed adding new Subadmin: ' . $result['response']);
		}
		
		
		jQuery('#back_button_add_alias')->removeClass('disabled');
		$this->render('global/jsonresponse', null, true);
		
	}

	public function subadminlistAction() 
	{
		
		if( $this->view->userData['UMasterAdmin'] != '1')
		{
			throw new Exception('MasterAdmin rights required.');
		}

	}
	
	public function subadminlistmatchesAction() 
	{
		
		if( $this->view->userData['UMasterAdmin'] != '1')
		{
			throw new Exception('MasterAdmin rights required.');
		}
		
		$configArchiveVault = Zend_Registry::get('config')->archiveVault;
		$configExim = Zend_Registry::get('config')->exim;
		
		if( 
			isset($configExim['smtp_archivevault_enable']) && 
			$configExim['smtp_archivevault_enable'] == '1'
		)
		{
			
			$this->view->archiveVaultAPIEnabled = true;
			$this->view->ArchiveVaultURL = $configArchiveVault['archiveVaultURL'];
			
		}                                              
		else
		{
			
			$this->view->archiveVaultAPIEnabled = false;
		}
		
		$this->view->filter = $this->requestParams['filter'];
		
		$this->view->subadmins = $this->admin->subadminList(array('filter' => $this->requestParams['filter'])); 	
		
	}
	
	public function subadmineditAction() 
	{

		if( $this->view->userData['UMasterAdmin'] != '1')
		{
			throw new Exception('MasterAdmin rights required.');
		}
		
		if( !array_key_exists('subadminid', $this->requestParams) )
		{
			throw new Exception('required argument missing: subadminid');
		}
		$configExim = Zend_Registry::get('config')->exim;
		
		if( 
			isset($configExim['smtp_archivevault_enable']) && 
			$configExim['smtp_archivevault_enable'] == '1'
		)
		{
			$this->view->archiveVaultAPIEnabled = true;
		}                                              
		else
		{
			$this->view->archiveVaultAPIEnabled = false;
		}
		
		//prep params for call                                
		$args = array('id' => $this->requestParams['subadminid']);
		$this->view->subadmin = $this->admin->subadminView( $args );
		$this->view->domains = $this->admin->domainList();
        jQuery::evalScript('$(".mail_row_paginator_aliases", "#List_Subadmins").remove()');
		$this->view->jsonIdsToRender['subadminListMatches'] = 'security/subadminedit.phtml';
		$this->render('global/jsonresponse', null, true);
		
	}

    public function passwordAction()
    {
        $this->view->password = Zend_Registry::get('config')->password;
    }

    public function passwordsaveAction()
    {
        $passwordConfig = Zend_Registry::get('config')->password;
        $invalidParam = "";
        //Check that values are numerical and sane
        if ($this->request->fields['min_length'] > 63 || $this->request->fields['min_length'] < 0 || !is_numeric($this->request->fields['min_length']))
        {
            $invalidParam = "Minimum Characters";
        }
        else if ($this->request->fields['min_lowercase_chars'] > 60 || $this->request->fields['min_lowercase_chars'] < 0 || !is_numeric($this->request->fields['min_lowercase_chars']))
        {
            $invalidParam = "Minimum Lowercase Characters";
        }
        else if ($this->request->fields['min_uppercase_chars'] > 60 || $this->request->fields['min_uppercase_chars'] < 0 || !is_numeric($this->request->fields['min_uppercase_chars']))
        {
            $invalidParam = "Minimum Uppercase Characters";
        }
        else if ($this->request->fields['min_numeric_chars'] > 60 || $this->request->fields['min_numeric_chars'] < 0 || !is_numeric($this->request->fields['min_numeric_chars']))
        {
            $invalidParam = "Minimum Numeric Characters";
        }
        else if ($this->request->fields['min_nonalphanumeric_chars'] > 60 || $this->request->fields['min_nonalphanumeric_chars'] < 0 || !is_numeric($this->request->fields['min_nonalphanumeric_chars']))
        {
            $invalidParam = "Minimum Non-Alphanumeric Characters";
        }

        if(strlen($invalidParam) == 0)
        {
            //If values are numerical and sane
            try
            {
                $passwordConfig = array_merge($this->request->fields, $passwordConfig);
                config::save('password', $this->request->fields);
            }
            catch (Zend_Exception $error)
            {
                jQuery::addError('Failed saving config: ' . $error);
            }

            // if(ok)
            jQuery::addMessage("Password policy updated");
        }
        else
        {
            //If bad parameter
            jQuery::addError('Invalid parameter: ' . $invalidParam);
            $invalidParam = "";
        }
        $this->_helper->viewRenderer->setNoRender();
        $this->render('global/jsonresponse', null, true);
    }
	
	public function subadminupdateAction() 
	{
	
		if( $this->view->global['demo'] == 1 )
		{
			throw new Exception('Disabled in online demo');
		}
		
		if( $this->view->userData['UMasterAdmin'] != '1' )
		{	
			throw new Exception('MasterAdmin rights required.');		
		}
		
		if( $this->requestParams['Password'] == 'unchanged' && $this->requestParams['PasswordVerify'] == 'unchanged') 
		{
			unset( $this->requestParams['Password'] );                                                             
			unset( $this->requestParams['PasswordVerify'] );
		}                                             
		
		// Num User quota
		if( $this->requestParams['NumUsersA'] > 0 )
			$this->requestParams['NumUsers'] = $this->requestParams['NumUsersA'];
		elseif($this->requestParams['NumUsersB'] > 0)
			$this->requestParams['NumUsers'] = $this->requestParams['NumUsersB'];
		else
			$this->requestParams['NumUsers'] = 0;

		// NumQuota for storage
		if( $this->requestParams['NumQuotaA'] > 0 )
			$this->requestParams['NumQuota'] = $this->requestParams['NumQuotaA'];
		elseif($this->requestParams['NumQuotaB'] > 0 && $this->requestParams['NumQuotaA'] != '0')
			$this->requestParams['NumQuota'] = $this->requestParams['NumQuotaB'];
		else
			$this->requestParams['NumQuota'] = 0;

	   	//if checkboxes !isset (not checked) then force to 0
		if( !array_key_exists('UAdd', $this->requestParams) )
		{

			$this->requestParams['UAdd'] = 0;	
		}
		
		if( !array_key_exists('UDelete', $this->requestParams) )
		{
			$this->requestParams['UDelete'] = 0;
		}
		
		if( !array_key_exists('UModify', $this->requestParams) )
		{	
			$this->requestParams['UModify'] = 0;	
		}
		
		if( !array_key_exists('USearch', $this->requestParams) )
		{	
			$this->requestParams['USearch'] = 0;
		}
		
		if( !array_key_exists('UAlias', $this->requestParams) )
		{
			$this->requestParams['UAlias'] = 0;	
		}
		
		if( !array_key_exists('ULogs', $this->requestParams) )
		{
			$this->requestParams['ULogs'] = 0;	
		}
		
		$this->requestParams['id'] = $this->requestParams['subadminid'];
		
		//First try update ArchiveVault
		$errorYet = false;
		
		//Prep and call the request to ArchiveVault API if enabled in main config and subadmin
		$configArchiveVault = Zend_Registry::get('config')->archiveVault;
		$configExim = Zend_Registry::get('config')->exim;
		
		if( 
			isset($configExim['smtp_archivevault_enable']) && 
			$configExim['smtp_archivevault_enable'] == '1'
		)
		{
		
			if( !array_key_exists('UArchiveVault', $this->requestParams) )
			{
				$this->requestParams['UArchiveVault'] = 0;
			}
			
			$args = archiveVaultAPIClient::splitUrl( $configArchiveVault['archiveVaultURL'] );
		
			$args['apiKey'] = $configArchiveVault['archiveVaultAPIKey'];
			$archiveVaultAPIClient = new archiveVaultAPIClient( $args );
			$result = $archiveVaultAPIClient->validateSettings();
			
			if( $result['status'] == 'failed' )
			{
				
				jQuery::addError('Failed updating new Subadmin user to ArchiveVault: ' . $result['response']['message']); 
				$errorYet = true;
				
			}
			else
			{
				
					// Delete old record (possibly none already existing) then create if enabled
					$result = $archiveVaultAPIClient->userdelete( $this->requestParams['Username'] );
					if( $result['status'] == 'failed' && $result['response']['message'] != 'Unable to find existing user.' )
					{
				
                     	jQuery::addError('Failed updating new Subadmin user to ArchiveVault: ' . $result['response']['message']); 
						$errorYet = true;
						
					}

				if( !$errorYet && isset($this->requestParams['UArchiveVault']) && $this->requestParams['UArchiveVault'] == '1' )
				{
					
					$newArchiveVaultRecord = array();
					$newArchiveVaultRecord['username'] = $this->requestParams['Username'];
					//user may not have entered a new password, then fetch old one
					if( !isset( $this->requestParams['Password']) ) 
					{
						
						$subadminRecordOld = $this->admin->subadminView( array('id' => $this->requestParams['subadminid']) );
						$newArchiveVaultRecord['password'] = $subadminRecordOld['Password'];
					}   
					else
					{
						$newArchiveVaultRecord['password'] = $this->requestParams['Password'];				    
					}
					$newArchiveVaultRecord['restriction'] = $this->requestParams['Domains'];
					$result = $archiveVaultAPIClient->usercreate( $newArchiveVaultRecord );
					if( $result['status'] == 'failed' )
					{

						jQuery::addError('Failed adding new Subadmin user to ArchiveVault: ' . $result['response']['message'] ); 
						$errorYet = true;

					}
					
				} 
				
			}
			
		}
		
		if( $errorYet )
		{
			
			$this->render('global/jsonresponse', null, true);
			return;
			
		}
		
		unset($this->requestParams['Username']);
		
		$result = $this->admin->subadminUpdate( $this->requestParams );
		if( $result['status'] == 'failed' )
		{
			jQuery::addError( $result['response'] ); 
		}
		else 
		{
			jQuery::evalScript(" setTimeout( function()	{ $('#secondary', '#Security').tabs('load',0) }, 1000) ");
			jQuery::addMessage('Changes saved.');
		}
		
		jQuery('#back_button_add_alias')->removeClass('disabled');
			
		//Prep and update ArchiveVault User delete and re-add
		$this->render('global/jsonresponse', null, true);
		
	}
	
	public function subadmindeleteAction() 
	{
	
		if( $this->view->global['demo'] == 1 )
			throw new Exception('Disabled in online demo');
		
		if( $this->view->userData['UMasterAdmin'] != '1' )
			throw new Exception('MasterAdmin rights required.');
		
		//check for required args
		if( !array_key_exists('subadminid', $this->requestParams) && !(array_key_exists('subadminids', $this->requestParams) && count($this->requestParams['subadminids']) > 0) )
			throw new Exception('No subadmins selected to delete.');
		
		// prepare args                                      
		if( array_key_exists('subadminid', $this->requestParams) )
			$args = array('ids' => array($this->requestParams['subadminid']) );
		else
			$args = array('ids' => $this->requestParams['subadminids']);
		
		
		//First try delete from ArchiveVault
		$errorYet = false;
		//Prep and call the request to ArchiveVault API if enabled in main config and subadmin
		$configArchiveVault = Zend_Registry::get('config')->archiveVault;
		$configExim = Zend_Registry::get('config')->exim;
		
		if( isset($configExim['smtp_archivevault_enable']) && $configExim['smtp_archivevault_enable'] == '1' )
		{
		
			$archiveVaultURLArgs = archiveVaultAPIClient::splitUrl( $configArchiveVault['archiveVaultURL'] );
		
			$archiveVaultURLArgs['apiKey'] = $configArchiveVault['archiveVaultAPIKey'];
			$archiveVaultAPIClient = new archiveVaultAPIClient( $archiveVaultURLArgs );
			$result = $archiveVaultAPIClient->validateSettings();
			
			if( $result['status'] == 'failed' )
			{
				
				jQuery::addError('Failed deleting Subadmin user from ArchiveVault: ' . $result['response']['message']); 
				$errorYet = true;
				
			}
			else
			{
				
   				foreach( $args['ids'] as $id ) 
				{

					$subadminRecord = $this->admin->subadminView( array('id' => $id) );
					$result = $archiveVaultAPIClient->userdelete( $subadminRecord['Username'] );

				}
                
				//suppress errors for now as would prevent deleting subadmin users in the event of ArchiveVault fail
				if( $result['status'] == 'failed' && $result['response']['message'] != 'Unable to find existing user.' )
				{
			
                    //jQuery::addError('Failed deleting Subadmin user from ArchiveVault: ' . $result['response']['message']); 
					//$errorYet = true;
					
				}   
				
			}
			
		}
		
		if( $errorYet )
		{
			
			$this->render('global/jsonresponse', null, true);
			return;
			
		}
		
		$success = $this->admin->subadminDelete( $args );
		if( $success['status'] == 'failed' )
			throw new Exception('Failed deleting Subadmin');

		foreach( $args['ids'] as $id ) 
		{
			
			jQuery::evalScript("$('.subadminRow[subadminid=" . $id . "]').fadeOut( 300, function(){ $(this).remove(); });");
				
		}                             
		
		$this->render('global/jsonresponse', null, true);
		
	}

	public function adminpasswordAction() 
	{
		
		//if save isset then process form else show form
		if( array_key_exists('save', $this->requestParams) ) 
		{
			
			if( $this->view->global['demo'] == 1 )
			{
				
				throw new Exception('Disabled in online demo');
				
			}
			
			if( strlen($this->requestParams['Password']) == 0 )
			{
				
				throw new Exception('Password can not be zero length. Password not changed.');
				
			}
		    
			$args['id'] = $this->view->userData['id'];
			$args['Username'] = $this->view->userData['Username'];
			$args['PasswordOld'] = $this->requestParams['PasswordOld'];
			$args['PasswordNew'] = $this->requestParams['Password'];
			
			$result = $this->admin->adminSetPassword( $args );
			
			if( $result['status'] == 'failed') 
			{
				
					jQuery::evalScript("$('#back_button_add_alias', '#password').removeClass('disabled');");
					jQuery::evalScript("$('#back_button_add_alias', '#password').fadeTo('fast', 1);");

				if($result['response'] == 'No match found.')
					jQuery::addError( 'Existing password does not match - Please try again' );
				else
					jQuery::addError( 'Failed: ' . $result['response'] );
				
			}
			else
			{                                                                              
				
				jQuery::addMessage('Password changed. You will need to login with the new password. Forwarding back to login.');
				jQuery::evalScript(" setTimeout( function() { location.href = $('#sign_out a').attr('href'); }, 4000); ");
				
			}
			header('Content-Type: application/json');
			$this->render('global/jsonresponse', null, true);   
        
		}

	}
	
}
