<commit_before><?php 
/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2014 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     New BSD License
 */

class Admin_LoginController extends Pimcore_Controller_Action_Admin {

    public function init() {

        parent::init();
        $this->protect();

        // IE compatibility
        //$this->getResponse()->setHeader("X-UA-Compatible", "IE=8; IE=9", true);
    }


    public function lostpasswordAction() {


        $username = $this->getParam("username");
        if ($username) {
            $user = User::getByName($username);
            if (!$user instanceof User) {
                $this->view->error = "user unknown";
            } else {
                if ($user->isActive()) {
                    if ($user->getEmail()) {
                        $token = Pimcore_Tool_Authentication::generateToken($username, $user->getPassword());
                        $uri = $this->getRequest()->getScheme() . "://" . $this->getRequest()->getHttpHost() ;
                        $loginUrl = $uri . "/admin/login/login/?username=" . $username . "&token=" . $token . "&reset=true";
                        
                        try {
                            
                            $mail = Pimcore_Tool::getMail(array($user->getEmail()), "Pimcore lost password service");
                            $mail->setIgnoreDebugMode(true);
                            $mail->setBodyText("Login to pimcore and change your password using the following link. This temporary login link will expire in 30 minutes: \r\n\r\n" . $loginUrl);
                            $mail->send();
                            $this->view->success = true;
                        } catch (Exception $e) {
                            $this->view->error = "could not send email";
                        }

                    } else {
                        $this->view->error = "user has no email address";
                    }
                } else {
                    $this->view->error = "user inactive";
                }

            }
        }


    }


    public function indexAction() {

        if ($this->getUser() instanceof User) {
            $this->redirect("/admin/?_dc=" . time());
        }

        if ($this->getParam("auth_failed")) {
            $this->view->error = "error_auth_failed";
        }
        if ($this->getParam("session_expired")) {
            $this->view->error = "error_session_expired";
        }
    }

    public function deeplinkAction () {
        // check for deeplink
        $queryString = $_SERVER["QUERY_STRING"];
        if(preg_match("/(document|asset|object)_([0-9]+)_([a-z]+)/", $queryString, $deeplink)) {
            if(strpos($queryString, "token")) {
                $deeplink = $deeplink[0];
                $this->redirect("/admin/login/login?deeplink=" . $deeplink . "&" . $queryString);
            } else if($queryString) {
                $this->view->tab = $queryString;
            }
        }
    }

    public function loginAction() {

        $user = null;

        try {
            if ($this->getParam("password")) {
                $user = Pimcore_Tool_Authentication::authenticatePlaintext($this->getParam("username"), $this->getParam("password"));
                if(!$user) {
                    throw new \Exception("Invalid username or password");
                }
            } else if ($this->getParam("token")) {

                $user = Pimcore_Tool_Authentication::authenticateToken($this->getParam("username"), $this->getParam("token"));

                if(!$user) {
                    throw new \Exception("Invalid username or token");
                }

                // save the information to session when the user want's to reset the password
                // this is because otherwise the old password is required => see also PIMCORE-1468
                if($this->getParam("reset")) {
                    Pimcore_Tool_Session::useSession(function($adminSession) {
                        $adminSession->password_reset = true;
                    });
                }
            } else {
                throw new \Exception("Invalid authentication method, must be either password or token");
            }
        } catch (Exception $e) {

            //see if module or plugin authenticates user
            Pimcore::getEventManager()->trigger("admin.login.login.failed", $this, [
                "username" => $this->getParam("username"),
                "password" => $this->getParam("password")
            ]);

            $user = $this->getUser();

            if(!$user instanceof User) {
                $this->writeLogFile($this->getParam("username"), $e->getMessage());
                Logger::info("Login failed: " . $e);
            }
        }

        if ($user instanceof User && $user->getId() && $user->isActive() && $user->getPassword()) {
            Pimcore_Tool_Session::useSession(function($adminSession) use ($user) {
                $adminSession->user = $user;

                Pimcore_Tool_Session::regenerateId();
            });

            if($this->_getParam('deeplink')){
                $this->redirect('/admin/login/deeplink/?' . $this->_getParam('deeplink'));
            } else {
                $this->redirect("/admin/?_dc=" . time());
            }
        } else {
            $this->redirect("/admin/login/?auth_failed=true");
            exit;
        }
    }

    public function logoutAction() {

        $controller = $this;

        Pimcore_Tool_Session::useSession(function($adminSession) use ($controller) {
            if ($adminSession->user instanceof User) {
                Pimcore::getEventManager()->trigger("admin.login.logout", $controller, ["user" => $adminSession->user]);
                $adminSession->user = null;
            }

            Zend_Session::destroy();
       });

        // cleanup pimcore-cookies => 315554400 => strtotime('1980-01-01')
        setcookie("pimcore_opentabs", false, 315554400, "/");

        $this->redirect("/admin/login/");
    }


    /**
     * Protection against bruteforce
     */
    protected function getLogFile() {

        $logfile = PIMCORE_LOG_DIRECTORY . "/loginerror.log";

        if (!is_file($logfile)) {
            Pimcore_File::put($logfile, "");
        }
<commit_msg>add additional hooks for authentication<commit_after><?php
/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2014 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     New BSD License
 */

class Admin_LoginController extends Pimcore_Controller_Action_Admin {

    public function init() {

        parent::init();
        $this->protect();

        // IE compatibility
        //$this->getResponse()->setHeader("X-UA-Compatible", "IE=8; IE=9", true);
    }


    public function lostpasswordAction() {


        $username = $this->getParam("username");
        if ($username) {
            $user = User::getByName($username);
            if (!$user instanceof User) {
                $this->view->error = "user unknown";
            } else {
                if ($user->isActive()) {
                    if ($user->getEmail()) {
                        $token = Pimcore_Tool_Authentication::generateToken($username, $user->getPassword());
                        $uri = $this->getRequest()->getScheme() . "://" . $this->getRequest()->getHttpHost() ;
                        $loginUrl = $uri . "/admin/login/login/?username=" . $username . "&token=" . $token . "&reset=true";

                        try {

                            $mail = Pimcore_Tool::getMail(array($user->getEmail()), "Pimcore lost password service");
                            $mail->setIgnoreDebugMode(true);
                            $mail->setBodyText("Login to pimcore and change your password using the following link. This temporary login link will expire in 30 minutes: \r\n\r\n" . $loginUrl);
                            $mail->send();
                            $this->view->success = true;
                        } catch (Exception $e) {
                            $this->view->error = "could not send email";
                        }

                    } else {
                        $this->view->error = "user has no email address";
                    }
                } else {
                    $this->view->error = "user inactive";
                }

            }
        }


    }


    public function indexAction() {

        $user = $this->getUser();

        if (!$user) {
            Pimcore::getEventManager()->trigger("admin.login.index.authenticate", $this, [
                "username" => $this->getParam("username"),
                "password" => $this->getParam("password")
            ]);

            $user = $this->getUser();

            if ($user instanceof User && $user->getId() && $user->isActive() && $user->getPassword()) {
                Pimcore_Tool_Session::useSession(function($adminSession) use ($user) {
                    $adminSession->user = $user;
                });
            }
        }

        if ($this->getUser() instanceof User) {
            $this->redirect("/admin/?_dc=" . time());
        }

        if ($this->getParam("auth_failed")) {
            $this->view->error = "error_auth_failed";
        }
        if ($this->getParam("session_expired")) {
            $this->view->error = "error_session_expired";
        }
    }

    public function deeplinkAction () {
        // check for deeplink
        $queryString = $_SERVER["QUERY_STRING"];
        if(preg_match("/(document|asset|object)_([0-9]+)_([a-z]+)/", $queryString, $deeplink)) {
            if(strpos($queryString, "token")) {
                $deeplink = $deeplink[0];
                $this->redirect("/admin/login/login?deeplink=" . $deeplink . "&" . $queryString);
            } else if($queryString) {
                $this->view->tab = $queryString;
            }
        }
    }

    public function loginAction() {
        $user = null;

        try {
            Pimcore::getEventManager()->trigger("admin.login.login.authenticate", $this, [
                "username" => $this->getParam("username"),
                "password" => $this->getParam("password")
            ]);

            $user = $this->getUser();

            if (!$user instanceof User) {
                if ($this->getParam("password")) {
                    $user = Pimcore_Tool_Authentication::authenticatePlaintext($this->getParam("username"), $this->getParam("password"));
                    if(!$user) {
                        throw new \Exception("Invalid username or password");
                    }
                } else if ($this->getParam("token")) {

                    $user = Pimcore_Tool_Authentication::authenticateToken($this->getParam("username"), $this->getParam("token"));

                    if(!$user) {
                        throw new \Exception("Invalid username or token");
                    }

                    // save the information to session when the user want's to reset the password
                    // this is because otherwise the old password is required => see also PIMCORE-1468
                    if($this->getParam("reset")) {
                        Pimcore_Tool_Session::useSession(function($adminSession) {
                            $adminSession->password_reset = true;
                        });
                    }
                } else {
                    throw new \Exception("Invalid authentication method, must be either password or token");
                }
            }
        } catch (Exception $e) {

            //see if module or plugin authenticates user
            Pimcore::getEventManager()->trigger("admin.login.login.failed", $this, [
                "username" => $this->getParam("username"),
                "password" => $<PASSWORD>")
            ]);

            $user = $this->getUser();

            if(!$user instanceof User) {
                $this->writeLogFile($this->getParam("username"), $e->getMessage());
                Logger::info("Login failed: " . $e);
            }
        }

        if ($user instanceof User && $user->getId() && $user->isActive() && $user->getPassword()) {
            Pimcore_Tool_Session::useSession(function($adminSession) use ($user) {
                $adminSession->user = $user;

                Pimcore_Tool_Session::regenerateId();
            });

            if($this->_getParam('deeplink')){
                $this->redirect('/admin/login/deeplink/?' . $this->_getParam('deeplink'));
            } else {
                $this->redirect("/admin/?_dc=" . time());
            }
        } else {
            $this->redirect("/admin/login/?auth_failed=true");
            exit;
        }
    }

    public function logoutAction() {

        $controller = $this;

        Pimcore_Tool_Session::useSession(function($adminSession) use ($controller) {
            if ($adminSession->user instanceof User) {
                Pimcore::getEventManager()->trigger("admin.login.logout", $controller, ["user" => $adminSession->user]);
                $adminSession->user = null;
            }

            Zend_Session::destroy();
        });

        // cleanup pimcore-cookies => 315554400 => strtotime('1980-01-01')
        setcookie("pimcore_opentabs", false, 315554400, "/");

        $this->redirect("/admin/login/");
    }


    /**
     * Protection against bruteforce
     */
    protected function getLogFile() {

        $logfile = PIMCORE_LOG_DIRECTORY . "/loginerror.log";

        if (!is_file($logfile)) {
            Pimcore_File::put($logfile, "");
        }

{'fraction_non_alphanumeric': 0.14649141403434388, 'fraction_numerical': 0.006359974560101759, 'mean_word_length': 1.678780995646413, 'pattern_counts': {'":': 2, '<': 6, '<?xml version=': 0, '>': 162, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4436645', 'n_tokens_mistral': 3898, 'n_tokens_neox': 3630, 'n_words': 730}