Version 4.3.0

This commit is contained in:
Neo committed 2025-12-19 05:47:12 -08:00
1 parent 96997ddd8e
commit fe1acf984a
1349 files changed
+116159 -67711

No files matched your search

@@ -45,11 +45,11 @@ class _advanced extends \IPS\Dispatcher\Controller
\IPS\Request::i()->tab = isset( \IPS\Request::i()->tab ) ? \IPS\Request::i()->tab : 'settings';
if ( $pos = mb_strpos( \IPS\Request::i()->tab, '-' ) )
{
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( mb_substr( \IPS\Request::i()->tab, 0, $pos ) ) ), mb_substr( \IPS\Request::i()->tab, $pos + 1 ) );
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( mb_substr( \IPS\Request::i()->tab, 0, $pos ) ) ), mb_substr( \IPS\Request::i()->tab, $pos + 1 ) );
}
else
{
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( \IPS\Request::i()->tab ) ) );
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( \IPS\Request::i()->tab ) ) );
}
/* If this is an AJAX request, just return it */
@@ -99,10 +99,7 @@ class _advanced extends \IPS\Dispatcher\Controller
/* Clear it */
\IPS\Data\Cache::i()->clearAll();
\IPS\Data\Store::i()->clearAll();
/* Enable/disable the clearcaches task */
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => intval( \IPS\CACHE_METHOD === 'None' and \IPS\CACHE_PAGE_TIMEOUT ) ), "`key`='clearcache'" );
/* Log and redirect */
\IPS\Session::i()->log( 'acplogs__datastore_settings_updated' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=datastore' ), 'saved' );
@@ -149,7 +146,7 @@ class _advanced extends \IPS\Dispatcher\Controller
{
if ( !$input->htmlId )
{
$input->htmlId = md5( uniqid() );
$input->htmlId = md5( mt_rand() );
}
$extra[] = $input;
@@ -170,7 +167,7 @@ class _advanced extends \IPS\Dispatcher\Controller
/* Cache */
$extra = array();
$toggles = array();
$toggles = array( 'Redis' => array( 'redis_enabled' ) );
$disabled = array();
$cacheConfigurationFields = array();
$options = array(
@@ -200,7 +197,7 @@ class _advanced extends \IPS\Dispatcher\Controller
{
if ( !$input->htmlId )
{
$input->htmlId = md5( uniqid() );
$input->htmlId = md5( mt_rand() );
}
$extra[] = $input;
@@ -218,6 +215,9 @@ class _advanced extends \IPS\Dispatcher\Controller
{
$form->add( $input );
}
$form->add( new \IPS\Helpers\Form\YesNo( 'redis_enabled', \IPS\REDIS_ENABLED, FALSE, array(), NULL, NULL, NULL, 'redis_enabled' ) );
$form->add( new \IPS\Helpers\Form\Number( 'cache_guest_page', \IPS\CACHE_PAGE_TIMEOUT, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'disable' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('for'), \IPS\Member::loggedIn()->language()->addToStack('seconds'), 'cache_guest_page' ) );
/* Handle submissions */
@@ -242,7 +242,7 @@ class _advanced extends \IPS\Dispatcher\Controller
}
/* If we've changed anything, explain to the admin they have to update */
if ( $values['datastore_method'] !== \IPS\STORE_METHOD or str_replace( '\\/', '/', json_encode( $storeConfiguration ) ) !== \IPS\STORE_CONFIG or $values['cache_method'] !== \IPS\CACHE_METHOD or json_encode( $cacheConfiguration ) !== \IPS\CACHE_CONFIG or $values['cache_guest_page'] !== \IPS\CACHE_PAGE_TIMEOUT )
if ( $values['datastore_method'] !== \IPS\STORE_METHOD or str_replace( '\\/', '/', json_encode( $storeConfiguration ) ) !== \IPS\STORE_CONFIG or $values['cache_method'] !== \IPS\CACHE_METHOD or json_encode( $cacheConfiguration ) !== \IPS\CACHE_CONFIG or $values['cache_guest_page'] !== \IPS\CACHE_PAGE_TIMEOUT or \IPS\REDIS_ENABLED != (boolean) $values['redis_enabled'] )
{
/* Connect to cache engine if we can and invalidate any existing caches */
try
@@ -256,17 +256,22 @@ class _advanced extends \IPS\Dispatcher\Controller
}
}
catch( \Exception $e ){}
/* Enable/disable the clearcaches task */
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => intval( $values['cache_method'] === 'None' and $values['cache_guest_page'] ) ), "`key`='clearcache'" );
/* Invalidate any existing datastore records */
try
{
$classname = 'IPS\Data\Store\\' . $values['datastore_method'];
$instance = new $classname( $storeConfiguration );
$instance->clearAll();
}
catch( \Exception $e ){}
/* Reset the last update flag for data store */
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'last_data_store_update' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'last_data_store_update' => time() ) );
/* Display */
$downloadUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=downloadDatastoreConstants' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'] ) );
$checkUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=datastore&checkConstants=1' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'] ) );
$downloadUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=downloadDatastoreConstants' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'], 'redis_enabled' => $values['redis_enabled'] ) );
$checkUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=datastore&checkConstants=1' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'], 'redis_enabled' => $values['redis_enabled'] ) );
return \IPS\Theme::i()->getTemplate( 'settings' )->dataStoreChange( $downloadUrl, $checkUrl );
}
/* Otherwise just log and redirect */
@@ -293,19 +298,38 @@ class _advanced extends \IPS\Dispatcher\Controller
foreach ( \IPS\IPS::defaultConstants() as $k => $v )
{
$val = constant( 'IPS\\' . $k );
if ( $val !== $v and !in_array( $k, array( 'STORE_METHOD', 'STORE_CONFIG', 'CACHE_METHOD', 'CACHE_CONFIG', 'CACHE_PAGE_TIMEOUT', 'SUITE_UNIQUE_KEY' ) ) )
if ( $val !== $v and !in_array( $k, array( 'STORE_METHOD', 'STORE_CONFIG', 'CACHE_METHOD', 'CACHE_CONFIG', 'CACHE_PAGE_TIMEOUT', 'SUITE_UNIQUE_KEY', 'READ_WRITE_SEPARATION', 'REDIS_ENABLED' ) ) )
{
$output .= "define( '{$k}', " . var_export( $val, TRUE ) . " );\n";
}
}
/* We have to treat READ_WRITE_SEPARATION special because admin/index.php always disables it */
if( \file_exists( \IPS\ROOT_PATH . '/constants.php' ) )
{
$constants = \file_get_contents( \IPS\ROOT_PATH . '/constants.php' );
/* Did we sniff the constant out with a quick check? */
if( mb_strpos( $constants, 'READ_WRITE_SEPARATION' ) )
{
preg_match( "/define\(\s*?['\"]READ_WRITE_SEPARATION[\"']\s*?,\s*?(.+?)\);/i", $constants, $matches );
if( isset( $matches[1] ) )
{
$output .= "define( 'READ_WRITE_SEPARATION', " . $matches[1] . " );\n";
}
}
}
$output .= "\n";
$output .= "define( 'REDIS_ENABLED', " . var_export( (boolean) \IPS\Request::i()->redis_enabled, TRUE ) . " );\n";
$output .= "define( 'STORE_METHOD', " . var_export( \IPS\Request::i()->store_method, TRUE ) . " );\n";
$output .= "define( 'STORE_CONFIG', " . var_export( \IPS\Request::i()->store_config, TRUE ) . " );\n";
$output .= "define( 'CACHE_METHOD', " . var_export( \IPS\Request::i()->cache_method, TRUE ) . " );\n";
$output .= "define( 'CACHE_CONFIG', " . var_export( \IPS\Request::i()->cache_config, TRUE ) . " );\n";
$output .= "define( 'CACHE_PAGE_TIMEOUT', " . var_export( (int) \IPS\Request::i()->cache_guest_page, TRUE ) . " );\n";
$output .= "define( 'SUITE_UNIQUE_KEY', " . var_export( mb_substr( md5( uniqid() ), 10, 10 ), TRUE ) . " );\n"; // Regenerate the unique key so there's no conflicts
$output .= "define( 'SUITE_UNIQUE_KEY', " . var_export( mb_substr( md5( mt_rand() ), 10, 10 ), TRUE ) . " );\n"; // Regenerate the unique key so there's no conflicts
$output .= "\n\n\n";
\IPS\Output::i()->sendOutput( $output, 200, 'text/x-php', array( 'Content-Disposition' => 'attachment; filename=constants.php' ) );
@@ -323,9 +347,7 @@ class _advanced extends \IPS\Dispatcher\Controller
/* Generate a cron key if we don't have one */
if ( !\IPS\Settings::i()->task_cron_key )
{
\IPS\Settings::i()->task_cron_key = md5( uniqid() );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Settings::i()->task_cron_key ), array( 'conf_key=?', 'task_cron_key' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'task_cron_key' => md5( mt_rand() ) ) );
}
/* Sort stuff out for the cron setting */
@@ -372,6 +394,7 @@ class _advanced extends \IPS\Dispatcher\Controller
/* Build and show form */
$form = new \IPS\Helpers\Form;
$form->addHeader('task_manager');
$form->add( new \IPS\Helpers\Form\Radio( 'task_use_cron', \IPS\CIC ? 'ips' : \IPS\Settings::i()->task_use_cron, FALSE, $options, function ( $val )
{
$cronFile = \IPS\ROOT_PATH . '/applications/core/interface/task/task.php';
@@ -380,6 +403,17 @@ class _advanced extends \IPS\Dispatcher\Controller
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('task_use_cron_executable', FALSE, array( 'sprintf' => array( $cronFile ) ) ) );
}
}, NULL, NULL, 'task_use_cron' ) );
$form->addHeader( 'security_header_ips' );
if ( !\IPS\CIC )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'xforward_matching', \IPS\Settings::i()->xforward_matching, FALSE ) );
}
$form->add( new \IPS\Helpers\Form\YesNo( 'match_ipaddress', \IPS\Settings::i()->match_ipaddress, FALSE ) );
if( \IPS\BYPASS_ACP_IP_CHECK === TRUE )
{
\IPS\Member::loggedIn()->language()->words['match_ipaddress_warning'] = \IPS\Member::loggedIn()->language()->addToStack('ip_override_warn');
}
$form->addHeader('performance_settings');
$form->add( new \IPS\Helpers\Form\Number( 'widget_cache_ttl', ( isset( \IPS\Settings::i()->widget_cache_ttl ) ) ? \IPS\Settings::i()->widget_cache_ttl : 60, FALSE, array( 'min' => 60 ), NULL, \IPS\Member::loggedIn()->language()->addToStack('for'), \IPS\Member::loggedIn()->language()->addToStack('seconds') ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'auto_polling_enabled', \IPS\Settings::i()->auto_polling_enabled, FALSE ) );
@@ -417,11 +451,18 @@ class _advanced extends \IPS\Dispatcher\Controller
{
\IPS\Dispatcher::i()->checkAcpPermission( 'advanced_manage_tasks' );
$table = new \IPS\Helpers\Table\Db( 'core_tasks', \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=tasks' ) );
$table = new \IPS\Helpers\Table\Db( 'core_tasks', \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=tasks' ), array( array( 'a.app_enabled=1' ) ) );
$table->joins = array(
array( 'select' => 'a.app_enabled', 'from' => array( 'core_applications', 'a' ), 'where' => "a.app_directory=app" )
);
$table->langPrefix = 'task_manager_';
$table->include = array( 'app', 'key', 'frequency', 'next_run', 'last_run' );
$table->mainColumn = 'key';
$table->quickSearch = 'key';
$table->primarySortBy = 'enabled';
$table->primarySortDirection = 'DESC';
$table->sortBy = $table->sortBy ?: 'next_run';
$table->sortDirection = $table->sortDirection ?: 'asc';
$table->quickSearch = function( $val )
@@ -429,11 +470,11 @@ class _advanced extends \IPS\Dispatcher\Controller
$matches = \IPS\Member::loggedIn()->language()->searchCustom( 'task__', $val, TRUE );
if ( count( $matches ) )
{
return '(' . \IPS\Db::i()->in( '`key`', array_keys( $matches ) ) . " OR `key` LIKE '%{$val}%')";
return array( '(' . \IPS\Db::i()->in( '`key`', array_keys( $matches ) ) . " OR `key` LIKE '%{$val}%')" );
}
else
{
return "`key` LIKE '%{$val}%'";
return array( "`key` LIKE '%" . \IPS\Db::i()->escape_string( $val ) . "%'" );
}
};
@@ -603,6 +644,10 @@ class _advanced extends \IPS\Dispatcher\Controller
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'advancedsettings' )->taskResult( TRUE, $output, $task->id );
}
}
catch( \RuntimeException $e )
{
\IPS\Output::i()->error( 'task_class_not_found', '4C124/6', 404, '' );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2C124/1', 404, '' );
@@ -803,7 +848,14 @@ class _advanced extends \IPS\Dispatcher\Controller
}
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Text( 'furl_friendly', $current ? $current['friendly'] : '', FALSE, array(), NULL, \IPS\Settings::i()->base_url . ( \IPS\Settings::i()->htaccess_mod_rewrite ? '' : 'index.php?/' ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'furl_friendly', $current ? $current['friendly'] : '', FALSE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('furl_friendly_placeholder') ), function( $val )
{
if( mb_substr( $val, 0, 3 ) == '{?}' )
{
throw new \DomainException( 'furl_too_greedy' );
}
},
\IPS\Settings::i()->base_url . ( \IPS\Settings::i()->htaccess_mod_rewrite ? '' : 'index.php?/' ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'furl_real', $current ? $current['real'] : '', FALSE, array(), NULL, \IPS\Settings::i()->base_url . 'index.php?' ) );
if ( $values = $form->values() )
@@ -853,15 +905,17 @@ class _advanced extends \IPS\Dispatcher\Controller
}
else
{
$key = 'key' . ( count( $furl ) + 1 );
ksort( $furl );
$keys = array_keys( $furl );
$lastKey = str_replace( 'key', '', end( $keys ) );
$key = 'key' . ( $lastKey + 1 );
$furl[ $key ] = $save;
}
\IPS\Session::i()->log( 'acplogs__advanced_furl_edited' );
$newValue = json_encode( $furl );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $newValue ), array( 'conf_key=?', 'furl_configuration' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'furl_configuration' => $newValue ) );
/* Clear Sidebar Caches */
\IPS\Widget::deleteCaches();
@@ -895,8 +949,7 @@ class _advanced extends \IPS\Dispatcher\Controller
{
unset( $furlDefinition[ \IPS\Request::i()->key ] );
$newValue = json_encode( $furlDefinition );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $newValue ), array( 'conf_key=?', 'furl_configuration' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'furl_configuration' => $newValue ) );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -916,8 +969,7 @@ class _advanced extends \IPS\Dispatcher\Controller
{
\IPS\Dispatcher::i()->checkAcpPermission( 'advanced_manage_furls' );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => NULL ), array( 'conf_key=?', 'furl_configuration' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'furl_configuration' => NULL ) );
unset( \IPS\Data\Store::i()->furl_configuration );
/* Clear guest page caches */
@@ -42,9 +42,17 @@ class _contactus extends \IPS\Dispatcher\Controller
{
$form = $this->_getConfigForm();
if ( $values = $form->values() )
if ( $values = $form->values( true ) )
{
$form->saveAsSettings();
/* If we unselect 'everyone' and save, an empty string is passed through, so the default value is picked up in Settings::changeValues(),
which is the 'everyone' preference...the end result is that everyone gets rechecked when you uncheck it. To counter that, we'll store an invalid
value here. */
if( $values['contact_access'] === '' )
{
$values['contact_access'] = '-1';
}
$form->saveAsSettings( $values );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -49,22 +49,18 @@ class _email extends \IPS\Dispatcher\Controller
$settingsForm->add( new \IPS\Helpers\Form\Email( 'email_in', \IPS\Settings::i()->email_in, TRUE ) );
$settingsForm->add( new \IPS\Helpers\Form\Color( 'email_color', \IPS\Settings::i()->email_color, TRUE ) );
$settingsForm->add( new \IPS\Helpers\Form\Upload( 'email_logo', \IPS\Settings::i()->email_logo ? \IPS\File::get( 'core_Theme', \IPS\Settings::i()->email_logo ) : NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'core_Theme' ) ) );
$settingsForm->add( new \IPS\Helpers\Form\YesNo( 'social_links_in_email', \IPS\Settings::i()->social_links_in_email, FALSE, array(), NULL, NULL, NULL, 'social_links_in_email' ) );
if ( \IPS\Settings::i()->promote_community_enabled )
{
$settingsForm->add( new \IPS\Helpers\Form\YesNo( 'our_picks_in_email', \IPS\Settings::i()->our_picks_in_email, FALSE, array(), NULL, NULL, NULL, 'our_picks_in_email' ) );
}
$settingsForm->addHeader( 'advanced_settings' );
$method = \IPS\Settings::i()->mail_method;
$disabled = array();
if ( \IPS\Settings::i()->sparkpost_api_key )
{
if ( \IPS\Settings::i()->sparkpost_use_for == 2 )
{
$method = 'sparkpost';
}
}
else
{
$disabled[] = 'sparkpost';
}
if ( \IPS\Settings::i()->sendgrid_api_key )
{
if ( \IPS\Settings::i()->sendgrid_use_for == 2 )
@@ -76,12 +72,18 @@ class _email extends \IPS\Dispatcher\Controller
{
$disabled[] = 'sendgrid';
}
/* We previously renamed this to 'php' */
if( $method == 'mail' )
{
$method = 'php';
}
$settingsForm->add( new \IPS\Helpers\Form\Radio( 'mail_method', $method, TRUE, array(
'options' => array( 'php' => ( \IPS\CIC ? 'mail_method_cic' : 'mail_method_php' ), 'smtp' => 'mail_method_smtp', 'sendgrid' => 'mail_method_sendgrid', 'sparkpost' => 'mail_method_sparkpost' ),
'options' => array( 'php' => ( \IPS\CIC ? 'mail_method_cic' : 'mail_method_php' ), 'smtp' => 'mail_method_smtp', 'sendgrid' => 'mail_method_sendgrid' ),
'disabled' => $disabled,
'toggles' => array(
'mail' => array( 'php_mail_extra' ),
'php' => array( 'php_mail_extra' ),
'smtp' => array( 'smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass', 'smtp_helo', 'smtp_protocol' ),
)
) ) );
@@ -107,15 +109,6 @@ class _email extends \IPS\Dispatcher\Controller
}
}
if ( $values['mail_method'] != 'sparkpost' and \IPS\Settings::i()->sparkpost_use_for == 2 )
{
$values['sparkpost_use_for'] = 1;
}
elseif ( $values['mail_method'] == 'sparkpost' )
{
$values['sparkpost_use_for'] = 2;
}
if ( $values['mail_method'] != 'sendgrid' and \IPS\Settings::i()->sendgrid_use_for == 2 )
{
$values['sendgrid_use_for'] = 1;
@@ -125,6 +118,11 @@ class _email extends \IPS\Dispatcher\Controller
$values['sendgrid_use_for'] = 2;
}
if ( $values['email_logo'] )
{
$values['email_logo'] = (string) $values['email_logo'];
}
$settingsForm->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__email_settings' );
@@ -239,7 +237,7 @@ class _email extends \IPS\Dispatcher\Controller
$val = \IPS\Member::loggedIn()->language()->get('phpmail_not_sent');
}
return \IPS\Theme::i()->getTemplate( 'logs' )->emailErrorLog( nl2br( htmlspecialchars( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) ), $row );
return \IPS\Theme::i()->getTemplate( 'logs' )->emailErrorLog( nl2br( htmlspecialchars( $val, ENT_DISALLOWED, 'UTF-8', FALSE ) ), $row );
},
'mlog_content' => function( $val, $row )
{
@@ -48,9 +48,13 @@ class _general extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Editor( 'site_offline_message', \IPS\Settings::i()->site_offline_message, FALSE, array( 'app' => 'core', 'key' => 'Admin', 'autoSaveKey' => 'onlineoffline', 'attachIds' => array( NULL, NULL, 'site_offline_message' ) ), NULL, NULL, NULL, 'site_offline_message_id' ) );
$form->add( new \IPS\Helpers\Form\Address( 'site_address', \IPS\GeoLocation::buildFromJson( \IPS\Settings::i()->site_address ), FALSE ) );
$form->add( new \IPS\Helpers\Form\Stack( 'site_social_profiles', \IPS\Settings::i()->site_social_profiles ? json_decode( \IPS\Settings::i()->site_social_profiles, true ) : array(), FALSE, array( 'stackFieldType' => '\IPS\core\Form\SocialProfiles', 'maxItems' => 50, 'key' => array( 'placeholder' => 'http://example.com', 'size' => 20 ) ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'site_twitter_id', \IPS\Settings::i()->site_twitter_id, FALSE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('site_twitter_id_placeholder'), 'size' => 20 ) ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'copyright_line', NULL, FALSE, array( 'app' => 'core', 'key' => 'copyright_line_value', 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('copyright_line_placeholder') ) ) );
$form->add( new \IPS\Helpers\Form\Stack( 'upgrade_email', explode( ',', \IPS\Settings::i()->upgrade_email ), FALSE, array( 'stackFieldType' => 'Email', 'maxItems' => 5 ) ) );
// $form->add( new \IPS\Helpers\Form\YesNo( 'diagnostics_reporting', \IPS\Settings::i()->diagnostics_reporting ) );
/* $form->add( new \IPS\Helpers\Form\CheckboxSet( 'diagnostics_reporting', array( 'usage' => ( (bool) \IPS\Settings::i()->usage_reporting ), 'diagnostics' => ( (bool) \IPS\Settings::i()->diagnostics_reporting ) ), FALSE, array( 'options' => array(
'usage' => 'diagnostics_reporting_usage',
'diagnostics' => 'diagnostics_reporting_diagnostics',
) ) ) ); */
if ( $values = $form->values() )
{
@@ -61,6 +65,12 @@ class _general extends \IPS\Dispatcher\Controller
return (bool) $value['key'];
} ) );
$values['site_address'] = json_encode( $values['site_address'] );
$values['upgrade_email'] = implode( ',', $values['upgrade_email'] );
$values['usage_reporting'] = in_array( 'usage', $values['diagnostics_reporting'] );
$values['diagnostics_reporting'] = in_array( 'diagnostics', $values['diagnostics_reporting'] );
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => intval( $values['usage_reporting'] ) ), array( '`key`=?', 'usagereporting' ) );
$form->saveAsSettings( $values );
+410 -190
View File
@@ -1,11 +1,11 @@
<?php
/**
* @brief Login Handlers
* @brief Login Methods
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 15 Mar 2013
* @since 12 May 2017
*/
namespace IPS\core\modules\admin\settings;
@@ -18,14 +18,19 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
}
/**
* Login Handlers
* Login Methods
*/
class _login extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\Login\LoginAbstract';
protected $nodeClass = 'IPS\Login\Handler';
/**
* Show the "add" button in the page root rather than the table root
*/
protected $_addButtonInRoot = FALSE;
/**
* Execute
@@ -34,54 +39,170 @@ class _login extends \IPS\Node\Controller
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'login_manage' );
\IPS\Dispatcher::i()->checkAcpPermission( 'login_access' );
return parent::execute();
}
/**
* Get Root Buttons
*
* @return array
*/
public function _getRootButtons()
{
$buttons = parent::_getRootButtons();
if ( isset( $buttons['add'] ) )
{
$buttons['add']['link'] = $buttons['add']['link']->setQueryString( '_new', 1 );
}
return $buttons;
}
/**
* Manage
*
* @return void
* @return void
*/
protected function manage()
{
\IPS\Output::i()->sidebar['actions'] = array(
'settings' => array(
'title' => 'login_settings',
'icon' => 'cog',
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&do=settings' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('login_settings') )
),
'forcelogout' => array(
'title' => 'force_all_logout',
'icon' => 'lock',
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&do=forceLogout' ),
'data' => array( 'confirm' => '' ),
),
);
/* Work out tabs */
$tabs = array();
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'login_manage' ) )
{
$tabs['handlers'] = 'login_handlers';
}
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'login_settings' ) )
{
$tabs['settings'] = 'login_settings';
}
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'registration_settings' ) )
{
$tabs['registration'] = 'registration_settings';
}
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'login_account_management' ) )
{
$tabs['accountsettings'] = 'account_management_settings';
}
/* Show IPS Connect "master" information */
$masterUrl = \IPS\Http\Url::internal( 'applications/core/interface/ipsconnect/ipsconnect.php', 'none' );
$masterKey = \IPS\CONNECT_MASTER_KEY ?: md5( md5( \IPS\Settings::i()->sql_user . \IPS\Settings::i()->sql_pass ) . \IPS\Settings::i()->board_start );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'login_ipsconnect_info', FALSE, array( 'sprintf' => array( $masterUrl, $masterKey ) ) ), 'info', NULL, FALSE );
return parent::manage();
/* Get active tab */
if ( isset( \IPS\Request::i()->tab ) and isset( $tabs[ \IPS\Request::i()->tab ] ) )
{
$activeTab = \IPS\Request::i()->tab;
}
else
{
$_tabs = array_keys( $tabs ) ;
$activeTab = array_shift( $_tabs );
}
/* Get active tab contents */
$output = '';
switch ( $activeTab )
{
case 'handlers':
\IPS\Dispatcher::i()->checkAcpPermission( 'login_manage' );
parent::manage();
$output = \IPS\Output::i()->output;
break;
case 'settings':
$output = $this->_settings();
break;
case 'registration':
$output = $this->_registration();
break;
case 'accountsettings':
$output = $this->_accountsettings();
break;
}
/* Output */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_settings_login');
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->output = $output;
}
else
{
\IPS\Output::i()->sidebar['actions'] = array(
'forcelogout' => array(
'title' => 'force_all_logout',
'icon' => 'lock',
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&do=forceLogout' ),
'data' => array( 'confirm' => '' ),
),
);
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, $output, \IPS\Http\Url::internal( "app=core&module=settings&controller=login" ) );
}
}
/**
* Force all users to be logged out
* Add/Edit Form
*
* @return void
* @return void
*/
protected function forceLogout()
protected function form()
{
\IPS\Db::i()->update( 'core_members_known_devices', array( 'login_key' => NULL ) );
\IPS\Db::i()->delete( 'core_sessions' );
\IPS\Session::i()->log( 'acplogs__logout_force' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login' ), 'logged_out_force' );
if ( \IPS\Request::i()->id )
{
return parent::form();
}
else
{
\IPS\Output::i()->output = new \IPS\Helpers\Wizard( array(
'login_handler' => function( $data )
{
$options = array();
foreach ( \IPS\Login\Handler::handlerClasses() as $class )
{
if ( !$class::$allowMultiple )
{
foreach ( \IPS\Login\Handler::roots() as $handler )
{
if ( $handler instanceof $class )
{
continue 2;
}
}
}
$options[ $class ] = $class::getTitle();
}
$form = new \IPS\Helpers\Form( 'login_handler_1', 'continue' );
$form->add( new \IPS\Helpers\Form\Radio( 'login_handler', TRUE, NULL, array( 'options' => $options ) ) );
if ( $values = $form->values() )
{
return array( 'handler' => $values['login_handler'] );
}
return $form;
},
'login_details' => function( $data )
{
$node = new $data['handler'];
$node->classname = $data['handler'];
$form = $this->_addEditForm( $node );
if ( $values = $form->values() )
{
try
{
$node->settings = array();
$node->order = \IPS\Db::i()->select( 'MAX(login_order)', $node::$databaseTable )->first() + 1;
$node->saveForm( $node->formatFormValues( $values ) );
\IPS\Session::i()->log( 'acplog__node_created', array( $this->title => TRUE, $node->titleForLog() => FALSE ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=settings&controller=login') );
}
catch ( \LogicException $e )
{
$form->error = $e->getMessage();
}
}
return $form;
}
), \IPS\Http\Url::internal('app=core&module=settings&controller=login&do=form') );
}
}
/**
@@ -92,48 +213,78 @@ class _login extends \IPS\Node\Controller
*/
protected function enableToggle()
{
$node = \IPS\Login\LoginAbstract::load( \IPS\Request::i()->id );
$loginMethod = \IPS\Login\Handler::load( \IPS\Request::i()->id );
if ( \IPS\Request::i()->status )
{
if ( method_exists( $node, 'testSettings' ) )
try
{
try
{
$node->testSettings();
}
catch ( \Exception $e )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=settings&controller=login&do=form&id={$node->key}" ) );
}
$loginMethod->testSettings();
}
catch ( \Exception $e )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=settings&controller=login&do=form&id={$loginMethod->id}" ) );
}
}
else
{
$others = \IPS\Db::i()->select( 'count(*)', 'core_login_handlers', array( 'login_enabled=? and login_key<>?', 1, $node->key ) )->first();
if( !$others )
{
\IPS\Output::i()->error( 'login_atleast_one', '1C166/3', 403, '' );
}
/* Allow the login handler to do stuff on-disable */
$node->onDisable();
$this->_disableCheck( $loginMethod );
}
/* Clear guest page caches */
/* Clear caches */
unset( \IPS\Data\Store::i()->loginMethods );
\IPS\Data\Cache::i()->clearAll();
/* Toggle */
return parent::enableToggle();
}
/**
* Settings
* Delete
*
* @return void
*/
protected function settings()
protected function delete()
{
/* Check it's okay */
$loginMethod = \IPS\Login\Handler::load( \IPS\Request::i()->id );
$this->_disableCheck( $loginMethod );
/* Do it */
parent::delete();
/* Clear caches */
unset( \IPS\Data\Store::i()->loginMethods );
\IPS\Data\Cache::i()->clearAll();
}
/**
* If a particular method is disabled/deleted - will we still be able to log in?
*
* @param \IPS\Login\Handler $methodToRemove Handler to be disabled/deleted
* @return void
*/
protected function _disableCheck( \IPS\Login\Handler $methodToRemove )
{
foreach ( \IPS\Login::methods() as $method )
{
if ( $method != $methodToRemove and $method->canProcess( \IPS\Member::loggedIn() ) and $method->acp )
{
return true;
}
}
\IPS\Output::i()->error( 'login_handler_cannot_disable', '1C166/5', 403, '' );
}
/**
* Login Settings
*
* @return string
*/
protected function _settings()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'login_settings' );
/* Build Form */
$form = new \IPS\Helpers\Form();
$form->addHeader( 'ipb_bruteforce_attempts' );
@@ -142,32 +293,6 @@ class _login extends \IPS\Node\Controller
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_bruteforce_unlock', \IPS\Settings::i()->ipb_bruteforce_unlock, FALSE, array(), NULL, NULL, NULL, 'ipb_bruteforce_unlock' ) );
$form->addHeader( 'login_settings' );
$form->add( new \IPS\Helpers\Form\YesNo( 'new_device_email', \IPS\Settings::i()->new_device_email, FALSE ) );
/* Check if the site works over HTTPS before we allow them to change that */
$httpsValue = \IPS\Settings::i()->logins_over_https;
$httpsDisabled = FALSE;
$toggles = array();
if ( mb_substr( \IPS\Settings::i()->base_url, 0, 8 ) === 'https://' )
{
$httpsValue = TRUE;
$httpsDisabled = TRUE;
\IPS\Member::loggedIn()->language()->words['logins_over_https_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'logins_over_https_enabled', FALSE );
}
else
{
try
{
$response = \IPS\Http\Url::external( 'https://' . mb_substr( \IPS\Settings::i()->base_url, 7 ) )->request()->get();
}
catch ( \IPS\Http\Request\Exception $e )
{
$httpsValue = FALSE;
$httpsDisabled = TRUE;
$toggles[] = 'form_logins_over_https_warning';
\IPS\Member::loggedIn()->language()->words['logins_over_https_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'logins_over_https_disabled', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) );
}
}
$form->add( new \IPS\Helpers\Form\YesNo( 'logins_over_https', $httpsValue, FALSE, array( 'disabled' => $httpsDisabled, 'togglesOn' => $toggles ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'disable_anonymous', !\IPS\Settings::i()->disable_anonymous, FALSE, array(), NULL, NULL, NULL, 'disable_anonymous' ) );
/* Save */
@@ -189,125 +314,220 @@ class _login extends \IPS\Node\Controller
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), "`key`='unlockmembers'" );
}
/* Cache this for the later check */
$currentLoginSetting = \IPS\Settings::i()->logins_over_https;
$form->saveAsSettings( $values );
/* Reset datastore if https setting has changed */
if( $currentLoginSetting != $values['logins_over_https'] )
{
\IPS\Theme::deleteCompiledCss();
\IPS\Data\Store::i()->clearAll();
}
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
\IPS\Session::i()->log( 'acplogs__login_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login' ), 'saved' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&tab=settings' ), 'saved' );
}
/* Display */
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( 'login_settings', $form, FALSE );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'login_settings' );
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( 'login_settings' ) );
return (string) $form;
}
/**
* Manually reprocess IPS Connect requests that are queued
* HTTPS check
*
* @return null
*/
protected function httpsCheck()
{
try
{
$response = \IPS\Http\Url::external( 'https://' . mb_substr( \IPS\Settings::i()->base_url, 7 ) )->request()->get();
\IPS\Output::i()->output = $response;
}
catch ( \IPS\Http\Request\Exception $e )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->message( $e->getMessage() ?: '500_error_title', 'error' );
}
}
/**
* Registration Settings
*
* @return string
*/
protected function _registration()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'registration_settings' );
/* Build Form */
$form = new \IPS\Helpers\Form();
$form->addHeader('registration_standard_settings');
$form->addMessage('registration_standard_settings_blurb');
$form->add( new \IPS\Helpers\Form\Radio( 'allow_reg', \IPS\Login::registrationType(), FALSE, array(
'options' => array(
'normal' => 'allow_reg_normal',
'full' => 'allow_reg_full',
'redirect' => 'allow_reg_redirect',
'disabled' => 'allow_reg_disabled'
),
'toggles' => array(
'full' => array( 'minimum_age', 'use_coppa' ),
'redirect' => array( 'allow_reg_target' )
),
'disabled' => \IPS\Login\Handler::findMethod( 'IPS\Login\Handler\Standard' ) ? array() : array( 'normal', 'full' )
) ) );
$form->add( new \IPS\Helpers\Form\Url( 'allow_reg_target', \IPS\Settings::i()->allow_reg_target, NULL, array(), function( $val )
{
if ( !$val and \IPS\Request::i()->allow_red === 'redirect' )
{
throw new \DomainException('form_required');
}
}, NULL, NULL, 'allow_reg_target' ) );
$form->add( new \IPS\Helpers\Form\Number( 'minimum_age', \IPS\Settings::i()->minimum_age, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'any_age' ), NULL, NULL, NULL, 'minimum_age' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'use_coppa', \IPS\Settings::i()->use_coppa, FALSE, array( 'togglesOn' => array( 'coppa_fax', 'coppa_address' ) ), NULL, NULL, NULL, 'use_coppa' ) );
$form->add( new \IPS\Helpers\Form\Tel( 'coppa_fax', \IPS\Settings::i()->coppa_fax, FALSE, array(), NULL, NULL, NULL, 'coppa_fax' ) );
$form->add( new \IPS\Helpers\Form\Address( 'coppa_address', \IPS\GeoLocation::buildFromJson( \IPS\Settings::i()->coppa_address ), FALSE, array(), NULL, NULL, NULL, 'coppa_address' ) );
$form->addHeader('registration_global_settings');
$form->addMessage('registration_global_settings_blurb');
$form->add( new \IPS\Helpers\Form\Radio( 'reg_auth_type', \IPS\Settings::i()->reg_auth_type, FALSE, array(
'options' => array( 'user' => 'reg_auth_type_user', 'admin' => 'reg_auth_type_admin', 'admin_user' => 'reg_auth_type_admin_user', 'none' => 'reg_auth_type_none' ),
'toggles' => array( 'user' => array( 'validate_day_prune' ), 'admin_user' => array( 'validate_day_prune' ) )
), NULL, NULL, NULL, 'reg_auth_type' ) );
$form->add( new \IPS\Helpers\Form\Number( 'validate_day_prune', \IPS\Settings::i()->validate_day_prune, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'validate_day_prune' ) );
$form->add( new \IPS\Helpers\Form\Stack( 'allowed_reg_email', explode( ',', \IPS\Settings::i()->allowed_reg_email ), FALSE, array( 'placeholder' => 'mycompany.com' ), function( $value ) {
if( isset( $value[0] ) AND mb_stripos( $value[0], '@' ) )
{
throw new \DomainException( 'allowed_reg_email_email_detected' );
}
}, NULL, NULL ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'new_reg_notify', \IPS\Settings::i()->new_reg_notify, FALSE, array(), NULL, NULL, NULL, 'new_reg_notify' ) );
$form->add( new \IPS\Helpers\Form\Radio( 'force_reg_terms', \IPS\Settings::i()->force_reg_terms, FALSE, array( 'options' => array(
'0' => 'force_reg_terms_0',
'1' => 'force_reg_terms_1',
) ) ) );
$form->add( new \IPS\Helpers\Form\Radio( 'updates_consent_default', \IPS\Settings::i()->updates_consent_default, FALSE, array(
'options' => array( 'enabled' => 'updates_consent_enabled', 'disabled' => 'updates_consent_disabled' ),
), NULL, NULL, NULL, 'updates_consent_default' ) );
/* Save */
if ( $values = $form->values() )
{
/* Save */
if ( isset( $values['allowed_reg_email'] ) and is_array( $values['allowed_reg_email'] ) )
{
$values['allowed_reg_email'] = implode( ',', $values['allowed_reg_email'] );
}
$form->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__registration_settings' );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
/* Redirect */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&tab=registration' ), 'saved' );
}
/* Display */
return (string) $form;
}
/**
* Account Management Settings
*
* @return string
*/
protected function _accountsettings()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'login_account_management' );
/* Build Form */
$form = new \IPS\Helpers\Form();
$form->addHeader( 'security_header_accounts' );
$form->add( new \IPS\Helpers\Form\YesNo( 'password_strength_meter', \IPS\Settings::i()->password_strength_meter, FALSE, array( 'togglesOn' => array( 'password_strength_meter_enforce' ) ), NULL, NULL, NULL, 'password_strength_meter' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'password_strength_meter_enforce', \IPS\Settings::i()->password_strength_meter_enforce, FALSE, array( 'togglesOn' => array( 'password_strength_option' ) ), NULL, NULL, NULL, 'password_strength_meter_enforce' ) );
$strengthOptions = array(
'3' => 'strength_3',
'4' => 'strength_4',
'5' => 'strength_5',
);
$form->add( new \IPS\Helpers\Form\Radio( 'password_strength_option', \IPS\Settings::i()->password_strength_option, FALSE, array( 'options' => $strengthOptions ), NULL, NULL, NULL, 'password_strength_option' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'device_management', \IPS\Settings::i()->device_management, FALSE ) );
$form->addHeader('account_management_email_pass');
$form->addMessage('account_management_email_pass_blurb');
$form->add( new \IPS\Helpers\Form\Radio( 'allow_email_changes', \IPS\Settings::i()->allow_email_changes, FALSE, array(
'options' => array(
'normal' => 'allow_email_changes_normal',
'redirect' => 'allow_email_changes_redirect',
'disabled' => 'allow_email_changes_disabled',
),
'toggles' => array(
'redirect' => array( 'allow_email_changes_target' )
)
) ) );
$form->add( new \IPS\Helpers\Form\Url( 'allow_email_changes_target', \IPS\Settings::i()->allow_email_changes_target, NULL, array(), function( $val )
{
if ( !$val and \IPS\Request::i()->allow_email_changes === 'redirect' )
{
throw new \DomainException('form_required');
}
}, NULL, NULL, 'allow_email_changes_target' ) );
$form->add( new \IPS\Helpers\Form\Radio( 'allow_password_changes', \IPS\Settings::i()->allow_password_changes, FALSE, array(
'options' => array(
'normal' => 'allow_password_changes_normal',
'redirect' => 'allow_password_changes_redirect',
'disabled' => 'allow_password_changes_disabled',
),
'toggles' => array(
'redirect' => array( 'allow_password_changes_target' )
)
) ) );
$form->add( new \IPS\Helpers\Form\Url( 'allow_password_changes_target', \IPS\Settings::i()->allow_password_changes_target, NULL, array(), function( $val )
{
if ( !$val and \IPS\Request::i()->allow_password_changes === 'redirect' )
{
throw new \DomainException('form_required');
}
}, NULL, NULL, 'allow_password_changes_target' ) );
$form->add( new \IPS\Helpers\Form\Radio( 'allow_forgot_password', \IPS\Settings::i()->allow_forgot_password, FALSE, array(
'options' => array(
'normal' => 'allow_forgot_password_normal',
'handler' => 'allow_forgot_password_handler',
'redirect' => 'allow_forgot_password_redirect',
'disabled' => 'allow_forgot_password_disabled',
),
'toggles' => array(
'redirect' => array( 'allow_forgot_password_target' )
)
) ) );
$form->add( new \IPS\Helpers\Form\Url( 'allow_forgot_password_target', \IPS\Settings::i()->allow_forgot_password_target, NULL, array(), function( $val )
{
if ( !$val and \IPS\Request::i()->allow_forgot_password === 'redirect' )
{
throw new \DomainException('form_required');
}
}, NULL, NULL, 'allow_forgot_password_target' ) );
/* Save */
if ( $values = $form->values() )
{
$values['password_strength_meter_enforce'] = $values['password_strength_meter'] ? $values['password_strength_meter_enforce'] : FALSE;
$form->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__account_management_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&tab=accountsettings' ), 'saved' );
}
/* Display */
return (string) $form;
}
/**
* Force all users to be logged out
*
* @return void
*/
protected function retryConnect()
protected function forceLogout()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('try_slave_request_again');
\IPS\Db::i()->update( 'core_members_known_devices', array( 'login_key' => NULL ) );
\IPS\Db::i()->delete( 'core_sessions' );
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect(
\IPS\Http\Url::internal( "app=core&module=settings&controller=login&do=retryConnect&slave=" . \IPS\Request::i()->slave ),
function( $data )
{
/* On first cycle get data */
if ( !is_array( $data ) )
{
/* Get total number of failures to process for progress bar */
$data = array( 'done' => 0, 'total' => count( \IPS\Db::i()->select( 'id', 'core_ipsconnect_queue', array( 'slave_id=?', intval( \IPS\Request::i()->slave ) ) ) ) );
}
/* Get the next request */
try
{
$request = \IPS\Db::i()->select( 'q.*, s.*', array( 'core_ipsconnect_queue', 'q' ), array( 'q.slave_id=?', intval( \IPS\Request::i()->slave ) ), 'q.id asc', array( 0, 1 ) )
->join( array( 'core_ipsconnect_slaves', 's' ), "s.slave_id=q.slave_id" )
->first();
/* Try to process request again */
try
{
parse_str( $request['request_url'], $variables );
$response = \IPS\Http\Url::external( $request['slave_url'] )
->setQueryString( $variables )
->request()
->get();
if( $response->httpResponseCode !== NULL AND $response->httpResponseCode > 200 )
{
/* Update fail count */
\IPS\Db::i()->update( 'core_ipsconnect_queue', 'fail_count=fail_count+1', array( 'id=?', $request['id'] ) );
/* Show error message */
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'connect_failure_details', FALSE, array( 'sprintf' =>
array( \IPS\Member::loggedIn()->language()->addToStack('connect_slavefail_http', FALSE, array( 'sprintf' => array( $response->httpResponseCode ) ) ) )
) ), '4C166/1', 503, '' );
}
$response = $response->decodeJson();
/* If this is a registered slave but the slave is telling us Connect is disabled, remove it */
if( isset( $response['status'] ) AND $response['status'] == 'DISABLED' )
{
\IPS\Db::i()->update( 'core_ipsconnect_slaves', array( 'slave_enabled' => 0 ), array( 'slave_id=?', $request['slave_id'] ) );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Db::i()->select( 'COUNT(*)', 'core_ipsconnect_slaves', array( 'slave_enabled=?', 1 ) )->first() ), array( 'conf_key=?', 'connect_slaves' ) );
unset( \IPS\Data\Store::i()->settings );
}
else if( !isset( $response['status'] ) OR $response['status'] != 'SUCCESS' )
{
throw new \RuntimeException( $response['status'] );
}
/* If we are here, request succeeded - remove from queue */
\IPS\Db::i()->delete( 'core_ipsconnect_queue', array( 'id=?', $request['id'] ) );
}
catch( \RuntimeException $e )
{
/* Update fail count */
\IPS\Db::i()->update( 'core_ipsconnect_queue', 'fail_count=fail_count+1', array( 'id=?', $request['id'] ) );
/* The request failed - show the admin why */
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack('connect_failure_details', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) ), '4C166/2', 503, '' );
}
$data['done']++;
/* Return null to indicate we are done */
return array( $data, 'connect_retry_success', round( $data['done'] / $data['total'] ) );
}
catch( \UnderflowException $e )
{
\IPS\Session::i()->log( 'acplog__connect_queue_cleared' );
/* Disable task */
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), "`key`='connect'" );
return NULL;
}
},
function()
{
/* And redirect back to the dashboard */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=overview&controller=dashboard' ), 'connect_queue_cleared' );
}
);
\IPS\Session::i()->log( 'acplogs__logout_force' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login' ), 'logged_out_force' );
}
}
@@ -79,7 +79,7 @@ class _posting extends \IPS\Dispatcher\Controller
protected function manage()
{
/* Work out output */
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $this->activeTab ) ) );
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
/* If this is an AJAX request, just return it */
if( \IPS\Request::i()->isAjax() )
@@ -109,8 +109,8 @@ class _posting extends \IPS\Dispatcher\Controller
$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', 'images' => 'attach_allowed_types_images', 'none' => 'attach_allowed_types_none' ),
'toggles' => array( 'all' => array( 'attach_allowed_extensions', 'attachment_resample_size', 'attachment_image_size' ), 'images' => array( 'attachment_resample_size', 'attachment_image_size' ) )
'options' => array( 'all' => 'attach_allowed_types_all', 'media' => 'attach_allowed_types_media', 'images' => 'attach_allowed_types_images', 'none' => 'attach_allowed_types_none' ),
'toggles' => array( 'all' => array( 'attach_allowed_extensions', 'attachment_resample_size', 'attachment_image_size' ), 'media' => array( 'attachment_resample_size', 'attachment_image_size' ), 'images' => array( 'attachment_resample_size', 'attachment_image_size' ) )
) ) );
$form->add( new \IPS\Helpers\Form\Text( 'attach_allowed_extensions', \IPS\Settings::i()->attach_allowed_extensions ? explode( ',', \IPS\Settings::i()->attach_allowed_extensions ) : NULL, FALSE, array( 'nullLang' => 'no_restriction', 'autocomplete' => array( 'freeChoice' => TRUE, 'source' => array( 'doc', 'docx', 'log', 'msg', 'odt', 'pages', 'rtf', 'tex', 'txt', 'wpd', 'wps', 'csv', 'dat', 'gbr', 'ged', 'key', 'keychain', 'pps', 'ppt', 'pptx', 'sdf', 'tar', 'tax2012', 'tax2014', 'vcf', 'xml', 'aif', 'iff', 'm3u', 'm4a', 'mid', 'mp3', 'mpa', 'ra', 'wav', 'wma', '3g2', '3gp', 'asf', 'asx', 'avi', 'flv', 'm4v', 'mov', 'mp4', 'mpg', 'rm', 'srt', 'swf', 'vob', 'wmv', '3dm', '3ds', 'max', 'obj', 'bmp', 'dds', 'gif', 'jpg', 'png', 'psd', 'pspimage', 'tga', 'thm', 'tif', 'tiff', 'yuv', 'ai', 'eps', 'ps', 'svg', 'indd', 'pct', 'pdf', 'xlr', 'xls', 'xlsx', 'accdb', 'db', 'dbf', 'mdb', 'pdb', 'sql', 'apk', 'app', 'bat', 'cgi', 'com', 'exe', 'gadget', 'jar', 'pif', 'vb', 'wsf', 'dem', 'gam', 'nes', 'rom', 'sav', 'dwg', 'dxf', 'gpx', 'kml', 'kmz', 'asp', 'aspx', 'cer', 'cfm', 'csr', 'css', 'htm', 'html', 'js', 'jsp', 'php', 'rss', 'xhtml', 'crx', 'plugin', 'fnt', 'fon', 'otf', 'ttf', 'cab', 'cpl', 'cur', 'deskthemepack', 'dll', 'dmp', 'drv', 'icns', 'ico', 'lnk', 'sys', 'cfg', 'ini', 'prf', 'hqx', 'mim', 'uue', '7z', 'cbr', 'deb', 'gz', 'pkg', 'rar', 'rpm', 'sitx', 'tar.gz', 'zip', 'zipx', 'bin', 'cue', 'dmg', 'iso', 'mdf', 'toast', 'vcd', 'c', 'class', 'cpp', 'cs', 'dtd', 'fla', 'h', 'java', 'lua', 'm', 'pl', 'py', 'sh', 'sln', 'swift', 'vcxproj', 'xcodeproj', 'bak', 'tmp', 'crdownload', 'ics', 'msi', 'part', 'torrent' ) ) ), NULL, NULL, NULL, 'attach_allowed_extensions' ) );
$form->addHeader('posting_images');
@@ -170,7 +170,7 @@ 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' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('dellog_days_after_deleted') ) );
$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') ) );
/* Save values */
if ( $values = $form->values() )
@@ -191,7 +191,7 @@ class _posting extends \IPS\Dispatcher\Controller
if( $values['rebuildImageProxy'] )
{
/* Remove any existing rebuilds */
\IPS\Db::i()->delete( 'core_queue', array( '`key`=? OR `key`=?', 'RebuildImageProxy', 'RebuildImageProxyNonContent' ) );
\IPS\Db::i()->delete( 'core_queue', \IPS\Db::i()->in( '`key`', array( 'RebuildImageProxy', 'RebuildImageProxyNonContent', 'DeleteImageProxyFiles' ) ) );
/* Unset task datastore */
unset( \IPS\Data\Store::i()->currentImageProxyRebuild );
@@ -199,21 +199,32 @@ class _posting extends \IPS\Dispatcher\Controller
$enableDisable = $values['remote_image_proxy'] ? TRUE : FALSE;
foreach ( \IPS\Content::routedClasses( FALSE, TRUE ) as $class )
{
try
if( isset( $class::$databaseColumnMap['content'] ) )
{
\IPS\Task::queue( 'core', 'RebuildImageProxy', array( 'class' => $class, 'status' => $enableDisable ), 5 );
try
{
\IPS\Task::queue( 'core', 'RebuildImageProxy', array( 'class' => $class, 'status' => $enableDisable ), 4 );
}
catch( \OutOfRangeException $ex ) { }
}
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 ), 5 );
\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'] );
$form->saveAsSettings( $values );
@@ -417,14 +428,26 @@ class _posting extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Number( 'max_poll_choices', \IPS\Settings::i()->max_poll_choices ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'poll_allow_public', \IPS\Settings::i()->poll_allow_public ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_poll_only', \IPS\Settings::i()->ipb_poll_only ) );
$form->add( new \IPS\Helpers\Form\Number( 'startpoll_cutoff', \IPS\Settings::i()->startpoll_cutoff, FALSE, array( 'unlimited' => -1, 'unlimitedLang' => 'always' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('hours') ) );
$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->addHeader('poll_voting');
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_creator_vote', \IPS\Settings::i()->allow_creator_vote ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'poll_allow_vdelete', \IPS\Settings::i()->poll_allow_vdelete, FALSE ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_result_view', \IPS\Settings::i()->allow_result_view, FALSE, array(), NULL, NULL, NULL, 'allow_result_view' ) );
if ( $form->saveAsSettings() )
if ( $values = $form->values( TRUE ) )
{
if ( ! $values['allow_poll_creation_after'] )
{
$values['startpoll_cutoff'] = 0;
}
unset( $values['allow_poll_creation_after'] );
$form->saveAsSettings( $values );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -77,7 +77,7 @@ class _terms extends \IPS\Dispatcher\Controller
$form->addHeader( 'guest_terms_options' );
$form->add( new \IPS\Helpers\Form\YesNo( 'guest_terms_bar', \IPS\Settings::i()->guest_terms_bar, FALSE, array( 'togglesOn' => array( 'guest_terms_bar_text' ) ) ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'guest_terms_bar_text', NULL, FALSE, array( 'app' => 'core', 'key' => 'guest_terms_bar_text_value', 'sprintf' => array( '{terms}', '{privacy}', '{guidelines}' ) ), NULL, NULL, NULL, 'guest_terms_bar_text' ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'guest_terms_bar_text', NULL, FALSE, array( 'app' => 'core', 'key' => 'guest_terms_bar_text_value', 'sprintf' => array( '{terms}', '{privacy}', '{guidelines}', '{cookies}' ) ), NULL, NULL, NULL, 'guest_terms_bar_text' ) );
if ( $values = $form->values() )
{
@@ -93,7 +93,7 @@ class _terms extends \IPS\Dispatcher\Controller
{
foreach( $values[ $k ] AS $lang_id => $text )
{
$values[ $k ][ $lang_id ] = str_replace( array( '{terms}', '{privacy}', '{guidelines}' ), array( '%1$s', '%2$s', '%3$s' ), $text );
$values[ $k ][ $lang_id ] = str_replace( array( '{terms}', '{privacy}', '{guidelines}', '{cookies}' ), array( '%1$s', '%2$s', '%3$s', '%4$s' ), $text );
}
}