<?php
class Admin_IndexController extends Zend_Controller_Action 
{
	
	public function init()
	{
	    $this->view->addHelperPath('library/Atmail/View/Helper/', 'Atmail_View_Helper');
		$this->_helper->pluginCall('initAdminController', $this);
		
		$this->request = $this->getRequest();
		 
		$this->view->baseUrl = $this->request->getBaseUrl();
		$this->view->appBaseUrl = $this->request->getBaseUrl() . (strpos($this->request->getBaseUrl(),'index.php')?'':'/' . 'index.php');
		$this->view->siteBaseUrl = Zend_Registry::get('siteBaseUrl');
        $this->view->moduleBaseUrl = $this->view->appBaseUrl . ($this->request->module == 'default' ? '/' : '/' . $this->request->module);
//        $this->view->moduleBaseUrl = $this->view->appBaseUrl . ($this->request->module == 'default'?'':'/' . $this->request->module);
		$this->view->global = Zend_Registry::get('config')->global;
		$this->view->reg = Zend_Registry::get('config')->reg;
		$this->view->company_url = $this->view->global['company_url'];           
		if($this->view->company_url == NULL || empty($this->view->company_url))
        {
        	$this->view->company_url = $this->siteBaseUrl;
        }

		$this->view->version = generateVersionString(getVersionCurrentLocalCodebase());
		
		if( empty($this->view->reg['downloadId']) || empty($this->view->reg['serialKey']) )
			$this->view->notRegistered = 1;
		
		require_once 'application/models/admin.php';
		
		$this->admin = new admin();
		$this->dbAdapter = Zend_Registry::get('dbAdapter');
		
		$this->view->localeString = Atmail_Locale::getLocaleString();
		$this->view->availableLocales = Atmail_Locale::getAvailableLocales();
		
		Atmail_Locale::setupLocaleAndTranslation();
	}
	
	public function indexAction() 
	{

        // check tmp
        if(!is_writable('/tmp'))
        {
            throw new Exception ("Atmail requires your /tmp directory to be writable for the http user. Please ensure /tmp has correct permissions and sticky bit applied.");
        }
		
		if( isset($this->request->error) ) //pretranslated error message sent from elsewhere
		{
			
			$this->view->error = $this->request->error;
			
		}
		
		if( isset($this->request->err) ) //error code with locally related translations in the phtml file
		{
			
			$this->view->err = $this->request->err;
			
		}
		else
		{
			
			//5 = all licenses have expired
			//4 = trial expired (only 1 lic of type trial) if all licenses expired = 
			//2 = grand total teats used > grand total available seats
			
		}

		//sanity check for version updates up to date else send user to admin with warning to run updates
		$updater = new Atmail_Update( $this->dbAdapter );
		$this->view->update = $updater->updateAvailable;
		$this->view->cliUpdate = $updater->cliUpdateAvailable;
		$this->view->dbUpdate = $updater->dbUpdateAvailable;
		
		// If !authenticated, show the login page, otherwise the admin UI
		if( !Atmail_FormAuth::authenticated() )
		{
			if($this->view->dbUpdate)
			{
				$this->view->error = $this->view->translate('Updates have been downloaded but not applied to the database, please apply the updates.');
			}
			else if($this->view->cliUpdate)
			{
				$this->view->error = $this->view->translate('Updates have been applied to the database but the cli update tool has not been run, please apply the updates.');
			}
			$this->view->username = $this->request->username;
			$this->render('login');
		}
		else
		{
		    $global = Zend_Registry::get('config')->global;
            $this->_session = new Zend_Session_Namespace(ATMAIL_ADMIN_NAMESPACE);
            
			// render login page if admin account not in session
            if(		(!isset($global['demo']) || $global['demo'] != 1)
				&&	(!isset($this->_session->Username) || empty($this->_session->Username)) )
			{
    			$this->render('login');
                return;
			}

            $identity = Zend_Auth::getInstance()->getIdentity();
			if( $identity != $this->_session->Username)
			{
				Zend_Registry::get('error')->info('Authenticated User does not match session.');
				$this->render('login');
				return;
			}

			$this->_session->setExpirationSeconds( $global['session_timeout'] * 60 );
			$this->_session->timeout = time() + $global['session_timeout'] * 60;
		    $this->admin->Username = $this->_session->Username;
		    $this->admin->Password = $this->_session->Password;
			$this->view->adminUser = $this->admin->getCurrentAdminData();
			$this->view->Username = $this->admin->Username;
			
			$configArchiveVault = Zend_Registry::get('config')->archiveVault;
            $configExim = Zend_Registry::get('config')->exim;

			// Load our login language
			$this->view->userData = $this->admin->getCurrentAdminData();
			Atmail_Locale::setupLocaleAndTranslation( $this->view->userData['Language'] );
				
			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;
				
			}
			
			//get the selected language from getCurrentAdminData, if !null then switch locale to that locale instead.
			$this->admin = new admin();
			$this->userData = $this->admin->getCurrentAdminData();
			if( isset($this->userData['Language']) && $this->userData['Language'] != null )
			{
			
				Atmail_Locale::setupLocaleAndTranslation($this->userData['Language']);
				
			}
			
			$this->render('index');
		}
	}
	
	public function jstranslateAction()
	{
	
		$this->view->setEncoding('UTF-8');
		if(!Atmail_FormAuth::authenticated())
		{
			// we have most probably timed out, so lets kick them to the timeout bootstrap page
			// this will poison json responses, which will fire the php.error ( or ajax.error ) which can detect the special page
			$this->_forward('timeout', 'index', 'default');
			return;
		}
		//This renders a translated js array (cached by browser)
		$this->getResponse()->setHeader('Content-Type','text/javascript; charset=utf-8');
		
	}
	
	
	public function loginAction() 
	{

        // check tmp
        if(!is_writable('/tmp'))
        {
            throw new Exception ("Atmail requires your /tmp directory to be writable for the http user. Please ensure /tmp has correct permissions and sticky bit applied.");
        }
        
		// Get the username, password, and webadmin-server and try to authenticate
		$server = $this->request->server;
		
		$password_md5 = 0;
		$admin_config = Zend_Registry::get('config')->admin;
		if(isset($admin_config['password']) && $admin_config['password'] == 'md5')
		{
			$password_md5 = 1;	
		}
		//sanity check posted vars
		if( strlen( $this->request->Username ) < 1 || strlen( $this->request->Password ) < 1 )
		{
			
			$this->view->error = "Missing username or password.";
			$this->render('login');
			return;
			
		}
		//if server is set we dont auth locally, we auth against remote server and use remote servers auth response
		if( !empty($server) ) 
		{
			
			//TODO: this should really be moved to admin model
			try 
			{
			
				/**
				 * Connect to API server and retrieve a greeting
				 * keep in mind that Zend_Rest_Client is not state based( no session) so credentials must be sent with each request
				 * so in admin we do have session so we create session vars to store username and password and pass them with each command after login
				 * currently no authentication is done on the local server (simulating 3rd party client), but can be added (even to auth against the same local store)
				 */
		                //clean up server and extract uri and basePath                 
				//first add on protocol identifier if not present
				if( strpos(strtolower($server), 'http://') !== 0 )
					$server = 'http://' . $server;
                
				//next find first / and split as URI and basePath
				if( strpos($server, '/', 7) !== false )
					$strPos = strpos($server, '/', 7);
				else
					$strPos = strlen($server);
				$serverURI = substr( $server, 0, $strPos );
                
				//if we cant find index.php then add it because must be implicit
				if( strpos( $server, 'index.php' ) === false ) 
				{
				
					if( substr($server, -1) !== '/')
						$server .= '/';
					$server .= 'index.php';
				
				}
                
				$serverBasePath = substr($server, strlen($serverURI), strpos($server, 'index.php', 7)+strlen('index.php')-strlen($serverURI) ); //must be complete path up to index.php (install path could be custom)
                
				Zend_Rest_Client::getHttpClient()->setAuth($this->request->Username, $this->request->Password);
               	
				$client = new Zend_Rest_Client($serverURI);
				
				$result = $client->get($serverBasePath . "/api/login/authenticate");
				
				$status = $result->isSuccess();
				
			} 
			catch (Exception $e) 
			{

				$this->view->error = "Unable to connect to specified server";
				$this->render('login');

			}
			
		} 
		else 
		{
			$auth = Zend_Auth::getInstance();
               
			$dbTables = new dbTables();
			$adapter = new Zend_Auth_Adapter_DbTable($this->dbAdapter);
			$adapter->setTableName($dbTables->AdminUsers);
			$adapter->setIdentityColumn('Username');
			$adapter->setCredentialColumn('Password');
			$adapter->setIdentity($this->request->Username);
			$adapter->setCredential($this->request->Password);

			// first up try plain text password match
			if( $password_md5 == 0 )
			{
				$result = $auth->authenticate($adapter);
			}
			
			// if fails try MD5 password match
			if ( $password_md5 || !$result->isValid() ) 
			{
			
			    $adapter->setCredentialTreatment('MD5(?)');
			    $result = $auth->authenticate( $adapter );
			
			}
			
			if( $result->isValid() )
			{
			
				$global = Zend_Registry::get('config')->global;
				if( !isset( $global['session_timeout'] ) )
				{
				
					$global['session_timeout'] = 3600;	
				
				}
				
				//if current session id already in use then regenerate up to 3 times to get unique SID
				if( !Zend_Registry::get('ATMAIL_UNIT_TESTING') )
				{

					Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ':  About to call enforceUniqueSID with SID = ' . session_id() );
					$sessionSaveHandler = Zend_Session::getSaveHandler();
					$sessionSaveHandler->enforceUniqueSID($this->request->Username);
					Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ':  done calling enforceUniqueSID now has SID = ' . session_id() );
					
				}
				

				// TODO: DO NOT STORE DATA IN THE SESSION - USE THE DB
				$this->_session = new Zend_Session_Namespace(ATMAIL_ADMIN_NAMESPACE);
				$this->_session->setExpirationSeconds( $global['session_timeout'] * 60 );
				$this->_session->timeout = time() + $global['session_timeout'] * 60;
				$this->_session->Username = $this->request->Username;
				//consider only storing password in session for remote servers for added security
				$this->_session->Password = $this->request->Password;
				try 
				{
				
					$adminUser = (array)$adapter->getResultRowObject(null, array('sessionData', 'Password') );
					
					//update Admin user record with last login date and ip
					$result = $this->dbAdapter->update( $dbTables->AdminUsers, array( 'LastLogin' => time(), 'ipAddress' => $_SERVER['REMOTE_ADDR'] ), array('Username = ' . $this->dbAdapter->quote($auth->getIdentity())) ); 
				    
					//update language if not Default
					if( isset( $this->request->Language ) && $this->request->Language != '' )
					{
						
						$result = $this->dbAdapter->update( $dbTables->AdminUsers, array( 'Language' => $this->request->Language ), array('Username = ' . $this->dbAdapter->quote($auth->getIdentity())) ); 
						
						
					}
				
				}
				catch( Exception $e )
				{

					// A fail at this point indicates missing fields from recent schema update so gracefully fall back until update script has run.
					// This block can be cleaned up again after update script has run.
					$adminUser = (array)$adapter->getResultRowObject(null, array('Password') );
					$result = $this->dbAdapter->update( $dbTables->AdminUsers, array( 'LastLogin' => time() ), array('Username = ' . $this->dbAdapter->quote($auth->getIdentity())) );
					
				}
				$this->view->adminUser = $adminUser;
				$this->view->Username = $auth->getIdentity();

				// clear all webmail cookies (security)
				$global = Zend_Registry::get('config')->global;
				if(!array_key_exists('exclusive_sessions', $global) || (array_key_exists('exclusive_sessions', $global) && $global['exclusive_sessions']))
				{
					// unset cookies
					if (isset($_SERVER['HTTP_COOKIE'])) {
						$cookies = explode(';', $_SERVER['HTTP_COOKIE']);
						foreach($cookies as $cookie) {
							$parts = explode('=', $cookie);
							$name = trim($parts[0]);
							if($name != ATMAIL_ADMIN_NAMESPACE)
							{
								setcookie($name, '', 0);
								setcookie($name, '', 0, '/');
								setcookie($name, '', 0, '/' . trim($this->view->siteBaseUrl, '/'));
							}
						}
					}
				}
				$this->_forward('index');
		
			} 
			else
			{
		    
				$this->view->error = "Authentication failed, try again";
				$this->render('login');
		
			}
			
		} 
	}

	public function adminsettingssaveAction()
	{

		$this->_helper->viewRenderer->setNoRender();
		$this->view->userData = $this->admin->getCurrentAdminData();
		if( empty($this->view->userData) )
		{

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

		}

		$global = Zend_Registry::get('config')->global;
		$this->_session = new Zend_Session_Namespace(ATMAIL_ADMIN_NAMESPACE);

		// render login page if admin account not in session
		if(		(!isset($global['demo']) || $global['demo'] != 1)
			&&	(!isset($this->_session->Username) || empty($this->_session->Username)) )
		{
			$this->render('login');
			return;
		}

		$identity = Zend_Auth::getInstance()->getIdentity();
		if( $identity != $this->_session->Username)
		{
			Zend_Registry::get('error')->info('Authenticated User does not match session.');
			$this->render('login');
			return;
		}
		$this->request = $this->getRequest();
		$this->requestParams = $this->request->getParams();
		unset($this->requestParams['fields']['id']);
		$this->requestParams['fields']['Username'] = $identity;
		echo Zend_Json::encode( $this->admin->adminUpdateSettings($this->requestParams['fields']) );

	}
	
	public function logoutAction() 
	{
		$this->view->registered = true;
		$auth = Zend_Auth::getInstance();
		$auth->clearIdentity();
		$this->_session = new Zend_Session_Namespace(ATMAIL_ADMIN_NAMESPACE);
		$this->_session->Username = null;
		$this->_session->Password = null;
		$this->view->message = $this->view->translate('Logout successful.');
		Zend_Session::expireSessionCookie();
		session_destroy();	    
		$this->_forward('index', 'index');
	}
	
	public function helpAction()
	{
		$global = Zend_Registry::get('config')->global;
        $this->view->install_type = $global['install_type'];
        $this->view->brandname = $global['brandname'];
    	$this->view->helpFile = $this->request->helpFile;
        $this->render('help');

	}	

}
