Version 4.2.0
This commit is contained in:
1 parent
0dc2aee5ed
commit
96997ddd8e
2074 files changed
+125454
-55780
No files matched your search
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief AJAX actions
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 04 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -91,7 +90,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack( 'form_maxlength', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->max_user_name_length ) ) ) );
|
||||
}
|
||||
elseif ( \IPS\Settings::i()->username_characters and !preg_match( '/^[' . str_replace( '\-', '-', preg_quote( \IPS\Settings::i()->username_characters, '/' ) ) . ']*$/i', $name ) )
|
||||
elseif ( \IPS\Settings::i()->username_characters and !preg_match( '/^[' . str_replace( '\-', '-', preg_quote( \IPS\Settings::i()->username_characters, '/' ) ) . ']*$/iu', $name ) )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('form_bad_value') );
|
||||
}
|
||||
@@ -187,6 +186,26 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Check it's an allowed domain */
|
||||
if ( \IPS\Settings::i()->allowed_reg_email !== '' AND $allowedEmailDomains = explode( ',', \IPS\Settings::i()->allowed_reg_email ) )
|
||||
{
|
||||
$matched = FALSE;
|
||||
foreach ( $allowedEmailDomains AS $domain )
|
||||
{
|
||||
if( \mb_stripos( $email, "@" . $domain ) !== FALSE )
|
||||
{
|
||||
$matched = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $allowedEmailDomains ) AND !$matched )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => $email );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
\IPS\Output::i()->json( $result );
|
||||
}
|
||||
|
||||
@@ -378,4 +397,20 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->json( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show information about chart timezones
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function chartTimezones()
|
||||
{
|
||||
$mysqlTimezone = \IPS\Db::i()->query( "SELECT TIMEDIFF( NOW(), CONVERT_TZ( NOW(), @@session.time_zone, '+00:00' ) );" )->fetch_row()[0];
|
||||
if ( preg_match( '/^(-?)(\d{2}):00:00/', $mysqlTimezone, $matches ) )
|
||||
{
|
||||
$mysqlTimezone = "GMT" . ( ( $matches[2] == 0 ) ? '' : ( ( $matches[1] ?: '+' ) . intval( $matches[2] ) ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->chartTimezoneInfo( $mysqlTimezone );
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Announcement
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 09 Oct 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief My Attachments Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 22 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief "Content" functions Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 29 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Designer mode controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 07 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Editor AJAX functions Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 29 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -116,9 +115,9 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( \IPS\Request::i()->image )
|
||||
if ( \IPS\Request::i()->image and \IPS\Request::i()->width and \IPS\Request::i()->height )
|
||||
{
|
||||
$embed = \IPS\Text\Parser::_imageEmbed( $url, FALSE, TRUE );
|
||||
$embed = \IPS\Text\Parser::imageEmbed( $url, intval( \IPS\Request::i()->width ), intval( \IPS\Request::i()->height ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Embed iframe display
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 15 Sep 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -36,7 +35,7 @@ class _embed extends \IPS\Content\Controller
|
||||
{
|
||||
$return = \IPS\Data\Cache::i()->getWithExpire( $cacheKey, TRUE );
|
||||
}
|
||||
|
||||
|
||||
/* Not in cache - fetch */
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
@@ -48,13 +47,18 @@ class _embed extends \IPS\Content\Controller
|
||||
{
|
||||
$return = '';
|
||||
}
|
||||
|
||||
|
||||
/* And cache */
|
||||
\IPS\Data\Cache::i()->storeWithExpire( $cacheKey, $return, \IPS\DateTime::create()->add( new \DateInterval('P1D') ), TRUE );
|
||||
}
|
||||
|
||||
|
||||
/* Output */
|
||||
$js = \IPS\Output::i()->js( 'js/embedHandler.js', 'core', 'interface' );
|
||||
$js = array(
|
||||
\IPS\Output::i()->js( 'js/commonEmbedHandler.js', 'core', 'interface' ),
|
||||
\IPS\Output::i()->js( 'js/externalEmbedHandler.js', 'core', 'interface' )
|
||||
);
|
||||
/* Intentionally replace the cssFiles array with a single file here, since we don't need the complete CSS framework in external embeds */
|
||||
\IPS\Output::i()->cssFiles = \IPS\Theme::i()->css( 'styles/embeds.css', 'core', 'front' );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->embedExternal( $return, $js ), 200 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief My followed content
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 16 Apr 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Guidelines
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 02 Sept 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Ignore Preferences
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 20 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Language Changer
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 17 Dec 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Login
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 7 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -52,7 +51,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$member = $login->authenticate();
|
||||
if ( $member !== NULL )
|
||||
{
|
||||
$this->_doLogin( $member, $login->flags['signin_anonymous'], $login->flags['remember_me'], \IPS\Login::getDestination() );
|
||||
$this->_doLogin( $member, $login->flags['signin_anonymous'], $login->flags['remember_me'], \IPS\Login::getDestination(), FALSE, $login->usedHandler );
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
@@ -99,9 +98,10 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
* @param bool $rememberMe If the "remember me" checkbox was checked
|
||||
* @param \IPS\Http\Url $destination Where to redirect to
|
||||
* @param bool $bypass2FA If true, will not perform 2FA check
|
||||
* @param string $loginHandler Which login handler processed the login
|
||||
* @return void
|
||||
*/
|
||||
protected function _doLogin( $member, $anonymous=FALSE, $rememberMe=TRUE, $destination=NULL, $bypass2FA=FALSE )
|
||||
protected function _doLogin( $member, $anonymous=FALSE, $rememberMe=TRUE, $destination=NULL, $bypass2FA=FALSE, $loginHandler=NULL )
|
||||
{
|
||||
/* Get destination */
|
||||
if ( !$destination )
|
||||
@@ -109,36 +109,26 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
/* Is this a known device? */
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
|
||||
/* Do we need to do 2FA? */
|
||||
if ( !$bypass2FA and $output = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Http\Url::internal( '' ), $member ) )
|
||||
if ( !$bypass2FA and $output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', \IPS\Http\Url::internal( '' ), $member ) )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $member->member_id, 'anonymous' => $anonymous, 'remember' => $rememberMe, 'destination' => (string) $destination );
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $member->member_id, 'anonymous' => $anonymous, 'remember' => $rememberMe, 'destination' => (string) $destination, 'handler' => $loginHandler );
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
|
||||
/* Set anonymous cookie */
|
||||
|
||||
/* Log in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
if ( $anonymous and !\IPS\Settings::i()->disable_anonymous )
|
||||
{
|
||||
\IPS\Session::i()->setAnon();
|
||||
\IPS\Request::i()->setCookie( 'anon_login', 1 );
|
||||
}
|
||||
|
||||
/* Log in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
|
||||
/* Set remember me cookie */
|
||||
if ( $rememberMe )
|
||||
{
|
||||
$expire = new \IPS\DateTime;
|
||||
$expire->add( new \DateInterval( 'P3M' ) );
|
||||
\IPS\Request::i()->setCookie( 'member_id', $member->member_id, $expire );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', $member->member_login_key, $expire );
|
||||
|
||||
if ( $anonymous and !\IPS\Settings::i()->disable_anonymous )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'anon_login', 1, $expire );
|
||||
}
|
||||
}
|
||||
/* Log device */
|
||||
$device->anonymous = $anonymous and !\IPS\Settings::i()->disable_anonymous;
|
||||
$device->updateAfterAuthentication( $rememberMe, $loginHandler );
|
||||
|
||||
/* Member sync */
|
||||
$member->memberSync( 'onLogin', array( \IPS\Login::getDestination() ) );
|
||||
@@ -174,10 +164,11 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
/* Have we already done 2FA? */
|
||||
$output = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=mfa', 'front', 'login' ), $member );
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
$output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=mfa', 'front', 'login' ), $member );
|
||||
if ( !$output )
|
||||
{
|
||||
$this->_doLogin( $member, $_SESSION['processing2FA']['anonymous'], $_SESSION['processing2FA']['remember'], $destination, TRUE );
|
||||
$this->_doLogin( $member, $_SESSION['processing2FA']['anonymous'], $_SESSION['processing2FA']['remember'], $destination, TRUE, $_SESSION['processing2FA']['handler'] );
|
||||
}
|
||||
|
||||
/* Nope, just send us where we want to go not logged in */
|
||||
@@ -249,7 +240,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
$this->_doLogin( $member, FALSE, TRUE, $destination );
|
||||
$this->_doLogin( $member, FALSE, TRUE, $destination, FALSE, $details['handler'] );
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
@@ -270,8 +261,12 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function logout()
|
||||
{
|
||||
$member = \IPS\Member::loggedIn();
|
||||
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Work out where we will be going after log out */
|
||||
if( !empty( $_SERVER['HTTP_REFERER'] ) )
|
||||
{
|
||||
$referrer = \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] );
|
||||
@@ -281,8 +276,6 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$redirectUrl = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
$member = \IPS\Member::loggedIn();
|
||||
|
||||
/* Are we logging out back to an admin user? */
|
||||
if( isset( $_SESSION['logged_in_as_key'] ) )
|
||||
@@ -295,28 +288,25 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
|
||||
\IPS\Request::i()->setCookie( 'member_id', NULL );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', NULL );
|
||||
\IPS\Request::i()->setCookie( 'anon_login', NULL );
|
||||
|
||||
foreach( \IPS\Request::i()->cookie as $name => $value )
|
||||
/* Do not allow the login_key to be re-used */
|
||||
if ( isset( \IPS\Request::i()->cookie['device_key'] ) )
|
||||
{
|
||||
if( mb_strpos( $name, "ipbforumpass_" ) !== FALSE )
|
||||
try
|
||||
{
|
||||
\IPS\Request::i()->setCookie( $name, NULL );
|
||||
$device = \IPS\Member\Device::loadAndAuthenticate( \IPS\Request::i()->cookie['device_key'], $member );
|
||||
$device->login_key = NULL;
|
||||
$device->save();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
/* Clear cookies */
|
||||
\IPS\Request::i()->clearLoginCookies();
|
||||
|
||||
/* Reset session global parameters */
|
||||
$_SESSION = array();
|
||||
|
||||
/* We have to explicitly reset the session cookie
|
||||
@link http://php.net/manual/en/function.session-destroy.php */
|
||||
/* Destroy the session (we have to explicitly reset the session cookie, see http://php.net/manual/en/function.session-destroy.php) */
|
||||
$_SESSION = array();
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
setcookie( session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] );
|
||||
|
||||
/* Then destroy the session itself */
|
||||
session_destroy();
|
||||
|
||||
/* Login handler callback */
|
||||
@@ -332,6 +322,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/* Member sync callback */
|
||||
$member->memberSync( 'onLogout', array( $redirectUrl ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $redirectUrl->setQueryString( '_fromLogout', 1 ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Lost Password
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 26 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -147,11 +146,15 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
catch( \BadMethodCallException $e ){}
|
||||
}
|
||||
|
||||
/* Log in, and invalidate all other sessions */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
$member->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( isset( \IPS\Request::i()->cookie['login_key'] ), '' );
|
||||
|
||||
/* Delete validating record and log in */
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) );
|
||||
|
||||
/* Log in and redirect */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Mark site as read
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 19 May 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Live meta tag editor
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 4 Sept 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Moderation
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 23 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Notification Settings Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 27 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -435,7 +434,6 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
/* Display */
|
||||
$output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'system', 'core' ) ), 'followForm' ) );
|
||||
|
||||
/* @see http://community.invisionpower.com/4bugtrack/follow-button-adds-meta-title-and-link-tags-r3209/ */
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief A deliberately empty controller intended for use by plugins which need to add small actions
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 09 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Poll View Voters Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 13 Jan 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Privacy Policy
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 28 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief External redirector with key checks
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 12 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -138,8 +137,6 @@ class _redirect extends \IPS\Dispatcher\Controller
|
||||
if( $advertisement->maximum_unit == 'c' AND $advertisement->maximum_value > -1 AND $advertisement->clicks + 1 >= $advertisement->maximum_value )
|
||||
{
|
||||
$update .= ", ad_active=0";
|
||||
|
||||
unset( \IPS\Data\Cache::i()->advertisements );
|
||||
}
|
||||
|
||||
/* Update the database */
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Register
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 3 July 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -58,7 +57,31 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->showOffline();
|
||||
}
|
||||
|
||||
if( isset( $_SESSION['coppa_user'] ) )
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=register', NULL, 'register' ), array(), 'loc_registering' );
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
|
||||
/* Quick registration does not work with COPPA */
|
||||
if ( \IPS\Settings::i()->quick_register )
|
||||
{
|
||||
$form = $this->_registrationForm();
|
||||
$form->class = 'ipsForm_fullWidth';
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('registration');
|
||||
|
||||
if( (string) \IPS\Request::i()->url() == (string) \IPS\Http\Url::internal( 'app=core&module=system&controller=register', NULL, 'register' ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( isset( $_SESSION['coppa_user'] ) AND ( \IPS\Settings::i()->use_coppa OR \IPS\Settings::i()->minimum_age > 0 ) )
|
||||
{
|
||||
if ( \IPS\Settings::i()->minimum_age > 0 )
|
||||
{
|
||||
@@ -112,14 +135,30 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
$steps['basic_info'] = function ( $data ) use ( $self )
|
||||
{
|
||||
$form = \IPS\core\modules\front\system\register::buildRegistrationForm();
|
||||
$form = $this->_registrationForm();
|
||||
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form, new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
};
|
||||
|
||||
/* Output */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('registration');
|
||||
\IPS\Output::i()->output = (string) new \IPS\Helpers\Wizard( $steps, \IPS\Http\Url::internal( 'app=core&module=system&controller=register' ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal registration form
|
||||
*
|
||||
* @return \IPS\Form
|
||||
*/
|
||||
protected function _registrationForm()
|
||||
{
|
||||
$form = \IPS\core\modules\front\system\register::buildRegistrationForm();
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if( !\IPS\Settings::i()->quick_register )
|
||||
{
|
||||
/* Custom Fields */
|
||||
$profileFields = array();
|
||||
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $id => $field )
|
||||
@@ -133,63 +172,111 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $fields instanceof \IPS\Helpers\Form\Editor )
|
||||
{
|
||||
$field->claimAttachments( $self->id );
|
||||
$field->claimAttachments( $this->id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and ( \IPS\Settings::i()->security_questions_prompt === 'register' or ( \IPS\Settings::i()->security_questions_prompt === 'optional' and !$values['security_questions_optout_title'] ) ) )
|
||||
{
|
||||
$answers = array();
|
||||
foreach ( $values as $k => $v )
|
||||
{
|
||||
if ( preg_match( '/^security_question_q_(\d+)$/', $k, $matches ) )
|
||||
{
|
||||
if ( isset( $answers[ $v ] ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'security_questions_unique', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->security_questions_number ?: 3 ) ) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$answers[ $v ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$form->error )
|
||||
{
|
||||
/* Create Member */
|
||||
$member = \IPS\core\modules\front\system\register::_createMember( $values, $profileFields );
|
||||
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
|
||||
$redirectUrl = \IPS\Login::getRegistrationDestination( $member );
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $redirectUrl ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$profileFields = array();
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and ( \IPS\Settings::i()->security_questions_prompt === 'register' or ( \IPS\Settings::i()->security_questions_prompt === 'optional' and !$values['security_questions_optout_title'] ) ) )
|
||||
{
|
||||
$answers = array();
|
||||
foreach ( $values as $k => $v )
|
||||
{
|
||||
if ( preg_match( '/^security_question_q_(\d+)$/', $k, $matches ) )
|
||||
{
|
||||
if ( isset( $answers[ $v ] ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'security_questions_unique', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->security_questions_number ?: 3 ) ) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$answers[ $v ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$form->error )
|
||||
{
|
||||
/* Create Member */
|
||||
$member = \IPS\core\modules\front\system\register::_createMember( $values, $profileFields );
|
||||
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form, new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
};
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Member\Device::loadOrCreate( $member, FALSE )->updateAfterAuthentication( TRUE, '' );
|
||||
|
||||
$redirectUrl = \IPS\Login::getRegistrationDestination( $member );
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $redirectUrl ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=register', NULL, 'register' ), array(), 'loc_registering' );
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('registration');
|
||||
\IPS\Output::i()->output = (string) new \IPS\Helpers\Wizard( $steps, \IPS\Http\Url::internal( 'app=core&module=system&controller=register' ), FALSE );
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function finish()
|
||||
{
|
||||
$steps = \IPS\Member\ProfileStep::loadAll();
|
||||
|
||||
/* Do we need to bother? We should only show this form if there are required items, but will show both required and suggested where possible to allow the user to complete as much of their profile as possible */
|
||||
$haveRequired = FALSE;
|
||||
foreach( $steps AS $id => $step )
|
||||
{
|
||||
if ( $step->required )
|
||||
{
|
||||
$haveRequired = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $haveRequired === FALSE )
|
||||
{
|
||||
/* Nope, forward */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
|
||||
$wizardSteps = array();
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=finish', 'front', 'register' );
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'ProfileSteps' ) AS $extension )
|
||||
{
|
||||
if ( method_exists( $extension, 'wizard') AND count( $extension::wizard() ) )
|
||||
{
|
||||
$wizardSteps = array_merge( $wizardSteps, $extension::wizard() );
|
||||
}
|
||||
}
|
||||
|
||||
$wizardSteps = array_merge( $wizardSteps, array( 'profile_done' => function( $data ) {
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'saved' );
|
||||
} ) );
|
||||
|
||||
$wizard = new \IPS\Helpers\Wizard( $wizardSteps, $url, TRUE, NULL, TRUE );
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/settings.css' ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('complete_profile_registration');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->finishRegistration( $wizard );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Registration Form
|
||||
*
|
||||
@@ -205,14 +292,21 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password' ) ) );
|
||||
|
||||
/* Profile fields */
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
if ( ! \IPS\Settings::i()->quick_register )
|
||||
{
|
||||
foreach ( $fields as $field )
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
$form->add( $field );
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
$form->add( $field );
|
||||
}
|
||||
}
|
||||
$form->addSeparator();
|
||||
}
|
||||
else
|
||||
{
|
||||
$form->class = 'ipsForm_vertical';
|
||||
}
|
||||
$form->addSeparator();
|
||||
|
||||
$question = FALSE;
|
||||
try
|
||||
@@ -221,53 +315,8 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
{
|
||||
$numberOfQuestions = \IPS\Settings::i()->security_questions_number ?: 3;
|
||||
$securityQuestions = array();
|
||||
foreach ( \IPS\MFA\SecurityQuestions\Question::roots() as $securityQuestion )
|
||||
{
|
||||
$securityQuestions[ $securityQuestion->id ] = $securityQuestion->_title;
|
||||
}
|
||||
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('security_questions_setup_blurb', FALSE, array( 'pluralize' => array( $numberOfQuestions ) ) ) );
|
||||
if ( \IPS\Settings::i()->security_questions_prompt === 'optional' )
|
||||
{
|
||||
$securityOptoutToggles = array();
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityOptoutToggles[] = 'security_question_q_' . $i;
|
||||
$securityOptoutToggles[] = 'security_question_a_' . $i;
|
||||
}
|
||||
|
||||
$optOutCheckbox = new \IPS\Helpers\Form\Checkbox( 'security_questions_optout_title', FALSE, FALSE, array( 'togglesOff' => $securityOptoutToggles ) );
|
||||
if ( \IPS\Member::loggedIn()->language()->checkKeyExists('security_questions_opt_out_warning_value') )
|
||||
{
|
||||
$optOutCheckbox->description = \IPS\Member::loggedIn()->language()->addToStack('security_questions_opt_out_warning_value');
|
||||
}
|
||||
$form->add( $optOutCheckbox );
|
||||
}
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityValidation = function( $val ) {
|
||||
if ( !$val and ( \IPS\Settings::i()->security_questions_prompt === 'register' or !isset( \IPS\Request::i()->security_questions_optout_title_checkbox ) ) )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
};
|
||||
|
||||
$questionField = new \IPS\Helpers\Form\Select( 'security_question_q_' . $i, NULL, FALSE, array( 'options' => $securityQuestions ), $securityValidation, NULL, NULL, 'security_question_q_' . $i );
|
||||
$questionField->label = \IPS\Member::loggedIn()->language()->addToStack('security_question_q');
|
||||
|
||||
$answerField = new \IPS\Helpers\Form\Text( 'security_question_a_' . $i, NULL, NULL, array(), $securityValidation, NULL, NULL, 'security_question_a_' . $i );
|
||||
$answerField->label = \IPS\Member::loggedIn()->language()->addToStack('security_question_a');
|
||||
|
||||
$form->add( $questionField );
|
||||
$form->add( $answerField );
|
||||
}
|
||||
$form->addSeparator();
|
||||
}
|
||||
/* 2FA Q&A? */
|
||||
static::addQuestion2FA( $form );
|
||||
|
||||
/* Random Q&A */
|
||||
if( $question )
|
||||
@@ -354,15 +403,74 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
} ) );
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_system.js', 'core', 'front' ), \IPS\Output::i()->js( 'front_templates.js', 'core', 'front' ) );
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add in the Q&A 2FA if it is enforced
|
||||
*
|
||||
* @param \IPS\Form $form Form
|
||||
* @return void
|
||||
*/
|
||||
protected static function addQuestion2FA( &$form )
|
||||
{
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
{
|
||||
$numberOfQuestions = \IPS\Settings::i()->security_questions_number ?: 3;
|
||||
$securityQuestions = array();
|
||||
foreach ( \IPS\MFA\SecurityQuestions\Question::roots() as $securityQuestion )
|
||||
{
|
||||
$securityQuestions[ $securityQuestion->id ] = $securityQuestion->_title;
|
||||
}
|
||||
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('security_questions_setup_blurb', FALSE, array( 'pluralize' => array( $numberOfQuestions ) ) ) );
|
||||
|
||||
if ( \IPS\Settings::i()->security_questions_prompt === 'optional' )
|
||||
{
|
||||
$securityOptoutToggles = array();
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityOptoutToggles[] = 'security_question_q_' . $i;
|
||||
$securityOptoutToggles[] = 'security_question_a_' . $i;
|
||||
}
|
||||
|
||||
$optOutCheckbox = new \IPS\Helpers\Form\Checkbox( 'security_questions_optout_title', FALSE, FALSE, array( 'togglesOff' => $securityOptoutToggles ) );
|
||||
if ( \IPS\Member::loggedIn()->language()->checkKeyExists('security_questions_opt_out_warning_value') )
|
||||
{
|
||||
$optOutCheckbox->description = \IPS\Member::loggedIn()->language()->addToStack('security_questions_opt_out_warning_value', TRUE, array( 'returnBlank' => TRUE ) );
|
||||
}
|
||||
$form->add( $optOutCheckbox );
|
||||
}
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityValidation = function( $val ) {
|
||||
if ( !$val and ( \IPS\Settings::i()->security_questions_prompt === 'register' or !isset( \IPS\Request::i()->security_questions_optout_title_checkbox ) ) )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
};
|
||||
|
||||
$questionField = new \IPS\Helpers\Form\Select( 'security_question_q_' . $i, NULL, FALSE, array( 'options' => $securityQuestions ), $securityValidation, NULL, NULL, 'security_question_q_' . $i );
|
||||
$questionField->label = \IPS\Member::loggedIn()->language()->addToStack('security_question_q');
|
||||
|
||||
$answerField = new \IPS\Helpers\Form\Text( 'security_question_a_' . $i, NULL, NULL, array(), $securityValidation, NULL, NULL, 'security_question_a_' . $i );
|
||||
$answerField->label = \IPS\Member::loggedIn()->language()->addToStack('security_question_a');
|
||||
|
||||
$form->add( $questionField );
|
||||
$form->add( $answerField );
|
||||
}
|
||||
$form->addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Member
|
||||
*
|
||||
* @param array $values Values from form
|
||||
* @param array $profileFields Profile field values from registration
|
||||
* @return \IPS\Member
|
||||
* @param array $values Values from form
|
||||
* @param array $profileFields Profile field values from registration
|
||||
* @return \IPS\Member
|
||||
*/
|
||||
public static function _createMember( $values, $profileFields )
|
||||
{
|
||||
@@ -385,15 +493,28 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Save */
|
||||
/* Initial Save */
|
||||
$member->save();
|
||||
|
||||
/* This looks a bit weird, but the extensions expect an account to exist at this point, so we'll let the system save it now, then do what we need to do, then save again */
|
||||
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
|
||||
{
|
||||
$extension = $step->extension;
|
||||
$extension::formatFormValues( $values, $member, $form );
|
||||
}
|
||||
|
||||
/* Save anything the profile extensions did */
|
||||
$member->save();
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
{
|
||||
if ( $values['security_questions_optout_title'] )
|
||||
if ( isset( $values['security_questions_optout_title'] ) )
|
||||
{
|
||||
$member->members_bitoptions['security_questions_opt_out'] = TRUE;
|
||||
|
||||
/* Log MFA Opt-out */
|
||||
$member->logHistory( 'core', 'mfa', array( 'handler' => 'questions', 'enable' => FALSE, 'optout' => TRUE ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -417,12 +538,18 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$member->members_bitoptions['has_security_answers'] = TRUE;
|
||||
|
||||
/* Log MFA Enable */
|
||||
$member->logHistory( 'core', 'mfa', array( 'handler' => 'questions', 'enable' => TRUE ) );
|
||||
}
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* Save custom field values */
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
if ( ! \IPS\Settings::i()->quick_register )
|
||||
{
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
}
|
||||
|
||||
/* Handle validation */
|
||||
$member->postRegistration();
|
||||
@@ -548,6 +675,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Log in and Redirect */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( TRUE );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'validate_email_confirmation' );
|
||||
}
|
||||
}
|
||||
@@ -678,6 +806,13 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
/* Invalidate sessions except this one */
|
||||
\IPS\Member::loggedIn()->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
if( isset( \IPS\Request::i()->cookie['login_key'] ) )
|
||||
{
|
||||
\IPS\Member\Device::loadOrCreate( \IPS\Member::loggedIn() )->updateAfterAuthentication( TRUE );
|
||||
}
|
||||
|
||||
/* If email validation is required, do that... */
|
||||
if ( in_array( \IPS\Settings::i()->reg_auth_type, array( 'user', 'admin_user' ) ) )
|
||||
{
|
||||
@@ -728,17 +863,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Request::i()->confirmedDelete( 'reg_cancel', 'reg_cancel_confirm', 'reg_cancel' );
|
||||
|
||||
/* Log the user out. Previously, we immediately deleted the account however this has been changed to let the cleanup task handle this instead. */
|
||||
\IPS\Request::i()->setCookie( 'member_id', NULL );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', NULL );
|
||||
\IPS\Request::i()->setCookie( 'anon_login', NULL );
|
||||
|
||||
foreach( \IPS\Request::i()->cookie as $name => $value )
|
||||
{
|
||||
if( mb_strpos( $name, "ipbforumpass_" ) !== FALSE )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( $name, NULL );
|
||||
}
|
||||
}
|
||||
\IPS\Request::i()->clearLoginCookies();
|
||||
|
||||
/* Reset session global parameters */
|
||||
$_SESSION = array();
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief User CP Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 10 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -144,8 +143,21 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$services[$key] = new $class( \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
$nextStep = NULL;
|
||||
if ( $completed = \IPS\Member::loggedIn()->profileCompletion() AND count( $completed['suggested'] ) )
|
||||
{
|
||||
foreach( $completed['suggested'] AS $id => $complete )
|
||||
{
|
||||
if ( !$complete )
|
||||
{
|
||||
$nextStep = \IPS\Member\ProfileStep::load( $id );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsOverview( $services );
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsOverview( $services, $nextStep );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,17 +181,7 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
\IPS\Output::i()->output = $mfaOutput;
|
||||
}
|
||||
|
||||
/* Do we have any pending validation emails? */
|
||||
try
|
||||
{
|
||||
$pending = \IPS\Db::i()->select( '*', 'core_validating', array( 'member_id=? AND email_chg=1', \IPS\Member::loggedIn()->member_id ), 'entry_date DESC' )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$pending = null;
|
||||
}
|
||||
|
||||
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
@@ -202,12 +204,16 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
}
|
||||
|
||||
/* Invalidate sessions except this one */
|
||||
\IPS\Member::loggedIn()->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
if( isset( \IPS\Request::i()->cookie['login_key'] ) )
|
||||
{
|
||||
\IPS\Member\Device::loadOrCreate( \IPS\Member::loggedIn() )->updateAfterAuthentication( TRUE );
|
||||
}
|
||||
|
||||
/* Delete any pending validation emails */
|
||||
if ( $pending['vid'] )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND email_chg=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND email_chg=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
/* Send a validation email if we need to */
|
||||
if ( \IPS\Settings::i()->reg_auth_type == 'user' or \IPS\Settings::i()->reg_auth_type == 'admin_user' )
|
||||
@@ -285,12 +291,11 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
catch( \BadMethodCallException $e ){}
|
||||
}
|
||||
|
||||
/* If we have a pass_hash cookie, update it so we stay logged in on the next page load */
|
||||
if( isset( \IPS\Request::i()->cookie['pass_hash'] ) )
|
||||
/* Invalidate sessions except this one */
|
||||
\IPS\Member::loggedIn()->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
if( isset( \IPS\Request::i()->cookie['login_key'] ) )
|
||||
{
|
||||
$expire = new \IPS\DateTime;
|
||||
$expire->add( new \DateInterval( 'P3M' ) );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', \IPS\Member::loggedIn()->member_login_key, $expire );
|
||||
\IPS\Member\Device::loadOrCreate( \IPS\Member::loggedIn() )->updateAfterAuthentication( TRUE );
|
||||
}
|
||||
|
||||
/* Send a confirmation email */
|
||||
@@ -301,6 +306,128 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsPassword( $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* Devices
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _devices()
|
||||
{
|
||||
$mfaOutput = \IPS\MFA\MFAHandler::accessToArea( 'core', 'DeviceManagement', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=devices', 'front', 'settings_devices' ) );
|
||||
if ( $mfaOutput )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=devices', 'front', 'settings_devices' ) );
|
||||
}
|
||||
\IPS\Output::i()->output = $mfaOutput;
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsDevices( array(), array() );
|
||||
}
|
||||
|
||||
$devices = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members_known_devices', array( 'member_id=? AND last_seen>?', \IPS\Member::loggedIn()->member_id, ( new \DateTime )->sub( new \DateInterval( \IPS\Member\Device::LOGIN_KEY_VALIDITY ) )->getTimestamp() ), 'last_seen DESC' ), 'IPS\Member\Device' );
|
||||
|
||||
$locations = array();
|
||||
$ipAddresses = array();
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members_known_ip_addresses', array( 'member_id=?', \IPS\Member::loggedIn()->member_id ), 'last_seen DESC' ) as $log )
|
||||
{
|
||||
if ( \IPS\Settings::i()->ipsgeoip )
|
||||
{
|
||||
if ( !array_key_exists( $log['ip_address'], $locations ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$locations[ $log['ip_address'] ] = \IPS\GeoLocation::getByIp( $log['ip_address'] );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$locations[ $log['ip_address'] ] = \IPS\Member::loggedIn()->language()->addToStack('unknown');
|
||||
}
|
||||
}
|
||||
|
||||
$ipAddresses[ $log['device_key'] ][ $log['ip_address'] ] = array(
|
||||
'location' => $locations[ $log['ip_address'] ],
|
||||
'date' => $log['last_seen']
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ipAddresses[ $log['device_key'] ][ $log['ip_address'] ] = array(
|
||||
'date' => $log['last_seen']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsDevices( $devices, $ipAddresses );
|
||||
}
|
||||
|
||||
/**
|
||||
* Secure Account
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function secureAccount()
|
||||
{
|
||||
/* Only logged in members */
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2C122/Q', 403, '' );
|
||||
}
|
||||
|
||||
$canChangePassword = FALSE;
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $k => $handler )
|
||||
{
|
||||
if ( $handler->canChange( 'password', \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$canChangePassword = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
$canConfigureMfa = FALSE;
|
||||
$hasConfiguredMfa = FALSE;
|
||||
foreach ( \IPS\MFA\MFAHandler::handlers() as $handler )
|
||||
{
|
||||
if ( $handler->isEnabled() and $handler->memberCanUseHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$canConfigureMfa = TRUE;
|
||||
|
||||
if ( $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$hasConfiguredMfa = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$services = \IPS\core\ProfileSync\ProfileSyncAbstract::services();
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'secure_account' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings', 'front', 'settings' ), \IPS\Member::loggedIn()->language()->addToStack('settings') );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('secure_account') );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->settingsSecureAccount( $canChangePassword, $canConfigureMfa, $hasConfiguredMfa, $services );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Automatic Login
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function disableAutomaticLogin()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$device = \IPS\Member\Device::loadAndAuthenticate( \IPS\Request::i()->device, \IPS\Member::loggedIn() );
|
||||
$device->login_key = NULL;
|
||||
$device->save();
|
||||
|
||||
\IPS\Db::i()->delete( 'core_sessions', array( 'member_id=? AND browser=? AND id<>?', $device->member_id, $device->user_agent, \IPS\Session::i()->id ) );
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=devices', 'front', 'settings_devices' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* MFA
|
||||
@@ -376,6 +503,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( isset( \IPS\Request::i()->mfa_setup ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
foreach ( $handlers as $key => $handler )
|
||||
{
|
||||
if ( ( count( $handlers ) == 1 ) or $key == \IPS\Request::i()->mfa_method )
|
||||
@@ -399,6 +528,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( isset( \IPS\Request::i()->_mfa ) and \IPS\Request::i()->_mfa == 'optout' )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] = TRUE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
@@ -416,6 +547,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function enableMfa()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Get the handler */
|
||||
$handlers = \IPS\MFA\MFAHandler::handlers();
|
||||
$key = \IPS\Request::i()->type;
|
||||
@@ -433,6 +566,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
/* Did we just submit it? */
|
||||
if ( isset( \IPS\Request::i()->mfa_setup ) and $handlers[ $key ]->configurationScreenSubmit( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$_SESSION['MFAAuthenticated'] = time();
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
@@ -451,6 +586,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function disableMfa()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Get the handler */
|
||||
$handlers = \IPS\MFA\MFAHandler::handlers();
|
||||
$key = \IPS\Request::i()->type;
|
||||
@@ -572,13 +709,13 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$member = \IPS\Member::loggedIn();
|
||||
}
|
||||
|
||||
|
||||
/* Can we use this? */
|
||||
if ( !$member->member_id or !( ( $member->failed_mfa_attempts >= \IPS\Settings::i()->security_questions_tries and \IPS\Settings::i()->mfa_lockout_behaviour == 'email' ) or in_array( 'email', explode( ',', \IPS\Settings::i()->mfa_forgot_behaviour ) ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C122/L', 403, '' );
|
||||
}
|
||||
|
||||
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
try
|
||||
@@ -703,9 +840,11 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* How many changes */
|
||||
$nameCount = \IPS\Db::i()->select( 'COUNT(*) as count, MIN(dname_date) as min_date', 'core_dnames_change', array(
|
||||
'dname_member_id=? AND dname_date>?',
|
||||
$nameCount = \IPS\Db::i()->select( 'COUNT(*) as count, MIN(log_date) as min_date', 'core_member_history', array(
|
||||
'log_member=? AND log_app=? AND log_type=? AND log_date>?',
|
||||
\IPS\Member::loggedIn()->member_id,
|
||||
'core',
|
||||
'display_name',
|
||||
\IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Member::loggedIn()->group['g_dname_date'] . 'D' ) )->getTimestamp()
|
||||
) )->first();
|
||||
|
||||
@@ -854,8 +993,22 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$src = $image->getAttribute('src');
|
||||
\IPS\Output::i()->parseFileObjectUrls( $src );
|
||||
|
||||
$imageProperties = @getimagesize( $src );
|
||||
|
||||
/* If we do not have any properties - remote fetch, and then check against the actual content as a fallback. We do this as a fallback as it can be slower. */
|
||||
if ( !$imageProperties )
|
||||
{
|
||||
try
|
||||
{
|
||||
$imageContent = \IPS\Http\Url::external( $src )->request()->get();
|
||||
$imageProperties = @getimagesizefromstring( (string) $imageContent );
|
||||
}
|
||||
catch( \IPS\Http\Request\Exception $e ) { }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$src = (string) \IPS\File::get( 'core_Attachment', $attachment['attach_location'] )->url;
|
||||
}
|
||||
|
||||
if( is_array( $imageProperties ) AND count( $imageProperties ) )
|
||||
@@ -981,8 +1134,21 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
$obj->save( $values );
|
||||
}
|
||||
|
||||
|
||||
$permissionRequest = 'permissionRequest_' . $service;
|
||||
$extraPermissions = NULL;
|
||||
$extraPermissionsButton = NULL;
|
||||
if ( isset( \IPS\Request::i()->$permissionRequest ) )
|
||||
{
|
||||
$login = \IPS\Login\LoginAbstract::load( $class::$loginKey );
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system&controller=settings&area=profilesync&service={$service}", 'front', "settings_{$service}" );
|
||||
|
||||
$extraPermissions = \IPS\Request::i()->$permissionRequest;
|
||||
$extraPermissionsButton = $login->loginForm( $url, TRUE );
|
||||
}
|
||||
|
||||
$photo = ( method_exists( $obj, 'photo' ) ) ? $obj->photo() : NULL;
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsProfileSync( $photo instanceof \IPS\File ? $photo->url : $photo, $headline, method_exists( $obj, 'status' ) ? $obj->status() : NULL, $form, $service, "profilesync__{$service}", ( $settings['photo'] or $settings['cover'] or $settings['status'] ) );
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsProfileSync( $photo instanceof \IPS\File ? $photo->url : $photo, $headline, method_exists( $obj, 'status' ) ? $obj->status() : NULL, $form, $service, "profilesync__{$service}", ( $settings['photo'] or $settings['cover'] or $settings['status'] ), $extraPermissions, $extraPermissionsButton );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1036,4 +1202,59 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
$redirectUrl = ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( "app=core&module=system&controller=settings", 'front', 'settings' );
|
||||
\IPS\Output::i()->redirect( $redirectUrl, 'signature_pref_toggled' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss Profile Completion
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function dismissProfile()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['profile_completion_dismissed'] = TRUE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$redirectUrl = ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( "app=core&module=system&controller=settings", 'front', 'settings' );
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completion Wizard
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function completion()
|
||||
{
|
||||
$steps = array();
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&do=completion', 'front', 'settings' );
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'ProfileSteps' ) AS $extension )
|
||||
{
|
||||
if ( method_exists( $extension, 'wizard') AND count( $extension::wizard() ) )
|
||||
{
|
||||
$steps = array_merge( $steps, $extension::wizard() );
|
||||
}
|
||||
}
|
||||
|
||||
$steps = array_merge( $steps, array( 'profile_done' => function( $data ) {
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=settings", 'front', 'settings' ), 'saved' );
|
||||
} ) );
|
||||
|
||||
$wizard = new \IPS\Helpers\Wizard( $steps, $url, TRUE, NULL, TRUE );
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/settings.css' ) );
|
||||
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'complete_your_profile' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->completeWizard( $wizard );
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Splash Controller
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 21 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Terms of Use
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 25 Sept 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Theme Changer
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 17 Dec 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Twitter Authentication
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 24 February 2017
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Twitter auth for ACP
|
||||
*/
|
||||
class _twitter extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* View Announcement
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
if ( ! \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) ) );
|
||||
}
|
||||
|
||||
$twitter = \IPS\Login::getHandler('Twitter');
|
||||
$promote = \IPS\core\Promote::getPromoter( 'Twitter' );
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' );
|
||||
|
||||
try
|
||||
{
|
||||
/* Get a request token */
|
||||
if ( !isset( \IPS\Request::i()->oauth_token ) )
|
||||
{
|
||||
$callback = $url->setQueryString( 'csrf', \IPS\Session::i()->csrfKey );
|
||||
$response = $twitter->sendRequest( 'get', 'https://api.twitter.com/oauth/request_token', array( 'oauth_callback' => (string) $callback ) )->decodeQueryString('oauth_token');
|
||||
\IPS\Output::i()->redirect( "https://api.twitter.com/oauth/authorize?force_login=1&oauth_token={$response['oauth_token']}" );
|
||||
}
|
||||
|
||||
/* CSRF Check */
|
||||
if ( \IPS\Request::i()->csrf !== \IPS\Session::i()->csrfKey )
|
||||
{
|
||||
throw new \IPS\Login\Exception( 'CSRF_FAIL', \IPS\Login\Exception::INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
/* Authenticate */
|
||||
$response = $twitter->sendRequest( 'post', 'https://api.twitter.com/oauth/access_token', array( 'oauth_verifier' => \IPS\Request::i()->oauth_verifier ), \IPS\Request::i()->oauth_token )->decodeQueryString('user_id');
|
||||
|
||||
$user = $twitter->sendRequest( 'get', 'https://api.twitter.com/1.1/account/verify_credentials.json', array(), $response['oauth_token'], $response['oauth_token_secret'] )->decodeJson();
|
||||
|
||||
/* Store the settings */
|
||||
$promote->saveSettings( array(
|
||||
'id' => $response['user_id'],
|
||||
'owner' => \IPS\Member::loggedIn()->member_id,
|
||||
'secret' => $response['oauth_token_secret'],
|
||||
'token' => $response['oauth_token'],
|
||||
'name' => $user['screen_name']
|
||||
) );
|
||||
|
||||
/* Show a done page */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('promote_twitter_sorted');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteTwitterComplete( $user );
|
||||
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Allow users to unsubscribe from site updates
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 12 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Visual Language Editor
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 27 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Visual Theme Editor
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 7 Nov 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -98,7 +97,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
$form = new \IPS\Helpers\Form( 'form', NULL );
|
||||
$settings = $theme->getThemeSettings();
|
||||
$settingKeyValues = array();
|
||||
|
||||
|
||||
foreach( $settings as $key => $data )
|
||||
{
|
||||
$settingKeyValues[ $key ] = $data['_value'];
|
||||
@@ -121,7 +120,17 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
// No break
|
||||
case 'Radio':
|
||||
$content = json_decode( $data['sc_content'], TRUE );
|
||||
$options['options'] = ( is_array( $content ) ) ? $content : array();
|
||||
|
||||
$options = array();
|
||||
if( is_array( $content ) )
|
||||
{
|
||||
foreach( $content as $_content )
|
||||
{
|
||||
$options[ $_content['key'] ] = $_content['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$options['options'] = $options;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Member Warnings
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 18 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Sidebar Widgets
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 19 Nov 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
@@ -155,10 +154,11 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
|
||||
try
|
||||
{
|
||||
$blocks = \IPS\Db::i()->select( '*', 'core_widget_areas', array( 'app=? AND module=? AND controller=? AND area=?', \IPS\Request::i()->pageApp, \IPS\Request::i()->pageModule, \IPS\Request::i()->pageController, \IPS\Request::i()->pageArea ) )->first();
|
||||
$blocks = json_decode( $blocks['widgets'], TRUE );
|
||||
$where = ( $key[0] ) == 'app' ? '`key`=? AND `app`=?' : '`key`=? AND `plugin`=?';
|
||||
$widgetMaster = \IPS\Db::i()->select( '*', 'core_widgets', array( $where, $key[2], $key[1] ) )->first();
|
||||
|
||||
$blocks = \IPS\Db::i()->select( '*', 'core_widget_areas', array( 'app=? AND module=? AND controller=? AND area=?', \IPS\Request::i()->pageApp, \IPS\Request::i()->pageModule, \IPS\Request::i()->pageController, \IPS\Request::i()->pageArea ) )->first();
|
||||
$blocks = json_decode( $blocks['widgets'], TRUE );
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
@@ -219,7 +219,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
\IPS\Db::i()->insert( 'core_widget_areas', array( 'app' => \IPS\Request::i()->pageApp, 'module' => \IPS\Request::i()->pageModule, 'controller' => \IPS\Request::i()->pageController, 'area' => \IPS\Request::i()->pageArea, 'widgets' => json_encode( $blocks ) ), TRUE );
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
\IPS\Output::i()->sendOutput( $widget->configuration()->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'widgets', 'core' ) ), 'formTemplate' ), $widget ) );
|
||||
\IPS\Output::i()->output = $widget->configuration()->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'widgets', 'core' ) ), 'formTemplate' ), $widget );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user