<?php
/**
 * Copyright 2005-2017 de Solis Soluções Livres Ltda.
 *
 * Este arquivo é parte do programa Gnuteca.
 *
 * O Gnuteca é um software de propriedade da SOLIS, sendo desenvolvido
 * e mantido exclusivamente por esta empresa.
 *
 * A licença de uso está disponível mediante aquisição exclusiva junto à
 * SOLIS. A licença é concedida sem caráter de exclusividade ao licenciado.
 * Os direitos de uso são perpétuos.
 *
 * Embora os códigos fontes sejam fornecidos, o software é de propriedade
 * da SOLIS, não sendo permitido ao adquirente da licença a sua revenda,
 * empréstimo ou cessão (onerosa ou não) à terceiros. Também não é permitido,
 * a qualquer título e tempo, promover no software qualquer tipo de alienação,
 * reprodução, distribuição, divulgação, registro, licenciamento, transferência
 * ou qualquer outro ato que prejudique ou comprometa os direitos de propriedade
 * de software, o nome e a imagem da sua proprietária e do próprio software,
 * além de configurar concorrência à SOLIS.
 *
 * O licenciado, com o acesso ao código fonte do software, terá o direito de
 * promover mudanças no respectivo código. No entanto, nas situações em que ele
 * contar com o suporte oficial prestado pela SOLIS, não poderá promover mudanças
 * no código fonte, sob pena de perda do referido suporte.
 *
 * Para conhecer em detalhes o Termo de Licenciamento do Software Gnuteca
 * leia o arquivo “LICENCA.txt” disponível junto ao código deste software.
 *
 *
 *
 *
 *
 *
 *
 **/
class FrmLogin extends GForm
{
    public $auth;
    public $MIOLO;
    public $module;
    public $busLibraryUnit;
    public $busAuthenticate;
    public $busPerson;
    public $args;

    public function __construct($args)
    {
        $this->args     = $args;
        $this->MIOLO    = MIOLO::getInstance();
        $this->module   = 'gnuteca3';

        $this->busLibraryUnit   = $this->MIOLO->getBusiness($this->module, 'BusLibraryUnit');
        $this->busAuthenticate  = $this->MIOLO->getBusiness($this->module, 'BusAuthenticate');
        $this->busPerson        = $this->MIOLO->getBusiness($this->module, 'BusPerson');

        if ( $this->getLoginType() == LOGIN_TYPE_ADMIN )
        {
            $label = _M('Acesso administrativo', $this->module);
            
            // Limpa cookie de abas ativas.
            $this->MIOLO->page->onload('document.cookie = "abas_ativas=; expires=Thu, 01 Jan 1970 00:00:00 UTC;";');
        }
        else
        {
            $label = _M('Login Gnuteca (Usuário)', $this->module);
        }
            
        parent::__construct( $label );
        $this->setIcon(GUtil::getImageTheme('login-16x16.png'));
        $this->page->addScript('mascaraCPF.js', 'gnuteca3');

        if ($this->getLoginType() != LOGIN_TYPE_USER_AJAX)
        {
            if ($this->page->isPostBack())
            {
                
            }
        }

        $this->setClass("loginForm");
    }


    public function mainFields($return = false)
    {
        $ui = $this->MIOLO->getUI();
        $loginType = $this->getLoginType();

        if ( $loginType == LOGIN_TYPE_USER_AJAX && MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_AZURE )
        {
            $fields = array();
            $buttons = array();
            $buttons[] = '';
            $buttons[] = new MButton('autenticarAzure', _M('Entrar com <b>Microsoft Azure</b>'), ':autenticarAzure', GUtil::getImageTheme('microsoft-16x16.png'));
            $buttons[] = GForm::getCloseButton();
            
            $fields[] = new MDiv('hctButtons', $buttons);
            $div = new GContainer('divLogin', $fields);
            $div->setClass('divLogin');
        }
        else
        {
            //Sempre pedir o código do usuário na Circulação de material
            $isAuthenticated = $this->isMaterialMovement() ? false : $this->isAuthenticated();
            $return_to = $this->getFormValue('return_to', MIOLO::_Request('return_to'));

            $fields[] = MMessage::getMessageContainer();

            if ( ! MIOLO::_REQUEST('uid') )
            {
                $this->errors = null;
            }

            if(!$return_to)
            {
                $return_to = $this->MIOLO->history->top();
            }

            if ($loginType == LOGIN_TYPE_USER_AJAX && (SIMPLE_SEARCH_LOGIN_STRING != 'SIMPLE_SEARCH_LOGIN_STRING') && strlen(SIMPLE_SEARCH_LOGIN_STRING) > 0 )
            {
                $fields[] = new MDiv(null,SIMPLE_SEARCH_LOGIN_STRING);
            }

            //escolhe label de acordo com situação
            if ( $loginType == LOGIN_TYPE_ADMIN )
            {
                $userLabel = _M('Operador', $this->module);
            }
            else if ( ($loginType == LOGIN_TYPE_USER || $loginType == LOGIN_TYPE_USER_AJAX ) )
            {
                if ((MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN_BASE)
                    || (MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN)
                    || (MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_AZURE))
                {
                    $userLabel = _M('Usuário', $this->module);
                }
                else
                {
                    $userLabel = _M('Código', $this->module);
                }
            }
            
            $labelLogin = new MLabel( $userLabel );
            $labelLogin->setWidth(DEFAULT_LABEL_SIZE);
            $uid = new MTextField('uid', $this->MIOLO->auth->login->iduser, null, 20);
            
            if ( $loginType == LOGIN_TYPE_ADMIN )
            {
                $userLabel = _M('Operador', $this->module);
                
                // Se estiver configurado o uso de máscara de cpf para operador.
                if ( OPERATOR_LOGIN_CPF == DB_TRUE )
                {
                    $uid->setAttribute('onKeyPress', 'MascaraCPF(this, event);');
                }
            }
            else 
            {
                // Se estiver configurado o uso de máscara de cpf para usuário. 
                if (USER_LOGIN_CPF == DB_TRUE && ((MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN_BASE)
                    || (MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN)
                    || (MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_AZURE)))
                {
                    $uid->setAttribute('onKeyPress', 'MascaraCPF(this, event);');
                } 
            }
            
            $uid->setClass('mTextUserField');
            
            $uid->setReadOnly($isAuthenticated);
            $fields[] = new GContainer('hctLogin', array($labelLogin, $uid));

            if (!$this->isMaterialMovement())
            {
                $labelPasswd = new MLabel(_M('Senha', $this->module));
                $labelPasswd->setWidth(DEFAULT_LABEL_SIZE);
                $pwd = new MPasswordField('pwd', '', null, 20);
                $pwd->setClass('mTextPasswdField');
                $fields[] = new GContainer('hctPasswd', array($labelPasswd, $pwd));
                
                if ( ($loginType == LOGIN_TYPE_USER || $loginType == LOGIN_TYPE_USER_AJAX ) && (RECOVER_PASSWORD == DB_TRUE) )
                {
                    $urlRecoverPassword = $this->MIOLO->getActionURL( 'gnuteca3' , "main:search:simpleSearch&subForm=RecoverPassword");
                    $fields[] = new MDiv('', new MLink('esqueciMinhaSenha', _M('Esqueci minha senha'), $urlRecoverPassword));
                }
            }

            if ($loginType == LOGIN_TYPE_ADMIN)
            {
                $label = new MLabel( _M('Biblioteca', $this->module) );
                $libraryUnitId = new GSelection('libraryUnitId', $_COOKIE['libraryUnitId'], null, $this->busLibraryUnit->listLibraryUnit(false, false), null, null, null, true);
                //Altera tempo de expiraçao para 30 anos.
                $libraryUnitId->addAttribute('onchange', 'var expiration_date = new Date(); expiration_date.setFullYear(expiration_date.getFullYear() + 30); document.cookie = \'libraryUnitId=\'+this.value+\'; expires=\'+expiration_date.toGMTString()+\';\';');
                $libraryUnitId->setClass('mTextLibraryField');
                $fields[] = new GContainer('hctLibraryUnit', array($label, $libraryUnitId));
            }
            
            if ($loginType == LOGIN_TYPE_USER   )
            {
                $bases =  BusinessGnuteca3BusAuthenticate::listMultipleLdap();
                if ( (MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN_BASE) && (strlen(implode('', $bases)) > 0) )
                {
                    $fields[] = $baseF = new GSelection('baseLdap', '', _M('Base:', $this->module), $bases, false, '','', true);
                    $baseF->setClass('mTextLibraryField');
                }
            }
            elseif ($loginType == LOGIN_TYPE_USER_AJAX)
            {
                $bases =  BusinessGnuteca3BusAuthenticate::listMultipleLdap();
                if ( (MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN_BASE) && (strlen(implode('', $bases)) > 0) )
                {
                    $fields[] = $baseF = new GSelection('baseLdapAjax', '', _M('Base:', $this->module), $bases, false, '','', true);
                    $baseF->setClass('mTextLibraryField');
                }
            }
            
            $this->jsSetFocus('uid', false); //seta foco no campo código
            $fields[] = new MHiddenField('tries', '');
            $fields[] = new MHiddenField('return_to', $return_to);
            $fields[] = new MHiddenField('redirect_action', $this->getFormValue('redirect_action', MIOLO::_REQUEST('redirect_action')));
            $fields[] = new MHiddenField('loginType', $loginType);

            $param = GUtil::getAjaxEventArgs();
            $ajaxAction = '';

            if ($loginType == LOGIN_TYPE_USER_AJAX)
            {
                $ajaxAction = GUtil::getAjax($this->getEvent(), $param);
            }
            else
            {
                $ajaxAction = 'javascript:'.GUtil::getAjax('btnLogin_click', $param).';';
            }

            $btnLogin = new MButton('btnLogin', _M('Autenticar', $this->module) , $ajaxAction, GUtil::getImageTheme('accept-16x16.png') );

            if (!$isAuthenticated)
            {
                $buttons[] = $btnLogin;
            }

            $btnLogout = new MButton('btnLogout', _M('Sair', $this->module) ,null, GUtil::getImageTheme('logout-16x16.png') );

            if ($isAuthenticated)
            {
                $buttons[] = $btnLogout;
            }

            if ($loginType == LOGIN_TYPE_USER_AJAX)
            {
                $buttons[] = GForm::getCloseButton();
            }
            
            $fields[] = $hctButtons = new MDiv('hctButtons', $buttons);
            $div = new GContainer('divLogin', $fields);
            $div->setClass('divLogin');
        }
        
        if ($return)
        {
            return array($div);
        }
        else
        {
            $this->setFields($div);
        }
    }

    /**
     * Essa função foi criada pois gerava problemas na pesquisa simples com subform.
     * Dessa forma não chamada função de busca.
     */
    public function searchFunction()
    {
        //não faz nada
    }

    public function getLoginFields()
    {
        $this->errors = null;
        $fields = $this->mainFields(true);

        if ( $this->errors )
        {
            //define o foco na mensagem para leitura de accessibilidade
            GForm::jsSetFocus( MMessage::MSG_DIV_ID ,false);
            $msg = implode('<br>', $this->errors );
            $message= MMessage::getStaticMessage( MMessage::MSG_DIV_ID, $msg , MMessage::TYPE_WARNING );
            $message->addAttribute('alt',strip_tags($msg));
            $message->addAttribute('title',strip_tags($msg));
            $fields = array_merge( array( $message ), $fields);
        }
        
        return $fields;
    }


    public function btnLogin_click()
    {
        $data = $this->getData();
        $max_tries = 3; // Max login tryes

        // autenticar usuario e obter dados do login
        $uid = $this->getFormValue('uid', MIOLO::_REQUEST('uid'));
        $pwd = $this->getFormValue('pwd', MIOLO::_REQUEST('pwd'));
        $loginType = $this->getLoginType();

        $this->MIOLO->logMessage('[LOGIN] Validating login information: ' . $uid);
        
        if ( $loginType == LOGIN_TYPE_USER)
        {        
            $base = $this->getFormValue('baseLdap', MIOLO::_REQUEST('baseLdap')); //obtém a base pelo user
        }
        elseif ($loginType == LOGIN_TYPE_USER_AJAX)
        {
            $base = $this->getFormValue('baseLdapAjax', MIOLO::_REQUEST('baseLdap')); //obtém a base pelo userAjax
        }

        $msg = 'Erro na identificação do usuário!';

        $MIOLO = MIOLO::getInstance();
        $MIOLO->getClass('gnuteca3', 'GDependencyCheck');

        if ($loginType == LOGIN_TYPE_ADMIN)
        {
            $busAttempt = $MIOLO->getBusiness('gnuteca3', 'BusMioloLoginAttempt');
            $attempt = $busAttempt->getAttempt($uid);
            $maximoDeTentativas = $MIOLO->getConf('login.tentativas');
            $tempoDeBloqueio = $MIOLO->getConf('login.tempodebloqueio');

            $tentativasRestantes = 0;
            if( !is_numeric($tempoDeBloqueio) )
            {
                $tempoDeBloqueio = 0;
            }
            if( !is_numeric($maximoDeTentativas) )
            {
                $maximoDeTentativas = 0;
            }

            //Verifica tentativas de login
            if( $maximoDeTentativas > 0 )
            {
                $tentativasRestantes = $maximoDeTentativas-MUtil::NVL($attempt->attempt,0);

                //Se alcançou o limite de tentativas, bloqueia o acesso pelo tempo configurado
                if( $tentativasRestantes < 0 && $attempt->minutos <= $tempoDeBloqueio )
                {
                    $err = new MExpandDiv(NULL, $msg. _M(' Aguarde @1 minutos e tente novamente', 'gnuteca3', $tempoDeBloqueio), null, null, 30);
                    new MMessageWarning($err);
                    return;
                }
            }
        }

        if ( $loginType == LOGIN_TYPE_USER || $loginType == LOGIN_TYPE_USER_AJAX ) //Autenticacao USUARIO
        {
            //Obtem login dependendo do modo de autenticação utilizado
            $uid = $this->busPerson->insertPersonLdapWhenNeeded($uid, $base, $pwd);
            
            if ( ((MY_LIBRARY_AUTHENTICATE_TYPE == BusinessGnuteca3BusAuthenticate::TYPE_AUTHENTICATE_LOGIN)) &&  $this->MIOLO->getConf('login.classUser') == 'gAuthMoodle' )
            {
                $this->MIOLO->getClass('gnuteca3', 'gauthmoodle');

                $gAuthMoodle = new gAuthMoodle();
                $uids = $gAuthMoodle->synchronizePersonFromMoodle($uid);
            }
            
            if($uids)
            {
                $uid = $uids;
            } 
                
  
            if ( ( $loginType == LOGIN_TYPE_USER_AJAX ) && $this->isMaterialMovement() )
            {
                $info = $this->busPerson->getBasicPersonInformations($uid);

                if ($info->personId)
                {
                    $_REQUEST['personId'] = $uid;
                    $_REQUEST['uid'] = $uid;
                    return true;
                }
                else
                {
                    $this->addError(_M('Usuário não existente!', $this->module));
                    return false;
                }
            }

            $result = $this->busAuthenticate->authenticate($uid, $pwd);

            if (!$result)
            {
                if( $maximoDeTentativas > 0 && strlen($uid) > 0 && isset($busAttempt) )
                {
                    //Insere tentativa de login
                    $busAttempt->setAttempt($uid);
                }

                $err = _M('Falha na autenticação. Verifique os dados digitados.', $this->module );
                if( $maximoDeTentativas > 0 && $tentativasRestantes > 0 && strlen($uid) > 0 )
                {
                    $err = $err . ' - Restam ' . ($tentativasRestantes) . ' ' . 'tentativa(s).';
                }
                $this->addError($err);

                if ($loginType == LOGIN_TYPE_USER_AJAX)
                {
                    return false;
                }
            }
            else
            {
                if ( isset($busAttempt) )
                {
                    //Limpa os registros de tentativas
                    $busAttempt->clearAttempt($uid);
                }

                $previousUrl = $this->MIOLO->getPreviousUrl();
                if ($previousUrl && strpos($previousUrl, 'myLibrary') )
                {
                    $goto = $previousUrl;
                }
                else
                {
                    $goto = $this->MIOLO->getActionURL($this->module, 'main:myLibrary', null, $opts);
                }

                //Verifica argumentos de redirecionamento passados
                $redirect_action = MIOLO::_REQUEST('redirect_action');
                $return_to = $this->getFormValue('return_to');
                if ($redirect_action)
                {
                    $goto = $this->MIOLO->getActionURL($this->module, $redirect_action);
                }
                else if ($return_to)
                {
                    $goto = $this->MIOLO->getActionURL($this->module, $return_to);
                }

                if ($loginType == LOGIN_TYPE_USER_AJAX)
                {
                    return true;
                }
                else
                {
                    $this->page->redirect($goto);
                }
            }
        }
        else //Autenticacao ADMIN
        {
            if ( strlen($pwd) > 0 && $this->MIOLO->auth->authenticate($uid, $pwd,true) )
            {
                //Verificacao de permissao biblioteca
               $busOperatorLibraryUnit = $this->MIOLO->getBusiness($this->module, 'BusOperatorLibraryUnit');
               $libperms = $busOperatorLibraryUnit->getOperatorLibraryUnit($uid);

               if ($libperms->operatorLibrary[0]->libraryUnitId) //Se vir alguma unidade, significa que nao tem permissao para todas bibliotecas
               {
                    $found = false;
                    foreach ($libperms->operatorLibrary as $v)
                    {
                       if ($v->libraryUnitId == MIOLO::_REQUEST('libraryUnitId'))
                       {
                           $libraryName = $v->libraryName;
                           $found = true;
                       }
                    }
                    if (!$found)
                    {
                        $this->MIOLO->auth->logout();
                        $this->error(_M('Você não possui permissão para acessar esta biblioteca!', $this->module), GUtil::getCloseAction(true), null, false);
                        return;
                    }
                }

                if ( isset($busAttempt) )
                {
                    //Limpa os registros de tentativas
                    $busAttempt->clearAttempt($uid);
                }

                //Escreve no objeto login a biblioteca
                $login = $this->MIOLO->auth->getLogin();
                $login->libraryUnitId = MIOLO::_REQUEST('libraryUnitId');
                $login->libraryName = $this->busLibraryUnit->getLibraryUnit($login->libraryUnitId)->libraryName;
                $this->MIOLO->auth->setLogin($login);

               //$return_to = $this->getFormValue('return_to');
                $return_to = MIOLO::_REQUEST('return_to','GET');

               if ( $return_to )
               {
                  $url = $return_to;
               }
               else
               {
                  $url = $this->MIOLO->getActionURL($this->module,'main');
               }
               $this->page->onload("window.location='$url'");
            }
            else
            {
                if( $maximoDeTentativas > 0 && strlen($uid) > 0 )
                {
                    //Insere tentativa de login
                    $busAttempt->setAttempt($uid);
                }

                $err = _M('Erro na identificação do usuário!', $this->module );
                if( $maximoDeTentativas > 0 && $tentativasRestantes > 0 && strlen($uid) > 0 )
                {
                    $err = $err . ' - Restam ' . ($tentativasRestantes) . ' ' . 'tentativa(s).';

                    $this->error($err, GUtil::getCloseAction(true), null, false);
                }
                else
                {
                    $this->error($err);
                }
            }
        }
    }

    public function btnLogout_click()
    {
        $this->MIOLO = MIOLO::getInstance();
        $this->module = MIOLO::getCurrentModule();
        $this->page->redirect($this->MIOLO->getActionURL($this->module, 'main:logout', NULL, array('loginType'=>$this->getLoginType())));
    }

    public function isAuthenticated()
    {
        $loginType = $this->getLoginType();

        if ( $loginType == LOGIN_TYPE_USER || $loginType == LOGIN_TYPE_USER_AJAX )
        {
            $checkAcess = $this->busAuthenticate->checkAcces();
            
            if ( $loginType == LOGIN_TYPE_USER_AJAX && !$checkAcess )
            {
                return $this->btnLogin_click();
            }

            return $checkAcess;
        }
        else
        {
            return $this->MIOLO->auth->isLogged();
        }
    }

    public function getLoginType()
    {
        $loginType = $this->getFormValue('loginType', MIOLO::_REQUEST('loginType'));

        if (!$loginType) //Tipo de login padrao (ADMIN)
        {
            if ($this->args->loginType)
            {
                $loginType = $this->args->loginType;
            }
            else
            {
                $loginType = LOGIN_TYPE_ADMIN;
            }
        }
        
        return $loginType;
    }

    public function isMaterialMovement()
    {
        return (MIOLO::_REQUEST('action') == 'main:materialMovement');
    }

    /**
     * Formulário de login é um formulário público não precisa de login (dah!)
     *
     * @return true;
     */
    public function checkAccess()
    {
        return true;
    }
    
    /**
     * Faz não pedir confirmação de edição
     * 
     * @return string manage 
     */
    public function getFormMode()
    {
        return 'search';
    }
}
?>
