Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -31,19 +31,19 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$input = mb_strtolower( \IPS\Request::i()->input );
|
||||
$input = str_replace( array( '%', '_' ), array( '\%', '\_' ), mb_strtolower( \IPS\Request::i()->input ) );
|
||||
|
||||
$where = array( "name LIKE CONCAT('%', ?, '%')" );
|
||||
$where = array( "name LIKE CONCAT(?, '%')" );
|
||||
$binds = array( $input );
|
||||
if ( \IPS\Dispatcher::i()->controllerLocation === 'admin' )
|
||||
{
|
||||
$where[] = "email LIKE CONCAT('%', ?, '%')";
|
||||
$where[] = "email LIKE CONCAT(?, '%')";
|
||||
$binds[] = $input;
|
||||
|
||||
if ( is_numeric( \IPS\Request::i()->input ) )
|
||||
if ( \is_numeric( \IPS\Request::i()->input ) )
|
||||
{
|
||||
$where[] = "member_id=?";
|
||||
$binds[] = intval( \IPS\Request::i()->input );
|
||||
$binds[] = \intval( \IPS\Request::i()->input );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,138 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->json( $results );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size and download count of an array of attachments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function attachmentInfo()
|
||||
{
|
||||
$toReturn = array();
|
||||
$member = \IPS\Member::loggedIn();
|
||||
$loadedExtensions = array();
|
||||
|
||||
/* As you can insert "other media" from other apps (such as Downloads), we need to route the attachIDs appropriately. */
|
||||
$attachmentIds = array();
|
||||
|
||||
foreach( array_keys( \IPS\Request::i()->attachIDs ) as $attachId )
|
||||
{
|
||||
if( (int) $attachId == $attachId AND mb_strlen( (int) $attachId ) == mb_strlen( $attachId ) )
|
||||
{
|
||||
$attachmentIds[] = $attachId;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
$url = \IPS\Http\Url::createFromString( $attachId );
|
||||
|
||||
/* Get the "real" query string (whatever the query string is, plus what we can get from decoding the FURL) */
|
||||
$qs = array_merge( $url->queryString, $url->hiddenQueryString );
|
||||
|
||||
/* We need an app, and it needs to not be an RSS link */
|
||||
if ( !isset( $qs['app'] ) )
|
||||
{
|
||||
throw new \UnexpectedValueException;
|
||||
}
|
||||
|
||||
/* Load the application */
|
||||
$application = \IPS\Application::load( $qs['app'] );
|
||||
|
||||
/* Loop through our content classes and see if we can find one that matches */
|
||||
foreach ( $application->extensions( 'core', 'ContentRouter' ) as $key => $extension )
|
||||
{
|
||||
$classes = $extension->classes;
|
||||
|
||||
/* So for each of those... */
|
||||
foreach ( $classes as $class )
|
||||
{
|
||||
/* Try to load it */
|
||||
try
|
||||
{
|
||||
$item = $class::loadFromURL( $url );
|
||||
|
||||
if( !$item->canView() )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
|
||||
/* If we're still here, we should be good. Any exceptions will have been caught by our general try/catch. */
|
||||
$toReturn[ $attachId ] = $item->getAttachmentInfo();
|
||||
break;
|
||||
}
|
||||
catch( \OutOfRangeException $e ){}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( \Exception $e ){}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get attachments */
|
||||
if( \count( $attachmentIds ) )
|
||||
{
|
||||
$attachments = \IPS\Db::i()->select( '*', 'core_attachments', array( \IPS\Db::i()->in( 'attach_id', $attachmentIds ) ) );
|
||||
|
||||
foreach( $attachments as $attachment )
|
||||
{
|
||||
$permission = FALSE;
|
||||
|
||||
if( $member->member_id )
|
||||
{
|
||||
if ( $member->member_id == $attachment['attach_member_id'] )
|
||||
{
|
||||
$permission = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if( $permission !== TRUE )
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_attachments_map', array( 'attachment_id=?', $attachment['attach_id'] ) ) as $map )
|
||||
{
|
||||
if ( !isset( $loadedExtensions[ $map['location_key'] ] ) )
|
||||
{
|
||||
$exploded = explode( '_', $map['location_key'] );
|
||||
try
|
||||
{
|
||||
$extensions = \IPS\Application::load( $exploded[0] )->extensions( 'core', 'EditorLocations' );
|
||||
if ( isset( $extensions[ $exploded[1] ] ) )
|
||||
{
|
||||
$loadedExtensions[ $map['location_key'] ] = $extensions[ $exploded[1] ];
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
if ( isset( $loadedExtensions[ $map['location_key'] ] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( $loadedExtensions[ $map['location_key'] ]->attachmentPermissionCheck( $member, $map['id1'], $map['id2'], $map['id3'], $attachment ) )
|
||||
{
|
||||
$permission = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Permission check */
|
||||
if ( $permission )
|
||||
{
|
||||
$toReturn[ $attachment['attach_id'] ] = array(
|
||||
'size' => \IPS\Output\Plugin\Filesize::humanReadableFilesize( $attachment['attach_filesize'], FALSE, TRUE ),
|
||||
'downloads' => \IPS\Member::loggedIn()->language()->formatNumber( $attachment['attach_hits'] )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $toReturn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean in json indicating whether the supplied username already exists
|
||||
@@ -90,7 +222,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, '/' ) ) . ']*$/iu', $name ) )
|
||||
elseif ( !\IPS\Login::usernameIsAllowed( $name ) )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('form_bad_value') );
|
||||
}
|
||||
@@ -185,7 +317,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $allowedEmailDomains ) AND !$matched )
|
||||
if ( \count( $allowedEmailDomains ) AND !$matched )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => $email );
|
||||
}
|
||||
@@ -214,12 +346,12 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Top Contributors
|
||||
*
|
||||
* @retun void
|
||||
* @return void
|
||||
*/
|
||||
public function topContributors()
|
||||
{
|
||||
/* How many? */
|
||||
$limit = intval( ( isset( \IPS\Request::i()->limit ) and \IPS\Request::i()->limit <= 25 ) ? \IPS\Request::i()->limit : 5 );
|
||||
$limit = \intval( ( isset( \IPS\Request::i()->limit ) and \IPS\Request::i()->limit <= 25 ) ? \IPS\Request::i()->limit : 5 );
|
||||
|
||||
/* What timeframe? */
|
||||
$where = array( array( 'member_received > 0' ) );
|
||||
@@ -242,12 +374,12 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
break;
|
||||
}
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', $where, NULL, NULL, 'member' );
|
||||
$topContributors = iterator_to_array( \IPS\Db::i()->select( 'member, rep', array( $innerQuery, 'in' ), NULL, 'rep DESC', $limit )->setKeyField('member')->setValueField('rep') );
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as themember, SUM(rep_rating) as rep', 'core_reputation_index', $where, NULL, NULL, 'themember' );
|
||||
$topContributors = iterator_to_array( \IPS\Db::i()->select( 'themember, rep', array( $innerQuery, 'in' ), NULL, 'rep DESC', $limit )->setKeyField('themember')->setValueField('rep') );
|
||||
}
|
||||
else
|
||||
{
|
||||
$topContributors = iterator_to_array( \IPS\Db::i()->select( 'member_id as member, pp_reputation_points as rep', 'core_members', array( 'pp_reputation_points > 0' ), 'rep DESC', $limit )->setKeyField('member')->setValueField('rep') );
|
||||
$topContributors = iterator_to_array( \IPS\Db::i()->select( 'member_id as themember, pp_reputation_points as rep', 'core_members', array( 'pp_reputation_points > 0' ), 'rep DESC', $limit )->setKeyField('themember')->setValueField('rep') );
|
||||
}
|
||||
|
||||
/* Load their data */
|
||||
@@ -269,10 +401,68 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Most Solved
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function mostSolved()
|
||||
{
|
||||
/* How many? */
|
||||
$limit = \intval( ( isset( \IPS\Request::i()->limit ) and \IPS\Request::i()->limit <= 25 ) ? \IPS\Request::i()->limit : 5 );
|
||||
|
||||
/* What timeframe? */
|
||||
$where = array( array( 'member_id > 0' ) );
|
||||
$timeframe = 'all';
|
||||
if ( isset( \IPS\Request::i()->time ) and \IPS\Request::i()->time != 'all' )
|
||||
{
|
||||
switch ( \IPS\Request::i()->time )
|
||||
{
|
||||
case 'week':
|
||||
$where[] = array( 'solved_date>' . \IPS\DateTime::create()->sub( new \DateInterval( 'P1W' ) )->getTimestamp() );
|
||||
$timeframe = 'week';
|
||||
break;
|
||||
case 'month':
|
||||
$where[] = array( 'solved_date>' . \IPS\DateTime::create()->sub( new \DateInterval( 'P1M' ) )->getTimestamp() );
|
||||
$timeframe = 'month';
|
||||
break;
|
||||
case 'year':
|
||||
$where[] = array( 'solved_date>' . \IPS\DateTime::create()->sub( new \DateInterval( 'P1Y' ) )->getTimestamp() );
|
||||
$timeframe = 'year';
|
||||
break;
|
||||
}
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_solved_index.member_id as themember, COUNT(*) as count', 'core_solved_index', $where, NULL, NULL, 'themember' );
|
||||
$topSolved = iterator_to_array( \IPS\Db::i()->select( 'themember, count', array( $innerQuery, 'in' ), NULL, 'count DESC', $limit )->setKeyField('themember')->setValueField('count') );
|
||||
}
|
||||
else
|
||||
{
|
||||
$topSolved = iterator_to_array( \IPS\Db::i()->select( 'MAX(member_id) as member_id, COUNT(*) as count', 'core_solved_index', NULL, 'count DESC', $limit, 'member_id' )->setKeyField('member_id')->setValueField('count') );
|
||||
}
|
||||
|
||||
/* Load their data */
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', \IPS\Db::i()->in( 'member_id', array_keys( $topSolved ) ) ) as $member )
|
||||
{
|
||||
\IPS\Member::constructFromData( $member );
|
||||
}
|
||||
|
||||
/* Render */
|
||||
$output = \IPS\Theme::i()->getTemplate( 'widgets' )->mostSolvedRows( $topSolved, $timeframe, \IPS\Request::i()->orientation );
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $output );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'block_mostSolved' );
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu Preview
|
||||
*
|
||||
* @retun void
|
||||
* @return void
|
||||
*/
|
||||
public function menuPreview()
|
||||
{
|
||||
@@ -306,7 +496,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
/* If there's new notifications, get the actual data */
|
||||
if ( \IPS\Request::i()->notifications < $return['notifications']['count'] )
|
||||
{
|
||||
$notificationsDifference = $return['notifications']['count'] - \IPS\Request::i()->notifications;
|
||||
$notificationsDifference = $return['notifications']['count'] - (int) \IPS\Request::i()->notifications;
|
||||
|
||||
/* Cap at 200 to prevent DOSing the server when there are like 1000+ notifications to send */
|
||||
if( $notificationsDifference > 200 )
|
||||
@@ -314,7 +504,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
$notificationsDifference = 200;
|
||||
}
|
||||
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_notifications', array( 'member=? AND ( read_time IS NULL OR read_time<? )', \IPS\Member::loggedIn()->member_id, time() ), 'updated_time DESC', $notificationsDifference ), 'IPS\Notification\Inline' ) as $notification )
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_notifications', array( '`member`=? AND ( read_time IS NULL OR read_time<? )', \IPS\Member::loggedIn()->member_id, time() ), 'updated_time DESC', $notificationsDifference ), 'IPS\Notification\Inline' ) as $notification )
|
||||
{
|
||||
/* It is possible that the content has been removed after the iterator has started but before we fetch the data */
|
||||
try
|
||||
@@ -342,7 +532,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( \IPS\Request::i()->messages < $return['messages']['count'] )
|
||||
{
|
||||
$messagesDifference = $return['messages']['count'] - \IPS\Request::i()->messages;
|
||||
$messagesDifference = $return['messages']['count'] - (int) \IPS\Request::i()->messages;
|
||||
|
||||
foreach ( \IPS\Db::i()->select( 'map_topic_id', 'core_message_topic_user_map', array( 'map_user_id=? AND map_user_active=1 AND map_has_unread=1 AND map_ignore_notification=0', \IPS\Member::loggedIn()->member_id ), 'map_last_topic_reply DESC', $messagesDifference ) as $conversationId )
|
||||
{
|
||||
@@ -386,7 +576,22 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
$phpass = new \PasswordStrength();
|
||||
|
||||
$response = array( 'result' => 'ok', 'score' => $phpass->classify( $password ), 'granular' => $phpass->calculate( $password ) );
|
||||
$score = NULL;
|
||||
$granular = NULL;
|
||||
|
||||
if( isset( \IPS\Request::i()->checkAgainstRequest ) AND \is_array( \IPS\Request::i()->checkAgainstRequest ) )
|
||||
{
|
||||
foreach( \IPS\Request::i()->checkAgainstRequest as $notIdenticalValue )
|
||||
{
|
||||
if( $notIdenticalValue AND $password == urldecode( $notIdenticalValue ) )
|
||||
{
|
||||
$score = $phpass::STRENGTH_VERY_WEAK;
|
||||
$granular = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response = array( 'result' => 'ok', 'score' => $score ?? $phpass->classify( $password ), 'granular' => $granular ?? $phpass->calculate( $password ) );
|
||||
|
||||
\IPS\Output::i()->json( $response );
|
||||
}
|
||||
@@ -401,9 +606,93 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
$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] ) ) );
|
||||
$mysqlTimezone = "GMT" . ( ( $matches[2] == 0 ) ? '' : ( ( $matches[1] ?: '+' ) . \intval( $matches[2] ) ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->chartTimezoneInfo( $mysqlTimezone );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss ACP Notification
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dismissAcpNotification()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if ( \IPS\Member::loggedIn()->isAdmin() )
|
||||
{
|
||||
\IPS\core\AdminNotification::dismissNotification( \IPS\Request::i()->id );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( array( 'status' => 'OK' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find suggested tags
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function findTags()
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$input = mb_strtolower( \IPS\Request::i()->input );
|
||||
|
||||
/* First, get the admin-defined tags */
|
||||
$definedTags = array();
|
||||
|
||||
if( isset( \IPS\Request::i()->class ) )
|
||||
{
|
||||
$class = \IPS\Request::i()->class;
|
||||
$containerClass = $class::$containerNodeClass;
|
||||
|
||||
try
|
||||
{
|
||||
$container = $containerClass::load( \IPS\Request::i()->container );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$container = NULL;
|
||||
}
|
||||
|
||||
if( $definedTags = $class::definedTags( $container ) )
|
||||
{
|
||||
foreach( $definedTags as $tag )
|
||||
{
|
||||
/* Only include tags that match the input term */
|
||||
if( mb_stripos( $tag, $input ) !== FALSE )
|
||||
{
|
||||
$results[] = array(
|
||||
'value' => $tag,
|
||||
'html' => $tag,
|
||||
'recommended' => true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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=? )', '*' ),
|
||||
);
|
||||
|
||||
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 )
|
||||
{
|
||||
if( !\in_array( $tag, $definedTags ) )
|
||||
{
|
||||
$results[] = array(
|
||||
'value' => $tag,
|
||||
'html' => $tag,
|
||||
'recommended' => false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $results );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -45,24 +45,89 @@ class _announcement extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'announcement_missing', '2C199/1', 404, '' );
|
||||
}
|
||||
|
||||
if ( !$announcement->canView() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error_no_perm', '2C199/2', 403, '' );
|
||||
}
|
||||
|
||||
/* if the site is offline, use the minimal layout */
|
||||
if ( ( !\IPS\Settings::i()->site_online and !\IPS\Member::loggedIn()->group['g_access_offline'] ) OR ( !\IPS\Member::loggedIn()->member_id AND !\IPS\Member::loggedIn()->group['g_view_board'] ) )
|
||||
|
||||
/* Display */
|
||||
$announcementHtml = \IPS\Theme::i()->getTemplate( 'system' )->announcement( $announcement );
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->sendOutput( $announcementHtml );
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=announcement&id=' . $announcement->id, NULL, 'announcement', $announcement->seo_title ), array(), 'loc_viewing_announcement', array( $announcement->title => FALSE ) );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( $announcement->title );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->announcement( $announcement );
|
||||
else
|
||||
{
|
||||
/* if the site is offline, use the minimal layout */
|
||||
if ( ( !\IPS\Settings::i()->site_online and !\IPS\Member::loggedIn()->group['g_access_offline'] ) OR ( !\IPS\Member::loggedIn()->member_id AND !\IPS\Member::loggedIn()->group['g_view_board'] ) )
|
||||
{
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=announcement&id=' . $announcement->id, NULL, 'announcement', $announcement->seo_title ), array(), 'loc_viewing_announcement', array( $announcement->title => FALSE ) );
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( $announcement->title );
|
||||
\IPS\Output::i()->output = $announcementHtml;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check permissions for linked content item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function permissionCheck()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->modPermission( 'can_manage_announcements' ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C185/1', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$url = \IPS\Http\Url::createFromString( \IPS\Request::i()->url, TRUE );
|
||||
}
|
||||
catch( \IPS\Http\Url\Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'unexpected_format' ) );
|
||||
}
|
||||
|
||||
/* Make sure this is a local URL */
|
||||
if( !$url->isInternal )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'not_local' ) );
|
||||
}
|
||||
|
||||
/* Get the definition */
|
||||
$furlDefinition = \IPS\Http\Url\Friendly::furlDefinition();
|
||||
|
||||
/* If we don't have a validate callback, we can return NULL */
|
||||
if ( !isset( $furlDefinition[ $url->seoTemplate ]['verify'] ) or !$furlDefinition[ $url->seoTemplate ]['verify'] )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'not_verified' ) );
|
||||
}
|
||||
|
||||
$class = $furlDefinition[ $url->seoTemplate ]['verify'];
|
||||
$item = $class::loadFromUrl( $url );
|
||||
|
||||
/* If the class does not have our method, return a not_verified status */
|
||||
if( !method_exists( $item, 'cannotViewGroups' ) )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'not_verified' ) );
|
||||
}
|
||||
|
||||
/* Get groups that cannot view the item */
|
||||
$groups = $item->cannotViewGroups();
|
||||
|
||||
if( !\count( $groups ) )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'all_permissions' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( array( 'html' => \IPS\Theme::i()->getTemplate( 'modcp', 'core', 'front' )->announcementGroupCheck( $groups ) ) );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -36,7 +36,7 @@ class _attachments extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Build Table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_attachments', \IPS\Http\Url::internal( 'app=core&module=system&controller=attachments', 'front', 'attachments' ), array( array( 'attach_member_id=?', \IPS\Member::loggedIn()->member_id ) ) );
|
||||
$table = new \IPS\core\Attachments\Table( 'core_attachments', \IPS\Http\Url::internal( 'app=core&module=system&controller=attachments', 'front', 'attachments' ), array( array( 'attach_member_id=?', \IPS\Member::loggedIn()->member_id ) ) );
|
||||
$table->include = array( 'attach_id', 'attach_location', 'attach_date', 'attach_file', 'attach_filesize', 'attach_is_image', 'attach_content', 'attach_hits' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate('myAttachments'), 'rows' );
|
||||
$table->joins = array();
|
||||
@@ -62,67 +62,4 @@ class _attachments extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('my_attachments') );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('myAttachments')->template( (string) $table, \IPS\Db::i()->select( 'SUM(attach_filesize)', 'core_attachments', array( 'attach_member_id=?', \IPS\Member::loggedIn()->member_id ) )->first(), \IPS\Db::i()->select( 'COUNT(*)', 'core_attachments', array( 'attach_member_id=?', \IPS\Member::loggedIn()->member_id ) )->first() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
/* Security check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
/* Load and check permission */
|
||||
try
|
||||
{
|
||||
$attachment = \IPS\Db::i()->select( '*', 'core_attachments', array( 'attach_id=?', \IPS\Request::i()->id ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C229/4', 404, '' );
|
||||
}
|
||||
|
||||
/* Check it belongs to us */
|
||||
if ( $attachment['attach_member_id'] !== \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C229/5', 403, '' );
|
||||
}
|
||||
|
||||
/* And we can delete it */
|
||||
if ( !\IPS\Member::loggedIn()->group['gbw_delete_attachments'] )
|
||||
{
|
||||
\IPS\core\extensions\core\EditorMedia\Attachment::getLocations( $attachment['attach_id'] );
|
||||
if ( count( \IPS\core\extensions\core\EditorMedia\Attachment::$locations[ $attachment['attach_id'] ] ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C229/8', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete */
|
||||
try
|
||||
{
|
||||
\IPS\File::get( 'core_Attachment', $attachment['attach_location'] )->delete();
|
||||
if ( $attachment['attach_thumb_location'] )
|
||||
{
|
||||
\IPS\File::get( 'core_Attachment', $attachment['attach_thumb_location'] )->delete();
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
\IPS\Db::i()->delete( 'core_attachments', array( 'attach_id=?', $attachment['attach_id'] ) );
|
||||
\IPS\Db::i()->delete( 'core_attachments_map', array( 'attachment_id=?', $attachment['attach_id'] ) );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=attachments', 'front', 'attachments' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -36,7 +36,7 @@ class _content extends \IPS\Dispatcher\Controller
|
||||
|
||||
$class = 'IPS\\' . implode( '\\', explode( '_', \IPS\Request::i()->content_class ) );
|
||||
|
||||
if ( ! class_exists( $class ) or ! in_array( 'IPS\Content', class_parents( $class ) ) )
|
||||
if ( ! class_exists( $class ) or ! \in_array( 'IPS\Content', class_parents( $class ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2S226/2', 404, '' );
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -29,6 +29,6 @@ class _designermode extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function missing()
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'theme_designers_mode_error_missing', FALSE, array( 'sprintf' => array( intval( \IPS\Request::i()->id ) ) ) ), "4C370/1", 500 );
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'theme_designers_mode_error_missing', FALSE, array( 'sprintf' => array( \intval( \IPS\Request::i()->id ) ) ) ), "4C370/1", 500 );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -78,8 +78,8 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
\IPS\Request::i()->height = $maxHeight;
|
||||
\IPS\Request::i()->width = floor( \IPS\Request::i()->height * $ratioW );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->image( \IPS\Request::i()->editorId, \IPS\Request::i()->width, \IPS\Request::i()->height, $maxWidth, $maxHeight, \IPS\Request::i()->float, \IPS\Request::i()->link, $ratioW, $ratioH, urldecode( \IPS\Request::i()->imageAlt ) );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->image( \IPS\Request::i()->editorId, \IPS\Request::i()->width, \IPS\Request::i()->height, $maxWidth, $maxHeight, \IPS\Request::i()->float, \IPS\Request::i()->link, $ratioW, $ratioH, urldecode( \IPS\Request::i()->imageAlt ), \IPS\Request::i()->editorUniqueId );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,28 +110,19 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
$url = \IPS\Http\Url::createFromString( \IPS\Request::i()->url, TRUE, TRUE );
|
||||
$embed = NULL;
|
||||
$error = NULL;
|
||||
$noEmbed = \IPS\Request::i()->noEmbed;
|
||||
|
||||
if ( ! empty( \IPS\Request::i()->embedLocalOnly ) )
|
||||
{
|
||||
$srcDomain = parse_url( \IPS\Settings::i()->base_url, PHP_URL_HOST );
|
||||
$lclDomain = parse_url( $url, PHP_URL_HOST );
|
||||
|
||||
/* This is via the ACP, so we will only allow internal embeds */
|
||||
if ( $srcDomain != $lclDomain )
|
||||
{
|
||||
$noEmbed = FALSE;
|
||||
$error = \IPS\Member::loggedIn()->language()->addToStack( 'embed__fail_cant_acp' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $noEmbed )
|
||||
|
||||
if ( !\IPS\Request::i()->noEmbed )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( \IPS\Request::i()->image )
|
||||
{
|
||||
\IPS\Text\Parser::isAllowedImageUrl( $url );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->image and \IPS\Request::i()->width and \IPS\Request::i()->height )
|
||||
{
|
||||
$embed = \IPS\Text\Parser::imageEmbed( $url, intval( \IPS\Request::i()->width ), intval( \IPS\Request::i()->height ) );
|
||||
$embed = \IPS\Text\Parser::imageEmbed( $url, \intval( \IPS\Request::i()->width ), \intval( \IPS\Request::i()->height ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -204,6 +195,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$emoji = ( \IPS\Settings::i()->emoji_style == 'disabled' or \IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') !== TRUE ) ? array() : json_decode( file_get_contents( \IPS\ROOT_PATH . '/applications/core/data/emoji.json' ), TRUE );
|
||||
|
||||
$setsToAdd = array();
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_emoticons', NULL, 'emo_set_position,emo_position' ) as $row )
|
||||
{
|
||||
$shortcode = ( \IPS\Settings::i()->emoji_shortcodes and preg_match( '/^:.*:$/', $row['typed'] ) );
|
||||
@@ -217,7 +209,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
$categoryName = '_default';
|
||||
}
|
||||
|
||||
$emoji[ $row['emo_set'] ][] = array(
|
||||
$setsToAdd[ $row['emo_set'] ][] = array(
|
||||
'code' => 'custom-' . $row['emo_set'] . '-' . $row['id'],
|
||||
'name' => $row['typed'],
|
||||
'skinTone' => false,
|
||||
@@ -229,6 +221,13 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
'width' => $row['width'],
|
||||
'height' => $row['height'],
|
||||
);
|
||||
}
|
||||
foreach ( $setsToAdd as $setKey => $emojiInSet )
|
||||
{
|
||||
$emoji[] = array(
|
||||
'category' => $setKey,
|
||||
'emoji' => $emojiInSet
|
||||
);
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $emoji );
|
||||
@@ -257,7 +256,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
/* Work out what tab we're on */
|
||||
if ( !\IPS\Request::i()->tab )
|
||||
{
|
||||
if( !count( $mediaSources ) )
|
||||
if( !\count( $mediaSources ) )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->myMedia( \IPS\Request::i()->editorId, $mediaSources, NULL, NULL, NULL );
|
||||
return;
|
||||
@@ -275,7 +274,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
/* Count how many we have */
|
||||
$count = $extension->count( \IPS\Member::loggedIn(), isset( \IPS\Request::i()->postKey ) ? \IPS\Request::i()->postKey : '', $search );
|
||||
|
||||
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
|
||||
$page = isset( \IPS\Request::i()->page ) ? \intval( \IPS\Request::i()->page ) : 1;
|
||||
|
||||
if( $page < 1 )
|
||||
{
|
||||
@@ -340,7 +339,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
$results = '';
|
||||
if ( mb_strlen( \IPS\Request::i()->input ) > 0 )
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', array( "name LIKE CONCAT( ?, '%' )", mb_strtolower( \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 ) ), 'name', 10 ) as $row )
|
||||
{
|
||||
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( \IPS\Member::constructFromData( $row ) );
|
||||
}
|
||||
@@ -348,4 +347,87 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->sendOutput( $results );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Languages supported by giphy
|
||||
* @see https://developers.giphy.com/docs/optional-settings/#language-support
|
||||
*/
|
||||
protected static $giphyLanguages = array( 'en', 'es', 'pt', 'id', 'fr', 'ar', 'tr', 'th', 'vi', 'hi', 'bn', 'da', 'fa', 'tl', 'fi',
|
||||
'de', 'it', 'ja', 'ru', 'ko', 'pl', 'nl', 'ro', 'hu', 'sv', 'cs', 'iw', 'ms', 'no', 'uk', 'zh-CN', 'zh-TW'
|
||||
);
|
||||
|
||||
/**
|
||||
* Get giphy images
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function giphy()
|
||||
{
|
||||
if ( \IPS\Settings::i()->giphy_enabled )
|
||||
{
|
||||
$limit = isset( \IPS\Request::i()->limit ) ? \IPS\Request::i()->limit : 30;
|
||||
$offset = isset( \IPS\Request::i()->offset ) ? \IPS\Request::i()->offset : 0;
|
||||
|
||||
$q = urlencode( \IPS\Request::i()->search );
|
||||
|
||||
/* Return the trending images if there's no search term */
|
||||
if ( !$q OR $q == '' )
|
||||
{
|
||||
$url = \IPS\Http\Url::external( "https://api.giphy.com/v1/gifs/trending" );
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::external( "https://api.giphy.com/v1/gifs/search" )->setQueryString( 'q', $q );
|
||||
}
|
||||
|
||||
$parameters = array(
|
||||
'api_key' => ( \IPS\Settings::i()->giphy_apikey ? \IPS\Settings::i()->giphy_apikey : \IPS\Settings::i()->giphy_apikey_default ),
|
||||
'limit' => $limit,
|
||||
'offset' => $offset
|
||||
);
|
||||
|
||||
$ourLocale = \IPS\Member::loggedIn()->language()->short;
|
||||
|
||||
if ( preg_match( '/^\w{2}[-_]\w{2}($|\.)/i',$ourLocale ) ) // This will only work for Unix-style locales
|
||||
{
|
||||
$langCode = \strtolower( \substr( $ourLocale, 0, 2 ) );
|
||||
|
||||
/* Giphy supports zh-CN and zh-TW, so we have to handle this one special */
|
||||
if( $langCode == 'zh' )
|
||||
{
|
||||
$langCode = \strtolower( \substr( $ourLocale, 0, 2 ) ) . '-' . \strtoupper( \substr( $ourLocale, 3, 2 ) );
|
||||
}
|
||||
|
||||
if( \in_array( $langCode, static::$giphyLanguages ) )
|
||||
{
|
||||
$parameters['lang'] = $langCode;
|
||||
}
|
||||
}
|
||||
|
||||
$url = $url->setQueryString($parameters);
|
||||
|
||||
if ( \IPS\Settings::i()->giphy_rating and \IPS\Settings::i()->giphy_rating !== 'x' )
|
||||
{
|
||||
$url = $url->setQueryString( 'rating', \IPS\Settings::i()->giphy_rating );
|
||||
}
|
||||
|
||||
$request = json_decode( $url->request()->get()->content, true );
|
||||
if ( isset( $request['message'] ) AND $request['message'] )
|
||||
{
|
||||
\IPS\Output::i()->json( array('error' => $request['message'] ) );
|
||||
}
|
||||
|
||||
$results = array( 'pagination' => $request['pagination'] );
|
||||
foreach ( $request['data'] as $row )
|
||||
{
|
||||
$results['images'][] = array(
|
||||
'thumb' => $row['images']['fixed_height_small']['url'],
|
||||
'url' => $row['images']['fixed_height']['url'],
|
||||
'title' => $row['title']
|
||||
);
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $results );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -31,11 +31,24 @@ class _facebook extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( ! \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=facebook' ) ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->addRef( \IPS\Http\Url::internal( 'app=core&module=system&controller=facebook' ) ) );
|
||||
}
|
||||
|
||||
/* Check the member has permission to manage promote settings */
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '3C396/1', 403, '' );
|
||||
}
|
||||
|
||||
$promote = \IPS\core\Promote::getPromoter( 'Facebook' );
|
||||
$facebook = $promote::getLoginHandler();
|
||||
|
||||
/* Required handler present and enabled? */
|
||||
if( $facebook === NULL )
|
||||
{
|
||||
\IPS\Output::i()->error( 'promote_facebook_setup_app', '3C396/2', 403, '' );
|
||||
}
|
||||
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=facebook' );
|
||||
|
||||
try
|
||||
@@ -48,7 +61,7 @@ class _facebook extends \IPS\Dispatcher\Controller
|
||||
'response_type' => 'code',
|
||||
'redirect_uri' => (string) \IPS\Http\Url::internal( 'oauth/callback/', 'none' ),
|
||||
'state' => $facebook->id . '-' . base64_encode( $url ) . '-' . \IPS\Session::i()->csrfKey . '-x',
|
||||
'scope' => 'manage_pages publish_pages publish_to_groups'
|
||||
'scope' => 'manage_pages publish_pages'
|
||||
) );
|
||||
|
||||
\IPS\Output::i()->redirect( $target );
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -282,7 +282,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
|
||||
try
|
||||
{
|
||||
if ( !in_array( \IPS\Request::i()->type, \IPS\core\Ignore::types() ) )
|
||||
if ( !\in_array( \IPS\Request::i()->type, \IPS\core\Ignore::types() ) )
|
||||
{
|
||||
throw new \OutOfRangeException( 'invalid_type' );
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -51,6 +51,6 @@ class _language extends \IPS\Dispatcher\Controller
|
||||
\IPS\Request::i()->setCookie( 'language', (int) \IPS\Request::i()->id );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Request::i()->referrer() ?: \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -22,6 +22,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _login extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* @brief Is this for displaying "content"? Affects if advertisements may be shown
|
||||
*/
|
||||
public $isContentPage = FALSE;
|
||||
|
||||
/**
|
||||
* Log In
|
||||
*
|
||||
@@ -39,7 +44,16 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' ) );
|
||||
|
||||
/* What's our referrer? */
|
||||
$postBeforeRegister = NULL;
|
||||
$ref = \IPS\Request::i()->ref;
|
||||
if ( !$ref and isset( \IPS\Request::i()->cookie['post_before_register'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$postBeforeRegister = \IPS\Db::i()->select( '*', 'core_post_before_registering', array( 'secret=?', \IPS\Request::i()->cookie['post_before_register'] ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e ){}
|
||||
}
|
||||
|
||||
/* Process */
|
||||
$error = NULL;
|
||||
@@ -47,24 +61,30 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( $success = $login->authenticate() )
|
||||
{
|
||||
if ( $ref and $ref = @base64_decode( $ref ) )
|
||||
if ( \IPS\Request::i()->referrer( FALSE, TRUE ) )
|
||||
{
|
||||
$ref = \IPS\Request::i()->referrer( FALSE, TRUE );
|
||||
}
|
||||
elseif ( $postBeforeRegister )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' or $ref->openRedirect() )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
$class = $postBeforeRegister['class'];
|
||||
$ref = $class::load( $postBeforeRegister['id'] )->url();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
elseif( !empty( $_SERVER['HTTP_REFERER'] ) )
|
||||
{
|
||||
$_ref = \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] );
|
||||
$ref = ( $_ref instanceof \IPS\Http\Url\Internal and ( !isset( $_ref->queryString['do'] ) or $_ref->queryString['do'] != 'validating' ) ) ? $_ref : \IPS\Http\Url::internal('');
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
$ref = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
if ( $success->mfa() )
|
||||
@@ -98,6 +118,9 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->login( $login, $ref, $error );
|
||||
|
||||
/* Don't cache for a short while to ensure sessions work */
|
||||
\IPS\Request::i()->setCookie( 'noCache', 1 );
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', NULL, 'login' ), array(), 'loc_logging_in' );
|
||||
}
|
||||
@@ -129,11 +152,11 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
/* Have we already done 2FA? */
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member, FALSE );
|
||||
$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 )
|
||||
{
|
||||
( new \IPS\Login\Success( $member, \IPS\Login\Handler::load( $_SESSION['processing2FA']['handler'] ), $_SESSION['processing2FA']['remember'], $_SESSION['processing2FA']['anonymous'] ) )->process();
|
||||
( new \IPS\Login\Success( $member, \IPS\Login\Handler::load( $_SESSION['processing2FA']['handler'] ), $_SESSION['processing2FA']['remember'], $_SESSION['processing2FA']['anonymous'], FALSE ) )->process();
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ), '', 303 );
|
||||
}
|
||||
|
||||
@@ -188,25 +211,13 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/* If successful (or if there's no way to reauthenticate which would only happen if a login handler has been deleted)) complete the link... */
|
||||
try
|
||||
{
|
||||
if ( $success = $login->authenticate() or ( !count( $login->usernamePasswordMethods() ) and !count( $login->buttonMethods() ) ) )
|
||||
if ( $success = $login->authenticate() or ( !\count( $login->usernamePasswordMethods() ) and !\count( $login->buttonMethods() ) ) )
|
||||
{
|
||||
$handler->completeLink( $member, $details['details'] );
|
||||
|
||||
unset( $_SESSION['linkAccounts'] );
|
||||
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
if ( $ref instanceof \IPS\Http\Url\Internal and !$ref->openRedirect() )
|
||||
{
|
||||
$destination = $ref;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
$destination = \IPS\Request::i()->referrer( FALSE, TRUE ) ?: \IPS\Http\Url::internal( '' );
|
||||
|
||||
$success = new \IPS\Login\Success( $member, $handler );
|
||||
if ( $success->mfa() )
|
||||
@@ -265,29 +276,8 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
|
||||
/* Do not allow the login_key to be re-used */
|
||||
if ( isset( \IPS\Request::i()->cookie['device_key'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$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();
|
||||
|
||||
/* 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"] );
|
||||
session_destroy();
|
||||
|
||||
/* Member sync callback */
|
||||
$member->memberSync( 'onLogout', array( $redirectUrl ) );
|
||||
/* Do it */
|
||||
\IPS\Login::logout( $redirectUrl );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $redirectUrl->setQueryString( '_fromLogout', 1 ) );
|
||||
@@ -312,7 +302,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/* Not logged in as admin? */
|
||||
if ( $admin->member_id != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( array( 'ref' => base64_encode( \IPS\Request::i()->url() ), '_err' => 'login_as_user_login' ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->addRef( (string) \IPS\Request::i()->url() )->setQueryString( '_err', 'login_as_user_login' ) );
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -22,6 +22,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* @brief Is this for displaying "content"? Affects if advertisements may be shown
|
||||
*/
|
||||
public $isContentPage = FALSE;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
@@ -51,7 +56,7 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( "lostpass", 'request_password' );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'bypassProfanity' => TRUE ), function( $val ){
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL ), function( $val ){
|
||||
if( !\IPS\Login::emailIsInUse( $val ) )
|
||||
{
|
||||
throw new \LogicException( 'lost_pass_no_email' );
|
||||
@@ -173,6 +178,9 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function validate()
|
||||
{
|
||||
/* Prevent the vid key from being exposed in referrers */
|
||||
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin" );
|
||||
|
||||
try
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'core_validating', array( 'vid=? AND member_id=? AND lost_pass=1', \IPS\Request::i()->vid, \IPS\Request::i()->mid ) )->first();
|
||||
@@ -184,8 +192,8 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Show form for new password */
|
||||
$form = new \IPS\Helpers\Form( "resetpass", 'save' );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'protect' => TRUE, 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'strengthMember' => \IPS\Member::load( \IPS\Request::i()->mid ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'protect' => TRUE, 'confirm' => 'password' ) ) );
|
||||
|
||||
/* Set new password */
|
||||
if ( $values = $form->values() )
|
||||
@@ -203,16 +211,19 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* 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 ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
$success = new \IPS\Login\Success( $member, \IPS\Login\Handler::findMethod( 'IPS\Login\Handler\Standard' ) );
|
||||
if ( $success->mfa() )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $success->member->member_id, 'anonymous' => $success->anonymous, 'remember' => $success->rememberMe, 'destination' => (string) \IPS\Http\Url::internal( '' ), 'handler' => $success->handler->id );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' )->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
$success->process();
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' )->setQueryString( '_fromLogin', 1 ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief marketplace
|
||||
* @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 Jul 2020
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* marketplace
|
||||
*/
|
||||
class _marketplace extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->member ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$token = \IPS\Db::i()->select( 'token', 'core_marketplace_tokens', array( 'id=?', \IPS\Request::i()->member ) )->first();
|
||||
if ( $token !== 'pending-' . \IPS\Request::i()->hash )
|
||||
{
|
||||
throw new \UnderflowException;
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_marketplace_tokens', array( 'token' => \IPS\Request::i()->access_token, 'expires_at' => time() + \IPS\Request::i()->expires_in ), array( 'id=?', \IPS\Request::i()->member ) );
|
||||
|
||||
echo 'OK';
|
||||
exit;
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
echo 'BAD_HASH';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'NO_MEMBER';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -36,7 +36,21 @@ class _markread extends \IPS\Dispatcher\Controller
|
||||
\IPS\Member::loggedIn()->markAllAsRead();
|
||||
}
|
||||
|
||||
/* Don't redirect to an external domain unless explicitly requested, and don't redirect back to ACP */
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ), 'core_site_marked_as_read' );
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't redirect to an external domain unless explicitly requested, and don't redirect back to ACP */
|
||||
$redirectTo = \IPS\Request::i()->referrer( FALSE, FALSE, 'front' ) ?: \IPS\Http\Url::internal( '' );
|
||||
|
||||
if ( $redirectTo === NULL )
|
||||
{
|
||||
$redirectTo = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $redirectTo, 'core_site_marked_as_read' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -60,21 +60,64 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
|
||||
$_tags = array();
|
||||
|
||||
/* Store the new meta tags */
|
||||
if( isset( \IPS\Request::i()->meta_tag_name ) AND is_array( \IPS\Request::i()->meta_tag_name ) )
|
||||
$metaTagNames = \IPS\Request::i()->meta_tag_name;
|
||||
$metaTagCustomNames = \IPS\Request::i()->meta_tag_name_other;
|
||||
$metaTagValues = \IPS\Request::i()->meta_tag_content;
|
||||
|
||||
/* Remove any default meta tags that have not been edited - don't save them permanently */
|
||||
if( isset( \IPS\Request::i()->defaultMetaTag ) )
|
||||
{
|
||||
foreach( \IPS\Request::i()->meta_tag_name as $k => $v )
|
||||
foreach( \IPS\Request::i()->defaultMetaTag as $k => $v )
|
||||
{
|
||||
if( $v AND ( $v != 'other' OR !empty( \IPS\Request::i()->meta_tag_name_other[ $k ] ) ) AND !isset( $_tags[ $v != 'other' ? $v : \IPS\Request::i()->meta_tag_name_other[ $k ] ] ) )
|
||||
if( ( $key = array_search( $k, $metaTagNames ) ) !== FALSE AND $metaTagValues[ $key ] == $v )
|
||||
{
|
||||
$_tags[ ( $v != 'other' ) ? $v : \IPS\Request::i()->meta_tag_name_other[ $k ] ] = \IPS\Request::i()->meta_tag_content[ $k ];
|
||||
unset( $metaTagNames[ $key ], $metaTagCustomNames[ $key ], $metaTagValues[ $key ] );
|
||||
}
|
||||
elseif( ( $key = array_search( $k, $metaTagCustomNames ) ) !== FALSE AND $metaTagValues[ $key ] == $v )
|
||||
{
|
||||
unset( $metaTagNames[ $key ], $metaTagCustomNames[ $key ], $metaTagValues[ $key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$save['meta_tags'] = json_encode( $_tags );
|
||||
/* If we asked to remove a default meta tag, store specially so we can do so */
|
||||
if( isset( \IPS\Request::i()->deleteDefaultMeta ) )
|
||||
{
|
||||
foreach( \IPS\Request::i()->deleteDefaultMeta as $v )
|
||||
{
|
||||
$_tags[ $v ] = NULL;
|
||||
|
||||
if( ( $key = array_search( $v, $metaTagNames ) ) !== FALSE )
|
||||
{
|
||||
unset( $metaTagNames[ $key ], $metaTagCustomNames[ $key ], $metaTagValues[ $key ] );
|
||||
}
|
||||
elseif( ( $key = array_search( $v, $metaTagCustomNames ) ) !== FALSE )
|
||||
{
|
||||
unset( $metaTagNames[ $key ], $metaTagCustomNames[ $key ], $metaTagValues[ $key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the new meta tags */
|
||||
if( \is_array( $metaTagNames ) )
|
||||
{
|
||||
foreach( $metaTagNames as $k => $v )
|
||||
{
|
||||
if( $v AND ( $v != 'other' OR !empty( $metaTagCustomNames[ $k ] ) ) AND !isset( $_tags[ $v != 'other' ? $v : $metaTagCustomNames[ $k ] ] ) )
|
||||
{
|
||||
$_tags[ ( $v != 'other' ) ? $v : $metaTagCustomNames[ $k ] ] = $metaTagValues[ $k ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the meta tags, if there are any to save */
|
||||
if( \count( $_tags ) OR \IPS\Request::i()->meta_tag_title != '' )
|
||||
{
|
||||
$save['meta_tags'] = json_encode( $_tags );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_seo_meta', $save );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->insert( 'core_seo_meta', $save );
|
||||
unset( \IPS\Data\Store::i()->metaTags );
|
||||
|
||||
/* Send back to the page */
|
||||
@@ -117,4 +160,148 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'meta_editor_no_acpperm', '3C155/2', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the web manifest file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manifest()
|
||||
{
|
||||
if( \IPS\IN_DEV === FALSE AND isset( \IPS\Data\Store::i()->manifest ) )
|
||||
{
|
||||
$output = \IPS\Data\Store::i()->manifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
$manifest = json_decode( \IPS\Settings::i()->manifest_details, TRUE );
|
||||
|
||||
$output = array(
|
||||
'scope' => '/',
|
||||
'name' => \IPS\Settings::i()->board_name,
|
||||
'theme_color' => \IPS\Theme::i()->settings['header']
|
||||
);
|
||||
|
||||
foreach( $manifest as $k => $v )
|
||||
{
|
||||
if( $v )
|
||||
{
|
||||
$output[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
$homeScreen = json_decode( \IPS\Settings::i()->icons_homescreen, TRUE ) ?? array();
|
||||
|
||||
foreach( $homeScreen as $k => $v )
|
||||
{
|
||||
if( mb_strpos( $k, 'android' ) !== FALSE )
|
||||
{
|
||||
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']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->mobile_app_prompt )
|
||||
{
|
||||
if ( !isset( $output['short_name'] ) )
|
||||
{
|
||||
$output['short_name'] = \IPS\Settings::i()->board_name;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
$cacheHeaders = ( \IPS\IN_DEV !== true AND \IPS\Theme::designersModeEnabled() !== true ) ? \IPS\Output::getCacheHeaders( time(), 86400 ) : array();
|
||||
|
||||
\IPS\Output::i()->sendOutput( json_encode( $output, JSON_PRETTY_PRINT ), 200, 'application/manifest+json', $cacheHeaders );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the IE browserconfig.xml file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function iebrowserconfig()
|
||||
{
|
||||
if( \IPS\IN_DEV === FALSE AND isset( \IPS\Data\Store::i()->iebrowserconfig ) )
|
||||
{
|
||||
$output = \IPS\Data\Store::i()->iebrowserconfig;
|
||||
}
|
||||
else
|
||||
{
|
||||
$manifest = json_decode( \IPS\Settings::i()->manifest_details, TRUE );
|
||||
|
||||
/* Init */
|
||||
$xml = new \XMLWriter;
|
||||
$xml->openMemory();
|
||||
$xml->setIndent( TRUE );
|
||||
$xml->startDocument( '1.0', 'UTF-8' );
|
||||
$xml->startElement( 'browserconfig' );
|
||||
$xml->startElement( 'msapplication' );
|
||||
$xml->startElement( 'tile' );
|
||||
|
||||
if( isset( $manifest['theme_color'] ) AND $manifest['theme_color'] )
|
||||
{
|
||||
$xml->writeElement( 'TileColor', $manifest['theme_color'] );
|
||||
}
|
||||
|
||||
$homeScreen = json_decode( \IPS\Settings::i()->icons_homescreen, TRUE ) ?? array();
|
||||
|
||||
foreach( $homeScreen as $k => $v )
|
||||
{
|
||||
if( mb_strpos( $k, 'msapplication' ) !== FALSE AND $k !== 'msapplication-TileImage' )
|
||||
{
|
||||
$file = \IPS\File::get( 'core_Icons', $v['url'] );
|
||||
|
||||
$xml->startElement( str_replace( 'msapplication-', '', $k ) );
|
||||
$xml->startAttribute( 'src' );
|
||||
$xml->text( (string) $file->url );
|
||||
$xml->endAttribute();
|
||||
$xml->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
$xml->endElement();
|
||||
$xml->endElement();
|
||||
$xml->endElement();
|
||||
$xml->endDocument();
|
||||
|
||||
$output = $xml->outputMemory();
|
||||
|
||||
\IPS\Data\Store::i()->iebrowserconfig = $output;
|
||||
}
|
||||
|
||||
$cacheHeaders = ( \IPS\IN_DEV !== true AND \IPS\Theme::designersModeEnabled() !== true ) ? \IPS\Output::getCacheHeaders( time(), 86400 ) : array();
|
||||
|
||||
\IPS\Output::i()->sendOutput( $output, 200, 'application/xml', $cacheHeaders );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -44,8 +44,8 @@ class _moderation extends \IPS\Dispatcher\Controller
|
||||
|
||||
$actions = explode( ',', \IPS\Settings::i()->spm_option );
|
||||
|
||||
/* Redirect to the users profile if we're deleting the content to avoid that the moderator sees a 404 error message */
|
||||
if ( in_array( 'delete', $actions ) )
|
||||
/* Redirect to the users profile if we're deleting the content to avoid that the moderator sees a 404 error message (unless soft delete is enabled) */
|
||||
if ( \in_array( 'delete', $actions ) AND !( \IPS\Member::loggedIn()->modPermission('can_manage_deleted_content') AND \IPS\Settings::i()->dellog_retention_period ) )
|
||||
{
|
||||
$redirectTarget = $member->url();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -31,6 +31,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2C154/2', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_system.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/notification_settings.css' ) );
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/notification_settings_responsive.css' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +56,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
$notifications = $table->getRows();
|
||||
|
||||
\IPS\Db::i()->update( 'core_notifications', array( 'read_time' => time() ), array( 'member=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
\IPS\Db::i()->update( 'core_notifications', array( 'read_time' => time() ), array( '`member`=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
\IPS\Member::loggedIn()->recountNotifications();
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
@@ -65,98 +72,162 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Options
|
||||
* Options: Dispatcher
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function options()
|
||||
{
|
||||
/* Check we're logged in */
|
||||
$this->_checkLoggedIn();
|
||||
|
||||
/* Build form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'allow_admin_mails', \IPS\Member::loggedIn()->allow_admin_mails ) );
|
||||
|
||||
$_autoTrack = array();
|
||||
if( \IPS\Member::loggedIn()->auto_follow['content'] )
|
||||
{
|
||||
$_autoTrack[] = 'content';
|
||||
}
|
||||
if( \IPS\Member::loggedIn()->auto_follow['comments'] )
|
||||
{
|
||||
$_autoTrack[] = 'comments';
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'auto_track', $_autoTrack, FALSE, array( 'options' => array( 'content' => 'auto_track_content', 'comments' => 'auto_track_comments' ), 'multiple' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'auto_track_type', \IPS\Member::loggedIn()->auto_follow['method'] ?: 'immediate', FALSE, array( 'options' => array(
|
||||
'immediate' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_immediate'),
|
||||
'daily' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_daily'),
|
||||
'weekly' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly'),
|
||||
'none' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_none')
|
||||
) ), NULL, NULL, NULL, 'auto_track_type' ) );
|
||||
/* Changed in 4.1: since email_notifications_once is new, combined show_pm_popup in and made a checkbox set for better organization */
|
||||
$notificationPrefValues = array();
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['show_pm_popup'] )
|
||||
{
|
||||
$notificationPrefValues[] = 'show_pm_popup';
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['email_notifications_once'] )
|
||||
{
|
||||
$notificationPrefValues[] = 'email_notifications_once';
|
||||
}
|
||||
if ( !\IPS\Member::loggedIn()->members_bitoptions['disable_notification_sounds'] )
|
||||
{
|
||||
$notificationPrefValues[] = 'enable_notification_sounds';
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'notification_prefs', $notificationPrefValues, FALSE, array( 'options' => array( 'show_pm_popup' => 'show_pm_popup', 'email_notifications_once' => 'email_notifications_once', 'enable_notification_sounds' => 'enable_notification_sounds' ), 'multiple' => TRUE ) ) );
|
||||
$form->addMatrix( 'notifications', \IPS\Notification::buildMatrix( \IPS\Member::loggedIn() ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
/* Init breadcrumb */
|
||||
$extensions = \IPS\Application::allExtensions( 'core', 'Notifications' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications', 'front', 'notifications' ), \IPS\Member::loggedIn()->language()->addToStack('notifications') );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options', 'front', 'notifications_options' ), \IPS\Member::loggedIn()->language()->addToStack('options') );
|
||||
|
||||
/* Are we viewing a particular type? */
|
||||
if ( isset( \IPS\Request::i()->type ) and array_key_exists( \IPS\Request::i()->type, $extensions ) )
|
||||
{
|
||||
/* Log if admin mail setting is changed */
|
||||
if ( \IPS\Member::loggedIn()->allow_admin_mails !== $values['allow_admin_mails'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'admin_mails', array( 'enabled' => $values['allow_admin_mails'] ) );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->allow_admin_mails = $values['allow_admin_mails'];
|
||||
\IPS\Member::loggedIn()->auto_track = json_encode( array(
|
||||
'content' => ( is_array( $values['auto_track'] ) AND in_array( 'content', $values['auto_track'] ) ) ? 1 : 0,
|
||||
'comments' => ( is_array( $values['auto_track'] ) AND in_array( 'comments', $values['auto_track'] ) ) ? 1 : 0,
|
||||
'method' => $values['auto_track_type']
|
||||
) );
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['show_pm_popup'] = ( is_array( $values['notification_prefs'] ) AND in_array( 'show_pm_popup', $values['notification_prefs'] ) ) ? 1 : 0;
|
||||
\IPS\Member::loggedIn()->members_bitoptions['email_notifications_once'] = ( is_array( $values['notification_prefs'] ) AND in_array( 'email_notifications_once', $values['notification_prefs'] ) ) ? 1 : 0;
|
||||
\IPS\Member::loggedIn()->members_bitoptions['disable_notification_sounds'] = ( is_array( $values['notification_prefs'] ) AND in_array( 'enable_notification_sounds', $values['notification_prefs'] ) ) ? 0 : 1;
|
||||
|
||||
\IPS\Notification::saveMatrix( \IPS\Member::loggedIn(), $values );
|
||||
|
||||
/* Refetch config to see if inline report center notification is set. We have to do this because if toggling report center
|
||||
option is disabled but inline is forced on by the admin, the setting won't be included in the $values array but the saveMatrix()
|
||||
method will automatically set it and calling notificationsConfiguration() will pull the data directly from the db. */
|
||||
$config = \IPS\Member::loggedIn()->notificationsConfiguration();
|
||||
|
||||
if ( isset( $config['report_center'] ) and !in_array( 'inline', $config['report_center'] ) )
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_bitoptions['no_report_count'] = TRUE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( "notifications__" . \IPS\Request::i()->type );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( "notifications__" . \IPS\Request::i()->type ) );
|
||||
return $this->_optionsType( \IPS\Request::i()->type, $extensions[ \IPS\Request::i()->type ] );
|
||||
}
|
||||
|
||||
/* Nope, viewing the index */
|
||||
else
|
||||
{
|
||||
return $this->_optionsIndex( $extensions );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options: Index
|
||||
*
|
||||
* @param array $extensions The extensions
|
||||
* @return void
|
||||
*/
|
||||
protected function _optionsIndex( $extensions )
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('notification_options');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('system')->notificationSettingsIndex( \IPS\Notification::membersOptionCategories( \IPS\Member::loggedIn(), $extensions ) );
|
||||
\IPS\Output::i()->globalControllers[] = 'core.front.system.notificationSettings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Options: Index
|
||||
*
|
||||
* @param string $extensionKey The extension key
|
||||
* @param object $extension The extension
|
||||
* @return void
|
||||
*/
|
||||
protected function _optionsType( $extensionKey, $extension )
|
||||
{
|
||||
$form = \IPS\Notification::membersTypeForm( \IPS\Member::loggedIn(), $extension );
|
||||
if ( $form === TRUE )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Member::loggedIn()->notificationsConfiguration = NULL;
|
||||
$categories = \IPS\Notification::membersOptionCategories( \IPS\Member::loggedIn(), array( $extensionKey => $extension ) );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate('system')->notificationSettingsIndexRowDetails( $extensionKey, $categories[ $extensionKey ] ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_bitoptions['no_report_count'] = FALSE;
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options', 'front', 'notifications_options' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options', 'front', 'notifications_options' ), 'saved' );
|
||||
}
|
||||
elseif ( $form )
|
||||
{
|
||||
$form->class = 'ipsForm_vertical';
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_system.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/notification_settings.css' ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'system' ), 'notificationsSettings' ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('notification_options');
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications', 'front', 'notifications' ), \IPS\Member::loggedIn()->language()->addToStack('notifications') );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('options') );
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
$form->actionButtons = array();
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate('system')->notificationSettingsType( \IPS\Member::loggedIn()->language()->addToStack("notifications__{$extensionKey}"), $form, TRUE ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('system')->notificationSettingsType( \IPS\Member::loggedIn()->language()->addToStack("notifications__{$extensionKey}"), $form, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable Sounds
|
||||
*
|
||||
* @param array $extensions The extensions
|
||||
* @return void
|
||||
*/
|
||||
protected function sounds()
|
||||
{
|
||||
$this->_checkLoggedIn();
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['disable_notification_sounds'] = ( \IPS\Request::i()->enable ? false : true );
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'ok' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options', 'front', 'notifications_options' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop receiving all notifications to a particular method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function disable()
|
||||
{
|
||||
$this->_checkLoggedIn();
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'Notifications' ) as $extension )
|
||||
{
|
||||
$options = \IPS\Notification::availableOptions( \IPS\Member::loggedIn(), $extension );
|
||||
foreach ( $options as $option )
|
||||
{
|
||||
if ( $option['type'] === 'standard' )
|
||||
{
|
||||
$value = array();
|
||||
foreach ( $option['options'] as $k => $optionDetails )
|
||||
{
|
||||
if ( ( $optionDetails['editable'] and $k !== \IPS\Request::i()->type and $optionDetails['value'] ) or ( !$optionDetails['editable'] and $optionDetails['value'] ) )
|
||||
{
|
||||
$value[] = $k;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $option['notificationTypes'] as $notificationKey )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'core_notification_preferences', array(
|
||||
'member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'notification_key' => $notificationKey,
|
||||
'preference' => implode( ',', $value )
|
||||
), TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( method_exists( $extension, 'disableExtra' ) )
|
||||
{
|
||||
$extension::disableExtra( \IPS\Member::loggedIn(), \IPS\Request::i()->type );
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'ok' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options', 'front', 'notifications_options' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +307,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$thing = NULL;
|
||||
try
|
||||
{
|
||||
if ( in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
if ( \in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'follow_thing', FALSE, array( 'sprintf' => array( $thing->_title ) ) );
|
||||
@@ -312,7 +383,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$type = 'follower_content';
|
||||
}
|
||||
elseif ( $class == 'IPS\Member\Club' or in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
elseif ( $class == 'IPS\Member\Club' or \in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
{
|
||||
$type = 'new_comment';
|
||||
}
|
||||
@@ -323,11 +394,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$notificationConfiguration = \IPS\Member::loggedIn()->notificationsConfiguration();
|
||||
$notificationConfiguration = isset( $notificationConfiguration[ $type ] ) ? $notificationConfiguration[ $type ] : array();
|
||||
$lang = 'follow_type_immediate';
|
||||
if ( in_array( 'email', $notificationConfiguration ) and in_array( 'inline', $notificationConfiguration ) )
|
||||
if ( \in_array( 'email', $notificationConfiguration ) and \in_array( 'inline', $notificationConfiguration ) )
|
||||
{
|
||||
$lang = 'follow_type_immediate_inline_email';
|
||||
}
|
||||
elseif ( in_array( 'email', $notificationConfiguration ) )
|
||||
elseif ( \in_array( 'email', $notificationConfiguration ) )
|
||||
{
|
||||
$lang = 'follow_type_immediate_email';
|
||||
}
|
||||
@@ -339,11 +410,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( empty( $notificationConfiguration ) )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ $lang . '_desc' ] = \IPS\Member::loggedIn()->language()->addToStack( 'follow_type_immediate_none', FALSE ) . ' <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>';
|
||||
\IPS\Member::loggedIn()->language()->words[ $lang . '_desc' ] = \IPS\Member::loggedIn()->language()->addToStack( 'follow_type_immediate_none', FALSE ) . ' <a href="' . \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options&type=core_Content', 'front', 'notifications_options' ) . '">' . \IPS\Member::loggedIn()->language()->addToStack( 'notification_options', FALSE ) . '</a>';
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ $lang . '_desc' ] = '<a href="' . \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options&type=' . $type, 'front', 'notifications_options' ) . '">' . \IPS\Member::loggedIn()->language()->addToStack( 'follow_type_immediate_change', FALSE ) . '</a>';
|
||||
\IPS\Member::loggedIn()->language()->words[ $lang . '_desc' ] = '<a href="' . \IPS\Http\Url::internal( 'app=core&module=system&controller=notifications&do=options&type=core_Content', 'front', 'notifications_options' ) . '">' . \IPS\Member::loggedIn()->language()->addToStack( 'follow_type_immediate_change', FALSE ) . '</a>';
|
||||
}
|
||||
|
||||
/* Build form */
|
||||
@@ -368,7 +439,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$options['none'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_no_notification');
|
||||
}
|
||||
|
||||
if ( count( $options ) > 1 )
|
||||
if ( \count( $options ) > 1 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'follow_type', $current ? $current['follow_notify_freq'] : NULL, TRUE, array(
|
||||
'options' => $options,
|
||||
@@ -382,12 +453,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$form->hiddenValues[ $k ] = $v;
|
||||
if ( empty( $notificationConfiguration ) )
|
||||
{
|
||||
$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>', '', FALSE );
|
||||
$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
|
||||
{
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack( $v ) . '<br>' . \IPS\Member::loggedIn()->language()->addToStack( $lang . '_desc' ), '', FALSE );
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack( $v ) . '<br>' . \IPS\Member::loggedIn()->language()->addToStack( $lang . '_desc' ), 'ipsPadding:none', FALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,7 +467,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
) ) );
|
||||
if ( $current )
|
||||
{
|
||||
$form->addButton( 'unfollow', 'link', \IPS\Http\Url::internal( "app=core&module=system§ion=notifications&do=unfollow&id={$current['follow_id']}&follow_app={$current['follow_app']}&follow_area={$current['follow_area']}" )->csrf(), 'ipsButton ipsButton_negative ipsPos_right', array('data-action' => 'unfollow') );
|
||||
$unfollowUrl = \IPS\Http\Url::internal( "app=core&module=system&controller=notifications&do=unfollow&id={$current['follow_id']}&follow_app={$current['follow_app']}&follow_area={$current['follow_area']}" )->csrf();
|
||||
if ( method_exists( $thing, 'url' ) AND $thing->url() )
|
||||
{
|
||||
$unfollowUrl = $unfollowUrl->addRef( (string) $thing->url() );
|
||||
}
|
||||
$form->addButton( 'unfollow', 'link', $unfollowUrl, 'ipsButton ipsButton_link ipsPos_left ipsButton_narrow', array('data-action' => 'unfollow') );
|
||||
}
|
||||
|
||||
/* Handle submissions */
|
||||
@@ -426,6 +502,9 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
\IPS\Db::i()->insert( 'core_follow', $save );
|
||||
}
|
||||
|
||||
/* Remove cached */
|
||||
\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 ) ) );
|
||||
|
||||
/* Also follow all nodes if following club */
|
||||
if( $class == "IPS\Member\Club" )
|
||||
{
|
||||
@@ -473,11 +552,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'system', 'core' ) ), 'followForm' ) );
|
||||
$output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'system', 'core' ), 'followForm' ) );
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -500,80 +579,36 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$follow = \IPS\Db::i()->select( '*', 'core_follow', array( 'follow_id=? AND follow_member_id=?', \IPS\Request::i()->id, \IPS\Member::loggedIn()->member_id ) )->first();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'cant_find_unfollow', '2C154/D', 404, '' );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', \IPS\Request::i()->id, \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
/* Get class */
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
elseif( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
\IPS\Db::i()->delete( 'core_follow_count_cache', array( 'id=? AND class=?', $follow['follow_rel_id'], 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) ) );
|
||||
|
||||
/* If we are unfollowing a club, unfollow all of its nodes */
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = NULL;
|
||||
foreach ( \IPS\Application::load( \IPS\Request::i()->follow_app )->extensions( 'core', 'ContentRouter' ) as $ext )
|
||||
{
|
||||
foreach ( $ext->classes as $classname )
|
||||
{
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
}
|
||||
if( isset( $classname::$containerFollowClasses ) )
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
{
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
if ( $class != "IPS\Member" )
|
||||
try
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( $follow['follow_rel_id'] );
|
||||
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . \IPS\Member::loggedIn()->member_id ), \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
}
|
||||
else if( !in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
{
|
||||
$thing = $class::load( $follow['follow_rel_id'] );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
}
|
||||
|
||||
/* Unfollow club areas */
|
||||
if( $class == "IPS\Member\Club" )
|
||||
{
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . \IPS\Member::loggedIn()->member_id ), \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
@@ -582,7 +617,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Request::i()->referrer() ?: \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,15 +631,20 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$perPage = 50;
|
||||
$thisPage = isset( \IPS\Request::i()->followerPage ) ? \IPS\Request::i()->followerPage : 1;
|
||||
$thisPage = ( $thisPage > 0 ) ? $thisPage : 1;
|
||||
|
||||
if( !\IPS\Request::i()->follow_app OR !\IPS\Request::i()->follow_area )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C154/E', 404, '' );
|
||||
}
|
||||
|
||||
/* Get class */
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
$class = 'IPS\Member';
|
||||
}
|
||||
else if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
$class = 'IPS\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -621,34 +661,38 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$anonymous = 0;
|
||||
try
|
||||
{
|
||||
if ( in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
if ( \in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
{
|
||||
$classname = $class::$contentItemClass;
|
||||
$containerClass = $class;
|
||||
$thing = $containerClass::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
$followers = $classname::containerFollowers( $thing, $classname::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $classname::containerFollowers( $thing, $classname::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$followersCount = $classname::containerFollowerCount( $thing );
|
||||
$anonymous = $classname::containerFollowerCount( $thing, $classname::FOLLOW_ANONYMOUS );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class == "IPS\Member\Club" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
$followers = $thing->followers( $class::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $thing->followers( $class::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$followersCount = $thing->followersCount();
|
||||
$anonymous = $thing->followersCount( $class::FOLLOW_ANONYMOUS );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
$followers = $thing->followers( $class::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $thing->followers( $class::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$followersCount = $thing->followersCount();
|
||||
$anonymous = $thing->followersCount( $class::FOLLOW_ANONYMOUS );
|
||||
$title = $thing->mapped('title');
|
||||
}
|
||||
else
|
||||
{
|
||||
$thing = $class::load( \IPS\Request::i()->follow_id );
|
||||
$followers = $thing->followers( $class::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $thing->followers( $class::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$followersCount = $thing->followersCount();
|
||||
$anonymous = $thing->followersCount( $class::FOLLOW_ANONYMOUS );
|
||||
$title = $thing->name;
|
||||
}
|
||||
}
|
||||
@@ -664,17 +708,167 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system§ion=notifications&do=followers&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id . "&_infScroll=1" );
|
||||
$removeAllUrl = \IPS\Http\Url::internal( "app=core&module=system§ion=notifications&do=removeFollowers&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id )->csrf();
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system&controller=notifications&do=followers&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id . "&_infScroll=1" );
|
||||
$removeAllUrl = \IPS\Http\Url::internal( "app=core&module=system&controller=notifications&do=removeFollowers&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id )->csrf();
|
||||
if ( method_exists( $thing, 'url' ) AND $thing->url() )
|
||||
{
|
||||
$removeAllUrl = $removeAllUrl->addRef( (string) $thing->url() );
|
||||
}
|
||||
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $url, ceil( $followers->count( TRUE ) / $perPage ), $thisPage, $perPage, FALSE, 'followerPage' );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $url, ceil( $followersCount / $perPage ), $thisPage, $perPage, FALSE, 'followerPage' );
|
||||
|
||||
/* Instruct bots not to index this page */
|
||||
\IPS\Output::i()->metaTags['robots'] = 'noindex';
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('item_followers', FALSE, array( 'sprintf' => array( $title ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( $thing->url(), $title );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('who_follows_this') );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->followers( $url, $pagination, $followers, $anonymous, $removeAllUrl );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfollow from email
|
||||
* If we're logged in, we can send them right to the normal follow form.
|
||||
* Otherwise, they get a special guest page using the gkey as an authentication key.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function unfollowFromEmail()
|
||||
{
|
||||
/* Logged in? */
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
/* Go to the normal page */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=notifications&do=follow&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id ) );
|
||||
}
|
||||
|
||||
if ( ! empty( \IPS\Request::i()->gkey ) )
|
||||
{
|
||||
list( $followKey, $memberKey ) = explode( '-', \IPS\Request::i()->gkey );
|
||||
/* Do we follow it? */
|
||||
try
|
||||
{
|
||||
$current = \IPS\Db::i()->select( '*', 'core_follow', array( 'MD5( CONCAT_WS( \';\', follow_app, follow_area, follow_rel_id, follow_member_id, follow_added ) )=?', $followKey ) )->first();
|
||||
|
||||
/* Already no subs? */
|
||||
if ( $current['follow_notify_freq'] === 'none' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'follow_guest_not_notified', '2C154/C', 404, '' );
|
||||
}
|
||||
|
||||
$member = \IPS\Member::load( $current['follow_member_id'] );
|
||||
|
||||
if ( md5( $member->email . ';' . $member->ip_address . ';' . $member->joined->getTimestamp() ) != $memberKey )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
|
||||
/* Get class */
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
elseif( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area );
|
||||
}
|
||||
if ( !class_exists( $class ) )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
|
||||
if ( \in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
{
|
||||
$classname = $class::$contentItemClass;
|
||||
$containerClass = $class;
|
||||
$thing = $containerClass::load( \IPS\Request::i()->follow_id );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class == "IPS\Member\Club" )
|
||||
{
|
||||
$thing = $class::load( \IPS\Request::i()->follow_id );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::load( \IPS\Request::i()->follow_id );
|
||||
$title = $thing->mapped('title');
|
||||
}
|
||||
else
|
||||
{
|
||||
$thing = $class::load( \IPS\Request::i()->follow_id );
|
||||
$title = $thing->name;
|
||||
}
|
||||
|
||||
/* Grab a count */
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_follow', array( 'follow_member_id=? and follow_notify_freq != ?', $member->member_id, 'none' ) )->first();
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'unfollowFromEmail', 'update_follow' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
|
||||
if ( $count == 1 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'guest_unfollow_single', 'single', FALSE, array( 'disabled' => true ) ) );
|
||||
\IPS\Member::loggedIn()->language()->words['guest_unfollow_single'] = \IPS\Member::loggedIn()->language()->addToStack('follow_guest_unfollow_thing', FALSE, array( 'sprintf' => array( $title ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'guest_unfollow_choice', 'single', FALSE, array(
|
||||
'options' => array(
|
||||
'single' => \IPS\Member::loggedIn()->language()->addToStack('follow_guest_unfollow_thing', FALSE, array( 'sprintf' => array( $title ) ) ),
|
||||
'all' => \IPS\Member::loggedIn()->language()->addToStack('follow_guest_unfollow_all', FALSE, array( 'pluralize' => array( $count ) ) ),
|
||||
),
|
||||
'descriptions' => array(
|
||||
'single' => \IPS\Member::loggedIn()->language()->addToStack('follow_guest_unfollow_thing_desc'),
|
||||
'all' => \IPS\Member::loggedIn()->language()->addToStack('follow_guest_unfollow_all_desc', FALSE, array( 'sprintf' => array( base64_encode( \IPS\Http\Url::internal( "app=core&module=system&controller=followed" ) ) ) ) )
|
||||
)
|
||||
) ) );
|
||||
}
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if ( $values['guest_unfollow_choice'] == 'single' or isset( $values['guest_unfollow_single'] ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_follow', array( 'follow_notify_freq' => 'none' ), array( 'follow_id=? AND follow_member_id=?', $current['follow_id'], $member->member_id ) );
|
||||
|
||||
/* Unfollow club areas */
|
||||
if ( $class == "IPS\Member\Club" )
|
||||
{
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->update( 'core_follow', array( 'follow_notify_freq' => 'none' ), array( 'follow_id=? AND follow_member_id=?', md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . $member->member_id ), $member->member_id ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_follow', array( 'follow_notify_freq' => 'none' ), array( 'follow_member_id=?', $member->member_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->unfollowFromEmail( $title, $member, $form, ! isset( \IPS\Request::i()->guest_unfollow_choice ) ? FALSE : \IPS\Request::i()->guest_unfollow_choice );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('follow_guest_unfollow_thing', FALSE, array( 'sprintf' => array( $title ) ) );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'follow_guest_key_not_found', '2C154/B', 404, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Follow button
|
||||
@@ -705,7 +899,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$thing = NULL;
|
||||
try
|
||||
{
|
||||
if ( in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
if ( \in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
{
|
||||
$classname = $class::$contentItemClass;
|
||||
$containerClass = $class;
|
||||
@@ -715,12 +909,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
else if ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
$count = $thing->followers()->count( TRUE );
|
||||
$count = $thing->followersCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
$thing = $class::load( \IPS\Request::i()->follow_id );
|
||||
$count = $thing->followers()->count( TRUE );
|
||||
$count = $thing->followersCount();
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
@@ -784,7 +978,9 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
\IPS\Session::i()->modLog( 'modlog__item_follow_removed', array( \IPS\Request::i()->follow_app => FALSE, \IPS\Request::i()->follow_area=> FALSE, \IPS\Request::i()->follow_id => FALSE ) );
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ), 'followers_removed' );
|
||||
\IPS\Output::i()->redirect( \IPS\Request::i()->referrer() ?: \IPS\Http\Url::internal( '' ), 'followers_removed' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Pixabay AJAX functions 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 12 Jan 2020
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor AJAX functions Controller
|
||||
*/
|
||||
class _pixabay extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Show the dialog window
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
if ( \IPS\Settings::i()->pixabay_enabled )
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate( 'system' )->pixabay( \IPS\Request::i()->uploader );
|
||||
\IPS\Output::i()->sendOutput( $output );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search pixabay
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function search()
|
||||
{
|
||||
if ( \IPS\Settings::i()->pixabay_enabled )
|
||||
{
|
||||
$limit = isset( \IPS\Request::i()->limit ) ? \IPS\Request::i()->limit : 20;
|
||||
$offset = isset( \IPS\Request::i()->offset ) ? \IPS\Request::i()->offset : 0;
|
||||
$query = isset( \IPS\Request::i()->search ) ? \IPS\Request::i()->search : '';
|
||||
$url = \IPS\Http\Url::external( "https://pixabay.com/api/" );
|
||||
|
||||
$parameters = array(
|
||||
'key' => \IPS\Settings::i()->pixabay_apikey,
|
||||
'image_type' => 'photo',
|
||||
'per_page' => 20,
|
||||
'page' => ( $offset ) ? ceil( $offset / 20 ) + 1 : 1
|
||||
);
|
||||
|
||||
$parameters['q'] = urlencode( $query );
|
||||
$cacheKey = 'pixabay_' . md5( json_encode( $parameters ) );
|
||||
|
||||
try
|
||||
{
|
||||
$request = \IPS\Data\Cache::i()->getWithExpire( $cacheKey, TRUE );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$url = $url->setQueryString($parameters);
|
||||
$request = json_decode( $url->request()->get()->content, true );
|
||||
|
||||
\IPS\Data\Cache::i()->storeWithExpire( $cacheKey, $request, \IPS\DateTime::create()->add( new \DateInterval('P1D') ), TRUE );
|
||||
}
|
||||
|
||||
if ( isset( $request['message'] ) AND $request['message'] )
|
||||
{
|
||||
\IPS\Output::i()->json( array('error' => $request['message'] ) );
|
||||
}
|
||||
|
||||
$results = array( 'pagination' => array( 'total_count' => $request['total'] ) );
|
||||
foreach ( $request['hits'] as $row )
|
||||
{
|
||||
$results['images'][] = array(
|
||||
'thumb' => $row['webformatURL'],
|
||||
'url' => $row['largeImageURL'],
|
||||
'imgid' => $row['id'],
|
||||
);
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $results );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search pixabay
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function getById()
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
|
||||
$url = \IPS\Http\Url::external( "https://pixabay.com/api/" )->setQueryString( array(
|
||||
'key' => \IPS\Settings::i()->pixabay_apikey,
|
||||
'id' => \IPS\Request::i()->id
|
||||
) );
|
||||
|
||||
|
||||
$request = json_decode( $url->request()->get()->content, true );
|
||||
|
||||
$url = NULL;
|
||||
$filename = NULL;
|
||||
foreach ( $request['hits'] as $row )
|
||||
{
|
||||
$url = $row['largeImageURL'];
|
||||
|
||||
if ( ! empty( $row['previewURL'] ) )
|
||||
{
|
||||
$filename = str_replace( '_150.', '.', basename( $row['previewURL'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Now get the URL contents */
|
||||
$data = \IPS\Http\Url::external( $url )->request()->get();
|
||||
|
||||
if ( ! $filename )
|
||||
{
|
||||
$filename = basename( $url );
|
||||
}
|
||||
|
||||
list( $image, $type ) = explode( '/', $data->httpHeaders['Content-Type'] );
|
||||
\IPS\Output::i()->json( array( 'content' => base64_encode( $data->content ), 'type' => $data->httpHeaders['Content-Type'], 'imageType' => $type, 'filename' => $filename ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -22,6 +22,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _redirect extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* @brief Is this for displaying "content"? Affects if advertisements may be shown
|
||||
*/
|
||||
public $isContentPage = FALSE;
|
||||
|
||||
/**
|
||||
* Handle munged links
|
||||
*
|
||||
@@ -30,50 +35,40 @@ 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 ) )
|
||||
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 ) )
|
||||
{
|
||||
/* Construct the URL */
|
||||
$url = \IPS\Http\Url::external( \IPS\Request::i()->url );
|
||||
|
||||
/* If it's a resource (image, etc.), we pull the actual contents to prevent the referrer being exposed (which is an issue in the ACP where the session ID is private) */
|
||||
if ( \IPS\Request::i()->resource )
|
||||
|
||||
/* If this is coming from email tracking, log the click */
|
||||
if( isset( \IPS\Request::i()->email ) AND \IPS\Settings::i()->prune_log_emailstats != 0 )
|
||||
{
|
||||
/* Except if it's internal or localhost, we can't make a HTTP request to it because doing that would potentially allow access to secured resources because the server
|
||||
thinks the request is internal. We don't need to worry about about things on this domain getting access to the referrer anyway */
|
||||
if ( $url->isLocalhost() )
|
||||
/* If we have a row for "today" then update it, otherwise insert one */
|
||||
$today = \IPS\DateTime::create()->format( 'Y-m-d' );
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url, NULL, 303 );
|
||||
}
|
||||
/* For everything else, pull the contents... */
|
||||
else
|
||||
{
|
||||
/* It can't be protocol relative */
|
||||
if ( !$url->data['scheme'] )
|
||||
/* We only include the time column in the query so that the db index can be effectively used */
|
||||
if( !\IPS\Request::i()->type )
|
||||
{
|
||||
$url = \IPS\Http\Url::external( 'http:' . \IPS\Request::i()->url );
|
||||
$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();
|
||||
}
|
||||
|
||||
/* Get the contents */
|
||||
try
|
||||
{
|
||||
$response = \IPS\Http\Url::external( $url )->request( \IPS\DEFAULT_REQUEST_TIMEOUT )->get();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
/* Send output - we only want to pass along the content and content type. We can't allow the response
|
||||
to perform a redirect (which would cause the referrer to be exposed) and we don't want to pass
|
||||
along any of their headers which could include setting cookies, etc. */
|
||||
\IPS\Output::i()->sendOutput( $response->content, $response->httpResponseCode == 200 ? 200 : 404, isset( $response->httpHeaders['Content-Type'] ) ? $response->httpHeaders['Content-Type'] : 'unknown/unknown' );
|
||||
\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 ) );
|
||||
}
|
||||
}
|
||||
/* For everything else, we'll do a 303 redirect */
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url, \IPS\Member::loggedIn()->language()->addToStack('external_redirect'), 303, TRUE );
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -82,23 +77,6 @@ class _redirect extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect an ACP click
|
||||
*
|
||||
* @note The purpose of this method is to avoid exposing \IPS\CP_DIRECTORY to non-admins
|
||||
* @return void
|
||||
*/
|
||||
protected function admin()
|
||||
{
|
||||
if( \IPS\Member::loggedIn()->isAdmin() )
|
||||
{
|
||||
$queryString = base64_decode( \IPS\Request::i()->_data );
|
||||
\IPS\Output::i()->redirect( new \IPS\Http\Url( \IPS\Http\Url::baseUrl() . \IPS\CP_DIRECTORY . '/?' . $queryString, TRUE ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->error( 'no_access_cp', '2C159/3', 403 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect an advertisement click
|
||||
*
|
||||
@@ -106,9 +84,6 @@ class _redirect extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function advertisement()
|
||||
{
|
||||
/* CSRF check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Get the advertisement */
|
||||
$advertisement = array();
|
||||
|
||||
@@ -129,20 +104,28 @@ class _redirect extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'ad_not_found', '2C159/1', 404, 'ad_not_found_admin' );
|
||||
}
|
||||
|
||||
/* We need to update click count for this advertisement. Does it need to be shut off too due to hitting click maximum?
|
||||
Note that this needs to be done as a string to do "col=col+1", which is why we're not using the ActiveRecord save() method.
|
||||
Updating by doing col=col+1 is more reliable when there are several clicks at nearly the same time. */
|
||||
$update = "ad_clicks=ad_clicks+1";
|
||||
|
||||
if( $advertisement->maximum_unit == 'c' AND $advertisement->maximum_value > -1 AND $advertisement->clicks + 1 >= $advertisement->maximum_value )
|
||||
if ( \IPS\Login::compareHashes( hash_hmac( "sha256", $advertisement->link, \IPS\Settings::i()->site_secret_key ), (string) \IPS\Request::i()->key ) OR \IPS\Login::compareHashes( hash_hmac( "sha256", $advertisement->link, \IPS\Settings::i()->site_secret_key . 'a' ), (string) \IPS\Request::i()->key ) )
|
||||
{
|
||||
$update .= ", ad_active=0";
|
||||
/* We need to update click count for this advertisement. Does it need to be shut off too due to hitting click maximum?
|
||||
Note that this needs to be done as a string to do "col=col+1", which is why we're not using the ActiveRecord save() method.
|
||||
Updating by doing col=col+1 is more reliable when there are several clicks at nearly the same time. */
|
||||
$update = "ad_clicks=ad_clicks+1";
|
||||
|
||||
if( $advertisement->maximum_unit == 'c' AND $advertisement->maximum_value > -1 AND $advertisement->clicks + 1 >= $advertisement->maximum_value )
|
||||
{
|
||||
$update .= ", ad_active=0";
|
||||
}
|
||||
|
||||
/* Update the database */
|
||||
\IPS\Db::i()->update( 'core_advertisements', $update, array( 'ad_id=?', $advertisement->id ) );
|
||||
|
||||
/* And do the redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( $advertisement->link ) );
|
||||
}
|
||||
/* If it doesn't validate, send the user to the index page */
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
/* Update the database */
|
||||
\IPS\Db::i()->update( 'core_advertisements', $update, array( 'ad_id=?', $advertisement->id ) );
|
||||
|
||||
/* And do the redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( $advertisement->link ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief referrals
|
||||
* @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 2019
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming Referrals
|
||||
*
|
||||
* Deprecated controller maintained for backwards compatibility with old referral links
|
||||
*/
|
||||
class _referrals extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Handle Referral
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'referred_by', \intval( \IPS\Request::i()->id ), \IPS\DateTime::create()->add( new \DateInterval( 'P1Y' ) ) );
|
||||
|
||||
try
|
||||
{
|
||||
$target = \IPS\Request::i()->direct ? \IPS\Http\Url::createFromString( base64_decode( \IPS\Request::i()->direct ) ) : \IPS\Http\Url::baseUrl();
|
||||
}
|
||||
catch( \IPS\Http\Url\Exception $e )
|
||||
{
|
||||
$target = NULL;
|
||||
}
|
||||
|
||||
if ( $target instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $target );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Settings::i()->base_url );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -22,6 +22,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* @brief Is this for displaying "content"? Affects if advertisements may be shown
|
||||
*/
|
||||
public $isContentPage = FALSE;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -50,6 +55,10 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
if ( isset( \IPS\Request::i()->oauth ) )
|
||||
{
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimalNoHome';
|
||||
}
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
}
|
||||
|
||||
@@ -69,21 +78,39 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=register', NULL, 'register' ), array(), 'loc_registering' );
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
|
||||
/* What's the "log in" link? */
|
||||
$loginUrl = \IPS\Http\Url::internal( 'app=core&module=system&controller=login', NULL, 'login' );
|
||||
if ( isset( \IPS\Request::i()->oauth ) and $ref = static::_refUrl() and $ref->base === 'none' )
|
||||
{
|
||||
$loginUrl = $ref;
|
||||
}
|
||||
|
||||
/* Post before registering? */
|
||||
$postBeforeRegister = NULL;
|
||||
if ( isset( \IPS\Request::i()->cookie['post_before_register'] ) or isset( \IPS\Request::i()->pbr ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$postBeforeRegister = \IPS\Db::i()->select( '*', 'core_post_before_registering', array( 'secret=?', \IPS\Request::i()->pbr ?: \IPS\Request::i()->cookie['post_before_register'] ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
}
|
||||
|
||||
/* Quick registration does not work with COPPA */
|
||||
if ( \IPS\Login::registrationType() == 'normal' )
|
||||
{
|
||||
$form = $this->_registrationForm();
|
||||
$form = $this->_registrationForm( $postBeforeRegister );
|
||||
$form->class = 'ipsForm_fullWidth';
|
||||
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('registration');
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\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' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupRegisterTemplate' ), new \IPS\Login( $loginUrl, \IPS\Login::LOGIN_REGISTRATION_FORM ), $postBeforeRegister );
|
||||
}
|
||||
else
|
||||
{
|
||||
\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' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupRegisterTemplate' ), new \IPS\Login( $loginUrl, \IPS\Login::LOGIN_REGISTRATION_FORM ), $postBeforeRegister ), new \IPS\Login( $loginUrl ), $postBeforeRegister );
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -109,12 +136,12 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* If coppa is enabled we need to add a birthday verification */
|
||||
if ( \IPS\Settings::i()->use_coppa OR \IPS\Settings::i()->minimum_age > 0 )
|
||||
{
|
||||
$steps['coppa'] = function( $data )
|
||||
$steps['coppa'] = function( $data ) use ( $postBeforeRegister )
|
||||
{
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( 'coppa', 'register_button' );
|
||||
$form->add( new \IPS\Helpers\Form\Date( 'bday', NULL, TRUE, array( 'max' => \IPS\DateTime::create() ) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Date( 'bday', NULL, TRUE, array( 'max' => \IPS\DateTime::create(), 'htmlAutocomplete' => "bday" ) ) );
|
||||
|
||||
if( $values = $form->values() )
|
||||
{
|
||||
/* Did we pass the minimum age requirement? */
|
||||
@@ -135,60 +162,56 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
return $values;
|
||||
}
|
||||
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->coppa( $form );
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->coppa( $form, $postBeforeRegister );
|
||||
};
|
||||
}
|
||||
|
||||
$self = $this;
|
||||
|
||||
$steps['basic_info'] = function ( $data ) use ( $self )
|
||||
$steps['basic_info'] = function ( $data ) use ( $self, $postBeforeRegister, $loginUrl )
|
||||
{
|
||||
$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' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) );
|
||||
$form = $this->_registrationForm( $postBeforeRegister );
|
||||
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupRegisterTemplate' ), new \IPS\Login( $loginUrl, \IPS\Login::LOGIN_REGISTRATION_FORM ), $postBeforeRegister ), new \IPS\Login( $loginUrl, \IPS\Login::LOGIN_REGISTRATION_FORM ), $postBeforeRegister );
|
||||
};
|
||||
|
||||
/* 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 );
|
||||
\IPS\Output::i()->output = (string) new \IPS\Helpers\Wizard( $steps, \IPS\Http\Url::internal( 'app=core&module=system&controller=register' ), FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal registration form
|
||||
*
|
||||
* @param array|NULL $postBeforeRegister The row from core_post_before_registering if applicable
|
||||
* @return \IPS\Form
|
||||
*/
|
||||
protected function _registrationForm()
|
||||
protected function _registrationForm( $postBeforeRegister )
|
||||
{
|
||||
$form = \IPS\core\modules\front\system\register::buildRegistrationForm();
|
||||
$form = static::buildRegistrationForm( $postBeforeRegister );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$profileFields = array();
|
||||
|
||||
if( \IPS\Login::registrationType() == 'full' )
|
||||
{
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $id => $field )
|
||||
{
|
||||
if( $field->required and ( $values[ $field->name ] === NULL or !isset( $values[ $field->name ] ) ) )
|
||||
if ( $field instanceof \IPS\Helpers\Form\Upload )
|
||||
{
|
||||
\IPS\Output::i()->error( 'reg_required_fields', '1C223/5', 403, '' );
|
||||
$profileFields[ "field_{$id}" ] = (string) $values[ $field->name ];
|
||||
}
|
||||
|
||||
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
|
||||
|
||||
if ( $fields instanceof \IPS\Helpers\Form\Editor )
|
||||
else
|
||||
{
|
||||
$field->claimAttachments( $this->id );
|
||||
$profileFields[ "field_{$id}" ] = $field::stringValue( !empty( $values[ $field->name ] ) ? $values[ $field->name ] : NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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'] ) ) )
|
||||
{
|
||||
@@ -213,40 +236,20 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
if ( !$form->error )
|
||||
{
|
||||
/* Create Member */
|
||||
$member = \IPS\core\modules\front\system\register::_createMember( $values, $profileFields );
|
||||
$member = static::_createMember( $values, $profileFields, $postBeforeRegister, $form );
|
||||
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Member\Device::loadOrCreate( $member, FALSE )->updateAfterAuthentication( TRUE, NULL );
|
||||
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' or $ref->openRedirect() )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $ref ) );
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $this->_performRedirect( $postBeforeRegister, TRUE ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
$this->_performRedirect( $postBeforeRegister );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,59 +273,75 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$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( !isset( \IPS\Request::i()->finishStarted ) )
|
||||
{
|
||||
if ( $step->required AND !$step->completed( \IPS\Member::loggedIn() ) )
|
||||
$haveRequired = FALSE;
|
||||
foreach( $steps AS $id => $step )
|
||||
{
|
||||
$haveRequired = TRUE;
|
||||
break;
|
||||
if ( $step->required AND !$step->completed( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$haveRequired = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $haveRequired === FALSE )
|
||||
{
|
||||
/* Nope, forward */
|
||||
$this->_performRedirect();
|
||||
}
|
||||
|
||||
/* Make sure we reset any temp data that might have been stored in the session */
|
||||
if( isset( $_SESSION['profileCompletionData'] ) )
|
||||
{
|
||||
unset( $_SESSION['profileCompletionData'] );
|
||||
}
|
||||
}
|
||||
|
||||
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' );
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=finish&finishStarted=1', 'front', 'register' )->setQueryString( 'ref', \IPS\Request::i()->ref );
|
||||
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'ProfileSteps' ) AS $extension )
|
||||
{
|
||||
if ( method_exists( $extension, 'wizard') AND count( $extension::wizard() ) )
|
||||
if ( method_exists( $extension, 'wizard') AND \is_array( $extension::wizard() ) AND \count( $extension::wizard() ) )
|
||||
{
|
||||
$wizardSteps = array_merge( $wizardSteps, $extension::wizard() );
|
||||
}
|
||||
if ( method_exists( $extension, 'extraStep') AND \count( $extension::extraStep() ) )
|
||||
{
|
||||
$wizardSteps = array_merge( $wizardSteps, $extension::extraStep() );
|
||||
}
|
||||
}
|
||||
|
||||
$wizardSteps = \IPS\Member\ProfileStep::setOrder( $wizardSteps );
|
||||
|
||||
$wizardSteps = array_merge( $wizardSteps, array( 'profile_done' => function( $data ) {
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'saved' );
|
||||
$this->_performRedirect( NULL, FALSE, 'saved' );
|
||||
} ) );
|
||||
|
||||
$wizard = new \IPS\Helpers\Wizard( $wizardSteps, $url, TRUE, NULL, TRUE );
|
||||
|
||||
$wizard->template = array( \IPS\Theme::i()->getTemplate( 'system', 'core', 'front' ), 'completeWizardTemplate' );
|
||||
|
||||
\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 );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->finishRegistration( (string) $wizard );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Registration Form
|
||||
*
|
||||
* @param array|NULL $postBeforeRegister The row from core_post_before_registering if applicable
|
||||
* @return \IPS\Helpers\Form
|
||||
*/
|
||||
public static function buildRegistrationForm()
|
||||
{
|
||||
public static function buildRegistrationForm( $postBeforeRegister = NULL )
|
||||
{
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( 'form', 'register_button', NULL, array( 'data-controller' => 'core.front.system.register') );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username', NULL, TRUE, array( 'accountUsername' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'accountEmail' => TRUE, 'maxLength' => 150, 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password', 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username', NULL, TRUE, array( 'accountUsername' => TRUE, 'htmlAutocomplete' => "username" ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', $postBeforeRegister ? $postBeforeRegister['email'] : NULL, TRUE, array( 'accountEmail' => TRUE, 'maxLength' => 150, 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "email" ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'protect' => TRUE, 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'strengthRequest' => array( 'username', 'email_address' ), 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "new-password" ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'protect' => TRUE, 'confirm' => 'password', 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "new-password" ) ) );
|
||||
|
||||
/* Profile fields */
|
||||
if ( \IPS\Login::registrationType() == 'full' )
|
||||
@@ -358,7 +377,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'q_and_a', NULL, TRUE, array(), function( $val )
|
||||
{
|
||||
$qanda = intval( \IPS\Request::i()->q_and_a_id );
|
||||
$qanda = \intval( \IPS\Request::i()->q_and_a_id );
|
||||
$pass = true;
|
||||
|
||||
if( $qanda )
|
||||
@@ -376,7 +395,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $answers )
|
||||
{
|
||||
$answers = is_array( $answers ) ? $answers : array( $answers );
|
||||
$answers = \is_array( $answers ) ? $answers : array( $answers );
|
||||
$pass = FALSE;
|
||||
|
||||
foreach( $answers as $answer )
|
||||
@@ -421,7 +440,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$form->addSeparator();
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', \IPS\Settings::i()->updates_consent_default == 'enabled' ? TRUE : FALSE, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', ( \IPS\Settings::i()->updates_consent_default == 'enabled' or \IPS\Request::i()->newsletter ) ? TRUE : FALSE, FALSE ) );
|
||||
|
||||
\IPS\core\modules\front\system\register::buildRegistrationTerm();
|
||||
|
||||
@@ -447,7 +466,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
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' ) ) )
|
||||
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();
|
||||
@@ -461,7 +480,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
if ( \IPS\Settings::i()->security_questions_prompt === 'optional' )
|
||||
{
|
||||
$securityOptoutToggles = array();
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
foreach ( range( 1, min( $numberOfQuestions, \count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityOptoutToggles[] = 'security_question_q_' . $i;
|
||||
$securityOptoutToggles[] = 'security_question_a_' . $i;
|
||||
@@ -474,7 +493,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
$form->add( $optOutCheckbox );
|
||||
}
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
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 ) ) )
|
||||
@@ -499,11 +518,13 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Create Member
|
||||
*
|
||||
* @param array $values Values from form
|
||||
* @param array $profileFields Profile field values from registration
|
||||
* @param array $values Values from form
|
||||
* @param array $profileFields Profile field values from registration
|
||||
* @param array|NULL $postBeforeRegister The row from core_post_before_registering if applicable
|
||||
* @param \IPS\Helpers\Form $form The form object
|
||||
* @return \IPS\Member
|
||||
*/
|
||||
public static function _createMember( $values, $profileFields )
|
||||
public static function _createMember( $values, $profileFields, $postBeforeRegister = NULL, &$form )
|
||||
{
|
||||
/* Create */
|
||||
$member = new \IPS\Member;
|
||||
@@ -515,6 +536,15 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$member->members_bitoptions['view_sigs'] = TRUE;
|
||||
$member->last_visit = time();
|
||||
|
||||
if( isset( \IPS\Request::i()->cookie['language'] ) AND \IPS\Request::i()->cookie['language'] )
|
||||
{
|
||||
$member->language = \IPS\Request::i()->cookie['language'];
|
||||
}
|
||||
elseif ( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) )
|
||||
{
|
||||
$member->language = \IPS\Lang::autoDetectLanguage( $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
|
||||
}
|
||||
|
||||
/* Query spam service */
|
||||
$spamCode = NULL;
|
||||
$spamAction = NULL;
|
||||
@@ -545,7 +575,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$member->logHistory( 'core', 'account', array( 'type' => 'register', 'spamCode' => $spamCode, 'spamAction' => $spamAction ), FALSE );
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and \in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
{
|
||||
if ( isset( $values['security_questions_optout_title'] ) )
|
||||
{
|
||||
@@ -570,7 +600,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $answers ) )
|
||||
if ( \count( $answers ) )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'core_security_answers', $answers );
|
||||
}
|
||||
@@ -583,6 +613,16 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* Cycle profile fields */
|
||||
foreach( $profileFields as $id => $fieldValue )
|
||||
{
|
||||
$field = \IPS\core\ProfileFields\Field::loadWithMember( mb_substr( $id, 6 ), NULL, NULL, NULL );
|
||||
if( $field->type == 'Editor' )
|
||||
{
|
||||
$field->claimAttachments( $member->member_id );
|
||||
}
|
||||
}
|
||||
|
||||
/* Save custom field values */
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
|
||||
@@ -597,8 +637,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
$member->logHistory( 'core', 'terms_acceptance', array( 'type' => 'terms' ) );
|
||||
|
||||
/* Handle validation */
|
||||
$member->postRegistration();
|
||||
/* Handle validation, but not if we were flagged as a spammer and banned */
|
||||
if( $spamAction != 3 )
|
||||
{
|
||||
$member->postRegistration( FALSE, FALSE, $postBeforeRegister, static::_refUrl() );
|
||||
}
|
||||
|
||||
/* Save and return */
|
||||
return $member;
|
||||
@@ -643,7 +686,6 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* They are cancelled and will be deleted, haha, etc */
|
||||
\IPS\Output::i()->error( 'reg_is_cancelled', '2C223/9', 403, '' );
|
||||
|
||||
}
|
||||
else if ( $validating['user_verified'] )
|
||||
{
|
||||
@@ -669,7 +711,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
$validating = \IPS\Db::i()->select( '*', 'core_validating', array( 'member_id=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
if ( !count( $validating ) )
|
||||
if ( !\count( $validating ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'validate_no_record', '2S129/3', 404, '' );
|
||||
}
|
||||
@@ -696,6 +738,9 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function validate()
|
||||
{
|
||||
/* Prevent the vid key from being exposed in referrers */
|
||||
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin" );
|
||||
|
||||
if( \IPS\Request::i()->vid AND \IPS\Request::i()->mid )
|
||||
{
|
||||
/* Load record */
|
||||
@@ -705,31 +750,71 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'validate_no_record', '2S129/2', 404, '' );
|
||||
$this->_performRedirect( NULL, FALSE, 'validate_no_record' );
|
||||
}
|
||||
|
||||
/* Validate */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->mid );
|
||||
if ( $record['new_reg'] )
|
||||
{
|
||||
$member->emailValidationConfirmed( $record );
|
||||
}
|
||||
else
|
||||
{
|
||||
$member->members_bitoptions['validating'] = FALSE;
|
||||
$member->save();
|
||||
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=?', $member->member_id ) );
|
||||
|
||||
/* Send a confirmation email */
|
||||
\IPS\Email::buildFromTemplate( 'core', 'email_address_changed', array( $member, $record['prev_email'] ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $record['prev_email'], array(), array(), NULL, NULL, array( 'Reply-To' => \IPS\Settings::i()->email_in ) );
|
||||
if ( isset( $record['ref'] ) )
|
||||
{
|
||||
\IPS\Request::i()->ref = base64_encode( $record['ref'] );
|
||||
}
|
||||
|
||||
/* If this is a new registration and the user has already validated their email, redirect */
|
||||
if ( $record['new_reg'] AND $record['user_verified'] )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=validating', 'front', 'register' ), 'reg_email_already_validated_admin' );
|
||||
}
|
||||
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->mid );
|
||||
|
||||
/* 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' );
|
||||
/* Post before registering? */
|
||||
try
|
||||
{
|
||||
$postBeforeRegister = \IPS\Db::i()->select( '*', 'core_post_before_registering', array( '`member`=?', $member->member_id ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$postBeforeRegister = NULL;
|
||||
}
|
||||
|
||||
/* Ask the user to confirm - this prevents spiders and similar scrapers seeing the link and following it without the user's knowledge */
|
||||
$form = new \IPS\Helpers\Form( 'form', 'validate_my_account' );
|
||||
$form->hiddenValues['custom'] = 'submitted';
|
||||
|
||||
if( $submitted = $form->values() )
|
||||
{
|
||||
/* Validate */
|
||||
if ( $record['new_reg'] )
|
||||
{
|
||||
$member->emailValidationConfirmed( $record );
|
||||
}
|
||||
else
|
||||
{
|
||||
$member->members_bitoptions['validating'] = FALSE;
|
||||
$member->save();
|
||||
|
||||
$member->memberSync( 'onEmailChange', array( $member->email, $record['prev_email'] ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=?', $member->member_id ) );
|
||||
|
||||
/* Send a confirmation email */
|
||||
\IPS\Email::buildFromTemplate( 'core', 'email_address_changed', array( $member, $record['prev_email'] ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $record['prev_email'], array(), array(), NULL, NULL, array( 'Reply-To' => \IPS\Settings::i()->email_in ) );
|
||||
}
|
||||
|
||||
/* Log in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( TRUE );
|
||||
|
||||
/* Redirect */
|
||||
$this->_performRedirect( $postBeforeRegister, FALSE, 'validate_email_confirmation' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_complete_details');
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'system', 'core', 'front' ), 'completeValidation' ), $member );
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're still here, just redirect to homepage */
|
||||
$this->_performRedirect( NULL, FALSE, 'validate_no_record' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,32 +912,22 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'account', array( 'type' => 'complete' ), FALSE );
|
||||
|
||||
/* Handle validation */
|
||||
\IPS\Member::loggedIn()->postRegistration( ( isset( $values['email_address'] ) ) ? FALSE : TRUE );
|
||||
$postBeforeRegister = NULL;
|
||||
if ( isset( \IPS\Request::i()->cookie['post_before_register'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$postBeforeRegister = \IPS\Db::i()->select( '*', 'core_post_before_registering', array( 'secret=?', \IPS\Request::i()->cookie['post_before_register'] ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
}
|
||||
\IPS\Member::loggedIn()->postRegistration( ( isset( $values['email_address'] ) ) ? FALSE : TRUE, FALSE, $postBeforeRegister, static::_refUrl() );
|
||||
|
||||
/* Set member as a full member in the session table */
|
||||
\IPS\Session::i()->setType( \IPS\Session\Front::LOGIN_TYPE_MEMBER );
|
||||
|
||||
/* Redirect */
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' or $ref->openRedirect() )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
$this->_performRedirect( $postBeforeRegister );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_complete_details');
|
||||
@@ -881,11 +956,19 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$pending = null;
|
||||
}
|
||||
|
||||
/* If we're pending *admin* validation, don't let them change their email - otherwise doing so would allow them to bypass validation
|
||||
@todo - this is kind of an unsatisfcatory solution as ideally it would put them back into admin approval, but this would require
|
||||
significant reengineering to address - see commit notes on this code block */
|
||||
if ( $pending and $pending['new_reg'] and $pending['user_verified'] )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C223/6', 403, '' );
|
||||
}
|
||||
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => \IPS\Member::loggedIn() ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => \IPS\Member::loggedIn(), 'htmlAutocomplete' => "email" ) ) );
|
||||
$captcha = new \IPS\Helpers\Form\Captcha;
|
||||
if ( (string) $captcha !== '' )
|
||||
{
|
||||
@@ -931,7 +1014,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* If email validation is required, do that... */
|
||||
if ( in_array( \IPS\Settings::i()->reg_auth_type, array( 'user', 'admin_user' ) ) )
|
||||
if ( \in_array( \IPS\Settings::i()->reg_auth_type, array( 'user', 'admin_user' ) ) )
|
||||
{
|
||||
/* Delete any pending validation emails */
|
||||
if ( $pending['vid'] )
|
||||
@@ -959,7 +1042,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -980,22 +1063,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()->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 */
|
||||
$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();
|
||||
|
||||
/* Member sync callback */
|
||||
\IPS\Member::loggedIn()->memberSync( 'onLogout', array( \IPS\Http\Url::internal( '' ) ) );
|
||||
\IPS\Login::logout();
|
||||
|
||||
/* Flag user as having cancelled their registration */
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'reg_cancelled' => time() ), array( 'member_id=? AND new_reg=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
@@ -1043,25 +1111,55 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
$this->_performRedirect();
|
||||
}
|
||||
|
||||
$subprocessors = array();
|
||||
/* Work out the main subprocessors that the user has no direct choice over */
|
||||
if ( \IPS\Settings::i()->privacy_show_processors )
|
||||
{
|
||||
foreach( \IPS\Application::enabledApplications() as $app )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url\Friendly::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
if ( $ref instanceof \IPS\Http\Url\Internal and !$ref->openRedirect() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
$subprocessors = array_merge( $subprocessors, $app->privacyPolicyThirdParties() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('terms_of_use');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('system')->reconfirmTerms( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'], \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'], $form );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('system')->reconfirmTerms( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'], \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'], $form, $subprocessors );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the post before registering submission
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function cancelPostBeforeRegister()
|
||||
{
|
||||
if( ! isset( \IPS\Request::i()->id ) or ! isset( \IPS\Request::i()->pbr ) or ! \IPS\Settings::i()->post_before_registering )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C223/D', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$pbr = \IPS\Db::i()->select( '*', 'core_post_before_registering', array( "id=? and secret=?", \IPS\Request::i()->id, \IPS\Request::i()->pbr ) )->first();
|
||||
|
||||
$class = $pbr['class'];
|
||||
try
|
||||
{
|
||||
$class::load( $pbr['id'] )->delete();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
|
||||
\IPS\Db::i()->delete( 'core_post_before_registering', array( 'class=? AND id=?', $pbr['class'], $pbr['id'] ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal(''), 'post_before_register_submission_cancelled' );
|
||||
}
|
||||
catch( \UnderFlowException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'pbr_row_not_found', '2C223/E', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1083,4 +1181,129 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] .= sprintf( \IPS\Member::loggedIn()->language()->get("reg_privacy_link"), \IPS\Http\Url::external( \IPS\Settings::i()->privacy_link ), 'target="_blank" rel="noopener"' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect the user
|
||||
* -consolidated to reduce duplicate code
|
||||
*
|
||||
* @param array|NULL $postBeforeRegister Post before registration data
|
||||
* @param bool $return Return the URL instead of redirecting
|
||||
* @param string $message (Optional) message to show during redirect
|
||||
* @return void
|
||||
*/
|
||||
protected function _performRedirect( $postBeforeRegister=NULL, $return=FALSE, $message='' )
|
||||
{
|
||||
/* Redirect */
|
||||
if ( $ref = static::_refUrl() )
|
||||
{
|
||||
// We got it!
|
||||
}
|
||||
elseif ( $postBeforeRegister )
|
||||
{
|
||||
try
|
||||
{
|
||||
$class = $postBeforeRegister['class'];
|
||||
$ref = $class::load( $postBeforeRegister['id'] )->url();
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
|
||||
if( $return === TRUE )
|
||||
{
|
||||
return $ref;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $ref, $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get referral URL
|
||||
*
|
||||
* @return \IPS\Http\Url|NULL
|
||||
*/
|
||||
protected static function _refUrl()
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( ( $ref instanceof \IPS\Http\Url\Internal ) and \in_array( $ref->base, array( 'front', 'none' ) ) and !$ref->openRedirect() )
|
||||
{
|
||||
return $ref;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ){ }
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPassword(): void
|
||||
{
|
||||
try
|
||||
{
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->mid );
|
||||
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C223/F', 403, '' );
|
||||
}
|
||||
|
||||
/* If this user isn't being forced, error */
|
||||
if ( !$member->members_bitoptions['password_reset_forced'] )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C223/H', 403, '' );
|
||||
}
|
||||
|
||||
if ( !\IPS\Login::compareHashes( md5( \IPS\SUITE_UNIQUE_KEY . $member->email . $member->name ), (string) \IPS\Request::i()->passkey ) )
|
||||
{
|
||||
\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 ) ) );
|
||||
if ( $mfa = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Request::i()->url(), $member ) )
|
||||
{
|
||||
\IPS\Output::i()->output = $mfa;
|
||||
return;
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'protect' => TRUE, 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'strengthRequest' => array( 'username', 'email_address' ), 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "new-password" ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'protect' => TRUE, 'confirm' => 'password', 'bypassProfanity' => \IPS\Helpers\Form\Text::BYPASS_PROFANITY_ALL, 'htmlAutocomplete' => "new-password" ) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$changed = $member->changePassword( $values['password'], 'forced' );
|
||||
if ( !$changed and \IPS\Login\Handler::findMethod( 'IPS\Login\Handler\Standard' ) )
|
||||
{
|
||||
$member->setLocalPassword( $values['password'] );
|
||||
$member->save();
|
||||
}
|
||||
|
||||
\IPS\Request::i()->setCookie( 'noCache', 1 );
|
||||
|
||||
$success = new \IPS\Login\Success( $member, \IPS\Login\Handler::findMethod( 'IPS\Login\Handler\Standard' ) );
|
||||
$success->process();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'set_password_stored' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->registerSetPassword( $form, $member );
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -63,6 +63,6 @@ class _theme extends \IPS\Dispatcher\Controller
|
||||
\IPS\Member::loggedIn()->save();
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Request::i()->referrer() ?: \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -31,10 +31,23 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( ! \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->addRef( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) );
|
||||
}
|
||||
|
||||
/* Check the member has permission to manage promote settings */
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '3C375/2', 403, '' );
|
||||
}
|
||||
|
||||
$twitter = \IPS\Login\Handler::findMethod('IPS\Login\Handler\Oauth1\Twitter');
|
||||
|
||||
/* Required handler present and enabled? */
|
||||
if( $twitter === NULL )
|
||||
{
|
||||
\IPS\Output::i()->error( 'promote_twitter_setup_app', '3C375/3', 403, '' );
|
||||
}
|
||||
|
||||
$promote = \IPS\core\Promote::getPromoter( 'Twitter' );
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' );
|
||||
$callback = $twitter->redirectionEndpoint()->setQueryString( 'state', $twitter->id . '-' . base64_encode( $url ) . '-' . \IPS\Session::i()->csrfKey . '-' );
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -29,6 +29,9 @@ class _unsubscribe extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Prevent the email and secure key from being exposed in referrers */
|
||||
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin" );
|
||||
|
||||
/* Get the member being requested */
|
||||
if( empty( \IPS\Request::i()->email ) )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -40,7 +40,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
$theme = \IPS\Theme::load( intval( \IPS\Request::i()->cookie['vseThemeId'] ) );
|
||||
$theme = \IPS\Theme::load( \intval( \IPS\Request::i()->cookie['vseThemeId'] ) );
|
||||
|
||||
if ( ! $theme->by_skin_gen )
|
||||
{
|
||||
@@ -65,7 +65,6 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
/* JS */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'library.js' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'js/jslang.php?langId=' . \IPS\Member::loggedIn()->language()->id, 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jscolor/jscolor.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'framework.js' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'app.js' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'vse/vsedata.js', 'core', 'interface' ) );
|
||||
@@ -75,32 +74,49 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'codemirror/codemirror.css', 'core', 'interface' ) );
|
||||
|
||||
$css = $theme->getRawCss( 'core', 'front', 'custom', \IPS\Theme::RETURN_ALL, true );
|
||||
$vseCss = null;
|
||||
$customCss = null;
|
||||
|
||||
/* VSE CSS */
|
||||
if ( isset( $css['core']['front']['custom']['vse.css'] ) )
|
||||
{
|
||||
$functionName = "css_" . mt_rand();
|
||||
\IPS\Theme::makeProcessFunction( \IPS\Theme::fixResourceTags( $css['core']['front']['custom']['vse.css']['css_content'], 'front' ), $functionName, '', FALSE, TRUE );
|
||||
$vseCss = call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
}
|
||||
|
||||
|
||||
if ( isset( $css['core']['front']['custom']['custom.css'] ) )
|
||||
{
|
||||
/* Custom CSS */
|
||||
$functionName = "css_" . mt_rand();
|
||||
\IPS\Theme::makeProcessFunction( \IPS\Theme::fixResourceTags( $css['core']['front']['custom']['custom.css']['css_content'], 'front' ), $functionName, '', FALSE, TRUE );
|
||||
$customCss = call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
$themeFunction = 'IPS\\Theme\\'. $functionName;
|
||||
$customCss = $themeFunction();
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', NULL );
|
||||
$settings = $theme->getThemeSettings();
|
||||
$settingKeyValues = array();
|
||||
$colorValues = array();
|
||||
|
||||
foreach( $settings as $key => $data )
|
||||
{
|
||||
$settingKeyValues[ $key ] = $data['_value'];
|
||||
|
||||
if( $data['sc_type'] === 'Color' )
|
||||
{
|
||||
if( preg_match( '/^#?[0-9a-fA-F]{6}$/', $data['_value'] ) )
|
||||
{
|
||||
$colorValue = str_replace('#', '', $data['_value']);
|
||||
$rgb = array();
|
||||
|
||||
if( \strlen( $colorValue ) === 3 )
|
||||
{
|
||||
$rgb[] = hexdec( \substr( $colorValue, 0, 1 ) . \substr( $colorValue, 0, 1 ) );
|
||||
$rgb[] = hexdec( \substr( $colorValue, 1, 1 ) . \substr( $colorValue, 1, 1 ) );
|
||||
$rgb[] = hexdec( \substr( $colorValue, 2, 1 ) . \substr( $colorValue, 2, 1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$rgb[] = hexdec( \substr( $colorValue, 0, 2 ) );
|
||||
$rgb[] = hexdec( \substr( $colorValue, 2, 2 ) );
|
||||
$rgb[] = hexdec( \substr( $colorValue, 4, 2 ) );
|
||||
}
|
||||
|
||||
$colorValues[ $key ] = implode( $rgb, ', ');
|
||||
}
|
||||
}
|
||||
|
||||
if ( $data['sc_show_in_vse'] )
|
||||
{
|
||||
@@ -122,7 +138,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
$content = json_decode( $data['sc_content'], TRUE );
|
||||
|
||||
$options = array();
|
||||
if( is_array( $content ) )
|
||||
if( \is_array( $content ) )
|
||||
{
|
||||
foreach( $content as $_content )
|
||||
{
|
||||
@@ -147,7 +163,8 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Template */
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'vse', 'core', 'front' )->globalTemplate( $vseCss, $customCss, $settingKeyValues, (string) $form, $theme->skin_gen_data );
|
||||
/* @note The first param used to be the VSE CSS, however as of 4.5 we handle the VSE differently and it is no longer used */
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'vse', 'core', 'front' )->globalTemplate( NULL, $customCss, $settingKeyValues, (string) $form, $theme->skin_gen_data, $colorValues );
|
||||
|
||||
\IPS\Output::i()->sendOutput( \IPS\Output::i()->output, 200, 'text/html' );
|
||||
}
|
||||
@@ -203,7 +220,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( isset( \IPS\Request::i()->cookie['vseThemeId'] ) )
|
||||
{
|
||||
$theme = \IPS\Theme::load( intval( \IPS\Request::i()->cookie['vseThemeId'] ) );
|
||||
$theme = \IPS\Theme::load( \intval( \IPS\Request::i()->cookie['vseThemeId'] ) );
|
||||
|
||||
if ( ! $theme->by_skin_gen )
|
||||
{
|
||||
@@ -216,7 +233,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->json( 'NO_PERMISSION', 403 );
|
||||
}
|
||||
|
||||
$theme->vseSave( \IPS\Request::i()->css, \IPS\Request::i()->customcss, \IPS\Request::i()->settings, \IPS\Request::i()->values );
|
||||
$theme->vseSave( \IPS\Request::i()->colors, \IPS\Request::i()->customcss, \IPS\Request::i()->settings );
|
||||
|
||||
\IPS\File::getClass('core_Theme')->deleteContainer( 'css_built_' . $theme->id );
|
||||
$theme->css_map = array();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -146,7 +146,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
/* Display */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_modcp.js', 'core' ) );
|
||||
$actions = \IPS\Db::i()->select( '*', 'core_members_warn_actions', NULL, 'wa_points ASC' );
|
||||
if ( count( $actions ) )
|
||||
if ( \count( $actions ) )
|
||||
{
|
||||
$min = NULL;
|
||||
foreach ( $actions as $a )
|
||||
@@ -161,7 +161,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
$form->addSidebar( \IPS\Theme::i()->getTemplate( 'modcp' )->warnActions( $actions, $member, $min ) );
|
||||
}
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('warn_member', FALSE, array( 'sprintf' => array( $member->name ) ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,17 +202,14 @@ class _warnings extends \IPS\Content\Controller
|
||||
$member->save();
|
||||
|
||||
/* Redirect */
|
||||
if ( isset( $_SERVER['HTTP_REFERER'] ) )
|
||||
if ( $redirectTo = \IPS\Request::i()->referrer() )
|
||||
{
|
||||
$url = \IPS\Http\Url\Friendly::createFromString( $_SERVER['HTTP_REFERER'] );
|
||||
if ( $url instanceof \IPS\Http\Url\Internal and !$url->openRedirect() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
return;
|
||||
}
|
||||
\IPS\Output::i()->redirect( $redirectTo );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $warning->url() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $warning->url() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -32,7 +32,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
/* Check Permissions */
|
||||
if ( ! \IPS\Member::loggedIn()->modPermission('can_manage_sidebar') )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission_manage_sidebar', '3S172/1', 403, '' );
|
||||
\IPS\Output::i()->error( 'no_permission_manage_sidebar', '2S172/1', 403, '' );
|
||||
}
|
||||
|
||||
parent::execute();
|
||||
@@ -147,7 +147,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( (string) $widget );
|
||||
\IPS\Output::i()->json( array( 'html' => (string) $widget, 'devices' => ( isset( $widget->configuration['devices_to_show'] ) ) ? $widget->configuration['devices_to_show'] : array('Phone', 'Tablet', 'Desktop') ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +214,8 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
|
||||
$widget->menuStyle = $widgetMaster['menu_style'];
|
||||
$form = new \IPS\Helpers\Form( 'form', 'saveSettings' );
|
||||
if ( $widget->configuration( $form ) !== NULL )
|
||||
|
||||
if ( $configurationForm = $widget->configuration( $form ) )
|
||||
{
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -223,12 +224,30 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
$values = $widget->preConfig( $values );
|
||||
}
|
||||
|
||||
/* Special advanced builder stuff */
|
||||
if ( \in_array( 'IPS\Widget\Builder', class_implements( $widget ) ) )
|
||||
{
|
||||
if( isset( $values['widget_adv__background_custom_image'] ) and $values['widget_adv__background_custom_image'] )
|
||||
{
|
||||
$values['widget_adv__background_custom_image'] = (string) $values['widget_adv__background_custom_image'];
|
||||
}
|
||||
}
|
||||
|
||||
if( isset( $values['show_on_all_devices'] ) and $values['show_on_all_devices'] )
|
||||
{
|
||||
$values['devices_to_show'] = array( 'Phone', 'Tablet', 'Desktop' );
|
||||
}
|
||||
|
||||
unset( $values['show_on_all_devices'] );
|
||||
|
||||
$blocks[ $k ]['configuration'] = $values;
|
||||
\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\Widget::deleteCaches( $block['key'], ( isset( $block['app'] ) ) ? $block['app'] : NULL, ( isset( $block['plugin'] ) ) ? $block['plugin'] : NULL );
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
\IPS\Output::i()->output = $widget->configuration()->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'widgets', 'core' ) ), 'formTemplate' ), $widget );
|
||||
|
||||
\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\Output::i()->output = $configurationForm->customTemplate( array( \IPS\Theme::i()->getTemplate( 'widgets', 'core' ), 'formTemplate' ), $widget );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,7 +261,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function saveOrder()
|
||||
{
|
||||
if( !in_array( \IPS\Request::i()->area, array( 'sidebar', 'header', 'footer' ) ) )
|
||||
if( !\in_array( \IPS\Request::i()->area, array( 'sidebar', 'header', 'footer' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'invalid_widget_area', '3S172/2', 403, '' );
|
||||
}
|
||||
@@ -307,13 +326,13 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Anything to update? */
|
||||
if ( count( $widgets ) > count( $newOrder ) )
|
||||
if ( \count( $widgets ) > \count( $newOrder ) )
|
||||
{
|
||||
/* No items left in area, or one has been removed */
|
||||
foreach( $widgets as $widget )
|
||||
{
|
||||
/* If we haven't seen this widget, it's been removed, so add to trash */
|
||||
if ( ! in_array( $widget['unique'], $seen ) )
|
||||
if ( ! \in_array( $widget['unique'], $seen ) )
|
||||
{
|
||||
\IPS\Widget::trash( $widget['unique'], $widget );
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user