Version 4.7.0

This commit is contained in:
Neo committed 2025-12-19 16:00:35 -08:00
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 );
}
}