TYPO3 API  SVNRelease
class.tx_felogin_pi1.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2007-2011 Steffen Kamper <info@sk-typo3.de>
00006 *  Based on Newloginbox (c) 2002-2004 Kasper Skårhøj <kasper@typo3.com>
00007 *
00008 *  All rights reserved
00009 *
00010 *  This script is part of the TYPO3 project. The TYPO3 project is
00011 *  free software; you can redistribute it and/or modify
00012 *  it under the terms of the GNU General Public License as published by
00013 *  the Free Software Foundation; either version 2 of the License, or
00014 *  (at your option) any later version.
00015 *
00016 *  The GNU General Public License can be found at
00017 *  http://www.gnu.org/copyleft/gpl.html.
00018 *
00019 *  This script is distributed in the hope that it will be useful,
00020 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 *  GNU General Public License for more details.
00023 *
00024 *  This copyright notice MUST APPEAR in all copies of the script!
00025 *
00026 *  The code was adapted from newloginbox, see manual for detailed description
00027 ***************************************************************/
00028 /**
00029  * Plugin 'Website User Login' for the 'felogin' extension.
00030  *
00031  * @author  Steffen Kamper <info@sk-typo3.de>
00032  * @package TYPO3
00033  * @subpackage  tx_felogin
00034  */
00035 class tx_felogin_pi1 extends tslib_pibase {
00036     var $prefixId      = 'tx_felogin_pi1';      // Same as class name
00037     var $scriptRelPath = 'pi1/class.tx_felogin_pi1.php';    // Path to this script relative to the extension dir.
00038     var $extKey        = 'felogin'; // The extension key.
00039     public $pi_checkCHash = false;
00040     public $pi_USER_INT_obj = true;
00041 
00042     protected $userIsLoggedIn;  // Is user logged in?
00043     protected $template;    // holds the template for FE rendering
00044     protected $uploadDir;   // upload dir, used for flexform template files
00045     protected $redirectUrl; // URL for the redirect
00046     protected $noRedirect = false;  // flag for disable the redirect
00047     protected $logintype;   // logintype (given as GPvar), possible: login, logout
00048 
00049     /**
00050      * The main method of the plugin
00051      *
00052      * @param   string      $content: The PlugIn content
00053      * @param   array       $conf: The PlugIn configuration
00054      *
00055      * @return  string      The content that is displayed on the website
00056      */
00057     public function main($content,$conf)    {
00058 
00059             // Loading TypoScript array into object variable:
00060         $this->conf = $conf;
00061         $this->uploadDir = 'uploads/tx_felogin/';
00062 
00063             // Loading default pivars
00064         $this->pi_setPiVarDefaults();
00065 
00066             // Loading language-labels
00067         $this->pi_loadLL();
00068 
00069             // Init FlexForm configuration for plugin:
00070         $this->pi_initPIflexForm();
00071         $this->mergeflexFormValuesIntoConf();
00072 
00073 
00074             // Get storage PIDs:
00075         if ($this->conf['storagePid']) {
00076             if (intval($this->conf['recursive'])) {
00077                 $this->spid = $this->pi_getPidList($this->conf['storagePid'], intval($this->conf['recursive']));
00078             } else {
00079                 $this->spid = $this->conf['storagePid'];
00080             }
00081         } else {
00082             $pids = $GLOBALS['TSFE']->getStorageSiterootPids();
00083             $this->spid = $pids['_STORAGE_PID'];
00084         }
00085 
00086             // GPvars:
00087         $this->logintype = t3lib_div::_GP('logintype');
00088         $this->referer = $this->validateRedirectUrl(t3lib_div::_GP('referer'));
00089         $this->noRedirect = ($this->piVars['noredirect'] || $this->conf['redirectDisable']);
00090 
00091             // if config.typolinkLinkAccessRestrictedPages is set, the var is return_url
00092         $returnUrl =  t3lib_div::_GP('return_url');
00093         if ($returnUrl) {
00094             $this->redirectUrl = $returnUrl;
00095         } else {
00096             $this->redirectUrl = t3lib_div::_GP('redirect_url');
00097         }
00098         $this->redirectUrl = $this->validateRedirectUrl($this->redirectUrl);
00099 
00100             // Get Template
00101         $templateFile = $this->conf['templateFile'] ? $this->conf['templateFile'] : 'EXT:felogin/template.html';
00102         $this->template = $this->cObj->fileResource($templateFile);
00103 
00104             // Is user logged in?
00105         $this->userIsLoggedIn = $GLOBALS['TSFE']->loginUser;
00106 
00107             // Redirect
00108         if ($this->conf['redirectMode'] && !$this->conf['redirectDisable'] && !$this->noRedirect) {
00109             $redirectUrl = $this->processRedirect();
00110             if (count($redirectUrl)) {
00111                 $this->redirectUrl = $this->conf['redirectFirstMethod'] ? array_shift($redirectUrl) : array_pop($redirectUrl);
00112             } else {
00113                 $this->redirectUrl = '';
00114             }
00115         }
00116 
00117             // What to display
00118         $content='';
00119         if ($this->piVars['forgot']) {
00120             $content .= $this->showForgot();
00121         } elseif ($this->piVars['forgothash']) {
00122             $content .= $this->changePassword();
00123         } else {
00124             if($this->userIsLoggedIn && !$this->logintype) {
00125                 $content .= $this->showLogout();
00126             } else {
00127                 $content .= $this->showLogin();
00128             }
00129         }
00130 
00131             // Process the redirect
00132         if (($this->logintype === 'login' || $this->logintype === 'logout') && $this->redirectUrl && !$this->noRedirect) {
00133             if (!$GLOBALS['TSFE']->fe_user->cookieId) {
00134                 $content .= $this->cObj->stdWrap($this->pi_getLL('cookie_warning', '', 1), $this->conf['cookieWarning_stdWrap.']);
00135             } else {
00136                 t3lib_utility_Http::redirect($this->redirectUrl);
00137             }
00138         }
00139 
00140             // Adds hook for processing of extra item markers / special
00141         if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['postProcContent']) && is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['postProcContent'])) {
00142             $_params = array(
00143                 'content' => $content
00144             );
00145             foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['postProcContent'] as $_funcRef) {
00146                 $content = t3lib_div::callUserFunction($_funcRef, $_params, $this);
00147             }
00148         }
00149 
00150         return $this->conf['wrapContentInBaseClass'] ? $this->pi_wrapInBaseClass($content) : $content;
00151 
00152     }
00153 
00154      /**
00155       * Shows the forgot password form
00156       *
00157       * @return string      content
00158       */
00159      protected function showForgot() {
00160         $subpart = $this->cObj->getSubpart($this->template, '###TEMPLATE_FORGOT###');
00161         $subpartArray = $linkpartArray = array();
00162         $postData =  t3lib_div::_POST($this->prefixId);
00163 
00164         if ($postData['forgot_email']) {
00165 
00166                 // get hashes for compare
00167             $postedHash = $postData['forgot_hash'];
00168             $hashData = $GLOBALS['TSFE']->fe_user->getKey('ses', 'forgot_hash');
00169 
00170 
00171             if ($postedHash === $hashData['forgot_hash']) {
00172                 $row = FALSE;
00173 
00174                     // look for user record
00175                 $data = $GLOBALS['TYPO3_DB']->fullQuoteStr($this->piVars['forgot_email'], 'fe_users');
00176                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00177                     'uid, username, password, email',
00178                     'fe_users',
00179                     '(email=' . $data .' OR username=' . $data . ') AND pid IN ('.$GLOBALS['TYPO3_DB']->cleanIntList($this->spid).') '.$this->cObj->enableFields('fe_users')
00180                 );
00181 
00182                 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
00183                     $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
00184                 }
00185 
00186                 if ($row) {
00187                             // generate an email with the hashed link
00188                         $error = $this->generateAndSendHash($row);
00189                 }
00190                     // generate message
00191                 if ($error) {
00192                     $markerArray['###STATUS_MESSAGE###'] = $this->cObj->stdWrap($error, $this->conf['forgotMessage_stdWrap.']);
00193                 } else {
00194                     $markerArray['###STATUS_MESSAGE###'] = $this->cObj->stdWrap($this->pi_getLL('ll_forgot_reset_message_emailSent', '', 1), $this->conf['forgotMessage_stdWrap.']);
00195                 }
00196                 $subpartArray['###FORGOT_FORM###'] = '';
00197 
00198 
00199             } else {
00200                     //wrong email
00201                 $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('forgot_reset_message', $this->conf['forgotMessage_stdWrap.']);
00202                 $markerArray['###BACKLINK_LOGIN###'] = '';
00203             }
00204         } else {
00205             $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('forgot_reset_message', $this->conf['forgotMessage_stdWrap.']);
00206             $markerArray['###BACKLINK_LOGIN###'] = '';
00207         }
00208 
00209         $markerArray['###BACKLINK_LOGIN###'] = $this->getPageLink($this->pi_getLL('ll_forgot_header_backToLogin', '', 1), array());
00210         $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('forgot_header', $this->conf['forgotHeader_stdWrap.']);
00211 
00212         $markerArray['###LEGEND###'] = $this->pi_getLL('reset_password', '', 1);
00213         $markerArray['###ACTION_URI###'] = $this->getPageLink('', array($this->prefixId . '[forgot]'=>1), true);
00214         $markerArray['###EMAIL_LABEL###'] = $this->pi_getLL('your_email', '', 1);
00215         $markerArray['###FORGOT_PASSWORD_ENTEREMAIL###'] = $this->pi_getLL('forgot_password_enterEmail', '', 1);
00216         $markerArray['###FORGOT_EMAIL###'] = $this->prefixId.'[forgot_email]';
00217         $markerArray['###SEND_PASSWORD###'] = $this->pi_getLL('reset_password', '', 1);
00218 
00219         $markerArray['###DATA_LABEL###'] = $this->pi_getLL('ll_enter_your_data', '', 1);
00220 
00221 
00222 
00223         $markerArray = array_merge($markerArray, $this->getUserFieldMarkers());
00224 
00225             // generate hash
00226         $hash = md5($this->generatePassword(3));
00227         $markerArray['###FORGOTHASH###'] = $hash;
00228             // set hash in feuser session
00229         $GLOBALS['TSFE']->fe_user->setKey('ses', 'forgot_hash', array('forgot_hash' => $hash));
00230 
00231 
00232         return $this->cObj->substituteMarkerArrayCached($subpart, $markerArray, $subpartArray, $linkpartArray);
00233     }
00234 
00235     /**
00236      * This function checks the hash from link and checks the validity. If it's valid it shows the form for
00237      * changing the password and process the change of password after submit, if not valid it returns the error message
00238      *
00239      * @return  string      The content.
00240      */
00241     protected function changePassword() {
00242 
00243         $subpartArray = $linkpartArray = array();
00244         $done = false;
00245 
00246         $minLength = intval($this->conf['newPasswordMinLength']) ? intval($this->conf['newPasswordMinLength']) : 6;
00247 
00248         $subpart = $this->cObj->getSubpart($this->template, '###TEMPLATE_CHANGEPASSWORD###');
00249 
00250         $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('change_password_header', $this->conf['changePasswordHeader_stdWrap.']);
00251         $markerArray['###STATUS_MESSAGE###'] = sprintf($this->getDisplayText('change_password_message', $this->conf['changePasswordMessage_stdWrap.']), $minLength);
00252 
00253         $markerArray['###BACKLINK_LOGIN###'] = '';
00254         $uid = $this->piVars['user'];
00255         $piHash = $this->piVars['forgothash'];
00256 
00257         $hash = explode('|', $piHash);
00258         if (intval($uid) == 0) {
00259             $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('change_password_notvalid_message', $this->conf['changePasswordMessage_stdWrap.']);
00260             $subpartArray['###CHANGEPASSWORD_FORM###'] = '';
00261         } else {
00262             $user = $this->pi_getRecord('fe_users', intval($uid));
00263             $userHash = $user['felogin_forgotHash'];
00264             $compareHash = explode('|', $userHash);
00265 
00266             if (!$compareHash || !$compareHash[1] || $compareHash[0] < time() ||  $hash[0] != $compareHash[0] ||  md5($hash[1]) != $compareHash[1]) {
00267                 $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('change_password_notvalid_message',$this->conf['changePasswordMessage_stdWrap.']);
00268                 $subpartArray['###CHANGEPASSWORD_FORM###'] = '';
00269             } else {
00270                     // all is fine, continue with new password
00271                 $postData = t3lib_div::_POST($this->prefixId);
00272 
00273                 if (isset($postData['changepasswordsubmit'])) {
00274                     if (strlen($postData['password1']) < $minLength) {
00275                         $markerArray['###STATUS_MESSAGE###'] = sprintf($this->getDisplayText('change_password_tooshort_message', $this->conf['changePasswordMessage_stdWrap.']), $minLength);
00276                     } elseif ($postData['password1'] != $postData['password2']) {
00277                         $markerArray['###STATUS_MESSAGE###'] = sprintf($this->getDisplayText('change_password_notequal_message', $this->conf['changePasswordMessage_stdWrap.']), $minLength);
00278                     } else {
00279                         $newPass = $postData['password1'];
00280 
00281                         if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['password_changed']) {
00282                             $_params = array(
00283                                 'user' => $user,
00284                                 'newPassword' => $newPass,
00285                             );
00286                             foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['password_changed'] as $_funcRef) {
00287                                 if ($_funcRef) {
00288                                     t3lib_div::callUserFunction($_funcRef, $_params, $this);
00289                                 }
00290                             }
00291                             $newPass = $_params['newPassword'];
00292                         }
00293 
00294                             // save new password and clear DB-hash
00295                         $res = $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00296                                 'fe_users',
00297                                 'uid=' . $user['uid'],
00298                                 array('password' => $newPass, 'felogin_forgotHash' => '')
00299                             );
00300                         $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('change_password_done_message', $this->conf['changePasswordMessage_stdWrap.']);
00301                         $done = true;
00302                         $subpartArray['###CHANGEPASSWORD_FORM###'] = '';
00303                         $markerArray['###BACKLINK_LOGIN###'] = $this->getPageLink($this->pi_getLL('ll_forgot_header_backToLogin', '', 1), array());
00304                     }
00305                 }
00306 
00307                 if (!$done) {
00308                     // Change password form
00309                     $markerArray['###ACTION_URI###'] = $this->pi_getPageLink($GLOBALS['TSFE']->id, '', array(
00310                         $this->prefixId . '[user]' => $user['uid'],
00311                         $this->prefixId . '[forgothash]' => $piHash
00312                     ));
00313                     $markerArray['###LEGEND###'] = $this->pi_getLL('change_password', '', 1);
00314                     $markerArray['###NEWPASSWORD1_LABEL###'] = $this->pi_getLL('newpassword_label1', '', 1);
00315                     $markerArray['###NEWPASSWORD2_LABEL###'] = $this->pi_getLL('newpassword_label2', '', 1);
00316                     $markerArray['###NEWPASSWORD1###'] = $this->prefixId . '[password1]';
00317                     $markerArray['###NEWPASSWORD2###'] = $this->prefixId . '[password2]';
00318                     $markerArray['###STORAGE_PID###'] = $this->spid;
00319                     $markerArray['###SEND_PASSWORD###'] = $this->pi_getLL('change_password', '', 1);
00320                     $markerArray['###FORGOTHASH###'] = $piHash;
00321                 }
00322             }
00323         }
00324 
00325         return $this->cObj->substituteMarkerArrayCached($subpart, $markerArray, $subpartArray, $linkpartArray);
00326     }
00327 
00328     /**
00329      * generates a hashed link and send it with email
00330      *
00331      * @param   array       $user   contains user data
00332      * @return  string      Empty string with success, error message with no success
00333      */
00334     protected function generateAndSendHash($user) {
00335         $hours = intval($this->conf['forgotLinkHashValidTime']) > 0 ? intval($this->conf['forgotLinkHashValidTime']) : 24;
00336         $validEnd = time() + 3600 * $hours;
00337         $validEndString = date($this->conf['dateFormat'], $validEnd);
00338 
00339         $hash = md5(t3lib_div::generateRandomBytes(64));
00340         $randHash = $validEnd . '|' . $hash;
00341         $randHashDB = $validEnd . '|' . md5($hash);
00342 
00343         //write hash to DB
00344         $res = $GLOBALS['TYPO3_DB']->exec_UPDATEquery('fe_users', 'uid=' . $user['uid'], array('felogin_forgotHash' => $randHashDB));
00345 
00346         // send hashlink to user
00347         $this->conf['linkPrefix'] = -1;
00348         $isAbsRelPrefix = !empty($GLOBALS['TSFE']->absRefPrefix);
00349         $isBaseURL  = !empty($GLOBALS['TSFE']->baseUrl);
00350         $isFeloginBaseURL = !empty($this->conf['feloginBaseURL']);
00351 
00352         if ($isFeloginBaseURL) {
00353                 // first priority
00354             $this->conf['linkPrefix'] = $this->conf['feloginBaseURL'];
00355         } else {
00356             if ($isBaseURL) {
00357                     // 3rd priority
00358                 $this->conf['linkPrefix'] = $GLOBALS['TSFE']->baseUrl;
00359             }
00360         }
00361 
00362         if ($this->conf['linkPrefix'] == -1 && !$isAbsRelPrefix) {
00363                 // no preix is set, return the error
00364             return $this->pi_getLL('ll_change_password_nolinkprefix_message');
00365         }
00366 
00367         $link = ($isAbsRelPrefix ? '' : $this->conf['linkPrefix']) . $this->pi_getPageLink($GLOBALS['TSFE']->id, '', array(
00368             $this->prefixId . '[user]' => $user['uid'],
00369             $this->prefixId . '[forgothash]' => $randHash
00370         ));
00371 
00372         $msg = sprintf($this->pi_getLL('ll_forgot_validate_reset_password', '', 0), $user['username'], $link, $validEndString);
00373 
00374             // no RDCT - Links for security reasons
00375         $oldSetting = $GLOBALS['TSFE']->config['config']['notification_email_urlmode'];
00376         $GLOBALS['TSFE']->config['config']['notification_email_urlmode'] = 0;
00377             // send the email
00378         $this->cObj->sendNotifyEmail($msg, $user['email'], '', $this->conf['email_from'], $this->conf['email_fromName'], $this->conf['replyTo']);
00379             // restore settings
00380         $GLOBALS['TSFE']->config['config']['notification_email_urlmode'] = $oldSetting;
00381 
00382         return '';
00383     }
00384 
00385     /**
00386      * Shows logout form
00387      *
00388      * @return  string      The content.
00389      */
00390     protected function showLogout() {
00391         $subpart = $this->cObj->getSubpart($this->template, '###TEMPLATE_LOGOUT###');
00392         $subpartArray = $linkpartArray = array();
00393 
00394         $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('status_header',$this->conf['logoutHeader_stdWrap.']);
00395         $markerArray['###STATUS_MESSAGE###']=$this->getDisplayText('status_message',$this->conf['logoutMessage_stdWrap.']);$this->cObj->stdWrap($this->flexFormValue('message','s_status'),$this->conf['logoutMessage_stdWrap.']);
00396 
00397         $markerArray['###LEGEND###'] = $this->pi_getLL('logout', '', 1);
00398         $markerArray['###ACTION_URI###'] = $this->getPageLink('',array(),true);
00399         $markerArray['###LOGOUT_LABEL###'] = $this->pi_getLL('logout', '', 1);
00400         $markerArray['###NAME###'] = htmlspecialchars($GLOBALS['TSFE']->fe_user->user['name']);
00401         $markerArray['###STORAGE_PID###'] = $this->spid;
00402         $markerArray['###USERNAME###'] = htmlspecialchars($GLOBALS['TSFE']->fe_user->user['username']);
00403         $markerArray['###USERNAME_LABEL###'] = $this->pi_getLL('username', '', 1);
00404         $markerArray['###NOREDIRECT###'] = $this->noRedirect ? '1' : '0';
00405         $markerArray['###PREFIXID###'] = $this->prefixId;
00406         $markerArray = array_merge($markerArray, $this->getUserFieldMarkers());
00407 
00408         if ($this->redirectUrl) {
00409                 // use redirectUrl for action tag because of possible access restricted pages
00410             $markerArray['###ACTION_URI###'] = htmlspecialchars($this->redirectUrl);
00411             $this->redirectUrl = '';
00412         }
00413         return $this->cObj->substituteMarkerArrayCached($subpart, $markerArray, $subpartArray, $linkpartArray);
00414     }
00415 
00416     /**
00417      * Shows login form
00418      *
00419      * @return  string      content
00420      */
00421      protected function showLogin() {
00422         $subpart = $this->cObj->getSubpart($this->template, '###TEMPLATE_LOGIN###');
00423         $subpartArray = $linkpartArray = array();
00424 
00425         $gpRedirectUrl = '';
00426 
00427         $markerArray['###LEGEND###'] = $this->pi_getLL('oLabel_header_welcome', '', 1);
00428 
00429         if($this->logintype === 'login') {
00430             if($this->userIsLoggedIn) {
00431                     // login success
00432                 $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('success_header',$this->conf['successHeader_stdWrap.']);
00433                 $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('success_message', $this->conf['successMessage_stdWrap.']);
00434                 $markerArray = array_merge($markerArray, $this->getUserFieldMarkers());
00435                 $subpartArray['###LOGIN_FORM###'] = '';
00436 
00437                     // Hook for general actions after after login has been confirmed (by Thomas Danzl <thomas@danzl.org>)
00438                 if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['login_confirmed']) {
00439                     $_params = array();
00440                     foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['login_confirmed'] as $_funcRef) {
00441                         if ($_funcRef) {
00442                             t3lib_div::callUserFunction($_funcRef, $_params, $this);
00443                         }
00444                     }
00445                 }
00446                     // show logout form directly
00447                 if ($this->conf['showLogoutFormAfterLogin']) {
00448                     $this->redirectUrl = '';
00449                     return $this->showLogout();
00450                 }
00451             } else {
00452                     // login error
00453                 $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('error_header',$this->conf['errorHeader_stdWrap.']);
00454                 $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('error_message',$this->conf['errorMessage_stdWrap.']);
00455                 $gpRedirectUrl = t3lib_div::_GP('redirect_url');
00456             }
00457         } else {
00458             if($this->logintype === 'logout') {
00459                     // login form after logout
00460                 $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('logout_header',$this->conf['welcomeHeader_stdWrap.']);
00461                 $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('logout_message',$this->conf['welcomeMessage_stdWrap.']);
00462             } else {
00463                     // login form
00464                 $markerArray['###STATUS_HEADER###'] = $this->getDisplayText('welcome_header',$this->conf['welcomeHeader_stdWrap.']);
00465                 $markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('welcome_message',$this->conf['welcomeMessage_stdWrap.']);
00466             }
00467         }
00468 
00469 
00470             // Hook (used by kb_md5fepw extension by Kraft Bernhard <kraftb@gmx.net>)
00471             // This hook allows to call User JS functions.
00472             // The methods should also set the required JS functions to get included
00473         $onSubmit = '';
00474         $extraHidden = '';
00475         $onSubmitAr = array();
00476         $extraHiddenAr = array();
00477 
00478             // check for referer redirect method. if present, save referer in form field
00479         if (t3lib_div::inList($this->conf['redirectMode'], 'referer') || t3lib_div::inList($this->conf['redirectMode'], 'refererDomains')) {
00480             $referer = $this->referer ? $this->referer : t3lib_div::getIndpEnv('HTTP_REFERER');
00481             if ($referer) {
00482                 $extraHiddenAr[] = '<input type="hidden" name="referer" value="' . htmlspecialchars($referer) . '" />';
00483             }
00484         }
00485 
00486         if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['loginFormOnSubmitFuncs'])) {
00487             $_params = array();
00488             foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['loginFormOnSubmitFuncs'] as $funcRef) {
00489                 list($onSub, $hid) = t3lib_div::callUserFunction($funcRef, $_params, $this);
00490                 $onSubmitAr[] = $onSub;
00491                 $extraHiddenAr[] = $hid;
00492             }
00493         }
00494         if (count($onSubmitAr)) {
00495             $onSubmit = implode('; ', $onSubmitAr).'; return true;';
00496         }
00497         if (count($extraHiddenAr)) {
00498             $extraHidden = implode(LF, $extraHiddenAr);
00499         }
00500 
00501         if (!$gpRedirectUrl && $this->redirectUrl) {
00502             $gpRedirectUrl = $this->redirectUrl;
00503         }
00504 
00505             // Login form
00506         $markerArray['###ACTION_URI###'] = $this->getPageLink('',array(),true);
00507         $markerArray['###EXTRA_HIDDEN###'] = $extraHidden; // used by kb_md5fepw extension...
00508         $markerArray['###LEGEND###'] = $this->pi_getLL('login', '', 1);
00509         $markerArray['###LOGIN_LABEL###'] = $this->pi_getLL('login', '', 1);
00510         $markerArray['###ON_SUBMIT###'] = $onSubmit; // used by kb_md5fepw extension...
00511         $markerArray['###PASSWORD_LABEL###'] = $this->pi_getLL('password', '', 1);
00512         $markerArray['###STORAGE_PID###'] = $this->spid;
00513         $markerArray['###USERNAME_LABEL###'] = $this->pi_getLL('username', '', 1);
00514         $markerArray['###REDIRECT_URL###'] = htmlspecialchars($gpRedirectUrl);
00515         $markerArray['###NOREDIRECT###'] = $this->noRedirect ? '1' : '0';
00516         $markerArray['###PREFIXID###'] = $this->prefixId;
00517         $markerArray = array_merge($markerArray, $this->getUserFieldMarkers());
00518 
00519         if ($this->flexFormValue('showForgotPassword','sDEF') || $this->conf['showForgotPasswordLink']) {
00520             $linkpartArray['###FORGOT_PASSWORD_LINK###'] = explode('|',$this->getPageLink('|',array($this->prefixId.'[forgot]'=>1)));
00521             $markerArray['###FORGOT_PASSWORD###'] = $this->pi_getLL('ll_forgot_header', '', 1);
00522         } else {
00523             $subpartArray['###FORGOTP_VALID###'] = '';
00524         }
00525 
00526 
00527             // The permanent login checkbox should only be shown if permalogin is not deactivated (-1), not forced to be always active (2) and lifetime is greater than 0
00528         if ($this->conf['showPermaLogin'] && t3lib_div::inList('0,1', $GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin']) && $GLOBALS['TYPO3_CONF_VARS']['FE']['lifetime'] > 0) {
00529             $markerArray['###PERMALOGIN###'] = $this->pi_getLL('permalogin', '', 1);
00530             if($GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 1) {
00531                 $markerArray['###PERMALOGIN_HIDDENFIELD_ATTRIBUTES###'] = 'disabled="disabled"';
00532                 $markerArray['###PERMALOGIN_CHECKBOX_ATTRIBUTES###'] = 'checked="checked"';
00533             } else {
00534                 $markerArray['###PERMALOGIN_HIDDENFIELD_ATTRIBUTES###'] = '';
00535                 $markerArray['###PERMALOGIN_CHECKBOX_ATTRIBUTES###'] = '';
00536             }
00537         } else {
00538             $subpartArray['###PERMALOGIN_VALID###'] = '';
00539         }
00540         return $this->cObj->substituteMarkerArrayCached($subpart, $markerArray, $subpartArray, $linkpartArray);
00541     }
00542 
00543     /**
00544      * Process redirect methods. The function searches for a redirect url using all configured methods.
00545      *
00546      * @return  string      redirect url
00547      */
00548      protected function processRedirect() {
00549         $redirect_url = array();
00550         if ($this->conf['redirectMode']) {
00551             $redirectMethods = t3lib_div::trimExplode(',', $this->conf['redirectMode'], TRUE);
00552             foreach ($redirectMethods as $redirMethod) {
00553                 if ($GLOBALS['TSFE']->loginUser && $this->logintype === 'login') {
00554                         // logintype is needed because the login-page wouldn't be accessible anymore after a login (would always redirect)
00555                     switch ($redirMethod) {
00556                         case 'groupLogin': // taken from dkd_redirect_at_login written by Ingmar Schlecht; database-field changed
00557                             $groupData = $GLOBALS['TSFE']->fe_user->groupData;
00558                             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00559                                 'felogin_redirectPid',
00560                                 $GLOBALS['TSFE']->fe_user->usergroup_table,
00561                                 'felogin_redirectPid!="" AND uid IN (' . implode(',', $groupData['uid']) . ')'
00562                             );
00563                             if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res))   {
00564                                 $redirect_url[] = $this->pi_getPageLink($row[0]); // take the first group with a redirect page
00565                             }
00566                         break;
00567                         case 'userLogin':
00568                             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00569                                 'felogin_redirectPid',
00570                                 $GLOBALS['TSFE']->fe_user->user_table,
00571                                 $GLOBALS['TSFE']->fe_user->userid_column . '=' . $GLOBALS['TSFE']->fe_user->user['uid'] . ' AND felogin_redirectPid!=""'
00572                             );
00573                             if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res))   {
00574                                 $redirect_url[] = $this->pi_getPageLink($row[0]);
00575                             }
00576                         break;
00577                         case 'login':
00578                             if ($this->conf['redirectPageLogin']) {
00579                                 $redirect_url[] = $this->pi_getPageLink(intval($this->conf['redirectPageLogin']));
00580                             }
00581                         break;
00582                         case 'getpost':
00583                             $redirect_url[] = $this->redirectUrl;
00584                         break;
00585                         case 'referer':
00586                                 // avoid forced logout, when trying to login immediatly after a logout
00587                             $redirect_url[] = preg_replace('/[&?]logintype=[a-z]+/', '', $this->referer);
00588                         break;
00589                         case 'refererDomains':
00590                                 // Auto redirect.
00591                                 // Feature to redirect to the page where the user came from (HTTP_REFERER).
00592                                 // Allowed domains to redirect to, can be configured with plugin.tx_felogin_pi1.domains
00593                                 // Thanks to plan2.net / Martin Kutschker for implementing this feature.
00594                             if ($this->conf['domains']) {
00595                                 $url = $this->referer;
00596                                     // is referring url allowed to redirect?
00597                                 $match = array();
00598                                 if (preg_match('/^http://([[:alnum:]._-]+)//', $url, $match)) {
00599                                     $redirect_domain = $match[1];
00600                                     $found = false;
00601                                     foreach(t3lib_div::trimExplode(',', $this->conf['domains'], TRUE) as $d) {
00602                                         if (preg_match('/(^|\.)/'.$d.'$', $redirect_domain)) {
00603                                             $found = true;
00604                                             break;
00605                                         }
00606                                     }
00607                                     if (!$found) {
00608                                         $url = '';
00609                                     }
00610                                 }
00611 
00612                                     // Avoid forced logout, when trying to login immediatly after a logout
00613                                 if ($url) {
00614                                     $redirect_url[] = preg_replace('/[&?]logintype=[a-z]+/', '', $url);
00615                             }
00616                             }
00617                         break;
00618                     }
00619                 } else if ($this->logintype === 'login') { // after login-error
00620                     switch ($redirMethod) {
00621                         case 'loginError':
00622                             if ($this->conf['redirectPageLoginError']) {
00623                                 $redirect_url[] = $this->pi_getPageLink(intval($this->conf['redirectPageLoginError']));
00624                             }
00625                         break;
00626                     }
00627                 } elseif (($this->logintype == '') && ($redirMethod == 'login') && $this->conf['redirectPageLogin']) {
00628                         // if login and page not accessible
00629                     $this->cObj->typolink('', array(
00630                         'parameter'                 => $this->conf['redirectPageLogin'],
00631                         'linkAccessRestrictedPages' => TRUE,
00632                     ));
00633                     $redirect_url[] = $this->cObj->lastTypoLinkUrl;
00634 
00635                 } elseif (($this->logintype == '') && ($redirMethod == 'logout') && $this->conf['redirectPageLogout'] && $GLOBALS['TSFE']->loginUser) {
00636                         // if logout and page not accessible
00637                     $redirect_url[] = $this->pi_getPageLink(intval($this->conf['redirectPageLogout']));
00638 
00639                 } elseif ($this->logintype === 'logout') { // after logout
00640 
00641                     // Hook for general actions after after logout has been confirmed
00642                     if ($this->logintype === 'logout' && $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['logout_confirmed']) {
00643                         $_params = array();
00644                         foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['felogin']['logout_confirmed'] as $_funcRef) {
00645                             if ($_funcRef) {
00646                                 t3lib_div::callUserFunction($_funcRef, $_params, $this);
00647                             }
00648                         }
00649                     }
00650 
00651                     switch ($redirMethod) {
00652                         case 'logout':
00653                             if ($this->conf['redirectPageLogout']) {
00654                                 $redirect_url[] = $this->pi_getPageLink(intval($this->conf['redirectPageLogout']));
00655                             }
00656                         break;
00657                     }
00658                 } else { // not logged in
00659                         // Placeholder for maybe future options
00660                     switch ($redirMethod) {
00661                         case 'getpost':
00662                             // preserve the get/post value
00663                             $redirect_url[] = $this->redirectUrl;
00664                         break;
00665                     }
00666                 }
00667 
00668                 }
00669             }
00670                 // remove empty values
00671             if (count($redirect_url)) {
00672                 return t3lib_div::trimExplode(',', implode(',', $redirect_url), TRUE);
00673             } else {
00674                 return array();
00675         }
00676     }
00677 
00678     /**
00679      * Reads flexform configuration and merge it with $this->conf
00680      *
00681      * @return  void
00682      */
00683      protected function mergeflexFormValuesIntoConf() {
00684         $flex = array();
00685         if ($this->flexFormValue('showForgotPassword', 'sDEF')) {
00686             $flex['showForgotPassword'] = $this->flexFormValue('showForgotPassword','sDEF');
00687         }
00688 
00689         if ($this->flexFormValue('showPermaLogin', 'sDEF')) {
00690             $flex['showPermaLogin'] = $this->flexFormValue('showPermaLogin', 'sDEF');
00691         }
00692 
00693         if ($this->flexFormValue('showLogoutFormAfterLogin', 'sDEF')) {
00694             $flex['showLogoutFormAfterLogin'] = $this->flexFormValue('showLogoutFormAfterLogin', 'sDEF');
00695         }
00696 
00697         if ($this->flexFormValue('pages', 'sDEF')) {
00698             $flex['pages'] = $this->flexFormValue('pages', 'sDEF');
00699         }
00700 
00701         if ($this->flexFormValue('recursive', 'sDEF')) {
00702             $flex['recursive'] = $this->flexFormValue('recursive', 'sDEF');
00703         }
00704 
00705         if ($this->flexFormValue('templateFile', 'sDEF')) {
00706             $flex['templateFile'] = $this->uploadDir . $this->flexFormValue('templateFile', 'sDEF');
00707         }
00708 
00709         if ($this->flexFormValue('redirectMode', 's_redirect')) {
00710             $flex['redirectMode'] = $this->flexFormValue('redirectMode', 's_redirect');
00711         }
00712 
00713         if ($this->flexFormValue('redirectFirstMethod', 's_redirect')) {
00714             $flex['redirectFirstMethod'] = $this->flexFormValue('redirectFirstMethod', 's_redirect');
00715         }
00716 
00717         if ($this->flexFormValue('redirectDisable', 's_redirect')) {
00718             $flex['redirectDisable'] = $this->flexFormValue('redirectDisable', 's_redirect');
00719         }
00720 
00721         if ($this->flexFormValue('redirectPageLogin', 's_redirect')) {
00722             $flex['redirectPageLogin'] = $this->flexFormValue('redirectPageLogin', 's_redirect');
00723         }
00724 
00725         if ($this->flexFormValue('redirectPageLoginError', 's_redirect')) {
00726             $flex['redirectPageLoginError'] = $this->flexFormValue('redirectPageLoginError','s_redirect');
00727         }
00728 
00729         if ($this->flexFormValue('redirectPageLogout', 's_redirect')) {
00730             $flex['redirectPageLogout'] = $this->flexFormValue('redirectPageLogout', 's_redirect');
00731         }
00732 
00733         $pid = $flex['pages'] ? $this->pi_getPidList($flex['pages'], $flex['recursive']) : 0;
00734         if ($pid > 0) {
00735             $flex['storagePid'] = $pid;
00736         }
00737 
00738         $this->conf = array_merge($this->conf, $flex);
00739     }
00740 
00741     /**
00742      * Loads a variable from the flexform
00743      *
00744      * @param   string      name of variable
00745      * @param   string      name of sheet
00746      * @return  string      value of var
00747      */
00748     protected function flexFormValue($var, $sheet) {
00749         return $this->pi_getFFvalue($this->cObj->data['pi_flexform'], $var,$sheet);
00750     }
00751 
00752     /**
00753      * Generate link with typolink function
00754      *
00755      * @param   string      linktext
00756      * @param   array       link vars
00757      * @param   boolean     true: returns only url  false (default) returns the link)
00758      *
00759      * @return  string      link or url
00760      */
00761      protected function getPageLink($label, $piVars,$returnUrl = false) {
00762         $additionalParams = '';
00763 
00764         if (count($piVars)) {
00765             foreach($piVars as $key=>$val) {
00766                 $additionalParams .= '&' . $key . '=' . $val;
00767             }
00768         }
00769             // should GETvars be preserved?
00770         if ($this->conf['preserveGETvars']) {
00771             $additionalParams .= $this->getPreserveGetVars();
00772         }
00773 
00774         $this->conf['linkConfig.']['parameter'] = $GLOBALS['TSFE']->id;
00775         if ($additionalParams)  {
00776             $this->conf['linkConfig.']['additionalParams'] =  $additionalParams;
00777         }
00778 
00779         if ($returnUrl) {
00780             return htmlspecialchars($this->cObj->typolink_url($this->conf['linkConfig.']));
00781         } else {
00782             return $this->cObj->typolink($label,$this->conf['linkConfig.']);
00783         }
00784     }
00785 
00786     /**
00787      * Is used by TS-setting preserveGETvars
00788      * possible values are "all" or a commaseperated list of GET-vars
00789      * they are used as additionalParams for link generation
00790      *
00791      * @return  string      additionalParams-string
00792      */
00793      protected function getPreserveGetVars() {
00794 
00795         $params = '';
00796         $preserveVars =! ($this->conf['preserveGETvars'] || $this->conf['preserveGETvars']=='all' ? array() : implode(',', (array)$this->conf['preserveGETvars']));
00797         $getVars = t3lib_div::_GET();
00798 
00799         foreach ($getVars as $key => $val) {
00800             if (stristr($key,$this->prefixId) === false) {
00801                 if (is_array($val)) {
00802                     foreach ($val as $key1 => $val1) {
00803                         if ($this->conf['preserveGETvars'] == 'all' || in_array($key . '[' . $key1 .']', $preserveVars)) {
00804                             $params .= '&' . $key . '[' . $key1 . ']=' . $val1;
00805                         }
00806                     }
00807                 } else {
00808                     if (!in_array($key, array('id','no_cache','logintype','redirect_url','cHash'))) {
00809                         $params .= '&' . $key . '=' . $val;
00810                     }
00811                 }
00812             }
00813         }
00814         return $params;
00815     }
00816 
00817     /**
00818      * Is used by forgot password - function with md5 option.
00819      *
00820      * @author  Bernhard Kraft
00821      *
00822      * @param   int         length of new password
00823      * @return  string      new password
00824      */
00825      protected function generatePassword($len) {
00826         $pass = '';
00827         while ($len--) {
00828             $char = rand(0,35);
00829             if ($char < 10) {
00830                 $pass .= '' . $char;
00831             } else {
00832                 $pass .= chr($char - 10 + 97);
00833             }
00834         }
00835         return $pass;
00836     }
00837 
00838     /**
00839      * Returns the header / message value from flexform if present, else from locallang.xml
00840      *
00841      * @param   string      label name
00842      * @param   string      TS stdWrap array
00843      * @return  string      label text
00844      */
00845     protected function getDisplayText($label, $stdWrapArray=array()) {
00846         $text = $this->flexFormValue($label, 's_messages') ? $this->cObj->stdWrap($this->flexFormValue($label, 's_messages'), $stdWrapArray) : $this->cObj->stdWrap($this->pi_getLL('ll_'.$label, '', 1), $stdWrapArray);
00847         $replace = $this->getUserFieldMarkers();
00848         return strtr($text, $replace);
00849     }
00850 
00851     /**
00852      * Returns Array of markers filled with user fields
00853      *
00854      * @return  array       marker array
00855      */
00856     protected function getUserFieldMarkers() {
00857         $marker = array();
00858         // replace markers with fe_user data
00859         if ($GLOBALS['TSFE']->fe_user->user) {
00860             // all fields of fe_user will be replaced, scheme is ###FEUSER_FIELDNAME###
00861             foreach ($GLOBALS['TSFE']->fe_user->user as $field => $value) {
00862                 $marker['###FEUSER_' . t3lib_div::strtoupper($field) . '###'] = $this->cObj->stdWrap($value, $this->conf['userfields.'][$field . '.']);
00863             }
00864             // add ###USER### for compatibility
00865             $marker['###USER###'] = $marker['###FEUSER_USERNAME###'];
00866         }
00867         return $marker;
00868     }
00869 
00870     /**
00871      * Returns a valid and XSS cleaned url for redirect, checked against configuration "allowedRedirectHosts"
00872      *
00873      * @param string $url
00874      * @return string cleaned referer or empty string if not valid
00875      */
00876     protected function validateRedirectUrl($url) {
00877         $url = strval($url);
00878         if ($url === '') {
00879             return '';
00880         }
00881 
00882         $decodedUrl = rawurldecode($url);
00883         $sanitizedUrl = t3lib_div::removeXSS($decodedUrl);
00884 
00885         if ($decodedUrl !== $sanitizedUrl || preg_match('#["<>\\\]+#', $url)) {
00886             t3lib_div::sysLog(sprintf($this->pi_getLL('xssAttackDetected'), $url), 'felogin', t3lib_div::SYSLOG_SEVERITY_WARNING);
00887             return '';
00888         }
00889 
00890             // Validate the URL:
00891         if ($this->isRelativeUrl($url) || $this->isInCurrentDomain($url) || $this->isInLocalDomain($url)) {
00892             return $url;
00893         }
00894 
00895             // URL is not allowed
00896         t3lib_div::sysLog(sprintf($this->pi_getLL('noValidRedirectUrl'), $url), 'felogin', t3lib_div::SYSLOG_SEVERITY_WARNING);
00897         return '';
00898     }
00899 
00900     /**
00901      * Determines whether the URL is on the current host
00902      * and belongs to the current TYPO3 installation.
00903      *
00904      * @param string $url URL to be checked
00905      * @return boolean Whether the URL belongs to the current TYPO3 installation
00906      */
00907     protected function isInCurrentDomain($url) {
00908         return (t3lib_div::isOnCurrentHost($url) && t3lib_div::isFirstPartOfStr($url, t3lib_div::getIndpEnv('TYPO3_SITE_URL')));
00909     }
00910 
00911     /**
00912      * Determines whether the URL matches a domain
00913      * in the sys_domain databse table.
00914      *
00915      * @param string $url Absolute URL which needs to be checked
00916      * @return boolean Whether the URL is considered to be local
00917      */
00918     protected function isInLocalDomain($url) {
00919         $result = FALSE;
00920 
00921         if (t3lib_div::isValidUrl($url)) {
00922             $parsedUrl = parse_url($url);
00923             if ($parsedUrl['scheme'] === 'http' || $parsedUrl['scheme'] === 'https' ) {
00924                 $host = $parsedUrl['host'];
00925                     // Removes the last path segment and slash sequences like /// (if given):
00926                 $path = preg_replace('#/+[^/]*$#', '', $parsedUrl['path']);
00927 
00928                 $localDomains = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00929                     'domainName',
00930                     'sys_domain',
00931                     '1=1' . $this->cObj->enableFields('sys_domain')
00932                 );
00933                 if (is_array($localDomains)) {
00934                     foreach ($localDomains as $localDomain) {
00935                             // strip trailing slashes (if given)
00936                         $domainName = rtrim($localDomain['domainName'], '/');
00937                         if (t3lib_div::isFirstPartOfStr($host. $path . '/', $domainName . '/')) {
00938                             $result = TRUE;
00939                             break;
00940                         }
00941                     }
00942                 }
00943             }
00944         }
00945         return $result;
00946     }
00947 
00948     /**
00949      * Determines wether the URL is relative to the
00950      * current TYPO3 installation.
00951      *
00952      * @param string $url URL which needs to be checked
00953      * @return boolean Whether the URL is considered to be relative
00954      */
00955     protected function isRelativeUrl($url) {
00956         $parsedUrl = @parse_url($url);
00957         if ($parsedUrl !== FALSE && !isset($parsedUrl['scheme']) && !isset($parsedUrl['host'])) {
00958                 // If the relative URL starts with a slash, we need to check if it's within the current site path
00959             return (!t3lib_div::isFirstPartOfStr($parsedUrl['path'], '/') || t3lib_div::isFirstPartOfStr($parsedUrl['path'], t3lib_div::getIndpEnv('TYPO3_SITE_PATH')));
00960         }
00961         return FALSE;
00962     }
00963 }
00964 
00965 
00966 
00967 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/felogin/pi1/class.tx_felogin_pi1.php'])) {
00968     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/felogin/pi1/class.tx_felogin_pi1.php']);
00969 }
00970 
00971 ?>