Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

@@ -11,7 +11,7 @@
namespace IPS\core\modules\admin\settings;
/* 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 _posting extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -37,7 +42,7 @@ class _posting extends \IPS\Dispatcher\Controller
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'posting_manage_acronym' ) )
{
$this->tabs['acronymExpansion'] = 'acronym_expansion';
$this->tabs['acronymExpansion'] = 'word_expansion';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'posting_manage_polls' ) )
{
@@ -79,7 +84,8 @@ class _posting extends \IPS\Dispatcher\Controller
protected function manage()
{
/* Work out output */
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
$methodFunction = '_manage' . mb_ucfirst( $this->activeTab );
$activeTabContents = $this->$methodFunction();
/* If this is an AJAX request, just return it */
if( \IPS\Request::i()->isAjax() )
@@ -106,7 +112,6 @@ class _posting extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form;
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_settings.js', 'core', 'admin' ) );
$form->attributes['data-controller'] = 'core.admin.settings.posting';
$form->hiddenValues['rebuildImageProxy'] = \IPS\Request::i()->rebuildImageProxy ?: 0;
$form->addHeader('posting_attachments');
$form->add( new \IPS\Helpers\Form\Radio( 'attach_allowed_types', \IPS\Settings::i()->attach_allowed_types, FALSE, array(
'options' => array( 'all' => 'attach_allowed_types_all', 'media' => 'attach_allowed_types_media', 'images' => 'attach_allowed_types_images', 'none' => 'attach_allowed_types_none' ),
@@ -117,16 +122,23 @@ class _posting extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\WidthHeight( 'attachment_resample_size', \IPS\Settings::i()->attachment_resample_size ? explode( 'x', \IPS\Settings::i()->attachment_resample_size ) : array( 0, 0 ), FALSE, array( 'resizableDiv' => FALSE, 'unlimited' => array( 0, 0 ) ), NULL, NULL, NULL, 'attachment_resample_size' ) );
$current = ( isset( \IPS\Settings::i()->attachment_image_size ) ) ? explode( 'x', \IPS\Settings::i()->attachment_image_size ) : array( 1000, 750 );
$form->add( new \IPS\Helpers\Form\WidthHeight( 'attachment_image_size', $current, FALSE, array( 'resizableDiv' => FALSE ), NULL, NULL, NULL, 'attachment_image_size' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'editor_embeds', \IPS\Settings::i()->editor_embeds, FALSE, array( 'togglesOn' => array( 'max_video_width' ) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'editor_embeds', \IPS\Settings::i()->editor_embeds, FALSE, array( 'togglesOn' => array( 'max_video_width', 'max_internalembed_width' ) ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'max_video_width', \IPS\Settings::i()->max_video_width, FALSE, array( 'unlimited' => 0 ), NULL, NULL, 'px', 'max_video_width' ) );
$form->add( new \IPS\Helpers\Form\Number( 'max_internalembed_width', \IPS\Settings::i()->max_internalembed_width, FALSE, array( 'unlimited' => 0 ), NULL, NULL, 'px', 'max_internalembed_width' ) );
$form->addHeader('remote_images');
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_remote_images', \IPS\Settings::i()->allow_remote_images, FALSE, array( 'togglesOn' => array( 'remote_image_proxy' ) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'remote_image_proxy', \IPS\Settings::i()->remote_image_proxy, FALSE, array( 'togglesOn' => array( 'remote_image_proxy_cache' ) ), NULL, NULL, NULL, 'remote_image_proxy' ) );
$form->add( new \IPS\Helpers\Form\Number( 'image_proxy_cache_period', \IPS\Settings::i()->image_proxy_cache_period, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'indefinitely' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('for'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'remote_image_proxy_cache' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_remote_images', \IPS\Settings::i()->allow_remote_images, FALSE, array( 'togglesOn' => array( 'allow_only_https_remote_images' ) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_only_https_remote_images', \IPS\Settings::i()->allow_only_https_remote_images, FALSE, array(), NULL, NULL, NULL, 'allow_only_https_remote_images' ) );
$form->addHeader('posting_content');
if ( \IPS\Login::registrationType() != 'disabled' )
{
$form->add( new \IPS\Helpers\Form\Radio( 'post_before_registering', \IPS\Settings::i()->post_before_registering, FALSE, array( 'options' => array( 1 => 'post_before_registering_on', 0 => 'post_before_registering_off' ) ), NULL, NULL, NULL, 'post_before_registering' ) );
}
\IPS\Member::loggedIn()->language()->words['post_before_registering_on'] = sprintf( \IPS\Member::loggedIn()->language()->get('post_before_registering_on'), \IPS\Member::loggedIn()->language()->addToStack( 'core_group_' . \IPS\Settings::i()->member_group ) );
$form->add( new \IPS\Helpers\Form\Number( 'max_title_length', \IPS\Settings::i()->max_title_length, FALSE, array( 'max' => 255 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('max_title_length_suffix') ) );
$form->add( new \IPS\Helpers\Form\Number( 'merge_concurrent_posts', \IPS\Settings::i()->merge_concurrent_posts, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('minutes') ) );
$form->add( new \IPS\Helpers\Form\Number( 'flood_control', \IPS\Settings::i()->flood_control, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'none' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('seconds') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'merge_concurrent_posts', \intval( \IPS\Settings::i()->merge_concurrent_posts ), FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::MINUTES, 'unlimited' => 0, 'unlimitedLang' => 'never' ) ) );
$form->add( new \IPS\Helpers\Form\Interval( 'flood_control', \IPS\Settings::i()->flood_control, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::SECONDS, 'unlimited' => 0, 'unlimitedLang' => 'none' ) ) );
$form->addHeader('edit_log');
$form->add( new \IPS\Helpers\Form\Radio( 'edit_log', \IPS\Settings::i()->edit_log, FALSE, array(
'options' => array(
@@ -139,10 +151,10 @@ class _posting extends \IPS\Dispatcher\Controller
)
) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'edit_log_public', \IPS\Settings::i()->edit_log_public, FALSE, array(), NULL, NULL, NULL, 'edit_log_public' ) );
$form->add( new \IPS\Helpers\Form\Number( 'edit_log_prune', \IPS\Settings::i()->edit_log_prune, FALSE, array( 'unlimited' => -1, 'unlimitedLang' => 'never' ), function( $value ){ if( $value < 1 AND $value != -1 ) { throw new \InvalidArgumentException('form_required'); } }, NULL, \IPS\Member::loggedIn()->language()->addToStack('days'), 'edit_log_prune' ) );
$form->add( new \IPS\Helpers\Form\Interval( 'edit_log_prune', \IPS\Settings::i()->edit_log_prune, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS, 'unlimited' => -1, 'unlimitedLang' => 'never' ), function( $value ){ if( $value < 1 AND $value != -1 ) { throw new \InvalidArgumentException('form_required'); } }, NULL, NULL, 'edit_log_prune' ) );
$form->addHeader('posting_items');
$form->add( new \IPS\Helpers\Form\Number( 'topic_redirect_prune', \IPS\Settings::i()->topic_redirect_prune, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'topic_redirect_prune', \IPS\Settings::i()->topic_redirect_prune, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS, 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), NULL ) );
$hasReviewableApps = false;
@@ -172,61 +184,23 @@ class _posting extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Number( 'dellog_retention_period', \IPS\Settings::i()->dellog_retention_period, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'immediately', 'max' => PHP_INT_MAX ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('dellog_days_after_deleted') ) );
$form->add( new \IPS\Helpers\Form\Number( 'ip_address_prune', \IPS\Settings::i()->ip_address_prune, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never', 'max' => PHP_INT_MAX ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('days') ) );
$form->add( new \IPS\Helpers\Form\Interval( 'ip_address_prune', \IPS\Settings::i()->ip_address_prune, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::DAYS, 'unlimited' => 0, 'unlimitedLang' => 'never', 'max' => PHP_INT_MAX ) ) );
/* Save values */
if ( $values = $form->values() )
{
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => (int) $values['allow_remote_images'] ), array( '`key`=?', 'imageproxy' ) );
{
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => (int) $values['post_before_registering'] ), array( '`key`=?', 'postBeforeRegisterFollowup' ) );
$clearCss = ( $values['max_video_width'] !== \IPS\Settings::i()->max_video_width );
$values['attachment_resample_size'] = implode( 'x', $values['attachment_resample_size'] );
$values['attachment_image_size'] = implode( 'x', $values['attachment_image_size'] );
$values['attach_allowed_extensions'] = is_array( $values['attach_allowed_extensions'] ) ? implode( ',', array_unique( array_map( function( $val )
$values['attach_allowed_extensions'] = \is_array( $values['attach_allowed_extensions'] ) ? implode( ',', array_unique( array_map( function( $val )
{
return ltrim( $val, '.' );
}, $values['attach_allowed_extensions'] ) ) ) : '';
$values['max_video_width_css'] = ( $values['max_video_width'] ) ? $values['max_video_width'] . 'px' : 'none';
/* Run the image proxy rebuild tasks */
if( $values['rebuildImageProxy'] )
{
/* Remove any existing rebuilds */
\IPS\Db::i()->delete( 'core_queue', \IPS\Db::i()->in( '`key`', array( 'RebuildImageProxy', 'RebuildImageProxyNonContent', 'DeleteImageProxyFiles' ) ) );
/* Unset task datastore */
unset( \IPS\Data\Store::i()->currentImageProxyRebuild );
$enableDisable = $values['remote_image_proxy'] ? TRUE : FALSE;
foreach ( \IPS\Content::routedClasses( FALSE, TRUE ) as $class )
{
if( isset( $class::$databaseColumnMap['content'] ) )
{
try
{
\IPS\Task::queue( 'core', 'RebuildImageProxy', array( 'class' => $class, 'status' => $enableDisable ), 4 );
}
catch( \OutOfRangeException $ex ) { }
}
}
foreach( \IPS\Application::allExtensions( 'core', 'EditorLocations', FALSE, NULL, NULL, TRUE, TRUE ) as $_key => $extension )
{
if( method_exists( $extension, 'rebuildImageProxy' ) )
{
\IPS\Task::queue( 'core', 'RebuildImageProxyNonContent', array( 'extension' => $_key, 'status' => $enableDisable ), 4 );
}
}
/* If we're disabling the image proxy, also delete the files */
if( !$enableDisable )
{
\IPS\Task::queue( 'core', 'DeleteImageProxyFiles', array( 'status' => $enableDisable ), 5 );
}
}
unset( $values['rebuildImageProxy'] );
$values['max_internalembed_width_css'] = ( $values['max_internalembed_width'] ) ? $values['max_internalembed_width'] . 'px' : 'none';
$form->saveAsSettings( $values );
@@ -261,7 +235,7 @@ class _posting extends \IPS\Dispatcher\Controller
/* So people don't set up filters, test with their admin account and think it's not working */
$groupsThatBypass = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_groups', array( 'g_bypass_badwords=1' ) ), 'IPS\Member\Group' );
if ( count( $groupsThatBypass ) )
if ( \count( $groupsThatBypass ) )
{
$names = array();
foreach ( $groupsThatBypass as $group )
@@ -336,7 +310,18 @@ class _posting extends \IPS\Dispatcher\Controller
{
$values['ipb_url_whitelist'] = implode( ",", $values['ipb_url_whitelist'] );
$values['ipb_url_blacklist'] = implode( ",", $values['ipb_url_blacklist'] );
$values['posts_add_nofollow_exclude'] = json_encode( $values['posts_add_nofollow_exclude'] );
$noFollowExclude = array();
if( \is_array( $values['posts_add_nofollow_exclude'] ) )
{
foreach( $values['posts_add_nofollow_exclude'] as $url )
{
$noFollowExclude[] = preg_replace( "/^http(s)?:\/\//", '', $url );
}
}
$values['posts_add_nofollow_exclude'] = json_encode( $noFollowExclude );
$form->saveAsSettings( $values );
/* Clear guest page caches */
@@ -351,7 +336,7 @@ class _posting extends \IPS\Dispatcher\Controller
}
/**
* Acronym expansion
* Word expansion
*
* @return string HTML to display
*/
@@ -361,7 +346,7 @@ class _posting extends \IPS\Dispatcher\Controller
/* Create the table */
$table = new \IPS\Helpers\Table\Db( 'core_acronyms', \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&tab=acronymExpansion' ) );
$table->langPrefix = 'acronym_';
$table->langPrefix = 'word_';
$table->mainColumn = 'a_short';
$table->rowClasses = array( 'a_long' => array( 'ipsTable_wrap' ) );
@@ -387,9 +372,9 @@ class _posting extends \IPS\Dispatcher\Controller
$table->rootButtons = array(
'add' => array(
'icon' => 'plus',
'title' => 'acronym_add',
'title' => 'word_add',
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&do=acronym' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('acronym_add') )
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('word_add') )
)
);
@@ -433,7 +418,7 @@ class _posting extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_poll_only', \IPS\Settings::i()->ipb_poll_only ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_poll_creation_after', ( \IPS\Settings::i()->startpoll_cutoff ? TRUE : FALSE ), FALSE, array( 'togglesOn' => array( 'startpoll_cutoff' ) ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'startpoll_cutoff', \IPS\Settings::i()->startpoll_cutoff, FALSE, array( 'unlimited' => -1, 'unlimitedLang' => 'always', 'max' => 43800 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('hours'), 'startpoll_cutoff' ) ); #max is roughly 5 years
$form->add( new \IPS\Helpers\Form\Interval( 'startpoll_cutoff', \IPS\Settings::i()->startpoll_cutoff, FALSE, array( 'valueAs' => \IPS\Helpers\Form\Interval::HOURS, 'unlimited' => -1, 'unlimitedLang' => 'always', 'max' => 43800 ), NULL, NULL, NULL, 'startpoll_cutoff' ) ); #max is roughly 5 years
$form->addHeader('poll_voting');
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_creator_vote', \IPS\Settings::i()->allow_creator_vote ) );
@@ -458,7 +443,7 @@ class _posting extends \IPS\Dispatcher\Controller
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&tab=polls' ), 'saved' );
}
return \IPS\Theme::i()->getTemplate( 'forms' )->blurb( 'polls_blurb' ) . $form;
return \IPS\Theme::i()->getTemplate( 'forms' )->blurb( 'polls_blurb', TRUE, TRUE ) . $form;
}
/**
@@ -536,7 +521,7 @@ class _posting extends \IPS\Dispatcher\Controller
move_uploaded_file( $values['profanity_upload'], $tempFile );
/* Initate a redirector */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&do=importProfanity' )->setQueryString( array( 'file' => $tempFile, 'key' => md5_file( $tempFile ) ) ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&do=importProfanity' )->setQueryString( array( 'file' => $tempFile, 'key' => md5_file( $tempFile ) ) )->csrf() );
}
/* Normal */
@@ -631,17 +616,19 @@ class _posting extends \IPS\Dispatcher\Controller
*/
protected function importProfanity()
{
\IPS\Session::i()->csrfCheck();
if ( !file_exists( \IPS\Request::i()->file ) or md5_file( \IPS\Request::i()->file ) !== \IPS\Request::i()->key )
{
\IPS\Output::i()->error( 'generic_error', '3C256/1', 500, '' );
}
$url = \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&do=importProfanity' )->setQueryString( array( 'file' => \IPS\Request::i()->file, 'key' => \IPS\Request::i()->key ) );
$url = \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&do=importProfanity' )->setQueryString( array( 'file' => \IPS\Request::i()->file, 'key' => \IPS\Request::i()->key ) )->csrf();
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect(
$url,
function( $data )
{
$data = intval( $data );
$data = \intval( $data );
/* Open XML file */
$xml = new \IPS\Xml\XMLReader;
@@ -733,7 +720,7 @@ class _posting extends \IPS\Dispatcher\Controller
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('acronym_a_short');
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('word_expansion');
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Output::i()->title );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( \IPS\Output::i()->title, $form, FALSE );
}
@@ -787,6 +774,8 @@ class _posting extends \IPS\Dispatcher\Controller
*/
public function rebuildThumbnails()
{
\IPS\Session::i()->csrfCheck();
\IPS\Task::queue( 'core', 'RebuildAttachmentThumbnails', array(), 4 );
/* And redirect */