Version 4.5.0

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

No files matched your search

@@ -11,7 +11,7 @@
namespace IPS\core\modules\admin\editor;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -22,6 +22,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _emoticons extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -56,7 +61,6 @@ class _emoticons extends \IPS\Dispatcher\Controller
'options' => array(
'native' => 'emoji_style_native',
'twemoji' => 'emoji_style_twemoji',
'emojione' => 'emoji_style_emojione',
'disabled' => 'emoji_style_disabled',
),
) ) );
@@ -75,7 +79,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
}
else
{
$activeTabContents = \IPS\Theme::i()->getTemplate( 'global' )->message( 'emoji_utf8mb4_required', 'error', NULL, TRUE, TRUE );
$activeTabContents = \IPS\Theme::i()->getTemplate( 'global' )->message( \IPS\CIC ? 'emoji_utf8mb4_required_cic' : 'emoji_utf8mb4_required', 'error', NULL, TRUE, TRUE );
}
}
else
@@ -148,10 +152,9 @@ class _emoticons extends \IPS\Dispatcher\Controller
{
$setId = $values['emoticons_add_choosegroup'];
$position = \IPS\Db::i()->select( 'MAX(emo_position)', 'core_emoticons', array( 'emo_set=?', $setId ) )->first( );
$position = $position['pos'];
}
if ( !is_array( $values['emoticons_upload'] ) )
if ( !\is_array( $values['emoticons_upload'] ) )
{
$values['emoticons_upload'] = array( $values['emoticons_upload'] );
}
@@ -180,13 +183,13 @@ class _emoticons extends \IPS\Dispatcher\Controller
);
}
if( count( $inserts ) )
if( \count( $inserts ) )
{
\IPS\Db::i()->insert( 'core_emoticons', $inserts );
}
/* Add 2x */
if( count( $images2x ) )
if( \count( $images2x ) )
{
foreach( \IPS\Db::i()->select( '*', 'core_emoticons', array( 'emo_set=?', $setId ) ) as $emo )
{
@@ -218,8 +221,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
}
}
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'emoji_cache' => time() ) );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -239,7 +241,8 @@ class _emoticons extends \IPS\Dispatcher\Controller
*/
protected function edit()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'emoticons_edit' );
\IPS\Dispatcher::i()->checkAcpPermission( 'emoticons_edit' );
\IPS\Session::i()->csrfCheck();
$position = 0;
$set = NULL;
@@ -264,7 +267,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
foreach ( $emoticons as $group => $emos )
{
if( isset( \IPS\Request::i()->$group ) AND is_array( \IPS\Request::i()->$group ) )
if( isset( \IPS\Request::i()->$group ) AND \is_array( \IPS\Request::i()->$group ) )
{
foreach( \IPS\Request::i()->$group as $id )
{
@@ -277,8 +280,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
}
}
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'emoji_cache' => time() ) );
\IPS\Output::i()->json( 'OK' );
return;
@@ -327,8 +329,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
}
}
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'emoji_cache' => time() ) );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -371,8 +372,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
\IPS\Session::i()->log( 'acplog__emoticon_deleted' );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'emoji_cache' => time() ) );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -409,8 +409,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
\IPS\Db::i()->delete( 'core_emoticons', array( 'emo_set=?', $set ) );
\IPS\Lang::deleteCustom( 'core', 'core_emoticon_group_'. $set );
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
unset( \IPS\Data\Store::i()->settings );
\IPS\Settings::i()->changeValues( array( 'emoji_cache' => time() ) );
/* Clear guest page caches */
\IPS\Data\Cache::i()->clearAll();
@@ -11,7 +11,7 @@
namespace IPS\core\modules\admin\editor;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -22,6 +22,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -56,7 +61,8 @@ class _settings extends \IPS\Dispatcher\Controller
protected function manage()
{
/* Work out output */
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
$methodToCall = '_manage' . mb_ucfirst( $this->activeTab );
$activeTabContents = $this->$methodToCall();
/* If this is an AJAX request, just return it */
if( \IPS\Request::i()->isAjax() )
@@ -87,6 +93,8 @@ class _settings extends \IPS\Dispatcher\Controller
0 => 'editor_paragraph_padding_off'
) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'enable_bbcode', \IPS\Settings::i()->enable_bbcode, FALSE ) );
if ( $values = $form->values() )
{
$clearCss = ( $values['editor_paragraph_padding'] !== \IPS\Settings::i()->editor_paragraph_padding );
@@ -11,7 +11,7 @@
namespace IPS\core\modules\admin\editor;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -56,6 +56,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
'ipsquote',
'ipssource',
'ipsspoiler',
'ipsgiphy',
'justify',
'lineutils',
'list',
@@ -71,6 +72,11 @@ class _toolbar extends \IPS\Dispatcher\Controller
'widget',
);
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -123,7 +129,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
'revert' => array(
'icon' => 'refresh',
'title' => 'editor_revert',
'link' => \IPS\Http\Url::internal( "app=core&module=editor&controller=toolbar&do=revert" ),
'link' => \IPS\Http\Url::internal( "app=core&module=editor&controller=toolbar&do=revert" )->csrf(),
'data' => array( 'confirm' => '', 'confirmSubMessage' => \IPS\Member::loggedIn()->language()->addToStack('editor_revert_confirm' ) )
)
);
@@ -136,6 +142,8 @@ class _toolbar extends \IPS\Dispatcher\Controller
*/
protected function save()
{
\IPS\Session::i()->csrfCheck();
$save = array();
$toolbars = json_decode( \IPS\Request::i()->toolbars, TRUE );
@@ -222,7 +230,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
{
$attributes[] = "{$k}='{$v}'";
}
$attributes = count( $attributes ) ? ( ' ' . implode( ' ', $attributes ) ) : '';
$attributes = \count( $attributes ) ? ( ' ' . implode( ' ', $attributes ) ) : '';
$content = ( $matches2[4] === 'true' ) ? '{content}' : '';
$matches2[3] = json_decode( $matches2[3] );
$matches2[5] = json_decode( $matches2[5] );
@@ -249,7 +257,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Select( 'editor_permission_areas', isset( $current[ $button ] ) ? $current[ $button ]['areas'] : '*', TRUE, array( 'options' => $areas, 'multiple' => TRUE, 'unlimited' => '*', 'unlimitedLang' => 'everywhere' ), NULL, NULL, NULL, 'l' . $b64Button ) );
/* If this is a custom one, add a delete button */
if ( in_array( mb_strtolower( $button ), explode( ',', mb_strtolower( \IPS\Settings::i()->ckeditor_extraPlugins ) ) ) or preg_match( '/^custom-\w{32}$/i', $button ) )
if ( \in_array( mb_strtolower( $button ), explode( ',', mb_strtolower( \IPS\Settings::i()->ckeditor_extraPlugins ) ) ) or preg_match( '/^custom-\w{32}$/i', $button ) )
{
$form->addButton( 'delete', 'link', (string) \IPS\Http\Url::internal( "app=core&module=editor&controller=toolbar&do=deletePlugin&key={$button}" ), 'ipsButton ipsButton_negative' );
}
@@ -342,7 +350,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
/* Build Form */
if ( class_exists( 'ZipArchive', FALSE ) )
{
if ( !is_writable( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins' ) )
if ( !\IPS\CIC2 AND !is_writable( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins' ) )
{
\IPS\Output::i()->error( 'editor_plugin_nowrite', '4C120/2', 403, '' );
}
@@ -352,9 +360,14 @@ class _toolbar extends \IPS\Dispatcher\Controller
else
{
$plugins = array();
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins' ) as $f )
$path = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins';
if ( \IPS\CIC2 )
{
if ( !$f->isDot() and $f->isDir() and $f !== 'index.html' and !in_array( (string) $f, array_merge( static::$defaultPlugins, explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins ) ) ) )
$path = \IPS\SITE_FILES_PATH . '/ckeditor_custom';
}
foreach ( new \DirectoryIterator( $path ) as $f )
{
if ( !$f->isDot() and $f->isDir() and $f !== 'index.html' and !\in_array( (string) $f, array_merge( static::$defaultPlugins, explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins ) ) ) )
{
$plugins[ (string) $f ] = (string) $f;
}
@@ -395,55 +408,125 @@ class _toolbar extends \IPS\Dispatcher\Controller
}
zip_close( $zip );
/* If the content of the plugin is in the root of the zip, then we need to manually create the folder and key */
$extractTo = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins';
if ( $inRoot === TRUE )
/* Cloud2 handles extraction */
if ( \IPS\CIC2 )
{
/* Remove the .zip extension from the filename */
$name = explode( '_', $fileName );
$name = array_shift( $name );
$extractTo .= '/' . $name;
\IPS\Cicloud\file( "IPScustomcke_{$name}.zip", \file_get_contents( $tmpName ) );
do
{
if ( isset( \IPS\Data\Store::i()->syncCompleted ) AND \IPS\Data\Store::i()->syncCompleted )
{
break;
}
}
while( TRUE );
}
/* Check it isn't already installed */
if ( in_array( $name, array_merge( static::$defaultPlugins, explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins ) ) ) )
else
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('editor_plugin_already_installed');
goto displayForm;
/* If the content of the plugin is in the root of the zip, then we need to manually create the folder and key */
$extractTo = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins';
if ( $inRoot === TRUE )
{
/* Remove the .zip extension from the filename */
$name = explode( '_', $fileName );
$name = array_shift( $name );
$extractTo .= '/' . $name;
}
$pluginDirectory = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $name;
if ( \IPS\CIC2 )
{
$pluginDirectory = \IPS\SITE_FILES_PATH . '/ckeditor_custom/' . $name;
}
/* Check it isn't already installed */
if ( \in_array( $name, array_merge( static::$defaultPlugins, explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins ) ) ) )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('editor_plugin_already_installed');
goto displayForm;
}
/* Extract it */
$zip = new \ZipArchive;
$zip->open( $tmpName );
$zip->extractTo( $extractTo );
$zip->close();
/* Delete the temp file */
unlink( $tmpName );
}
/* Extract it */
$zip = new \ZipArchive;
$zip->open( $tmpName );
$zip->extractTo( $extractTo );
$zip->close();
/* Delete the temp file */
unlink( $tmpName );
}
else
{
$name = $values['editor_plugin_folder'];
if ( !file_exists( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $name . '/plugin.js' ) )
$path = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $name . '/plugin.js';
if ( \IPS\CIC2 )
{
$path = \IPS\SITE_FILES_PATH . '/ckeditor_custom/' . $name . '/plugin.js';
}
if ( !file_exists( $path ) )
{
\IPS\Output::i()->error( 'editor_bad_plugin_directory', '1C120/9', 400, '' );
}
}
unset( \IPS\Data\Store::i()->syncCompleted );
/* See if we can sniff out requirements for this plugin. */
if ( !file_exists( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $name . '/plugin.js' ) )
$path = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $name . '/plugin.js';
if ( \IPS\CIC2 )
{
\IPS\Output::i()->error( 'editor_bad_plugin', '1C120/9', 400, '' );
$path = \IPS\SITE_FILES_PATH . '/ckeditor_custom/' . $name . '/plugin.js';
}
$file = \file_get_contents( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $name . '/plugin.js' );
if ( !file_exists( $path ) )
{
/* If we just extracted some files remove them as the plugin was apparently not valid */
if ( isset( $values['editor_plugin_zip'] ) )
{
if( \is_dir( $pluginDirectory ) )
{
if ( \IPS\CIC2 )
{
\IPS\Cicloud\deleteFolder( 'ckeditor_custom/' . $name );
}
else
{
try
{
$iterator = new \RecursiveDirectoryIterator( $pluginDirectory, \FilesystemIterator::SKIP_DOTS );
foreach ( new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::CHILD_FIRST ) as $file )
{
if ( $file->isDir() )
{
@rmdir( $file->getPathname() );
}
else
{
@unlink( $file->getPathname() );
}
}
$handle = opendir( $pluginDirectory );
closedir ( $pluginDirectory );
@rmdir( $pluginDirectory );
}
catch( \UnexpectedValueException $e ){}
}
}
}
\IPS\Output::i()->error( 'editor_bad_plugin', '1C120/B', 400, '' );
}
$file = \file_get_contents( $path );
preg_match( "#requires: \'(.+?)\',#i", $file, $matches );
if ( isset( $matches[1] ) )
{
$required = explode( ',', $matches[1] );
$rewriteFileWithIpsContextMenuRequirement = FALSE;
if ( in_array( 'contextmenu', $required ) )
if ( \in_array( 'contextmenu', $required ) )
{
$required[ array_search( 'contextmenu', $required ) ] = 'ipscontextmenu';
$rewriteFileWithIpsContextMenuRequirement = TRUE;
@@ -451,9 +534,9 @@ class _toolbar extends \IPS\Dispatcher\Controller
$current = array_merge( static::$defaultPlugins, explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins ) );
$missing = array_diff( $required, $current );
if ( count( $missing ) > 0 )
if ( \count( $missing ) > 0 )
{
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'editor_missing_requirements', FALSE, array( 'sprintf' => array( count( $missing ), implode( ', ', $missing ) ) ) ), '2C120/5', 404, '' );
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'editor_missing_requirements', FALSE, array( 'sprintf' => array( \count( $missing ), implode( ', ', $missing ) ) ) ), '2C120/5', 404, '' );
}
if ( $rewriteFileWithIpsContextMenuRequirement )
@@ -543,7 +626,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
}
/* Automatically detect and allow custom css classes */
if( count( $cssClasses ) )
if( \count( $cssClasses ) )
{
$settingClasses = \IPS\Settings::i()->editor_allowed_classes ? explode( ',', \IPS\Settings::i()->editor_allowed_classes ) : array();
$settingClasses = array_unique( array_merge( $settingClasses, $cssClasses ) );
@@ -565,7 +648,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
}
/* Automatically detect and allow custom css classes */
if( count( $dataControllers ) )
if( \count( $dataControllers ) )
{
$settingControllers = \IPS\Settings::i()->editor_allowed_datacontrollers ? explode( ',', \IPS\Settings::i()->editor_allowed_datacontrollers ) : array();
$settingControllers = array_unique( array_merge( $settingControllers, $dataControllers ) );
@@ -714,30 +797,46 @@ JS;
}
/* Write it */
$dir = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $key;
if ( !is_dir( $dir ) )
if ( \IPS\CIC2 )
{
mkdir( $dir );
chmod( $dir, \IPS\IPS_FOLDER_PERMISSION );
}
\file_put_contents( $dir . '/plugin.js', $pluginFile );
if ( $values['editor_button_image'] )
{
if ( !is_dir( $dir . '/icons' ) )
\IPS\Cicloud\file( 'plugin.js', $pluginFile, "ckeditor_custom/{$key}" );
if ( $values['editor_button_image'] )
{
mkdir( $dir . '/icons' );
chmod( $dir . '/icons', \IPS\IPS_FOLDER_PERMISSION );
\IPS\Cicloud\file( "{$key}.png", \file_get_contents( $values['editor_button_image'] ), "ckeditor_custom/{$key}/icons" );
}
\file_put_contents( "{$dir}/icons/{$key}.png", file_get_contents( $values['editor_button_image'] ) );
}
if ( $dialogFile )
{
if ( !is_dir( $dir . '/dialogs' ) )
if ( $dialogFile )
{
mkdir( $dir . '/dialogs' );
chmod( $dir . '/dialogs', \IPS\IPS_FOLDER_PERMISSION );
\IPS\Cicloud\file( "{$key}.js", $dialogFile, "ckeditor_custom/{$key}/dialogs" );
}
}
else
{
$dir = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $key;
if ( !is_dir( $dir ) )
{
mkdir( $dir );
chmod( $dir, \IPS\IPS_FOLDER_PERMISSION );
}
\file_put_contents( $dir . '/plugin.js', $pluginFile );
if ( $values['editor_button_image'] )
{
if ( !is_dir( $dir . '/icons' ) )
{
mkdir( $dir . '/icons' );
chmod( $dir . '/icons', \IPS\IPS_FOLDER_PERMISSION );
}
\file_put_contents( "{$dir}/icons/{$key}.png", file_get_contents( $values['editor_button_image'] ) );
}
if ( $dialogFile )
{
if ( !is_dir( $dir . '/dialogs' ) )
{
mkdir( $dir . '/dialogs' );
chmod( $dir . '/dialogs', \IPS\IPS_FOLDER_PERMISSION );
}
\file_put_contents( "{$dir}/dialogs/{$key}.js", $dialogFile );
}
\file_put_contents( "{$dir}/dialogs/{$key}.js", $dialogFile );
}
/* Save name */
@@ -758,7 +857,7 @@ JS;
}
if ( \IPS\NO_WRITES )
{
\IPS\Output::i()->error( 'no_writes', '1C120/3', 403, '' );
\IPS\Output::i()->error( 'no_writes', '1C120/C', 403, '' );
}
/* Make sure the user confirmed the deletion */
@@ -772,7 +871,7 @@ JS;
$jsFile = file_get_contents( \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/' . $file . '/plugin.js' );
if ( preg_match( '/requires:\"(.+?)\"/i', $jsFile, $matches ) )
{
if ( in_array( mb_strtolower( \IPS\Request::i()->key ), explode( ',', mb_strtolower( $matches[1] ) ) ) )
if ( \in_array( mb_strtolower( \IPS\Request::i()->key ), explode( ',', mb_strtolower( $matches[1] ) ) ) )
{
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'editor_plugin_requirements', FALSE, array( 'sprintf' => array( $file ) ) ), '1C120/3', 403, '' );
}
@@ -842,16 +941,25 @@ JS;
* @return void
*/
public function revert()
{
{
\IPS\Session::i()->csrfCheck();
if ( !empty( \IPS\Settings::i()->ckeditor_extraPlugins ) and !\IPS\NO_WRITES )
{
$extraPlugins = explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins );
$dir = \IPS\ROOT_PATH . '/applications/core/interface/ckeditor/ckeditor/plugins/';
foreach( $extraPlugins AS $key )
{
if ( is_dir( $dir . $key ) )
if ( \IPS\CIC2 )
{
$this->_recursiveRmDir( $dir . $key );
\IPS\Cicloud\deleteFolder( "ckeditor_custom/{$key}" );
}
else
{
if ( is_dir( $dir . $key ) )
{
$this->_recursiveRmDir( $dir . $key );
}
}
}