Version 4.7.0
This commit is contained in:
1 parent
517a5e1f70
commit
8ba7d43898
1933 files changed
+65613
-11332
No files matched your search
@@ -656,15 +656,58 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Return current CSRF token
|
||||
*
|
||||
* @return string|null
|
||||
* @return void
|
||||
*/
|
||||
public function getCsrfKey(): ?string
|
||||
public function getCsrfKey()
|
||||
{
|
||||
if ( ! \IPS\Member::loggedIn()->member_id )
|
||||
if ( isset( \IPS\Request::i()->path ) )
|
||||
{
|
||||
\IPS\Output::i()->json( [ 'key' => \IPS\Session::i()->csrfKey ] );
|
||||
$baseUrlData = parse_url( \IPS\Http\Url::baseUrl() );
|
||||
|
||||
/* If the baseURL was site.com/forums/, JS returns pathname which is /forums/foo
|
||||
so we need to check for a path in the baseURL and make sure its removed from the
|
||||
incoming path. We want to look for 'admin', so 'forums/admin' would confuse it */
|
||||
$pathToUse = '';
|
||||
if ( isset( $baseUrlData['path'] ) and $baseUrlData['path'] )
|
||||
{
|
||||
$pathToUse .= trim( $baseUrlData['path'], '/' );
|
||||
}
|
||||
|
||||
$path = trim( \IPS\Request::i()->path, '/' );
|
||||
|
||||
if ( $pathToUse )
|
||||
{
|
||||
$path = trim( preg_replace( '#^' . $pathToUse . '#', '', $path ), '/' );
|
||||
}
|
||||
|
||||
$bits = explode( '/', $path );
|
||||
|
||||
/* This is an ACP URL, so we need the admin session */
|
||||
if ( $bits[0] == \IPS\CP_DIRECTORY )
|
||||
{
|
||||
/* Ask ajax to follow the redirect for the Admin session CSRF */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=getCsrfKey', 'admin' ) );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
\IPS\Output::i()->json( [ 'key' => \IPS\Session::i()->csrfKey ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any events in the session cache and clear the cache
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getDataLayerEvents()
|
||||
{
|
||||
$payload = '{}';
|
||||
if ( \IPS\Settings::i()->core_datalayer_enabled AND \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
$payload = \IPS\core\DataLayer::i()->jsonEvents;
|
||||
\IPS\core\DataLayer::i()->clearCache();
|
||||
}
|
||||
|
||||
/* Using this instead of \IPS\Output::i()->json because it's already JSON encoded */
|
||||
\IPS\Output::i()->sendOutput( \IPS\Member::loggedIn()->language()->stripVLETags( $payload ), 200, 'application/json', \IPS\Output::i()->httpHeaders );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief alerts
|
||||
* @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 May 2022
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* alerts
|
||||
*/
|
||||
class _alerts extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss alert
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function dismiss()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Update user last seen */
|
||||
try
|
||||
{
|
||||
$alert = \IPS\core\Alerts\Alert::load( \IPS\Request::i()->id );
|
||||
|
||||
if( $alert->reply == 2 and $alert->author()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'alert_cant_dismiss', '3C428/1', 403, '' );
|
||||
}
|
||||
|
||||
$alert->dismiss();
|
||||
}
|
||||
catch( \OutOfRangeException $e ) {}
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( base64_decode( \IPS\Request::i()->ref ) );
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class _announcement extends \IPS\Content\Controller
|
||||
/* Get groups that cannot view the item */
|
||||
$groups = $item->cannotViewGroups();
|
||||
|
||||
if( !\count( $groups ) )
|
||||
if( !$groups )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'all_permissions' ) );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Easy mode controller
|
||||
* @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 Oct 2021
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect
|
||||
*/
|
||||
class _easymode extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Proxy remote CSS URLs to allow for JS to select classes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function proxy()
|
||||
{
|
||||
if ( \IPS\Theme::isUsingEasyModeEditor() )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->f ) )
|
||||
{
|
||||
$url = base64_decode( \IPS\Request::i()->f );
|
||||
$storage = \IPS\File::getClass( 'core_Theme' );
|
||||
$storageUrl = parse_url( $storage->baseUrl() );
|
||||
$test = parse_url( $url );
|
||||
|
||||
/* Does this URL match the host of the storage URL? */
|
||||
if ( preg_match( "/\.css(\.gz)?(\?|$)/", $url ) and isset( $test['host'] ) and $test['host'] == $storageUrl['host'] )
|
||||
{
|
||||
$encoded = ( preg_match( "/\.css\.gz?(\?|$)/", $url ) );
|
||||
|
||||
try
|
||||
{
|
||||
$css = \IPS\Http\Url::external( $url )->setScheme('https')->request()->get();
|
||||
|
||||
if ( $encoded )
|
||||
{
|
||||
$css = gzdecode( $css );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( $css, 200, 'text/css' );
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* still here? */
|
||||
\IPS\Output::i()->sendOutput( '/* Could not read ' . $url . '*/', 200, 'text/css' );
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
$results = '';
|
||||
if ( mb_strlen( \IPS\Request::i()->input ) > 0 )
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->like( 'name', \IPS\Request::i()->input ) ), 'name', 10 ) as $row )
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->like( 'name', \IPS\Request::i()->input ), array( 'temp_ban !=?', '-1' ) ), 'name', 10 ) as $row )
|
||||
{
|
||||
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( \IPS\Member::constructFromData( $row ) );
|
||||
}
|
||||
@@ -440,4 +440,48 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->json( $results );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stored replies
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function storedReplies()
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$reply = \IPS\core\StoredReplies::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
|
||||
\IPS\Output::i()->json( [
|
||||
'id' => $reply->id,
|
||||
'title' => $reply->title,
|
||||
'reply' => $reply->text
|
||||
] );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->json( [ 'error' => \IPS\Theme::i()->getTemplate( 'system', 'core' )->noResults() ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$results = [];
|
||||
foreach ( \IPS\core\StoredReplies::roots() as $reply )
|
||||
{
|
||||
if ( $reply->enabled )
|
||||
{
|
||||
$results[] = ['id' => $reply->id, 'title' => $reply->title];
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $results ) )
|
||||
{
|
||||
\IPS\Output::i()->json( [ 'error' => \IPS\Theme::i()->getTemplate( 'system', 'core' )->noResults() ] );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $results );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,10 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
|
||||
/* Delete any lost pass validating records that are older than 45 minutes - These records are only valid for one hour. */
|
||||
\IPS\Db::i()->delete( 'core_validating', [ 'member_id=? AND lost_pass=1 AND entry_date<?', $member->member_id, time() - 2700 ] );
|
||||
|
||||
try
|
||||
{
|
||||
$existing = \IPS\Db::i()->select( array( 'vid', 'email_sent' ), 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) )->first();
|
||||
@@ -200,6 +204,12 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_validation_key', '2S151/1', 410, '' );
|
||||
}
|
||||
|
||||
/* Show a nicer error message if their link has expired */
|
||||
if( $record['entry_date'] < \IPS\DateTime::create()->sub( new \DateInterval( 'PT1H' ) )->getTimestamp() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'lost_pass_expired', '2S151/4', 410, '' );
|
||||
}
|
||||
|
||||
/* Show form for new password */
|
||||
$form = new \IPS\Helpers\Form( "resetpass", 'save' );
|
||||
|
||||
@@ -177,7 +177,7 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
$manifest = json_decode( \IPS\Settings::i()->manifest_details, TRUE );
|
||||
|
||||
$output = array(
|
||||
'scope' => '/',
|
||||
'scope' => rtrim( \IPS\Settings::i()->base_url, '/' ) . '/',
|
||||
'name' => \IPS\Settings::i()->board_name,
|
||||
'theme_color' => \IPS\Theme::i()->settings['header']
|
||||
);
|
||||
@@ -191,6 +191,7 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$homeScreen = json_decode( \IPS\Settings::i()->icons_homescreen, TRUE ) ?? array();
|
||||
$homeScreenMaskable = json_decode( \IPS\Settings::i()->icons_homescreen_maskable, TRUE ) ?? array();
|
||||
|
||||
foreach( $homeScreen as $k => $v )
|
||||
{
|
||||
@@ -206,35 +207,30 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
$output['icons'][] = array(
|
||||
'src' => (string) $file->url,
|
||||
'type' => \IPS\File::getMimeType( $file->originalFilename ),
|
||||
'sizes' => $v['width'] . 'x' . $v['height']
|
||||
);
|
||||
'sizes' => $v['width'] . 'x' . $v['height'],
|
||||
'purpose' => 'any'
|
||||
);;
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->mobile_app_prompt )
|
||||
|
||||
foreach( $homeScreenMaskable as $k => $v )
|
||||
{
|
||||
if ( !isset( $output['short_name'] ) )
|
||||
if( mb_strpos( $k, 'android' ) !== FALSE )
|
||||
{
|
||||
$output['short_name'] = \IPS\Settings::i()->board_name;
|
||||
if( !isset( $output['icons'] ) )
|
||||
{
|
||||
$output['icons'] = array();
|
||||
}
|
||||
|
||||
$file = \IPS\File::get( 'core_Icons', $v['url'] );
|
||||
|
||||
$output['icons'][] = array(
|
||||
'src' => (string) $file->url,
|
||||
'type' => \IPS\File::getMimeType( $file->originalFilename ),
|
||||
'sizes' => $v['width'] . 'x' . $v['height'],
|
||||
'purpose' => 'maskable'
|
||||
);;
|
||||
}
|
||||
if ( !isset( $output['display'] ) )
|
||||
{
|
||||
$output['display'] = 'standalone';
|
||||
}
|
||||
|
||||
$output['prefer_related_applications'] = TRUE;
|
||||
$output['related_applications'] = array(
|
||||
array(
|
||||
'platform' => 'play',
|
||||
'id' => \IPS\Settings::i()->mobile_app_play_id ?: \IPS\APP_MULTICOMMUNITY_PLAY_ID,
|
||||
'url' => \IPS\Settings::i()->mobile_app_play_url ?: \IPS\APP_MULTICOMMUNITY_PLAY_URL,
|
||||
),
|
||||
array(
|
||||
'platform' => 'itunes',
|
||||
'id' => \IPS\Settings::i()->mobile_app_itunes_id ?: \IPS\APP_MULTICOMMUNITY_ITUNES_ID, // Note: this is also defined in includeMeta because iOS handles this different.
|
||||
'url' => \IPS\Settings::i()->mobile_app_itunes_url ?: \IPS\APP_MULTICOMMUNITY_ITUNES_URL,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
\IPS\Data\Store::i()->manifest = $output;
|
||||
|
||||
@@ -519,8 +519,8 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$form->hiddenValues[ $k ] = $v;
|
||||
if ( empty( $notificationConfiguration ) )
|
||||
{
|
||||
$type = $type == 'follower_content' ? 'core_Content' : $type;
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack( 'follow_type_no_config' ) . ' <a href="' . \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options&type=' . $type, 'front', 'notifications_options' ) . '">' . \IPS\Member::loggedIn()->language()->addToStack( 'notification_options', FALSE ) . '</a>', 'ipsPadding:none', FALSE );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -601,15 +601,18 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
/* Send notification if following member */
|
||||
if( $class == "IPS\Member" )
|
||||
{
|
||||
/* Give points */
|
||||
$receiver = \IPS\Member::load( \IPS\Request::i()->follow_rel_id );
|
||||
$receiver->achievementAction( 'core', 'FollowMember', [
|
||||
'giver' => \IPS\Member::loggedIn()
|
||||
] );
|
||||
if( $values['follow_public'] )
|
||||
{
|
||||
/* Give points */
|
||||
$receiver = \IPS\Member::load( \IPS\Request::i()->follow_id );
|
||||
$receiver->achievementAction( 'core', 'FollowMember', [
|
||||
'giver' => \IPS\Member::loggedIn()
|
||||
] );
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'member_follow', \IPS\Member::loggedIn(), array( \IPS\Member::loggedIn() ) );
|
||||
$notification->recipients->attach( $thing );
|
||||
$notification->send();
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'member_follow', \IPS\Member::loggedIn(), array( \IPS\Member::loggedIn() ) );
|
||||
$notification->recipients->attach( $thing );
|
||||
$notification->send();
|
||||
}
|
||||
}
|
||||
else if ( \in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
{
|
||||
@@ -1061,8 +1064,9 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=?', \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id ) );
|
||||
|
||||
if( \IPS\Request::i()->follow_area == 'club' )
|
||||
\IPS\Db::i()->delete( 'core_follow_count_cache', array( 'id=? AND class=?', \IPS\Request::i()->follow_id, 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) ) );
|
||||
|
||||
if( \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -34,11 +34,12 @@ class _redirect extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* First check the key to make sure this actually came from HTMLPurifier */
|
||||
if ( \IPS\Login::compareHashes( hash_hmac( "sha256", \IPS\Request::i()->url, \IPS\Settings::i()->site_secret_key ), (string) \IPS\Request::i()->key ) OR \IPS\Login::compareHashes( hash_hmac( "sha256", \IPS\Request::i()->url, \IPS\Settings::i()->site_secret_key . 'r' ), (string) \IPS\Request::i()->key ) )
|
||||
/* The URL may have had a line-break added in the outbound email if it's a long URL, we need to fix that. Then check the key matches. */
|
||||
$url = str_replace( [ '%20','%0D' ], '', (string) \IPS\Http\Url::createFromString( \IPS\Request::i()->url ) );
|
||||
if ( \IPS\Login::compareHashes( hash_hmac( "sha256", $url, \IPS\Settings::i()->site_secret_key ), (string) \IPS\Request::i()->key ) OR \IPS\Login::compareHashes( hash_hmac( "sha256", $url, \IPS\Settings::i()->site_secret_key . 'r' ), (string) \IPS\Request::i()->key ) )
|
||||
{
|
||||
/* Construct the URL */
|
||||
$url = \IPS\Http\Url::external( \IPS\Request::i()->url );
|
||||
$url = \IPS\Http\Url::external( $url );
|
||||
|
||||
/* If this is coming from email tracking, log the click */
|
||||
if( isset( \IPS\Request::i()->email ) AND \IPS\Settings::i()->prune_log_emailstats != 0 )
|
||||
|
||||
@@ -42,7 +42,8 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
if( \IPS\Request::i()->do !== 'complete' and \IPS\Request::i()->do !== 'setPassword'
|
||||
and \IPS\Request::i()->do !== 'changeEmail' and \IPS\Request::i()->do !== 'validate'
|
||||
and \IPS\Request::i()->do !== 'validating' and \IPS\Request::i()->do !== 'reconfirm'
|
||||
and \IPS\Request::i()->do !== 'finish' and \IPS\Request::i()->do !== 'cancel' )
|
||||
and \IPS\Request::i()->do !== 'finish' and \IPS\Request::i()->do !== 'cancel'
|
||||
and \IPS\Request::i()->do !== 'resend' )
|
||||
{
|
||||
if ( \IPS\Login::registrationType() == 'redirect' )
|
||||
{
|
||||
@@ -60,6 +61,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimalNoHome';
|
||||
}
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->pageCaching = FALSE;
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) \IPS\Http\Url::internal( 'app=core&module=system&controller=register', 'front', 'register' );
|
||||
}
|
||||
|
||||
@@ -1057,9 +1059,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function cancel()
|
||||
{
|
||||
/* This bit is kind of important */
|
||||
/* This bit is kind of important - don't allow externally created accounts to be deleted, they could already have commerce data */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
if ( \IPS\Member::loggedIn()->name and \IPS\Member::loggedIn()->email and !\IPS\Db::i()->select( 'COUNT(*)', 'core_validating', array( 'member_id=? AND new_reg=1', \IPS\Member::loggedIn()->member_id ) )->first() )
|
||||
if ( (\IPS\Member::loggedIn()->name and \IPS\Member::loggedIn()->email
|
||||
and !\IPS\Db::i()->select( 'COUNT(*)', 'core_validating', array( 'member_id=? AND new_reg=1', \IPS\Member::loggedIn()->member_id ) )->first() )
|
||||
OR \IPS\Member::loggedIn()->members_bitoptions['created_externally'] )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C223/1', 403, '' );
|
||||
}
|
||||
@@ -1279,7 +1283,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'node_error', '2C223/G', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'set_password_title', NULL, array( 'sprintf' => array( $member->name ) ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'set_password_title', FALSE, array( 'sprintf' => array( $member->name ) ) );
|
||||
if ( $mfa = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Request::i()->url(), $member ) )
|
||||
{
|
||||
\IPS\Output::i()->output = $mfa;
|
||||
|
||||
@@ -51,8 +51,6 @@ class _serviceworker extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* VARIABLES TO PASS THROUGH TO JS */
|
||||
$DEBUG = ( ( \IPS\IN_DEV and \IPS\DEV_DEBUG_JS ) or \IPS\DEBUG_JS ) ? 'true' : 'false'; // Weird casting is intentional.
|
||||
$SW_CACHE_BUST = \IPS\SW_CACHE_BUST ? 'true' : 'false'; // Weird casting is intentional.
|
||||
$HTTP_CACHE_DURATION = \IPS\CACHE_PAGE_TIMEOUT;
|
||||
$BASE_URL = \IPS\Settings::i()->base_url;
|
||||
$CACHED_ASSETS = json_encode( $cachedUrls, JSON_UNESCAPED_SLASHES );
|
||||
$OFFLINE_URL = (string) \IPS\Http\Url::internal("app=core&module=system&controller=offline", "front", "user_offline");
|
||||
@@ -64,12 +62,9 @@ class _serviceworker extends \IPS\Dispatcher\Controller
|
||||
$output = <<<JAVASCRIPT
|
||||
"use strict";
|
||||
const DEBUG = {$DEBUG};
|
||||
const SW_CACHE_BUST = {$SW_CACHE_BUST};
|
||||
const BASE_URL = "{$BASE_URL}";
|
||||
const CACHED_ASSETS = {$CACHED_ASSETS};
|
||||
const CACHE_NAME = 'invision-community-{$CACHE_VERSION}';
|
||||
const HTTP_CACHE_DURATION = {$HTTP_CACHE_DURATION};
|
||||
const HTTP_CACHE_BUFFER = 60;
|
||||
const OFFLINE_URL = "{$OFFLINE_URL}";
|
||||
const NOTIFICATION_ICON = {$NOTIFICATION_ICON};
|
||||
const DEFAULT_NOTIFICATION_TITLE = "{$DEFAULT_NOTIFICATION_TITLE}";
|
||||
|
||||
@@ -22,6 +22,13 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* @brief These properties are used to specify datalayer context properties.
|
||||
*
|
||||
*/
|
||||
public static $dataLayerContext = array(
|
||||
'community_area' => [ 'value' => 'settings', 'odkUpdate' => true]
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute
|
||||
@@ -384,7 +391,10 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'current_password', '', TRUE, array( 'protect' => TRUE, 'validateFor' => \IPS\Member::loggedIn(), 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "current-password" ) ) );
|
||||
if ( !\IPS\Member::loggedIn()->members_bitoptions['password_reset_forced'] )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'current_password', '', TRUE, array( 'protect' => TRUE, 'validateFor' => \IPS\Member::loggedIn(), 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "current-password" ) ) );
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'new_password', '', TRUE, array( 'protect' => TRUE, 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'strengthMember' => \IPS\Member::loggedIn(), 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "new-password" ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'confirm_new_password', '', TRUE, array( 'protect' => TRUE, 'confirm' => 'new_password', 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "new-password" ) ) );
|
||||
|
||||
@@ -597,6 +607,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function _mfa()
|
||||
{
|
||||
\IPS\Output::i()->bypassCsrfKeyCheck = true;
|
||||
|
||||
/* Validate password */
|
||||
if ( !isset( $_SESSION['passwordValidatedForMfa'] ) )
|
||||
{
|
||||
@@ -646,11 +658,11 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
return $output . $mfaOutput;
|
||||
}
|
||||
|
||||
/* Do any enabling/diabling */
|
||||
/* Do any enabling/disabling */
|
||||
if ( isset( \IPS\Request::i()->act ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
|
||||
/* Get the handler */
|
||||
$key = \IPS\Request::i()->type;
|
||||
if ( !isset( $handlers[ $key ] ) or \IPS\MFA\MFAHandler::accessToArea( 'core', 'SecurityQuestions', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) ) )
|
||||
@@ -671,11 +683,11 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
}
|
||||
|
||||
/* Show the configruation modal */
|
||||
|
||||
/* Show the configuration modal */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('settings');
|
||||
return $output . \IPS\Theme::i()->getTemplate( 'system' )->settingsMfaSetup( $handlers[ $key ]->configurationScreen( \IPS\Member::loggedIn(), FALSE, \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa&act=enable&type=' . $key, 'front', 'settings_mfa' ) ), \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa&act=enable&type=' . $key, 'front', 'settings_mfa' ) );
|
||||
}
|
||||
@@ -1708,7 +1720,7 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
$this->_performRedirect( \IPS\Http\Url::internal( "app=core&module=system&controller=settings", 'front', 'settings' ), 'block_newsletter_subscribed' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toggle Anonymously Online
|
||||
*
|
||||
@@ -1717,26 +1729,57 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
protected function updateAnon()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
|
||||
/* Check this value can be toggled */
|
||||
if( \IPS\Member::loggedIn()->group['g_hide_online_list'] >= 1 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'online_status_cannot_change', '2C122/X', 403, '' );
|
||||
}
|
||||
|
||||
/* Update the bitwise flag */
|
||||
\IPS\Member::loggedIn()->members_bitoptions['is_anon'] = (bool) \IPS\Request::i()->value;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
|
||||
/* Update users devices */
|
||||
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members_known_devices', array( "member_id=?", \IPS\Member::loggedIn()->member_id ) ), 'IPS\Member\Device' ) AS $device )
|
||||
{
|
||||
$device->anonymous = ( (bool) \IPS\Request::i()->value ) ? 1 : 0;
|
||||
$device->save();
|
||||
}
|
||||
|
||||
|
||||
/* Update the session */
|
||||
\IPS\Session::i()->setType( ( (bool) \IPS\Request::i()->value ) ? \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS : \IPS\Session\Front::LOGIN_TYPE_MEMBER );
|
||||
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
|
||||
|
||||
$this->_performRedirect( \IPS\Http\Url::internal( "app=core&module=system&controller=settings&area=mfa", 'front', 'settings_mfa' ), 'saved' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Whether PII is included in the data layer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function togglePii()
|
||||
{
|
||||
if ( ! \IPS\Settings::i()->core_datalayer_member_pii_choice )
|
||||
{
|
||||
\IPS\Output::i()->error( 'page_not_found', '3T251/7', 404 );
|
||||
}
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Update the bitwise flag */
|
||||
\IPS\Member::loggedIn()->datalayer_collect_pii = (bool) ! \IPS\Member::loggedIn()->datalayer_collect_pii;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
|
||||
$this->_performRedirect( \IPS\Http\Url::internal( "app=core&module=system&controller=settings&area=mfa", 'front', 'settings_mfa' ), 'saved' );
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
$rgb[] = hexdec( \substr( $colorValue, 4, 2 ) );
|
||||
}
|
||||
|
||||
$colorValues[ $key ] = implode( $rgb, ', ');
|
||||
$colorValues[ $key ] = implode( ', ', $rgb );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->language()->words['widget_adv__custom_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'widget_adv__custom__desc', NULL, array( 'sprintf' => array( \IPS\Request::i()->block ) ) );
|
||||
\IPS\Member::loggedIn()->language()->words['widget_adv__custom_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'widget_adv__custom__desc', FALSE, array( 'sprintf' => array( \IPS\Request::i()->block ) ) );
|
||||
\IPS\Output::i()->output = $configurationForm->customTemplate( array( \IPS\Theme::i()->getTemplate( 'widgets', 'core' ), 'formTemplate' ), $widget );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user