Version 4.7.6

This commit is contained in:
Neo committed 2025-12-19 16:05:19 -08:00
1 parent 8ba7d43898
commit 7b7404e741
1085 files changed
+30590 -7837

No files matched your search

@@ -183,7 +183,8 @@ class _directory extends \IPS\Dispatcher\Controller
$myClubsInvites = NULL;
if ( \IPS\Member::loggedIn()->member_id )
{
$myClubsActivity = \IPS\Content\Search\Query::init()->filterByClub( \IPS\Member::loggedIn()->clubs() )->setLimit(6)->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->search();
$myClubsActivity = new \IPS\core\Stream;
$myClubsActivity = $myClubsActivity->query()->filterByClub( \IPS\Member::loggedIn()->clubs() )->setLimit(6)->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->search();
$myClubsInvites = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_clubs_memberships', array( 'member_id=? and ( status=? or status=? )', \IPS\Member::loggedIn()->member_id, \IPS\Member\Club::STATUS_REQUESTED, \IPS\Member\Club::STATUS_INVITED )
)->join(
'core_clubs',
@@ -57,7 +57,7 @@ class _page extends \IPS\Dispatcher\Controller
/* Club info in sidebar */
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
{
\IPS\Output::i()->sidebar['contextual'] .= \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $this->page->club, NULL, 'sidebar' );
\IPS\Output::i()->sidebar['contextual'] .= \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $this->page->club, NULL, 'sidebar', $this->page );
}
if( ( \IPS\GeoLocation::enabled() and \IPS\Settings::i()->clubs_locations AND $location = $this->page->club->location() ) )
@@ -82,24 +82,26 @@ class _streams extends \IPS\Dispatcher\Controller
/* RSS validate? */
$member = NULL;
if ( isset( \IPS\Request::i()->rss ) )
if ( isset( \IPS\Request::i()->rss ) AND isset( \IPS\Request::i()->member ) AND isset( \IPS\Request::i()->key ) )
{
if ( isset( \IPS\Request::i()->member ) AND isset( \IPS\Request::i()->key ) )
$member = \IPS\Member::load( \IPS\Request::i()->member );
if ( !$member->member_id OR !\IPS\Login::compareHashes( $member->getUniqueMemberHash(), (string) \IPS\Request::i()->key ) )
{
$member = \IPS\Member::load( \IPS\Request::i()->member );
if ( !$member->member_id OR !\IPS\Login::compareHashes( $member->getUniqueMemberHash(), (string) \IPS\Request::i()->key ) )
{
$member = NULL;
}
/* If we do not have a specific member, and this member is not allowed to view the site, throw an error as they do not have permission */
if ( ! $member and ! \IPS\Member::loggedIn()->group['g_view_board'] )
{
\IPS\Output::i()->error( 'stream_no_permission', '2C280/G', 403, '' );
}
$member = NULL;
}
/* If we do not have a specific member, and this member is not allowed to view the site, throw an error as they do not have permission */
if ( ! $member and ! \IPS\Member::loggedIn()->group['g_view_board'] )
{
\IPS\Output::i()->error( 'stream_no_permission', '2C280/G', 403, '' );
}
}
else if ( ! \IPS\Member::loggedIn()->group['g_view_board'] )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
}
$form = NULL;
/* Viewing a particular stream? */
@@ -204,13 +204,13 @@ class _messenger extends \IPS\Content\Controller
try
{
$alert = \IPS\core\Alerts\Alert::load( $conversation->alert );
if( ! $alert->forMember( \IPS\Member::loggedIn() ) and $alert->author()->member_id != \IPS\Member::loggedIn()->member_id )
{
$alert = NULL;
}
}
catch ( \OutOfRangeException $e ) {}
if( !$alert->forMember( \IPS\Member::loggedIn() ) )
{
$alert = NULL;
}
}
}
@@ -359,6 +359,11 @@ class _messenger extends \IPS\Content\Controller
/* Performance: if $count is 0, don't bother selecting ... it's a wasted query */
if( $count )
{
if ( $alert = \IPS\core\Alerts\Alert::getAlertCurrentlyFilteringMessages() )
{
$where[] = array( 'core_message_topics.mt_alert=?', $alert->id );
}
/* Get iterator */
$iterator = \IPS\Db::i()->select(
'core_message_topic_user_map.*, core_message_topics.*',
@@ -496,6 +501,9 @@ class _messenger extends \IPS\Content\Controller
if( $alert->forMember( \IPS\Member::loggedIn() ) )
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('alert_modal_title', FALSE, array( 'sprintf' => array( $alert->title ) ) );
$form->elements['']['messenger_content']->defaultValue = '<blockquote class="ipsQuote">' . $alert->content . "</blockquote><br>";
$form->elements['']['messenger_content']->setValue(TRUE , FALSE );
}
}
catch ( \OutOfRangeException $e ) {}
@@ -1014,4 +1022,16 @@ class _messenger extends \IPS\Content\Controller
'counts' => $counts
);
}
/**
* Remove any messenger filters
*
* @return void
*/
protected function removeAlertFilter()
{
\IPS\core\Alerts\Alert::clearMessengerFilters();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=messaging&controller=messenger&overview=1') );
}
}
@@ -530,7 +530,7 @@ class _promote extends \IPS\Dispatcher\Controller
$scheduled = time();
$scheduleAuto = 0;
if ( $values['promote_schedule'] == 'custom' )
if ( $values['promote_schedule'] == 'custom' AND $values['promote_custom_date'] )
{
$scheduled = $values['promote_custom_date']->getTimestamp();
}
@@ -22,6 +22,21 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _ajax extends \IPS\Dispatcher\Controller
{
/**
* Find Member
*
* @return void
*/
public function subscribeToSolved()
{
\IPS\Session::i()->csrfCheck();
\IPS\Member::loggedIn()->members_bitoptions['no_solved_reenage'] = 0;
\IPS\Member::loggedIn()->save();
\IPS\Output::i()->json( [ 'message' => \IPS\Member::loggedIn()->language()->addToStack( 'mark_solved_reengage_back_on' ) ] );
}
/**
* Find Member
*
@@ -634,8 +649,8 @@ class _ajax extends \IPS\Dispatcher\Controller
/* Then look for used tags */
$where = array(
array( "tag_text LIKE CONCAT(?, '%')", $input ),
array( 'tag_perm_visible=?', 1 ),
array( '(' . \IPS\Db::i()->findInSet( 'tag_perm_text', \IPS\Member::loggedIn()->groups ) . ' OR ' . 'tag_perm_text=? )', '*' ),
array( '(tag_perm_visible=? OR tag_perm_aai_lookup IS NULL)', 1 ),
array( '(' . \IPS\Db::i()->findInSet( 'tag_perm_text', \IPS\Member::loggedIn()->groups ) . ' OR ' . 'tag_perm_text=? OR tag_perm_text IS NULL)', '*' ),
);
foreach ( \IPS\Db::i()->select( 'tag_text', 'core_tags', $where, 'LENGTH(tag_text) ASC', array( 0, 20 ), 'tag_text' )->join( 'core_tags_perms', array( 'tag_perm_aai_lookup=tag_aai_lookup' ) ) as $tag )
@@ -660,6 +675,9 @@ class _ajax extends \IPS\Dispatcher\Controller
*/
public function getCsrfKey()
{
/* Don't cache the CSRF key */
\IPS\Output::i()->pageCaching = FALSE;
if ( isset( \IPS\Request::i()->path ) )
{
$baseUrlData = parse_url( \IPS\Http\Url::baseUrl() );
@@ -47,7 +47,7 @@ class _alerts extends \IPS\Dispatcher\Controller
{
$alert = \IPS\core\Alerts\Alert::load( \IPS\Request::i()->id );
if( $alert->reply == 2 and $alert->author()->member_id )
if( $alert->reply == 2 and \IPS\Member::loggedIn()->member_id and \IPS\Member::loggedIn()->canUseMessenger() )
{
\IPS\Output::i()->error( 'alert_cant_dismiss', '3C428/1', 403, '' );
}
@@ -59,4 +59,16 @@ class _alerts extends \IPS\Dispatcher\Controller
/* Redirect */
\IPS\Output::i()->redirect( base64_decode( \IPS\Request::i()->ref ) );
}
/**
* Set currently filtering alert and redirect
*
* @return void
*/
protected function viewReplies()
{
\IPS\core\Alerts\Alert::setAlertCurrentlyFilteringMessages( \IPS\core\Alerts\Alert::load( \IPS\Request::i()->id ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=messaging&controller=messenger&overview=1') );
}
}
@@ -344,9 +344,39 @@ 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 ), array( 'temp_ban !=?', '-1' ) ), 'name', 10 ) as $row )
$memberIds = [];
if ( isset( \IPS\Request::i()->contentClass ) AND isset( \IPS\Request::i()->contentId ) )
{
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( \IPS\Member::constructFromData( $row ) );
$class = \IPS\Request::i()->contentClass;
if ( \class_exists( $class ) AND \IPS\IPS::classUsesTrait( $class, 'IPS\Content\Statistics' ) )
{
try
{
$item = $class::load( \IPS\Request::i()->contentId );
foreach( $item->mostRecent( \IPS\Request::i()->input ) AS $row )
{
$memberIds[] = $row->member_id;
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( $row );
}
}
catch( \OutOfRangeException | \BadMethodCallException $e ) { }
}
}
/* If there are less than ten recent participants matching the input, fill it out with non-participants. */
if ( \count( $memberIds ) < 10 )
{
$where = array( \IPS\Db::i()->like( 'name', \IPS\Request::i()->input ) );
$where[] = array( 'temp_ban !=?', '-1' );
if ( \count( $memberIds ) )
{
$where[] = array( \IPS\Db::i()->in( 'member_id', $memberIds, TRUE ) );
}
foreach ( \IPS\Db::i()->select( '*', 'core_members', $where, 'name', 10 - \count( $memberIds ) ) as $row )
{
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( \IPS\Member::constructFromData( $row ) );
}
}
}
@@ -34,6 +34,8 @@ class _login extends \IPS\Dispatcher\Controller
*/
protected function manage()
{
\IPS\Output::i()->pageCaching = FALSE;
/* Init login class */
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' ) );
@@ -112,6 +114,16 @@ class _login extends \IPS\Dispatcher\Controller
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
}
/* If there is only one button handler, redirect */
if ( !isset( \IPS\Request::i()->_processLogin ) and !$login->usernamePasswordMethods() and \count( $login->buttonMethods() ) == 1 )
{
$buttonMethod = $login->buttonMethods()[ array_key_first( $login->buttonMethods() ) ];
if( method_exists( $buttonMethod, 'authenticateButton' ) )
{
$buttonMethod->authenticateButton( $login );
}
}
/* Display Login Form */
\IPS\Output::i()->allowDefaultWidgets = FALSE;
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
@@ -29,6 +29,7 @@ class _offline extends \IPS\Dispatcher\Controller
*/
protected function manage()
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->offline(), 200, 'text/html' );
}
}
@@ -35,44 +35,51 @@ class _redirect extends \IPS\Dispatcher\Controller
protected function manage()
{
/* 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 ) )
try
{
/* Construct the 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 )
$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 ) )
{
/* If we have a row for "today" then update it, otherwise insert one */
$today = \IPS\DateTime::create()->format( 'Y-m-d' );
/* Construct the URL */
$url = \IPS\Http\Url::external( $url );
try
/* If this is coming from email tracking, log the click */
if( isset( \IPS\Request::i()->email ) AND \IPS\Settings::i()->prune_log_emailstats != 0 )
{
/* We only include the time column in the query so that the db index can be effectively used */
if( !\IPS\Request::i()->type )
{
$currentRow = \IPS\Db::i()->select( '*', 'core_statistics', array( 'type=? AND time>? AND value_4=? AND extra_data IS NULL', 'email_clicks', 1, $today ) )->first();
}
else
{
$currentRow = \IPS\Db::i()->select( '*', 'core_statistics', array( 'type=? AND time>? AND value_4=? AND extra_data=?', 'email_clicks', 1, $today, \IPS\Request::i()->type ) )->first();
}
/* If we have a row for "today" then update it, otherwise insert one */
$today = \IPS\DateTime::create()->format( 'Y-m-d' );
\IPS\Db::i()->update( 'core_statistics', "value_1=value_1+1", array( 'id=?', $currentRow['id'] ) );
}
catch( \UnderflowException $e )
{
\IPS\Db::i()->insert( 'core_statistics', array( 'type' => 'email_clicks', 'value_1' => 1, 'value_4' => $today, 'time' => time(), 'extra_data' => \IPS\Request::i()->type ) );
try
{
/* We only include the time column in the query so that the db index can be effectively used */
if( !\IPS\Request::i()->type )
{
$currentRow = \IPS\Db::i()->select( '*', 'core_statistics', array( 'type=? AND time>? AND value_4=? AND extra_data IS NULL', 'email_clicks', 1, $today ) )->first();
}
else
{
$currentRow = \IPS\Db::i()->select( '*', 'core_statistics', array( 'type=? AND time>? AND value_4=? AND extra_data=?', 'email_clicks', 1, $today, \IPS\Request::i()->type ) )->first();
}
\IPS\Db::i()->update( 'core_statistics', "value_1=value_1+1", array( 'id=?', $currentRow['id'] ) );
}
catch( \UnderflowException $e )
{
\IPS\Db::i()->insert( 'core_statistics', array( 'type' => 'email_clicks', 'value_1' => 1, 'value_4' => $today, 'time' => time(), 'extra_data' => \IPS\Request::i()->type ) );
}
}
/* Send the user to the URL after setting the referrer policy header */
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin" );
\IPS\Output::i()->redirect( $url, \IPS\Request::i()->email ? '' : \IPS\Member::loggedIn()->language()->addToStack('external_redirect'), 303, \IPS\Request::i()->email ? FALSE : TRUE );
}
/* If it doesn't validate, send the user to the index page */
else
{
throw new \DomainException();
}
/* Send the user to the URL after setting the referrer policy header */
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin" );
\IPS\Output::i()->redirect( $url, \IPS\Request::i()->email ? '' : \IPS\Member::loggedIn()->language()->addToStack('external_redirect'), 303, \IPS\Request::i()->email ? FALSE : TRUE );
}
/* If it doesn't validate, send the user to the index page */
else
catch( \DomainException $e )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
}
@@ -560,7 +560,7 @@ class _register extends \IPS\Dispatcher\Controller
}
}
if ( \IPS\Settings::i()->quick_register )
if ( \IPS\Settings::i()->allow_reg != 'disabled' )
{
/* Initial Save */
$member->save();
@@ -1312,4 +1312,4 @@ class _register extends \IPS\Dispatcher\Controller
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->registerSetPassword( $form, $member );
}
}
}
@@ -1841,6 +1841,27 @@ class _settings extends \IPS\Dispatcher\Controller
return \IPS\Theme::i()->getTemplate( 'system' )->settingsReferrals( $table, $url, $rules );
}
/**
* Toggle New Device Email
*
* @return void
*/
protected function updateDeviceEmail()
{
\IPS\Session::i()->csrfCheck();
/* Update the bitwise flag */
\IPS\Member::loggedIn()->members_bitoptions['new_device_email'] = (bool) \IPS\Request::i()->value;
\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=devices", 'front', 'settings_devices' ), 'saved' );
}
/**
* Redirect the user
* -consolidated to reduce duplicate code
@@ -48,16 +48,27 @@ class _unsubscribe extends \IPS\Dispatcher\Controller
/* Verify the key is correct */
if ( \IPS\Login::compareHashes( md5( $member->email . ':' . $member->members_pass_hash ), (string) \IPS\Request::i()->key ) )
{
/* Set the member not to receive future emails */
$member->allow_admin_mails = 0;
$member->save();
/* Log it */
$member->logHistory( 'core', 'admin_mails', array( 'enabled' => FALSE ) );
$action = 'bulkEmail';
if ( isset( \IPS\Request::i()->action ) and \IPS\Request::i()->action === 'markSolved' )
{
$action = 'markSolved';
$member->members_bitoptions['no_solved_reenage'] = 1;
$member->save();
}
else
{
/* Set the member not to receive future emails */
$member->allow_admin_mails = 0;
$member->save();
/* Log it */
$member->logHistory( 'core', 'admin_mails', array( 'enabled' => FALSE ) );
}
/* And then show them a confirmation screen */
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->unsubscribed( $action );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('unsubscribed');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->unsubscribed();
}
else
{