Version 4.3.6

This commit is contained in:
Neo committed 2025-12-19 05:49:12 -08:00
1 parent fe1acf984a
commit 1a0c7fd3c2
609 files changed
+14707 -5726

No files matched your search

+107 -2
View File
@@ -115,7 +115,7 @@ class _Application extends \IPS\Application
return (
$module->key == 'system'
and
in_array( $controller, array( 'login', 'register', 'lostpass', 'terms', 'ajax', 'privacy', 'editor', 'language', 'theme', 'redirect', 'guidelines' ) )
in_array( $controller, array( 'login', 'register', 'lostpass', 'terms', 'ajax', 'privacy', 'editor', 'language', 'theme', 'redirect', 'guidelines', 'announcement' ) )
)
or
(
@@ -141,7 +141,8 @@ class _Application extends \IPS\Application
'login', // Because you can login when offline
'embed', // Because the offline message can contain embedded media
'lostpass',
'register'
'register',
'announcement' // Announcements can be useful when the site is offline
) )
or
(
@@ -271,6 +272,110 @@ class _Application extends \IPS\Application
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=modcp&controller=modcp&tab=reports&action=view&id=' . \IPS\Request::i()->rid , 'front', 'modcp_report' ) );
}
}
/**
* Get any third parties this app uses for the privacy policy
*
* @return array( title => language bit, description => language bit, privacyUrl => privacy policy URL )
*/
public function privacyPolicyThirdParties()
{
/* Apps can overload this */
$subprocessors = array();
/* Analytics */
if ( \IPS\Settings::i()->ipbseo_ga_provider == 'ga' )
{
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('enhancements__core_GoogleAnalytics'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_GoogleAnalytics'),
'privacyUrl' => 'https://www.google.com/intl/en/policies/privacy/'
);
}
else if ( \IPS\Settings::i()->ipbseo_ga_provider == 'piwik' )
{
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('analytics_provider_piwik'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_Piwik'),
'privacyUrl' => 'https://matomo.org/privacy-policy/'
);
}
/* Facebook Pixel */
$fb = new \IPS\core\extensions\core\CommunityEnhancements\FacebookPixel();
if ( $fb->enabled )
{
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('enhancements__core_FacebookPixel'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_FacebookPixel'),
'privacyUrl' => 'https://www.facebook.com/about/privacy/'
);
}
/* IPS Spam defense */
if ( \IPS\Settings::i()->spam_service_enabled )
{
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('enhancements__core_SpamMonitoring'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_SpamMonitoring'),
'privacyUrl' => 'https://invisioncommunity.com/legal/privacy'
);
}
/* Send Grid */
$sendgrid = new \IPS\core\extensions\core\CommunityEnhancements\Sendgrid();
if ( $sendgrid->enabled )
{
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('enhancements__core_Sendgrid'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_SendGrid'),
'privacyUrl' => 'https://sendgrid.com/policies/privacy/'
);
}
/* Captcha */
if ( \IPS\Settings::i()->bot_antispam_type !== 'none' )
{
switch ( \IPS\Settings::i()->bot_antispam_type )
{
case 'recaptcha2':
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('captcha_type_recaptcha2'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_captcha'),
'privacyUrl' => 'https://www.google.com/policies/privacy/'
);
break;
case 'invisible':
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('captcha_type_invisible'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_captcha'),
'privacyUrl' => 'https://www.google.com/policies/privacy/'
);
break;
case 'keycaptcha':
$subprocessors[] = array(
'title' => \IPS\Member::loggedIn()->language()->addToStack('captcha_type_keycaptcha'),
'description' => \IPS\Member::loggedIn()->language()->addToStack('pp_desc_captcha'),
'privacyUrl' => 'https://www.keycaptcha.com'
);
break;
}
}
return $subprocessors;
}
/**
* Get any settings that are uploads
*
* @return array
*/
public function uploadSettings()
{
/* Apps can overload this */
return array( 'email_logo' );
}
/**
* Imports an IN_DEV email template into the database
+2 -1
View File
@@ -306,7 +306,8 @@ class _members extends \IPS\Api\Controller
$member = new \IPS\Member;
$member->member_group_id = \IPS\Settings::i()->member_group;
$member->members_bitoptions['created_externally'] = TRUE;
$member = $this->_createOrUpdate( $member );
return new \IPS\Api\Response( 201, $member->apiOutput( $this->member ) );
+40 -2
View File
@@ -47,20 +47,34 @@ class _search extends \IPS\Api\Controller
* @apiparam string eitherTermsOrTags Whether to search both tags and search term ("and") or either ("or")
* @apiparam string search_and_or Whether to perform an "and" search or an "or" search for all search terms
* @apiparam string search_in Specify "titles" to search in titles only, otherwise titles and content are both searched
* @apiparam int search_as Member ID to perform the search as (guest permissions will be used when this parameter is omitted)
* @return array
* @apiresponse int page api_int_page
* @apiresponse int perPage api_int_perpage
* @apiresponse int totalResults api_int_totalresults
* @apiresponse int totalPages api_int_totalpages
* @apiresponse [\IPS\Content\Search\Result] results api_results_thispage
* @note For requests using an OAuth Access Token for a particular member, only content the authorized user can view will be included and the "search_as" parameter will be ignored.
*/
public function GETindex()
{
$memberPermissions = $this->member;
if( !$this->member AND isset( \IPS\Request::i()->search_as ) )
{
$memberPermissions = \IPS\Member::load( \IPS\Request::i()->search_as );
if( !$memberPermissions->member_id )
{
$memberPermissions = NULL;
}
}
/* Get valid content types */
$contentTypes = \IPS\core\modules\front\search\search::contentTypes();
$contentTypes = \IPS\core\modules\front\search\search::contentTypes( $memberPermissions ?: TRUE );
/* Initialize search */
$query = \IPS\Content\Search\Query::init();
$query = \IPS\Content\Search\Query::init( $memberPermissions ?: NULL );
/* Set content type */
if ( isset( \IPS\Request::i()->type ) and array_key_exists( \IPS\Request::i()->type, $contentTypes ) )
@@ -209,4 +223,28 @@ class _search extends \IPS\Api\Controller
);
}
/**
* GET /core/search/contenttypes
* Get list of content types that can be searched
*
* @clientapiparam int search_as Member ID to perform the search as (by default, search results are based on guest permissions)
* @return array
* @apiresponse array contenttypes Content types that can be used in /search requests in the 'type' parameter
*/
public function GETitem()
{
$memberPermissions = $this->member;
if( !$this->member AND isset( \IPS\Request::i()->search_as ) )
{
$memberPermissions = \IPS\Member::load( \IPS\Request::i()->search_as );
if( !$memberPermissions->member_id )
{
$memberPermissions = NULL;
}
}
return new \IPS\Api\Response( 200, array( 'contenttypes' => array_keys( \IPS\core\modules\front\search\search::contentTypes( $memberPermissions ?: TRUE ) ) ) );
}
}
+2 -1
View File
@@ -140,7 +140,8 @@
"membertools_ip": "membertools_ip",
"member_recount_content": "member_recount_content",
"member_export": "member_export",
"member_history": "member_history"
"member_history": "member_history",
"member_export_pi": "member_export_pi"
},
"groups": {
"groups_manage": "groups_manage",
+53 -1
View File
@@ -221,6 +221,16 @@
"searching"
]
},
"app=core&module=discovery&controller=search&searchResult=form_search_method": {
"lang_key": "search_method",
"restriction": "search_manage",
"keywords": [
"elastic",
"elasticsearch",
"mysql",
"search"
]
},
"app=core&module=discovery&controller=search&searchResult=search_index_timeframe": {
"lang_key": "search_index_timeframe",
"restriction": "search_manage",
@@ -1209,7 +1219,7 @@
]
},
"app=core&module=moderation&controller=spam": {
"lang_key": "menu__core_membersettings_spam",
"lang_key": "menu__core_moderation_spam",
"restriction": "spam_manage",
"keywords": [
"spam",
@@ -1609,6 +1619,15 @@
"logs"
]
},
"app=core&module=settings&controller=email&searchResult=our_picks_in_email": {
"lang_key": "our_picks_in_email",
"restriction": "email_manage",
"keywords": [
"email",
"our picks",
"promotion"
]
},
"app=core&module=settings&controller=email&searchResult=settings_form_email_color": {
"lang_key": "email_color",
"restriction": "email_manage",
@@ -1651,6 +1670,14 @@
"smtp"
]
},
"app=core&module=settings&controller=email&searchResult=social_links_in_email": {
"lang_key": "social_links_in_email",
"restriction": "email_manage",
"keywords": [
"email",
"social"
]
},
"app=core&module=settings&controller=general&searchResult=form_board_name": {
"lang_key": "board_name",
"restriction": "general_manage",
@@ -1821,6 +1848,13 @@
"validation"
]
},
"app=core&module=settings&controller=login&tab=registration&searchResult=updates_consent_default": {
"lang_key": "updates_consent_default",
"restriction": "login_access",
"keywords": [
"gdpr"
]
},
"app=core&module=settings&controller=login&tab=registration&searchResult=use_coppa": {
"lang_key": "use_coppa",
"restriction": "registration_manage",
@@ -1983,6 +2017,15 @@
"flood control"
]
},
"app=core&module=settings&controller=posting&searchResult=form_ip_address_prune": {
"lang_key": "ip_address_prune",
"restriction": "posting_manage",
"keywords": [
"gdpr",
"ip address",
"prune"
]
},
"app=core&module=settings&controller=posting&searchResult=form_max_title_length": {
"lang_key": "max_title_length",
"restriction": "posting_manage",
@@ -2254,6 +2297,7 @@
"restriction": "terms_manage",
"keywords": [
"conditions",
"gdpr",
"guidelines",
"legal",
"privacy policy",
@@ -2266,6 +2310,7 @@
"restriction": "terms_manage",
"keywords": [
"cookie control",
"gdpr",
"terms bar"
]
},
@@ -2276,6 +2321,13 @@
"cookie control"
]
},
"app=core&module=settings&controller=terms&searchResult=privacy_show_processors": {
"lang_key": "privacy_show_processors",
"restriction": "terms_manage",
"keywords": [
"gdpr"
]
},
"app=core&module=staff&controller=admin": {
"lang_key": "menu__core_staff_admin",
"restriction": "restrictions_manage",
@@ -0,0 +1,72 @@
<?php
/**
* @brief Moderator Permissions: {class}
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
{subpackage}
* @since {date}
*/
namespace IPS\{app}\extensions\core\ContentModeratorPermissions;
/* 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;
}
/**
* Moderator Permissions: {class}
*/
class _{class}
{
/**
* Get Permissions
*
* @param array $toggles Toggle data
* @code
return array(
'key' => 'YesNo', // Can just return a string with type
'key' => array( // Or an array for more options
'YesNo', // Type
array( ... ), // Options (as defined by type's class)
'prefix', // Prefix
'suffix', // Suffix
),
...
);
* @endcode
* @return array
*/
public function getPermissions( $toggles )
{
return array();
}
/**
* After change
*
* @param array $moderator The moderator
* @param array $changed Values that were changed
* @return void
*/
public function onChange( $moderator, $changed )
{
}
/**
* After change
*
* @param array $moderator The moderator
* @return void
*/
public function onDelete( $moderator )
{
}
}
@@ -54,9 +54,10 @@ class _{class}
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -0,0 +1,37 @@
<?php
/**
* @brief ACP Export Personal Information
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
{subpackage}
* @since {date}
*/
namespace IPS\{app}\extensions\core\MemberExportPersonalInformation;
/* 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;
}
/**
* @brief ACP Export Personal Information
*/
class _Main
{
/**
* Return data
* @param \IPS\Member $member The member
*
* @return array
*/
public function getData( \IPS\Member $member )
{
$return = array();
return $return;
}
}
@@ -61,7 +61,7 @@ class _{class}
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
@@ -38,6 +38,26 @@ class _{class}
return array();
}
/**
* Save settings for ACP configuration
*
* @param array $values Values
* @return void
*/
public function saveSettings( $values )
{
if ( $values['sitemap_configuration_info'] )
{
// Store default values for any settings you define
//\IPS\Settings::i()->changeValues( array( ) );
}
else
{
// Store the actual submitted value for any settings you define, from the $values array
//\IPS\Settings::i()->changeValues( array( ) );
}
}
/**
* Get the sitemap filename(s)
*
+32 -29
View File
@@ -551,34 +551,38 @@
</table>
<br /><br />]]></template_content_html><template_data>$output, $app, $area, $max, $count, $email</template_data><template_content_plaintext>{$output|raw}
</template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>core</template_app><template_name>upgrade</template_name><template_content_html><![CDATA[
{$email->language->addToStack("dashboard_version_info", FALSE, array( 'sprintf' => $version ))}
<br />
<br />
{{if $security}}
<table width='100%' cellpadding='15' cellspacing='0' border='0' style='background: #b52b38; color: #fff;'>
{{foreach $updates as $update}}
{$email->language->addToStack("dashboard_version_info", FALSE, array( 'sprintf' => $update['version'] ))}
<br />
<br />
{{if $update['security']}}
<table width='100%' cellpadding='15' cellspacing='0' border='0' style='background: #b52b38; color: #fff;'>
<tr>
<td dir='{dir}'>
{$email->language->addToStack('this_is_a_security_update')}
</td>
</tr>
</table>
<br />
{{endif}}
<table width='100%' cellpadding='10' cellspacing='0' border='0'>
<tr>
<td dir='{dir}'>
{$email->language->addToStack('this_is_a_security_update')}
<td dir='{dir}' valign='top' style='background: #f9f9f9;'>
{$update['releasenotes']|raw}
</td>
</tr>
</table>
<br />
{{endif}}
<table width='100%' cellpadding='10' cellspacing='0' border='0'>
<tr>
<td dir='{dir}' valign='top' style='background: #f9f9f9;'>
{$releaseNotes|raw}
</td>
</tr>
</table>
<br /><br />
<br /><br />
{{endforeach}}
<a href='{url="&app=core&module=system&controller=upgrade" base="admin"}' style="color: #fff; font-family: 'Helvetica Neue', helvetica, sans-serif; text-decoration: none; font-size: 12px; background: {setting="email_color"}; line-height: 32px; padding: 0 10px; display: inline-block; border-radius: 3px;">{$email->language->addToStack("upgrade_now")}</a>
]]></template_content_html><template_data>$version, $releaseNotes, $security, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("dashboard_version_info", FALSE, array( 'sprintf' => $version ))}
{{if $security}}
{$email->language->addToStack('this_is_a_security_update')}
{{endif}}
]]></template_content_html><template_data>$updates, $latestVersion, $email</template_data><template_content_plaintext><![CDATA[{{foreach $updates as $update}}
{$email->language->addToStack("dashboard_version_info", FALSE, array( 'sprintf' => $update['version'] ))}
{{if $update['security']}}
{$email->language->addToStack('this_is_a_security_update')}
{{endif}}
{{endforeach}}
{$email->language->addToStack("upgrade_now")}: {url="&app=core&module=system&controller=upgrade" base="admin"}]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>core</template_app><template_name>notification_club_join</template_name><template_content_html><![CDATA[<br />
{$email->language->addToStack("notification__club_join", FALSE, array( 'sprintf' => array( $member->name, $club->name ) ) )}
@@ -804,7 +808,7 @@
<br />
</td>
</tr>
{{endif}}]]></template_content_html><template_data>$key, $member, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("unsubscribe_blurb", FALSE)} {$email->language->addToStack( 'adjust_notification_prefs', FALSE )}: {url="app=core&module=system&controller=notifications&do=options&type={$key}" seoTemplate="notifications_options"}]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>core</template_app><template_name>notification_new_content</template_name><template_content_html><![CDATA[
{{endif}}]]></template_content_html><template_data>$key, $member, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("unsubscribe_blurb", FALSE)} {$email->language->addToStack( 'adjust_notification_prefs', FALSE )}: {url="app=core&module=system&controller=notifications&do=options&type={$key}" base="front" seoTemplate="notifications_options"}]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>core</template_app><template_name>notification_new_content</template_name><template_content_html><![CDATA[
{{if $content->author()->member_id}}
{$email->language->addToStack("email_new_content", FALSE, array( 'sprintf' => array( $content->author()->url(), $content->author()->name, $content->indefiniteArticle( $email->language ) ) ) )} <a href='{$content->url()}'>{$content->mapped('title')}</a>
{{elseif $content->author()->real_name}}
@@ -1311,9 +1315,8 @@
{{endif}}
<td class='responsive_fullwidth cOurPicksRow' dir='{dir}' width='48%' valign='top' style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 15px;">
{{$staff = \IPS\Member::load( $item->added_by );}}
{{$title = $item->objectTitle;}}
<h2 style='font-size: 20px; margin: 0;'>
<a href="{$item->object()->url()}" style='color: #4a8aca; text-decoration: none;'>{$item->objectTitle}</a>
<a href="{$item->object()->url()}" style='color: #4a8aca; text-decoration: none;'>{$item->ourPicksTitle}</a>
</h2>
<p style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 13px; color: #8c8c8c; line-height: 21px; margin: 0">
{$item->objectMetaDescription( $email->language )}
@@ -1325,7 +1328,7 @@
{{endif}}
<p style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 15px; color: #8c8c8c; line-height: 21px; margin-top: 5px; margin-bottom: 0">
<a href="{$item->object()->url()}" style='color: #4a8aca; text-decoration: none;'>{$email->language->addToStack("digests_read_more")}</a>
{{if $counts = $item->objectDataCount}}
{{if $counts = $item->objectDataCount( $email->language )}}
&nbsp;&nbsp;({$counts['words']})
{{endif}}
</p>
@@ -1341,7 +1344,7 @@
</td>
<td dir='{dir}' width='100%' style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 13px; color: #8c8c8c;">
<strong>{$email->language->addToStack("promoted_by")}</strong><br>
{$staff->name}, {datetime="$item->sent" relative="false"}
{$staff->name}, {expression="\IPS\DateTime::ts( $item->sent )->localeDate( $email->language )"} {expression="\IPS\DateTime::ts( $item->sent )->localeTime( TRUE, TRUE, $email->language )"}
</td>
</tr>
</table>
@@ -1386,12 +1389,12 @@
{{endif}}
{{if \IPS\Settings::i()->site_social_profiles AND \IPS\Settings::i()->social_links_in_email AND $links = json_decode( \IPS\Settings::i()->site_social_profiles, TRUE ) AND count( $links )}}
{{$socialColors = array('internal' => '#008b00;', 'delicious' => '#3274D1;', 'deviantart' => '#16A085;', 'digg' => '#14589E;', 'email' => '#444;', 'facebook' => '#3B5998;', 'google' => '#D14836;', 'google-plus' => '#D14836;', 'linkedin' => '#007FB1;', 'reddit' => '#FF4500;', 'stumble' => '#EB4924;', 'twitter' => '#00ACED;', 'vk' => '#507299;', 'weibo' => '#D32F2F;', 'youtube' => '#E62117;', 'foursquare' => '#2D5BE3;', 'etsy' => '#F56400;', 'flickr' => '#202022;', 'github' => '#000000;', 'instagram' => '#E13D62;', 'pinterest' => '#BD081C;', 'slack' => '#42C299;', 'xing' => '#B0D400;');}}
{{$socialColors = array('internal' => '#008b00;', 'delicious' => '#3274D1;', 'deviantart' => '#16A085;', 'digg' => '#14589E;', 'email' => '#444;', 'facebook' => '#3B5998;', 'google' => '#D14836;', 'google-plus' => '#D14836;', 'linkedin' => '#007FB1;', 'reddit' => '#FF4500;', 'stumble' => '#EB4924;', 'twitter' => '#00ACED;', 'vk' => '#507299;', 'weibo' => '#D32F2F;', 'youtube' => '#E62117;', 'foursquare' => '#2D5BE3;', 'etsy' => '#F56400;', 'flickr' => '#202022;', 'github' => '#000000;', 'instagram' => '#E13D62;', 'pinterest' => '#BD081C;', 'slack' => '#42C299;', 'xing' => '#B0D400;', 'tumblr' => '#EB4924;');}}
<tr>
<td dir='{dir}' valign="top"><img src='{setting="base_url"}applications/core/interface/email/spacer.png' width='1' height='1' alt=''></td>
<td dir='{dir}' valign='top' width='800' align='center' style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 12px; color: #bdbdbd; line-height: 18px; padding-left: 10px;">
{{foreach $links as $profile}}
<a href='{$profile['key']}' target='_blank' class='cShareLink' style='width: 28px; height: 28px; line-height: 34px; text-align: center; border-radius: 16px; display: inline-block; color: white !important; font-size: 15px; margin: 4px 2px; background-color: {$socialColors[ $profile['value'] ]}'><img src='{setting="base_url"}applications/core/interface/email/{$profile['value']}.png' width='18' height='18' alt="{$profile['value']}"></a>
<a href='{$profile['key']}' target='_blank' rel="noopener" class='cShareLink' style='width: 28px; height: 28px; line-height: 34px; text-align: center; border-radius: 16px; display: inline-block; color: white !important; font-size: 15px; margin: 4px 2px; background-color: {$socialColors[ $profile['value'] ]}'><img src='{setting="base_url"}applications/core/interface/email/{$profile['value']}.png' width='18' height='18' alt="{$profile['value']}"></a>
{{endforeach}}
</td>
<td dir='{dir}' valign="top"><img src='{setting="base_url"}applications/core/interface/email/spacer.png' width='1' height='1' alt=''></td>
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+132 -89
View File
@@ -4377,18 +4377,18 @@
"name": "core_admin_permission_rows",
"columns": {
"row_id": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 8,
"name": "row_id",
"type": "INT",
"unsigned": false,
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": [],
"zerofill": false
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"row_id_type": {
"name": "row_id_type",
@@ -8993,9 +8993,9 @@
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"length": 20,
"name": "map_user_id",
"type": "INT",
"type": "BIGINT",
"unsigned": false,
"values": [],
"zerofill": false
@@ -10116,9 +10116,9 @@
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"length": 20,
"name": "upgrade_mid",
"type": "INT",
"type": "BIGINT",
"unsigned": false,
"values": [],
"zerofill": false
@@ -10614,18 +10614,18 @@
"zerofill": false
},
"plugin_enabled": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "Plugin is enabled?",
"decimals": null,
"default": "1",
"length": 1,
"name": "plugin_enabled",
"type": "BINARY",
"unsigned": false,
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": [],
"zerofill": false
"allow_null": false,
"default": "1",
"comment": "Plugin is enabled?",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"plugin_order": {
"allow_null": false,
@@ -13250,9 +13250,9 @@
"comment": "",
"decimals": null,
"default": "0",
"length": 8,
"length": 20,
"name": "ignore_owner_id",
"type": "INT",
"type": "BIGINT",
"unsigned": false,
"values": [],
"zerofill": false
@@ -13264,9 +13264,9 @@
"comment": "",
"decimals": null,
"default": "0",
"length": 8,
"length": 20,
"name": "ignore_ignore_id",
"type": "INT",
"type": "BIGINT",
"unsigned": false,
"values": [],
"zerofill": false
@@ -16985,9 +16985,9 @@
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"length": 20,
"name": "status_author_id",
"type": "INT",
"type": "BIGINT",
"unsigned": false,
"values": [],
"zerofill": false
@@ -17403,18 +17403,18 @@
"zerofill": false
},
"data": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "",
"length": 0,
"name": "data",
"type": "TEXT",
"unsigned": false,
"type": "MEDIUMTEXT",
"length": 0,
"decimals": null,
"values": [],
"zerofill": false
"allow_null": false,
"default": "",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"offset": {
"allow_null": false,
@@ -17912,9 +17912,9 @@
"comment": "The object author id",
"decimals": null,
"default": "0",
"length": 10,
"length": 20,
"name": "index_author",
"type": "INT",
"type": "BIGINT",
"unsigned": true,
"values": [],
"zerofill": false
@@ -18046,18 +18046,18 @@
"zerofill": false
},
"index_date_commented": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "Object last commented\/reviewed date",
"decimals": null,
"default": null,
"length": 10,
"name": "index_date_commented",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "Object last commented\/reviewed date",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
"values": [],
"zerofill": false
}
},
"indexes": {
@@ -18095,38 +18095,6 @@
"index_item_id"
]
},
"container": {
"type": "key",
"name": "container",
"length": [
181,
null
],
"columns": [
"index_class",
"index_container_id"
]
},
"index_date_updated": {
"type": "key",
"name": "index_date_updated",
"length": [
null
],
"columns": [
"index_date_updated"
]
},
"index_date_created": {
"type": "key",
"name": "index_date_created",
"length": [
null
],
"columns": [
"index_date_created"
]
},
"index_hidden": {
"type": "key",
"name": "index_hidden",
@@ -18181,12 +18149,75 @@
"index_club_id"
]
},
"index_date_commented": {
"type": "key",
"name": "index_date_commented",
"columns": [
"index_date_commented",
"index_date_updated"
],
"length": [
null,
null
]
},
"container": {
"type": "key",
"name": "container",
"length": [
171,
null,
null
],
"columns": [
"index_class",
"index_container_id",
"index_date_commented"
]
},
"author_posted_in": {
"type": "key",
"name": "author_posted_in",
"length": [
null,
null
],
"columns": [
"index_author",
"index_item_index_id"
]
},
"index_date_updated": {
"type": "key",
"name": "index_date_updated",
"length": [
null,
null
],
"columns": [
"index_date_updated",
"index_date_commented"
]
},
"index_date_created": {
"type": "key",
"name": "index_date_created",
"length": [
null,
null
],
"columns": [
"index_date_created",
"index_date_commented"
]
},
"author_lookup": {
"type": "key",
"name": "author_lookup",
"length": [
null,
170,
160,
null,
null,
null
],
@@ -18194,7 +18225,8 @@
"index_author",
"index_class",
"index_hidden",
"index_date_updated"
"index_date_updated",
"index_date_commented"
]
},
"index_content": {
@@ -18218,10 +18250,21 @@
"columns": [
"index_title"
]
},
"index_item_author": {
"type": "key",
"name": "index_item_author",
"columns": [
"index_item_author",
"index_date_commented"
],
"length": [
null,
null
]
}
},
"collation": "utf8mb4_unicode_ci",
"comment": "",
"reporting": "count"
},
"core_widget_trash": {
@@ -20027,9 +20070,9 @@
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"length": 20,
"name": "index_author_id",
"type": "INT",
"type": "BIGINT",
"unsigned": false,
"values": [],
"zerofill": false
@@ -24464,7 +24507,7 @@
"token"
],
"allow_null": false,
"default": null,
"default": "code",
"comment": "The response type",
"unsigned": false,
"zerofill": false,
+25
View File
@@ -639,6 +639,16 @@
"default": "imagemagick",
"report": "full"
},
{
"key": "imagick_strip_exif",
"default": "1",
"report": "full"
},
{
"key": "ip_address_prune",
"default": "",
"report": "full"
},
{
"key": "ipb_bruteforce_attempts",
"default": "3",
@@ -1024,6 +1034,11 @@
"default": "",
"report": "bool"
},
{
"key": "privacy_show_processors",
"default": "1",
"report": "full"
},
{
"key": "privacy_text",
"default": "",
@@ -1054,6 +1069,11 @@
"default": "0",
"report": "full"
},
{
"key": "promote_facebook_auth",
"default": "0",
"report": "none"
},
{
"key": "promote_groups",
"default": "",
@@ -1284,6 +1304,11 @@
"default": "",
"report": "none"
},
{
"key": "search_index_maxresults",
"default": "10000",
"report": "full"
},
{
"key": "search_index_timeframe",
"default": "0",
+1 -1
View File
@@ -1 +1 @@
{"profilesync":"P0Y0M0DT1H0M0S","updatecheck":"P0Y0M1DT0H0M0S","cleanup":"P0Y0M1DT0H0M0S","sitemapgenerator":"P0Y0M0DT0H15M0S","queue":"P0Y0M0DT0H1M0S","pop":"P0Y0M0DT0H10M0S","digest":"P0Y0M0DT0H10M0S","publish":"P0Y0M0DT0H10M0S","clearcache":"P0Y0M0DT0H10M0S","clearsessions":"P0Y0M0DT0H30M0S","viewupdates":"P0Y0M0DT0H5M0S","imageproxy":"P0Y0M0DT0H30M0S","cleanupattachments":"P0Y0M0DT12H0M0S","cleanupfiles":"P0Y0M1DT0H0M0S","unlockmembers":"P0Y0M0DT1H0M0S","leaderboard":"P0Y0M0DT6H0M0S","deletecontent":"P0Y0M1DT0H0M0S","clubrebuild":"P0Y0M0DT0H20M0S","onlineusers":"P0Y0M0DT0H15M0S","promote":"P0Y0M0DT0H5M0S","prunesearchindex":"P0Y0M1DT0H0M0S","prunesystemlogs":"P0Y0M1DT0H0M0S","automaticmoderation":"P0Y0M0DT0H10M0S","usagereporting":"P0Y0M7DT0H0M0S","userAgentStatistics":"P0Y0M0DT0H30M0S"}
{"profilesync":"P0Y0M0DT1H0M0S","updatecheck":"P0Y0M1DT0H0M0S","cleanup":"P0Y0M1DT0H0M0S","sitemapgenerator":"P0Y0M0DT0H15M0S","queue":"P0Y0M0DT0H1M0S","pop":"P0Y0M0DT0H10M0S","digest":"P0Y0M0DT0H10M0S","publish":"P0Y0M0DT0H10M0S","clearcache":"P0Y0M0DT0H10M0S","clearsessions":"P0Y0M0DT0H30M0S","viewupdates":"P0Y0M0DT0H5M0S","imageproxy":"P0Y0M0DT0H30M0S","cleanupattachments":"P0Y0M0DT12H0M0S","cleanupfiles":"P0Y0M1DT0H0M0S","unlockmembers":"P0Y0M0DT1H0M0S","leaderboard":"P0Y0M0DT6H0M0S","deletecontent":"P0Y0M1DT0H0M0S","clubrebuild":"P0Y0M0DT0H20M0S","onlineusers":"P0Y0M0DT0H15M0S","promote":"P0Y0M0DT0H5M0S","prunesearchindex":"P0Y0M1DT0H0M0S","prunesystemlogs":"P0Y0M1DT0H0M0S","automaticmoderation":"P0Y0M0DT0H10M0S","usagereporting":"P0Y0M7DT0H0M0S","userAgentStatistics":"P0Y0M0DT0H30M0S","pruneipaddresses":"P0Y0M1DT0H0M0S","clearelasticsearchtasks":"P0Y0M1DT0H0M0S"}
File diff suppressed because it is too large. Load diff
+35 -1
View File
@@ -259,9 +259,43 @@
"102046": "4.2.7",
"102047": "4.2.8",
"102048": "4.2.8",
"102049": "4.2.9",
"103000": "4.3.0 Beta 1",
"103002": "4.3.0 Beta 2",
"103003": "4.3.0 Beta 3",
"103004": "4.3.0 Beta 4",
"103005": "4.3.0"
"103005": "4.3.0",
"103006": "4.3.1",
"103007": "4.3.1",
"103008": "4.3.1",
"103009": "4.3.2",
"103010": "4.3.2",
"103011": "4.3.3",
"103012": "4.3.3",
"103013": "4.3.3",
"103014": "4.3.3",
"103015": "4.3.3",
"103016": "4.3.3",
"103017": "4.3.3",
"103018": "4.3.3",
"103019": "4.3.3",
"103020": "4.3.3",
"103021": "4.3.4",
"103022": "4.3.4",
"103023": "4.3.4",
"103024": "4.3.4",
"103025": "4.3.4",
"103026": "4.3.5 Beta 1",
"103027": "4.3.5 Beta 2",
"103028": "4.3.5",
"103029": "4.3.5",
"103030": "4.3.5",
"103031": "4.3.5",
"103032": "4.3.5",
"103033": "4.3.6 Beta 1",
"103034": "4.3.6 Beta 2",
"103035": "4.3.6",
"103036": "4.3.6",
"103037": "4.3.6",
"103038": "4.3.6"
}
@@ -0,0 +1,35 @@
<?php
/**
* @brief Google Analytics Community Enhancements
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Aug 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\extensions\core\CommunityEnhancements;
/* 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;
}
/**
* Google Analytics Community Enhancement
*/
class _GoogleAnalytics
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -0,0 +1,35 @@
<?php
/**
* @brief Community Enhancements: Mandrill integration
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 20 June 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\extensions\core\CommunityEnhancements;
/* 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;
}
/**
* Community Enhancements: Mandrill integration
*/
class _Mandrill
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -80,7 +80,7 @@ class _SpamMonitoring
// \IPS\Output::i()->error( $e->getMessage(), '2C116/2', 403, '' );
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&tab=service' ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&tab=service' ) );
}
/**
@@ -1,3 +1,37 @@
<?php
/**
* @brief Sparkpost Community Enhancement extension
* @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
* @subpackage
* @since 18 Sep 2014
* @version SVN_VERSION_NUMBER
* @deprecated 4.3
*/
namespace IPS\core\extensions\core\CommunityEnhancements;
// this file intentionally left blank
/* 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;
}
/**
* IP Address Lookup extension
*/
class _Sparkpost
{
/**
* @deprecated
*
*@return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -6,13 +6,13 @@ namespace IPS\core\extensions\core\Dashboard;
class _IpsconnectMaster
{
public function canView()
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return FALSE;
}
public function getBlock()
{
return '';
return TRUE;
}
}
@@ -39,7 +39,7 @@ class _LatestNews
*/
public function getBlock()
{
//
}
/**
@@ -59,14 +59,15 @@ class _Admin
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -49,14 +49,15 @@ class _Announcement
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -54,9 +54,10 @@ class _Clubs
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
try
{
@@ -196,7 +197,7 @@ class _Clubs
if( count( $toUpdate ) )
{
\IPS\Db::i()->update( 'core_clubs_fieldvalues', $toUpdate, array( 'club_id=?', $clubFieldValues['member_id'] ) );
\IPS\Db::i()->update( 'core_clubs_fieldvalues', $toUpdate, array( 'club_id=?', $clubFieldValues['club_id'] ) );
}
}
@@ -53,14 +53,15 @@ class _CustomField
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -48,14 +48,15 @@ class _Members
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
try
{
@@ -48,14 +48,15 @@ class _Messaging
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
try
{
@@ -54,9 +54,10 @@ class _Meta
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
$data = \IPS\Db::i()->select( '*', 'core_content_meta', array( "meta_id=? AND meta_type=?", $id1, $id3 ) )->first();
@@ -64,10 +65,12 @@ class _Meta
if ( $item->container() )
{
if ( $item->container()->can( 'attachments', $member ) )
if ( !$item->canView( $member ) )
{
return $item->canView( $member );
return FALSE;
}
return $viewOnly or $item->container()->can( 'attachments', $member );
}
else
{
@@ -48,14 +48,15 @@ class _Modcp
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
if ( $member->modPermission( 'mod_see_warn' ) )
{
@@ -54,9 +54,10 @@ class _ProfileSteps
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return FALSE;
}
@@ -48,14 +48,15 @@ class _Reports
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return $member->modPermission( 'can_view_reports' );
}
@@ -53,9 +53,10 @@ class _ReviewResponses
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
try
{
@@ -48,14 +48,15 @@ class _ShareLinks
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return FALSE;
}
@@ -48,14 +48,15 @@ class _Signatures
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -48,14 +48,15 @@ class _Staffdirectory
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -61,9 +61,10 @@ class _Widget
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
@@ -45,14 +45,14 @@ class _Promote
{
$data = \IPS\Db::i()->select( '*', 'core_social_promote', array( "promote_media != '[]' and promote_id >?", $offset ), 'promote_id', array( 0, 1 ) )->first();
$update = array();
foreach( json_decode( $data['promote_media'], TRUE ) as $location )
{
if ( $location )
{
try
{
\IPS\File::get( $oldConfiguration ?: 'core_Promote', $location )->move( $storageConfiguration );
$update[] = (string) \IPS\File::get( $oldConfiguration ?: 'core_Promote', $location )->move( $storageConfiguration );
}
catch( \Exception $e )
{
@@ -60,10 +60,14 @@ class _Promote
}
}
}
if ( $update )
{
\IPS\Db::i()->update( 'core_social_promote', array( 'promote_media' => json_encode( $update ), array( 'promote_id=?', $data['promote_id'] ) ) );
}
return $data['promote_id'];
}
/**
* Fix all URLs
*
@@ -72,14 +76,14 @@ class _Promote
*/
public function fixUrls( $offset )
{
$data = \IPS\Db::i()->select( '*', 'core_social_promote', array( "promote_media!=?", '[]' ), 'promote_id', array( 0, 1 ) )->first();
$data = \IPS\Db::i()->select( '*', 'core_social_promote', array( "promote_media!=?", '[]' ), 'promote_id', array( $offset, 1 ) )->first();
$fixed = array();
foreach( json_decode( $data['promote_media'], TRUE ) as $location )
{
if ( $new = \IPS\File::repairUrl( $location ) )
{
$fixed[] = $location;
$fixed[] = $new;
}
}
@@ -45,7 +45,13 @@ class _Reaction
{
$reaction = \IPS\Db::i()->select( '*', 'core_reactions', array(), 'reaction_id', array( $offset, 1 ) )->first();
\IPS\File::get( $oldConfiguration ?: 'core_Reaction', $reaction['reaction_icon'] )->move( $storageConfiguration );
$url = (string) \IPS\File::get( $oldConfiguration ?: 'core_Reaction', $reaction['reaction_icon'] )->move( $storageConfiguration );
if ( $url != $reaction['reaction_icon'] )
{
\IPS\Db::i()->update( 'core_reactions', array( 'reaction_icon' => $url ), array( 'reaction_id=?', $reaction['reaction_id'] ) );
unset( \IPS\Data\Store::i()->reactions );
}
}
/**
@@ -62,7 +68,7 @@ class _Reaction
return TRUE;
}
catch( \UunderflowException $e )
catch( \UnderflowException $e )
{
return FALSE;
}
@@ -48,7 +48,7 @@ class _Theme
*/
public function count()
{
return 5; // While this isn't the number of files, it's the number of steps this will take to move them, which is all it's used for
return 6; // While this isn't the number of files, it's the number of steps this will take to move them, which is all it's used for
}
/**
@@ -203,6 +203,27 @@ class _Theme
/* Trash new CSS and images */
\IPS\Theme::clearFiles( \IPS\Theme::TEMPLATES + \IPS\Theme::CSS + \IPS\Theme::IMAGES );
return TRUE;
case 5:
$settings = array();
foreach( \IPS\Application::applications() AS $app )
{
$settings = array_merge( $settings, $app->uploadSettings() );
}
foreach( $settings AS $key )
{
if ( \IPS\Settings::i()->$key )
{
try
{
\IPS\File::get( $oldConfiguration ?: 'core_Theme', \IPS\Settings::i()->$key )->move( $storageConfiguration );
}
catch( \Exception $e ) {}
}
}
throw new \UnderflowException;
default:
@@ -318,6 +339,28 @@ class _Theme
\IPS\Output::clearJsFiles();
/* All done */
return TRUE;
case 5:
$settings = array();
foreach( \IPS\Application::applications() AS $app )
{
$settings = array_merge( $settings, $app->uploadSettings() );
}
$update = array();
foreach( $settings AS $key )
{
if ( \IPS\Settings::i()->$key AND $new = \IPS\File::repairUrl( \IPS\Settings::i()->$key ) )
{
$update[ $key ] = $new;
}
}
if ( count( $update ) )
{
\IPS\Settings::i()->changeValues( $update );
}
throw new \UnderflowException;
}
}
@@ -403,6 +446,21 @@ class _Theme
}
}
}
/* Setting? */
$settings = array();
foreach( \IPS\Application::applications() AS $app )
{
$settings = array_merge( $settings, $app->uploadSettings() );
}
foreach( $settings AS $key )
{
if ( \IPS\Settings::i()->$key AND \IPS\Settings::i()->$key == (string) $file )
{
return TRUE;
}
}
/* Not found? Then must not be valid */
return FALSE;
@@ -53,7 +53,7 @@ class _Content
{
$form->add( new \IPS\Helpers\Form\Number( 'g_attach_max', $group->g_id ? $group->g_attach_max : 500000, FALSE, array( 'unlimited' => -1 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack( 'filesize_raw_k' ), 'g_attach_max' ) );
}
$form->add( new \IPS\Helpers\Form\Number( 'g_attach_per_post', $group->g_id ? $group->g_attach_per_post : 50000, FALSE, array( 'unlimited' => 0 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack( 'filesize_raw_k' ), 'g_attach_per_post' ) );
$form->add( new \IPS\Helpers\Form\Number( 'g_attach_per_post', $group->g_id ? $group->g_attach_per_post : 50000, FALSE, array( 'unlimited' => 0 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack( 'g_attach_per_post_suffix' ), 'g_attach_per_post' ) );
if( $group->g_id != \IPS\Settings::i()->guest_group )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'gbw_delete_attachments', $group->g_bitoptions['gbw_delete_attachments'], FALSE, array(), NULL, NULL, NULL, 'gbw_delete_attachments' ) );
@@ -174,11 +174,10 @@ class _GroupSettings
/* Privacy */
$form->addHeader( 'group_privacy' );
if ( \IPS\Application\Module::get( 'core', 'online', 'front' )->visible )
if( $group->g_id != \IPS\Settings::i()->guest_group )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'g_hide_online_list', !$group->g_hide_online_list, FALSE, array(), NULL, NULL, NULL, 'g_hide_online_list' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'g_hide_online_list', $group->g_hide_online_list, FALSE, array(), NULL, NULL, NULL, 'g_hide_online_list' ) );
}
$form->add( new \IPS\Helpers\Form\YesNo( 'gbw_hide_group', !$group->g_bitoptions['gbw_hide_group'], FALSE, array(), NULL, NULL, NULL, 'gbw_hide_group' ) );
if ( \IPS\Settings::i()->ignore_system_on )
@@ -286,10 +285,6 @@ class _GroupSettings
{
$group->g_search_flood = $values['g_search_flood'];
}
if ( isset( $values['g_hide_online_list'] ) )
{
$group->g_hide_online_list = !$values['g_hide_online_list'];
}
if ( isset( $values['gbw_hide_group'] ) )
{
@@ -301,6 +296,32 @@ class _GroupSettings
{
$group->g_bitoptions['gbw_cannot_be_ignored'] = !$values['can_be_ignored'];
}
/* Update existing sessions if this setting is changed */
if( isset( $values['g_hide_online_list'] ) AND $group->g_hide_online_list != (int) $values['g_hide_online_list'] )
{
/* We have to send a limit even though we want all records because otherwise the Database store does not return all columns */
foreach( \IPS\Session\Store::i()->getOnlineUsers( 0, 'desc', array( 0, 5000 ), $group->g_id, TRUE ) as $sessionData )
{
/* Set public sessions to Anonymous */
if( $values['g_hide_online_list'] == \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS AND $sessionData['login_type'] != \IPS\Session\Front::LOGIN_TYPE_INCOMPLETE )
{
$sessionData['login_type'] = \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS;
}
/* Set anonymous sessions to public */
elseif( $sessionData['login_type'] == \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS )
{
$sessionData['login_type'] = \IPS\Session\Front::LOGIN_TYPE_MEMBER;
}
\IPS\Session\Store::i()->updateSession( $sessionData );
}
}
if ( isset( $values['g_hide_online_list'] ) )
{
$group->g_hide_online_list = $values['g_hide_online_list'];
}
}
/**
@@ -340,7 +361,7 @@ class _GroupSettings
}
catch ( \Exception $e )
{
$newGroup->icon = NULL;
$newGroup->g_icon = NULL;
}
$newGroup->save();
@@ -36,8 +36,10 @@ class _GroupLimits
'exclude' => array( 'g_id', 'g_icon', 'prefix', 'suffix', 'g_promotion', 'g_bitoptions' ),
'lessIsMore' => array( 'g_search_flood', 'g_pm_flood_mins' ),
'neg1IsBest' => array( 'g_attach_max', 'g_max_bgimg_upload', 'g_max_messages', 'g_pm_perday', 'g_pm_flood_mins', 'g_max_mass_pm', 'g_rep_max_positive' ),
'zeroIsBest' => array( 'g_edit_cutoff', 'g_displayname_unit', 'g_sig_unit', 'g_mod_preview', 'g_ppd_limit', 'g_ppd_unit', 'gbw_no_status_update', 'g_max_bgimg_upload', 'gbw_disable_prefixes', 'gbw_disable_tagging', 'g_attach_per_post' ),
'zeroIsBest' => array( 'g_displayname_unit', 'g_sig_unit', 'g_mod_preview', 'g_ppd_limit', 'g_ppd_unit', 'gbw_no_status_update', 'g_max_bgimg_upload', 'gbw_disable_prefixes', 'gbw_disable_tagging' ),
'callback' => array(
'g_edit_cutoff' => array( $this, '_editCutoff' ),
'g_attach_per_post' => array( $this, '_attachMaxPerPost' ),
'g_signature_limits' => array( $this, '_signatureLimits' ),
'g_photo_max_vars' => array( $this, '_photoVars' ),
'g_dname_date' => array( $this, '_displayNameDate' ),
@@ -50,10 +52,91 @@ class _GroupLimits
'g_lock_unlock_own' => array( $this, '_perAppSettings' ),
'g_can_report' => array( $this, '_perAppSettings' ),
'g_club_allowed_nodes' => array( $this, '_clubNodes' ),
'g_create_clubs' => array( $this, '_createClub' ),
)
);
}
/**
* Cutoff for editing - only use a group's value if the group is able to edit
*
* @param array $a Group A's values
* @param array $b Group B's values
* @param string $k The key we want to get the combined value for
* @param array $member Member data
* @return mixed
*/
public function _editCutoff( $a, $b, $k, $member )
{
$cutoff = array();
if( $a['g_edit_posts'] )
{
if( $a[ $k ] == 0 )
{
return 0;
}
else
{
$cutoff[] = $a[ $k ];
}
}
if( $b['g_edit_posts'] )
{
if( $b[ $k ] == 0 )
{
return 0;
}
else
{
$cutoff[] = $b[ $k ];
}
}
return \count( $cutoff ) ? max( $cutoff ) : 0;
}
/**
* Max per-content-item attachment storage space
*
* @param array $a Group A's values
* @param array $b Group B's values
* @param string $k The key we want to get the combined value for
* @param array $member Member data
* @return mixed
*/
public function _attachMaxPerPost( $a, $b, $k, $member )
{
$maxAttachments = array();
if( $a['g_attach_max'] !== 0 )
{
if( $a[ $k ] == 0 )
{
return 0;
}
else
{
$maxAttachments[] = $a[ $k ];
}
}
if( $b['g_attach_max'] !== 0 )
{
if( $b[ $k ] == 0 )
{
return 0;
}
else
{
$maxAttachments[] = $b[ $k ];
}
}
return \count( $maxAttachments ) ? max( $maxAttachments ) : 0;
}
/**
* Per-App Settings
*
@@ -241,7 +324,8 @@ class _GroupLimits
public function _displayNameChanges( $a, $b, $k, $member )
{
$changes = $b[ $k ];
$timeFrame = $a['g_dname_date'];
/* Get the most generous date allowance */
$timeFrame = max( array( $a['g_dname_date'], $b['g_dname_date'] ) );
if( $changes == -1 OR $a[ $k ] == -1 )
{
@@ -283,9 +367,15 @@ class _GroupLimits
/* Time frame restriction */
else if( $changes )
{
{
$_compare = round( $timeFrame / $changes );
/* If there are no permitted changes allowed for group A, but there is a date set (is is default, then clear the date for the logic below */
if ( ! $a[ $k ] and $a['g_dname_date'] )
{
$a['g_dname_date'] = 0;
}
/* Existing has no time frame restriction */
if( !$a['g_dname_date'] AND $a[ $k ] )
{
@@ -382,4 +472,26 @@ class _GroupLimits
return implode( ",", $nodeTypes );
}
/**
* Available club types
*
* @param array $a Group A's values
* @param array $b Group B's values
* @param string $k The key we want to get the combined value for
* @param array $member Member data
* @return mixed
*/
public function _createClub( $a, $b, $k, $member )
{
if ( $a[$k] == '*' or $b[$k] == '*' )
{
return '*';
}
/* Merge together all available club types */
$types = array_unique( array_merge( explode( ",", $a[$k] ), explode( ",", $b[$k] ) ) );
return implode( ",", $types );
}
}
@@ -66,6 +66,8 @@ class _ErrorLogs
$table->include = array( 'log_member', 'log_error_code', 'log_error', 'log_date', 'log_ip_address' );
$table->mainColumn = 'log_date';
$table->langPrefix = 'errorlogs_';
$table->widths = array( 'log_error_code' => 10, 'log_ip_address' => 10, 'log_request_uri' => 30, 'log_date' => 10, 'log_member' => 10 );
$table->rowClasses = array( 'log_error' => array( 'ipsTable_wrap' ), 'log_request_uri' => array( 'ipsTable_wrap' ) );
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'tables', 'core', 'admin' ), 'table' );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'tables', 'core', 'admin' ), 'rows' );
@@ -90,7 +90,7 @@ class _Reports
try
{
$report = \IPS\core\Reports\Report::load( $row['rid'] );
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $report->url(), TRUE, $reort->mapped('title') );
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $report->url(), TRUE, $report->mapped('title') );
}
catch( \OutOfRangeException $e )
{
@@ -30,7 +30,7 @@ class _Members
public function hasAccess()
{
/* Check Permissions */
return \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'member_edit' );
return \IPS\Member::loggedIn()->hasAcpRestriction( "core","members" );
}
/**
@@ -32,21 +32,37 @@ class _BasicInformation extends \IPS\core\MemberACPProfile\Block
$hasPassword = FALSE;
$canChangePassword = \IPS\Login\Handler::findMethod( 'IPS\Login\Handler\Standard' );
$activeIntegrations = array();
foreach ( \IPS\Login::methods() as $method )
if ( \IPS\Member::loggedIn()->hasAcpRestriction('core', 'members', 'member_edit') )
{
if ( $method->canProcess( $this->member ) )
/* Is this an admin? */
if ( $this->member->isAdmin() AND !\IPS\Member::loggedIn()->hasAcpRestriction('core', 'members', 'member_edit_admin' ) )
{
if ( !( $method instanceof \IPS\Login\Handler\Standard ) )
$canChangePassword = FALSE;
}
if ( $canChangePassword !== FALSE )
{
foreach ( \IPS\Login::methods() as $method )
{
$activeIntegrations[] = $method->_title;
}
if ( $method->canChangePassword( $this->member ) )
{
$hasPassword = TRUE;
$canChangePassword = TRUE;
if ( $method->canProcess( $this->member ) )
{
if ( !( $method instanceof \IPS\Login\Handler\Standard ) )
{
$activeIntegrations[] = $method->_title;
}
if ( $method->canChangePassword( $this->member ) )
{
$hasPassword = TRUE;
$canChangePassword = TRUE;
}
}
}
}
}
else
{
$canChangePassword = FALSE;
}
$accountActions = array();
if ( \IPS\Member::loggedIn()->member_id != $this->member->member_id AND \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'member_login' ) AND !$this->member->isBanned() )
@@ -78,6 +94,16 @@ class _BasicInformation extends \IPS\core\MemberACPProfile\Block
);
}
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'member_export_pi' ) )
{
$accountActions[] = array(
'title' => 'member_export_pi_title',
'icon' => 'download',
'link' => \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=exportPersonalInfo&id={$this->member->member_id}" ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('member_export_pi_title') )
);
}
$activeSubscription = FALSE;
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->nexus_subs_enabled ) // I know... this should really be a hook... I won't tell if you won't
{
@@ -138,7 +138,7 @@ class _Header extends \IPS\core\MemberACPProfile\Block
}
elseif ( \IPS\Settings::i()->reputation_enabled and \IPS\Request::i()->type == 'reputation' )
{
$form->add( new \IPS\Helpers\Form\Number( 'member_reputation', $this->member->pp_reputation_points, FALSE ) );
$form->add( new \IPS\Helpers\Form\Number( 'member_reputation', $this->member->pp_reputation_points, FALSE, array( 'min' => NULL ) ) );
}
else
{
@@ -30,7 +30,7 @@ class _Locations extends \IPS\core\MemberACPProfile\LazyLoadingBlock
public function lazyOutput()
{
$mapMarkers = array();
if ( \IPS\Settings::i()->ipsgeoip and \IPS\Settings::i()->googlemaps and \IPS\Settings::i()->google_maps_api_key )
if ( \IPS\Settings::i()->ipsgeoip and \IPS\GeoLocation::enabled() )
{
foreach ( \IPS\Db::i()->select( 'DISTINCT ip_address', 'core_members_known_ip_addresses', array( 'member_id=?', $this->member->member_id ) ) as $ipAddress )
{
@@ -50,7 +50,7 @@ class _LoginMethods extends \IPS\core\MemberACPProfile\LazyLoadingBlock
{
continue;
}
if ( $option == 'status' and ( !$this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) or !\IPS\core\Statuses\Status::canCreateFromCreateMenu( $this->member ) or !\IPS\Settings::i()->profile_comments or $this->member->group['gbw_no_status_update'] ) )
if ( $option == 'status' and ( !$this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status', 'front' ) ) or !\IPS\core\Statuses\Status::canCreateFromCreateMenu( $this->member ) or !\IPS\Settings::i()->profile_comments or $this->member->group['gbw_no_status_update'] ) )
{
continue;
}
@@ -29,13 +29,23 @@ class _Main extends \IPS\core\MemberACPProfile\MainTab
*/
public function leftColumnBlocks()
{
return array(
'IPS\core\extensions\core\MemberACPProfileBlocks\BasicInformation',
'IPS\core\extensions\core\MemberACPProfileBlocks\Groups',
'IPS\core\extensions\core\MemberACPProfileBlocks\DevicesAndIPAddresses',
'IPS\core\extensions\core\MemberACPProfileBlocks\MFA',
'IPS\core\extensions\core\MemberACPProfileBlocks\OAuth'
);
$return = array();
$return[] = 'IPS\core\extensions\core\MemberACPProfileBlocks\BasicInformation';
$return[] = 'IPS\core\extensions\core\MemberACPProfileBlocks\Groups';
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'membertools_ip' ) )
{
$return[] = 'IPS\core\extensions\core\MemberACPProfileBlocks\DevicesAndIPAddresses';
}
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'member_mfa' ) )
{
$return[] = 'IPS\core\extensions\core\MemberACPProfileBlocks\MFA';
}
$return[] = 'IPS\core\extensions\core\MemberACPProfileBlocks\OAuth';
return $return;
}
/**
@@ -0,0 +1,115 @@
<?php
/**
* @brief ACP Export Personal Information
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 15 May 2018
*/
namespace IPS\core\extensions\core\MemberExportPersonalInformation;
/* 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;
}
/**
* @brief ACP Export Personal Information
*/
class _Main
{
/**
* Return data
* @param \IPS\Member $member The member
*
* @return array
*/
public function getData( \IPS\Member $member )
{
$return = array();
/* Basic Data */
$columns = array(
'name',
'email',
'joined',
'ip_address',
'timezone',
'last_visit',
'last_post',
'birthday',
'allow_admin_mails',
'member_title'
);
foreach( $columns as $col )
{
$val = NULL;
switch( $col )
{
case 'last_visit':
case 'last_post':
$val = ( ! empty( $member->$col ) ) ? \IPS\DateTime::ts( $member->$col )->rfc3339() : NULL;
break;
case 'joined':
$val = $member->joined->rfc3339();
break;
default:
$val = (string) $member->$col;
break;
}
$return['core'][ $col ] = $val;
}
/* Known IP addresses stored */
$return['known_ip_addresses'] = array_keys( $member->ipAddresses() );
/* Devices used */
$devices = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members_known_devices', array( 'member_id=? AND last_seen>?', $member->member_id, ( new \DateTime )->sub( new \DateInterval( \IPS\Member\Device::LOGIN_KEY_VALIDITY ) )->getTimestamp() ), 'last_seen DESC' ), 'IPS\Member\Device' );
foreach ( $devices as $device )
{
try
{
$log = \IPS\Db::i()->select( '*', 'core_members_known_ip_addresses', array( 'member_id=? AND device_key=?', \IPS\Member::loggedIn()->member_id, $device->device_key ), 'last_seen DESC' )->first();
}
catch ( \UnderflowException $e )
{
continue;
}
$return['known_browsers'][] = array(
'useragent' => $device->userAgent()->browser . ' ' . $device->userAgent()->browserVersion,
'last_seen' => \IPS\DateTime::ts( $log['last_seen'] )->rfc3339()
);
}
/* Accepted T&S */
foreach( \IPS\Db::i()->select( '*', 'core_member_history', array( 'log_app=? and log_member=? and log_type=?', 'core', $member->member_id, 'terms_acceptance' ) ) as $row )
{
$data = json_decode( $row['log_data'], TRUE );
if ( ! empty( $data['type'] ) )
{
$return['terms_accepted'][ $data['type'] ][] = \IPS\DateTime::ts( $row['log_date'] )->rfc3339();
}
}
/* Accepted Bulk Email */
foreach( \IPS\Db::i()->select( '*', 'core_member_history', array( 'log_app=? and log_member=? and log_type=?', 'core', $member->member_id, 'admin_mails' ) ) as $row )
{
$data = json_decode( $row['log_data'], TRUE );
$return['bulk_mail_optins'][] = array(
'enabled' => (boolean) $data['enabled'],
'date' => \IPS\DateTime::ts( $row['log_date'] )->rfc3339()
);
}
return $return;
}
}
@@ -0,0 +1,86 @@
<?php
/**
* @brief Member filter extension: Bulk mail filter
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 31 July 2018
*/
namespace IPS\core\extensions\core\MemberFilter;
/* 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;
}
/**
* @brief Member filter: Bulk mail filter
*/
class _Bulkmail
{
/**
* Determine if the filter is available in a given area
*
* @param string $area Area to check
* @return bool
*/
public function availableIn( $area )
{
return \in_array( $area, array( 'group_promotions' ) );
}
/**
* Get Setting Field
*
* @param mixed $criteria Value returned from the save() method
* @return array Array of form elements
*/
public function getSettingField( $criteria )
{
$options = array( 'any' => 'any', 'on' => 'member_filter_bulk_mail_on', 'off' => 'member_filter_bulk_mail_off' );
return array(
new \IPS\Helpers\Form\Radio( 'member_filter_bulk_mail', isset( $criteria['bulk_mail'] ) ? $criteria['bulk_mail'] : 'any', FALSE, array( 'options' => $options ) ),
);
}
/**
* Save the filter data
*
* @param array $post Form values
* @return mixed False, or an array of data to use later when filtering the members
* @throws \LogicException
*/
public function save( $post )
{
return ( isset( $post['member_filter_bulk_mail'] ) and \in_array( $post['member_filter_bulk_mail'], array( 'on', 'off' ) ) ) ? array( 'bulk_mail' => $post['member_filter_bulk_mail'] ) : FALSE;
}
/**
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
if ( isset( $data['bulk_mail'] ) )
{
switch ( $data['bulk_mail'] )
{
case 'on':
return array( "allow_admin_mails=1" );
break;
case 'off':
return array( "allow_admin_mails=0" );
break;
}
}
return NULL;
}
}
@@ -83,7 +83,7 @@ class _Content
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
@@ -92,13 +92,13 @@ class _Content
switch ( $data['content_count_operator'] )
{
case 'gt':
return array( array( "member_posts>?", (int) $data['content_count_score'] ) );
return array( "member_posts>?", (int) $data['content_count_score'] );
break;
case 'lt':
return array( array( "member_posts<?", (int) $data['content_count_score'] ) );
return array( "member_posts<?", (int) $data['content_count_score'] );
break;
case 'eq':
return array( array( "member_posts=?", (int) $data['content_count_score'] ) );
return array( "member_posts=?", (int) $data['content_count_score'] );
break;
}
}
@@ -121,7 +121,7 @@ class _Group
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
@@ -137,7 +137,7 @@ class _Group
if( count($_set) )
{
return "( member_group_id IN(" . $data['groups'] . ") OR " . implode( ' OR ', $_set ) . ' )';
return array( "( member_group_id IN(" . $data['groups'] . ") OR " . implode( ' OR ', $_set ) . ' )' );
}
}
@@ -72,11 +72,15 @@ class _Joined
{
return $post['bmf_members_joined'][3] ? array( 'days_lt' => intval( $post['bmf_members_joined'][3] ) ) : FALSE;
}
elseif( $post['bmf_members_joined'][2] == 'range' )
{
return ( empty( $post['bmf_members_joined'][0] ) OR empty( $post['bmf_members_joined'][0]['start'] ) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['bmf_members_joined'][0] ), TRUE ) );
}
}
else
{
/* Normalize objects to their array form. Bulk mailer stores options as a json array where as member export does not, so $data['range']['start'] is a DateTime object */
return ( empty($post['bmf_members_joined'][0]) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['bmf_members_joined'][0] ), TRUE ) );
return ( empty( $post['bmf_members_joined'][0] ) OR empty( $post['bmf_members_joined'][0]['start'] ) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['bmf_members_joined'][0] ), TRUE ) );
}
}
@@ -84,31 +88,56 @@ class _Joined
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
if( !empty($data['range']) AND !empty($data['range']['end']) )
{
$start = ( $data['range']['start'] ) ? new \IPS\DateTime( $data['range']['start'] ) : NULL;
$end = ( $data['range']['end'] ) ? new \IPS\DateTime( $data['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $data['range']['start'] )
{
try
{
/* Try just what is stored */
$start = new \IPS\DateTime( $data['range']['start'] );
}
catch( \Exception $e )
{
/* If there was an error, try dashes so DateTime will assume European dates. @see <a href='http://php.net/manual/en/function.strtotime.php#refsect1-function.strtotime-notes'>PHP Documentation</a> */
$start = new \IPS\DateTime( str_replace( '/', '-', $data['range']['start'] ) );
}
}
if ( $data['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $data['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $data['range']['end'] ) );
}
}
if( $start and $end )
{
return "core_members.joined BETWEEN {$start->getTimestamp()} AND {$end->getTimestamp()}";
return array( "core_members.joined BETWEEN {$start->getTimestamp()} AND {$end->getTimestamp()}" );
}
}
elseif( !empty( $data['days'] ) AND (int) $data['days'] )
{
$date = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . (int) $data['days'] . 'D' ) );
return "core_members.joined < {$date->getTimestamp()}";
return array( "core_members.joined < {$date->getTimestamp()}" );
}
elseif( !empty( $data['days_lt'] ) AND (int) $data['days_lt'] )
{
$date = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . (int) $data['days_lt'] . 'D' ) );
return "core_members.joined > {$date->getTimestamp()}";
return array( "core_members.joined > {$date->getTimestamp()}" );
}
return NULL;
@@ -136,8 +165,32 @@ class _Joined
if( !empty( $filters['range'] ) AND !empty( $filters['range']['end'] ) )
{
$start = ( $filters['range']['start'] ) ? new \IPS\DateTime( $filters['range']['start'] ) : NULL;
$end = ( $filters['range']['end'] ) ? new \IPS\DateTime( $filters['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $filters['range']['start'] )
{
try
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
catch( \Exception $e )
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
}
if ( $filters['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $filters['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $filters['range']['end'] ) );
}
}
if( $start and $end )
{
@@ -160,8 +213,32 @@ class _Joined
{
if( !empty( $filters['range'] ) AND !empty( $filters['range']['end'] ) )
{
$start = ( $filters['range']['start'] ) ? new \IPS\DateTime( $filters['range']['start'] ) : NULL;
$end = ( $filters['range']['end'] ) ? new \IPS\DateTime( $filters['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $filters['range']['start'] )
{
try
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
catch( \Exception $e )
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
}
if ( $filters['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $filters['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $filters['range']['end'] ) );
}
}
if ( $start and $end )
{
@@ -72,11 +72,15 @@ class _Lastpost
{
return $post['mf_members_last_post'][3] ? array( 'days_lt' => intval( $post['mf_members_last_post'][3] ) ) : FALSE;
}
elseif( $post['mf_members_last_post'][2] == 'range' )
{
return ( empty( $post['mf_members_last_post'][0] ) OR empty( $post['mf_members_last_post'][0]['start'] ) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['mf_members_last_post'][0] ), TRUE ) );
}
}
else
{
/* Normalize objects to their array form. Bulk mailer stores options as a json array where as member export does not, so $data['range']['start'] is a DateTime object */
return ( empty($post['mf_members_last_post'][0]) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['mf_members_last_post'][0] ), TRUE ) );
return ( empty( $post['mf_members_last_post'][0] ) OR empty( $post['mf_members_last_post'][0]['start'] ) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['mf_members_last_post'][0] ), TRUE ) );
}
}
@@ -84,31 +88,56 @@ class _Lastpost
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
if( !empty($data['range']) AND !empty($data['range']['end']) )
{
$start = ( $data['range']['start'] ) ? new \IPS\DateTime( $data['range']['start'] ) : NULL;
$end = ( $data['range']['end'] ) ? new \IPS\DateTime( $data['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $data['range']['start'] )
{
try
{
/* Try just what is stored */
$start = new \IPS\DateTime( $data['range']['start'] );
}
catch( \Exception $e )
{
/* If there was an error, try dashes so DateTime will assume European dates. @see <a href='http://php.net/manual/en/function.strtotime.php#refsect1-function.strtotime-notes'>PHP Documentation</a> */
$start = new \IPS\DateTime( str_replace( '/', '-', $data['range']['start'] ) );
}
}
if ( $data['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $data['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $data['range']['end'] ) );
}
}
if( $start and $end )
{
return "core_members.member_last_post BETWEEN {$start->getTimestamp()} AND {$end->getTimestamp()}";
return array( "core_members.member_last_post BETWEEN {$start->getTimestamp()} AND {$end->getTimestamp()}" );
}
}
elseif( !empty( $data['days'] ) AND (int) $data['days'] )
{
$date = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . (int) $data['days'] . 'D' ) );
return "( core_members.member_last_post < {$date->getTimestamp()} OR core_members.member_last_post IS NULL )";
return array( "( core_members.member_last_post < {$date->getTimestamp()} OR core_members.member_last_post IS NULL )" );
}
elseif( !empty( $data['days_lt'] ) AND (int) $data['days_lt'] )
{
$date = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . (int) $data['days_lt'] . 'D' ) );
return "( core_members.member_last_post > {$date->getTimestamp()} )";
return array( "( core_members.member_last_post > {$date->getTimestamp()} )" );
}
@@ -150,8 +179,32 @@ class _Lastpost
if( !empty( $filters['range'] ) AND !empty( $filters['range']['end'] ) )
{
$start = ( $filters['range']['start'] ) ? new \IPS\DateTime( $filters['range']['start'] ) : NULL;
$end = ( $filters['range']['end'] ) ? new \IPS\DateTime( $filters['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $filters['range']['start'] )
{
try
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
catch( \Exception $e )
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
}
if ( $filters['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $filters['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $filters['range']['end'] ) );
}
}
if( $start and $end )
{
@@ -174,8 +227,32 @@ class _Lastpost
{
if( !empty( $filters['range'] ) AND !empty( $filters['range']['end'] ) )
{
$start = ( $filters['range']['start'] ) ? new \IPS\DateTime( $filters['range']['start'] ) : NULL;
$end = ( $filters['range']['end'] ) ? new \IPS\DateTime( $filters['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $filters['range']['start'] )
{
try
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
catch( \Exception $e )
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
}
if ( $filters['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $filters['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $filters['range']['end'] ) );
}
}
if ( $start and $end )
{
@@ -72,11 +72,15 @@ class _Lastvisit
{
return $post['bmf_members_last_visit'][3] ? array( 'days_lt' => intval( $post['bmf_members_last_visit'][3] ) ) : FALSE;
}
elseif( $post['bmf_members_last_visit'][2] == 'range' )
{
return ( empty( $post['bmf_members_last_visit'][0] ) OR empty( $post['bmf_members_last_visit'][0]['start'] ) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['bmf_members_last_visit'][0] ), TRUE ) );
}
}
else
{
/* Normalize objects to their array form. Bulk mailer stores options as a json array where as member export does not, so $data['range']['start'] is a DateTime object */
return ( empty($post['bmf_members_last_visit'][0]) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['bmf_members_last_visit'][0] ), TRUE ) );
return ( empty( $post['bmf_members_last_visit'][0] ) OR empty( $post['bmf_members_last_visit'][0]['start'] ) ) ? FALSE : array( 'range' => json_decode( json_encode( $post['bmf_members_last_visit'][0] ), TRUE ) );
}
}
@@ -84,31 +88,56 @@ class _Lastvisit
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
if( !empty($data['range']) AND !empty($data['range']['end']) )
{
$start = ( $data['range']['start'] ) ? new \IPS\DateTime( $data['range']['start'] ) : NULL;
$end = ( $data['range']['end'] ) ? new \IPS\DateTime( $data['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $data['range']['start'] )
{
try
{
/* Try just what is stored */
$start = new \IPS\DateTime( $data['range']['start'] );
}
catch( \Exception $e )
{
/* If there was an error, try dashes so DateTime will assume European dates. @see <a href='http://php.net/manual/en/function.strtotime.php#refsect1-function.strtotime-notes'>PHP Documentation</a> */
$start = new \IPS\DateTime( str_replace( '/', '-', $data['range']['start'] ) );
}
}
if ( $data['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $data['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $data['range']['end'] ) );
}
}
if( $start and $end )
{
return "core_members.last_visit BETWEEN {$start->getTimestamp()} AND {$end->getTimestamp()}";
return array( "core_members.last_activity BETWEEN {$start->getTimestamp()} AND {$end->getTimestamp()}" );
}
}
elseif( !empty( $data['days'] ) AND (int) $data['days'] )
{
$date = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . (int) $data['days'] . 'D' ) );
return "core_members.last_visit < {$date->getTimestamp()}";
return array( "core_members.last_activity < {$date->getTimestamp()}" );
}
elseif( !empty( $data['days_lt'] ) AND (int) $data['days_lt'] )
{
$date = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . (int) $data['days_lt'] . 'D' ) );
return "core_members.last_visit > {$date->getTimestamp()}";
return array( "core_members.last_activity > {$date->getTimestamp()}" );
}
return NULL;
@@ -135,8 +164,32 @@ class _Lastvisit
if( !empty( $filters['range'] ) AND !empty( $filters['range']['end'] ) )
{
$start = ( $filters['range']['start'] ) ? new \IPS\DateTime( $filters['range']['start'] ) : NULL;
$end = ( $filters['range']['end'] ) ? new \IPS\DateTime( $filters['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $filters['range']['start'] )
{
try
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
catch( \Exception $e )
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
}
if ( $filters['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $filters['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $filters['range']['end'] ) );
}
}
if( $start and $end )
{
@@ -159,8 +212,32 @@ class _Lastvisit
{
if( !empty( $filters['range'] ) AND !empty( $filters['range']['end'] ) )
{
$start = ( $filters['range']['start'] ) ? new \IPS\DateTime( $filters['range']['start'] ) : NULL;
$end = ( $filters['range']['end'] ) ? new \IPS\DateTime( $filters['range']['end'] ) : NULL;
$start = NULL;
$end = NULL;
if ( $filters['range']['start'] )
{
try
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
catch( \Exception $e )
{
$start = new \IPS\DateTime( $filters['range']['start'] );
}
}
if ( $filters['range']['end'] )
{
try
{
$end = new \IPS\DateTime( $filters['range']['end'] );
}
catch( \Exception $e )
{
$end = new \IPS\DateTime( str_replace( '/', '-', $filters['range']['end'] ) );
}
}
if ( $start and $end )
{
@@ -64,14 +64,14 @@ class _Leaderboard
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
if( isset( $data['leaderboard'] ) )
{
$leaderBoardSelect = \IPS\Db::i()->select( 'leader_member_id', 'core_reputation_leaderboard_history', 'leader_position=1', NULL, NULL, NULL, NULL, \IPS\Db::SELECT_DISTINCT );
return ( $data['leaderboard'] == 'active' ) ? array( array( 'core_members.member_id IN(' . $leaderBoardSelect . ')' ) ) : array( array( 'core_members.member_id NOT IN(' . $leaderBoardSelect . ')' ) );
return ( $data['leaderboard'] == 'active' ) ? array( 'core_members.member_id IN(' . $leaderBoardSelect . ')' ) : array( 'core_members.member_id NOT IN(' . $leaderBoardSelect . ')' );
}
return NULL;
@@ -1,4 +1,31 @@
<?php
/**
* @brief Member filter extension
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 5 Apr 2017
*/
// Removed
namespace IPS\core\extensions\core\MemberFilter;
/* 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;
}
class _Linkedaccounts
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -0,0 +1,86 @@
<?php
/**
* @brief Member filter extension: Name
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 14 May 2018
*/
namespace IPS\core\extensions\core\MemberFilter;
/* 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;
}
/**
* @brief Member filter: Name
*/
class _Name
{
/**
* Determine if the filter is available in a given area
*
* @param string $area Area to check
* @return bool
*/
public function availableIn( $area )
{
return in_array( $area, array( 'bulkmail' ) );
}
/**
* Get Setting Field
*
* @param mixed $criteria Value returned from the save() method
* @return array Array of form elements
*/
public function getSettingField( $criteria )
{
$options = array( 'any' => 'mf_name_whatever', 'yes' => 'mf_name_yes', 'no' => 'mf_name_no' );
return array(
new \IPS\Helpers\Form\Radio( 'mf_name', isset( $criteria['mf_name'] ) ? $criteria['mf_name'] : 'yes', FALSE, array( 'options' => $options ) ),
);
}
/**
* Save the filter data
*
* @param array $post Form values
* @return mixed False, or an array of data to use later when filtering the members
* @throws \LogicException
*/
public function save( $post )
{
return ( isset( $post['mf_name'] ) and in_array( $post['mf_name'], array( 'yes', 'no' ) ) ) ? array( 'mf_name' => $post['mf_name'] ) : FALSE;
}
/**
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
if ( isset( $data['mf_name'] ) )
{
switch ( $data['mf_name'] )
{
case 'yes':
return array( "core_members.name <> ''" );
break;
case 'no':
return array( "core_members.name = ''" );
break;
}
}
return NULL;
}
}
@@ -83,7 +83,7 @@ class _Reputation
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
@@ -92,13 +92,13 @@ class _Reputation
switch ( $data['reputation_operator'] )
{
case 'gt':
return array( array( "pp_reputation_points>?", (int) $data['reputation_score'] ) );
return array( "pp_reputation_points>?", (int) $data['reputation_score'] );
break;
case 'lt':
return array( array( "pp_reputation_points<?", (int) $data['reputation_score'] ) );
return array( "pp_reputation_points<?", (int) $data['reputation_score'] );
break;
case 'eq':
return array( array( "pp_reputation_points=?", (int) $data['reputation_score'] ) );
return array( "pp_reputation_points=?", (int) $data['reputation_score'] );
break;
}
}
@@ -64,7 +64,7 @@ class _Twofactor
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return string|array|NULL Where clause
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
*/
public function getQueryWhereClause( $data )
{
@@ -73,10 +73,10 @@ class _Twofactor
switch ( $data['two_factor'] )
{
case 'active':
return array( array( "mfa_details IS NOT NULL AND mfa_details !=?", "[]" ) );
return array( "mfa_details IS NOT NULL AND mfa_details !=?", "[]" );
break;
case 'inactive':
return array( array( "( mfa_details IS NULL OR mfa_details =? )", "[]" ) );
return array( "( mfa_details IS NULL OR mfa_details =? )", "[]" );
break;
}
}
@@ -8,4 +8,24 @@
* @since 08 Apr 2013
*/
// Removed
namespace IPS\core\extensions\core\MemberForm;
/* 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;
}
class _BasicInformation
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -8,4 +8,24 @@
* @since 08 Apr 2013
*/
// Removed
namespace IPS\core\extensions\core\MemberForm;
/* 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;
}
class _Profile
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -1,3 +1,31 @@
<?php
/**
* @brief Admin CP Member Form
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 08 Apr 2013
*/
// Removed
namespace IPS\core\extensions\core\MemberForm;
/* 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;
}
class _Restrictions
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -1,11 +1,31 @@
<?php
/**
* @brief Admin CP Member Form: MFA
* @brief Admin CP Member Form
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 28 Sep 2016
* @since 08 Apr 2013
*/
// Removed
namespace IPS\core\extensions\core\MemberForm;
/* 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;
}
class _SecurityAnswers
{
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -260,7 +260,7 @@ class _Core
}
catch ( \Exception $e )
{
$device = $jsonValue['device'];
$device = htmlspecialchars( $jsonValue['device'], ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE );
}
if ( $jsonValue['type'] == 'new_device' )
{
@@ -382,7 +382,7 @@ class _Core
$account = NULL;
$link = NULL;
if ( $handler and isset( $jsonValue['account_id'] ) or isset( $jsonValue['account_name'] ) )
if ( $handler and ( isset( $jsonValue['account_id'] ) or isset( $jsonValue['account_name'] ) ) )
{
$account = $jsonValue['account_name'];
if ( $link = $handler->userLink( $jsonValue['account_id'], $jsonValue['account_name'] ) )
@@ -419,7 +419,7 @@ class _Core
case 'account':
$spamDefenseScore = NULL;
if ( isset( $jsonValue['spamCode'] ) )
if ( isset( $jsonValue['spamCode'] ) AND isset( $jsonValue['spamAction'] ) )
{
$spamDefenseScore = \IPS\Member::loggedIn()->language()->addToStack( 'history_spam_defense_' . $jsonValue['spamAction'], FALSE, array( 'sprintf' => array( $jsonValue['spamCode'] ) ) );
}
@@ -101,7 +101,8 @@ class _Content extends \IPS\core\MemberACPProfile\Restriction
$c = \IPS\Member::loggedIn()->language()->addToStack( 'moderation_' . $k );
if ( $changes[ $v ]['new'] != -1 )
{
$c = \IPS\Member::loggedIn()->language()->addToStack( 'history_received_warning_penalty_time', FALSE, array( 'sprintf' => array( $c, \IPS\DateTime::formatInterval( new \DateInterval( $changes[ $v ]['new'] ), 2 ) ) ) );
$interval = \IPS\DateTime::formatInterval( ( is_numeric( $changes[ $v ]['new'] ) ) ? \IPS\DateTime::create()->diff( \IPS\DateTime::ts( $changes[ $v ]['new'] ) ) : new \DateInterval( $changes[ $v ]['new'] ), 2 );
$c = \IPS\Member::loggedIn()->language()->addToStack( 'history_received_warning_penalty_time', FALSE, array( 'sprintf' => array( $c, $interval ) ) );
}
}
else
@@ -6,5 +6,13 @@ namespace IPS\core\extensions\core\MemberSync;
class _History
{
public function __construct() { }
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -6,5 +6,13 @@ namespace IPS\core\extensions\core\MemberSync;
class _ipsconnect
{
public function __construct() { }
/**
* @deprecated
*
* @return bool
*/
final public function deprecated()
{
return TRUE;
}
}
@@ -81,8 +81,8 @@ class _Reports extends \IPS\Content\Controller
/* fetch only reports for content of enabled applications */
$where .= " AND " . \IPS\Db::i()->in( 'class', array_merge( array( 'IPS\core\Messenger\Conversation', 'IPS\core\Messenger\Message' ), array_values( \IPS\Content::routedClasses( FALSE, TRUE ) ) ) );
$table = new \IPS\Helpers\Table\Content( '\IPS\core\Reports\Report', \IPS\Http\Url::internal( 'app=core&module=modcp&controller=modcp&tab=reports', NULL, 'modcp_reports' ), array( array( $where, \IPS\Db::i()->select( 'perm_id', 'core_permission_index', \IPS\Db::i()->findInSet( 'perm_view', array_merge( array( \IPS\Member::loggedIn()->member_group_id ), array_filter( explode( ',', \IPS\Member::loggedIn()->mgroup_others ) ) ) ) . " OR perm_view='*'" ) ) ) );
$table = new \IPS\Helpers\Table\Content( '\IPS\core\Reports\Report', \IPS\Http\Url::internal( 'app=core&module=modcp&controller=modcp&tab=reports', NULL, 'modcp_reports' ), array( array( $where, \IPS\Db::i()->select( 'perm_id', 'core_permission_index', \IPS\Db::i()->findInSet( 'perm_view', \IPS\Member::loggedIn()->permissionArray() ) . " OR perm_view='*'" ) ) ) );
$table->sortBy = $table->sortBy ?: 'first_report_date';
$table->sortDirection = 'desc';
@@ -29,7 +29,7 @@ class _Warnings
*/
public function getTab()
{
if ( ! \IPS\Member::loggedIn()->modPermission('mod_see_warn') )
if ( ! \IPS\Member::loggedIn()->modPermission('mod_see_warn') OR ! \IPS\Settings::i()->warn_on )
{
return null;
}
@@ -101,9 +101,17 @@ class _Content
throw new \OutOfRangeException;
}
/* If the content item is queued for deletion, add the query string parameter so we can see it */
$url = $notification->item->url();
if( $notification->item->hidden() == -2 )
{
$url = $url->setQueryString( 'showDeleted', 1 );
}
return array(
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__new_content', FALSE, array( 'sprintf' => array( $item->author()->name, mb_strtolower( $item->indefiniteArticle() ), $item->searchIndexContainerClass()->_title, $item->mapped('title') ) ) ),
'url' => $notification->item->url(),
'url' => $url,
'content' => $notification->item->content(),
'author' => $notification->item->author(),
'unread' => (bool) ( $item->unread() )
@@ -263,6 +271,14 @@ class _Content
}
$comment = $commentClass::loadAndCheckPerms( $notification->item_sub_id );
/* If the comment is in the deletion queue, add the showDeleted=1 parameter otherwise it just won't show up */
$url = $comment->url('find');
if( $comment->hidden() == -2 )
{
$url = $url->setQueryString( 'showDeleted', 1 );
}
/* Unread? */
$unread = false;
@@ -273,7 +289,7 @@ class _Content
return array(
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__new_comment', FALSE, array( 'pluralize' => array( count( $commenters ) ), 'sprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $names ), $item->mapped('title') ) ) ),
'url' => $comment->url('find'),
'url' => $url,
'content' => $comment->content(),
'author' => $comment->author(),
'unread' => $unread,
@@ -173,6 +173,17 @@ class _Core
$src = $image->getAttribute('src');
\IPS\Output::i()->parseFileObjectUrls( $src );
$imageProperties = @getimagesize( $src );
/* getimagesize failed so let's try to use getimagesizefromstring */
if( !$imageProperties )
{
try
{
$image = \IPS\Http\Url::external( $src )->request()->get();
$imageProperties = getimagesizefromstring( $image->content );
}
catch ( \IPS\Http\Request\Exception $e ) {}
}
}
if( is_array( $imageProperties ) AND count( $imageProperties ) )
@@ -300,11 +311,11 @@ class _Core
if ( $newPhoto->file )
{
$member->logHistory( 'core', 'photo', array( 'coverphoto' => 'new' ) );
$member->logHistory( 'core', 'coverphoto', array( 'action' => 'new' ) );
}
else
{
$member->logHistory( 'core', 'photo', array( 'coverphoto' => 'remove' ) );
$member->logHistory( 'core', 'coverphoto', array( 'action' => 'remove' ) );
}
}
@@ -341,7 +352,7 @@ class _Core
{
return \IPS\Login\Handler::load( $item )->canProcess( static::$_member );
}
catch ( \OutOfRangeExcetpion $e )
catch ( \OutOfRangeException $e )
{
return TRUE;
}
@@ -683,7 +694,24 @@ class _Core
}
}, NULL, NULL, 'member_photo_upload' ) );
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'allowedMimes' => 'image/*', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), NULL, NULL, NULL, 'member_photo_url' ) );
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'allowedMimes' => 'image/*', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), function( $val ) use ( $member ){
if ( $val instanceof \IPS\Http\Url )
{
try
{
$image = \IPS\Image::create( (string) $val->request()->get() );
}
catch ( \InvalidArgumentException $e )
{
throw new \DomainException('member_photo_bad_url');
}
if( $image->isAnimatedGif and !$member->group['g_upload_animated_photos'] )
{
throw new \DomainException('member_photo_upload_no_animated');
}
}
}, NULL, NULL, 'member_photo_url' ) );
}
foreach ( $extra as $element )
@@ -88,9 +88,18 @@ class _Bulkmail
$content = str_replace( $k, '*|' . str_replace( array( '{', '}' ), '', $k ) . '|*', $content );
}
}
/* Format content */
$content = \IPS\Email::staticParseTextForEmail( $content, \IPS\Lang::load( \IPS\Lang::defaultLanguage() ) );
foreach( array_keys( \IPS\core\BulkMail\Bulkmailer::getTags() ) as $k )
{
$content = str_replace( '%7B' . mb_substr( $k, 1, -1 ) . '%7D', '*|' . mb_substr( $k, 1, -1 ) . '|*', $content );
$content = str_replace( '*%7' . mb_substr( $k, 1, -1 ) . '%7C*', '*|' . mb_substr( $k, 1, -1 ) . '|*', $content );
}
/* Send it */
$email = \IPS\Email::buildFromContent( $mail->subject, \IPS\Email::staticParseTextForEmail( $content, \IPS\Lang::load( \IPS\Lang::defaultLanguage() ) ), NULL, \IPS\Email::TYPE_BULK )
$email = \IPS\Email::buildFromContent( $mail->subject, $content, NULL, \IPS\Email::TYPE_BULK )
->setUnsubscribe( 'core', 'unsubscribeBulk' );
$sent = 0;
foreach ( $recipients as $languageId => $_recipients )
@@ -116,11 +116,14 @@ class _DeleteOrMoveContent
if ( isset( $data['moveTo'] ) )
{
$moveTo = $classname::load( $data['moveTo'] );
$text = \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_move_content', FALSE, array( 'htmlsprintf' => array( "<a href='{$node->url()}' target='_blank'>{$node->_title}</a>", "<a href='{$moveTo->url()}' target='_blank'>" . strip_tags( $moveTo->_title ) . "</a>" ) ) );
$link1 = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $node->url(), TRUE, $node->_title, FALSE );
$link2 = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $moveTo->url(), TRUE, $moveTo->_title, FALSE );
$text = \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_move_content', FALSE, array( 'htmlsprintf' => array( $link1, $link2 ) ) );
}
else
{
$text = \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_deleting', FALSE, array( 'htmlsprintf' => array( "<a href='{$node->url()}' target='_blank'>{$node->_title}</a>" ) ) );
$link = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $node->url(), TRUE, $node->_title, FALSE );
$text = \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_deleting', FALSE, array( 'htmlsprintf' => array( $link ) ) );
}
return array( 'text' => $text, 'complete' => $data['originalCount'] ? ( round( 100 / $data['originalCount'] * $offset, 2 ) ) : 100 );
@@ -89,7 +89,7 @@ class _Follow
$complete = 100;
}
$title = strip_tags( ( $item instanceof \IPS\Content\Comment ) ? $item->item()->mapped('title') : $item->mapped('title') );
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_follow', FALSE, array( 'htmlsprintf' => array( "<a href='{$item->url()}' target='_blank'>{$title}</a>" ) ) ), 'complete' => $complete );
$title = ( $item instanceof \IPS\Content\Comment ) ? $item->item()->mapped('title') : $item->mapped('title');
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_follow', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $item->url(), TRUE, $title, FALSE ) ) ) ), 'complete' => $complete );
}
}
@@ -0,0 +1,141 @@
<?php
/**
* @brief Background Task
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 21 Aug 2018
*/
namespace IPS\core\extensions\core\Queue;
/* 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;
}
/**
* Background Task
*/
class _IndexSingleItem
{
/**
* Parse data before queuing
*
* @param array $data
* @return array
*/
public function preQueueData( $data )
{
$classname = $data['class'];
\IPS\Log::debug( "Getting preQueueData for {$classname}", 'index_single_item' );
if ( \in_array( 'IPS\Content\Comment', class_parents( $classname ) ) )
{
$where = array( $classname::$databasePrefix . $classname::$databaseColumnMap['item'] . '=?', $data['id'] );
}
else
{
/* Just in case an item slips in here */
$where = array( $classname::$databasePrefix . $classname::$databaseColumnId . '=?', $data['id'] );
}
$data['count'] = \IPS\Db::i()->select( 'COUNT(*)', $classname::$databaseTable, $where )->first();
$data['indexed'] = 0;
return $data;
}
/**
* Run Background Task
*
* @param mixed $data Data as it was passed to \IPS\Task::queue()
* @param int $offset Offset
* @return int New offset
* @throws \IPS\Task\Queue\OutOfRangeException Indicates offset doesn't exist and thus task is complete
*/
public function run( $data, $offset )
{
$classname = $data['class'];
if ( !is_subclass_of( $classname, 'IPS\Content\Searchable' ) )
{
throw new \IPS\Task\Queue\OutOfRangeException;
}
if ( \in_array( 'IPS\Content\Comment', class_parents( $classname ) ) )
{
$where = array( $classname::$databasePrefix . $classname::$databaseColumnMap['item'] . '=?', $data['id'] );
}
else
{
$where = array( $classname::$databasePrefix . $classname::$databaseColumnId . '=?', $data['id'] );
}
$done = 0;
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', $classname::$databaseTable, $where, $classname::$databasePrefix . $classname::$databaseColumnId . ' ASC', array( $offset, 50 ) ), $classname ) AS $object )
{
try
{
if ( !$object->isFutureDate() )
{
\IPS\Content\Search\Index::i()->index( $object );
}
}
catch( \Exception $e )
{
\IPS\Log::log( $e, 'index_single_item' );
}
catch( \Throwable $e )
{
\IPS\Log::log( $e, 'index_single_item' );
}
$done++;
}
if ( !$done )
{
throw new \IPS\Task\Queue\OutOfRangeException;
}
return $offset + $done;
}
/**
* Get Progress
*
* @param mixed $data Data as it was passed to \IPS\Task::queue()
* @param int $offset Offset
* @return array( 'text' => 'Doing something...', 'complete' => 50 ) Text explaining task and percentage complete
* @throws \OutOfRangeException Indicates offset doesn't exist and thus task is complete
*/
public function getProgress( $data, $offset )
{
$class = $data['class'];
$exploded = explode( '\\', $class );
if ( !class_exists( $class ) or !\IPS\Application::appIsEnabled( $exploded[1] ) )
{
throw new \OutOfRangeException;
}
if ( \in_array( 'IPS\Content\Review', class_parents( $class ) ) )
{
$lang = \IPS\Member::loggedIn()->language()->addToStack('reindexing_single_item_reviews', FALSE, array( 'sprintf' => array( $data['url'], $data['title'] ) ) );
}
elseif ( \in_array( 'IPS\Content\Comment', class_parents( $class ) ) )
{
$lang = \IPS\Member::loggedIn()->language()->addToStack('reindexing_single_item_comments', FALSE, array( 'sprintf' => array( $data['url'], $data['title'] ) ) );
}
else
{
$lang = \IPS\Member::loggedIn()->language()->addToStack('reindexing_single_item', FALSE, array( 'sprintf' => array( $data['url'], $data['title'] ) ) );
}
return array( 'text' => $lang, 'complete' => $data['count'] ? ( round( 100 / $data['count'] * $data['indexed'], 2 ) ) : 100 );
}
}
@@ -30,6 +30,14 @@ class _InstallLanguage
*/
public function preQueueData( $data )
{
/* Get count...this is an estimate but is good enough for the progress bar */
$data['originalCount'] = \IPS\Db::i()->select( 'COUNT(DISTINCT(word_key))', 'core_sys_lang_words', array( 'word_app=?', $data['application'] ) )->first();
if ( !$data['originalCount'] )
{
return NULL;
}
return $data;
}
@@ -43,50 +51,20 @@ class _InstallLanguage
*/
public function run( $data, $offset )
{
$offset = intval( $offset );
if( \IPS\Application::appIsEnabled( $data['application'] ) AND file_exists( \IPS\ROOT_PATH . "/applications/{$data['application']}/data/lang.xml" ) )
{
/* Open XML file */
$xml = new \IPS\Xml\XMLReader;
$xml->open( \IPS\ROOT_PATH . "/applications/{$data['application']}/data/lang.xml" );
$xml->read();
$rowsInserted = \IPS\Application::load( $data['application'] )->installLanguages( $offset, 500 );
/* Get the version */
$xml->read();
$xml->read();
$version = $xml->getAttribute('version');
$inserts = array();
/* Start looping through each word */
while ( $xml->read() )
/* If we didn't insert any, then we're done */
if( $rowsInserted )
{
if( $xml->name != 'word' OR $xml->nodeType != \XMLReader::ELEMENT )
{
continue;
}
$key = $xml->getAttribute('key');
$value = $xml->readString();
$inserts[] = array(
'word_app' => $data['application'],
'word_key' => $key,
'lang_id' => $data['language_id'],
'word_default' => $value,
'word_default_version' => $version,
'word_js' => (int) $xml->getAttribute('js'),
'word_export' => 1,
);
$xml->next();
return $rowsInserted + $offset;
}
}
\IPS\Db::i()->insert( 'core_sys_lang_words', $inserts, TRUE );
throw new \IPS\Task\Queue\OutOfRangeException;
}
else
{
/* Application doesn't exist anymore */
throw new \IPS\Task\Queue\OutOfRangeException;
}
throw new \IPS\Task\Queue\OutOfRangeException;
}
/**
@@ -99,7 +77,7 @@ class _InstallLanguage
*/
public function getProgress( $data, $offset )
{
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack( 'backgroundQueue_importing_english', FALSE, array( 'sprintf' => \IPS\Application::load( $data['application'] )->_title ) ), 'complete' => NULL );
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack( 'backgroundQueue_importing_english', FALSE, array( 'sprintf' => \IPS\Application::load( $data['application'] )->_title ) ), 'complete' => $data['originalCount'] ? ( round( 100 / $data['originalCount'] * $offset, 2 ) ) : 100 );
}
/**
@@ -110,8 +88,10 @@ class _InstallLanguage
*/
public function postComplete( $data )
{
$data = json_decode($data['data'], TRUE);
\IPS\Db::i()->insert( 'core_sys_lang_words', \IPS\Db::i()->select( "NULL AS word_id, {$data['language_id']} AS lang_id, word_app, word_plugin, word_theme, word_key, word_custom, word_default, word_default_version, word_custom_version, word_js, word_export", 'core_sys_lang_words', array( "word_export=? AND word_app=? AND lang_id=?", 0, $data['application'], \IPS\Lang::defaultLanguage() ) ) );
$data = json_decode( $data['data'], TRUE );
\IPS\Db::i()->query( "REPLACE INTO " . \IPS\Db::i()->prefix . "core_sys_lang_words (lang_id, word_app, word_plugin, word_theme, word_key, word_custom, word_default, word_default_version, word_custom_version, word_js, word_export ) SELECT {$data['language_id']} AS lang_id, word_app, word_plugin, word_theme, word_key, word_custom, word_default, word_default_version, word_custom_version, word_js, 0 FROM " . \IPS\Db::i()->prefix . "core_sys_lang_words WHERE word_export=0 AND word_app='{$data['application']}' AND lang_id=" . \IPS\Lang::defaultLanguage() );
unset( \IPS\Data\Store::i()->languages );
}
}
@@ -76,66 +76,76 @@ class _MemberContent
}
$select = \IPS\Db::i()->select( '*', $classname::$databaseTable, static::_getWhere( $data ), $classname::$databasePrefix.$classname::$databaseColumnId, array( 0, 100 ) );
if ( count( $select ) )
{
foreach ( new \IPS\Patterns\ActiveRecordIterator( $select, $classname ) as $item )
{
/* If this is the first comment on an item where a first comment is required (e.g. posts) do nothing, as when we get to the item, that will handle it */
if ( $item instanceof \IPS\Content\Comment )
{
$itemClass = $item::$itemClass;
if ( $itemClass::$firstCommentRequired and $item->isFirst() )
{
continue;
}
}
/* Do the action... */
try
{
switch ( $data['action'] )
{
case 'hide':
$item->hide( isset( $data['initiated_by_member_id'] ) ? \IPS\Member::load( $data['initiated_by_member_id'] ) : NULL );
break;
case 'delete':
$item->delete( isset( $data['initiated_by_member_id'] ) ? \IPS\Member::load( $data['initiated_by_member_id'] ) : NULL );
break;
case 'merge':
$member = \IPS\Member::load( $data['merge_with_id'] );
if ( ! $data['merge_with_id'] and $data['merge_with_name'] )
{
$member->name = $data['merge_with_name'];
}
$item->changeAuthor( $member );
break;
}
}
catch( \OutOfRangeException $e )
{
}
catch( \ErrorException $e )
{
}
}
if( $offset + 100 >= $data['originalCount'] )
foreach ( new \IPS\Patterns\ActiveRecordIterator( $select, $classname ) as $item )
{
/* If this is the first comment on an item where a first comment is required (e.g. posts) do nothing, as when we get to the item, that will handle it */
if ( $item instanceof \IPS\Content\Comment )
{
throw new \IPS\Task\Queue\OutOfRangeException;
$itemClass = $item::$itemClass;
if ( $itemClass::$firstCommentRequired and $item->isFirst() )
{
/* ... but we want to update the IP address of this post */
if ( $data['action'] === 'merge' and empty( $data['merge_with_id'] ) )
{
try
{
$item->changeIpAddress( '' );
$item->changeAuthor( new \IPS\Member );
}
catch( \OutOfRangeException $e ) {}
}
continue;
}
}
return ( $offset + 100 );
/* Do the action... */
try
{
switch ( $data['action'] )
{
case 'hide':
$item->hide( isset( $data['initiated_by_member_id'] ) ? \IPS\Member::load( $data['initiated_by_member_id'] ) : NULL );
break;
case 'delete':
$item->delete( isset( $data['initiated_by_member_id'] ) ? \IPS\Member::load( $data['initiated_by_member_id'] ) : NULL );
break;
case 'merge':
$member = \IPS\Member::load( $data['merge_with_id'] );
if ( ! $data['merge_with_id'] and $data['merge_with_name'] )
{
$member->name = $data['merge_with_name'];
}
$item->changeAuthor( $member );
if ( ! $data['merge_with_id'] )
{
$item->changeIpAddress( '' );
}
break;
}
}
catch( \OutOfRangeException $e )
{
}
catch( \ErrorException $e )
{
}
}
else
if( $offset + 100 >= $data['originalCount'] )
{
throw new \IPS\Task\Queue\OutOfRangeException;
}
return ( $offset + 100 );
}
/**
@@ -158,14 +168,15 @@ class _MemberContent
$member = \IPS\Member::load( $data['member_id'] );
if ( $member->member_id )
{
$member = $member->link();
/* htmlsprintf is safe here because $member->link() uses a template */
$sprintf = array( 'htmlsprintf' => array( $member->link(), \IPS\Member::loggedIn()->language()->addToStack( $classname::$title . '_pl_lc' ) ) );
}
else
{
$member = $data['name'];
$sprintf = array( 'sprintf' => array( $data['name'], \IPS\Member::loggedIn()->language()->addToStack( $classname::$title . '_pl_lc' ) ) );
}
$text = \IPS\Member::loggedIn()->language()->addToStack( 'backgroundQueue_membercontent_' . $data['action'], FALSE, array( 'htmlsprintf' => array( $member, \IPS\Member::loggedIn()->language()->addToStack( $classname::$title . '_pl_lc' ) ) ) );
$text = \IPS\Member::loggedIn()->language()->addToStack( 'backgroundQueue_membercontent_' . $data['action'], FALSE, $sprintf );
return array( 'text' => $text, 'complete' => $data['originalCount'] ? ( round( 100 / $data['originalCount'] * $offset, 2 ) ) : 100 );
}
@@ -44,6 +44,12 @@ class _MoveMembers
return null;
}
/* Skip this task if we're trying to move them to the same group */
if( isset( $data['oldGroup'] ) AND $data['oldGroup'] AND $data['oldGroup'] === $data['group'] )
{
return NULL;
}
return $data;
}
@@ -61,7 +61,10 @@ class _RebuildSearchIndex
if( \IPS\Settings::i()->search_method == 'mysql' and \IPS\Settings::i()->search_index_timeframe )
{
$where[] = array( $classname::$databasePrefix . $classname::$databaseColumnMap['date'] . '> ?', \IPS\DateTime::ts( time() - ( 86400 * \IPS\Settings::i()->search_index_timeframe ) )->getTimestamp() );
if( isset( $classname::$databaseColumnMap['date'] ) )
{
$where[] = array( $classname::$databasePrefix . $classname::$databaseColumnMap['date'] . '> ?', \IPS\DateTime::ts( time() - ( 86400 * \IPS\Settings::i()->search_index_timeframe ) )->getTimestamp() );
}
}
return array( 'where' => $where, 'joins' => $joins );
@@ -120,6 +120,10 @@ class _RecountStarRatings
{
$class = $data['class'];
$exploded = explode( '\\', $class );
if ( !class_exists( $class ) or !\IPS\Application::appIsEnabled( $exploded[1] ) )
{
throw new \OutOfRangeException;
}
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack('rebuilding_starratings', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $class::$title, FALSE, array( 'strtolower' => TRUE ) ) ) ) ), 'complete' => $data['count'] ? ( round( 100 / $data['count'] * $offset, 2 ) ) : 100 );
}
@@ -0,0 +1,106 @@
<?php
/**
* @brief Background Task: Unsub members
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 13 June 2018
*/
namespace IPS\core\extensions\core\Queue;
/* 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;
}
/**
* Background Task: Unsub members
*/
class _UnsubMembers
{
/**
* Parse data before queuing
*
* @param array $data
* @return array
*/
public function preQueueData( $data )
{
$select = \IPS\Db::i()->select( 'core_members.*', 'core_members', $data['where'], 'member_id ASC', array(), NULL, NULL, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS )
->join( 'core_pfields_content', 'core_members.member_id=core_pfields_content.member_id' )
->join( array( 'core_validating', 'v' ), 'v.member_id=core_members.member_id')
->join( array( 'core_admin_permission_rows', 'm' ), "m.row_id=core_members.member_id AND m.row_id_type='member'" )
->join( array( 'core_admin_permission_rows', 'g' ), array( 'g.row_id', \IPS\Db::i()->select( 'row_id', array( 'core_admin_permission_rows', 'sub' ), array( "((sub.row_id=core_members.member_group_id OR FIND_IN_SET( sub.row_id, core_members.mgroup_others ) ) AND sub.row_id_type='group') AND g.row_id_type='group'" ), NULL, array( 0, 1 ) ) ) );
$data['originalCount'] = $select->count( TRUE );
if( $data['originalCount'] == 0 )
{
return null;
}
return $data;
}
/**
* Run Background Task
*
* @param mixed $data Data as it was passed to \IPS\Task::queue()
* @param int $offset Offset
* @return int New offset
* @throws \IPS\Task\Queue\OutOfRangeException Indicates offset doesn't exist and thus task is complete
*/
public function run( $data, $offset )
{
$perCycle = 1000;
$select = \IPS\Db::i()->select( 'core_members.*', 'core_members', $data['where'], 'member_id ASC', array( 0, $perCycle ), NULL, NULL, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS )
->join( 'core_pfields_content', 'core_members.member_id=core_pfields_content.member_id' )
->join( array( 'core_validating', 'v' ), 'v.member_id=core_members.member_id')
->join( array( 'core_admin_permission_rows', 'm' ), "m.row_id=core_members.member_id AND m.row_id_type='member'" )
->join( array( 'core_admin_permission_rows', 'g' ), array( 'g.row_id', \IPS\Db::i()->select( 'row_id', array( 'core_admin_permission_rows', 'sub' ), array( "((sub.row_id=core_members.member_group_id OR FIND_IN_SET( sub.row_id, core_members.mgroup_others ) ) AND sub.row_id_type='group') AND g.row_id_type='group'" ), NULL, array( 0, 1 ) ) ) );
$total = $select->count( TRUE );
if ( !$select->count() or $offset > $data['originalCount'] )
{
throw new \IPS\Task\Queue\OutOfRangeException;
}
foreach( $select AS $row )
{
try
{
$member = \IPS\Member::constructFromData( $row );
$member->allow_admin_mails = 0;
$member->save();
}
catch( \Exception $e ) {}
$offset++;
}
return $offset;
}
/**
* Get Progress
*
* @param mixed $data Data as it was passed to \IPS\Task::queue()
* @param int $offset Offset
* @return array( 'text' => 'Doing something...', 'complete' => 50 ) Text explaining task and percentage complete
* @throws \OutOfRangeException Indicates offset doesn't exist and thus task is complete
*/
public function getProgress( $data, $offset )
{
$text = \IPS\Member::loggedIn()->language()->addToStack('unsubscribing_members', FALSE, array() );
return array( 'text' => $text, 'complete' => $data['originalCount'] ? ( round( 100 / $data['originalCount'] * $offset, 2 ) ) : 100 );
}
}
@@ -75,6 +75,6 @@ class _WarnNotifications
$numberofFollowers = intval( $warning->notificationsCount( $warning->getModerators() ) );
$complete = $numberofFollowers ? ( round( 100 / $numberofFollowers * $offset, 2 ) ) : 100;
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_follow', FALSE, array( 'htmlsprintf' => array( "<a href='{$warning->url()}' target='_blank'>" . strip_tags( $warning->mapped('title') ) . "</a>" ) ) ), 'complete' => $complete );
return array( 'text' => \IPS\Member::loggedIn()->language()->addToStack('backgroundQueue_follow', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $warning->url(), TRUE, $warning->mapped('title'), FALSE ) ) ) ), 'complete' => $complete );
}
}
@@ -221,10 +221,15 @@ class _Content extends \IPS\Content\ExtensionGenerator
{
$exploded = explode( '_', $filename );
$block = (int) array_pop( $exploded );
$totalLimit = isset( $settings["sitemap_{$class::$title}_count"] ) AND $settings["sitemap_{$class::$title}_count"] ? $settings["sitemap_{$class::$title}_count"] : self::RECOMMENDED_ITEM_LIMIT;
$totalLimit = ( isset( $settings["sitemap_{$class::$title}_count"] ) AND $settings["sitemap_{$class::$title}_count"] ) ? $settings["sitemap_{$class::$title}_count"] : self::RECOMMENDED_ITEM_LIMIT;
$offset = ( $block - 1 ) * \IPS\Sitemap::MAX_PER_FILE;
$limit = \IPS\Sitemap::MAX_PER_FILE;
if ( ! $totalLimit )
{
return NULL;
}
if ( $totalLimit > -1 and ( $offset + $limit ) > $totalLimit )
{
$limit = $totalLimit - $offset;
@@ -253,6 +258,8 @@ class _Content extends \IPS\Content\ExtensionGenerator
{
if( !$item->canView( new \IPS\Member ) )
{
/* Update the last ID, so if we get 500 results that cannot be viewed, the last ID updates for the next batch */
$lastId = $item->$idColumn;
continue;
}
@@ -45,6 +45,24 @@ class _Profiles
);
}
/**
* Save settings for ACP configuration
*
* @param array $values Values
* @return void
*/
public function saveSettings( $values )
{
if ( $values['sitemap_configuration_info'] )
{
\IPS\Settings::i()->changeValues( array( 'sitemap_profiles_count' => $this->recommendedSettings['sitemap_profiles_count'], 'sitemap_profiles_content' => $this->recommendedSettings['sitemap_profiles_content'], 'sitemap_profiles_priority' => $this->recommendedSettings['sitemap_profiles_priority'] ) );
}
else
{
\IPS\Settings::i()->changeValues( array( 'sitemap_profiles_count' => $values['sitemap_profiles_count'], 'sitemap_profiles_content' => $values['sitemap_profiles_content'], 'sitemap_profiles_priority' => $values['sitemap_profiles_priority'] ) );
}
}
/**
* Get the sitemap filename(s)
*
@@ -133,7 +133,7 @@ class _ClubMembership extends \IPS\nexus\Invoice\Item\Purchase
/**
* URL
*
* @return |IPS\Http\Url|NULL
* @return \IPS\Http\Url|NULL
*/
public function url()
{
@@ -150,7 +150,7 @@ class _ClubMembership extends \IPS\nexus\Invoice\Item\Purchase
/**
* ACP URL
*
* @return |IPS\Http\Url|NULL
* @return \IPS\Http\Url|NULL
*/
public function acpUrl()
{
@@ -291,7 +291,7 @@ class _ClubMembership extends \IPS\nexus\Invoice\Item\Purchase
/**
* Warning to display to admin when cancelling a purchase
*
* @param \IPS\nexus\Invoice $invoice The invoice
* @param \IPS\nexus\Purchase $purchase The Purchase
* @return string
*/
public static function onCancelWarning( \IPS\nexus\Purchase $purchase )
@@ -420,7 +420,7 @@ class _ClubMembership extends \IPS\nexus\Invoice\Item\Purchase
*
* @param array $values Values from form
* @param \IPS\nexus\Invoice $invoice The invoice
* @return \IPS\nexus\extensions\nexus\Item\MiscellaneousCharge
* @return \IPS\nexus\extensions\nexus\Item\ClubMembership
*/
public static function createFromForm( array $values, \IPS\nexus\Invoice $invoice )
{
@@ -442,9 +442,9 @@ class _ClubMembership extends \IPS\nexus\Invoice\Item\Purchase
$item->renewalTerm = $club->renewalTerm( $fee->currency );
$item->payTo = $club->owner;
$item->commission = \IPS\Settings::i()->clubs_paid_commission;
if ( $fees = json_decode( \IPS\Settings::i()->clubs_paid_transfee, TRUE ) and isset( $fees[ $price->currency ] ) )
if ( $fees = \IPS\Settings::i()->clubs_paid_transfee and isset( $fees[ $fee->currency ] ) )
{
$item->fee = new \IPS\nexus\Money( $fees[ $price->currency ]['amount'], $fee->currency );
$item->fee = new \IPS\nexus\Money( $fees[ $fee->currency ]['amount'], $fee->currency );
}
return $item;
@@ -1,6 +1,75 @@
CKEditor 4 Changelog
====================
## CKEditor 4.10
New Features:
* [#1751](https://github.com/ckeditor/ckeditor-dev/issues/1751): Introduced the **Autocomplete** feature that consists of the following plugins:
* [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) &ndash; Provides contextual completion feature for custom text matches based on user input.
* [Text Watcher](https://ckeditor.com/cke4/addon/textWatcher) &ndash; Checks whether an editor's text change matches the chosen criteria.
* [Text Match](https://ckeditor.com/cke4/addon/textMatch) &ndash; Allows to search [`CKEDITOR.dom.range`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dom_range.html) for matching text.
* [#1703](https://github.com/ckeditor/ckeditor-dev/issues/1703): Introduced the [Mentions](https://ckeditor.com/cke4/addon/mentions) plugin providing smart completion feature for custom text matches based on user input starting with a chosen marker character.
* [#1746](https://github.com/ckeditor/ckeditor-dev/issues/1703): Introduced the [Emoji](https://ckeditor.com/cke4/addon/emoji) plugin providing completion feature for emoji ideograms.
* [#1761](https://github.com/ckeditor/ckeditor-dev/issues/1761): The [Auto Link](https://ckeditor.com/cke4/addon/autolink) plugin now supports email links.
Fixed Issues:
* [#1458](https://github.com/ckeditor/ckeditor-dev/issues/1458): [Edge] Fixed: After blurring the editor it takes 2 clicks to focus a widget.
* [#1034](https://github.com/ckeditor/ckeditor-dev/issues/1034): Fixed: JAWS leaves forms mode after pressing the <kbd>Enter</kbd> key in an inline editor instance.
* [#1748](https://github.com/ckeditor/ckeditor-dev/pull/1748): Fixed: Missing [`CKEDITOR.dialog.definition.onHide`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dialog_definition.html#property-onHide) API documentation. Thanks to [sunnyone](https://github.com/sunnyone)!
* [#1321](https://github.com/ckeditor/ckeditor-dev/issues/1321): Ideographic space character (`\u3000`) is lost when pasting text.
* [#1776](https://github.com/ckeditor/ckeditor-dev/issues/1776): Empty caption placeholder of the [Image Base](https://ckeditor.com/cke4/addon/imagebase) plugin is not hidden when blurred.
* [#1592](https://github.com/ckeditor/ckeditor-dev/issues/1592): The [Image Base](https://ckeditor.com/cke4/addon/imagebase) plugin caption is not visible after paste.
* [#620](https://github.com/ckeditor/ckeditor-dev/issues/620): Fixed: The [`config.forcePasteAsPlainText`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-forcePasteAsPlainText) option is not respected in internal and cross-editor pasting.
* [#1467](https://github.com/ckeditor/ckeditor-dev/issues/1467): Fixed: The resizing cursor of the [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin appearing in the middle of a merged cell.
API Changes:
* [#850](https://github.com/ckeditor/ckeditor-dev/issues/850): Backward incompatibility: Replaced the `replace` dialog from the [Find / Replace](https://ckeditor.com/cke4/addon/find) plugin with a `tabId` option in the `find` command.
* [#1582](https://github.com/ckeditor/ckeditor-dev/issues/1582): The [`CKEDITOR.editor.addCommand()`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_editor.html#method-addCommand) method can now accept a [`CKEDITOR.command`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_command.html) instance as a parameter.
* [#1712](https://github.com/ckeditor/ckeditor-dev/issues/1712): The [`extraPlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins), [`removePlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removePlugins) and [`plugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-plugins) configuration options allow whitespace.
* [#1802](https://github.com/ckeditor/ckeditor-dev/issues/1802): The [`extraPlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins), [`removePlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removePlugins) and [`plugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-plugins) configuration options allow passing plugin names as an array.
* [#1724](https://github.com/ckeditor/ckeditor-dev/issues/1724): Added an option to the [`getClientRect()`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-getClientRect) function allowing to retrieve an absolute bounding rectangle of the element, i.e. a position relative to the upper-left corner of the topmost viewport.
* [#1498](https://github.com/ckeditor/ckeditor-dev/issues/1498) : Added a new [`getClientRects()`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-getClientRects) method to `CKEDITOR.dom.range`. It returns a list of rectangles for each selected element.
* [#1993](https://github.com/ckeditor/ckeditor-dev/issues/1993): Added the [`CKEDITOR.tools.throttle()`](http://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR_tools.html#method-throttle) function.
Other Changes:
* Updated [SCAYT](https://ckeditor.com/cke4/addon/scayt) (Spell Check As You Type) and [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) (WSC) plugins:
* Language dictionary update: Added support for the Uzbek Latin language.
* Languages no longer supported as additional languages: Manx - Isle of Man (`gv_GB`) and Interlingua (`ia_XR`).
* Extended and improved language dictionaries: Georgian and Swedish. Also added the missing word _"Ensure"_ to the American, British and Canada English language.
* [#141](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/141) Fixed: SCAYT throws "Uncaught Error: Error in RangyWrappedRange module: createRange(): Parameter must be a Window object or DOM node".
* [#153](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/153) [Chrome] Fixed: Correcting a word in the widget in SCAYT moves focus to another editable.
* [#155](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/155) [IE8] Fixed: SCAYT throws an error and does not work.
* [#156](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/156) [IE10] Fixed: SCAYT does not seem to work.
* Fixed: After some text is dragged and dropped, the markup is not refreshed for grammar problems in SCAYT.
* Fixed: Request to FastCGI fails when the user tries to replace a word with non-English characters with a proper suggestion in WSC.
* [Firefox] Fixed: <kbd>Ctrl</kbd>+<kbd>Z</kbd> removes focus in SCAYT.
* Grammar support for default languages was improved.
* New application source URL was added in SCAYT.
* Removed green marks and legend related to grammar-supported languages in the Languages tab of SCAYT. Grammar is now supported for almost all the anguages in the list for an additional fee.
* Fixed: JavaScript error in the console: "Cannot read property 'split' of undefined" in SCAYT and WSC.
* [IE10] Fixed: Markup is not set for a specific case in SCAYT.
* Fixed: Accessibility issue: No `alt` attribute for the logo image in the About tab of SCAYT.
## CKEditor 4.9.2
**Security Updates:**
* Fixed XSS vulnerability in the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) (`image2`) plugin reported by [Kyaw Min Thein](https://twitter.com/kyawminthein99).
Issue summary: It was possible to execute XSS inside CKEditor using the `<img>` tag and specially crafted HTML. Please note that the default presets (Basic/Standard/Full) do not include this plugin, so you are only at risk if you made a custom build and enabled this plugin.
We would like to thank the [Drupal security team](https://www.drupal.org/drupal-security-team) for bringing this matter to our attention and coordinating the fix and release process!
## CKEditor 4.9.1
Fixed Issues:
* [#1835](https://github.com/ckeditor/ckeditor-dev/issues/1835): Fixed: Integration between [CKFinder](https://ckeditor.com/ckeditor-4/ckfinder/) and the [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin does not work.
## CKEditor 4.9
New Features:
@@ -38,7 +107,7 @@ Fixed Issues:
API Changes:
* [#1346](https://github.com/ckeditor/ckeditor-dev/issues/1346): [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) [context manager API](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.balloontoolbar.contextManager) is now available in the [`pluginDefinition.init`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-method-init) method of the [requiring](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-property-requires) plugin.
* [#1346](https://github.com/ckeditor/ckeditor-dev/issues/1346): [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) [context manager API](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.balloontoolbar.contextManager) is now available in the [`pluginDefinition.init()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-method-init) method of the [requiring](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-property-requires) plugin.
* [#1530](https://github.com/ckeditor/ckeditor-dev/issues/1530): Added the possibility to use custom icons for [buttons](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR_ui_button.html).
Other Changes:
@@ -69,9 +138,9 @@ New Features:
* [#468](https://github.com/ckeditor/ckeditor-dev/issues/468): [Edge] Introduced support for the Clipboard API.
* [#607](https://github.com/ckeditor/ckeditor-dev/issues/607): Manually inserted Hex color is prefixed with a hash character (`#`) if needed. It ensures a valid Hex color value is used when setting the table cell border or background color with the [Color Dialog](https://ckeditor.com/cke4/addon/colordialog) window.
* [#584](https://github.com/ckeditor/ckeditor-dev/issues/584): [Font size and Family](https://ckeditor.com/cke4/addon/font) and [Format](https://ckeditor.com/cke4/addon/format) drop-downs are not toggleable anymore. Default option to reset styles added.
* [#856](https://github.com/ckeditor/ckeditor-dev/issues/856): Introduced the [`CKEDITOR.tools.keystrokeToArray`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-keystrokeToArray) method. It converts a keystroke into its string representation, returning every key name as a separate array element.
* [#1053](https://github.com/ckeditor/ckeditor-dev/issues/1053): Introduced the [`CKEDITOR.tools.object.merge`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.object-method-merge) method. It allows to merge two objects, returning the new object with all properties from both objects deeply cloned.
* [#1073](https://github.com/ckeditor/ckeditor-dev/issues/1073): Introduced the [`CKEDITOR.tools.array.every`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.array-method-every) method. It invokes a given test function on every array element and returns `true` if all elements pass the test.
* [#856](https://github.com/ckeditor/ckeditor-dev/issues/856): Introduced the [`CKEDITOR.tools.keystrokeToArray()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-keystrokeToArray) method. It converts a keystroke into its string representation, returning every key name as a separate array element.
* [#1053](https://github.com/ckeditor/ckeditor-dev/issues/1053): Introduced the [`CKEDITOR.tools.object.merge()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.object-method-merge) method. It allows to merge two objects, returning the new object with all properties from both objects deeply cloned.
* [#1073](https://github.com/ckeditor/ckeditor-dev/issues/1073): Introduced the [`CKEDITOR.tools.array.every()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.array-method-every) method. It invokes a given test function on every array element and returns `true` if all elements pass the test.
Fixed Issues:
@@ -83,7 +152,7 @@ Fixed Issues:
* [#842](https://github.com/ckeditor/ckeditor-dev/issues/842): Fixed: List style not restored when toggling list indent level in the [Indent List](https://ckeditor.com/cke4/addon/indentlist) plugin.
* [#711](https://github.com/ckeditor/ckeditor-dev/issues/711): Fixed: Dragging widgets should only work with the left mouse button.
* [#862](https://github.com/ckeditor/ckeditor-dev/issues/862): Fixed: The "Object Styles" group in the [Styles Combo](https://ckeditor.com/cke4/addon/stylescombo) plugin is visible only if the whole element is selected.
* [#994](https://github.com/ckeditor/ckeditor-dev/pull/994): Fixed: Typo in the [`CKEDITOR.focusManager.focus`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.focusManager-method-focus) API documentation. Thanks to [benjy](https://github.com/benjy)!
* [#994](https://github.com/ckeditor/ckeditor-dev/pull/994): Fixed: Typo in the [`CKEDITOR.focusManager.focus()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.focusManager-method-focus) API documentation. Thanks to [benjy](https://github.com/benjy)!
* [#1014](https://github.com/ckeditor/ckeditor-dev/issues/1014): Fixed: The [Table Tools](https://ckeditor.com/cke4/addon/tabletools) Cell Properties dialog is now [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf) aware &mdash; it is not possible to change the cell width or height if corresponding styles are disabled.
* [#877](https://github.com/ckeditor/ckeditor-dev/issues/877): Fixed: A list with custom bullets with exotic characters crashes the editor when [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword).
* [#605](https://github.com/ckeditor/ckeditor-dev/issues/605): Fixed: Inline widgets do not preserve trailing spaces.
@@ -104,7 +173,7 @@ Fixed Issues:
API Changes:
* [#1097](https://github.com/ckeditor/ckeditor-dev/issues/1097): Widget [`upcast`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-upcast) methods are now called in the [widget definition's](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-property-definition) context.
* [#1118](https://github.com/ckeditor/ckeditor-dev/issues/1118): Added the `show` option in the [`balloonPanel.attach`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ui.balloonPanel-method-attach) method, allowing to attach a hidden [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) instance.
* [#1118](https://github.com/ckeditor/ckeditor-dev/issues/1118): Added the `show` option in the [`balloonPanel.attach()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ui.balloonPanel-method-attach) method, allowing to attach a hidden [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) instance.
* [#1145](https://github.com/ckeditor/ckeditor-dev/issues/1145): Added the [`skipNotifications`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition-property-skipNotifications) option to the [`CKEDITOR.fileTools.uploadWidgetDefinition`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition), allowing to switch off default notifications displayed by upload widgets.
Other Changes:
@@ -133,7 +202,7 @@ Other Changes:
* Updated the [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) plugin:
* [#40](https://github.com/WebSpellChecker/ckeditor-plugin-wsc/issues/40): Fixed: IE10 throws an error when spell checking is started.
* [#800](https://github.com/ckeditor/ckeditor-dev/issues/800): Added the [`CKEDITOR.dom.selection.isCollapsed`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-method-isCollapsed) method which is a simpler way to check if the selection is collapsed.
* [#800](https://github.com/ckeditor/ckeditor-dev/issues/800): Added the [`CKEDITOR.dom.selection.isCollapsed()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-method-isCollapsed) method which is a simpler way to check if the selection is collapsed.
* [#830](https://github.com/ckeditor/ckeditor-dev/issues/830): Added an option to define which dialog tab should be shown by default when creating [`CKEDITOR.dialogCommand`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dialogCommand).
## CKEditor 4.7.2
@@ -156,15 +225,15 @@ Fixed Issues:
* [#501](https://github.com/ckeditor/ckeditor-dev/issues/501): Fixed: Double click does not open the dialog for modifying anchors inserted via the [Link](https://ckeditor.com/cke4/addon/link) plugin.
* [#9780](https://dev.ckeditor.com/ticket/9780): [IE8-9] Fixed: Clicking inside an empty [read-only](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-readOnly) editor throws an error.
* [#16820](https://dev.ckeditor.com/ticket/16820): [IE10] Fixed: Clicking below a single horizontal rule throws an error.
* [#426](https://github.com/ckeditor/ckeditor-dev/issues/426): Fixed: The [`range.cloneContents`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-cloneContents) method selects the whole element when the selection starts at the beginning of that element.
* [#644](https://github.com/ckeditor/ckeditor-dev/issues/644): Fixed: The [`range.extractContents`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-extractContents) method returns an incorrect result when multiple nodes are selected.
* [#684](https://github.com/ckeditor/ckeditor-dev/issues/684): Fixed: The [`elementPath.contains`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.elementPath-method-contains) method incorrectly excludes the last element instead of root when the `fromTop` parameter is set to `true`.
* [#426](https://github.com/ckeditor/ckeditor-dev/issues/426): Fixed: The [`range.cloneContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-cloneContents) method selects the whole element when the selection starts at the beginning of that element.
* [#644](https://github.com/ckeditor/ckeditor-dev/issues/644): Fixed: The [`range.extractContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-extractContents) method returns an incorrect result when multiple nodes are selected.
* [#684](https://github.com/ckeditor/ckeditor-dev/issues/684): Fixed: The [`elementPath.contains()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.elementPath-method-contains) method incorrectly excludes the last element instead of root when the `fromTop` parameter is set to `true`.
Other Changes:
* Updated the [SCAYT](https://ckeditor.com/cke4/addon/scayt) (Spell Check As You Type) plugin:
* [#148](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/148): Fixed: SCAYT leaves underlined word after the CKEditor Replace dialog corrects it.
* [#751](https://github.com/ckeditor/ckeditor-dev/issues/751): Added the [`CKEDITOR.dom.nodeList.toArray`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.nodeList-method-toArray) method which returns an array representation of a [node list](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.nodeList).
* [#751](https://github.com/ckeditor/ckeditor-dev/issues/751): Added the [`CKEDITOR.dom.nodeList.toArray()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.nodeList-method-toArray) method which returns an array representation of a [node list](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.nodeList).
## CKEditor 4.7.1
@@ -183,7 +252,7 @@ Fixed Issues:
* [#424](https://github.com/ckeditor/ckeditor-dev/issues/424): Fixed: Error thrown by [Tab Key Handling](https://ckeditor.com/cke4/addon/tab) and [Indent List](https://ckeditor.com/cke4/addon/indentlist) plugins when pressing <kbd>Tab</kbd> with no selection in inline editor.
* [#476](https://github.com/ckeditor/ckeditor-dev/issues/476): Fixed: Anchors inserted with the [Link](https://ckeditor.com/cke4/addon/link) plugin on collapsed selection cannot be edited.
* [#417](https://github.com/ckeditor/ckeditor-dev/issues/417): Fixed: The [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin throws an error when used with a table with only header or footer rows.
* [#523](https://github.com/ckeditor/ckeditor-dev/issues/523): Fixed: The [`editor.getCommandKeystroke`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getCommandKeystroke) method does not obtain the correct keystroke.
* [#523](https://github.com/ckeditor/ckeditor-dev/issues/523): Fixed: The [`editor.getCommandKeystroke()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getCommandKeystroke) method does not obtain the correct keystroke.
* [#534](https://github.com/ckeditor/ckeditor-dev/issues/534): [IE] Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) does not work in Quirks Mode.
* [#450](https://github.com/ckeditor/ckeditor-dev/issues/450): Fixed: [`CKEDITOR.filter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter) incorrectly transforms the `margin` CSS property.
@@ -203,8 +272,8 @@ New Features:
* [#16847](https://dev.ckeditor.com/ticket/16847): Added support for parsing and inlining any formatting created using the Microsoft Word style system to the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin.
* [#16818](https://dev.ckeditor.com/ticket/16818): Added table cell height parsing in the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin.
* [#16850](https://dev.ckeditor.com/ticket/16850): Added a new [`config.enableContextMenu`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enableContextMenu) configuration option for enabling and disabling the [context menu](https://ckeditor.com/cke4/addon/contextmenu).
* [#16937](https://dev.ckeditor.com/ticket/16937): The `command` parameter in [CKEDITOR.editor.getCommandKeystroke](http://docs.ckeditor.dev/#!/api/CKEDITOR.editor-method-getCommandKeystroke) now also accepts a command name as an argument.
* [#17010](https://dev.ckeditor.com/ticket/17010): The [`CKEDITOR.dom.range.shrink`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-shrink) method now allows for skipping bogus `<br>` elements.
* [#16937](https://dev.ckeditor.com/ticket/16937): The `command` parameter in [`CKEDITOR.editor.getCommandKeystroke()`](http://docs.ckeditor.dev/#!/api/CKEDITOR.editor-method-getCommandKeystroke) now also accepts a command name as an argument.
* [#17010](https://dev.ckeditor.com/ticket/17010): The [`CKEDITOR.dom.range.shrink()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-shrink) method now allows for skipping bogus `<br>` elements.
Fixed Issues:
@@ -238,7 +307,7 @@ Fixed Issues:
* [#14407](https://dev.ckeditor.com/ticket/14407): [IE] Fixed: Non-editable widgets can be edited.
* [#16927](https://dev.ckeditor.com/ticket/16927): Fixed: An error thrown if a bundle containing the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin is run in ES5 strict mode. Thanks to [Igor Rubinovich](https://github.com/IgorRubinovich)!
* [#16920](https://dev.ckeditor.com/ticket/16920): Fixed: Several plugins not using the [Dialog](https://ckeditor.com/cke4/addon/dialog) plugin as a direct dependency.
* [PR#336](https://github.com/ckeditor/ckeditor-dev/pull/336): Fixed: Typo in [`CKEDITOR.getCss`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-method-getCss) API documentation. Thanks to [knusperpixel](https://github.com/knusperpixel)!
* [PR#336](https://github.com/ckeditor/ckeditor-dev/pull/336): Fixed: Typo in [`CKEDITOR.getCss()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-method-getCss) API documentation. Thanks to [knusperpixel](https://github.com/knusperpixel)!
* [#17027](https://dev.ckeditor.com/ticket/17027): Fixed: Command event data should be initialized as an empty object.
* Fixed the behavior of HTML parser when parsing `src`/`srcdoc` attributes of the `<iframe>` element in a CKEditor setup with ACF turned off and without the [Iframe Dialog](https://ckeditor.com/cke4/addon/iframe) plugin. The issue was originally reported as a security issue by [Sriramk21](https://twitter.com/sriramk21) from Pegasystems and was later downgraded by the security team into a normal issue due to the requirement of having ACF turned off. Disabling [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) is against [security best practices](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_best_practices-section-security), so the problem described above has not been considered a security issue as such.
@@ -269,7 +338,7 @@ Fixed Issues:
* [#16728](https://dev.ckeditor.com/ticket/16728): [IE] Fixed: [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) breaks the editor in Quirks Mode.
* [#16795](https://dev.ckeditor.com/ticket/16795): [IE] Fixed: [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) breaks the editor in Compatibility Mode.
* [#16675](https://dev.ckeditor.com/ticket/16675): Fixed: Styles applied with [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) to a single table cell are applied to the whole table.
* [#16753](https://dev.ckeditor.com/ticket/16753): Fixed: [`element.setSize`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-setSize) sets incorrect editor dimensions if the border width is represented as a fraction of pixels.
* [#16753](https://dev.ckeditor.com/ticket/16753): Fixed: [`element.setSize()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-setSize) sets incorrect editor dimensions if the border width is represented as a fraction of pixels.
* [#16705](https://dev.ckeditor.com/ticket/16705): [Firefox] Fixed: Unable to paste images as Base64 strings when using [Clipboard](https://ckeditor.com/cke4/addon/clipboard).
* [#14869](https://dev.ckeditor.com/ticket/14869): Fixed: JavaScript error is thrown when trying to use [Find](https://ckeditor.com/cke4/addon/find) in a [`<div>`-based editor](https://ckeditor.com/cke4/addon/divarea).
@@ -277,7 +346,7 @@ Fixed Issues:
New Features:
* [#16639](https://dev.ckeditor.com/ticket/16639): The `callback` parameter in the [CKEDITOR.ajax.post](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ajax-method-post) method became optional.
* [#16639](https://dev.ckeditor.com/ticket/16639): The `callback` parameter in the [`CKEDITOR.ajax.post()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ajax-method-post) method became optional.
Fixed Issues:
@@ -375,7 +444,7 @@ Fixed Issues:
* [#13548](https://dev.ckeditor.com/ticket/13548): [IE] Fixed: Clicking the [elements path](https://ckeditor.com/cke4/addon/elementspath) disables Cut and Copy icons.
* [#13812](https://dev.ckeditor.com/ticket/13812): Fixed: When aborting file upload the placeholder for image is left.
* [#14659](https://dev.ckeditor.com/ticket/14659): [Blink] Fixed: Content scrolled to the top after closing the dialog in a [`<div>`-based editor](https://ckeditor.com/cke4/addon/divarea).
* [#14825](https://dev.ckeditor.com/ticket/14825): [Edge] Fixed: Focusing the editor causes unwanted scrolling due to dropped support for the `setActive` method.
* [#14825](https://dev.ckeditor.com/ticket/14825): [Edge] Fixed: Focusing the editor causes unwanted scrolling due to dropped support for the `setActive()` method.
## CKEditor 4.5.10
File diff suppressed because it is too large. Load diff
@@ -6,13 +6,14 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
body
{
/* Font */
font-family: sans-serif, Arial, Verdana, "Trebuchet MS";
/* Emoji fonts are added to visualise them nicely in Internet Explorer. */
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 12px;
/* Text color */
color: #333;
/* Remove the background color to make it transparent */
/* Remove the background color to make it transparent. */
background-color: #fff;
margin: 20px;
@@ -60,7 +61,7 @@ ol,ul,dl
{
/* IE7: reset rtl list margin. (#7334) */
*margin-right: 0px;
/* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/
/* Preserved spaces for list items with text direction different than the list. (#6249,#8049)*/
padding: 0 40px;
}
@@ -2,4 +2,4 @@
Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.lang['bg']={"widget":{"move":"Кликни и влачи, за да преместиш","label":"%1 widget"},"undo":{"redo":"Връщане на предишен статус","undo":"Възтанови"},"toolbar":{"toolbarCollapse":"Свиване на лентата с инструменти","toolbarExpand":"Разширяване на лентата с инструменти","toolbarGroups":{"document":"Документ","clipboard":"Клипборд/Отмяна","editing":"Промяна","forms":"Форми","basicstyles":"Базови стилове","paragraph":"Параграф","links":"Връзки","insert":"Вмъкване","styles":"Стилове","colors":"Цветове","tools":"Инструменти"},"toolbars":"Ленти с инструменти"},"sourcearea":{"toolbar":"Изходен код"},"notification":{"closed":"Notification closed."},"list":{"bulletedlist":"Вмъкване/Премахване на точков списък","numberedlist":"Вмъкване/Премахване на номериран списък"},"justify":{"block":"Двустранно подравняване","center":"Център","left":"Подравни в ляво","right":"Подравни в дясно"},"indent":{"indent":"Увеличаване на отстъпа","outdent":"Намаляване на отстъпа"},"font":{"fontSize":{"label":"Размер","voiceLabel":"Размер на шрифт","panelTitle":"Размер на шрифт"},"label":"Шрифт","panelTitle":"Име на шрифт","voiceLabel":"Шрифт"},"elementspath":{"eleLabel":"Път за елементите","eleTitle":"%1 елемент"},"colordialog":{"clear":"Изчистване","highlight":"Осветяване","options":"Цветови опции","selected":"Изберете цвят","title":"Изберете цвят"},"colorbutton":{"auto":"Автоматично","bgColorTitle":"Фонов цвят","colors":{"000":"Черно","800000":"Кестеняво","8B4513":"Светлокафяво","2F4F4F":"Dark Slate Gray","008080":"Teal","000080":"Navy","4B0082":"Индиго","696969":"Тъмно сиво","B22222":"Огнено червено","A52A2A":"Кафяво","DAA520":"Златисто","006400":"Тъмно зелено","40E0D0":"Тюркуазено","0000CD":"Средно синьо","800080":"Пурпурно","808080":"Сиво","F00":"Червено","FF8C00":"Тъмно оранжево","FFD700":"Златно","008000":"Зелено","0FF":"Светло синьо","00F":"Blue","EE82EE":"Violet","A9A9A9":"Dim Gray","FFA07A":"Light Salmon","FFA500":"Orange","FFFF00":"Yellow","00FF00":"Lime","AFEEEE":"Pale Turquoise","ADD8E6":"Light Blue","DDA0DD":"Plum","D3D3D3":"Light Grey","FFF0F5":"Lavender Blush","FAEBD7":"Antique White","FFFFE0":"Light Yellow","F0FFF0":"Honeydew","F0FFFF":"Azure","F0F8FF":"Alice Blue","E6E6FA":"Lavender","FFF":"White","1ABC9C":"Strong Cyan","2ECC71":"Emerald","3498DB":"Bright Blue","9B59B6":"Amethyst","4E5F70":"Grayish Blue","F1C40F":"Vivid Yellow","16A085":"Dark Cyan","27AE60":"Dark Emerald","2980B9":"Strong Blue","8E44AD":"Dark Violet","2C3E50":"Desaturated Blue","F39C12":"Orange","E67E22":"Carrot","E74C3C":"Pale Red","ECF0F1":"Bright Silver","95A5A6":"Light Grayish Cyan","DDD":"Light Gray","D35400":"Pumpkin","C0392B":"Strong Red","BDC3C7":"Silver","7F8C8D":"Grayish Cyan","999":"Dark Gray"},"more":"Още цветове","panelTitle":"Цветове","textColorTitle":"Цвят на шрифт"},"clipboard":{"copy":"Копирай","copyError":"Настройките за сигурност на вашия бразуър не разрешават на редактора да изпълни запаметяването. За целта използвайте клавиатурата (Ctrl/Cmd+C).","cut":"Отрежи","cutError":"Настройките за сигурност на Вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. Моля ползвайте клавиатурните команди за целта (ctrl+x).","paste":"Вмъкни","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Зона за вмъкване","pasteMsg":"Paste your content inside the area below and press OK.","title":"Вмъкни"},"button":{"selectedLabel":"%1 (Избрано)"},"basicstyles":{"bold":"Удебелен","italic":"Наклонен","strike":"Зачертан текст","subscript":"Индексиран текст","superscript":"Суперскрипт","underline":"Подчертан"},"editor":"Текстов редактор за форматиран текст","editorPanel":"Панел на текстовия редактор","common":{"editorHelp":"натиснете ALT 0 за помощ","browseServer":"Избор от сървърLine truncated
CKEDITOR.lang['bg']={"widget":{"move":"Кликни и влачи, за да преместиш","label":"%1 приставка"},"undo":{"redo":"Пренаправи","undo":"Отмени"},"toolbar":{"toolbarCollapse":"Свиване на лентата с инструменти","toolbarExpand":"Разширяване на лентата с инструменти","toolbarGroups":{"document":"Документ","clipboard":"Клипборд/Отмяна","editing":"Редакция","forms":"Форми","basicstyles":"Базови стилове","paragraph":"Параграф","links":"Връзки","insert":"Вмъкване","styles":"Стилове","colors":"Цветове","tools":"Инструменти"},"toolbars":"Ленти с инструменти"},"sourcearea":{"toolbar":"Код"},"notification":{"closed":"Известието е затворено."},"list":{"bulletedlist":"Вмъкване/премахване на точков списък","numberedlist":"Вмъкване/премахване на номериран списък"},"justify":{"block":"Двустранно подравняване","center":"Център","left":"Подравни в ляво","right":"Подравни в дясно"},"indent":{"indent":"Увеличаване на отстъпа","outdent":"Намаляване на отстъпа"},"font":{"fontSize":{"label":"Размер","voiceLabel":"Размер на шрифт","panelTitle":"Размер на шрифт"},"label":"Шрифт","panelTitle":"Име на шрифт","voiceLabel":"Шрифт"},"elementspath":{"eleLabel":"Път за елементите","eleTitle":"%1 елемент"},"colordialog":{"clear":"Изчистване","highlight":"Осветяване","options":"Цветови опции","selected":"Изберете цвят","title":"Избор на цвят"},"colorbutton":{"auto":"Автоматично","bgColorTitle":"Фонов цвят","colors":{"000":"Черно","800000":"Кестеняво","8B4513":"Светлокафяво","2F4F4F":"Тъмно плочесто сиво","008080":"Сиво птиче","000080":"Морско синьо","4B0082":"Индиго","696969":"Тъмно сиво","B22222":"Огнено червено","A52A2A":"Кафяво","DAA520":"Златисто","006400":"Тъмно зелено","40E0D0":"Тюркуазено","0000CD":"Средно синьо","800080":"Пурпурно","808080":"Сиво","F00":"Червено","FF8C00":"Тъмно оранжево","FFD700":"Златно","008000":"Зелено","0FF":"Светло синьо","00F":"Синьо","EE82EE":"Виолетово","A9A9A9":"Бледо сиво","FFA07A":"Светло розово-оранжево","FFA500":"Оранжево","FFFF00":"Жълто","00FF00":"Варосано","AFEEEE":"Тюркоазено остро","ADD8E6":"Светло синьо","DDA0DD":"Сливово","D3D3D3":"Светло сиво","FFF0F5":"Лавандула изчервено","FAEBD7":"Антично бяло","FFFFE0":"Светло жълто","F0FFF0":"Медена роса","F0FFFF":"Лазурно","F0F8FF":"Алиса синьо","E6E6FA":"Лавандула","FFF":"Бяло","1ABC9C":"Силно синьо-зелено","2ECC71":"Изомрудено","3498DB":"Ярко синьо","9B59B6":"Аметист","4E5F70":"Сивкаво синьо","F1C40F":"Блестящо жълто","16A085":"Тъмно синьо-зелено","27AE60":"Тъмно изомрудено","2980B9":"Силно синьо","8E44AD":"Тъмно виолетово","2C3E50":"Ненаситено синьо","F39C12":"Оранжево","E67E22":"Морков","E74C3C":"Бледо червено","ECF0F1":"Ярко сребърно","95A5A6":"Светло сивкаво синьо-зелено","DDD":"Светло сиво","D35400":"Тиквено","C0392B":"Силно червено","BDC3C7":"Сребърно","7F8C8D":"Сивкаво синьо-зелено","999":"Тъмно сиво"},"more":"Още цветове","panelTitle":"Цветове","textColorTitle":"Цвят на текста"},"clipboard":{"copy":"Копирай","copyError":"Настройките за сигурност на вашия бразуър не разрешават на редактора да изпълни действията по копиране. За целта използвайте клавиатурата (Ctrl+C).","cut":"Отрежи","cutError":"Настройките за сигурност на вашия браузър не позволяват на редактора автоматично да изъплни действията за отрязване. За целта използвайте клавиатурата (Ctrl+X).","paste":"Вмъкни","pasteNotification":"Натиснете %1 за да вмъкнете. Вашият браузър не поддържа поставяне с бутон от лентата с инструменти или от контLine truncated
@@ -2,4 +2,4 @@
Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.lang['cs']={"widget":{"move":"Klepněte a táhněte pro přesunutí","label":"Ovládací prvek %1"},"undo":{"redo":"Znovu","undo":"Zpět"},"toolbar":{"toolbarCollapse":"Skrýt panel nástrojů","toolbarExpand":"Zobrazit panel nástrojů","toolbarGroups":{"document":"Dokument","clipboard":"Schránka/Zpět","editing":"Úpravy","forms":"Formuláře","basicstyles":"Základní styly","paragraph":"Odstavec","links":"Odkazy","insert":"Vložit","styles":"Styly","colors":"Barvy","tools":"Nástroje"},"toolbars":"Panely nástrojů editoru"},"sourcearea":{"toolbar":"Zdroj"},"notification":{"closed":"Oznámení zavřeno."},"list":{"bulletedlist":"Odrážky","numberedlist":"Číslování"},"justify":{"block":"Zarovnat do bloku","center":"Zarovnat na střed","left":"Zarovnat vlevo","right":"Zarovnat vpravo"},"indent":{"indent":"Zvětšit odsazení","outdent":"Zmenšit odsazení"},"font":{"fontSize":{"label":"Velikost","voiceLabel":"Velikost písma","panelTitle":"Velikost"},"label":"Písmo","panelTitle":"Písmo","voiceLabel":"Písmo"},"elementspath":{"eleLabel":"Cesta objektu","eleTitle":"%1 objekt"},"colordialog":{"clear":"Vyčistit","highlight":"Zvýraznit","options":"Nastavení barvy","selected":"Vybráno","title":"Výběr barvy"},"colorbutton":{"auto":"Automaticky","bgColorTitle":"Barva pozadí","colors":{"000":"Černá","800000":"Kaštanová","8B4513":"Sedlová hněď","2F4F4F":"Tmavě bledě šedá","008080":"Čírka","000080":"Námořnická modř","4B0082":"Inkoustová","696969":"Tmavě šedá","B22222":"Pálená cihla","A52A2A":"Hnědá","DAA520":"Zlatý prut","006400":"Tmavě zelená","40E0D0":"Tyrkisová","0000CD":"Středně modrá","800080":"Purpurová","808080":"Šedá","F00":"Červená","FF8C00":"Tmavě oranžová","FFD700":"Zlatá","008000":"Zelená","0FF":"Azurová","00F":"Modrá","EE82EE":"Fialová","A9A9A9":"Kalně šedá","FFA07A":"Světle lososová","FFA500":"Oranžová","FFFF00":"Žlutá","00FF00":"Limetková","AFEEEE":"Bledě tyrkisová","ADD8E6":"Světle modrá","DDA0DD":"Švestková","D3D3D3":"Světle šedá","FFF0F5":"Levandulově ruměnná","FAEBD7":"Antická bílá","FFFFE0":"Světle žlutá","F0FFF0":"Medová rosa","F0FFFF":"Azurová","F0F8FF":"Alenčina modrá","E6E6FA":"Levandulová","FFF":"Bílá","1ABC9C":"Silná azurová","2ECC71":"Emeraldová","3498DB":"Jasně modrá","9B59B6":"Ametystová","4E5F70":"Šedomodrá","F1C40F":"Sytá žlutá","16A085":"Tmavě azurová","27AE60":"Tmavě emeraldová","2980B9":"Silná modrá","8E44AD":"Tmavě fialová","2C3E50":"Odsycená modrá","F39C12":"Oranžová","E67E22":"Mrkvová","E74C3C":"Bledě červená","ECF0F1":"Světle stříbrná","95A5A6":"Světlě šedoazurová","DDD":"Světle šedá","D35400":"Dýňová","C0392B":"Silná červená","BDC3C7":"Stříbrná","7F8C8D":"Šedoazurová","999":"Tmavošedá"},"more":"Více barev...","panelTitle":"Barvy","textColorTitle":"Barva textu"},"clipboard":{"copy":"Kopírovat","copyError":"Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro kopírování zvoleného textu do schránky. Prosím zkopírujte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+C).","cut":"Vyjmout","cutError":"Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+X).","paste":"Vložit","pasteNotification":"Stiskněte %1 pro vložení. Váš prohlížeč nepodporuje vkládání pomocí tlačítka na panelu nástrojů nebo volby kontextového menu.","pasteArea":"Oblast vkládání","pasteMsg":"Vložte svůj obsah do oblasti níže a stiskněte OK.","title":"Vložit"},"button":{"selectedLabel":"%1 (Vybráno)"},"basicstyles":{"bold":"Tučné","italic":"Kurzíva","strike":"Přeškrtnuté","subscript":"Dolní index","superscript":"Horní index","underline":"Podtržené"},"editor":"Textový editor","editorPanel":"Panel textového editoru","common":{"editorHelp":"Stiskněte ALT 0 pro nápovědu","browseServer":"Vybrat na serveru","url":"URL","protocol":"Protokol","upload":"Odeslat","uploadSubmit":"Odeslat na server","image":"Obrázek","flash":"Flash","form":"Formulář","checkbox":"Zaškrtávací políčko","radio":"Přepínač","textField":"Textové pole","textarea":"Textová oblast","hiddenField":"Skryté pole","button":"Tlačítko","select":"Seznam","imageButton":"Obrázkové tlačítko","notSet":"<nenastaveno>","id":"Id","name":"Jméno","langDir":"Směr jazyka","langDirLtr":"Zleva doprava (LTR)","langDirRtl":"Zprava doleva (RTL)","langCode":"Kód jazyka","longDescr":"Dlouhý popis URL","cssClass":"Třída stylu","advisoryTitle":"Pomocný titulek","cssStyle":"Styl","ok":"OK","cancel":"Zrušit","close":"Zavřít","preview":"Náhled","resize":"Uchopit pro změnu velikosti","generalTab":"Obecné","advancedTab":"Rozšířené","validateNumberFailed":"Zadaná hodnota není číselná.","confirmNewPage":"Jakékoliv neuložené změny obsahu budou ztraceny. Line truncated
CKEDITOR.lang['cs']={"widget":{"move":"Klepněte a táhněte pro přesunutí","label":"Ovládací prvek %1"},"undo":{"redo":"Znovu","undo":"Zpět"},"toolbar":{"toolbarCollapse":"Skrýt panel nástrojů","toolbarExpand":"Zobrazit panel nástrojů","toolbarGroups":{"document":"Dokument","clipboard":"Schránka/Zpět","editing":"Úpravy","forms":"Formuláře","basicstyles":"Základní styly","paragraph":"Odstavec","links":"Odkazy","insert":"Vložit","styles":"Styly","colors":"Barvy","tools":"Nástroje"},"toolbars":"Panely nástrojů editoru"},"sourcearea":{"toolbar":"Zdroj"},"notification":{"closed":"Oznámení zavřeno."},"list":{"bulletedlist":"Odrážky","numberedlist":"Číslování"},"justify":{"block":"Zarovnat do bloku","center":"Zarovnat na střed","left":"Zarovnat vlevo","right":"Zarovnat vpravo"},"indent":{"indent":"Zvětšit odsazení","outdent":"Zmenšit odsazení"},"font":{"fontSize":{"label":"Velikost","voiceLabel":"Velikost písma","panelTitle":"Velikost"},"label":"Písmo","panelTitle":"Písmo","voiceLabel":"Písmo"},"elementspath":{"eleLabel":"Cesta objektu","eleTitle":"%1 objekt"},"colordialog":{"clear":"Vyčistit","highlight":"Zvýraznit","options":"Nastavení barvy","selected":"Vybráno","title":"Výběr barvy"},"colorbutton":{"auto":"Automaticky","bgColorTitle":"Barva pozadí","colors":{"000":"Černá","800000":"Kaštanová","8B4513":"Sedlová hněď","2F4F4F":"Tmavě bledě šedá","008080":"Čírka","000080":"Námořnická modř","4B0082":"Inkoustová","696969":"Tmavě šedá","B22222":"Pálená cihla","A52A2A":"Hnědá","DAA520":"Zlatý prut","006400":"Tmavě zelená","40E0D0":"Tyrkisová","0000CD":"Středně modrá","800080":"Purpurová","808080":"Šedá","F00":"Červená","FF8C00":"Tmavě oranžová","FFD700":"Zlatá","008000":"Zelená","0FF":"Azurová","00F":"Modrá","EE82EE":"Fialová","A9A9A9":"Kalně šedá","FFA07A":"Světle lososová","FFA500":"Oranžová","FFFF00":"Žlutá","00FF00":"Limetková","AFEEEE":"Bledě tyrkisová","ADD8E6":"Světle modrá","DDA0DD":"Švestková","D3D3D3":"Světle šedá","FFF0F5":"Levandulově ruměnná","FAEBD7":"Antická bílá","FFFFE0":"Světle žlutá","F0FFF0":"Medová rosa","F0FFFF":"Azurová","F0F8FF":"Alenčina modrá","E6E6FA":"Levandulová","FFF":"Bílá","1ABC9C":"Silná azurová","2ECC71":"Emeraldová","3498DB":"Jasně modrá","9B59B6":"Ametystová","4E5F70":"Šedomodrá","F1C40F":"Sytá žlutá","16A085":"Tmavě azurová","27AE60":"Tmavě emeraldová","2980B9":"Silná modrá","8E44AD":"Tmavě fialová","2C3E50":"Odsycená modrá","F39C12":"Oranžová","E67E22":"Mrkvová","E74C3C":"Bledě červená","ECF0F1":"Světle stříbrná","95A5A6":"Světlě šedoazurová","DDD":"Světle šedá","D35400":"Dýňová","C0392B":"Silná červená","BDC3C7":"Stříbrná","7F8C8D":"Šedoazurová","999":"Tmavošedá"},"more":"Více barev...","panelTitle":"Barvy","textColorTitle":"Barva textu"},"clipboard":{"copy":"Kopírovat","copyError":"Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro kopírování zvoleného textu do schránky. Prosím zkopírujte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+C).","cut":"Vyjmout","cutError":"Bezpečnostní nastavení vašeho prohlížeče nedovolují editoru spustit funkci pro vyjmutí zvoleného textu do schránky. Prosím vyjměte zvolený text do schránky pomocí klávesnice (Ctrl/Cmd+X).","paste":"Vložit","pasteNotification":"Stiskněte %1 pro vložení. Váš prohlížeč nepodporuje vkládání pomocí tlačítka na panelu nástrojů nebo volby kontextového menu.","pasteArea":"Oblast vkládání","pasteMsg":"Vložte svůj obsah do oblasti níže a stiskněte OK.","title":"Vložit"},"button":{"selectedLabel":"%1 (Vybráno)"},"basicstyles":{"bold":"Tučné","italic":"Kurzíva","strike":"Přeškrtnuté","subscript":"Dolní index","superscript":"Horní index","underline":"Podtržené"},"editor":"Textový editor","editorPanel":"Panel textového editoru","common":{"editorHelp":"Stiskněte ALT 0 pro nápovědu","browseServer":"Vybrat na serveru","url":"URL","protocol":"Protokol","upload":"Odeslat","uploadSubmit":"Odeslat na server","image":"Obrázek","flash":"Flash","form":"Formulář","checkbox":"Zaškrtávací políčko","radio":"Přepínač","textField":"Textové pole","textarea":"Textová oblast","hiddenField":"Skryté pole","button":"Tlačítko","select":"Seznam","imageButton":"Obrázkové tlačítko","notSet":"<nenastaveno>","id":"Id","name":"Jméno","langDir":"Směr jazyka","langDirLtr":"Zleva doprava (LTR)","langDirRtl":"Zprava doleva (RTL)","langCode":"Kód jazyka","longDescr":"Dlouhý popis URL","cssClass":"Třída stylu","advisoryTitle":"Pomocný titulek","cssStyle":"Styl","ok":"OK","cancel":"Zrušit","close":"Zavřít","preview":"Náhled","resize":"Uchopit pro změnu velikosti","generalTab":"Obecné","advancedTab":"Rozšířené","validateNumberFailed":"Zadaná hodnota není číselná.","confirmNewPage":"Jakékoliv neuložené změny obsahu budou ztraceny. Line truncated
@@ -2,4 +2,4 @@
Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.lang['de']={"widget":{"move":"Zum Verschieben anwählen und ziehen","label":"%1 Steuerelement"},"undo":{"redo":"Wiederherstellen","undo":"Rückgängig"},"toolbar":{"toolbarCollapse":"Werkzeugleiste einklappen","toolbarExpand":"Werkzeugleiste ausklappen","toolbarGroups":{"document":"Dokument","clipboard":"Zwischenablage/Rückgängig","editing":"Editieren","forms":"Formulare","basicstyles":"Grundstile","paragraph":"Absatz","links":"Links","insert":"Einfügen","styles":"Stile","colors":"Farben","tools":"Werkzeuge"},"toolbars":"Editor Werkzeugleisten"},"sourcearea":{"toolbar":"Quellcode"},"notification":{"closed":"Benachrichtigung geschlossen."},"list":{"bulletedlist":"Liste","numberedlist":"Nummerierte Liste einfügen/entfernen"},"justify":{"block":"Blocksatz","center":"Zentriert","left":"Linksbündig","right":"Rechtsbündig"},"indent":{"indent":"Einzug erhöhen","outdent":"Einzug verringern"},"font":{"fontSize":{"label":"Größe","voiceLabel":"Schrifgröße","panelTitle":"Schriftgröße"},"label":"Schriftart","panelTitle":"Schriftartname","voiceLabel":"Schriftart"},"elementspath":{"eleLabel":"Elementepfad","eleTitle":"%1 Element"},"colordialog":{"clear":"Entfernen","highlight":"Hervorheben","options":"Farboptionen","selected":"Ausgewählte Farbe","title":"Farbe auswählen"},"colorbutton":{"auto":"Automatisch","bgColorTitle":"Hintergrundfarbe","colors":{"000":"Schwarz","800000":"Kastanienbraun","8B4513":"Braun","2F4F4F":"Dunkles Schiefergrau","008080":"Blaugrün","000080":"Marineblau","4B0082":"Indigo","696969":"Dunkelgrau","B22222":"Ziegelrot","A52A2A":"Braun","DAA520":"Goldgelb","006400":"Dunkelgrün","40E0D0":"Türkis","0000CD":"Mittelblau","800080":"Lila","808080":"Grau","F00":"Rot","FF8C00":"Dunkelorange","FFD700":"Gold","008000":"Grün","0FF":"Cyan","00F":"Blau","EE82EE":"Violett","A9A9A9":"Dunkelgrau","FFA07A":"Helles Lachsrosa","FFA500":"Orange","FFFF00":"Gelb","00FF00":"Lime","AFEEEE":"Blasstürkis","ADD8E6":"Hellblau","DDA0DD":"Pflaumenblau","D3D3D3":"Hellgrau","FFF0F5":"Lavendel","FAEBD7":"Antik Weiß","FFFFE0":"Hellgelb","F0FFF0":"Honigtau","F0FFFF":"Azurblau","F0F8FF":"Alice Blau","E6E6FA":"Lavendel","FFF":"Weiß","1ABC9C":"Strong Cyan","2ECC71":"Smaragdgrün","3498DB":"Bright Blue","9B59B6":"Amethystblau","4E5F70":"Graublau","F1C40F":"Vivid Yellow","16A085":"Dunkelcyan","27AE60":"Dunkelsmaragdgrün","2980B9":"Strong Blue","8E44AD":"Dunkelviolett","2C3E50":"Entsättigtes blau","F39C12":"Orange","E67E22":"Möhrenfarben","E74C3C":"Blassrot","ECF0F1":"Glänzendes Silber","95A5A6":"Helles Graublau","DDD":"Hellgrau","D35400":"Kürbisfarben","C0392B":"Strong Red","BDC3C7":"Silber","7F8C8D":"Graucyan","999":"Dunkelgrau"},"more":"Weitere Farben...","panelTitle":"Farben","textColorTitle":"Textfarbe"},"clipboard":{"copy":"Kopieren","copyError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).","cut":"Ausschneiden","cutError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).","paste":"Einfügen","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Einfügebereich","pasteMsg":"Paste your content inside the area below and press OK.","title":"Einfügen"},"button":{"selectedLabel":"%1 (Ausgewählt)"},"basicstyles":{"bold":"Fett","italic":"Kursiv","strike":"Durchgestrichen","subscript":"Tiefgestellt","superscript":"Hochgestellt","underline":"Unterstrichen"},"editor":"WYSIWYG-Editor","editorPanel":"WYSIWYG-Editor-Leiste","common":{"editorHelp":"Drücken Sie ALT 0 für Hilfe","browseServer":"Server durchsuchen","url":"URL","protocol":"Protokoll","upload":"Hochladen","uploadSubmit":"Zum Server senden","image":"Bild","flash":"Flash","form":"Formular","checkbox":"Kontrollbox","radio":"Optionsfeld","textField":"Textfeld","textarea":"Textfeld","hiddenField":"Verstecktes Feld","button":"Schaltfläche","select":"Auswahlfeld","imageButton":"Bildschaltfläche","notSet":"<nicht festgelegt>","id":"Kennung","name":"Name","langDir":"Schreibrichtung","langDirLtr":"Links nach Rechts (LTR)","langDirRtl":"Rechts nach Links (RTL)","langCode":"Sprachcode","longDescr":"Langbeschreibungs-URL","cssClass":"Formatvorlagenklassen","advisoryTitle":"Titel Beschreibung","cssStyle":"Stil","ok":"OK","cancel":"Abbrechen","close":"Schließen","preview":"Vorschau","resize":"Größe ändern","generalTab":"Allgemein","advancedTab":"Erweitert","validateNumberFailed":"Dieser Wert ist keine Nummer.","confirmNewPage":"Alle nicht gespeicherten Änderungen gehen verloren. Sind Sie sicher die neue Seite zu laden?","confirmCancel":"Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schließen?","options":"Optionen","target":"Zielseite","targetNew":"Neues Fenster (_blank)","targetTop":"ObeLine truncated
CKEDITOR.lang['de']={"widget":{"move":"Zum Verschieben anwählen und ziehen","label":"%1 Steuerelement"},"undo":{"redo":"Wiederherstellen","undo":"Rückgängig"},"toolbar":{"toolbarCollapse":"Werkzeugleiste einklappen","toolbarExpand":"Werkzeugleiste ausklappen","toolbarGroups":{"document":"Dokument","clipboard":"Zwischenablage/Rückgängig","editing":"Editieren","forms":"Formulare","basicstyles":"Grundstile","paragraph":"Absatz","links":"Links","insert":"Einfügen","styles":"Stile","colors":"Farben","tools":"Werkzeuge"},"toolbars":"Editor Werkzeugleisten"},"sourcearea":{"toolbar":"Quellcode"},"notification":{"closed":"Benachrichtigung geschlossen."},"list":{"bulletedlist":"Liste","numberedlist":"Nummerierte Liste einfügen/entfernen"},"justify":{"block":"Blocksatz","center":"Zentriert","left":"Linksbündig","right":"Rechtsbündig"},"indent":{"indent":"Einzug erhöhen","outdent":"Einzug verringern"},"font":{"fontSize":{"label":"Größe","voiceLabel":"Schrifgröße","panelTitle":"Schriftgröße"},"label":"Schriftart","panelTitle":"Schriftartname","voiceLabel":"Schriftart"},"elementspath":{"eleLabel":"Elementepfad","eleTitle":"%1 Element"},"colordialog":{"clear":"Entfernen","highlight":"Hervorheben","options":"Farboptionen","selected":"Ausgewählte Farbe","title":"Farbe auswählen"},"colorbutton":{"auto":"Automatisch","bgColorTitle":"Hintergrundfarbe","colors":{"000":"Schwarz","800000":"Kastanienbraun","8B4513":"Braun","2F4F4F":"Dunkles Schiefergrau","008080":"Blaugrün","000080":"Marineblau","4B0082":"Indigo","696969":"Dunkelgrau","B22222":"Ziegelrot","A52A2A":"Braun","DAA520":"Goldgelb","006400":"Dunkelgrün","40E0D0":"Türkis","0000CD":"Mittelblau","800080":"Lila","808080":"Grau","F00":"Rot","FF8C00":"Dunkelorange","FFD700":"Gold","008000":"Grün","0FF":"Cyan","00F":"Blau","EE82EE":"Violett","A9A9A9":"Dunkelgrau","FFA07A":"Helles Lachsrosa","FFA500":"Orange","FFFF00":"Gelb","00FF00":"Lime","AFEEEE":"Blasstürkis","ADD8E6":"Hellblau","DDA0DD":"Pflaumenblau","D3D3D3":"Hellgrau","FFF0F5":"Lavendel","FAEBD7":"Antik Weiß","FFFFE0":"Hellgelb","F0FFF0":"Honigtau","F0FFFF":"Azurblau","F0F8FF":"Alice Blau","E6E6FA":"Lavendel","FFF":"Weiß","1ABC9C":"Strong Cyan","2ECC71":"Smaragdgrün","3498DB":"Bright Blue","9B59B6":"Amethystblau","4E5F70":"Graublau","F1C40F":"Vivid Yellow","16A085":"Dunkelcyan","27AE60":"Dunkelsmaragdgrün","2980B9":"Strong Blue","8E44AD":"Dunkelviolett","2C3E50":"Entsättigtes blau","F39C12":"Orange","E67E22":"Möhrenfarben","E74C3C":"Blassrot","ECF0F1":"Glänzendes Silber","95A5A6":"Helles Graublau","DDD":"Hellgrau","D35400":"Kürbisfarben","C0392B":"Strong Red","BDC3C7":"Silber","7F8C8D":"Graucyan","999":"Dunkelgrau"},"more":"Weitere Farben...","panelTitle":"Farben","textColorTitle":"Textfarbe"},"clipboard":{"copy":"Kopieren","copyError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch kopieren. Bitte benutzen Sie die System-Zwischenablage über STRG-C (kopieren).","cut":"Ausschneiden","cutError":"Die Sicherheitseinstellungen Ihres Browsers lassen es nicht zu, den Text automatisch auszuschneiden. Bitte benutzen Sie die System-Zwischenablage über STRG-X (ausschneiden) und STRG-V (einfügen).","paste":"Einfügen","pasteNotification":"Drücken Sie %1 zum Einfügen. Ihr Browser unterstützt nicht das Einfügen über dem Knopf in der Toolbar oder dem Kontextmenü.","pasteArea":"Einfügebereich","pasteMsg":"Fügen Sie den Inhalt in den unteren Bereich ein und drücken Sie OK.","title":"Einfügen"},"button":{"selectedLabel":"%1 (Ausgewählt)"},"basicstyles":{"bold":"Fett","italic":"Kursiv","strike":"Durchgestrichen","subscript":"Tiefgestellt","superscript":"Hochgestellt","underline":"Unterstrichen"},"editor":"WYSIWYG-Editor","editorPanel":"WYSIWYG-Editor-Leiste","common":{"editorHelp":"Drücken Sie ALT 0 für Hilfe","browseServer":"Server durchsuchen","url":"URL","protocol":"Protokoll","upload":"Hochladen","uploadSubmit":"Zum Server senden","image":"Bild","flash":"Flash","form":"Formular","checkbox":"Kontrollbox","radio":"Optionsfeld","textField":"Textfeld","textarea":"Textfeld","hiddenField":"Verstecktes Feld","button":"Schaltfläche","select":"Auswahlfeld","imageButton":"Bildschaltfläche","notSet":"<nicht festgelegt>","id":"Kennung","name":"Name","langDir":"Schreibrichtung","langDirLtr":"Links nach Rechts (LTR)","langDirRtl":"Rechts nach Links (RTL)","langCode":"Sprachcode","longDescr":"Langbeschreibungs-URL","cssClass":"Formatvorlagenklassen","advisoryTitle":"Titel Beschreibung","cssStyle":"Stil","ok":"OK","cancel":"Abbrechen","close":"Schließen","preview":"Vorschau","resize":"Größe ändern","generalTab":"Allgemein","advancedTab":"Erweitert","validateNumberFailed":"Dieser Wert ist keine Nummer.","confirmNewPage":"Alle nicht gespeicherten Änderungen gehen verloren. Sind Sie sicher die neue Seite zu laden?","confirmCancel":"Einige Optionen wurden geändert. Wollen Sie den Dialog dennoch schließen?","options":"Optionen","target":"Zielseite","targetNew":"NLine truncated
@@ -2,4 +2,4 @@
Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.lang['en-au']={"widget":{"move":"Click and drag to move","label":"%1 widget"},"undo":{"redo":"Redo","undo":"Undo"},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"sourcearea":{"toolbar":"Source"},"notification":{"closed":"Notification closed."},"list":{"bulletedlist":"Insert/Remove Bulleted List","numberedlist":"Insert/Remove Numbered List"},"justify":{"block":"Justify","center":"Centre","left":"Align Left","right":"Align Right"},"indent":{"indent":"Increase Indent","outdent":"Decrease Indent"},"font":{"fontSize":{"label":"Size","voiceLabel":"Font Size","panelTitle":"Font Size"},"label":"Font","panelTitle":"Font Name","voiceLabel":"Font"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"colordialog":{"clear":"Clear","highlight":"Highlight","options":"Colour Options","selected":"Selected Colour","title":"Select colour"},"colorbutton":{"auto":"Automatic","bgColorTitle":"Background Colour","colors":{"000":"Black","800000":"Maroon","8B4513":"Saddle Brown","2F4F4F":"Dark Slate Gray","008080":"Teal","000080":"Navy","4B0082":"Indigo","696969":"Dark Gray","B22222":"Fire Brick","A52A2A":"Brown","DAA520":"Golden Rod","006400":"Dark Green","40E0D0":"Turquoise","0000CD":"Medium Blue","800080":"Purple","808080":"Gray","F00":"Red","FF8C00":"Dark Orange","FFD700":"Gold","008000":"Green","0FF":"Cyan","00F":"Blue","EE82EE":"Violet","A9A9A9":"Dim Gray","FFA07A":"Light Salmon","FFA500":"Orange","FFFF00":"Yellow","00FF00":"Lime","AFEEEE":"Pale Turquoise","ADD8E6":"Light Blue","DDA0DD":"Plum","D3D3D3":"Light Grey","FFF0F5":"Lavender Blush","FAEBD7":"Antique White","FFFFE0":"Light Yellow","F0FFF0":"Honeydew","F0FFFF":"Azure","F0F8FF":"Alice Blue","E6E6FA":"Lavender","FFF":"White","1ABC9C":"Strong Cyan","2ECC71":"Emerald","3498DB":"Bright Blue","9B59B6":"Amethyst","4E5F70":"Greyish Blue","F1C40F":"Vivid Yellow","16A085":"Dark Cyan","27AE60":"Dark Emerald","2980B9":"Strong Blue","8E44AD":"Dark Violet","2C3E50":"Desaturated Blue","F39C12":"Orange","E67E22":"Carrot","E74C3C":"Pale Red","ECF0F1":"Bright Silver","95A5A6":"Light Greyish Cyan","DDD":"Light Grey","D35400":"Pumpkin","C0392B":"Strong Red","BDC3C7":"Silver","7F8C8D":"Greyish Cyan","999":"Dark Grey"},"more":"More Colours...","panelTitle":"Colors","textColorTitle":"Text Colour"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK.","title":"Paste"},"button":{"selectedLabel":"%1 (Selected)"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strike Through","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Align","left":"Left","right":"Right","center":"Center","justify":"Justify","alignLeft":"Align LeftLine truncated
CKEDITOR.lang['en-au']={"widget":{"move":"Click and drag to move","label":"%1 widget"},"undo":{"redo":"Redo","undo":"Undo"},"toolbar":{"toolbarCollapse":"Collapse Toolbar","toolbarExpand":"Expand Toolbar","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editor toolbars"},"sourcearea":{"toolbar":"Source"},"notification":{"closed":"Notification closed."},"list":{"bulletedlist":"Insert/Remove Bulleted List","numberedlist":"Insert/Remove Numbered List"},"justify":{"block":"Justify","center":"Centre","left":"Align Left","right":"Align Right"},"indent":{"indent":"Increase Indent","outdent":"Decrease Indent"},"font":{"fontSize":{"label":"Size","voiceLabel":"Font Size","panelTitle":"Font Size"},"label":"Font","panelTitle":"Font Name","voiceLabel":"Font"},"elementspath":{"eleLabel":"Elements path","eleTitle":"%1 element"},"colordialog":{"clear":"Clear","highlight":"Highlight","options":"Colour Options","selected":"Selected Colour","title":"Select colour"},"colorbutton":{"auto":"Automatic","bgColorTitle":"Background Colour","colors":{"000":"Black","800000":"Maroon","8B4513":"Saddle Brown","2F4F4F":"Dark Slate Gray","008080":"Teal","000080":"Navy","4B0082":"Indigo","696969":"Dark Gray","B22222":"Fire Brick","A52A2A":"Brown","DAA520":"Golden Rod","006400":"Dark Green","40E0D0":"Turquoise","0000CD":"Medium Blue","800080":"Purple","808080":"Gray","F00":"Red","FF8C00":"Dark Orange","FFD700":"Gold","008000":"Green","0FF":"Cyan","00F":"Blue","EE82EE":"Violet","A9A9A9":"Dim Gray","FFA07A":"Light Salmon","FFA500":"Orange","FFFF00":"Yellow","00FF00":"Lime","AFEEEE":"Pale Turquoise","ADD8E6":"Light Blue","DDA0DD":"Plum","D3D3D3":"Light Grey","FFF0F5":"Lavender Blush","FAEBD7":"Antique White","FFFFE0":"Light Yellow","F0FFF0":"Honeydew","F0FFFF":"Azure","F0F8FF":"Alice Blue","E6E6FA":"Lavender","FFF":"White","1ABC9C":"Strong Cyan","2ECC71":"Emerald","3498DB":"Bright Blue","9B59B6":"Amethyst","4E5F70":"Greyish Blue","F1C40F":"Vivid Yellow","16A085":"Dark Cyan","27AE60":"Dark Emerald","2980B9":"Strong Blue","8E44AD":"Dark Violet","2C3E50":"Desaturated Blue","F39C12":"Orange","E67E22":"Carrot","E74C3C":"Pale Red","ECF0F1":"Bright Silver","95A5A6":"Light Greyish Cyan","DDD":"Light Grey","D35400":"Pumpkin","C0392B":"Strong Red","BDC3C7":"Silver","7F8C8D":"Greyish Cyan","999":"Dark Grey"},"more":"More Colours...","panelTitle":"Colors","textColorTitle":"Text Colour"},"clipboard":{"copy":"Copy","copyError":"Your browser security settings don't permit the editor to automatically execute copying operations. Please use the keyboard for that (Ctrl/Cmd+C).","cut":"Cut","cutError":"Your browser security settings don't permit the editor to automatically execute cutting operations. Please use the keyboard for that (Ctrl/Cmd+X).","paste":"Paste","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Paste Area","pasteMsg":"Paste your content inside the area below and press OK.","title":"Paste"},"button":{"selectedLabel":"%1 (Selected)"},"basicstyles":{"bold":"Bold","italic":"Italic","strike":"Strike Through","subscript":"Subscript","superscript":"Superscript","underline":"Underline"},"editor":"Rich Text Editor","editorPanel":"Rich Text Editor panel","common":{"editorHelp":"Press ALT 0 for help","browseServer":"Browse Server","url":"URL","protocol":"Protocol","upload":"Upload","uploadSubmit":"Send it to the Server","image":"Image","flash":"Flash","form":"Form","checkbox":"Checkbox","radio":"Radio Button","textField":"Text Field","textarea":"Textarea","hiddenField":"Hidden Field","button":"Button","select":"Selection Field","imageButton":"Image Button","notSet":"<not set>","id":"Id","name":"Name","langDir":"Language Direction","langDirLtr":"Left to Right (LTR)","langDirRtl":"Right to Left (RTL)","langCode":"Language Code","longDescr":"Long Description URL","cssClass":"Stylesheet Classes","advisoryTitle":"Advisory Title","cssStyle":"Style","ok":"OK","cancel":"Cancel","close":"Close","preview":"Preview","resize":"Resize","generalTab":"General","advancedTab":"Advanced","validateNumberFailed":"This value is not a number.","confirmNewPage":"Any unsaved changes to this content will be lost. Are you sure you want to load new page?","confirmCancel":"You have changed some options. Are you sure you want to close the dialog window?","options":"Options","target":"Target","targetNew":"New Window (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"Same Window (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Left to Right (LTR)","langDirRTL":"Right to Left (RTL)","styles":"Style","cssClasses":"Stylesheet Classes","width":"Width","height":"Height","align":"Align","left":"Left","right":"Right","center":"Centre","justify":"Justify","alignLeft":"Align LeftLine truncated
@@ -2,4 +2,4 @@
Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.lang['et']={"widget":{"move":"Click and drag to move","label":"%1 widget"},"undo":{"redo":"Toimingu kordamine","undo":"Tagasivõtmine"},"toolbar":{"toolbarCollapse":"Tööriistariba peitmine","toolbarExpand":"Tööriistariba näitamine","toolbarGroups":{"document":"Dokument","clipboard":"Lõikelaud/tagasivõtmine","editing":"Muutmine","forms":"Vormid","basicstyles":"Põhistiilid","paragraph":"Lõik","links":"Lingid","insert":"Sisesta","styles":"Stiilid","colors":"Värvid","tools":"Tööriistad"},"toolbars":"Redaktori tööriistaribad"},"sourcearea":{"toolbar":"Lähtekood"},"notification":{"closed":"Notification closed."},"list":{"bulletedlist":"Punktloend","numberedlist":"Numberloend"},"justify":{"block":"Rööpjoondus","center":"Keskjoondus","left":"Vasakjoondus","right":"Paremjoondus"},"indent":{"indent":"Taande suurendamine","outdent":"Taande vähendamine"},"font":{"fontSize":{"label":"Suurus","voiceLabel":"Kirja suurus","panelTitle":"Suurus"},"label":"Kiri","panelTitle":"Kiri","voiceLabel":"Kiri"},"elementspath":{"eleLabel":"Elementide asukoht","eleTitle":"%1 element"},"colordialog":{"clear":"Eemalda","highlight":"Näidis","options":"Värvi valikud","selected":"Valitud värv","title":"Värvi valimine"},"colorbutton":{"auto":"Automaatne","bgColorTitle":"Tausta värv","colors":{"000":"Must","800000":"Kastanpruun","8B4513":"Sadulapruun","2F4F4F":"Tume paehall","008080":"Sinakasroheline","000080":"Meresinine","4B0082":"Indigosinine","696969":"Tumehall","B22222":"Šamottkivi","A52A2A":"Pruun","DAA520":"Kuldkollane","006400":"Tumeroheline","40E0D0":"Türkiissinine","0000CD":"Keskmine sinine","800080":"Lilla","808080":"Hall","F00":"Punanae","FF8C00":"Tumeoranž","FFD700":"Kuldne","008000":"Roheline","0FF":"Tsüaniidsinine","00F":"Sinine","EE82EE":"Violetne","A9A9A9":"Tuhm hall","FFA07A":"Hele lõhe","FFA500":"Oranž","FFFF00":"Kollane","00FF00":"Lubja hall","AFEEEE":"Kahvatu türkiis","ADD8E6":"Helesinine","DDA0DD":"Ploomililla","D3D3D3":"Helehall","FFF0F5":"Lavendlipunane","FAEBD7":"Antiikvalge","FFFFE0":"Helekollane","F0FFF0":"Meloniroheline","F0FFFF":"Taevasinine","F0F8FF":"Beebisinine","E6E6FA":"Lavendel","FFF":"Valge","1ABC9C":"Strong Cyan","2ECC71":"Emerald","3498DB":"Bright Blue","9B59B6":"Amethyst","4E5F70":"Grayish Blue","F1C40F":"Vivid Yellow","16A085":"Dark Cyan","27AE60":"Dark Emerald","2980B9":"Strong Blue","8E44AD":"Dark Violet","2C3E50":"Desaturated Blue","F39C12":"Oraanž","E67E22":"Porgand","E74C3C":"Pale Red","ECF0F1":"Bright Silver","95A5A6":"Light Grayish Cyan","DDD":"Light Gray","D35400":"Pumpkin","C0392B":"Strong Red","BDC3C7":"Silver","7F8C8D":"Grayish Cyan","999":"Tume hall"},"more":"Rohkem värve...","panelTitle":"Värvid","textColorTitle":"Teksti värv"},"clipboard":{"copy":"Kopeeri","copyError":"Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt kopeerida. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+C).","cut":"Lõika","cutError":"Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).","paste":"Aseta","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Asetamise ala","pasteMsg":"Paste your content inside the area below and press OK.","title":"Asetamine"},"button":{"selectedLabel":"%1 (Selected)"},"basicstyles":{"bold":"Paks","italic":"Kursiiv","strike":"Läbijoonitud","subscript":"Allindeks","superscript":"Ülaindeks","underline":"Allajoonitud"},"editor":"Rikkalik tekstiredaktor","editorPanel":"Rikkaliku tekstiredaktori paneel","common":{"editorHelp":"Abi saamiseks vajuta ALT 0","browseServer":"Serveri sirvimine","url":"URL","protocol":"Protokoll","upload":"Laadi üles","uploadSubmit":"Saada serverisse","image":"Pilt","flash":"Flash","form":"Vorm","checkbox":"Märkeruut","radio":"Raadionupp","textField":"Tekstilahter","textarea":"Tekstiala","hiddenField":"Varjatud lahter","button":"Nupp","select":"Valiklahter","imageButton":"Piltnupp","notSet":"<määramata>","id":"ID","name":"Nimi","langDir":"Keele suund","langDirLtr":"Vasakult paremale (LTR)","langDirRtl":"Paremalt vasakule (RTL)","langCode":"Keele kood","longDescr":"Pikk kirjeldus URL","cssClass":"Stiilistiku klassid","advisoryTitle":"Soovituslik pealkiri","cssStyle":"Laad","ok":"Olgu","cancel":"Loobu","close":"Sulge","preview":"Eelvaade","resize":"Suuruse muutmiseks lohista","generalTab":"Üldine","advancedTab":"Täpsemalt","validateNumberFailed":"See väärtus pole number.","confirmNewPage":"Kõik salvestamata muudatused lähevad kaotsi. Kas oled kindel, et tahad laadida uue lehe?","confirmCancel":"Mõned valikud on muudetud. Kas oled kindel, et tahad dialoogi sulgeda?","options":"Valikud","target":"Sihtkoht","targetNew":"Uus aken (_blank)","targetTop":"Kõige ülemine aken (_top)","targetSelf":"Sama aken (_self)","targetParent":"Vanemaken (_parent)","langDirLTR":"Vasakult paremale (LTR)","langDirRTL":"Paremalt vaLine truncated
CKEDITOR.lang['et']={"widget":{"move":"Click and drag to move","label":"%1 vidin"},"undo":{"redo":"Toimingu kordamine","undo":"Tagasivõtmine"},"toolbar":{"toolbarCollapse":"Tööriistariba peitmine","toolbarExpand":"Tööriistariba näitamine","toolbarGroups":{"document":"Dokument","clipboard":"Lõikelaud/tagasivõtmine","editing":"Muutmine","forms":"Vormid","basicstyles":"Põhistiilid","paragraph":"Lõik","links":"Lingid","insert":"Sisesta","styles":"Stiilid","colors":"Värvid","tools":"Tööriistad"},"toolbars":"Redaktori tööriistaribad"},"sourcearea":{"toolbar":"Lähtekood"},"notification":{"closed":"Teavitused on suletud."},"list":{"bulletedlist":"Punktloend","numberedlist":"Numberloend"},"justify":{"block":"Rööpjoondus","center":"Keskjoondus","left":"Vasakjoondus","right":"Paremjoondus"},"indent":{"indent":"Taande suurendamine","outdent":"Taande vähendamine"},"font":{"fontSize":{"label":"Suurus","voiceLabel":"Kirja suurus","panelTitle":"Suurus"},"label":"Kiri","panelTitle":"Kiri","voiceLabel":"Kiri"},"elementspath":{"eleLabel":"Elementide asukoht","eleTitle":"%1 element"},"colordialog":{"clear":"Eemalda","highlight":"Näidis","options":"Värvi valikud","selected":"Valitud värv","title":"Värvi valimine"},"colorbutton":{"auto":"Automaatne","bgColorTitle":"Tausta värv","colors":{"000":"Must","800000":"Kastanpruun","8B4513":"Sadulapruun","2F4F4F":"Tume paehall","008080":"Sinakasroheline","000080":"Meresinine","4B0082":"Indigosinine","696969":"Tumehall","B22222":"Šamottkivi","A52A2A":"Pruun","DAA520":"Kuldkollane","006400":"Tumeroheline","40E0D0":"Türkiissinine","0000CD":"Keskmine sinine","800080":"Lilla","808080":"Hall","F00":"Punanae","FF8C00":"Tumeoranž","FFD700":"Kuldne","008000":"Roheline","0FF":"Tsüaniidsinine","00F":"Sinine","EE82EE":"Violetne","A9A9A9":"Tuhm hall","FFA07A":"Hele lõhe","FFA500":"Oranž","FFFF00":"Kollane","00FF00":"Lubja hall","AFEEEE":"Kahvatu türkiis","ADD8E6":"Helesinine","DDA0DD":"Ploomililla","D3D3D3":"Helehall","FFF0F5":"Lavendlipunane","FAEBD7":"Antiikvalge","FFFFE0":"Helekollane","F0FFF0":"Meloniroheline","F0FFFF":"Taevasinine","F0F8FF":"Beebisinine","E6E6FA":"Lavendel","FFF":"Valge","1ABC9C":"Strong Cyan","2ECC71":"Emerald","3498DB":"Bright Blue","9B59B6":"Amethyst","4E5F70":"Grayish Blue","F1C40F":"Vivid Yellow","16A085":"Dark Cyan","27AE60":"Dark Emerald","2980B9":"Strong Blue","8E44AD":"Dark Violet","2C3E50":"Desaturated Blue","F39C12":"Oraanž","E67E22":"Porgand","E74C3C":"Pale Red","ECF0F1":"Bright Silver","95A5A6":"Light Grayish Cyan","DDD":"Light Gray","D35400":"Pumpkin","C0392B":"Strong Red","BDC3C7":"Silver","7F8C8D":"Grayish Cyan","999":"Tume hall"},"more":"Rohkem värve...","panelTitle":"Värvid","textColorTitle":"Teksti värv"},"clipboard":{"copy":"Kopeeri","copyError":"Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt kopeerida. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+C).","cut":"Lõika","cutError":"Sinu veebisirvija turvaseaded ei luba redaktoril automaatselt lõigata. Palun kasutage selleks klaviatuuri klahvikombinatsiooni (Ctrl/Cmd+X).","paste":"Aseta","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Asetamise ala","pasteMsg":"Paste your content inside the area below and press OK.","title":"Asetamine"},"button":{"selectedLabel":"%1 (Selected)"},"basicstyles":{"bold":"Paks","italic":"Kursiiv","strike":"Läbijoonitud","subscript":"Allindeks","superscript":"Ülaindeks","underline":"Allajoonitud"},"editor":"Rikkalik tekstiredaktor","editorPanel":"Rikkaliku tekstiredaktori paneel","common":{"editorHelp":"Abi saamiseks vajuta ALT 0","browseServer":"Serveri sirvimine","url":"URL","protocol":"Protokoll","upload":"Laadi üles","uploadSubmit":"Saada serverisse","image":"Pilt","flash":"Flash","form":"Vorm","checkbox":"Märkeruut","radio":"Raadionupp","textField":"Tekstilahter","textarea":"Tekstiala","hiddenField":"Varjatud lahter","button":"Nupp","select":"Valiklahter","imageButton":"Piltnupp","notSet":"<määramata>","id":"ID","name":"Nimi","langDir":"Keele suund","langDirLtr":"Vasakult paremale (LTR)","langDirRtl":"Paremalt vasakule (RTL)","langCode":"Keele kood","longDescr":"Pikk kirjeldus URL","cssClass":"Stiilistiku klassid","advisoryTitle":"Soovituslik pealkiri","cssStyle":"Laad","ok":"Olgu","cancel":"Loobu","close":"Sulge","preview":"Eelvaade","resize":"Suuruse muutmiseks lohista","generalTab":"Üldine","advancedTab":"Täpsemalt","validateNumberFailed":"See väärtus pole number.","confirmNewPage":"Kõik salvestamata muudatused lähevad kaotsi. Kas oled kindel, et tahad laadida uue lehe?","confirmCancel":"Mõned valikud on muudetud. Kas oled kindel, et tahad dialoogi sulgeda?","options":"Valikud","target":"Sihtkoht","targetNew":"Uus aken (_blank)","targetTop":"Kõige ülemine aken (_top)","targetSelf":"Sama aken (_self)","targetParent":"Vanemaken (_parent)","langDirLTR":"Vasakult paremale (LTR)","langDirRTL":"Paremalt vLine truncated
Loaded 100 of 609 files, more files were not shown because too many files have changed in this diff. Show more