Version 4.1.2

This commit is contained in:
Neo committed 2025-12-19 05:32:19 -08:00
1 parent 3ba79295ee
commit 28bd025b35
1131 files changed
+63658 -20579

No files matched your search

@@ -44,7 +44,7 @@ class _applications extends \IPS\Node\Controller
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . "/applications/" ) as $file )
{
if ( $file->isDir() AND !in_array( $file->getFilename(), $installed ) )
if ( $file->isDir() AND !in_array( $file->getFilename(), $installed ) AND !$file->isDot() )
{
if( file_exists( $file->getPathname() . '/data/application.json' ) )
{
@@ -420,19 +420,12 @@ class _applications extends \IPS\Node\Controller
'unlimitedLang' => 'all'
), NULL, NULL, NULL, 'app_disabled_groups' ) );
$form->add( new \IPS\Helpers\Form\Editor( 'app_disabled_message', $node->disabled_message, FALSE, array( 'app' => 'core', 'key' => 'Admin', 'autoSaveKey' => $node->_key . 'app_disabled_message', 'attachIds' => array( $node->id, NULL, 'appdisabled' ) ), NULL, NULL, NULL, 'app_disabled_message_editor' ) );
if ( count( $node->extensions( 'core', 'FrontNavigation' ) ) )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'app_hide_tab', !$node->hide_tab ) );
}
/* And then save the values, if appropriate */
if ( $values = $form->values() )
{
$node->disabled_message = $values['app_disabled_message'];
$node->disabled_groups = $values['app_enabled'] ? NULL : ( $values['app_disabled_groups'] == '*' ? '*' : implode( ',', $values['app_disabled_groups'] ) );
$node->hide_tab = ( isset( $values['app_hide_tab'] ) and !$values['app_hide_tab'] );
$node->save();
if ( !\IPS\NO_WRITES )
@@ -558,7 +551,7 @@ class _applications extends \IPS\Node\Controller
unset($download);
\Phar::unlinkArchive($pharPath);
\IPS\Output::i()->sendOutput( $output, 200, 'application/tar', array( 'Content-Disposition' => \IPS\Output::getContentDisposition( 'attachment', $application->directory . '.tar' ) ) );
\IPS\Output::i()->sendOutput( $output, 200, 'application/tar', array( 'Content-Disposition' => \IPS\Output::getContentDisposition( 'attachment', $application->directory . '.tar' ) ), FALSE, FALSE, FALSE );
}
/**
@@ -629,11 +622,21 @@ class _applications extends \IPS\Node\Controller
/* Determine our current version and the last version we ran */
$currentVersion = \IPS\Application::load( $data['key'] )->long_version;
$allVersions = \IPS\Application::load( $data['key'] )->getAllVersions();
$longVersions = array_keys( $allVersions );
$humanVersions = array_values( $allVersions );
$lastRan = ( isset( $data['extra']['_last'] ) ) ? intval( $data['extra']['_last'] ) : $currentVersion;
if( count($allVersions) )
{
$latestLVersion = array_pop( $longVersions );
$latestHVersion = array_pop( $humanVersions );
\IPS\Db::i()->insert( 'core_upgrade_history', array( 'upgrade_version_human' => $latestHVersion, 'upgrade_version_id' => $latestLVersion, 'upgrade_date' => time(), 'upgrade_mid' => (int) \IPS\Member::loggedIn()->member_id, 'upgrade_app' => $data['key'] ) );
}
/* Now find any upgrade paths since the last one we ran that need to be executed */
$upgradeSteps = \IPS\Application::load( $data['key'] )->getUpgradeSteps( $lastRan );
/* Did we find any? */
if( count( $upgradeSteps ) )
{
@@ -683,6 +686,14 @@ class _applications extends \IPS\Node\Controller
/* If the next step exists, run it */
if( method_exists( $upgrader, $_methodName ) )
{
/* Get custom title first as the step may unset session variables that are being referenced */
$customTitleMethod = 'step' . $upgradeStep . 'CustomTitle';
if ( method_exists( $upgrader, $customTitleMethod ) )
{
$language = $upgrader->$customTitleMethod();
}
$result = $upgrader->$_methodName();
/* If the result is 'true' we move on to the next step, otherwise we need to run the same step again and store the data returned */
@@ -708,7 +719,7 @@ class _applications extends \IPS\Node\Controller
}
$laststep = 'start';
$language = \IPS\Member::loggedIn()->language()->addToStack('appupdate_databasechanges', FALSE, array( 'sprintf' => $allVersions[ $_next ] ) );
$language = $language ?: \IPS\Member::loggedIn()->language()->addToStack('appupdate_databasechanges', FALSE, array( 'sprintf' => $allVersions[ $_next ] ) );
$progress = round( ( 30 * ( $data['extra']['_totalSteps'] - count($upgradeSteps) ) ) / ( $data['extra']['_totalSteps'] ?: 1 ) );
}
else
@@ -1016,6 +1027,9 @@ class _applications extends \IPS\Node\Controller
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
/* Clear \Data\Store */
\IPS\Data\Store::i()->clearAll();
}
/* Legacy */
catch ( \UnexpectedValueException $e )
@@ -1142,7 +1156,7 @@ class _applications extends \IPS\Node\Controller
\IPS\Output::i()->error( 'app_dir_not_write', '4C133/8', 500, '' );
}
if( !is_writable( \IPS\ROOT_PATH . "/plugins/" ) ) // necessary as we write the hooks.txt file here
if( !is_writable( \IPS\ROOT_PATH . "/plugins/" ) ) // necessary as we write the hooks.php file here
{
\IPS\Output::i()->error( 'plugin_dir_not_write', '4C133/L', 403, '' );
}
@@ -1148,6 +1148,7 @@ class _developer extends \IPS\Dispatcher\Controller
$table = new \IPS\Helpers\Table\Custom( $json, \IPS\Http\Url::internal( "app=core&module=applications&controller=developer&appKey={$this->application->directory}&tab=schema" ) );
$table->langPrefix = 'database_table_';
$table->mainColumn = 'name';
$table->limit = 150;
$table->include = array( 'name' );
/* Set default sort */
@@ -1672,7 +1673,7 @@ class _developer extends \IPS\Dispatcher\Controller
$output = new \IPS\Helpers\Table\Custom( $definition['columns'], \IPS\Http\Url::internal( "app=core&module=applications&controller=developer&appKey={$this->application->directory}&do=editSchema&_name={$definition['name']}&existing=1&tab=columns" ) );
$output->langPrefix = 'database_column_';
$output->include = array( 'name', 'type', 'length', 'unsigned', 'zerofill', 'binary', 'allow_null', 'default', 'auto_increment', 'comment' );
$output->limit = 150;
$output->rootButtons = array(
'add' => array(
'icon' => 'plus',
@@ -1738,7 +1739,7 @@ class _developer extends \IPS\Dispatcher\Controller
$output = new \IPS\Helpers\Table\Custom( $definition['indexes'], \IPS\Http\Url::internal( "app=core&module=applications&controller=developer&appKey={$this->application->directory}&do=editSchema&_name={$definition['name']}&existing=1&tab=indexes" ) );
$output->langPrefix = 'database_index_';
$output->exclude = array( 'length' );
$output->limit = 150;
$output->rootButtons = array(
'add' => array(
'icon' => 'plus',
@@ -1795,6 +1796,7 @@ class _developer extends \IPS\Dispatcher\Controller
{
$output = new \IPS\Helpers\Table\Custom( isset( $definition['inserts'] ) ? $definition['inserts'] : array(), \IPS\Http\Url::internal( "app=core&module=applications&controller=developer&appKey={$this->application->directory}&do=editSchema&_name={$definition['name']}&existing=1&tab=inserts" ) );
$output->langPrefix = "‌";
$output->limit = 150;
$output->rootButtons = array(
'add' => array(
@@ -2826,7 +2828,6 @@ class _developer extends \IPS\Dispatcher\Controller
},
NULL,
FALSE,
TRUE,
TRUE
);
@@ -3131,7 +3132,7 @@ class _developer extends \IPS\Dispatcher\Controller
}
/* Check our Regex will be okay with it */
preg_match( '/^\\\IPS\\\Db::i\(\)->(.+?)\(\s*[\'"](.+?)[\'"]\s*,\s*(.+?)\)\s*;$/', $val, $matches );
preg_match( '/^\\\IPS\\\Db::i\(\)->(.+?)\(\s*[\'"](.+?)[\'"]\s*(,\s*(.+?))?\)\s*;$/', $val, $matches );
if ( empty( $matches ) )
{
throw new \DomainException( 'versions_query_format' );
@@ -0,0 +1,358 @@
<?php
/**
* @brief Menu Manager
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 29 Jun 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\admin\applications;
/* 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;
}
/**
* menu
*/
class _menu extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'menu_manage' );
\IPS\Output::i()->responsive = FALSE;
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/menumanager.css', 'core', 'admin' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_system.js', 'core', 'admin' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery.nestedSortable.js', 'core', 'interface' ) );
parent::execute();
}
/**
* Manage Menu
*
* @return void
*/
protected function manage()
{
/* Buttons */
\IPS\Output::i()->sidebar['actions']['publish'] = array(
'icon' => 'cloud-upload',
'link' => \IPS\Http\Url::internal('app=core&module=applications&controller=menu&do=publish'),
'title' => 'menu_manager_publish',
'class' => ( isset( \IPS\Data\Store::i()->frontNavigation ) && \IPS\Data\Store::i()->frontNavigation == \IPS\core\FrontNavigation::frontNavigation( TRUE ) ) ? 'ipsButton_disabled' : '',
'data' => array(
'action' => 'publishMenu'
)
);
\IPS\Output::i()->sidebar['actions']['restore'] = array(
'icon' => 'refresh',
'link' => \IPS\Http\Url::internal('app=core&module=applications&controller=menu&do=restore'),
'title' => 'menu_manager_revert',
'data' => array(
'action' => 'restoreMenu'
)
);
/* Get items from the database */
$items = array( 0 => array(), 1 => array() );
foreach ( \IPS\Db::i()->select( '*', 'core_menu', NULL, 'position' ) as $item )
{
if ( \IPS\Application::appIsEnabled( $item['app'] ) )
{
$class = 'IPS\\' . $item['app'] . '\extensions\core\FrontNavigation\\' . $item['extension'];
$items[ intval( $item['parent'] ) ][ $item['id'] ] = new $class( json_decode( $item['config'], TRUE ), $item['id'], $item['permissions'] );
}
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_applications_menu');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'applications' )->menuManager( $items );
}
/**
* Publish Menu
*
* @return void
*/
protected function publish()
{
unset( \IPS\Data\Store::i()->frontNavigation );
\IPS\Session::i()->log( 'acplog__menu_published' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=applications&controller=menu'), 'menu_manager_published' );
}
/**
* Add Menu Item
*
* @return void
*/
protected function form()
{
/* What menu items have we already configured? */
$current = array();
foreach ( \IPS\Db::i()->select( '*', 'core_menu', NULL, 'position' ) as $item )
{
if ( !isset( $current[ $item['app'] ][ $item['extension'] ] ) )
{
$current[ $item['app'] ][ $item['extension'] ] = 0;
}
$current[ $item['app'] ][ $item['extension'] ]++;
}
/* Are we editing an existing item? */
$existing = NULL;
if ( \IPS\Request::i()->id )
{
try
{
$existing = \IPS\Db::i()->select( '*', 'core_menu', array( 'id=?', \IPS\Request::i()->id ) )->first();
}
catch ( \OutOfRangeException $e ) { }
}
/* What options are available? */
$options = array();
$toggles = array();
$fieldNames = array();
$extraFields = array();
foreach ( \IPS\Application::allExtensions( 'core', 'FrontNavigation', FALSE, 'core', NULL, FALSE ) as $key => $class )
{
if ( method_exists( $class, 'typeTitle' ) )
{
$exploded = explode( '_', $key );
if ( $class::allowMultiple() or !isset( $current[ $exploded[0] ][ $exploded[1] ] ) or ( $existing and $existing['app'] == $exploded[0] and $existing['extension'] == $exploded[1] ) )
{
$options[ $key ] = $class::typeTitle();
foreach ( $class::configuration( $existing ? json_decode( $existing['config'], TRUE ) : array(), $existing ? $existing['id'] : NULL ) as $field )
{
if ( !$field->htmlId )
{
$field->htmlId = md5( uniqid() );
}
$toggles[ $key ][ $field->name ] = $field->htmlId;
$fieldNames[ $key ][] = $field->name;
$extraFields[] = $field;
}
if ( $class::permissionsCanInherit() )
{
$toggles[ $key ][] = 'menu_manager_access_type';
}
else
{
$toggles[ $key ][] = 'menu_manager_access';
}
}
}
}
/* Create the form */
$form = new \IPS\Helpers\Form( 'menu_item', 'save_menu_item' );
$form->class = 'ipsForm_vertical';
$form->add( new \IPS\Helpers\Form\Radio( 'menu_manager_extension', $existing ? "{$existing['app']}_{$existing['extension']}" : NULL, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
foreach ( $extraFields as $field )
{
$form->add( $field );
}
$groups = array();
foreach ( \IPS\Member\Group::groups() as $group )
{
$groups[ $group->g_id ] = $group->name;
}
$form->add( new \IPS\Helpers\Form\Radio( 'menu_manager_access_type', ( $existing and $existing['permissions'] ) ? 1 : 0, TRUE, array(
'options' => array( 0 => 'menu_manager_access_type_inherit', 1 => 'menu_manager_access_type_override' ),
'toggles' => array( 1 => array( 'menu_manager_access' ) )
), NULL, NULL, NULL, 'menu_manager_access_type' ) );
$form->add( new \IPS\Helpers\Form\Select( 'menu_manager_access', $existing ? ( $existing['permissions'] == '*' ? '*' : explode( ',', $existing['permissions'] ) ) : '*', NULL, array( 'multiple' => TRUE, 'options' => $groups, 'unlimited' => '*', 'unlimitedLang' => 'everyone' ), NULL, NULL, NULL, 'menu_manager_access' ) );
if( !$existing ){
$form->hiddenValues['newItem'] = TRUE;
}
/* Handle submissions */
if ( $values = $form->values() )
{
$exploded = explode( '_', $values['menu_manager_extension'] );
$class = 'IPS\\' . $exploded[0] . '\extensions\core\FrontNavigation\\' . $exploded[1];
$config = array();
if ( isset( $fieldNames[ $values['menu_manager_extension'] ] ) )
{
foreach ( $values as $k => $v )
{
if ( in_array( $k, $fieldNames[ $values['menu_manager_extension'] ] ) )
{
$config[ $k ] = $v;
}
}
}
$save = array(
'app' => $exploded[0],
'extension' => $exploded[1],
'config' => json_encode( $config ),
'parent' => $existing ? $existing['parent'] : ( \IPS\Request::i()->parent ?: NULL ),
);
if ( $class::permissionsCanInherit() )
{
if ( $values['menu_manager_access_type'] )
{
$save['permissions'] = $values['menu_manager_access'] == '*' ? '*' : implode( ',', $values['menu_manager_access'] );
}
else
{
$save['permissions'] = '';
}
}
else
{
$save['permissions'] = $values['menu_manager_access'] == '*' ? '*' : implode( ',', $values['menu_manager_access'] );
}
if ( $existing )
{
$id = $existing['id'];
$_config = $class::parseConfiguration( $config, $id );
if ( $_config != $config )
{
$save['config'] = json_encode( $_config );
}
\IPS\Db::i()->update( 'core_menu', $save, array( 'id=?', $id ) );
}
else
{
try
{
$save['position'] = \IPS\Db::i()->select( 'MAX(position)', 'core_menu', array( 'parent=?', \IPS\Request::i()->parent ) )->first() + 1;
}
catch ( \UnderflowException $e )
{
$save['position'] = 1;
}
$id = \IPS\Db::i()->insert( 'core_menu', $save );
$_config = $class::parseConfiguration( $config, $id );
if ( $_config != $config )
{
\IPS\Db::i()->update( 'core_menu', array( 'config' => json_encode( $_config ) ), array( 'id=?', $id ) );
}
}
if( \IPS\Request::i()->isAjax() )
{
$item = new $class( $_config, $id, $save['permissions'] );
$output = array(
'menu_item' => \IPS\Theme::i()->getTemplate( 'applications' )->menuItem( $item, $id )
);
/* If the item has a parent and it's a dropdown menu, then the menu_item
we need to return needs to be the one used for dropdown menus */
if ( $save['parent'] )
{
try
{
$parent = \IPS\Db::i()->select( '*', 'core_menu', array( 'id=?', $save['parent'] ) )->first();
$parentClass = 'IPS\\' . $parent['app'] . '\extensions\core\FrontNavigation\\' . $parent['extension'];
$parentItem = new $parentClass( json_decode( $parent['config'], TRUE ), $parent['id'], $parent['permissions'] );
if ( $parent['app'] === 'core' and $parent['extension'] === 'Menu' )
{
$output['menu_item'] = \IPS\Theme::i()->getTemplate( 'applications' )->menuManagerDropdownItem( $item, $id );
}
}
catch ( \UnderflowException $e ) { }
}
/* If this is a dropdown item, we also need to return the HTML for the dropdown edit screen */
if ( $exploded[1] == 'Menu' )
{
$output['dropdown_menu'] = \IPS\Theme::i()->getTemplate( 'applications' )->menuManagerDropdown( $item, $id, ( isset( $parentItem ) ? $parentItem : 0 ) );
}
\IPS\Output::i()->json( $output );
}
else
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=applications&controller=menu') );
}
}
/* Display */
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'applications', 'core' ) ), 'menuManagerForm' ) );
}
/**
* Remove an item
*
* @return void
*/
protected function remove()
{
static::_remove( intval( \IPS\Request::i()->id ) );
\IPS\Output::i()->json('OK');
}
/**
* Remove a menu item
*
* @param int $id ID of item to remove
* @return void
*/
protected static function _remove( $id )
{
foreach ( \IPS\Db::i()->select( 'id', 'core_menu', array( 'parent=?', $id ) ) as $child )
{
static::_remove( $child );
}
\IPS\Db::i()->delete( 'core_menu', array( 'id=?', $id ) );
}
/**
* Reorder Items
*
* @return void
*/
protected function reorder()
{
$positions = array();
foreach ( \IPS\Request::i()->menu_order as $id => $parent )
{
if ( !isset( $positions[ $parent ] ) )
{
$positions[ $parent ] = 1;
}
\IPS\Db::i()->update( 'core_menu', array( 'position' => $positions[ $parent ]++, 'parent' => $parent == 'null' ? NULL : $parent ), array( 'id=?', $id ) );
}
\IPS\Output::i()->json('OK');
}
/**
* Restore Default Menu
*
* @return void
*/
protected function restore()
{
\IPS\core\FrontNavigation::buildDefaultFrontNavigation();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=applications&controller=menu'), 'menu_manager_reverted' );
}
}
@@ -38,6 +38,86 @@ class _plugins extends \IPS\Node\Controller
\IPS\Dispatcher::i()->checkAcpPermission( 'plugins_view' );
parent::execute();
}
/**
* Manage
*
* @return void
*/
protected function manage()
{
if ( \IPS\Settings::i()->disable_all_plugins )
{
\IPS\Output::i()->sidebar['actions'][] = array(
'icon' => 'undo',
'link' => \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins&do=reenableAll' ),
'title' => 'plugins_reenable_all',
);
}
else
{
\IPS\Output::i()->sidebar['actions'][] = array(
'icon' => 'times',
'link' => \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins&do=disableAll' ),
'title' => 'plugins_disable_all',
);
}
parent::manage();
}
/**
* Disable All
*
* @return void
*/
protected function disableAll()
{
$disabledPlugins = array();
foreach ( \IPS\Plugin::plugins() as $plugin )
{
if ( $plugin->enabled )
{
$plugin->enabled = FALSE;
$plugin->save();
$disabledPlugins[] = $plugin->id;
}
}
\IPS\Settings::i()->disable_all_plugins = implode( ',', $disabledPlugins );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Settings::i()->disable_all_plugins ), array( 'conf_key=?', 'disable_all_plugins' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins' ) );
}
/**
* Re-enable All
*
* @return void
*/
protected function reenableAll()
{
foreach ( explode( ',', \IPS\Settings::i()->disable_all_plugins ) as $plugin )
{
try
{
$plugin = \IPS\Plugin::load( $plugin );
$plugin->enabled = TRUE;
$plugin->save();
}
catch ( \Exception $e ) {}
}
\IPS\Settings::i()->disable_all_plugins = '';
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => '' ), array( 'conf_key=?', 'disable_all_plugins' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins' ) );
}
/**
* Toggle Enabled/Disable
@@ -50,7 +130,10 @@ class _plugins extends \IPS\Node\Controller
{
\IPS\Output::i()->error( 'no_writes', '1C145/G', 403, '' );
}
/* Remove plugin.js so it can be rebuilt with only active plugins */
\IPS\Output\Javascript::deleteCompiled( 'core', 'plugins', 'plugins.js' );
return parent::enableToggle();
}
@@ -200,7 +283,8 @@ class _plugins extends \IPS\Node\Controller
if ( !$plugin->location )
{
$plugin->location = 'p' . mb_substr( md5( uniqid() ), 0, 10 );
$directory = \mb_strtolower( preg_replace( '#[^a-zA-Z0-9_]#', '', $plugin->name ) );
$plugin->location = file_exists( \IPS\ROOT_PATH . "/plugins/" . $directory ) ? 'p' . mb_substr( md5( uniqid() ), 0, 10 ) : $directory;
}
$plugin->version_long = $xml->getAttribute('version_long');
@@ -382,6 +466,7 @@ class _plugins extends \IPS\Node\Controller
case 'cssFiles':
case 'jsFiles':
case 'resourcesFiles':
$class = ( \IPS\Theme::designersModeEnabled() ) ? '\IPS\Theme\Advanced\Theme' : '\IPS\Theme';
while ( $xml->read() and in_array( $xml->name, array( 'html', 'css', 'js', 'resources' ) ) )
{
@@ -394,7 +479,7 @@ class _plugins extends \IPS\Node\Controller
preg_match('/^<ips:template parameters="(.+?)?"([^>]+?)>(\r\n?|\n)/', $content, $matches );
$output = preg_replace( '/^<ips:template parameters="(.+?)?"([^>]+?)>(\r\n?|\n)/', '', $content );
\IPS\Theme::addTemplate( array(
$class::addTemplate( array(
'app' => 'core',
'location' => 'global',
'group' => 'plugins',
@@ -408,7 +493,7 @@ class _plugins extends \IPS\Node\Controller
break;
case 'css':
\IPS\Theme::addCss( array(
$class::addCss( array(
'app' => 'core',
'location' => 'front',
'path' => 'custom',
@@ -438,7 +523,7 @@ class _plugins extends \IPS\Node\Controller
break;
case 'resources':
\IPS\Theme::addResource( array(
$class::addResource( array(
'app' => 'core',
'location' => 'global',
'path' => '/plugins/',
@@ -1210,6 +1295,10 @@ class _plugins extends \IPS\Node\Controller
{
throw new \DomainException( 'form_number_bad' );
}
if( $val < 10000 )
{
throw new \DomainException( 'versions_long_too_low' );
}
if( isset( $json[ $val ] ) )
{
throw new \DomainException( 'versions_long_exists' );
@@ -1428,7 +1517,7 @@ class _plugins extends \IPS\Node\Controller
}
/* Build */
\IPS\Output::i()->sendOutput( $xml->asXML(), 200, 'application/xml', array( "Content-Disposition" => \IPS\Output::getContentDisposition( 'attachment', $plugin->name . '.xml' ) ) );
\IPS\Output::i()->sendOutput( $xml->asXML(), 200, 'application/xml', array( "Content-Disposition" => \IPS\Output::getContentDisposition( 'attachment', $plugin->name . '.xml' ) ), FALSE, FALSE, FALSE );
}
/**
@@ -443,7 +443,7 @@ class _bulkmail extends \IPS\Dispatcher\Controller
/* Start the form */
$form = new \IPS\Helpers\Form;
$form->class = 'ipsForm_vertical';
$form->addtab( 'bulkmail__main' );
$form->addTab( 'bulkmail__main' );
$form->add( new \IPS\Helpers\Form\Text( 'mail_subject', $mail->subject, TRUE ) );
$form->add( new \IPS\Helpers\Form\Editor( 'mail_body', $mail->content ?: "<p>{member_name},</p><p>&nbsp;</p>", TRUE, array( 'app' => 'core', 'key' => 'Admin', 'autoSaveKey' => 'bulkmail' . ( $mail->id ? '-' . $mail->id : '' ), 'tags' => $tags, 'attachIds' => array( $mail->id, NULL, 'bulkmail' ) ) ) );
@@ -453,7 +453,7 @@ class _bulkmail extends \IPS\Dispatcher\Controller
}
/* Add the filters tab and the "generic filters" header */
$form->addtab( 'bulkmail__filters' );
$form->addTab( 'bulkmail__filters' );
$form->addHeader( 'generic_bm_filters' );
$lastApp = 'core';
@@ -201,7 +201,7 @@ class _ajax extends \IPS\Dispatcher\Controller
}
if ( !in_array( 'unmodified', explode( ',', \IPS\Request::i()->filters ) ) )
{
$where[] = array( 'template_user_edited>0' );
$where[] = array( 'template_user_edited>0 or template_added_to > 0' );
}
$where[] = array( 'template_set_id IN (' . implode( ',' , $parents ) . ')' );
@@ -42,7 +42,7 @@ class _emails extends \IPS\Dispatcher\Controller
public function manage()
{
/* Create the table */
$table = new \IPS\Helpers\Table\Db( 'core_email_templates', \IPS\Http\Url::internal( 'app=core&module=customization&controller=emails' ), array( "template_parent=?", 0 ) );
$table = new \IPS\Helpers\Table\Db( 'core_email_templates', \IPS\Http\Url::internal( 'app=core&module=customization&controller=emails' ), array( array( "template_parent=?", 0 ) ) );
$table->langPrefix = 'emailtpl_';
$table->mainColumn = 'template_name';
$table->include = array( 'template_name', 'template_app' );
@@ -94,14 +94,20 @@ class _emails extends \IPS\Dispatcher\Controller
return $return;
};
/* Import button */
/* Buttons */
\IPS\Output::i()->sidebar['actions'] = array(
'upload' => array(
'title' => 'upload_email_template',
'icon' => 'upload',
'link' => \IPS\Http\Url::internal( 'app=core&module=customization&controller=emails&do=import' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('upload_email_template') )
),
),
'preview' => array(
'title' => 'preview_email_wrapper',
'icon' => 'search',
'link' => \IPS\Http\Url::internal( 'app=core&module=customization&controller=emails&do=preview' ),
'data' => array( 'ipsDialog' => \IPS\Http\Url::internal( 'app=core&module=customization&controller=emails&do=preview' ), 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('preview_email_wrapper') )
),
);
/* Display */
@@ -312,4 +318,38 @@ class _emails extends \IPS\Dispatcher\Controller
$key = $template['template_key'] . '_email_plaintext';
\IPS\Data\Store::i()->$key = $ptFunction;
}
/**
* Simple wrapper for the email out, so that we can show it in an iframe
*
* @return void
*/
public function preview()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('emailtpl_edit');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'customization', 'core', 'admin' )->emailFrame( \IPS\Http\Url::internal( 'app=core&module=customization&controller=emails&do=emailPreview' ) );
}
/**
* Outputs the raw email preview HTML (to be called inside an iframe)
*
* @return void
*/
public function emailPreview()
{
/* Add some dummy content */
$body = \IPS\Theme::i()->getTemplate( 'customization', 'core', 'admin' )->emailPreview();
$templateData = \IPS\Db::i()->select( '*', 'core_email_templates', array( "template_app=? AND template_name=?", 'core', 'emailWrapper' ) )->first();
$template = "namespace IPS\Theme;\n" . \IPS\Theme::compileTemplate( $templateData['template_content_html'], "email_html_core_emailWrapper", $templateData['template_data'] );
if( !function_exists( 'IPS\\Theme\\email_html_core_emailWrapper' ) )
{
eval( $template );
}
$output = call_user_func_array( 'IPS\\Theme\\email_html_core_emailWrapper', array( NULL, new \IPS\Member, $body, NULL, FALSE, '', NULL ) );
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
}
@@ -274,7 +274,7 @@ class _themes extends \IPS\Node\Controller
else if ( $data['toImport'] )
{
$toImport = $_SESSION['theme_dev_import'];
reset( $toImport );
$themeId = key( $toImport );
$theme = \IPS\Theme::load( $themeId );
@@ -295,10 +295,18 @@ class _themes extends \IPS\Node\Controller
$languageIds = array_keys( \IPS\Lang::languages() );
$languageInserts = array();
$seen = array();
require \IPS\ROOT_PATH . "/themes/{$themeId}/lang.php";
foreach ( $lang as $k => $v )
{
if ( isset( $seen[ $k ] ) )
{
continue;
}
$seen[ $k ] = true;
if ( mb_substr( $k, 0, 17 ) === 'theme_custom_tab_' )
{
\IPS\Lang::deleteCustom( 'core', $k );
@@ -306,7 +314,7 @@ class _themes extends \IPS\Node\Controller
foreach ( $languageIds as $langId )
{
$languageInserts[] = array(
\IPS\Db::i()->insert( 'core_sys_lang_words', array(
'lang_id' => $langId,
'word_app' => NULL,
'word_plugin' => NULL,
@@ -318,14 +326,9 @@ class _themes extends \IPS\Node\Controller
'word_custom_version' => NULL,
'word_js' => FALSE,
'word_export' => TRUE
);
) );
}
}
if ( count( $languageInserts ) )
{
\IPS\Db::i()->insert( 'core_sys_lang_words', $languageInserts );
}
}
break;
case 'html':
@@ -605,8 +608,13 @@ class _themes extends \IPS\Node\Controller
return \IPS\Theme::i()->getTemplate( 'customization' )->resourceDisplay( $row );
},
'resource_name' => function( $val, $row )
'resource_name' => function( $val, $row ) use ($set)
{
if ( in_array( mb_substr( $row['resource_name'], mb_strrpos( $row['resource_name'], '.' ) + 1 ), \IPS\Image::$imageExtensions ) )
{
$row['resource_filename'] = $set->resource( ltrim( $row['resource_path'], '/' ) . $row['resource_name'], $row['resource_app'], $row['resource_location'] );
}
return \IPS\Theme::i()->getTemplate( 'customization' )->resourceName( $row );
},
'resource_filename' => function( $val, $row )
@@ -1029,9 +1037,9 @@ class _themes extends \IPS\Node\Controller
'set_author_name' => $xml->getAttribute('author_name'),
'set_author_url' => $xml->getAttribute('author_url'),
'set_version' => $xml->getAttribute('version'),
'set_long_version' => $xml->getAttribute('long_version'),
'set_long_version' => ( $xml->getAttribute('long_version') ) ? $xml->getAttribute('long_version') : \IPS\Application::load('core')->long_version,
'set_is_default' => $set->is_default,
'set_permissions' => implode( ',', $groups )
'set_permissions' => $set->id ? $set->permissions : implode( ',', $groups )
) );
if ( $xml->getAttribute('editor_skin') )
@@ -1064,6 +1072,7 @@ class _themes extends \IPS\Node\Controller
/* Move to correct app */
$appKey = NULL;
$version = \IPS\Theme::load( \IPS\Request::i()->id )->long_version;
$xml->read();
while ( $xml->read() )
{
@@ -1278,19 +1287,32 @@ class _themes extends \IPS\Node\Controller
$languageIds = isset( $languageIds ) ? $languageIds : array_keys( \IPS\Lang::languages() );
foreach ( $languageIds as $langId )
{
\IPS\Db::i()->insert( 'core_sys_lang_words', array(
'lang_id' => $langId,
'word_app' => NULL,
'word_plugin' => NULL,
'word_theme' => \IPS\Request::i()->id,
'word_key' => $xml->getAttribute('key'),
'word_default' => $xml->readString(),
'word_custom' => NULL,
'word_default_version' => $version,
'word_custom_version' => NULL,
'word_js' => FALSE,
'word_export' => TRUE
) );
$default = $xml->readString();
$exists = \IPS\Db::i()->select( 'COUNT(*)', 'core_sys_lang_words', array( array( 'lang_id=? and word_key=? and word_theme=?', $langId, $xml->getAttribute('key'), \IPS\Request::i()->id ) ) )->first();
if ( $exists )
{
\IPS\Db::i()->update( 'core_sys_lang_words', array(
'word_default' => $default,
'word_default_version' => $version,
), array( array( 'lang_id=? and word_key=? and word_theme=?', $langId, $xml->getAttribute('key'), \IPS\Request::i()->id ) ) );
}
else
{
\IPS\Db::i()->insert( 'core_sys_lang_words', array(
'lang_id' => $langId,
'word_app' => NULL,
'word_plugin' => NULL,
'word_theme' => \IPS\Request::i()->id,
'word_key' => $xml->getAttribute('key'),
'word_default' => $default,
'word_custom' => NULL,
'word_default_version' => $version,
'word_custom_version' => NULL,
'word_js' => FALSE,
'word_export' => TRUE
) );
}
}
$xml->next();
@@ -1332,6 +1354,8 @@ class _themes extends \IPS\Node\Controller
{
$set = \IPS\Theme::load( \IPS\Request::i()->id );
\IPS\Theme::deleteCompiledResources( null, null, null, null, $set->id );
\IPS\Theme::deleteCompiledTemplate( null, null, null, $set->id );
\IPS\Theme::deleteCompiledCss( null, null, null, null, $set->id );
\IPS\Data\Store::i()->delete( 'core_theme_import_' . md5_file( \IPS\Request::i()->file ) );
@@ -1377,9 +1401,9 @@ class _themes extends \IPS\Node\Controller
if ( isset( $conflicts['template'] ) AND count( $conflicts['template'] ) )
{
$templates = iterator_to_array( \IPS\Db::i()->select(
'*, MD5( CONCAT( template_app, ".", template_location, ".", template_group, ".", template_name ) ) as bit_key',
'*, MD5( CONCAT( template_app, \'.\', template_location, \'.\', template_group, \'.\', template_name ) ) as bit_key',
'core_theme_templates',
'template_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( template_app, ".", template_location, ".", template_group, ".", template_name ) )', array_keys( $conflicts['template'] ) )
'template_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( template_app, \'.\', template_location, \'.\', template_group, \'.\', template_name ) )', array_keys( $conflicts['template'] ) )
)->setKeyField( 'bit_key' ) );
}
else
@@ -1390,9 +1414,9 @@ class _themes extends \IPS\Node\Controller
if ( isset( $conflicts['css'] ) AND count( $conflicts['css'] ) )
{
$css = iterator_to_array( \IPS\Db::i()->select(
'*, MD5( CONCAT( css_app, ".", css_location, ".", css_path, ".", css_name ) ) as bit_key',
'*, MD5( CONCAT( css_app, \'.\', css_location, \'.\', css_path, \'.\', css_name ) ) as bit_key',
'core_theme_css',
'css_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( css_app, ".", css_location, ".", css_path, ".", css_name ) )', array_keys( $conflicts['css'] ) )
'css_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( css_app, \'.\', css_location, \'.\', css_path, \'.\', css_name ) )', array_keys( $conflicts['css'] ) )
)->setKeyField( 'bit_key' ) );
}
else
@@ -1458,18 +1482,18 @@ class _themes extends \IPS\Node\Controller
if ( isset( $conflicts['template'] ) AND count( $conflicts['template'] ) )
{
$templates = iterator_to_array( \IPS\Db::i()->select(
'*, MD5( CONCAT( template_app, ".", template_location, ".", template_group, ".", template_name ) ) as bit_key',
'*, MD5( CONCAT( template_app, \'.\', template_location, \'.\', template_group, \'.\', template_name ) ) as bit_key',
'core_theme_templates',
'template_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( template_app, ".", template_location, ".", template_group, ".", template_name ) )', array_keys( $conflicts['template'] ) )
'template_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( template_app, \'.\', template_location, \'.\', template_group, \'.\', template_name ) )', array_keys( $conflicts['template'] ) )
)->setKeyField( 'bit_key' ) );
}
if ( isset( $conflicts['css'] ) AND count( $conflicts['css'] ) )
{
$css = iterator_to_array( \IPS\Db::i()->select(
'*, MD5( CONCAT( css_app, ".", css_location, ".", css_path, ".", css_name ) ) as bit_key',
'*, MD5( CONCAT( css_app, \'.\', css_location, \'.\', css_path, \'.\', css_name ) ) as bit_key',
'core_theme_css',
'css_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( css_app, ".", css_location, ".", css_path, ".", css_name ) )', array_keys( $conflicts['css'] ) )
'css_set_id=' . $id . ' AND ' . \IPS\Db::i()->in('MD5( CONCAT( css_app, \'.\', css_location, \'.\', css_path, \'.\', css_name ) )', array_keys( $conflicts['css'] ) )
)->setKeyField( 'bit_key' ) );
}
@@ -2034,7 +2058,30 @@ class _themes extends \IPS\Node\Controller
/* Language strings */
$xml->startElement('language');
foreach ( \IPS\Db::i()->select( '*', 'core_sys_lang_words', array( 'word_theme=?', $themeSet->id ) ) as $row )
$parents = array( $themeSet->id );
try
{
foreach( $themeSet->parents() as $parent )
{
$parents[] = $parent->_id;
}
}
catch( \OutOfRangeException $e ) { }
$words = array();
foreach ( \IPS\Db::i()->select(
'*, INSTR(\',' . implode( ',' , $parents ) . ',\', CONCAT(\',\',word_theme,\',\') ) as theorder',
'core_sys_lang_words',
array( 'word_theme IN(' . implode( ',' , $parents ) . ')' ),
'theorder desc'
) as $data )
{
$words[ $data['word_key'] ] = $data;
}
foreach ( $words as $row )
{
$xml->startElement( 'word' );
$xml->startAttribute('key');
@@ -2108,10 +2155,10 @@ class _themes extends \IPS\Node\Controller
$form = new \IPS\Helpers\Form();
$form->hiddenValues['id'] = $id;
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_name', NULL, TRUE, array( 'regex' => '/^([A-Z0-9_\\-]+?)$/i' ),
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_name', NULL, TRUE, array( 'regex' => '/^([A-Z0-9_]+?)$/i' ),
function( $val )
{
if ( ! preg_match( '/^([A-Z0-9_\-]+?)$/i', $val ) )
if ( ! preg_match( '/^([A-Z0-9_]+?)$/i', $val ) )
{
throw new \InvalidArgumentException( 'form_bad_value' );
}
@@ -2265,8 +2312,11 @@ class _themes extends \IPS\Node\Controller
if ( isset( $template['template_content'] ) )
{
$template['type'] = 'templates';
$template['name'] = $template['template_name'];
$template['type'] = 'templates';
$template['name'] = $template['template_name'];
$template['app'] = $template['template_app'];
$template['location'] = $template['template_location'];
$template['group'] = $template['template_group'];
}
}
else
@@ -2275,8 +2325,11 @@ class _themes extends \IPS\Node\Controller
if ( isset( $template['css_content'] ) )
{
$template['type'] = 'css';
$template['name'] = $template['css_name'];
$template['type'] = 'css';
$template['name'] = $template['css_name'];
$template['app'] = $template['css_app'];
$template['location'] = $template['css_location'];
$template['group'] = $template['css_path'];
}
}
}
@@ -2285,8 +2338,11 @@ class _themes extends \IPS\Node\Controller
\IPS\Output::i()->error( 'node_error', '3S121/1', 500, '' );
}
\IPS\Session::i()->log( 'acplogs__themetemplate_deleted', array( $template['name'] => FALSE ) );
if ( isset( $template['app'] ) )
{
\IPS\Session::i()->log( 'acplogs__themetemplate_deleted', array( $template['app'] => FALSE, $template['location'] => FALSE, $template['group'] => FALSE, $template['name'] => FALSE ) );
}
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -2363,7 +2419,7 @@ class _themes extends \IPS\Node\Controller
if ( in_array( $k, array( 'app', 'location', 'group', 'name' ) ) )
{
$url[] = 't_' . $k . '=' . $v;
$log[ $k ] = $v;
$log[ $v ] = FALSE;
}
}
@@ -0,0 +1,88 @@
<?php
/**
* @brief Search settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 14 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\admin\discovery;
/* 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;
}
/**
* Search settings
*/
class _search extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'search_manage' );
parent::execute();
}
/**
* Manage Settings
*
* @return void
*/
protected function manage()
{
/* Rebuild button */
\IPS\Output::i()->sidebar['actions'] = array(
'rebuildIndex' => array(
'title' => 'search_rebuild_index',
'icon' => 'undo',
'link' => \IPS\Http\Url::internal( 'app=core&module=discovery&controller=search&do=queueIndexRebuild' ),
'data' => array( 'confirm' => '', 'confirmSubMessage' => \IPS\Member::loggedIn()->language()->get('search_rebuild_index_confirm') ),
),
);
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Number( 'search_index_timeframe', \IPS\Settings::i()->search_index_timeframe, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'all' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_prefix'), \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_suffix'), 'search_index_timeframe' ) );
if ( $values = $form->values() )
{
$indexPrune = \IPS\Settings::i()->search_index_timeframe;
/* Go ahead and save... */
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplogs__search_settings' );
/* And re-index if setting updated */
if( $indexPrune != $values['search_index_timeframe'] )
{
\IPS\Content\Search\Index::i()->rebuild();
}
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_discovery_search');
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global' )->block( 'menu__core_discovery_search', $form );
}
/**
* Queue an index rebuild
*
* @return void
*/
protected function queueIndexRebuild()
{
\IPS\Content\Search\Index::i()->rebuild();
\IPS\Session::i()->log( 'acplogs__queued_search_index' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=discovery&controller=search' ), 'search_index_rebuilding' );
}
}
@@ -0,0 +1,145 @@
<?php
/**
* @brief streams
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 01 Jul 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\admin\discovery;
/* 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;
}
/**
* streams
*/
class _streams extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\core\Stream';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'streams_manage' );
parent::execute();
}
/**
* Manage Settings
*
* @return void
*/
protected function manage()
{
\IPS\Output::i()->sidebar['actions'] = array(
'rebuildIndex' => array(
'title' => 'all_activity_stream_settings',
'icon' => 'cog',
'link' => \IPS\Http\Url::internal( 'app=core&module=discovery&controller=streams&do=allActivitySettings' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('all_activity_stream_settings') )
),
'rebuildDefault' => array(
'title' => 'restore_default_streams',
'icon' => 'cog',
'link' => \IPS\Http\Url::internal( 'app=core&module=discovery&controller=streams&do=restoreDefaultStreams' )
),
);
return parent::manage();
}
/**
* Restores default streams
*
* @return void
*/
protected function restoreDefaultStreams()
{
$schema = json_decode( file_get_contents( \IPS\ROOT_PATH . "/applications/core/data/schema.json" ), TRUE );
foreach ( $schema['core_streams']['inserts'] as $insertData )
{
try
{
\IPS\Db::i()->replace( 'core_streams', $insertData );
}
catch( \IPS\Db\Exception $e )
{}
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=discovery&controller=streams' ), 'restore_default_streams_restored' );
}
/**
* All Activity Stream Settings
*
* @return void
*/
protected function allActivitySettings()
{
$types = array( 'register', 'follow_member', 'follow_content', 'photo' );
if ( \IPS\Settings::i()->reputation_enabled )
{
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
{
$types[] = 'like';
}
elseif ( \IPS\Settings::i()->reputation_point_types == 'both' )
{
$types[] = 'like';
$types[] = 'rep_neg';
}
elseif ( \IPS\Settings::i()->reputation_point_types == 'positive' )
{
$types[] = 'like';
}
elseif ( \IPS\Settings::i()->reputation_point_types == 'negative' )
{
$types[] = 'rep_neg';
}
}
$options = array();
$currentValuesStream = array();
foreach ( $types as $k )
{
$key = "all_activity_{$k}";
if ( \IPS\Settings::i()->$key )
{
$currentValuesStream[] = $k;
}
$options[ $k ] = ( $k == 'like' and \IPS\Settings::i()->reputation_point_types != 'like' ) ? 'all_activity_rep_pos' : $key;
}
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'all_activity_extra_stream', $currentValuesStream, FALSE, array( 'options' => $options ) ) );
if ( $values = $form->values() )
{
$toSave = array();
foreach ( $types as $k )
{
$toSave[ "all_activity_{$k}" ] = intval( in_array( $k, $values['all_activity_extra_stream'] ) );
}
$form->saveAsSettings( $toSave );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=discovery&controller=streams' ), 'saved' );
}
\IPS\Output::i()->output = $form;
}
}
@@ -80,28 +80,32 @@ class _emoticons extends \IPS\Dispatcher\Controller
'toggles' => array( 'create' => array( 'emoticons_add_newgroup' ), 'existing' => array( 'emoticons_add_choosegroup' ) ),
'disabled' => empty($groups)
) ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'emoticons_add_newgroup', NULL, FALSE, array(), NULL, NULL, NULL, 'emoticons_add_newgroup' ) );
$form->add( new \IPS\Helpers\Form\Select( 'emoticons_add_choosegroup', NULL, FALSE, array( 'options' => $groups ), NULL, NULL, NULL, 'emoticons_add_choosegroup' ) );
if ( $values = $form->values() )
$form->add( new \IPS\Helpers\Form\Translatable( 'emoticons_add_newgroup', NULL, FALSE, array(), function( $value )
{
if ( $values['emoticons_add_group'] === 'create' )
if ( \IPS\Request::i()->emoticons_add_group === 'create' )
{
foreach ( \IPS\Lang::languages() as $lang )
{
if ( $lang->default )
{
if( !$values['emoticons_add_newgroup'][ $lang->id ] )
if( ! $value[ $lang->id ] )
{
$form->elements['']['emoticons_add_newgroup']->error = \IPS\Member::loggedIn()->language()->addToStack( 'emoticon_group_name_error' );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'emoticons_add', $form, FALSE );
return;
throw new \InvalidArgumentException('form_required');
}
}
}
}
}, NULL, NULL, 'emoticons_add_newgroup' ) );
if ( !empty( $groups ) )
{
$form->add( new \IPS\Helpers\Form\Select( 'emoticons_add_choosegroup', NULL, FALSE, array( 'options' => $groups ), NULL, NULL, NULL, 'emoticons_add_choosegroup' ) );
}
if ( $values = $form->values() )
{
if ( $values['emoticons_add_group'] === 'create' )
{
$position = 0;
$setId = md5( uniqid() );
\IPS\Lang::saveCustom( 'core', "core_emoticon_group_{$setId}", $values['emoticons_add_newgroup'] );
@@ -120,8 +124,18 @@ class _emoticons extends \IPS\Dispatcher\Controller
}
$inserts = array();
$images2x = array();
foreach ( $values['emoticons_upload'] as $file )
{
/* Is it "retina" */
if( \mb_stristr( $file->filename, '@2x' ) )
{
$filename_2x = preg_replace( "/^(.+?)\.[0-9a-f]{32}(?:\..+?)$/i", "$1", str_replace( '@2x', '', $file->filename ) );
$images2x[ $filename_2x ] = (string) $file;
continue;
}
$filename = preg_replace( "/^(.+?)\.[0-9a-f]{32}(?:\..+?)$/i", "$1", $file->filename );
$inserts[] = array(
@@ -132,8 +146,42 @@ class _emoticons extends \IPS\Dispatcher\Controller
'emo_position' => ++$position,
);
}
\IPS\Db::i()->insert( 'core_emoticons', $inserts );
if( count( $inserts ) )
{
\IPS\Db::i()->insert( 'core_emoticons', $inserts );
}
/* Add 2x */
if( count( $images2x ) )
{
foreach( \IPS\Db::i()->select( '*', 'core_emoticons', array( 'emo_set=?', $setId ) ) as $emo )
{
$file = \IPS\File::get( 'core_Emoticons', $emo['image'] );
$imageDimensions = $file->getImageDimensions();
/* There isn't an original for the 2x emo */
if( !isset( $images2x[ $file->filename ] ) )
{
continue;
}
\IPS\Db::i()->update( 'core_emoticons', array(
'image_2x' => $images2x[ $file->filename ],
'width' => $imageDimensions[0],
'height' => $imageDimensions[1]
), 'id=' . $emo['id']);
unset( $images2x[ $file->filename ] );
}
/* Delete any unused 2x files */
foreach( $images2x as $img )
{
\IPS\File::get( 'core_Emoticons', $img )->delete();
}
}
unset( \IPS\Data\Store::i()->emoticons );
/* Clear guest page caches */
@@ -205,6 +253,11 @@ class _emoticons extends \IPS\Dispatcher\Controller
if ( isset( $emoticons[ $id ] ) )
{
if ( !$data['name'] )
{
continue;
}
if ( !isset( $data['order'] ) )
{
if ( !isset( $orders[ $set ] ) )
@@ -256,6 +309,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
if ( $emoticon['id'] )
{
\IPS\File::get( 'core_Emoticons', $emoticon['image'] )->delete();
\IPS\File::get( 'core_Emoticons', $emoticon['image_2x'] )->delete();
}
\IPS\Db::i()->delete( 'core_emoticons', array( 'id=?', (int) \IPS\Request::i()->id ) );
@@ -296,6 +350,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
try
{
\IPS\File::get( 'core_Emoticons', $emoticon['image'] )->delete();
\IPS\File::get( 'core_Emoticons', $emoticon['image_2x'] )->delete();
}
catch ( \UnderflowException $e ) { }
}
@@ -0,0 +1,132 @@
<?php
/**
* @brief settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 13 Aug 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\admin\editor;
/* 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;
}
/**
* settings
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
/* Restrictions check */
\IPS\Dispatcher::i()->checkAcpPermission( 'settings_manage' );
/* Choose active tab */
$this->tabs = array( 'general' => 'editor_settings_general', 'advanced' => 'editor_settings_advanced' );
if ( isset( \IPS\Request::i()->tab ) and array_key_exists( \IPS\Request::i()->tab, $this->tabs ) )
{
$this->activeTab = \IPS\Request::i()->tab;
}
else
{
$keys = array_keys( $this->tabs );
$this->activeTab = array_shift( $keys );
}
/* Run */
parent::execute();
}
/**
* Manage
*
* @return void
*/
protected function manage()
{
/* Work out output */
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $this->activeTab ) ) );
/* If this is an AJAX request, just return it */
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->output = $activeTabContents;
return;
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('editor_settings');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $this->tabs, $this->activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=editor&controller=settings" ) );
}
/**
* General Settings
*
* @return void
*/
protected function _manageGeneral()
{
$form = new \IPS\Helpers\Form( 'form' );
$form->add( new \IPS\Helpers\Form\Radio( 'editor_paste_behaviour', \IPS\Settings::i()->editor_paste_behaviour, FALSE, array( 'options' => array(
'rich' => 'editor_paste_behaviour_rich',
'force' => 'editor_paste_behaviour_force',
) ) ) );
$form->add( new \IPS\Helpers\Form\Radio( 'editor_paragraph_padding', \IPS\Settings::i()->editor_paragraph_padding, FALSE, array( 'options' => array(
1 => 'editor_paragraph_padding_on',
0 => 'editor_paragraph_padding_off'
) ) ) );
if ( $values = $form->values() )
{
$clearCss = ( $values['editor_paragraph_padding'] !== \IPS\Settings::i()->editor_paragraph_padding );
$form->saveAsSettings();
if ( $clearCss )
{
\IPS\Theme::deleteCompiledCss();
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=editor&controller=settings&tab=general" ), 'saved' );
}
/* Display */
return $form;
}
/**
* Advanced Settings
*
* @return void
*/
protected function _manageAdvanced()
{
$form = new \IPS\Helpers\Form( 'form' );
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('editor_allowed_formmsg') );
$form->add( new \IPS\Helpers\Form\Stack( 'editor_allowed_classes', \IPS\Settings::i()->editor_allowed_classes ? explode( ',', \IPS\Settings::i()->editor_allowed_classes ) : array(), FALSE ) );
$form->add( new \IPS\Helpers\Form\Stack( 'editor_allowed_datacontrollers', \IPS\Settings::i()->editor_allowed_datacontrollers ? explode( ',', \IPS\Settings::i()->editor_allowed_datacontrollers ) : array(), FALSE ) );
$form->add( new \IPS\Helpers\Form\Stack( 'editor_allowed_iframe_bases', \IPS\Settings::i()->editor_allowed_iframe_bases ? explode( ',', \IPS\Settings::i()->editor_allowed_iframe_bases ) : array(), FALSE, array( 'placeholder' => 'example.com/embed/' ) ) );
if ( $values = $form->values() )
{
$form->saveAsSettings();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=editor&controller=settings&tab=advanced" ), 'saved' );
}
/* Display */
return $form;
}
}
@@ -77,39 +77,10 @@ class _toolbar extends \IPS\Dispatcher\Controller
'title' => 'editor_revert',
'link' => \IPS\Http\Url::internal( "app=core&module=editor&controller=toolbar&do=revert" ),
'data' => array( 'confirm' => '', 'confirmSubMessage' => \IPS\Member::loggedIn()->language()->addToStack('editor_revert_confirm' ) )
),
'edit' => array(
'icon' => 'cog',
'title' => 'editor_advanced_config',
'link' => \IPS\Http\Url::internal( "app=core&module=editor&controller=toolbar&do=advanced" ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('editor_advanced_config') )
),
)
);
}
/**
* Advanced ckeditor configuration options
*
* @return void
*/
public function advanced()
{
$form = new \IPS\Helpers\Form( 'form' );
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('editor_allowed_formmsg') );
$form->add( new \IPS\Helpers\Form\Stack( 'editor_allowed_classes', \IPS\Settings::i()->editor_allowed_classes ? explode( ',', \IPS\Settings::i()->editor_allowed_classes ) : array(), FALSE ) );
$form->add( new \IPS\Helpers\Form\Stack( 'editor_allowed_datacontrollers', \IPS\Settings::i()->editor_allowed_datacontrollers ? explode( ',', \IPS\Settings::i()->editor_allowed_datacontrollers ) : array(), FALSE ) );
if ( $values = $form->values() )
{
$form->saveAsSettings();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=editor&controller=toolbar" ), 'saved' );
}
/* Display */
\IPS\Output::i()->output = $form;
}
/**
* Save
*
@@ -309,6 +280,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
\IPS\Output::i()->error( 'editor_plugin_nowrite', '4C120/2', 403, '' );
}
$form->add( new \IPS\Helpers\Form\Upload( 'editor_plugin_zip', NULL, TRUE, array( 'allowedFileTypes' => array( 'zip' ), 'temporary' => TRUE ) ) );
\IPS\Member::loggedIn()->language()->words['editor_plugin_zip_desc'] = sprintf( \IPS\Member::loggedIn()->language()->get( 'editor_plugin_zip_desc' ), \IPS\Helpers\Form\Editor::ckeditorVersion() );
}
else
{
@@ -321,6 +293,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
}
}
$form->add( new \IPS\Helpers\Form\Select( 'editor_plugin_folder', NULL, TRUE, array( 'options' => $plugins ) ) );
\IPS\Member::loggedIn()->language()->words['editor_plugin_folder_desc'] = sprintf( \IPS\Member::loggedIn()->language()->get( 'editor_plugin_folder_desc' ), \IPS\Helpers\Form\Editor::ckeditorVersion() );
}
/* Handle Submissions */
@@ -344,7 +317,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
$name = mb_substr( zip_entry_name( $resource ), 0, -1 );
$name = explode( '/', $name );
$name = array_shift( $name );
if ( strstr( $fileName, $name ) !== FALSE )
if ( strstr( mb_strtolower( $fileName ), mb_strtolower( $name ) ) !== FALSE )
{
$inRoot = FALSE;
break;
@@ -139,7 +139,7 @@ class _languages extends \IPS\Node\Controller
\IPS\Data\Cache::i()->clearAll();
/* Log */
\IPS\Session::i()->log( 'lang_created', array( $values['lang_title'] => FALSE ) );
\IPS\Session::i()->log( 'acplogs__lang_created', array( $values['lang_title'] => FALSE ) );
/* Redirect */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=languages&controller=languages' ), 'saved' );
@@ -330,7 +330,7 @@ class _languages extends \IPS\Node\Controller
{
if ( isset( \IPS\Request::i()->cookie['vle_editor'] ) and \IPS\Request::i()->cookie['vle_editor'] )
{
\IPS\Output::i()->error( 'no_translate_with_vle', '', 403 ); //@todo errorcode
\IPS\Output::i()->error( 'no_translate_with_vle', '1C126/8', 403, '' );
}
try
@@ -476,6 +476,11 @@ class _languages extends \IPS\Node\Controller
\IPS\Output::clearJsFiles( 'global', 'root', 'js_lang_' . $word['lang_id'] . '.js' );
}
if ( $word['word_key'] === '_list_format_' )
{
unset( \IPS\Data\Store::i()->listFormats );
}
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -709,6 +714,29 @@ class _languages extends \IPS\Node\Controller
}
else
{
/* Add "UTF8" if we can */
$currentLocale = setlocale( LC_ALL, '0' );
foreach ( array( \IPS\Request::i()->locale . ".UTF-8", \IPS\Request::i()->locale . ".UTF8" ) as $l )
{
$test = setlocale( LC_ALL, $l );
if ( $test !== FALSE )
{
\IPS\Request::i()->locale = $l;
break;
}
}
foreach( explode( ";", $currentLocale ) as $locale )
{
$parts = explode( "=", $locale );
if( in_array( $parts[0], array( 'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME' ) ) )
{
setlocale( constant( $parts[0] ), $parts[1] );
}
}
/* Insert the language pack record */
$max = \IPS\Db::i()->select( 'MAX(lang_order)', 'core_sys_lang' )->first();
$insertId = \IPS\Db::i()->insert( 'core_sys_lang', array(
'lang_short' => \IPS\Request::i()->locale,
@@ -165,7 +165,7 @@ class _groups extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form( ( !$group->g_id ? 'groups_add' : $group->g_id ) );
foreach ( $extensions as $k => $class )
{
$form->addtab( 'group__' . $k );
$form->addTab( 'group__' . $k );
$class->process( $form, $group );
}
@@ -75,7 +75,7 @@ class _ip extends \IPS\Dispatcher\Controller
try
{
$geolocation = \IPS\GeoLocation::getByIp( $ip );
$map = $geolocation->map()->render( 400, 350, 6 );
$map = $geolocation->map()->render( 400, 350, 0.6 );
}
catch ( \Exception $e ) {}
@@ -124,13 +124,13 @@ class _members extends \IPS\Dispatcher\Controller
'from' => array( 'core_pfields_content', 'p' ),
'where' => 'p.member_id=core_members.member_id' ),
array(
'select' => 'row_id',
'from' => array( 'core_admin_permission_rows', 'a' ),
'where' => "a.row_id=core_members.member_id AND a.row_id_type='member'" ),
'select' => 'm.row_id',
'from' => array( 'core_admin_permission_rows', 'm' ),
'where' => "m.row_id=core_members.member_id AND m.row_id_type='member'" ),
array(
'select' => 'g_access_cp',
'from' => array( 'core_groups', 'g' ),
'where' => "g.g_id=core_members.member_group_id" ),
'select' => 'g.row_id',
'from' => array( 'core_admin_permission_rows', 'g' ),
'where' => "( g.row_id=core_members.member_group_id OR FIND_IN_SET( g.row_id, core_members.mgroup_others ) ) AND g.row_id_type='group'" ),
);
/* Makes query less efficient */
@@ -183,7 +183,7 @@ class _members extends \IPS\Dispatcher\Controller
'members_filter_locked' => 'failed_login_count>=' . (int) \IPS\Settings::i()->ipb_bruteforce_attempts,
'members_filter_spam' => \IPS\Db::i()->bitwiseWhere( \IPS\Member::$bitOptions['members_bitoptions'], 'bw_is_spammer' ),
'members_filter_validating' => '( v.lost_pass=0 AND v.vid IS NOT NULL )',
'members_filter_administrators' => '( a.row_id IS NOT NULL OR g.g_access_cp=1 )'
'members_filter_administrators' => '( m.row_id IS NOT NULL OR g.row_id IS NOT NULL )'
);
/* Custom parsers */
@@ -372,6 +372,7 @@ class _members extends \IPS\Dispatcher\Controller
'members_last_post' => \IPS\Request::i()->members_last_post,
'members_last_visit' => \IPS\Request::i()->members_last_visit,
'members_posts' => \IPS\Request::i()->members_posts,
'filter' => \IPS\Request::i()->filter,
) );
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'member_delete' ) )
@@ -519,6 +520,28 @@ class _members extends \IPS\Dispatcher\Controller
$where[] = array( 'posts'.$operator.'?', (int) \IPS\Request::i()->members_posts[1] );
}
if( isset( \IPS\Request::i()->filter ) )
{
switch ( \IPS\Request::i()->filter )
{
case 'members_filter_banned':
$where[] = array( 'temp_ban<>0' );
break;
case 'members_filter_locked':
$where[] = array( 'failed_login_count>=' . (int) \IPS\Settings::i()->ipb_bruteforce_attempts );
break;
case 'members_filter_spam':
$where[] = array( \IPS\Db::i()->bitwiseWhere( \IPS\Member::$bitOptions['members_bitoptions'], 'bw_is_spammer' ) );
break;
case 'members_filter_validating':
$where[] = array( '( v.lost_pass=0 AND v.vid IS NOT NULL )' );
break;
case 'members_filter_administrators':
$where[] = array( '( m.row_id IS NOT NULL OR g.row_id IS NOT NULL )' );
break;
}
}
if ( !count( $where ) )
{
if ( \IPS\Request::i()->action === 'prune' )
@@ -812,7 +835,7 @@ class _members extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form;
foreach ( $extensions as $k => $class )
{
$form->addtab( 'member__' . $k );
$form->addTab( 'member__' . $k );
$class->process( $form, $member );
if ( method_exists( $class, 'actionButtons' ) )
@@ -999,6 +1022,7 @@ class _members extends \IPS\Dispatcher\Controller
$member->pp_main_photo = NULL;
$member->pp_main_photo = (string) $values['member_photo_upload'];
$member->pp_thumb_photo = (string) $values['member_photo_upload']->thumbnail( 'core_Profile', \IPS\PHOTO_THUMBNAIL_SIZE, \IPS\PHOTO_THUMBNAIL_SIZE, TRUE );
$member->photo_last_update = time();
}
break;
@@ -1006,11 +1030,13 @@ class _members extends \IPS\Dispatcher\Controller
$member->pp_photo_type = 'custom';
$member->pp_main_photo = NULL;
$member->pp_main_photo = (string) $values['member_photo_url'];
$member->photo_last_update = time();
break;
case 'none':
$member->pp_main_photo = NULL;
$member->members_bitoptions['bw_disable_gravatar'] = 1;
$member->photo_last_update = NULL;
break;
default:
@@ -1057,10 +1083,13 @@ class _members extends \IPS\Dispatcher\Controller
}
/* Init Table */
$table = new \IPS\Helpers\Table\Custom( $member->ipAddresses(), \IPS\Http\Url::internal( "app=core&module=members&controller=members&id={$member->member_id}&do=ip" ) );
$table->langPrefix = 'members_iptable_';
$table->mainColumn = 'ip';
$table->sortBy = $table->sortBy ?: 'last';
$ips = $member->ipAddresses();
$table = new \IPS\Helpers\Table\Custom( $ips, \IPS\Http\Url::internal( "app=core&module=members&controller=members&id={$member->member_id}&do=ip" ) );
$table->langPrefix = 'members_iptable_';
$table->mainColumn = 'ip';
$table->sortBy = $table->sortBy ?: 'last';
$table->quickSearch = 'ip';
/* Parsers */
$table->parsers = array(
@@ -1404,7 +1433,14 @@ class _members extends \IPS\Dispatcher\Controller
}
/* Do it */
$accountToKeep->merge( $accountToDelete );
try
{
$accountToKeep->merge( $accountToDelete );
}
catch( \InvalidArgumentException $e )
{
\IPS\Output::i()->error( $e->getMessage(), '3C114/J', 403, '' );
}
/* Delete the account */
$accountToDelete->delete( FALSE );
@@ -154,19 +154,10 @@ class _notifications extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Number( 'subs_autoprune', \IPS\Settings::i()->subs_autoprune, FALSE, array(), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days') ) );
$form->add( new \IPS\Helpers\Form\Select( 'autoforum_sub_groups', \IPS\Settings::i()->autoforum_sub_groups ? explode( ",", \IPS\Settings::i()->autoforum_sub_groups ) : array(), FALSE, array( 'options' => \IPS\Member\Group::groups( TRUE, FALSE ), 'parse' => 'normal', 'multiple' => TRUE ) ) );
$form->add( new \IPS\Helpers\Form\Select( 'auto_track_method', \IPS\Settings::i()->auto_track_method, FALSE, array( 'options' => array(
0 => 'select_disabled',
'immediate' => 'follow_type_immediate',
'daily' => 'follow_type_daily',
'weekly' => 'follow_type_weekly',
) ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'prune_notifications', \IPS\Settings::i()->prune_notifications, FALSE, array(), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('months') ) );
if ( $values = $form->values() )
{
$values['autoforum_sub_groups'] = implode( ",", $values['autoforum_sub_groups'] );
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplog__notification_settings' );
@@ -170,7 +170,7 @@ class _ranks extends \IPS\Dispatcher\Controller
{
$pip = \IPS\File::get( 'core_Theme', $current['icon'] );
}
$form->add( new \IPS\Helpers\Form\Number( 'member_ranks_num_pips' , $current ? $current['pips'] : 0, FALSE, array( 'min' => 0 ), NULL, NULL, NULL, 'member_ranks_pips' ) );
$form->add( new \IPS\Helpers\Form\Number( 'member_ranks_num_pips' , $current ? $current['pips'] : 0, FALSE, array( 'min' => 0, 'max' => 100 ), NULL, NULL, NULL, 'member_ranks_pips' ) );
$form->add( new \IPS\Helpers\Form\Upload( 'member_ranks_icon', $pip, FALSE, array( 'image' => array( 'maxWidth' => 140, 'maxHeight' => 140 ), 'storageExtension' => 'core_Theme' ), NULL, NULL, NULL, 'member_ranks_icon' ) );
if ( $values = $form->values() )
@@ -76,13 +76,26 @@ class _reputation extends \IPS\Dispatcher\Controller
{
\IPS\Dispatcher::i()->checkAcpPermission( 'reps_settings' );
/* Fake names for the "like" preview */
/* Random for the "like" preview */
$maxMemberId = \IPS\Db::i()->select( 'MAX(member_id)', 'core_members' )->first();
$names = array();
foreach ( range( 1, 3 ) as $i )
foreach ( range( 1, ( $maxMemberId > 3 ) ? 3 : $maxMemberId ) as $i )
{
do
{
$randomMemberId = rand( 1, $maxMemberId );
}
while ( array_key_exists( $randomMemberId, $names ) );
try
{
$member = \IPS\Member::constructFromData( \IPS\Db::i()->select( '*', 'core_members', empty( $names ) ? array() : 'member_id NOT IN(' . implode( ',', array_keys( $names ) ) . ')', 'RAND()', 1 )->first() );
$where = array( array( 'member_id>=?', $randomMemberId ) );
if ( !empty( $names ) )
{
$where[] = \IPS\Db::i()->in( 'member_id', array_keys( $names ), TRUE );
}
$member = \IPS\Member::constructFromData( \IPS\Db::i()->select( '*', 'core_members', $where, 'member_id ASC', 1 )->first() );
$names[ $member->member_id ] = '<a>' . htmlentities( $member->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) . '</a>';
}
catch ( \Exception $e )
@@ -142,7 +155,7 @@ class _reputation extends \IPS\Dispatcher\Controller
else
{
/* Create the table */
$table = new \IPS\Helpers\Table\Db( 'core_reputation_levels', \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=reputation' ) );
$table = new \IPS\Helpers\Table\Db( 'core_reputation_levels', \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=reputation&tab=levels' ) );
$table->langPrefix = 'rep_';
/* Columns */
@@ -7,7 +7,6 @@
* @package IPS Social Suite
* @since 18 Apr 2013
* @version SVN_VERSION_NUMBER
* @modified 13.09.2015 by IAF
*/
namespace IPS\core\modules\admin\membersettings;
@@ -67,7 +66,7 @@ class _spam extends \IPS\Dispatcher\Controller
}
/* Add a button for logs */
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'spam_service_log' ) )
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'spam_service_log' ) )
{
\IPS\Output::i()->sidebar['actions']['errorLog'] = array(
'title' => 'spamlogs',
@@ -174,11 +173,11 @@ class _spam extends \IPS\Dispatcher\Controller
$disabled = TRUE;
if( !\IPS\Settings::i()->ipb_reg_number )
{
$form->addMessage( '__iaf__nulling_null_alert', 'ipsMessage ipsMessage_error' ); //Changing error message to custom
\IPS\Member::loggedIn()->language()->words['spam_service_enabled_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'spam_service_nokey', FALSE, array( 'sprintf' => array( \IPS\Http\Url::internal( 'app=core&module=settings&controller=licensekey', null ) ) ) );
}
else
{
$form->addMessage( '__iaf__nulling_null_alert', 'ipsMessage ipsMessage_error' ); //Changing error message to custom
\IPS\Member::loggedIn()->language()->words['spam_service_enabled_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'spam_service_noservice' );
}
}
@@ -417,6 +416,4 @@ class _spam extends \IPS\Dispatcher\Controller
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('spamlogssettings');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global')->block( 'spamlogssettings', $form, FALSE );
}
}
/* Nulled by IandroidFan (IAF) */
}
@@ -206,7 +206,7 @@ class _warnings extends \IPS\Node\Controller
$form->add( new \IPS\Helpers\Form\Custom( 'wa_' . $k, ( $current ? array( $current[ 'wa_' . $k ], $current[ 'wa_' . $k . '_unit' ] ) : 0 ), FALSE, array(
'getHtml' => function( $element )
{
return \IPS\Theme::i()->getTemplate( 'members' )->warningTime( $element->name, $element->value, TRUE );
return \IPS\Theme::i()->getTemplate( 'members' )->warningTime( $element->name, $element->value, 'for', 'indefinitely' );
},
'formatValue'=> function( $element )
{
@@ -7,7 +7,6 @@
* @package IPS Social Suite
* @since 2 July 2013
* @version SVN_VERSION_NUMBER
* @modified 13.09.2015 by IAF
*/
namespace IPS\core\modules\admin\overview;
@@ -141,30 +140,7 @@ class _dashboard extends \IPS\Dispatcher\Controller
}
/* Get new core update available data */
$system = \IPS\Application::load( 'core' );
$update = array();
if( $system->update_version )
{
$versions = json_decode( $system->update_version, TRUE );
if ( is_array( $versions ) and !isset( $versions[0] ) and isset( $versions['longversion'] ) )
{
$versions = array( $versions );
}
$update = array();
foreach ( $versions as $data )
{
if( !empty($data['longversion']) AND $data['longversion'] > $system->long_version )
{
if( $data['released'] AND intval($data['released']) == $data['released'] AND \strlen($data['released']) == 10 )
{
$data['released'] = (string) \IPS\DateTime::ts( $data['released'] )->localeDate();
}
$update[] = $data;
}
}
}
$update = \IPS\Application::load( 'core' )->availableUpgrade( TRUE );
/* Don't show the ACP header bar */
\IPS\Output::i()->hiddenElements[] = 'acpHeader';
@@ -281,22 +257,5 @@ class _dashboard extends \IPS\Dispatcher\Controller
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=dashboard" ), 'saved' );
}
/**
* Download latest version
*
* @return void
*/
public function upgrade()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('ips_suite_upgrade');
$form = new \IPS\Helpers\Form( NULL, NULL );
$form->addMessage( "__iaf__nulling_null_alert", 'ipsMessage ipsMessage_error' ); //No requests to IPS. Only error message about Null.
\IPS\Output::i()->output = $form;
}
}
/* Nulled by IandroidFan (IAF) */
}
}
@@ -86,15 +86,17 @@ class _files extends \IPS\Dispatcher\Controller
$table->parsers = array(
'attach_file' => function( $val, $row ) use ( $table )
{
$url = \IPS\Http\Url::external( \IPS\File::get( 'core_Attachment', $row['attach_location'] )->url )->makeSafeForAcp( $row['attach_is_image'] );
if ( $row['attach_is_image'] and $table->filter === 'images' )
{
$url = \IPS\Http\Url::external( \IPS\File::get( 'core_Attachment', $row['attach_location'] )->url )->makeSafeForAcp( TRUE );
return "<a href='{$url}' target='_blank'><img src='{$url}' style='max-height:200px'></a>";
}
$val = htmlentities( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
return "<a href='{$url}' target='_blank'>{$val}</a>";
else
{
$url = \IPS\Http\Url::external( \IPS\Settings::i()->base_url . "applications/core/interface/file/attachment.php" )->setQueryString( 'id', $row['attach_id'] )->makeSafeForAcp( FALSE );
$val = htmlentities( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
return "<a href='{$url}' target='_blank'>{$val}</a>";
}
},
'attach_filesize' => function( $val )
{
@@ -253,8 +255,8 @@ class _files extends \IPS\Dispatcher\Controller
'disabled'=> class_exists( 'Imagick', FALSE ) ? array() : array( 'imagemagick' )
) ) );
$form->add( new \IPS\Helpers\Form\Number( 'image_jpg_quality', \IPS\Settings::i()->image_jpg_quality, FALSE, array( 'min' => 0, 'max' => 100, 'range' => TRUE ), NULL, NULL, NULL, 'image_jpg_quality' ) );
$form->add( new \IPS\Helpers\Form\Number( 'image_png_quality_gd', \IPS\Settings::i()->image_png_quality_gd, FALSE, array( 'min' => 0, 'max' => 9, 'range' => TRUE ), NULL, NULL, NULL, 'image_png_quality_gd' ) );
$form->add( new \IPS\Helpers\Form\Number( 'image_jpg_quality', \IPS\Settings::i()->image_jpg_quality, FALSE, array( 'min' => 0, 'max' => 100, 'range' => TRUE, 'step' => 1 ), NULL, NULL, NULL, 'image_jpg_quality' ) );
$form->add( new \IPS\Helpers\Form\Number( 'image_png_quality_gd', \IPS\Settings::i()->image_png_quality_gd, FALSE, array( 'min' => 0, 'max' => 9, 'range' => TRUE, 'step' => 1 ), NULL, NULL, NULL, 'image_png_quality_gd' ) );
if ( $values = $form->values() )
{
@@ -632,10 +634,12 @@ class _files extends \IPS\Dispatcher\Controller
\IPS\Db::i()->update( 'core_file_storage', array( 'configuration' => json_encode( $currentHandlerSettings ) ), array( 'id=?', $current['id'] ) );
unset( \IPS\Data\Store::i()->storageConfigurations );
}
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
if ( $current !== NULL and ! $createNewAndMove )
{
$classname::getClass( $current['id'] )->settingsUpdated();
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=overview&controller=files&do=settings&tab=configurations' ), 'saved' );
}
catch ( \LogicException $e )
@@ -666,7 +670,7 @@ class _files extends \IPS\Dispatcher\Controller
}
catch( \UnderflowException $e )
{
\IPS\Output::i()->error( 'files_invalid_id', '3C158/5', 404, '' );
\IPS\Output::i()->json( array( 'needsMoving' => FALSE ) );
}
$currentConf = json_decode( $current['configuration'], TRUE );
@@ -103,7 +103,7 @@ class _advertisements extends \IPS\Dispatcher\Controller
},
'ad_active' => function( $val, $row )
{
return \IPS\Theme::i()->getTemplate( 'promotion' )->activeBadge( $row['ad_id'], ( $val == -1 ) ? 'ad_filters_pending' : ( ( $val == 0 ) ? 'ad_filters_inactive' : 'ad_filters_active' ), $val );
return \IPS\Theme::i()->getTemplate( 'promotion' )->activeBadge( $row['ad_id'], ( $val == -1 ) ? 'ad_filters_pending' : ( ( $val == 0 ) ? 'ad_filters_inactive' : 'ad_filters_active' ), $val, $row );
},
'ad_clicks' => function( $val, $row )
{
@@ -622,4 +622,15 @@ class _advertisements extends \IPS\Dispatcher\Controller
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'admin' )->blankTemplate( $preview ) );
}
/**
* Adsense Help
*
* @return void
*/
protected function adsense()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('google_adsense_header');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('promotion')->adsenseHelp();
}
}
@@ -100,8 +100,15 @@ class _seo extends \IPS\Dispatcher\Controller
}
if ( ( !isset( \IPS\Request::i()->htaccess_mod_rewrite ) and \IPS\Settings::i()->htaccess_mod_rewrite ) or \IPS\Request::i()->htaccess_mod_rewrite or \IPS\Request::i()->htaccess_mod_rewrite_checkbox )
{
$response = \IPS\Http\Url::external( \IPS\Settings::i()->base_url . 'login' )->request( 5, '1.1', FALSE )->get();
if ( !in_array( mb_substr( $response->httpResponseCode, 0, 1 ), array( '2', '3' ) ) and ( \IPS\Settings::i()->site_online OR $response->httpResponseCode != 503 ) )
try
{
$response = \IPS\Http\Url::external( \IPS\Settings::i()->base_url . 'login' )->request( 5, '1.1', FALSE )->get();
if ( !in_array( mb_substr( $response->httpResponseCode, 0, 1 ), array( '2', '3' ) ) and ( \IPS\Settings::i()->site_online OR $response->httpResponseCode != 503 ) )
{
\IPS\Member::loggedIn()->language()->words['htaccess_mod_rewrite_warning'] = \IPS\Member::loggedIn()->language()->get( $isApache ? 'htaccess_mod_rewrite_err' : 'htaccess_mod_rewrite_err_na' );
}
}
catch( \IPS\Http\Request\Exception $e )
{
\IPS\Member::loggedIn()->language()->words['htaccess_mod_rewrite_warning'] = \IPS\Member::loggedIn()->language()->get( $isApache ? 'htaccess_mod_rewrite_err' : 'htaccess_mod_rewrite_err_na' );
}
@@ -477,7 +484,7 @@ Options -MultiViews
RewriteEngine On
RewriteBase {$dir}
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \\.(js|css|jpeg|jpg|gif|png|ico)(\\?|$) - [L,NC,R=404]
RewriteRule \\.(js|css|jpeg|jpg|gif|png|ico)(\\?|$) {$dir}404error.php [L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
@@ -167,7 +167,6 @@ class _advanced extends \IPS\Dispatcher\Controller
$options = array(
'None' => 'datastore_method_None',
'Apc' => 'datastore_method_Apc',
'Eaccelerator' => 'datastore_method_Eaccelerator',
'Memcache' => 'datastore_method_Memcache',
'Redis' => 'datastore_method_Redis',
'Wincache' => 'datastore_method_Wincache',
@@ -329,6 +328,7 @@ class _advanced extends \IPS\Dispatcher\Controller
}
}, NULL, NULL, 'task_use_cron' ) );
$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 ) );
if ( $values = $form->values() )
{
@@ -630,6 +630,7 @@ class _advanced extends \IPS\Dispatcher\Controller
$definition = \IPS\Http\Url::furlDefinition();
$table = new \IPS\Helpers\Table\Custom( $definition, \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=furl' ) );
$table->include = array( 'friendly', 'real' );
$table->limit = 100;
$table->langPrefix = 'furl_';
$table->mainColumn = 'real';
$table->parsers = array(
@@ -735,12 +736,13 @@ class _advanced extends \IPS\Dispatcher\Controller
{
$furl = \IPS\Settings::i()->furl_configuration ? json_decode( \IPS\Settings::i()->furl_configuration, TRUE ) : array();
$save = array(
'friendly' => $values['furl_friendly'],
'real' => $values['furl_real'],
'custom' => true
);
$currentDefinition = \IPS\Http\Url::furlDefinition();
$save = \IPS\Request::i()->key ? $currentDefinition[ \IPS\Request::i()->key ] : array();
$save['friendly'] = $values['furl_friendly'];
$save['real'] = $values['furl_real'];
$save['custom'] = true;
if ( \IPS\Request::i()->key )
{
$furl[ \IPS\Request::i()->key ] = $save;
@@ -56,10 +56,12 @@ class _email extends \IPS\Dispatcher\Controller
'options' => array( 'mail' => 'mail_method_php', 'smtp' => 'mail_method_smtp' ),
'toggles' => array(
'mail' => array( 'php_mail_extra' ),
'smtp' => array( 'smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass', 'smtp_helo' )
'smtp' => array( 'smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass', 'smtp_helo', 'smtp_protocol' )
)
) ) );
$options = array( 'plain' => 'smtp_plaintext', 'ssl' => 'smtp_ssl', 'tls' => 'smtp_tls' );
$settingsForm->add( new \IPS\Helpers\Form\Text( 'smtp_host', \IPS\Settings::i()->smtp_host, FALSE, array(), NULL, NULL, NULL, 'smtp_host' ) );
$settingsForm->add( new \IPS\Helpers\Form\Select( 'smtp_protocol', \IPS\Settings::i()->smtp_protocol, FALSE, array( 'options' => $options ), NULL, NULL, NULL, 'smtp_protocol' ) );
$settingsForm->add( new \IPS\Helpers\Form\Number( 'smtp_port', \IPS\Settings::i()->smtp_port, FALSE, array(), NULL, NULL, NULL, 'smtp_port' ) );
$settingsForm->add( new \IPS\Helpers\Form\Text( 'smtp_user', \IPS\Settings::i()->smtp_user, FALSE, array(), NULL, NULL, NULL, 'smtp_user' ) );
$settingsForm->add( new \IPS\Helpers\Form\Password( 'smtp_pass', \IPS\Settings::i()->smtp_pass, FALSE, array(), NULL, NULL, NULL, 'smtp_pass' ) );
@@ -68,7 +70,7 @@ class _email extends \IPS\Dispatcher\Controller
{
$sendTestEmail = FALSE;
foreach( array( 'mail_method', 'smtp_host', 'smtp_port', 'smtp_pass', 'smtp_user', 'php_mail_extra' ) as $setting )
foreach( array( 'mail_method', 'smtp_host', 'smtp_port', 'smtp_pass', 'smtp_user', 'php_mail_extra', 'smtp_protocol' ) as $setting )
{
if( $values[ $setting ] != \IPS\Settings::i()->$setting )
{
@@ -49,19 +49,12 @@ 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\Translatable( 'copyright_line', NULL, FALSE, array( 'app' => 'core', 'key' => 'copyright_line_value', 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('copyright_line_placeholder') ) ) );
$form->addHeader( 'home_link' );
$form->add( new \IPS\Helpers\Form\YesNo( 'show_home_link', \IPS\Settings::i()->show_home_link, FALSE, array(
'togglesOn' => array( 'home_name', 'home_url' ),
) ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'home_name', NULL, FALSE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('home_name_placeholder'), 'app' => 'core', 'key' => 'home_name_value' ), NULL, NULL, NULL, 'home_name' ) );
$form->add( new \IPS\Helpers\Form\Url( 'home_url', \IPS\Settings::i()->home_url, FALSE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('home_url_placeholder') ), NULL, NULL, NULL, 'home_url' ) );
$form->add( new \IPS\Helpers\Form\Stack( 'upgrade_email', explode( ',', \IPS\Settings::i()->upgrade_email ), FALSE, array( 'stackFieldType' => 'Email' ) ) );
if ( $values = $form->values() )
{
\IPS\Lang::saveCustom( 'core', "copyright_line_value", $values['copyright_line'] );
\IPS\Lang::saveCustom( 'core', "home_name_value", $values['home_name'] );
unset( $values['copyright_line'], $values['home_name'] );
unset( $values['copyright_line'] );
$form->saveAsSettings();
@@ -7,7 +7,6 @@
* @package IPS Social Suite
* @since 17 Apr 2013
* @version SVN_VERSION_NUMBER
* @modified 13.09.2015 by IAF
*/
namespace IPS\core\modules\admin\settings;
@@ -96,29 +95,9 @@ class _licensekey extends \IPS\Dispatcher\Controller
protected function settings()
{
$form = new \IPS\Helpers\Form;
$form->addHeader('ipb_license_edit_main');
$form->add( new \IPS\Helpers\Form\Text( 'ipb_reg_number', \IPS\Settings::i()->ipb_reg_number, TRUE ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_active', \IPS\Settings::i()->ipb_license_active ) );
$form->add( new \IPS\Helpers\Form\Text( 'ipb_license_expires', \IPS\Settings::i()->ipb_license_expires ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_cloud', \IPS\Settings::i()->ipb_license_cloud ) );
$form->addHeader('ipb_license_urls');
$form->add( new \IPS\Helpers\Form\Text( 'ipb_license_url', \IPS\Settings::i()->ipb_license_url ) );
$form->add( new \IPS\Helpers\Form\Text( 'ipb_license_test_url', \IPS\Settings::i()->ipb_license_test_url ) );
$form->addHeader('ipb_license_components');
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_forums', \IPS\Settings::i()->ipb_license_product_forums ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_calendar', \IPS\Settings::i()->ipb_license_product_calendar ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_blog', \IPS\Settings::i()->ipb_license_product_blog ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_gallery', \IPS\Settings::i()->ipb_license_product_gallery ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_downloads', \IPS\Settings::i()->ipb_license_product_downloads ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_cms', \IPS\Settings::i()->ipb_license_product_cms ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_nexus', \IPS\Settings::i()->ipb_license_product_nexus ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_license_product_copyright', \IPS\Settings::i()->ipb_license_product_copyright ) );
$form->addHeader('ipb_license_services');
$form->add( new \IPS\Helpers\Form\Text( 'ipb_license_chat_limit', \IPS\Settings::i()->ipb_license_chat_limit ) );
$form->add( new \IPS\Helpers\Form\Text( 'ipb_license_support', \IPS\Settings::i()->ipb_license_support ) );
$form->add( new \IPS\Helpers\Form\Text( 'ipb_reg_number', NULL, TRUE, array(), function( $val ){
\IPS\IPS::checkLicenseKey( $val, \IPS\Settings::i()->base_url );
} ) );
if ( $values = $form->values() )
{
@@ -141,6 +120,4 @@ class _licensekey extends \IPS\Dispatcher\Controller
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('license_settings');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( 'menu__core_settings_licensekey', $form );
}
}
/* Nulled by IandroidFan (IAF) */
}
@@ -56,7 +56,7 @@ class _posting extends \IPS\Dispatcher\Controller
{
$this->tabs['urlFilters'] = 'url_settings';
}
/* Choose active tab */
if ( isset( \IPS\Request::i()->tab ) and array_key_exists( \IPS\Request::i()->tab, $this->tabs ) )
{
@@ -112,12 +112,14 @@ class _posting extends \IPS\Dispatcher\Controller
) ) );
$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');
$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' ) );
$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(), NULL, NULL, NULL, 'remote_image_proxy' ) );
$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\Number( 'max_video_width', \IPS\Settings::i()->max_video_width, FALSE, array( 'unlimited' => 0 ), NULL, NULL, 'px' ) );
$form->addHeader('posting_content');
$form->add( new \IPS\Helpers\Form\YesNo( 'strip_quotes', !\IPS\Settings::i()->strip_quotes, FALSE, array(), NULL, NULL, NULL, 'strip_quotes' ) );
$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') ) );
@@ -169,7 +171,6 @@ class _posting extends \IPS\Dispatcher\Controller
{
$clearCss = ( $values['max_video_width'] !== \IPS\Settings::i()->max_video_width );
$values['strip_quotes'] = $values['strip_quotes'] ? FALSE : TRUE;
$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 )
@@ -328,33 +329,13 @@ class _posting extends \IPS\Dispatcher\Controller
{
$values['ipb_url_whitelist'] = implode( ",", $values['ipb_url_whitelist'] );
$values['ipb_url_blacklist'] = implode( ",", $values['ipb_url_blacklist'] );
/* We need to clean these up */
$nofollowExclude = array();
foreach( $values['posts_add_nofollow_exclude'] as $domain )
{
/* We only want to compare against the domain, not the full URL */
$domain = str_replace( array( 'http://', 'https://' ), '', $domain );
/* And we are comparing against the non-www. version during parsing */
$domain = preg_replace( '/^www\./', '', $domain );
/* Use the domain as the key as well to prevent duplicates for efficiency purposes */
$nofollowExclude[ $domain ] = $domain;
}
$values['posts_add_nofollow_exclude'] = json_encode( array_values( $nofollowExclude ) );
$values['posts_add_nofollow_exclude'] = json_encode( $values['posts_add_nofollow_exclude'] );
$form->saveAsSettings( $values );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
\IPS\Session::i()->log( 'acplogs__url_filter_settings' );
/* Redirect otherwise our changes to posts_add_nofollow_exclude won't reflect initially */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=posting&tab=urlFilters' ), 'saved' );
}
return $form;
@@ -1,242 +0,0 @@
<?php
/**
* @brief Search settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 14 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\admin\settings;
/* 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;
}
/**
* Search settings
*/
class _search extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'search_manage' );
parent::execute();
}
/**
* Manage Settings
*
* @return void
* @note There is a hardcoded check for Sphinx here
* @todo The lang string replacements need to be checked <- checked for what?
*/
protected function manage()
{
/* Rebuild button */
\IPS\Output::i()->sidebar['actions'] = array(
'rebuildIndex' => array(
'title' => 'search_rebuild_index',
'icon' => 'undo',
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=search&do=queueIndexRebuild' ),
'data' => array( 'confirm' => '', 'confirmSubMessage' => \IPS\Member::loggedIn()->language()->get('search_rebuild_index_confirm') ),
),
);
\IPS\Member::loggedIn()->language()->words['search_engine__sphinx_desc'] = sprintf( \IPS\Member::loggedIn()->language()->get('search_engine__sphinx_desc'), \IPS\Settings::i()->sphinx_base_path . '/sphinx.conf' );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Radio( 'search_engine', isset( \IPS\Request::i()->search_sphinx_server ) ? 'sphinx' : \IPS\Settings::i()->search_engine, TRUE, array( 'options' => $this->_getEngines(), 'toggles' => array( 'mysql' => array( 'search_index_timeframe' ), 'sphinx' => array( 'form_header_sphinx_header', 'form_header_sphinx_instructions', 'search_sphinx_server', 'search_sphinx_port', 'sphinx_base_path', 'sphinx_prefix' ) ) ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'search_index_timeframe', \IPS\Settings::i()->search_index_timeframe, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'all' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_prefix'), \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_suffix'), 'search_index_timeframe' ) );
$form->addHeader( 'sphinx_header' );
if ( \IPS\Settings::i()->search_engine == 'sphinx' )
{
$form->addMessage( 'sphinx_instructions', '', TRUE, 'form_header_sphinx_instructions' );
}
$form->add( new \IPS\Helpers\Form\Text( 'search_sphinx_server', \IPS\Settings::i()->search_sphinx_server, FALSE, array(), function( $val )
{
if ( $val === 'localhost' )
{
throw new \DomainException('search_sphinx_server_err');
}
}, NULL, NULL, 'search_sphinx_server' ) );
$form->add( new \IPS\Helpers\Form\Number( 'search_sphinx_port', \IPS\Settings::i()->search_sphinx_port, FALSE, array( 'placeholder' => "3312" ), NULL, NULL, NULL, 'search_sphinx_port' ) );
$form->add( new \IPS\Helpers\Form\Text( 'sphinx_base_path', \IPS\Settings::i()->sphinx_base_path, FALSE, array( 'placeholder' => "/var/sphinx" ), NULL, NULL, NULL, 'sphinx_base_path' ) );
$form->add( new \IPS\Helpers\Form\Text( 'sphinx_prefix', \IPS\Settings::i()->sphinx_prefix, FALSE, array(), NULL, NULL, NULL, 'sphinx_prefix' ) );
if ( $values = $form->values() )
{
$existing = \IPS\Settings::i()->search_engine;
$indexPrune = \IPS\Settings::i()->search_index_timeframe;
/* Did we just enable Sphinx? If so, we need some more instructions... */
if( $existing != $values['search_engine'] and $values['search_engine'] === 'sphinx' )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=search&do=sphinxInstructions' )->setQueryString( $values ) );
}
/* Otherwise go ahead and save... */
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplogs__search_settings' );
/* And re-index if setting updated */
if( $existing != $values['search_engine'] or $indexPrune != $values['search_index_timeframe'] )
{
\IPS\Content\Search\Index::i()->rebuild();
}
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_settings_search');
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global' )->block( 'menu__core_settings_search', $form );
}
/**
* Show Sphinx instructions
*
* @return void
*/
public function sphinxInstructions()
{
$configuration = array();
foreach ( array( 'search_sphinx_server', 'search_sphinx_port', 'sphinx_prefix', 'sphinx_base_path' ) as $k )
{
$configuration[ $k ] = isset( \IPS\Request::i()->$k ) ? \IPS\Request::i()->$k : '';
}
$error = NULL;
if ( isset( \IPS\Request::i()->check ) )
{
try
{
$database = \IPS\Db::i( 'SPHINXQL', array(
'sql_host' => \IPS\Request::i()->search_sphinx_server,
'sql_user' => NULL,
'sql_pass' => NULL,
'sql_database' => NULL,
'sql_port' => (int) \IPS\Request::i()->search_sphinx_port,
'sql_socket' => NULL,
'sql_utf8mb4' => NULL,
) );
$result = $database->query("SHOW STATUS");
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 'sphinx' ), array( 'conf_key=?', 'search_engine' ) );
foreach ( $configuration as $k => $v )
{
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $v ), array( 'conf_key=?', $k ) );
\IPS\Settings::i()->$k = $v;
}
unset( \IPS\Data\Store::i()->settings );
\IPS\Session::i()->log( 'acplogs__search_settings' );
\IPS\Content\Search\Index::i()->rebuild();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=search' ), 'sphinx_setup_successful' );
}
catch( \Exception $exception )
{
\IPS\Log::i( \LOG_INFO )->write( get_class( $exception ) . "\n" . $exception->getCode() . ": " . $exception->getMessage() . "\n" . $exception->getTraceAsString() );
$error = 'sphinx_appear_invalid';
}
}
$configurationUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=search&do=sphinxConfiguration' )->setQueryString( $configuration );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('sphinx_header');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'settings' )->sphinxInstructions( $configurationUrl, $error );
}
/**
* Get Sphinx conifguration file
*
* @return void
*/
public function sphinxConfiguration()
{
$server = isset( \IPS\Request::i()->search_sphinx_server ) ? \IPS\Request::i()->search_sphinx_server : \IPS\Settings::i()->search_sphinx_server;
$port = isset( \IPS\Request::i()->search_sphinx_port ) ? \IPS\Request::i()->search_sphinx_port : \IPS\Settings::i()->search_sphinx_port;
$prefix = isset( \IPS\Request::i()->sphinx_prefix ) ? \IPS\Request::i()->sphinx_prefix : \IPS\Settings::i()->sphinx_prefix;
$path = isset( \IPS\Request::i()->sphinx_base_path ) ? \IPS\Request::i()->sphinx_base_path : \IPS\Settings::i()->sphinx_base_path;
$collation = 'utf8_general_ci';
$sphinxConfiguration = <<<SPHINX
searchd
{
listen = {$server}:{$port}:mysql41
max_children = 30
pid_file = {$path}/buildsearchd.pid
preopen_indexes = 0
collation_server = {$collation}
workers = threads
}
index {$prefix}ips
{
type = rt
path = {$path}/index
rt_field = index_title
rt_field = index_content
rt_field = index_tags
rt_attr_bigint = index_object_id
rt_attr_bigint = index_item_id
rt_attr_bigint = index_container_id
rt_attr_bigint = index_author
rt_attr_bigint = index_views
rt_attr_bigint = index_num_comments
rt_attr_bigint = index_num_reviews
rt_attr_json = index_permissions
rt_attr_timestamp = index_date_created
rt_attr_timestamp = index_date_updated
rt_attr_string = index_class
rt_attr_uint = index_class_id
rt_attr_uint = index_hidden
}
SPHINX;
\IPS\Output::i()->sendOutput( $sphinxConfiguration, 200, 'application/octet-stream', array( 'Content-Disposition' => 'attachment; filename=sphinx.conf' ) );
}
/**
* Get the array of engine options
*
* @return array
*/
protected function _getEngines()
{
$engines = array();
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . "/system/Content/Search/" ) as $file )
{
if ( $file->isDir() and !$file->isDot() and $file != 'index.html' )
{
$name = mb_strtolower( $file );
$engines[ $name ] = 'search_engine__' . $name;
}
}
return $engines;
}
/**
* Queue an index rebuild
*
* @return void
*/
protected function queueIndexRebuild()
{
\IPS\Content\Search\Index::i()->rebuild();
\IPS\Session::i()->log( 'acplogs__queued_search_index' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=search' ), 'search_index_rebuilding' );
}
}
@@ -78,21 +78,76 @@ class _terms extends \IPS\Dispatcher\Controller
if ( $values = $form->values() )
{
/* What were our previous values? */
$existingPrivacyPolicy = iterator_to_array( \IPS\Db::i()->select( 'word_custom', 'core_sys_lang_words', array( 'word_key=?', 'privacy_text_value' ) ) );
$existingRegistrationTerms = iterator_to_array( \IPS\Db::i()->select( 'word_custom', 'core_sys_lang_words', array( 'word_key=?', 'reg_rules_value' ) ) );
/* Save */
foreach ( array( 'gl_guidelines' => 'guidelines_value', 'privacy_text' => 'privacy_text_value', 'reg_rules' => 'reg_rules_value' ) as $k => $v )
{
\IPS\Lang::saveCustom( 'core', $v, $values[ $k ] );
unset( $values[ $k ] );
}
$form->saveAsSettings( $values );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
/* Log */
\IPS\Session::i()->log( 'acplogs__terms_edited' );
/* Do we need to ask the admin if they want to ask members to reconfirm? */
$changedPrivacyPolicy = $existingPrivacyPolicy != iterator_to_array( \IPS\Db::i()->select( 'word_custom', 'core_sys_lang_words', array( 'word_key=?', 'privacy_text_value' ) ) );
$changedRegistrationTerms = $existingRegistrationTerms != iterator_to_array( \IPS\Db::i()->select( 'word_custom', 'core_sys_lang_words', array( 'word_key=?', 'reg_rules_value' ) ) );
if ( $changedPrivacyPolicy or $changedRegistrationTerms )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=settings&controller=terms&do=reconfirm')->setQueryString( array(
'privacy' => intval( $changedPrivacyPolicy ),
'reg' => intval( $changedRegistrationTerms )
) ) );
}
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_settings_terms');
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global' )->block( 'menu__core_settings_terms', $form );
}
/**
* Ask the admin if they want users to re-confirm
*
* @return void
*/
protected function reconfirm()
{
$form = new \IPS\Helpers\Form;
$form->addMessage( 'admin_reconfirm_blurb' );
if ( \IPS\Request::i()->reg )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'admin_reconfirm_reg_terms', FALSE ) );
}
if ( \IPS\Request::i()->privacy )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'admin_reconfirm_privacy', FALSE ) );
}
if ( $values = $form->values() )
{
if ( isset( $values['admin_reconfirm_reg_terms'] ) and $values['admin_reconfirm_reg_terms'] )
{
\IPS\Db::i()->update( 'core_members', "members_bitoptions2 = members_bitoptions2 | " . \IPS\Member::$bitOptions['members_bitoptions']['members_bitoptions2']['must_reaccept_terms'] );
}
if ( isset( $values['admin_reconfirm_privacy'] ) and $values['admin_reconfirm_privacy'] )
{
\IPS\Db::i()->update( 'core_members', "members_bitoptions2 = members_bitoptions2 | " . \IPS\Member::$bitOptions['members_bitoptions']['members_bitoptions2']['must_reaccept_privacy'] );
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=settings&controller=terms') );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_settings_terms');
\IPS\Output::i()->output = $form;
}
}
@@ -457,11 +457,6 @@ class _admin extends \IPS\Dispatcher\Controller
'ctime' => function( $val )
{
return (string) \IPS\DateTime::ts( $val );
},
'module' => function( $val, $key )
{
$key = "module__{$key['appcomponent']}_{$val}";
return \IPS\Member::loggedIn()->language()->addToStack( $key );
}
);
$table->sortBy = $table->sortBy ?: 'ctime';
@@ -472,7 +467,6 @@ class _admin extends \IPS\Dispatcher\Controller
'member_id' => \IPS\Helpers\Table\SEARCH_MEMBER,
'ip_address' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
'ctime' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'module' => array( \IPS\Helpers\Table\SEARCH_NODE, array( 'class' => 'IPS\Application', 'subnodeWhere' => array( 'sys_module_area=?', 'admin' ), 'searchProp' => 'key' ) ),
'note' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
);
$table->quickSearch = 'note';
@@ -279,6 +279,9 @@ class _moderators extends \IPS\Dispatcher\Controller
}
}
}
/* We need to remember which keys are 'nodes' so we can adjust values upon submit */
$nodeFields = array();
/* Build */
$form = new \IPS\Helpers\Form;
@@ -304,6 +307,12 @@ class _moderators extends \IPS\Dispatcher\Controller
/* Class */
$type = is_array( $data ) ? $data[0] : $data;
$class = '\IPS\Helpers\Form\\' . ( $type );
/* Remember 'nodes' */
if( $type == 'Node' )
{
$nodeFields[ $name ] = $name;
}
/* Current Value */
if ( $currentPermissions === '*' )
@@ -326,6 +335,12 @@ class _moderators extends \IPS\Dispatcher\Controller
else
{
$currentValue = ( isset( $currentPermissions[ $name ] ) ? $currentPermissions[ $name ] : NULL );
/* We translate nodes to -1 so the moderator permissions merging works as expected allowing "all" to override individual node selections */
if( $type == 'Node' AND $currentValue == -1 )
{
$currentValue = 0;
}
}
/* Options */
@@ -360,6 +375,16 @@ class _moderators extends \IPS\Dispatcher\Controller
{
foreach ( $values as $k => $v )
{
/* For node fields, if the value is 0 translate it to -1 so mod permissions can merge properly */
if( in_array( $k, $nodeFields ) )
{
if( $v == 0 )
{
$v = -1;
$values[ $k ] = $v;
}
}
if ( is_array( $v ) )
{
foreach ( $v as $l => $w )
@@ -422,6 +447,7 @@ class _moderators extends \IPS\Dispatcher\Controller
/* Display */
\IPS\Output::i()->title = $_name;
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_members.js', 'core', 'admin' ) );
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'members' )->moderatorPermissions( $_name, $form );
}
@@ -541,11 +567,6 @@ class _moderators extends \IPS\Dispatcher\Controller
'ctime' => function( $val )
{
return (string) \IPS\DateTime::ts( $val );
},
'module' => function( $val, $key )
{
$key = "module__{$key['appcomponent']}_{$val}";
return \IPS\Member::loggedIn()->language()->addToStack( $key );
}
);
$table->sortBy = $table->sortBy ?: 'ctime';
@@ -556,7 +577,6 @@ class _moderators extends \IPS\Dispatcher\Controller
'member_id' => \IPS\Helpers\Table\SEARCH_MEMBER,
'ip_address' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
'ctime' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'module' => array( \IPS\Helpers\Table\SEARCH_NODE, array( 'class' => 'IPS\Application', 'subnodeWhere' => array( 'sys_module_area=?', 'front' ), 'searchProp' => 'key' ) )
);
/* Add a button for settings */
@@ -66,6 +66,7 @@ class _sql extends \IPS\Dispatcher\Controller
$table->sortBy = $table->sortBy ?: 'name';
$table->sortDirection = $table->sortDirection ?: 'asc';
$table->quickSearch = 'name';
$table->limit = 200;
/* Buttons */
$table->rowButtons = function( $row )
@@ -7,7 +7,6 @@
* @package IPS Social Suite
* @since 21 May 2014
* @version SVN_VERSION_NUMBER
* @modified 13.09.2015 by IAF
*/
namespace IPS\core\modules\admin\support;
@@ -159,12 +158,7 @@ class _support extends \IPS\Dispatcher\Controller
$baseUrl = $baseUrl->setQueryString( 'next', $overrideThingToTry );
}
$possibleSolutions = array( '_requirementsChecker', '_databaseChecker', '_clearCaches', '_connectionChecker', '_md5sumChecker', '_upgradeCheck', '_defaultTheme' );
if ( !\IPS\NO_WRITES )
{
$possibleSolutions[] = '_disableThirdParty';
}
$possibleSolutions[] = '_knowledgebase';
$possibleSolutions = array( '_requirementsChecker', '_databaseChecker', '_clearCaches', '_connectionChecker', '_md5sumChecker', '_upgradeCheck', '_disableAdvertisements', '_disableThirdParty', '_knowledgebase' );
$self = $this;
return new \IPS\Helpers\MultipleRedirect(
@@ -298,42 +292,17 @@ class _support extends \IPS\Dispatcher\Controller
* @return string|NULL
*/
public function _md5sumChecker( $id )
{
return NULL;
}
/**
* Step 2: md5sum Checker Iterator
*
* @param string $directory Directory to look through
* @return array
*/
public function _md5sumCheckerIterator( $directory, $correctMd5s )
{
$return = array();
foreach( new \DirectoryIterator( $directory ) as $file )
{
try
{
if ( mb_substr( $file, 0, 1 ) === '.' or mb_substr( $file, 0, 1 ) === '_' or $file == 'index.html' )
$files = \IPS\Application::md5Check();
if ( count( $files ) )
{
continue;
}
if ( $file->isDir() )
{
$return = array_merge( $return, $this->_md5sumCheckerIterator( $file->getPathname(), $correctMd5s ) );
}
elseif ( mb_substr( $file, -4 ) === '.php' )
{
$fullPath = $file->getPathname();
$shortPath = mb_substr( $fullPath, mb_strlen( \IPS\ROOT_PATH ) );
if ( $shortPath != '/init.php' and isset( $correctMd5s[ $shortPath ] ) and md5( preg_replace( '#\s#', '', file_get_contents( $fullPath ) ) ) != $correctMd5s[ $shortPath ] ) // We strip whitespace since FTP in ASCII mode will change the whitespace characters
{
$return[] = $fullPath;
}
return \IPS\Theme::i()->getTemplate( 'support' )->md5sum( $files, $id );
}
}
return $return;
catch ( \Exception $e ) {}
return NULL;
}
/**
@@ -400,47 +369,49 @@ class _support extends \IPS\Dispatcher\Controller
}
/**
* Step 2: Self Service - Instruct user to try using default theme
* Step 2: Self Service - Disable advertisements
*
* @param int $id The current ID
* @return string|NULL
*/
public function _defaultTheme( $id )
public function _disableAdvertisements( $id )
{
if ( isset( \IPS\Request::i()->deleteTheme ) )
if ( isset( \IPS\Request::i()->enableAds ) )
{
try
{
\IPS\Theme::load( \IPS\Request::i()->deleteTheme )->delete();
foreach ( explode( ',', \IPS\Request::i()->enableAds ) as $ad )
{
try
{
$ad = \IPS\core\Advertisement::load( $ad );
$ad->active = 1;
$ad->save();
}
catch ( \Exception $e ) {}
}
catch ( \Exception $e ) {}
return NULL;
}
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_templates', 'template_set_id>0' )->first() or \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_css', 'css_set_id>0' )->first() )
{
$newTheme = new \IPS\Theme;
$newTheme->permissions = \IPS\Member::loggedIn()->member_group_id;
$newTheme->save();
$newTheme->installThemeSettings();
$newTheme->copyResourcesFromSet();
\IPS\Lang::saveCustom( 'core', "core_theme_set_title_" . $newTheme->id, "IPS Support" );
\IPS\Member::loggedIn()->skin = $newTheme->id;
if( \IPS\Member::loggedIn()->acp_skin !== NULL )
{
\IPS\Member::loggedIn()->acp_skin = $newTheme->id;
}
\IPS\Member::loggedIn()->save();
return \IPS\Theme::i()->getTemplate( 'support' )->tryNow( $id, 'try_default_theme', '&deleteTheme=' . $newTheme->id );
}
$disabledAds = array();
return NULL;
/* Loop ads */
foreach( \IPS\Db::i()->select( '*' ,'core_advertisements', array( 'ad_active=?', 1 ) ) as $ad )
{
$ad = \IPS\core\Advertisement::constructFromData( $ad );
$ad->active = 0;
$disabledAds[] = $ad->id;
}
/* Do any? */
if ( count( $disabledAds ) )
{
return \IPS\Theme::i()->getTemplate( 'support' )->disabledAdvertisements( $id, '&enableAds=' . implode( ',', $disabledAds ) );
}
else
{
return NULL;
}
}
/**
@@ -451,8 +422,28 @@ class _support extends \IPS\Dispatcher\Controller
*/
public function _disableThirdParty( $id )
{
if ( isset( \IPS\Request::i()->enableApps ) or isset( \IPS\Request::i()->enablePlugins ) )
/* Button to put stuff back */
if ( isset( \IPS\Request::i()->deleteTheme ) or isset( \IPS\Request::i()->enableApps ) or isset( \IPS\Request::i()->enablePlugins ) )
{
/* Theme */
if ( isset( \IPS\Request::i()->deleteTheme ) )
{
try
{
\IPS\Theme::load( \IPS\Request::i()->deleteTheme )->delete();
}
catch ( \Exception $e ) {}
if( isset( $_SESSION['old_acp_theme'] ) )
{
\IPS\Member::loggedIn()->acp_skin = $_SESSION['old_acp_theme'];
\IPS\Member::loggedIn()->save();
unset( $_SESSION['old_acp_theme'] );
}
}
/* Apps */
foreach ( explode( ',', \IPS\Request::i()->enableApps ) as $app )
{
try
@@ -464,6 +455,7 @@ class _support extends \IPS\Dispatcher\Controller
catch ( \Exception $e ) {}
}
/* Plugins */
foreach ( explode( ',', \IPS\Request::i()->enablePlugins ) as $plugin )
{
try
@@ -478,41 +470,71 @@ class _support extends \IPS\Dispatcher\Controller
return NULL;
}
/* Init */
$restoredDefaultTheme = FALSE;
$disabledApps = array();
$disabledPlugins = array();
$disabledAppNames = array();
$disabledPluginNames = array();
/* Loop Apps */
foreach ( \IPS\Application::applications() as $app )
/* Do we need to restore the default theme? */
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_templates', 'template_set_id>0' )->first() or \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_css', 'css_set_id>0' )->first() )
{
if ( $app->enabled and !in_array( $app->directory, \IPS\Application::$ipsApps ) )
$newTheme = new \IPS\Theme;
$newTheme->permissions = \IPS\Member::loggedIn()->member_group_id;
$newTheme->save();
$newTheme->installThemeSettings();
$newTheme->copyResourcesFromSet();
\IPS\Lang::saveCustom( 'core', "core_theme_set_title_" . $newTheme->id, "IPS Support" );
\IPS\Member::loggedIn()->skin = $newTheme->id;
if( \IPS\Member::loggedIn()->acp_skin !== NULL )
{
$app->enabled = FALSE;
$app->save();
$disabledApps[] = $app->directory;
$disabledAppNames[] = $app->_title;
$_SESSION['old_acp_theme'] = \IPS\Member::loggedIn()->acp_skin;
\IPS\Member::loggedIn()->acp_skin = $newTheme->id;
}
\IPS\Member::loggedIn()->save();
$restoredDefaultTheme = TRUE;
}
/* Do we need to disable any third party apps/plugins? */
if ( !\IPS\NO_WRITES )
{
/* Loop Apps */
foreach ( \IPS\Application::applications() as $app )
{
if ( $app->enabled and !in_array( $app->directory, \IPS\Application::$ipsApps ) )
{
$app->enabled = FALSE;
$app->save();
$disabledApps[] = $app->directory;
$disabledAppNames[] = $app->_title;
}
}
/* Look Plugins */
foreach ( \IPS\Plugin::plugins() as $plugin )
{
if ( $plugin->enabled )
{
$plugin->enabled = FALSE;
$plugin->save();
$disabledPlugins[] = $plugin->id;
$disabledPluginNames[] = $plugin->_title;
}
}
}
/* Look Plugins */
foreach ( \IPS\Plugin::plugins() as $plugin )
/* Did we do anything? */
if ( $restoredDefaultTheme or count( $disabledApps ) or count( $disabledPlugins ) )
{
if ( $plugin->enabled )
{
$plugin->enabled = FALSE;
$plugin->save();
$disabledPlugins[] = $plugin->id;
$disabledPluginNames[] = $plugin->_title;
}
}
/* Do any? */
if ( count( $disabledApps ) or count( $disabledPlugins ) )
{
return \IPS\Theme::i()->getTemplate( 'support' )->thirdParty( $id, $disabledAppNames, $disabledPluginNames, '&enableApps=' . implode( ',', $disabledApps ) . '&enablePlugins=' . implode( ',', $disabledPlugins ) );
return \IPS\Theme::i()->getTemplate( 'support' )->thirdParty( $id, $disabledAppNames, $disabledPluginNames, $restoredDefaultTheme, '&enableApps=' . implode( ',', $disabledApps ) . '&enablePlugins=' . implode( ',', $disabledPlugins ) . ( $restoredDefaultTheme ? '&deleteTheme=' . $newTheme->id : '' ) );
}
else
{
@@ -550,7 +572,123 @@ class _support extends \IPS\Dispatcher\Controller
*/
public function _contactSupport( $data )
{
return \IPS\Theme::i()->getTemplate( 'global' )->message( '__iaf__nulling_null_alert', 'error' );
$licenseData = \IPS\IPS::licenseKey();
if ( !$licenseData or strtotime( $licenseData['expires'] ) < time() )
{
return \IPS\Theme::i()->getTemplate( 'global' )->message( 'get_support_no_license', 'warning' );
}
try
{
$supportedVerions = \IPS\Http\Url::ips('support/versions')->request()->get()->decodeJson();
if ( \IPS\Application::load('core')->long_version > $supportedVerions['max'] )
{
return \IPS\Theme::i()->getTemplate( 'global' )->message( 'get_support_unsupported_prerelease', 'warning' );
}
if ( \IPS\Application::load('core')->long_version < $supportedVerions['min'] )
{
return \IPS\Theme::i()->getTemplate( 'global' )->message( 'get_support_unsupported_obsolete', 'warning' );
}
}
catch ( \Exception $e ) {}
$form = new \IPS\Helpers\Form( 'contact_support', 'contact_support_submit' );
$form->class = 'ipsForm_vertical ipsPad';
$extraOptions = array( 'admin' => 'support_request_admin' );
if ( $this->_supportLog( TRUE ) )
{
$form->hiddenValues['_log'] = '1';
$extraOptions['log'] = 'support_request_log';
}
$form->add( new \IPS\Helpers\Form\Text( 'support_request_title', NULL, TRUE, array( 'maxLength' => 128 ) ) );
$form->add( new \IPS\Helpers\Form\Editor( 'support_request_body', NULL, TRUE, array( 'app' => 'core', 'key' => 'Admin', 'autoSaveKey' => 'acp-support-request' ) ) );
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'support_request_extra', array( 'admin', 'log' ), FALSE, array( 'options' => $extraOptions ) ) );
if ( $values = $form->values() )
{
$admin = NULL;
if ( in_array( 'admin', $values['support_request_extra'] ) )
{
$password = '';
$length = rand( 8, 15 );
for ( $i = 0; $i < $length; $i++ )
{
do {
$key = rand( 33, 126 );
} while ( in_array( $key, array( 34, 39, 60, 62, 92 ) ) );
$password .= chr( $key );
}
$supportAccount = \IPS\Member::load( 'nobody@invisionpower.com', 'email' );
if ( !$supportAccount->member_id )
{
$name = 'IPS Support';
$_supportAccount = \IPS\Member::load( $name, 'name' );
if ( $_supportAccount->member_id )
{
$number = 2;
while ( $_supportAccount->member_id )
{
$name = "IPS Support {$number}";
$_supportAccount = \IPS\Member::load( $name, 'name' );
$number++;
}
}
$supportAccount = new \IPS\Member;
$supportAccount->name = $name;
$supportAccount->email = 'nobody@invisionpower.com';
$supportAccount->member_group_id = \IPS\Settings::i()->admin_group;
}
$supportAccount->members_pass_salt = $supportAccount->generateSalt();
$supportAccount->members_pass_hash = $supportAccount->encryptedPassword( $password );
$supportAccount->save();
$admin = json_encode( array( 'name' => $supportAccount->name, 'email' => $supportAccount->email, 'password' => $password, 'dir' => \IPS\CP_DIRECTORY ) );
}
$log = NULL;
if ( in_array( 'log', $values['support_request_extra'] ) )
{
$log = $this->_supportLog( FALSE );
}
$key = md5( \IPS\Http\Url::internal('app=core&module=support&controller=support') );
unset( $_SESSION["wizard-{$key}-step"] );
unset( $_SESSION["wizard-{$key}-data"] );
\IPS\Output::i()->parseFileObjectUrls( $values['support_request_body'] );
$response = \IPS\Http\Url::ips('support')->request()->login( \IPS\Settings::i()->ipb_reg_number, '' )->post( array(
'title' => $values['support_request_title'],
'message' => $values['support_request_body'],
'admin' => $admin,
'log' => $log,
'_log' => intval( isset( $values['_log'] ) )
) );
switch ( $response->httpResponseCode )
{
case 200:
case 201:
return \IPS\Theme::i()->getTemplate( 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'get_support_done', FALSE, array( 'pluralize' => array( intval( (string) $response ) ) ) ), 'success' );
case 401:
case 403:
return \IPS\Theme::i()->getTemplate( 'global' )->message( 'get_support_no_license', 'warning' );
case 429:
return \IPS\Theme::i()->getTemplate( 'global' )->message( 'get_support_duplicate', 'error' );
case 502:
default:
return \IPS\Theme::i()->getTemplate( 'global' )->message( 'get_support_error', 'error' );
}
}
return (string) $form;
}
/**
@@ -597,6 +735,4 @@ class _support extends \IPS\Dispatcher\Controller
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('support')->logToSend( $this->_supportLog( FALSE ) );
}
}
/* Nulled by IandroidFan (IAF) */
}
@@ -58,7 +58,7 @@ class _systemLogs extends \IPS\Dispatcher\Controller
krsort( $dataSource );
/* Create the table */
$table = new \IPS\Helpers\Table\Custom( array_slice( $dataSource, 0, 50 ), \IPS\Http\Url::internal( 'app=core&module=support&controller=systemLogs' ) );
$table = new \IPS\Helpers\Table\Custom( $dataSource, \IPS\Http\Url::internal( 'app=core&module=support&controller=systemLogs' ) );
$table->langPrefix = 'systemlogs_';
$table->mainColumn = 'title';
@@ -89,7 +89,7 @@ class _ajax extends \IPS\core\modules\front\system\ajax
$keywords[ $word['url'] ]['keywords'][] = $word['keyword'];
}
\file_put_contents( \IPS\ROOT_PATH . "/applications/{$qs['app']}/data/acpsearch.json", json_encode( $keywords ) );
\file_put_contents( \IPS\ROOT_PATH . "/applications/{$qs['app']}/data/acpsearch.json", json_encode( $keywords, version_compare( PHP_VERSION, '5.4.0' ) >= 0 ? JSON_PRETTY_PRINT : 0 ) );
}
\IPS\Output::i()->json( 'ok' );
@@ -34,7 +34,7 @@ class _login extends \IPS\Dispatcher\Controller
$url = \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'admin', NULL, array(), \IPS\Settings::i()->logins_over_https );
if ( isset( \IPS\Request::i()->ref ) )
{
$url = $url->setQueryString( 'ref', base64_encode( \IPS\Request::i()->ref ) );
$url = $url->setQueryString( 'ref', \IPS\Request::i()->ref );
}
$login = new \IPS\Login( $url );
$login->flagOptions = FALSE;
@@ -62,14 +62,21 @@ class _login extends \IPS\Dispatcher\Controller
$this->log( 'ok' );
/* Clean out any existing session ID in the URL */
$queryString = '';
$queryString = array();
if( isset( \IPS\Request::i()->ref ) )
{
$queryString = preg_replace( "/adsess=([a-zA-Z0-9]+)(?:&|$)/", '', base64_decode( \IPS\Request::i()->ref ) );
$_queryString = array();
parse_str( preg_replace( "/adsess=([a-zA-Z0-9]+)(?:&|$)/", '', base64_decode( \IPS\Request::i()->ref ) ), $_queryString );
foreach ( $_queryString as $k => $v )
{
if ( in_array( $k, array( 'app', 'module', 'controller' ) ) )
{
$queryString[ $k ] = $v;
}
}
}
/* Boink */
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( $queryString ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( http_build_query( $queryString ) ) );
}
/* Error */
else
@@ -0,0 +1,352 @@
<?php
/**
* @brief upgrade
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 28 Jul 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\admin\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;
}
/**
* upgrade
*/
class _upgrade extends \IPS\Dispatcher\Controller
{
/**
* Manage
*
* @return void
*/
protected function manage()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'upgrade_manage' );
if ( \IPS\NO_WRITES )
{
\IPS\Output::i()->error( 'no_writes', '1C287/1', 403, '' );
}
$wizard = new \IPS\Helpers\Wizard( array(
'upgrade_confirm_update' => array( $this, '_selectVersion' ),
'upgrade_login' => array( $this, '_login' ),
'upgrade_extract_update' => array( $this, '_extractUpdate' ),
'upgrade_upgrade' => array( $this, '_upgrade' ),
), \IPS\Http\Url::internal( 'app=core&module=system&controller=upgrade' ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('ips_suite_upgrade');
\IPS\Output::i()->output = $wizard;
}
/**
* Select Version
*
* @param array $data Wizard data
* @return string|array
*/
public function _selectVersion( $data )
{
/* Check latest version */
$versions = array();
foreach ( \IPS\Db::i()->select( '*', 'core_applications', \IPS\Db::i()->in( 'app_directory', \IPS\Application::$ipsApps ) ) as $app )
{
if ( $app['app_enabled'] )
{
$versions[] = $app['app_long_version'];
}
}
$version = min( $versions );
$url = \IPS\Http\Url::ips('updateCheck');
if ( \IPS\USE_DEVELOPMENT_BUILDS )
{
$url = $url->setQueryString( 'development', 1 );
}
try
{
$response = $url->setQueryString( 'version', $version )->request()->get()->decodeJson();
$coreApp = \IPS\Application::load('core');
$coreApp->update_version = json_encode( $response );
$coreApp->update_last_check = time();
$coreApp->save();
}
catch ( \Exception $e ) { }
/* Build form */
$form = new \IPS\Helpers\Form( 'select_version' );
$options = array();
$descriptions = array();
$latestVersion = 0;
foreach( \IPS\Application::load( 'core' )->availableUpgrade() as $possibleVersion )
{
$options[ $possibleVersion['longversion'] ] = $possibleVersion['version'];
$descriptions[ $possibleVersion['longversion'] ] = $possibleVersion;
if ( $latestVersion < $possibleVersion['longversion'] )
{
$latestVersion = $possibleVersion['longversion'];
}
}
$form->add( new \IPS\Helpers\Form\Radio( 'version', $latestVersion, TRUE, array( 'options' => $options, '_details' => $descriptions ) ) );
/* Handle submissions */
if ( $values = $form->values() )
{
return array( 'version' => $values['version'] );
}
/* Display */
return $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'system' ) ), 'upgradeSelectVersion' ) );
}
/**
* Login
*
* @param array $data Wizard data
* @return string|array
*/
public function _login( $data )
{
/* Build form */
$form = new \IPS\Helpers\Form( 'login', 'continue' );
$form->hiddenValues['version'] = $data['version'];
$form->add( new \IPS\Helpers\Form\Email( 'ips_email_address', NULL ) );
$form->add( new \IPS\Helpers\Form\Password( 'ips_password', NULL ) );
/* Handle submissions */
if ( $values = $form->values() )
{
$key = \IPS\IPS::licenseKey();
$url = \IPS\Http\Url::ips( 'build/' . $key['key'] )->setQueryString( 'ip', \IPS\Request::i()->ipAddress() );
if ( \IPS\USE_DEVELOPMENT_BUILDS )
{
$url = $url->setQueryString( 'development', 1 );
}
elseif ( isset( $values['version'] ) )
{
$url = $url->setQueryString( 'versionToDownload', $values['version'] );
}
if ( \IPS\CP_DIRECTORY !== 'admin' )
{
$url = $url->setQueryString( 'cp_directory', \IPS\CP_DIRECTORY );
}
try
{
$response = $url->request( 30 )->login( $values['ips_email_address'], $values['ips_password'] )->get();
switch ( $response->httpResponseCode )
{
case 200:
if ( !preg_match( '/^ips_[a-z0-9]{5}$/', (string) $response ) )
{
\IPS\Log::i( LOG_ERR )->write( (string) $response );
$form->error = \IPS\Member::loggedIn()->language()->addToStack('download_upgrade_error');
break;
}
else
{
$data['key'] = (string) $response;
return $data;
}
case 304:
if ( \IPS\Db::i()->select( 'MIN(app_long_version)', 'core_applications', \IPS\Db::i()->in( 'app_directory', \IPS\Application::$ipsApps ) )->first() < \IPS\Application::getAvailableVersion('core') )
{
$data['key'] = NULL;
return $data;
}
$form->error = \IPS\Member::loggedIn()->language()->addToStack('download_upgrade_nothing');
break;
default:
$form->error = (string) $response;
}
}
catch ( \Exception $exception )
{
\IPS\Log::i( LOG_ERR )->write( get_class( $exception ) . "\n" . $exception->getCode() . ": " . $exception->getMessage() . "\n" . $exception->getTraceAsString() );
$form->error = \IPS\Member::loggedIn()->language()->addToStack('download_upgrade_error');
}
}
return (string) $form;
}
/**
* Extract Update
*
* @param array $data Wizard data
* @return string|array
*/
public function _extractUpdate( $data )
{
/* Download & Extract */
if ( $data['key'] and !isset( \IPS\Request::i()->check ) )
{
/* Muliple Redirector */
return (string) new \IPS\Helpers\MultipleRedirect( \IPS\Http\Url::internal('app=core&module=system&controller=upgrade'), function( $mrData ) use ( $data )
{
/* Init */
if ( !is_array( $mrData ) )
{
return array( array( 'status' => 'download' ), \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_downloading'), 0 );
}
/* Download */
elseif ( $mrData['status'] == 'download' )
{
if ( !isset( $mrData['tmpFileName'] ) )
{
$mrData['tmpFileName'] = tempnam( \IPS\TEMP_DIRECTORY, 'IPS' ) . '.zip';
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_downloading'), 0 );
}
else
{
if ( !isset( $mrData['range'] ) )
{
$mrData['range'] = 0;
}
$startRange = $mrData['range'];
$endRange = $startRange + 1000000 - 1;
$response = \IPS\Http\Url::ips("download/{$data['key']}")->request( 30 )->setHeaders( array( 'Range' => "bytes={$startRange}-{$endRange}" ) )->get();
try
{
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Fetching download [range={$startRange}-{$endRange}] with a response code: " . $response->httpResponseCode, 'auto_upgrade' );
}
catch( \Exception $ex ) { }
if ( $response->httpResponseCode == 404 )
{
if ( isset( $mrData['tmpFileName'] ) )
{
@unlink( $mrData['tmpFileName'] );
}
return array( \IPS\Theme::i()->getTemplate('system')->upgradeDeltaFailed( TRUE, isset( $data['key'] ) ? \IPS\Http\Url::ips("download/{$data['key']}") : NULL ) );
}
elseif ( $response->httpResponseCode == 206 )
{
$totalFileSize = intval( mb_substr( $response->httpHeaders['Content-Range'], mb_strpos( $response->httpHeaders['Content-Range'], '/' ) + 1 ) );
$fh = \fopen( $mrData['tmpFileName'], 'a' );
\fwrite( $fh, (string) $response );
\fclose( $fh );
$mrData['range'] = $endRange + 1;
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_downloading'), 100 / $totalFileSize * $mrData['range'] );
}
else
{
$mrData['status'] = 'extract';
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_extracting'), 0 );
}
}
}
/* Extract */
elseif ( $mrData['status'] == 'extract' )
{
try
{
try
{
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Attempting to extract", 'auto_upgrade' );
}
catch( \Exception $ex ) { }
/* Open the zip */
$zip = \IPS\Archive\Zip::fromLocalFile( $mrData['tmpFileName'], $data['key'] . '/' );
/* Extract some files */
$numberToDo = 20;
if ( !isset( $mrData['extractNumber'] ) )
{
$mrData['extractNumber'] = 0;
}
$offset = $mrData['extractNumber'];
if ( $zip->extract( \IPS\ROOT_PATH, $numberToDo, $offset ) === TRUE )
{
if ( isset( $mrData['tmpFileName'] ) )
{
@unlink( $mrData['tmpFileName'] );
}
return NULL;
}
else
{
$mrData['extractNumber'] += $numberToDo;
$numberOfFiles = $zip->numberOfFiles();
try
{
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Extracting files {$mrData['extractNumber']} / {$numberOfFiles}", 'auto_upgrade' );
}
catch( \Exception $ex ) { }
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_extracting'), 100 / $numberOfFiles * $mrData['extractNumber'] );
}
}
catch ( \RuntimeException $e )
{
try
{
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Extract Failed", 'auto_upgrade' );
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( $e, 'auto_upgrade' );
}
catch( \Exception $ex ) { }
\IPS\Session\Admin::i()->log( ( $e->getCode() === \IPS\Archive\Exception::COULD_NOT_OPEN ) ? 'delta_upgrade_zip_fail' : ( $e->getCode() === \IPS\Archive\Exception::COULD_NOT_WRITE ? 'delta_upgrade_write_fail' : '' ) );
if ( isset( $mrData['tmpFileName'] ) )
{
@unlink( $mrData['tmpFileName'] );
}
return array( \IPS\Theme::i()->getTemplate('system')->upgradeDeltaFailed( $e->getCode(), isset( $data['key'] ) ? \IPS\Http\Url::ips("download/{$data['key']}") : NULL ) );
}
}
},
function()
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=system&controller=upgrade&check=1') );
} );
}
/* Run md5 check */
try
{
$files = \IPS\Application::md5Check();
if ( count( $files ) )
{
return \IPS\Theme::i()->getTemplate('system')->upgradeDeltaFailed( $files, isset( $data['key'] ) ? \IPS\Http\Url::ips("download/{$data['key']}") : NULL );
}
}
catch ( \Exception $e ) {}
/* Nope, we're good! */
return $data;
}
/**
* Upgrade
*
* @param array $data Wizard data
* @return string|array
*/
public function _upgrade( $data )
{
\IPS\Output::i()->redirect( 'upgrade/?adsess=' . \IPS\Request::i()->adsess );
}
}