<?php

namespace Sabre\DAV\Auth\Backend;

// NOTE:
// Change validateUserPass_multi (and possibly validateUserPass_direct) for non imap authentication

/**
 * This is an authentication backend that talks to netwin NWAuth.
 *
 * @package Surgemail SabreDav NWAuth Authentication
 * @subpackage DAV
 * @copyright Copyright (C) 2012 NetWin Ltd. All rights reserved.
 * @author Marijn Weehuizen (http://netwinsite.com/)
 */
class Nwauth extends AbstractBasic {

    protected $pdo;
    protected $realm;

    public function __construct(\PDO $pdo) {
		$this->pdo = $pdo;
		$this->realm = "SabreDAV";
    }


    public function validateUserPass($user, $password) {
		$username = $user;
		if (!preg_match('/@/', $username )) return false;
//			$username = $username.'@calsvr';

		$wanted_hash=md5($username . ':' . $this->realm . ':' . $password);
		dbg("NWAUTH user=$username pass={hidden} hash=$wanted_hash");

		if($this->cachedAuthent($username, $wanted_hash)){
			// cool just use the cached one :-)
			return true;
		}

		dbg("No cached login, trying IMAP");
		if(!$this->validateUserPass_multi($username, $password)){
			return false;
		}

		dbg("Authentication SUCCESS");
		$this->validatePrincipals($user);
		dbg("NWAUTH Principals Validated");
		$this->cachedAdd($username,$wanted_hash);
		dbg("NWAUTH Authentication cached Validated");
		return true;
    }

    public function validatePrincipals($username) {

		dbg('validating db entries :-)');
		try {

			// Now make sure this exists in our calendar database :-)
			$stmt = $this->pdo->prepare('SELECT uri, email FROM principals WHERE uri = ?');
			$stmt->execute(array("principals/".$username));
			$result = $stmt->fetchAll();

			if($result){
				dbg('principal already found');
				return;
			}

            $stmt = $this->pdo->prepare('INSERT INTO principals (uri, email, displayname) VALUES (?, ?, ?);');
            $stmt->execute(array('principals/'.$username, $username, $username));
            $stmt->execute(array('principals/'.$username.'/calendar-proxy-read', null, null));
            $stmt->execute(array('principals/'.$username.'/calendar-proxy-write', null, null));

			dbg('principal entries created for '.$username);

            //$stmt = $this->pdo->prepare('INSERT INTO calendars (uri, email, displayname) VALUES (?, ?, ?);');
            //$stmt->execute(array('principals/'.$username, $username, $username));

		} catch (Exception $e) {
			dbg("Exception caught ".$e);
		}
	}
    public function cachedAuthent($username, $wanted_hash){
        $stmt = $this->pdo->prepare('SELECT username, digesta1, created FROM `users` WHERE username = ?');
        $stmt->execute(array($username));
        $result = $stmt->fetchAll();

        if (count($result)==0){
        	return false;
        }

		if($result[0]['digesta1']!=$wanted_hash){
			dbg("NWAUTH Cached login password invalid ($username) ");
			return false;
		}

		$age = time() - $result[0]['created'];
		$maxage = 30*60; // Cache login credentials for 30 minutes
		if($age > 1 ){ // $maxage
			dbg("NWAUTH Cached login expired ($username) age=$age/$maxage");
			return false;
		}

		dbg("NWAUTH Cached login valid ($username) age=$age/$maxage");

		return true;
    }
    public function cachedAdd($username, $hash){
        $stmt = $this->pdo->prepare('DELETE FROM users WHERE username = ?');
        $stmt->execute(array($username));

        $stmt = $this->pdo->prepare('INSERT INTO users (username, digesta1, created) VALUES (?, ?, ?);');
        $stmt->execute(array($username, $hash, time()));
		dbg('login cache updated for '.$username);
    }
    public function validateUserPass_multi($username, $password) {
		// change $type to 2 for nwauth direct authentication!
        $type = 1;
		if($type==1){
			return $this->validateUserPass_imap($username,$password);
		}else{
			return $this->validateUserPass_direct($username,$password);
		}
		return false;
	}

    public function validateUserPass_direct($username, $password) {

        $auth_cmd = "sudo -u mail /usr/local/surgemail/nwauth -path /usr/local/surgemail -check ".$username." ".$password." 2>&1";
        dbg("NWAuth2 auth=".$auth_cmd);
		$auth_res = shell_exec($auth_cmd);
       	dbg("NWAuth2 RESULT=".$auth_res);

		if (!preg_match('/^\+OK/', $auth_res)){
	       	dbg("NWAuth2 login=FAILED (".$username .")");
			return false;
		}
       	dbg("NWAuth2 login=SUCCESS (".$username .")");

        return true;
    }

    public function validateUserPass_imap($username, $password) {
		$authorised = false;
		try {
            $imap = imap_open("{127.0.0.1:143/notls}INBOX", $username, $password, OP_HALFOPEN);
  			if($imap){
				dbg("NWAUTH imap login SUCCESS ($username)");
				$authorised = true;
			}else{
				dbg("NWAUTH imap login FAILED ($username)");
			}
			imap_close($imap);
	  	} catch (Exception $e) {
		 	dbg("Imap login exception ".$e->getMessage());
	  	}
		dbg("NWAUTH authorised=[".($authorised?'YES':'NO')."]");
        return $authorised;
    }

}
