]> git.mxchange.org Git - friendica.git/blob - src/Module/Admin/Site.php
allow shorthands in the system.maximagesize
[friendica.git] / src / Module / Admin / Site.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Module\Admin;
23
24 use Friendica\App;
25 use Friendica\Core\Renderer;
26 use Friendica\Core\Search;
27 use Friendica\Core\System;
28 use Friendica\Core\Theme;
29 use Friendica\Core\Worker;
30 use Friendica\Database\DBA;
31 use Friendica\DI;
32 use Friendica\Model\Contact;
33 use Friendica\Model\User;
34 use Friendica\Module\BaseAdmin;
35 use Friendica\Module\Conversation\Community;
36 use Friendica\Module\Register;
37 use Friendica\Navigation\SystemMessages;
38 use Friendica\Protocol\Relay;
39 use Friendica\Util\BasePath;
40 use Friendica\Util\EMailer\MailBuilder;
41 use Friendica\Util\Strings;
42
43 class Site extends BaseAdmin
44 {
45 //      const SHORTHAND_REGEX = '/*/i';
46
47         protected function post(array $request = [])
48         {
49                 self::checkAdminAccess();
50
51                 self::checkFormSecurityTokenRedirectOnError('/admin/site', 'admin_site');
52
53                 $a = DI::app();
54
55                 if (!empty($_POST['republish_directory'])) {
56                         Worker::add(Worker::PRIORITY_LOW, 'Directory');
57                         return;
58                 }
59
60                 if (empty($_POST['page_site'])) {
61                         return;
62                 }
63
64                 $sitename         = (!empty($_POST['sitename'])         ? trim($_POST['sitename'])      : '');
65                 $sender_email     = (!empty($_POST['sender_email'])     ? trim($_POST['sender_email'])  : '');
66                 $banner           = (!empty($_POST['banner'])           ? trim($_POST['banner'])                             : false);
67                 $email_banner     = (!empty($_POST['email_banner'])     ? trim($_POST['email_banner'])                       : false);
68                 $shortcut_icon    = (!empty($_POST['shortcut_icon'])    ? trim($_POST['shortcut_icon']) : '');
69                 $touch_icon       = (!empty($_POST['touch_icon'])       ? trim($_POST['touch_icon'])    : '');
70                 $additional_info  = (!empty($_POST['additional_info'])  ? trim($_POST['additional_info'])                    : '');
71                 $language         = (!empty($_POST['language'])         ? trim($_POST['language'])      : '');
72                 $theme            = (!empty($_POST['theme'])            ? trim($_POST['theme'])         : '');
73                 $theme_mobile     = (!empty($_POST['theme_mobile'])     ? trim($_POST['theme_mobile'])  : '');
74                 $maximagesize     = (!empty($_POST['maximagesize'])     ? trim($_POST['maximagesize'])              : 0);
75                 $maximagelength   = (!empty($_POST['maximagelength'])   ? intval(trim($_POST['maximagelength']))             : -1);
76                 $jpegimagequality = (!empty($_POST['jpegimagequality']) ? intval(trim($_POST['jpegimagequality']))           : 100);
77
78                 $register_policy        = (!empty($_POST['register_policy'])         ? intval(trim($_POST['register_policy']))             : 0);
79                 $daily_registrations    = (!empty($_POST['max_daily_registrations']) ? intval(trim($_POST['max_daily_registrations']))     : 0);
80                 $abandon_days           = (!empty($_POST['abandon_days'])            ? intval(trim($_POST['abandon_days']))                : 0);
81
82                 $register_text          = (!empty($_POST['register_text'])           ? strip_tags(trim($_POST['register_text']))           : '');
83
84                 $allowed_sites          = (!empty($_POST['allowed_sites'])           ? trim($_POST['allowed_sites'])  : '');
85                 $allowed_email          = (!empty($_POST['allowed_email'])           ? trim($_POST['allowed_email'])  : '');
86                 $forbidden_nicknames    = (!empty($_POST['forbidden_nicknames'])     ? strtolower(trim($_POST['forbidden_nicknames'])) : '');
87                 $system_actor_name      = (!empty($_POST['system_actor_name'])       ? trim($_POST['system_actor_name']) : '');
88                 $no_oembed_rich_content = !empty($_POST['no_oembed_rich_content']);
89                 $allowed_oembed         = (!empty($_POST['allowed_oembed'])          ? trim($_POST['allowed_oembed']) : '');
90                 $block_public           = !empty($_POST['block_public']);
91                 $force_publish          = !empty($_POST['publish_all']);
92                 $global_directory       = (!empty($_POST['directory'])               ? trim($_POST['directory'])      : '');
93                 $newuser_private        = !empty($_POST['newuser_private']);
94                 $enotify_no_content     = !empty($_POST['enotify_no_content']);
95                 $private_addons         = !empty($_POST['private_addons']);
96                 $disable_embedded       = !empty($_POST['disable_embedded']);
97                 $allow_users_remote_self = !empty($_POST['allow_users_remote_self']);
98                 $explicit_content       = !empty($_POST['explicit_content']);
99                 $proxify_content        = !empty($_POST['proxify_content']);
100                 $cache_contact_avatar   = !empty($_POST['cache_contact_avatar']);
101
102                 $enable_multi_reg       = !empty($_POST['enable_multi_reg']);
103                 $enable_openid          = !empty($_POST['enable_openid']);
104                 $enable_regfullname     = !empty($_POST['enable_regfullname']);
105                 $register_notification  = !empty($_POST['register_notification']);
106                 $community_page_style   = (!empty($_POST['community_page_style']) ? intval(trim($_POST['community_page_style'])) : 0);
107                 $max_author_posts_community_page = (!empty($_POST['max_author_posts_community_page']) ? intval(trim($_POST['max_author_posts_community_page'])) : 0);
108
109                 $verifyssl              = !empty($_POST['verifyssl']);
110                 $proxyuser              = (!empty($_POST['proxyuser'])              ? trim($_POST['proxyuser']) : '');
111                 $proxy                  = (!empty($_POST['proxy'])                  ? trim($_POST['proxy'])     : '');
112                 $timeout                = (!empty($_POST['timeout'])                ? intval(trim($_POST['timeout']))                : 60);
113                 $maxloadavg             = (!empty($_POST['maxloadavg'])             ? intval(trim($_POST['maxloadavg']))             : 20);
114                 $min_memory             = (!empty($_POST['min_memory'])             ? intval(trim($_POST['min_memory']))             : 0);
115                 $optimize_tables        = (!empty($_POST['optimize_tables'])        ? intval(trim($_POST['optimize_tables']))        : false);
116                 $contact_discovery      = (!empty($_POST['contact_discovery'])      ? intval(trim($_POST['contact_discovery']))      : Contact\Relation::DISCOVERY_NONE);
117                 $synchronize_directory  = (!empty($_POST['synchronize_directory'])  ? intval(trim($_POST['synchronize_directory']))  : false);
118                 $poco_requery_days      = (!empty($_POST['poco_requery_days'])      ? intval(trim($_POST['poco_requery_days']))      : 7);
119                 $poco_discovery         = (!empty($_POST['poco_discovery'])         ? intval(trim($_POST['poco_discovery']))         : false);
120                 $poco_local_search      = !empty($_POST['poco_local_search']);
121                 $nodeinfo               = !empty($_POST['nodeinfo']);
122                 $mail_enabled           = !empty($_POST['mail_enabled']);
123                 $ostatus_enabled        = !empty($_POST['ostatus_enabled']);
124                 $diaspora_enabled       = !empty($_POST['diaspora_enabled']);
125                 $ssl_policy             = (!empty($_POST['ssl_policy'])             ? intval($_POST['ssl_policy'])                    : 0);
126                 $force_ssl              = !empty($_POST['force_ssl']);
127                 $show_help              = !empty($_POST['show_help']);
128                 $dbclean                = !empty($_POST['dbclean']);
129                 $dbclean_expire_days    = (!empty($_POST['dbclean_expire_days'])    ? intval($_POST['dbclean_expire_days'])           : 0);
130                 $dbclean_unclaimed      = (!empty($_POST['dbclean_unclaimed'])      ? intval($_POST['dbclean_unclaimed'])             : 0);
131                 $dbclean_expire_conv    = (!empty($_POST['dbclean_expire_conv'])    ? intval($_POST['dbclean_expire_conv'])           : 0);
132                 $suppress_tags          = !empty($_POST['suppress_tags']);
133                 $max_comments           = (!empty($_POST['max_comments'])           ? intval($_POST['max_comments'])                  : 0);
134                 $max_display_comments   = (!empty($_POST['max_display_comments'])   ? intval($_POST['max_display_comments'])          : 0);
135                 $temppath               = (!empty($_POST['temppath'])               ? trim($_POST['temppath'])   : '');
136                 $singleuser             = (!empty($_POST['singleuser'])             ? trim($_POST['singleuser']) : '');
137                 $only_tag_search        = !empty($_POST['only_tag_search']);
138                 $compute_group_counts   = !empty($_POST['compute_group_counts']);
139                 $check_new_version_url  = (!empty($_POST['check_new_version_url'])  ? trim($_POST['check_new_version_url']) : 'none');
140
141                 $worker_queues    = (!empty($_POST['worker_queues'])                ? intval($_POST['worker_queues'])                 : 10);
142                 $worker_fastlane  = !empty($_POST['worker_fastlane']);
143
144                 $relay_directly    = !empty($_POST['relay_directly']);
145                 $relay_scope       = (!empty($_POST['relay_scope'])       ? trim($_POST['relay_scope'])        : '');
146                 $relay_server_tags = (!empty($_POST['relay_server_tags']) ? trim($_POST['relay_server_tags'])  : '');
147                 $relay_deny_tags   = (!empty($_POST['relay_deny_tags'])   ? trim($_POST['relay_deny_tags'])    : '');
148                 $relay_user_tags   = !empty($_POST['relay_user_tags']);
149                 $active_panel      = (!empty($_POST['active_panel'])      ? "#" . trim($_POST['active_panel']) : '');
150
151                 // Has the directory url changed? If yes, then resubmit the existing profiles there
152                 if ($global_directory != DI::config()->get('system', 'directory') && ($global_directory != '')) {
153                         DI::config()->set('system', 'directory', $global_directory);
154                         Worker::add(Worker::PRIORITY_LOW, 'Directory');
155                 }
156
157                 if (DI::baseUrl()->getUrlPath() != "") {
158                         $diaspora_enabled = false;
159                 }
160                 if ($ssl_policy != intval(DI::config()->get('system', 'ssl_policy'))) {
161                         if ($ssl_policy == App\BaseURL::SSL_POLICY_FULL) {
162                                 DBA::e("UPDATE `contact` SET
163                                 `url`     = REPLACE(`url`    , 'http:' , 'https:'),
164                                 `photo`   = REPLACE(`photo`  , 'http:' , 'https:'),
165                                 `thumb`   = REPLACE(`thumb`  , 'http:' , 'https:'),
166                                 `micro`   = REPLACE(`micro`  , 'http:' , 'https:'),
167                                 `request` = REPLACE(`request`, 'http:' , 'https:'),
168                                 `notify`  = REPLACE(`notify` , 'http:' , 'https:'),
169                                 `poll`    = REPLACE(`poll`   , 'http:' , 'https:'),
170                                 `confirm` = REPLACE(`confirm`, 'http:' , 'https:'),
171                                 `poco`    = REPLACE(`poco`   , 'http:' , 'https:')
172                                 WHERE `self` = 1"
173                                 );
174                                 DBA::e("UPDATE `profile` SET
175                                 `photo`   = REPLACE(`photo`  , 'http:' , 'https:'),
176                                 `thumb`   = REPLACE(`thumb`  , 'http:' , 'https:')
177                                 WHERE 1 "
178                                 );
179                         } elseif ($ssl_policy == App\BaseURL::SSL_POLICY_SELFSIGN) {
180                                 DBA::e("UPDATE `contact` SET
181                                 `url`     = REPLACE(`url`    , 'https:' , 'http:'),
182                                 `photo`   = REPLACE(`photo`  , 'https:' , 'http:'),
183                                 `thumb`   = REPLACE(`thumb`  , 'https:' , 'http:'),
184                                 `micro`   = REPLACE(`micro`  , 'https:' , 'http:'),
185                                 `request` = REPLACE(`request`, 'https:' , 'http:'),
186                                 `notify`  = REPLACE(`notify` , 'https:' , 'http:'),
187                                 `poll`    = REPLACE(`poll`   , 'https:' , 'http:'),
188                                 `confirm` = REPLACE(`confirm`, 'https:' , 'http:'),
189                                 `poco`    = REPLACE(`poco`   , 'https:' , 'http:')
190                                 WHERE `self` = 1"
191                                 );
192                                 DBA::e("UPDATE `profile` SET
193                                 `photo`   = REPLACE(`photo`  , 'https:' , 'http:'),
194                                 `thumb`   = REPLACE(`thumb`  , 'https:' , 'http:')
195                                 WHERE 1 "
196                                 );
197                         }
198                 }
199                 DI::config()->set('system', 'ssl_policy'            , $ssl_policy);
200                 DI::config()->set('system', 'maxloadavg'            , $maxloadavg);
201                 DI::config()->set('system', 'min_memory'            , $min_memory);
202                 DI::config()->set('system', 'optimize_tables'       , $optimize_tables);
203                 DI::config()->set('system', 'contact_discovery'     , $contact_discovery);
204                 DI::config()->set('system', 'synchronize_directory' , $synchronize_directory);
205                 DI::config()->set('system', 'poco_requery_days'     , $poco_requery_days);
206                 DI::config()->set('system', 'poco_discovery'        , $poco_discovery);
207                 DI::config()->set('system', 'poco_local_search'     , $poco_local_search);
208                 DI::config()->set('system', 'nodeinfo'              , $nodeinfo);
209                 DI::config()->set('config', 'sitename'              , $sitename);
210                 DI::config()->set('config', 'sender_email'          , $sender_email);
211                 DI::config()->set('system', 'suppress_tags'         , $suppress_tags);
212                 DI::config()->set('system', 'shortcut_icon'         , $shortcut_icon);
213                 DI::config()->set('system', 'touch_icon'            , $touch_icon);
214
215                 if ($banner == "") {
216                         DI::config()->delete('system', 'banner');
217                 } else {
218                         DI::config()->set('system', 'banner', $banner);
219                 }
220
221                 if (empty($email_banner)) {
222                         DI::config()->delete('system', 'email_banner');
223                 } else {
224                         DI::config()->set('system', 'email_banner', $email_banner);
225                 }
226
227                 if (empty($additional_info)) {
228                         DI::config()->delete('config', 'info');
229                 } else {
230                         DI::config()->set('config', 'info', $additional_info);
231                 }
232                 DI::config()->set('system', 'language', $language);
233                 DI::config()->set('system', 'theme', $theme);
234                 Theme::install($theme);
235
236                 if ($theme_mobile == '---') {
237                         DI::config()->delete('system', 'mobile-theme');
238                 } else {
239                         DI::config()->set('system', 'mobile-theme', $theme_mobile);
240                 }
241                 if ($singleuser == '---') {
242                         DI::config()->delete('system', 'singleuser');
243                 } else {
244                         DI::config()->set('system', 'singleuser', $singleuser);
245                 }
246                 if (preg_match('/\d+(?:\s*[kmg])?/i', $maximagesize)) {
247                         DI::config()->set('system', 'maximagesize', $maximagesize);
248                 } else {
249                         DI::sysmsg()->addNotice(DI::l10n()->t('%s is no valid input for maximum image size', $maximagesize));
250                 }
251                 DI::config()->set('system', 'max_image_length'       , $maximagelength);
252                 DI::config()->set('system', 'jpeg_quality'           , $jpegimagequality);
253
254                 DI::config()->set('config', 'register_policy'        , $register_policy);
255                 DI::config()->set('system', 'max_daily_registrations', $daily_registrations);
256                 DI::config()->set('system', 'account_abandon_days'   , $abandon_days);
257                 DI::config()->set('config', 'register_text'          , $register_text);
258                 DI::config()->set('system', 'allowed_sites'          , $allowed_sites);
259                 DI::config()->set('system', 'allowed_email'          , $allowed_email);
260                 DI::config()->set('system', 'forbidden_nicknames'    , $forbidden_nicknames);
261                 DI::config()->set('system', 'system_actor_name'      , $system_actor_name);
262                 DI::config()->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content);
263                 DI::config()->set('system', 'allowed_oembed'         , $allowed_oembed);
264                 DI::config()->set('system', 'block_public'           , $block_public);
265                 DI::config()->set('system', 'publish_all'            , $force_publish);
266                 DI::config()->set('system', 'newuser_private'        , $newuser_private);
267                 DI::config()->set('system', 'enotify_no_content'     , $enotify_no_content);
268                 DI::config()->set('system', 'disable_embedded'       , $disable_embedded);
269                 DI::config()->set('system', 'allow_users_remote_self', $allow_users_remote_self);
270                 DI::config()->set('system', 'explicit_content'       , $explicit_content);
271                 DI::config()->set('system', 'proxify_content'        , $proxify_content);
272                 DI::config()->set('system', 'cache_contact_avatar'   , $cache_contact_avatar);
273                 DI::config()->set('system', 'check_new_version_url'  , $check_new_version_url);
274
275                 DI::config()->set('system', 'block_extended_register', !$enable_multi_reg);
276                 DI::config()->set('system', 'no_openid'              , !$enable_openid);
277                 DI::config()->set('system', 'no_regfullname'         , !$enable_regfullname);
278                 DI::config()->set('system', 'register_notification'  , $register_notification);
279                 DI::config()->set('system', 'community_page_style'   , $community_page_style);
280                 DI::config()->set('system', 'max_author_posts_community_page', $max_author_posts_community_page);
281                 DI::config()->set('system', 'verifyssl'              , $verifyssl);
282                 DI::config()->set('system', 'proxyuser'              , $proxyuser);
283                 DI::config()->set('system', 'proxy'                  , $proxy);
284                 DI::config()->set('system', 'curl_timeout'           , $timeout);
285                 DI::config()->set('system', 'imap_disabled'          , !$mail_enabled && function_exists('imap_open'));
286                 DI::config()->set('system', 'ostatus_disabled'       , !$ostatus_enabled);
287                 DI::config()->set('system', 'diaspora_enabled'       , $diaspora_enabled);
288
289                 DI::config()->set('config', 'private_addons'         , $private_addons);
290
291                 DI::config()->set('system', 'force_ssl'              , $force_ssl);
292                 DI::config()->set('system', 'hide_help'              , !$show_help);
293
294                 DI::config()->set('system', 'dbclean'                , $dbclean);
295                 DI::config()->set('system', 'dbclean-expire-days'    , $dbclean_expire_days);
296                 DI::config()->set('system', 'dbclean_expire_conversation', $dbclean_expire_conv);
297
298                 if ($dbclean_unclaimed == 0) {
299                         $dbclean_unclaimed = $dbclean_expire_days;
300                 }
301
302                 DI::config()->set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
303
304                 DI::config()->set('system', 'max_comments', $max_comments);
305                 DI::config()->set('system', 'max_display_comments', $max_display_comments);
306
307                 if ($temppath != '') {
308                         $temppath = BasePath::getRealPath($temppath);
309                 }
310
311                 DI::config()->set('system', 'temppath', $temppath);
312
313                 DI::config()->set('system', 'only_tag_search'  , $only_tag_search);
314                 DI::config()->set('system', 'compute_group_counts', $compute_group_counts);
315
316                 DI::config()->set('system', 'worker_queues'    , $worker_queues);
317                 DI::config()->set('system', 'worker_fastlane'  , $worker_fastlane);
318
319                 DI::config()->set('system', 'relay_directly'   , $relay_directly);
320                 DI::config()->set('system', 'relay_scope'      , $relay_scope);
321                 DI::config()->set('system', 'relay_server_tags', $relay_server_tags);
322                 DI::config()->set('system', 'relay_deny_tags'  , $relay_deny_tags);
323                 DI::config()->set('system', 'relay_user_tags'  , $relay_user_tags);
324
325                 DI::baseUrl()->redirect('admin/site' . $active_panel);
326         }
327
328         protected function content(array $request = []): string
329         {
330                 parent::content();
331
332                 /* Installed langs */
333                 $lang_choices = DI::l10n()->getAvailableLanguages();
334
335                 if (DI::config()->get('system', 'directory_submit_url') &&
336                         !DI::config()->get('system', 'directory')) {
337                         DI::config()->set('system', 'directory', dirname(DI::config()->get('system', 'directory_submit_url')));
338                         DI::config()->delete('system', 'directory_submit_url');
339                 }
340
341                 /* Installed themes */
342                 $theme_choices = [];
343                 $theme_choices_mobile = [];
344                 $theme_choices_mobile['---'] = DI::l10n()->t('No special theme for mobile devices');
345                 $files = glob('view/theme/*');
346                 if (is_array($files)) {
347                         $allowed_theme_list = DI::config()->get('system', 'allowed_themes');
348
349                         foreach ($files as $file) {
350                                 if (intval(file_exists($file . '/unsupported'))) {
351                                         continue;
352                                 }
353
354                                 $f = basename($file);
355
356                                 // Only show allowed themes here
357                                 if (($allowed_theme_list != '') && !strstr($allowed_theme_list, $f)) {
358                                         continue;
359                                 }
360
361                                 $theme_name = ((file_exists($file . '/experimental')) ? DI::l10n()->t('%s - (Experimental)', $f) : $f);
362
363                                 if (file_exists($file . '/mobile')) {
364                                         $theme_choices_mobile[$f] = $theme_name;
365                                 } else {
366                                         $theme_choices[$f] = $theme_name;
367                                 }
368                         }
369                 }
370
371                 /* Community page style */
372                 $community_page_style_choices = [
373                         Community::DISABLED         => DI::l10n()->t('No community page'),
374                         Community::DISABLED_VISITOR => DI::l10n()->t('No community page for visitors'),
375                         Community::LOCAL            => DI::l10n()->t('Public postings from users of this site'),
376                         Community::GLOBAL           => DI::l10n()->t('Public postings from the federated network'),
377                         Community::LOCAL_AND_GLOBAL => DI::l10n()->t('Public postings from local users and the federated network')
378                 ];
379
380                 /* get user names to make the install a personal install of X */
381                 // @TODO Move to Model\User::getNames()
382                 $user_names = [];
383                 $user_names['---'] = DI::l10n()->t('Multi user instance');
384
385                 $usersStmt = DBA::select('user', ['username', 'nickname'], ['account_removed' => 0, 'account_expired' => 0]);
386                 foreach (DBA::toArray($usersStmt) as $user) {
387                         $user_names[$user['nickname']] = $user['username'];
388                 }
389
390                 /* Banner */
391                 $banner = DI::config()->get('system', 'banner');
392
393                 if ($banner == false) {
394                         $banner = '<a href="https://friendi.ca"><img id="logo-img" width="32" height="32" src="images/friendica.svg" alt="logo" /></a><span id="logo-text"><a href="https://friendi.ca">Friendica</a></span>';
395                 }
396
397                 $email_banner = DI::config()->get('system', 'email_banner');
398
399                 if ($email_banner == false) {
400                         $email_banner = MailBuilder::DEFAULT_EMAIL_BANNER;
401                 }
402
403                 $additional_info = DI::config()->get('config', 'info');
404
405                 // Automatically create temporary paths
406                 System::getTempPath();
407
408                 /* Register policy */
409                 $register_choices = [
410                         Register::CLOSED => DI::l10n()->t('Closed'),
411                         Register::APPROVE => DI::l10n()->t('Requires approval'),
412                         Register::OPEN => DI::l10n()->t('Open')
413                 ];
414
415                 $ssl_choices = [
416                         App\BaseURL::SSL_POLICY_NONE => DI::l10n()->t('No SSL policy, links will track page SSL state'),
417                         App\BaseURL::SSL_POLICY_FULL => DI::l10n()->t('Force all links to use SSL'),
418                         App\BaseURL::SSL_POLICY_SELFSIGN => DI::l10n()->t('Self-signed certificate, use SSL for local links only (discouraged)')
419                 ];
420
421                 $check_git_version_choices = [
422                         'none' => DI::l10n()->t('Don\'t check'),
423                         'stable' => DI::l10n()->t('check the stable version'),
424                         'develop' => DI::l10n()->t('check the development version')
425                 ];
426
427                 $discovery_choices = [
428                         Contact\Relation::DISCOVERY_NONE => DI::l10n()->t('none'),
429                         Contact\Relation::DISCOVERY_LOCAL => DI::l10n()->t('Local contacts'),
430                         Contact\Relation::DISCOVERY_INTERACTOR => DI::l10n()->t('Interactors'),
431                         // "All" is deactivated until we are sure not to put too much stress on the fediverse with this
432                         // ContactRelation::DISCOVERY_ALL => DI::l10n()->t('All'),
433                 ];
434
435                 $diaspora_able = (DI::baseUrl()->getUrlPath() == '');
436
437                 $t = Renderer::getMarkupTemplate('admin/site.tpl');
438                 return Renderer::replaceMacros($t, [
439                         '$title'             => DI::l10n()->t('Administration'),
440                         '$page'              => DI::l10n()->t('Site'),
441                         '$general_info'      => DI::l10n()->t('General Information'),
442                         '$submit'            => DI::l10n()->t('Save Settings'),
443                         '$republish'         => DI::l10n()->t('Republish users to directory'),
444                         '$registration'      => DI::l10n()->t('Registration'),
445                         '$upload'            => DI::l10n()->t('File upload'),
446                         '$corporate'         => DI::l10n()->t('Policies'),
447                         '$advanced'          => DI::l10n()->t('Advanced'),
448                         '$portable_contacts' => DI::l10n()->t('Auto Discovered Contact Directory'),
449                         '$performance'       => DI::l10n()->t('Performance'),
450                         '$worker_title'      => DI::l10n()->t('Worker'),
451                         '$relay_title'       => DI::l10n()->t('Message Relay'),
452                         '$relay_description' => DI::l10n()->t('Use the command "console relay" in the command line to add or remove relays.'),
453                         '$no_relay_list'     => DI::l10n()->t('The system is not subscribed to any relays at the moment.'),
454                         '$relay_list_title'  => DI::l10n()->t('The system is currently subscribed to the following relays:'),
455                         '$relay_list'        => Relay::getList(['url']),
456                         '$relocate'          => DI::l10n()->t('Relocate Node'),
457                         '$relocate_msg'      => DI::l10n()->t('Relocating your node enables you to change the DNS domain of this node and keep all the existing users and posts. This process takes a while and can only be started from the relocate console command like this:'),
458                         '$relocate_cmd'      => DI::l10n()->t('(Friendica directory)# bin/console relocate https://newdomain.com'),
459                         '$baseurl'           => DI::baseUrl()->get(true),
460
461                         // name, label, value, help string, extra data...
462                         '$sitename'         => ['sitename', DI::l10n()->t('Site name'), DI::config()->get('config', 'sitename'), ''],
463                         '$sender_email'     => ['sender_email', DI::l10n()->t('Sender Email'), DI::config()->get('config', 'sender_email'), DI::l10n()->t('The email address your server shall use to send notification emails from.'), '', '', 'email'],
464                         '$system_actor_name' => ['system_actor_name', DI::l10n()->t('Name of the system actor'), User::getActorName(), DI::l10n()->t("Name of the internal system account that is used to perform ActivityPub requests. This must be an unused username. If set, this can't be changed again.")],
465                         '$banner'           => ['banner', DI::l10n()->t('Banner/Logo'), $banner, ''],
466                         '$email_banner'     => ['email_banner', DI::l10n()->t('Email Banner/Logo'), $email_banner, ''],
467                         '$shortcut_icon'    => ['shortcut_icon', DI::l10n()->t('Shortcut icon'), DI::config()->get('system', 'shortcut_icon'), DI::l10n()->t('Link to an icon that will be used for browsers.')],
468                         '$touch_icon'       => ['touch_icon', DI::l10n()->t('Touch icon'), DI::config()->get('system', 'touch_icon'), DI::l10n()->t('Link to an icon that will be used for tablets and mobiles.')],
469                         '$additional_info'  => ['additional_info', DI::l10n()->t('Additional Info'), $additional_info, DI::l10n()->t('For public servers: you can add additional information here that will be listed at %s/servers.', Search::getGlobalDirectory())],
470                         '$language'         => ['language', DI::l10n()->t('System language'), DI::config()->get('system', 'language'), '', $lang_choices],
471                         '$theme'            => ['theme', DI::l10n()->t('System theme'), DI::config()->get('system', 'theme'), DI::l10n()->t('Default system theme - may be over-ridden by user profiles - <a href="%s" id="cnftheme">Change default theme settings</a>', DI::baseUrl()->get(true) . '/admin/themes'), $theme_choices],
472                         '$theme_mobile'     => ['theme_mobile', DI::l10n()->t('Mobile system theme'), DI::config()->get('system', 'mobile-theme', '---'), DI::l10n()->t('Theme for mobile devices'), $theme_choices_mobile],
473                         '$ssl_policy'       => ['ssl_policy', DI::l10n()->t('SSL link policy'), DI::config()->get('system', 'ssl_policy'), DI::l10n()->t('Determines whether generated links should be forced to use SSL'), $ssl_choices],
474                         '$force_ssl'        => ['force_ssl', DI::l10n()->t('Force SSL'), DI::config()->get('system', 'force_ssl'), DI::l10n()->t('Force all Non-SSL requests to SSL - Attention: on some systems it could lead to endless loops.')],
475                         '$show_help'        => ['show_help', DI::l10n()->t('Show help entry from navigation menu'), !DI::config()->get('system', 'hide_help'), DI::l10n()->t('Displays the menu entry for the Help pages from the navigation menu. It is always accessible by calling /help directly.')],
476                         '$singleuser'       => ['singleuser', DI::l10n()->t('Single user instance'), DI::config()->get('system', 'singleuser', '---'), DI::l10n()->t('Make this instance multi-user or single-user for the named user'), $user_names],
477
478                         '$maximagesize'     => ['maximagesize', DI::l10n()->t('Maximum image size'), DI::config()->get('system', 'maximagesize'), DI::l10n()->t('Maximum size in bytes of uploaded images. Default is 0, which means no limits.
479                                                                                                         The value of <code>upload_max_filesize</code> in your <code>PHP.ini</code> needs be set to at least the desired limit.
480                                                                                                         Currently <code>upload_max_filesize</code> is set to %s (%sB)', Strings::getBytesFromShorthand(ini_get('upload_max_filesize')), ini_get('upload_max_filesize')),
481                                                                                                         '', '', '', '\d+(?:\s*[kmg])?'],
482                         '$maximagelength'   => ['maximagelength', DI::l10n()->t('Maximum image length'), DI::config()->get('system', 'max_image_length'), DI::l10n()->t('Maximum length in pixels of the longest side of uploaded images. Default is -1, which means no limits.')],
483                         '$jpegimagequality' => ['jpegimagequality', DI::l10n()->t('JPEG image quality'), DI::config()->get('system', 'jpeg_quality'), DI::l10n()->t('Uploaded JPEGS will be saved at this quality setting [0-100]. Default is 100, which is full quality.')],
484
485                         '$register_policy'        => ['register_policy', DI::l10n()->t('Register policy'), DI::config()->get('config', 'register_policy'), '', $register_choices],
486                         '$daily_registrations'    => ['max_daily_registrations', DI::l10n()->t('Maximum Daily Registrations'), DI::config()->get('system', 'max_daily_registrations'), DI::l10n()->t('If registration is permitted above, this sets the maximum number of new user registrations to accept per day.  If register is set to closed, this setting has no effect.')],
487                         '$register_text'          => ['register_text', DI::l10n()->t('Register text'), DI::config()->get('config', 'register_text'), DI::l10n()->t('Will be displayed prominently on the registration page. You can use BBCode here.')],
488                         '$forbidden_nicknames'    => ['forbidden_nicknames', DI::l10n()->t('Forbidden Nicknames'), DI::config()->get('system', 'forbidden_nicknames'), DI::l10n()->t('Comma separated list of nicknames that are forbidden from registration. Preset is a list of role names according RFC 2142.')],
489                         '$abandon_days'           => ['abandon_days', DI::l10n()->t('Accounts abandoned after x days'), DI::config()->get('system', 'account_abandon_days'), DI::l10n()->t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')],
490                         '$allowed_sites'          => ['allowed_sites', DI::l10n()->t('Allowed friend domains'), DI::config()->get('system', 'allowed_sites'), DI::l10n()->t('Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains')],
491                         '$allowed_email'          => ['allowed_email', DI::l10n()->t('Allowed email domains'), DI::config()->get('system', 'allowed_email'), DI::l10n()->t('Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains')],
492                         '$no_oembed_rich_content' => ['no_oembed_rich_content', DI::l10n()->t('No OEmbed rich content'), DI::config()->get('system', 'no_oembed_rich_content'), DI::l10n()->t('Don\'t show the rich content (e.g. embedded PDF), except from the domains listed below.')],
493                         '$allowed_oembed'         => ['allowed_oembed', DI::l10n()->t('Trusted third-party domains'), DI::config()->get('system', 'allowed_oembed'), DI::l10n()->t('Comma separated list of domains from which content is allowed to be embedded in posts like with OEmbed. All sub-domains of the listed domains are allowed as well.')],
494                         '$block_public'           => ['block_public', DI::l10n()->t('Block public'), DI::config()->get('system', 'block_public'), DI::l10n()->t('Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.')],
495                         '$force_publish'          => ['publish_all', DI::l10n()->t('Force publish'), DI::config()->get('system', 'publish_all'), DI::l10n()->t('Check to force all profiles on this site to be listed in the site directory.') . '<strong>' . DI::l10n()->t('Enabling this may violate privacy laws like the GDPR') . '</strong>'],
496                         '$global_directory'       => ['directory', DI::l10n()->t('Global directory URL'), DI::config()->get('system', 'directory'), DI::l10n()->t('URL to the global directory. If this is not set, the global directory is completely unavailable to the application.')],
497                         '$newuser_private'        => ['newuser_private', DI::l10n()->t('Private posts by default for new users'), DI::config()->get('system', 'newuser_private'), DI::l10n()->t('Set default post permissions for all new members to the default privacy group rather than public.')],
498                         '$enotify_no_content'     => ['enotify_no_content', DI::l10n()->t('Don\'t include post content in email notifications'), DI::config()->get('system', 'enotify_no_content'), DI::l10n()->t('Don\'t include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.')],
499                         '$private_addons'         => ['private_addons', DI::l10n()->t('Disallow public access to addons listed in the apps menu.'), DI::config()->get('config', 'private_addons'), DI::l10n()->t('Checking this box will restrict addons listed in the apps menu to members only.')],
500                         '$disable_embedded'       => ['disable_embedded', DI::l10n()->t('Don\'t embed private images in posts'), DI::config()->get('system', 'disable_embedded'), DI::l10n()->t('Don\'t replace locally-hosted private photos in posts with an embedded copy of the image. This means that contacts who receive posts containing private photos will have to authenticate and load each image, which may take a while.')],
501                         '$explicit_content'       => ['explicit_content', DI::l10n()->t('Explicit Content'), DI::config()->get('system', 'explicit_content'), DI::l10n()->t('Set this to announce that your node is used mostly for explicit content that might not be suited for minors. This information will be published in the node information and might be used, e.g. by the global directory, to filter your node from listings of nodes to join. Additionally a note about this will be shown at the user registration page.')],
502                         '$proxify_content'        => ['proxify_content', DI::l10n()->t('Proxify external content'), DI::config()->get('system', 'proxify_content'), DI::l10n()->t('Route external content via the proxy functionality. This is used for example for some OEmbed accesses and in some other rare cases.')],
503                         '$cache_contact_avatar'   => ['cache_contact_avatar', DI::l10n()->t('Cache contact avatars'), DI::config()->get('system', 'cache_contact_avatar'), DI::l10n()->t('Locally store the avatar pictures of the contacts. This uses a lot of storage space but it increases the performance.')],
504                         '$allow_users_remote_self'=> ['allow_users_remote_self', DI::l10n()->t('Allow Users to set remote_self'), DI::config()->get('system', 'allow_users_remote_self'), DI::l10n()->t('With checking this, every user is allowed to mark every contact as a remote_self in the repair contact dialog. Setting this flag on a contact causes mirroring every posting of that contact in the users stream.')],
505                         '$enable_multi_reg'       => ['enable_multi_reg', DI::l10n()->t('Enable multiple registrations'), !DI::config()->get('system', 'block_extended_register'), DI::l10n()->t('Enable users to register additional accounts for use as pages.')],
506                         '$enable_openid'          => ['enable_openid', DI::l10n()->t('Enable OpenID'), !DI::config()->get('system', 'no_openid'), DI::l10n()->t('Enable OpenID support for registration and logins.')],
507                         '$enable_regfullname'     => ['enable_regfullname', DI::l10n()->t('Enable Fullname check'), !DI::config()->get('system', 'no_regfullname'), DI::l10n()->t('Enable check to only allow users to register with a space between the first name and the last name in their full name.')],
508                         '$register_notification'  => ['register_notification', DI::l10n()->t('Email administrators on new registration'), DI::config()->get('system', 'register_notification'), DI::l10n()->t('If enabled and the system is set to an open registration, an email for each new registration is sent to the administrators.')],
509                         '$community_page_style'   => ['community_page_style', DI::l10n()->t('Community pages for visitors'), DI::config()->get('system', 'community_page_style'), DI::l10n()->t('Which community pages should be available for visitors. Local users always see both pages.'), $community_page_style_choices],
510                         '$max_author_posts_community_page' => ['max_author_posts_community_page', DI::l10n()->t('Posts per user on community page'), DI::config()->get('system', 'max_author_posts_community_page'), DI::l10n()->t('The maximum number of posts per user on the community page. (Not valid for "Global Community")')],
511                         '$mail_able'              => function_exists('imap_open'),
512                         '$mail_enabled'           => ['mail_enabled', DI::l10n()->t('Enable Mail support'), !DI::config()->get('system', 'imap_disabled', !function_exists('imap_open')), DI::l10n()->t('Enable built-in mail support to poll IMAP folders and to reply via mail.')],
513                         '$mail_not_able'          => DI::l10n()->t('Mail support can\'t be enabled because the PHP IMAP module is not installed.'),
514                         '$ostatus_enabled'        => ['ostatus_enabled', DI::l10n()->t('Enable OStatus support'), !DI::config()->get('system', 'ostatus_disabled'), DI::l10n()->t('Enable built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public.')],
515                         '$diaspora_able'          => $diaspora_able,
516                         '$diaspora_not_able'      => DI::l10n()->t('Diaspora support can\'t be enabled because Friendica was installed into a sub directory.'),
517                         '$diaspora_enabled'       => ['diaspora_enabled', DI::l10n()->t('Enable Diaspora support'), DI::config()->get('system', 'diaspora_enabled', $diaspora_able), DI::l10n()->t('Enable built-in Diaspora network compatibility for communicating with diaspora servers.')],
518                         '$verifyssl'              => ['verifyssl', DI::l10n()->t('Verify SSL'), DI::config()->get('system', 'verifyssl'), DI::l10n()->t('If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites.')],
519                         '$proxyuser'              => ['proxyuser', DI::l10n()->t('Proxy user'), DI::config()->get('system', 'proxyuser'), DI::l10n()->t('User name for the proxy server.')],
520                         '$proxy'                  => ['proxy', DI::l10n()->t('Proxy URL'), DI::config()->get('system', 'proxy'), DI::l10n()->t('If you want to use a proxy server that Friendica should use to connect to the network, put the URL of the proxy here.')],
521                         '$timeout'                => ['timeout', DI::l10n()->t('Network timeout'), DI::config()->get('system', 'curl_timeout'), DI::l10n()->t('Value is in seconds. Set to 0 for unlimited (not recommended).')],
522                         '$maxloadavg'             => ['maxloadavg', DI::l10n()->t('Maximum Load Average'), DI::config()->get('system', 'maxloadavg'), DI::l10n()->t('Maximum system load before delivery and poll processes are deferred - default %d.', 20)],
523                         '$min_memory'             => ['min_memory', DI::l10n()->t('Minimal Memory'), DI::config()->get('system', 'min_memory'), DI::l10n()->t('Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 (deactivated).')],
524                         '$optimize_tables'        => ['optimize_tables', DI::l10n()->t('Periodically optimize tables'), DI::config()->get('system', 'optimize_tables'), DI::l10n()->t('Periodically optimize tables like the cache and the workerqueue')],
525
526                         '$contact_discovery'      => ['contact_discovery', DI::l10n()->t('Discover followers/followings from contacts'), DI::config()->get('system', 'contact_discovery'), DI::l10n()->t('If enabled, contacts are checked for their followers and following contacts.') . '<ul>' .
527                                 '<li>' . DI::l10n()->t('None - deactivated') . '</li>' .
528                                 '<li>' . DI::l10n()->t('Local contacts - contacts of our local contacts are discovered for their followers/followings.') . '</li>' .
529                                 '<li>' . DI::l10n()->t('Interactors - contacts of our local contacts and contacts who interacted on locally visible postings are discovered for their followers/followings.') . '</li></ul>',
530                                 $discovery_choices],
531                         '$synchronize_directory'  => ['synchronize_directory', DI::l10n()->t('Synchronize the contacts with the directory server'), DI::config()->get('system', 'synchronize_directory'), DI::l10n()->t('if enabled, the system will check periodically for new contacts on the defined directory server.')],
532
533                         '$poco_requery_days'      => ['poco_requery_days', DI::l10n()->t('Days between requery'), DI::config()->get('system', 'poco_requery_days'), DI::l10n()->t('Number of days after which a server is requeried for his contacts.')],
534                         '$poco_discovery'         => ['poco_discovery', DI::l10n()->t('Discover contacts from other servers'), DI::config()->get('system', 'poco_discovery'), DI::l10n()->t('Periodically query other servers for contacts. The system queries Friendica, Mastodon and Hubzilla servers.')],
535                         '$poco_local_search'      => ['poco_local_search', DI::l10n()->t('Search the local directory'), DI::config()->get('system', 'poco_local_search'), DI::l10n()->t('Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated.')],
536
537                         '$nodeinfo'               => ['nodeinfo', DI::l10n()->t('Publish server information'), DI::config()->get('system', 'nodeinfo'), DI::l10n()->t('If enabled, general server and usage data will be published. The data contains the name and version of the server, number of users with public profiles, number of posts and the activated protocols and connectors. See <a href="http://the-federation.info/">the-federation.info</a> for details.')],
538
539                         '$check_new_version_url'  => ['check_new_version_url', DI::l10n()->t('Check upstream version'), DI::config()->get('system', 'check_new_version_url'), DI::l10n()->t('Enables checking for new Friendica versions at github. If there is a new version, you will be informed in the admin panel overview.'), $check_git_version_choices],
540                         '$suppress_tags'          => ['suppress_tags', DI::l10n()->t('Suppress Tags'), DI::config()->get('system', 'suppress_tags'), DI::l10n()->t('Suppress showing a list of hashtags at the end of the posting.')],
541                         '$dbclean'                => ['dbclean', DI::l10n()->t('Clean database'), DI::config()->get('system', 'dbclean'), DI::l10n()->t('Remove old remote items, orphaned database records and old content from some other helper tables.')],
542                         '$dbclean_expire_days'    => ['dbclean_expire_days', DI::l10n()->t('Lifespan of remote items'), DI::config()->get('system', 'dbclean-expire-days'), DI::l10n()->t('When the database cleanup is enabled, this defines the days after which remote items will be deleted. Own items, and marked or filed items are always kept. 0 disables this behaviour.')],
543                         '$dbclean_unclaimed'      => ['dbclean_unclaimed', DI::l10n()->t('Lifespan of unclaimed items'), DI::config()->get('system', 'dbclean-expire-unclaimed'), DI::l10n()->t('When the database cleanup is enabled, this defines the days after which unclaimed remote items (mostly content from the relay) will be deleted. Default value is 90 days. Defaults to the general lifespan value of remote items if set to 0.')],
544                         '$dbclean_expire_conv'    => ['dbclean_expire_conv', DI::l10n()->t('Lifespan of raw conversation data'), DI::config()->get('system', 'dbclean_expire_conversation'), DI::l10n()->t('The conversation data is used for ActivityPub and OStatus, as well as for debug purposes. It should be safe to remove it after 14 days, default is 90 days.')],
545                         '$max_comments'           => ['max_comments', DI::l10n()->t('Maximum numbers of comments per post'), DI::config()->get('system', 'max_comments'), DI::l10n()->t('How much comments should be shown for each post? Default value is 100.')],
546                         '$max_display_comments'   => ['max_display_comments', DI::l10n()->t('Maximum numbers of comments per post on the display page'), DI::config()->get('system', 'max_display_comments'), DI::l10n()->t('How many comments should be shown on the single view for each post? Default value is 1000.')],
547                         '$temppath'               => ['temppath', DI::l10n()->t('Temp path'), DI::config()->get('system', 'temppath'), DI::l10n()->t('If you have a restricted system where the webserver can\'t access the system temp path, enter another path here.')],
548                         '$only_tag_search'        => ['only_tag_search', DI::l10n()->t('Only search in tags'), DI::config()->get('system', 'only_tag_search'), DI::l10n()->t('On large systems the text search can slow down the system extremely.')],
549                         '$compute_group_counts'   => ['compute_group_counts', DI::l10n()->t('Generate counts per contact group when calculating network count'), DI::config()->get('system', 'compute_group_counts'), DI::l10n()->t('On systems with users that heavily use contact groups the query can be very expensive.')],
550
551                         '$worker_queues'          => ['worker_queues', DI::l10n()->t('Maximum number of parallel workers'), DI::config()->get('system', 'worker_queues'), DI::l10n()->t('On shared hosters set this to %d. On larger systems, values of %d are great. Default value is %d.', 5, 20, 10)],
552                         '$worker_fastlane'        => ['worker_fastlane', DI::l10n()->t('Enable fastlane'), DI::config()->get('system', 'worker_fastlane'), DI::l10n()->t('When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.')],
553
554                         '$relay_directly'         => ['relay_directly', DI::l10n()->t('Direct relay transfer'), DI::config()->get('system', 'relay_directly'), DI::l10n()->t('Enables the direct transfer to other servers without using the relay servers')],
555                         '$relay_scope'            => ['relay_scope', DI::l10n()->t('Relay scope'), DI::config()->get('system', 'relay_scope'), DI::l10n()->t('Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts with selected tags should be received.'), [Relay::SCOPE_NONE => DI::l10n()->t('Disabled'), Relay::SCOPE_ALL => DI::l10n()->t('all'), Relay::SCOPE_TAGS => DI::l10n()->t('tags')]],
556                         '$relay_server_tags'      => ['relay_server_tags', DI::l10n()->t('Server tags'), DI::config()->get('system', 'relay_server_tags'), DI::l10n()->t('Comma separated list of tags for the "tags" subscription.')],
557                         '$relay_deny_tags'        => ['relay_deny_tags', DI::l10n()->t('Deny Server tags'), DI::config()->get('system', 'relay_deny_tags'), DI::l10n()->t('Comma separated list of tags that are rejected.')],
558                         '$relay_user_tags'        => ['relay_user_tags', DI::l10n()->t('Allow user tags'), DI::config()->get('system', 'relay_user_tags'), DI::l10n()->t('If enabled, the tags from the saved searches will used for the "tags" subscription in addition to the "relay_server_tags".')],
559
560                         '$form_security_token'    => self::getFormSecurityToken('admin_site'),
561                         '$relocate_button'        => DI::l10n()->t('Start Relocation'),
562                 ]);
563         }
564 }