]> git.mxchange.org Git - friendica.git/blob - mod/settings.php
642229de0b578428bbb9c58c2cf86b5d63519be9
[friendica.git] / mod / settings.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 use Friendica\App;
23 use Friendica\BaseModule;
24 use Friendica\Content\Feature;
25 use Friendica\Content\Nav;
26 use Friendica\Core\ACL;
27 use Friendica\Core\Hook;
28 use Friendica\Core\Logger;
29 use Friendica\Core\Renderer;
30 use Friendica\Core\Worker;
31 use Friendica\Database\DBA;
32 use Friendica\DI;
33 use Friendica\Model\Group;
34 use Friendica\Model\Item;
35 use Friendica\Model\Notification;
36 use Friendica\Model\Profile;
37 use Friendica\Model\User;
38 use Friendica\Model\Verb;
39 use Friendica\Module\BaseSettings;
40 use Friendica\Module\Security\Login;
41 use Friendica\Protocol\Activity;
42 use Friendica\Protocol\Email;
43 use Friendica\Util\Temporal;
44 use Friendica\Worker\Delivery;
45
46 function settings_init(App $a)
47 {
48         if (!local_user()) {
49                 notice(DI::l10n()->t('Permission denied.'));
50                 return;
51         }
52
53         BaseSettings::createAside();
54 }
55
56 function settings_post(App $a)
57 {
58         if (!$a->isLoggedIn()) {
59                 notice(DI::l10n()->t('Permission denied.'));
60                 return;
61         }
62
63         if (!empty($_SESSION['submanage'])) {
64                 return;
65         }
66
67         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'addon')) {
68                 BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_addon');
69
70                 Hook::callAll('addon_settings_post', $_POST);
71                 DI::baseUrl()->redirect(DI::args()->getQueryString());
72                 return;
73         }
74
75         $user = User::getById($a->getLoggedInUserId());
76
77         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'connectors')) {
78                 BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_connectors');
79
80                 if (!empty($_POST['general-submit'])) {
81                         DI::pConfig()->set(local_user(), 'system', 'accept_only_sharer', intval($_POST['accept_only_sharer']));
82                         DI::pConfig()->set(local_user(), 'system', 'disable_cw', !intval($_POST['enable_cw']));
83                         DI::pConfig()->set(local_user(), 'system', 'no_intelligent_shortening', !intval($_POST['enable_smart_shortening']));
84                         DI::pConfig()->set(local_user(), 'system', 'simple_shortening', intval($_POST['simple_shortening']));
85                         DI::pConfig()->set(local_user(), 'system', 'attach_link_title', intval($_POST['attach_link_title']));
86                         DI::pConfig()->set(local_user(), 'ostatus', 'legacy_contact', $_POST['legacy_contact']);
87                 } elseif (!empty($_POST['mail-submit'])) {
88                         $mail_server       =                 $_POST['mail_server']       ?? '';
89                         $mail_port         =                 $_POST['mail_port']         ?? '';
90                         $mail_ssl          = strtolower(trim($_POST['mail_ssl']          ?? ''));
91                         $mail_user         =                 $_POST['mail_user']         ?? '';
92                         $mail_pass         =            trim($_POST['mail_pass']         ?? '');
93                         $mail_action       =            trim($_POST['mail_action']       ?? '');
94                         $mail_movetofolder =            trim($_POST['mail_movetofolder'] ?? '');
95                         $mail_replyto      =                 $_POST['mail_replyto']      ?? '';
96                         $mail_pubmail      =                 $_POST['mail_pubmail']      ?? '';
97
98                         if (function_exists('imap_open') && !DI::config()->get('system', 'imap_disabled')) {
99                                 if (!DBA::exists('mailacct', ['uid' => local_user()])) {
100                                         DBA::insert('mailacct', ['uid' => local_user()]);
101                                 }
102                                 if (strlen($mail_pass)) {
103                                         $pass = '';
104                                         openssl_public_encrypt($mail_pass, $pass, $user['pubkey']);
105                                         DBA::update('mailacct', ['pass' => bin2hex($pass)], ['uid' => local_user()]);
106                                 }
107
108                                 $r = DBA::update('mailacct', [
109                                         'server'       => $mail_server,
110                                         'port'         => $mail_port,
111                                         'ssltype'      => $mail_ssl,
112                                         'user'         => $mail_user,
113                                         'action'       => $mail_action,
114                                         'movetofolder' => $mail_movetofolder,
115                                         'mailbox'      => 'INBOX',
116                                         'reply_to'     => $mail_replyto,
117                                         'pubmail'      => $mail_pubmail
118                                 ], ['uid' => local_user()]);
119
120                                 Logger::notice('updating mailaccount', ['response' => $r]);
121                                 $mailacct = DBA::selectFirst('mailacct', [], ['uid' => local_user()]);
122                                 if (DBA::isResult($mailacct)) {
123                                         $mb = Email::constructMailboxName($mailacct);
124
125                                         if (strlen($mailacct['server'])) {
126                                                 $dcrpass = '';
127                                                 openssl_private_decrypt(hex2bin($mailacct['pass']), $dcrpass, $user['prvkey']);
128                                                 $mbox = Email::connect($mb, $mail_user, $dcrpass);
129                                                 unset($dcrpass);
130                                                 if (!$mbox) {
131                                                         notice(DI::l10n()->t('Failed to connect with email account using the settings provided.'));
132                                                 }
133                                         }
134                                 }
135                         }
136                 }
137
138                 Hook::callAll('connector_settings_post', $_POST);
139                 DI::baseUrl()->redirect(DI::args()->getQueryString());
140                 return;
141         }
142
143         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'features')) {
144                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/features', 'settings_features');
145                 foreach ($_POST as $k => $v) {
146                         if (strpos($k, 'feature_') === 0) {
147                                 DI::pConfig()->set(local_user(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0));
148                         }
149                 }
150                 return;
151         }
152
153         BaseModule::checkFormSecurityTokenRedirectOnError('/settings', 'settings');
154
155         // Import Contacts from CSV file
156         if (!empty($_POST['importcontact-submit'])) {
157                 if (isset($_FILES['importcontact-filename'])) {
158                         // was there an error
159                         if ($_FILES['importcontact-filename']['error'] > 0) {
160                                 Logger::notice('Contact CSV file upload error', ['error' => $_FILES['importcontact-filename']['error']]);
161                                 notice(DI::l10n()->t('Contact CSV file upload error'));
162                         } else {
163                                 $csvArray = array_map('str_getcsv', file($_FILES['importcontact-filename']['tmp_name']));
164                                 Logger::notice('Import started', ['lines' => count($csvArray)]);
165                                 // import contacts
166                                 foreach ($csvArray as $csvRow) {
167                                         // The 1st row may, or may not contain the headers of the table
168                                         // We expect the 1st field of the row to contain either the URL
169                                         // or the handle of the account, therefore we check for either
170                                         // "http" or "@" to be present in the string.
171                                         // All other fields from the row will be ignored
172                                         if ((strpos($csvRow[0],'@') !== false) || in_array(parse_url($csvRow[0], PHP_URL_SCHEME), ['http', 'https'])) {
173                                                 Worker::add(PRIORITY_LOW, 'AddContact', $_SESSION['uid'], $csvRow[0]);
174                                         } else {
175                                                 Logger::notice('Invalid account', ['url' => $csvRow[0]]);
176                                         }
177                                 }
178                                 Logger::notice('Import done');
179
180                                 info(DI::l10n()->t('Importing Contacts done'));
181                                 // delete temp file
182                                 unlink($_FILES['importcontact-filename']['tmp_name']);
183                         }
184                 } else {
185                         Logger::notice('Import triggered, but no import file was found.');
186                 }
187
188                 return;
189         }
190
191         if (!empty($_POST['resend_relocate'])) {
192                 Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, local_user());
193                 info(DI::l10n()->t("Relocate message has been send to your contacts"));
194                 DI::baseUrl()->redirect('settings');
195         }
196
197         Hook::callAll('settings_post', $_POST);
198
199         if (!empty($_POST['password']) || !empty($_POST['confirm'])) {
200                 $newpass = $_POST['password'];
201                 $confirm = $_POST['confirm'];
202
203                 try {
204                         if ($newpass != $confirm) {
205                                 throw new Exception(DI::l10n()->t('Passwords do not match.'));
206                         }
207
208                         //  check if the old password was supplied correctly before changing it to the new value
209                         User::getIdFromPasswordAuthentication(local_user(), $_POST['opassword']);
210
211                         $result = User::updatePassword(local_user(), $newpass);
212                         if (!DBA::isResult($result)) {
213                                 throw new Exception(DI::l10n()->t('Password update failed. Please try again.'));
214                         }
215
216                         info(DI::l10n()->t('Password changed.'));
217                 } catch (Exception $e) {
218                         notice($e->getMessage());
219                         notice(DI::l10n()->t('Password unchanged.'));
220                 }
221         }
222
223         $username         = (!empty($_POST['username'])        ? trim($_POST['username'])          : '');
224         $email            = (!empty($_POST['email'])           ? trim($_POST['email'])             : '');
225         $timezone         = (!empty($_POST['timezone'])        ? trim($_POST['timezone'])          : '');
226         $language         = (!empty($_POST['language'])        ? trim($_POST['language'])          : '');
227
228         $defloc           = (!empty($_POST['defloc'])          ? trim($_POST['defloc'])            : '');
229         $maxreq           = (!empty($_POST['maxreq'])          ? intval($_POST['maxreq'])          : 0);
230         $expire           = (!empty($_POST['expire'])          ? intval($_POST['expire'])          : 0);
231         $def_gid          = (!empty($_POST['group-selection']) ? intval($_POST['group-selection']) : 0);
232
233
234         $expire_items     = (!empty($_POST['expire_items']) ? intval($_POST['expire_items'])     : 0);
235         $expire_notes     = (!empty($_POST['expire_notes']) ? intval($_POST['expire_notes'])     : 0);
236         $expire_starred   = (!empty($_POST['expire_starred']) ? intval($_POST['expire_starred']) : 0);
237         $expire_photos    = (!empty($_POST['expire_photos'])? intval($_POST['expire_photos'])    : 0);
238         $expire_network_only    = (!empty($_POST['expire_network_only'])? intval($_POST['expire_network_only'])  : 0);
239
240         $delete_openid    = ((!empty($_POST['delete_openid']) && (intval($_POST['delete_openid']) == 1)) ? 1: 0);
241
242         $allow_location   = ((!empty($_POST['allow_location']) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
243         $publish          = ((!empty($_POST['profile_in_directory']) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
244         $net_publish      = ((!empty($_POST['profile_in_netdirectory']) && (intval($_POST['profile_in_netdirectory']) == 1)) ? 1: 0);
245         $account_type     = ((!empty($_POST['account-type']) && (intval($_POST['account-type']))) ? intval($_POST['account-type']) : 0);
246         $page_flags       = ((!empty($_POST['page-flags']) && (intval($_POST['page-flags']))) ? intval($_POST['page-flags']) : 0);
247         $blockwall        = ((!empty($_POST['blockwall']) && (intval($_POST['blockwall']) == 1)) ? 0: 1); // this setting is inverted!
248         $blocktags        = ((!empty($_POST['blocktags']) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
249         $unkmail          = ((!empty($_POST['unkmail']) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
250         $cntunkmail       = (!empty($_POST['cntunkmail']) ? intval($_POST['cntunkmail']) : 0);
251         $hide_friends     = (($_POST['hide-friends'] == 1) ? 1: 0);
252         $hidewall         = (($_POST['hidewall'] == 1) ? 1: 0);
253         $unlisted         = (($_POST['unlisted'] == 1) ? 1: 0);
254         $accessiblephotos = (($_POST['accessible-photos'] == 1) ? 1: 0);
255
256         $notify_like      = (($_POST['notify_like'] == 1) ? 1 : 0);
257         $notify_announce  = (($_POST['notify_announce'] == 1) ? 1 : 0);
258
259         $email_textonly   = (($_POST['email_textonly'] == 1) ? 1 : 0);
260         $detailed_notif   = (($_POST['detailed_notif'] == 1) ? 1 : 0);
261
262         $notify_ignored   = (($_POST['notify_ignored'] == 1) ? 1 : 0);
263
264         $notify = 0;
265
266         if (!empty($_POST['notify1'])) {
267                 $notify += intval($_POST['notify1']);
268         }
269         if (!empty($_POST['notify2'])) {
270                 $notify += intval($_POST['notify2']);
271         }
272         if (!empty($_POST['notify3'])) {
273                 $notify += intval($_POST['notify3']);
274         }
275         if (!empty($_POST['notify4'])) {
276                 $notify += intval($_POST['notify4']);
277         }
278         if (!empty($_POST['notify5'])) {
279                 $notify += intval($_POST['notify5']);
280         }
281         if (!empty($_POST['notify6'])) {
282                 $notify += intval($_POST['notify6']);
283         }
284         if (!empty($_POST['notify7'])) {
285                 $notify += intval($_POST['notify7']);
286         }
287         if (!empty($_POST['notify8'])) {
288                 $notify += intval($_POST['notify8']);
289         }
290
291         // Adjust the page flag if the account type doesn't fit to the page flag.
292         if (($account_type == User::ACCOUNT_TYPE_PERSON) && !in_array($page_flags, [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE])) {
293                 $page_flags = User::PAGE_FLAGS_NORMAL;
294         } elseif (($account_type == User::ACCOUNT_TYPE_ORGANISATION) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
295                 $page_flags = User::PAGE_FLAGS_SOAPBOX;
296         } elseif (($account_type == User::ACCOUNT_TYPE_NEWS) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
297                 $page_flags = User::PAGE_FLAGS_SOAPBOX;
298         } elseif (($account_type == User::ACCOUNT_TYPE_COMMUNITY) && !in_array($page_flags, [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP])) {
299                 $page_flags = User::PAGE_FLAGS_COMMUNITY;
300         }
301
302         $err = '';
303
304         if ($username != $user['username']) {
305                 if (strlen($username) > 40) {
306                         $err .= DI::l10n()->t('Please use a shorter name.');
307                 }
308                 if (strlen($username) < 3) {
309                         $err .= DI::l10n()->t('Name too short.');
310                 }
311         }
312
313         if ($email != $user['email']) {
314                 //  check for the correct password
315                 try {
316                         User::getIdFromPasswordAuthentication(local_user(), $_POST['mpassword']);
317                 } catch (Exception $ex) {
318                         $err .= DI::l10n()->t('Wrong Password.');
319                         $email = $user['email'];
320                 }
321                 //  check the email is valid
322                 if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
323                         $err .= DI::l10n()->t('Invalid email.');
324                 }
325                 //  ensure new email is not the admin mail
326                 if (DI::config()->get('config', 'admin_email')) {
327                         $adminlist = explode(",", str_replace(" ", "", strtolower(DI::config()->get('config', 'admin_email'))));
328                         if (in_array(strtolower($email), $adminlist)) {
329                                 $err .= DI::l10n()->t('Cannot change to that email.');
330                                 $email = $user['email'];
331                         }
332                 }
333         }
334
335         if (strlen($err)) {
336                 notice($err);
337                 return;
338         }
339
340         if (($timezone != $user['timezone']) && strlen($timezone)) {
341                 $a->setTimeZone($timezone);
342         }
343
344         $aclFormatter = DI::aclFormatter();
345
346         $str_group_allow   = !empty($_POST['group_allow'])   ? $aclFormatter->toString($_POST['group_allow'])   : '';
347         $str_contact_allow = !empty($_POST['contact_allow']) ? $aclFormatter->toString($_POST['contact_allow']) : '';
348         $str_group_deny    = !empty($_POST['group_deny'])    ? $aclFormatter->toString($_POST['group_deny'])    : '';
349         $str_contact_deny  = !empty($_POST['contact_deny'])  ? $aclFormatter->toString($_POST['contact_deny'])  : '';
350
351         DI::pConfig()->set(local_user(), 'expire', 'items', $expire_items);
352         DI::pConfig()->set(local_user(), 'expire', 'notes', $expire_notes);
353         DI::pConfig()->set(local_user(), 'expire', 'starred', $expire_starred);
354         DI::pConfig()->set(local_user(), 'expire', 'photos', $expire_photos);
355         DI::pConfig()->set(local_user(), 'expire', 'network_only', $expire_network_only);
356
357         // Reset like notifications when they are going to be shown again
358         if (!DI::pConfig()->get(local_user(), 'system', 'notify_like') && $notify_like) {
359                 DI::notification()->setAllSeenForUser(local_user(), ['vid' => Verb::getID(Activity::LIKE)]);
360         }
361
362         DI::pConfig()->set(local_user(), 'system', 'notify_like', $notify_like);
363
364         // Reset share notifications when they are going to be shown again
365         if (!DI::pConfig()->get(local_user(), 'system', 'notify_announce') && $notify_announce) {
366                 DI::notification()->setAllSeenForUser(local_user(), ['vid' => Verb::getID(Activity::ANNOUNCE)]);
367         }
368
369         DI::pConfig()->set(local_user(), 'system', 'notify_announce', $notify_announce);
370
371         DI::pConfig()->set(local_user(), 'system', 'email_textonly', $email_textonly);
372         DI::pConfig()->set(local_user(), 'system', 'detailed_notif', $detailed_notif);
373         DI::pConfig()->set(local_user(), 'system', 'notify_ignored', $notify_ignored);
374         DI::pConfig()->set(local_user(), 'system', 'unlisted', $unlisted);
375         DI::pConfig()->set(local_user(), 'system', 'accessible-photos', $accessiblephotos);
376
377         if ($account_type == User::ACCOUNT_TYPE_COMMUNITY) {
378                 $str_group_allow   = '';
379                 $str_contact_allow = '';
380                 $str_group_deny    = '';
381                 $str_contact_deny  = '';
382
383                 DI::pConfig()->set(local_user(), 'system', 'unlisted', true);
384
385                 $blockwall    = true;
386                 $blocktags    = true;
387                 $hide_friends = true;
388         }
389
390         if ($page_flags == User::PAGE_FLAGS_PRVGROUP) {
391                 $str_group_allow = '<' . Group::FOLLOWERS . '>';
392         }
393
394         $fields = ['username' => $username, 'email' => $email, 'timezone' => $timezone,
395                 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_group_allow, 'deny_cid' => $str_contact_deny, 'deny_gid' => $str_group_deny,
396                 'notify-flags' => $notify, 'page-flags' => $page_flags, 'account-type' => $account_type, 'default-location' => $defloc,
397                 'allow_location' => $allow_location, 'maxreq' => $maxreq, 'expire' => $expire, 'def_gid' => $def_gid, 'blockwall' => $blockwall,
398                 'hidewall' => $hidewall, 'blocktags' => $blocktags, 'unkmail' => $unkmail, 'cntunkmail' => $cntunkmail, 'language' => $language];
399
400         if ($delete_openid) {
401                 $fields['openid'] = '';
402                 $fields['openidserver'] = '';
403         }
404
405         $profile_fields = ['publish' => $publish, 'net-publish' => $net_publish, 'hide-friends' => $hide_friends];
406
407         if (!User::update($fields, local_user()) || !Profile::update($profile_fields, local_user())) {
408                 notice(DI::l10n()->t('Settings were not updated.'));
409         }
410
411         // clear session language
412         unset($_SESSION['language']);
413
414         DI::baseUrl()->redirect('settings');
415         return; // NOTREACHED
416 }
417
418
419 function settings_content(App $a)
420 {
421         $o = '';
422         Nav::setSelected('settings');
423
424         if (!local_user()) {
425                 //notice(DI::l10n()->t('Permission denied.'));
426                 return Login::form();
427         }
428
429         if (!empty($_SESSION['submanage'])) {
430                 notice(DI::l10n()->t('Permission denied.'));
431                 return '';
432         }
433
434         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'oauth')) {
435                 if ((DI::args()->getArgc() > 3) && (DI::args()->getArgv()[2] === 'delete')) {
436                         BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth', 't');
437
438                         DBA::delete('application-token', ['application-id' => DI::args()->getArgv()[3], 'uid' => local_user()]);
439                         DI::baseUrl()->redirect('settings/oauth/', true);
440                         return '';
441                 }
442
443                 $applications = DBA::selectToArray('application-view', ['id', 'uid', 'name', 'website', 'scopes', 'created_at'], ['uid' => local_user()]);
444
445                 $tpl = Renderer::getMarkupTemplate('settings/oauth.tpl');
446                 $o .= Renderer::replaceMacros($tpl, [
447                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
448                         '$baseurl'             => DI::baseUrl()->get(true),
449                         '$title'               => DI::l10n()->t('Connected Apps'),
450                         '$name'                => DI::l10n()->t('Name'),
451                         '$website'             => DI::l10n()->t('Home Page'),
452                         '$created_at'          => DI::l10n()->t('Created'),
453                         '$delete'              => DI::l10n()->t('Remove authorization'),
454                         '$apps'                => $applications,
455                 ]);
456                 return $o;
457         }
458
459         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'addon')) {
460                 $addon_settings_forms = [];
461                 foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'addon_settings']) as $hook) {
462                         $data = [];
463                         Hook::callSingle(DI::app(), 'addon_settings', [$hook['file'], $hook['function']], $data);
464
465                         if (!empty($data['href'])) {
466                                 $tpl = Renderer::getMarkupTemplate('settings/addon/link.tpl');
467                                 $addon_settings_forms[] = Renderer::replaceMacros($tpl, [
468                                         '$addon' => $data['addon'],
469                                         '$title' => $data['title'],
470                                         '$href'  => $data['href'],
471                                 ]);
472                         } elseif(!empty($data['addon'])) {
473                                 $tpl = Renderer::getMarkupTemplate('settings/addon/panel.tpl');
474                                 $addon_settings_forms[$data['addon']] = Renderer::replaceMacros($tpl, [
475                                         '$addon'  => $data['addon'],
476                                         '$title'  => $data['title'],
477                                         '$open'   => (DI::args()->getArgv()[2] ?? '') === $data['addon'],
478                                         '$html'   => $data['html'] ?? '',
479                                         '$submit' => $data['submit'] ?? DI::l10n()->t('Save Settings'),
480                                 ]);
481                         }
482                 }
483
484                 $tpl = Renderer::getMarkupTemplate('settings/addons.tpl');
485                 $o .= Renderer::replaceMacros($tpl, [
486                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_addon"),
487                         '$title'        => DI::l10n()->t('Addon Settings'),
488                         '$no_addons_settings_configured' => DI::l10n()->t('No Addon settings configured'),
489                         '$addon_settings_forms' => $addon_settings_forms,
490                 ]);
491                 return $o;
492         }
493
494         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'features')) {
495
496                 $arr = [];
497                 $features = Feature::get();
498                 foreach ($features as $fname => $fdata) {
499                         $arr[$fname] = [];
500                         $arr[$fname][0] = $fdata[0];
501                         foreach (array_slice($fdata,1) as $f) {
502                                 $arr[$fname][1][] = ['feature_' . $f[0], $f[1], Feature::isEnabled(local_user(), $f[0]), $f[2]];
503                         }
504                 }
505
506                 $tpl = Renderer::getMarkupTemplate('settings/features.tpl');
507                 $o .= Renderer::replaceMacros($tpl, [
508                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_features"),
509                         '$title'               => DI::l10n()->t('Additional Features'),
510                         '$features'            => $arr,
511                         '$submit'              => DI::l10n()->t('Save Settings'),
512                 ]);
513                 return $o;
514         }
515
516         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'connectors')) {
517                 $accept_only_sharer        = intval(DI::pConfig()->get(local_user(), 'system', 'accept_only_sharer'));
518                 $enable_cw                 = !intval(DI::pConfig()->get(local_user(), 'system', 'disable_cw'));
519                 $enable_smart_shortening   = !intval(DI::pConfig()->get(local_user(), 'system', 'no_intelligent_shortening'));
520                 $simple_shortening         = intval(DI::pConfig()->get(local_user(), 'system', 'simple_shortening'));
521                 $attach_link_title         = intval(DI::pConfig()->get(local_user(), 'system', 'attach_link_title'));
522                 $legacy_contact            = DI::pConfig()->get(local_user(), 'ostatus', 'legacy_contact');
523
524                 if (!empty($legacy_contact)) {
525                         /// @todo Isn't it supposed to be a $a->internalRedirect() call?
526                         DI::page()['htmlhead'] = '<meta http-equiv="refresh" content="0; URL=' . DI::baseUrl().'/ostatus_subscribe?url=' . urlencode($legacy_contact) . '">';
527                 }
528
529                 $connector_settings_forms = [];
530                 foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'connector_settings']) as $hook) {
531                         $data = [];
532                         Hook::callSingle(DI::app(), 'connector_settings', [$hook['file'], $hook['function']], $data);
533
534                         $tpl = Renderer::getMarkupTemplate('settings/addon/connector.tpl');
535                         $connector_settings_forms[$data['connector']] = Renderer::replaceMacros($tpl, [
536                                 '$connector' => $data['connector'],
537                                 '$title'     => $data['title'],
538                                 '$image'     => $data['image'] ?? '',
539                                 '$enabled'   => $data['enabled'] ?? true,
540                                 '$open'      => (DI::args()->getArgv()[2] ?? '') === $data['connector'],
541                                 '$html'      => $data['html'] ?? '',
542                                 '$submit'    => $data['submit'] ?? DI::l10n()->t('Save Settings'),
543                         ]);
544                 }
545
546                 if ($a->isSiteAdmin()) {
547                         $diasp_enabled = DI::l10n()->t('Built-in support for %s connectivity is %s', DI::l10n()->t('Diaspora (Socialhome, Hubzilla)'), ((DI::config()->get('system', 'diaspora_enabled')) ? DI::l10n()->t('enabled') : DI::l10n()->t('disabled')));
548                         $ostat_enabled = DI::l10n()->t('Built-in support for %s connectivity is %s', DI::l10n()->t('OStatus (GNU Social)'), ((DI::config()->get('system', 'ostatus_disabled')) ? DI::l10n()->t('disabled') : DI::l10n()->t('enabled')));
549                 } else {
550                         $diasp_enabled = "";
551                         $ostat_enabled = "";
552                 }
553
554                 $mail_disabled = ((function_exists('imap_open') && (!DI::config()->get('system', 'imap_disabled'))) ? 0 : 1);
555                 if (!$mail_disabled) {
556                         $mailacct = DBA::selectFirst('mailacct', [], ['uid' => local_user()]);
557                 } else {
558                         $mailacct = null;
559                 }
560
561                 $mail_server       = $mailacct['server'] ?? '';
562                 $mail_port         = (!empty($mailacct['port']) && is_numeric($mailacct['port'])) ? (int)$mailacct['port'] : '';
563                 $mail_ssl          = $mailacct['ssltype'] ?? '';
564                 $mail_user         = $mailacct['user'] ?? '';
565                 $mail_replyto      = $mailacct['reply_to'] ?? '';
566                 $mail_pubmail      = $mailacct['pubmail'] ?? 0;
567                 $mail_action       = $mailacct['action'] ?? 0;
568                 $mail_movetofolder = $mailacct['movetofolder'] ?? '';
569                 $mail_chk          = $mailacct['last_check'] ?? DBA::NULL_DATETIME;
570
571
572                 $tpl = Renderer::getMarkupTemplate('settings/connectors.tpl');
573
574                 $mail_disabled_message = ($mail_disabled ? DI::l10n()->t('Email access is disabled on this site.') : '');
575
576                 $ssl_options = ['TLS' => 'TLS', 'SSL' => 'SSL'];
577
578                 if (DI::config()->get('system', 'insecure_imap')) {
579                         $ssl_options['notls'] = DI::l10n()->t('None');
580                 }
581
582                 $o .= Renderer::replaceMacros($tpl, [
583                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_connectors"),
584
585                         '$title'        => DI::l10n()->t('Social Networks'),
586
587                         '$diasp_enabled' => $diasp_enabled,
588                         '$ostat_enabled' => $ostat_enabled,
589
590                         '$general_settings' => DI::l10n()->t('General Social Media Settings'),
591                         '$accept_only_sharer' => [
592                                 'accept_only_sharer',
593                                 DI::l10n()->t('Followed content scope'),
594                                 $accept_only_sharer,
595                                 DI::l10n()->t('By default, conversations in which your follows participated but didn\'t start will be shown in your timeline. You can turn this behavior off, or expand it to the conversations in which your follows liked a post.'),
596                                 [
597                                         Item::COMPLETION_NONE    => DI::l10n()->t('Only conversations my follows started'),
598                                         Item::COMPLETION_COMMENT => DI::l10n()->t('Conversations my follows started or commented on (default)'),
599                                         Item::COMPLETION_LIKE    => DI::l10n()->t('Any conversation my follows interacted with, including likes'),
600                                 ]
601                         ],
602                         '$enable_cw' => ['enable_cw', DI::l10n()->t('Enable Content Warning'), $enable_cw, DI::l10n()->t('Users on networks like Mastodon or Pleroma are able to set a content warning field which collapse their post by default. This enables the automatic collapsing instead of setting the content warning as the post title. Doesn\'t affect any other content filtering you eventually set up.')],
603                         '$enable_smart_shortening' => ['enable_smart_shortening', DI::l10n()->t('Enable intelligent shortening'), $enable_smart_shortening, DI::l10n()->t('Normally the system tries to find the best link to add to shortened posts. If disabled, every shortened post will always point to the original friendica post.')],
604                         '$simple_shortening' => ['simple_shortening', DI::l10n()->t('Enable simple text shortening'), $simple_shortening, DI::l10n()->t('Normally the system shortens posts at the next line feed. If this option is enabled then the system will shorten the text at the maximum character limit.')],
605                         '$attach_link_title' => ['attach_link_title', DI::l10n()->t('Attach the link title'), $attach_link_title, DI::l10n()->t('When activated, the title of the attached link will be added as a title on posts to Diaspora. This is mostly helpful with "remote-self" contacts that share feed content.')],
606                         '$legacy_contact' => ['legacy_contact', DI::l10n()->t('Your legacy ActivityPub/GNU Social account'), $legacy_contact, DI::l10n()->t("If you enter your old account name from an ActivityPub based system or your GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done.")],
607
608                         '$repair_ostatus_url' => DI::baseUrl() . '/repair_ostatus',
609                         '$repair_ostatus_text' => DI::l10n()->t('Repair OStatus subscriptions'),
610
611                         '$connector_settings_forms' => $connector_settings_forms,
612
613                         '$h_mail' => DI::l10n()->t('Email/Mailbox Setup'),
614                         '$mail_desc' => DI::l10n()->t("If you wish to communicate with email contacts using this service \x28optional\x29, please specify how to connect to your mailbox."),
615                         '$mail_lastcheck' => ['mail_lastcheck', DI::l10n()->t('Last successful email check:'), $mail_chk, ''],
616                         '$mail_disabled' => $mail_disabled_message,
617                         '$mail_server'  => ['mail_server',      DI::l10n()->t('IMAP server name:'), $mail_server, ''],
618                         '$mail_port'    => ['mail_port',        DI::l10n()->t('IMAP port:'), $mail_port, ''],
619                         '$mail_ssl'     => ['mail_ssl',         DI::l10n()->t('Security:'), strtoupper($mail_ssl), '', $ssl_options],
620                         '$mail_user'    => ['mail_user',        DI::l10n()->t('Email login name:'), $mail_user, ''],
621                         '$mail_pass'    => ['mail_pass',        DI::l10n()->t('Email password:'), '', ''],
622                         '$mail_replyto' => ['mail_replyto',     DI::l10n()->t('Reply-to address:'), $mail_replyto, 'Optional'],
623                         '$mail_pubmail' => ['mail_pubmail',     DI::l10n()->t('Send public posts to all email contacts:'), $mail_pubmail, ''],
624                         '$mail_action'  => ['mail_action',      DI::l10n()->t('Action after import:'), $mail_action, '', [0 => DI::l10n()->t('None'), 1 => DI::l10n()->t('Delete'), 2 => DI::l10n()->t('Mark as seen'), 3 => DI::l10n()->t('Move to folder')]],
625                         '$mail_movetofolder' => ['mail_movetofolder', DI::l10n()->t('Move to folder:'), $mail_movetofolder, ''],
626                         '$submit' => DI::l10n()->t('Save Settings'),
627                 ]);
628
629                 Hook::callAll('display_settings', $o);
630                 return $o;
631         }
632
633         /*
634          * ACCOUNT SETTINGS
635          */
636
637         $profile = DBA::selectFirst('profile', [], ['uid' => local_user()]);
638         if (!DBA::isResult($profile)) {
639                 notice(DI::l10n()->t('Unable to find your profile. Please contact your admin.'));
640                 return '';
641         }
642
643         $user = User::getById($a->getLoggedInUserId());
644
645         $username   = $user['username'];
646         $email      = $user['email'];
647         $nickname   = $a->getLoggedInUserNickname();
648         $timezone   = $user['timezone'];
649         $language   = $user['language'];
650         $notify     = $user['notify-flags'];
651         $defloc     = $user['default-location'];
652         $openid     = $user['openid'];
653         $maxreq     = $user['maxreq'];
654         $expire     =  ((intval($user['expire'])) ? $user['expire'] : '');
655         $unkmail    = $user['unkmail'];
656         $cntunkmail = $user['cntunkmail'];
657
658         $expire_items = DI::pConfig()->get(local_user(), 'expire', 'items', true);
659         $expire_notes = DI::pConfig()->get(local_user(), 'expire', 'notes', true);
660         $expire_starred = DI::pConfig()->get(local_user(), 'expire', 'starred', true);
661         $expire_photos = DI::pConfig()->get(local_user(), 'expire', 'photos', false);
662         $expire_network_only = DI::pConfig()->get(local_user(), 'expire', 'network_only', false);
663
664         if (!strlen($user['timezone'])) {
665                 $timezone = $a->getTimeZone();
666         }
667
668         // Set the account type to "Community" when the page is a community page but the account type doesn't fit
669         // This is only happening on the first visit after the update
670         if (in_array($user['page-flags'], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]) &&
671                 ($user['account-type'] != User::ACCOUNT_TYPE_COMMUNITY))
672                 $user['account-type'] = User::ACCOUNT_TYPE_COMMUNITY;
673
674         $pageset_tpl = Renderer::getMarkupTemplate('settings/pagetypes.tpl');
675
676         $pagetype = Renderer::replaceMacros($pageset_tpl, [
677                 '$account_types'        => DI::l10n()->t("Account Types"),
678                 '$user'                 => DI::l10n()->t("Personal Page Subtypes"),
679                 '$community'            => DI::l10n()->t("Community Forum Subtypes"),
680                 '$account_type'         => $user['account-type'],
681                 '$type_person'          => User::ACCOUNT_TYPE_PERSON,
682                 '$type_organisation'    => User::ACCOUNT_TYPE_ORGANISATION,
683                 '$type_news'            => User::ACCOUNT_TYPE_NEWS,
684                 '$type_community'       => User::ACCOUNT_TYPE_COMMUNITY,
685
686                 '$account_person'       => ['account-type', DI::l10n()->t('Personal Page'), User::ACCOUNT_TYPE_PERSON,
687                                                                         DI::l10n()->t('Account for a personal profile.'),
688                                                                         ($user['account-type'] == User::ACCOUNT_TYPE_PERSON)],
689
690                 '$account_organisation' => ['account-type', DI::l10n()->t('Organisation Page'), User::ACCOUNT_TYPE_ORGANISATION,
691                                                                         DI::l10n()->t('Account for an organisation that automatically approves contact requests as "Followers".'),
692                                                                         ($user['account-type'] == User::ACCOUNT_TYPE_ORGANISATION)],
693
694                 '$account_news'         => ['account-type', DI::l10n()->t('News Page'), User::ACCOUNT_TYPE_NEWS,
695                                                                         DI::l10n()->t('Account for a news reflector that automatically approves contact requests as "Followers".'),
696                                                                         ($user['account-type'] == User::ACCOUNT_TYPE_NEWS)],
697
698                 '$account_community'    => ['account-type', DI::l10n()->t('Community Forum'), User::ACCOUNT_TYPE_COMMUNITY,
699                                                                         DI::l10n()->t('Account for community discussions.'),
700                                                                         ($user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY)],
701
702                 '$page_normal'          => ['page-flags', DI::l10n()->t('Normal Account Page'), User::PAGE_FLAGS_NORMAL,
703                                                                         DI::l10n()->t('Account for a regular personal profile that requires manual approval of "Friends" and "Followers".'),
704                                                                         ($user['page-flags'] == User::PAGE_FLAGS_NORMAL)],
705
706                 '$page_soapbox'         => ['page-flags', DI::l10n()->t('Soapbox Page'), User::PAGE_FLAGS_SOAPBOX,
707                                                                         DI::l10n()->t('Account for a public profile that automatically approves contact requests as "Followers".'),
708                                                                         ($user['page-flags'] == User::PAGE_FLAGS_SOAPBOX)],
709
710                 '$page_community'       => ['page-flags', DI::l10n()->t('Public Forum'), User::PAGE_FLAGS_COMMUNITY,
711                                                                         DI::l10n()->t('Automatically approves all contact requests.'),
712                                                                         ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)],
713
714                 '$page_freelove'        => ['page-flags', DI::l10n()->t('Automatic Friend Page'), User::PAGE_FLAGS_FREELOVE,
715                                                                         DI::l10n()->t('Account for a popular profile that automatically approves contact requests as "Friends".'),
716                                                                         ($user['page-flags'] == User::PAGE_FLAGS_FREELOVE)],
717
718                 '$page_prvgroup'        => ['page-flags', DI::l10n()->t('Private Forum [Experimental]'), User::PAGE_FLAGS_PRVGROUP,
719                                                                         DI::l10n()->t('Requires manual approval of contact requests.'),
720                                                                         ($user['page-flags'] == User::PAGE_FLAGS_PRVGROUP)],
721
722
723         ]);
724
725         $noid = DI::config()->get('system', 'no_openid');
726
727         if ($noid) {
728                 $openid_field = false;
729         } else {
730                 $openid_field = ['openid_url', DI::l10n()->t('OpenID:'), $openid, DI::l10n()->t("\x28Optional\x29 Allow this OpenID to login to this account."), "", "readonly", "url"];
731         }
732
733         $opt_tpl = Renderer::getMarkupTemplate("field_checkbox.tpl");
734         if (DI::config()->get('system', 'publish_all')) {
735                 $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
736         } else {
737                 $profile_in_dir = Renderer::replaceMacros($opt_tpl, [
738                         '$field' => ['profile_in_directory', DI::l10n()->t('Publish your profile in your local site directory?'), $profile['publish'], DI::l10n()->t('Your profile will be published in this node\'s <a href="%s">local directory</a>. Your profile details may be publicly visible depending on the system settings.', DI::baseUrl().'/directory')]
739                 ]);
740         }
741
742         $net_pub_desc = '';
743         if (strlen(DI::config()->get('system', 'directory'))) {
744                 $net_pub_desc = ' ' . DI::l10n()->t('Your profile will also be published in the global friendica directories (e.g. <a href="%s">%s</a>).', DI::config()->get('system', 'directory'), DI::config()->get('system', 'directory'));
745         }
746
747         $tpl_addr = Renderer::getMarkupTemplate('settings/nick_set.tpl');
748
749         $prof_addr = Renderer::replaceMacros($tpl_addr,[
750                 '$desc' => DI::l10n()->t("Your Identity Address is <strong>'%s'</strong> or '%s'.", $nickname . '@' . DI::baseUrl()->getHostname() . DI::baseUrl()->getUrlPath(), DI::baseUrl() . '/profile/' . $nickname),
751                 '$basepath' => DI::baseUrl()->getHostname()
752         ]);
753
754         $stpl = Renderer::getMarkupTemplate('settings/settings.tpl');
755
756         /* Installed langs */
757         $lang_choices = DI::l10n()->getAvailableLanguages();
758
759         /// @TODO Fix indending (or so)
760         $o .= Renderer::replaceMacros($stpl, [
761                 '$ptitle'       => DI::l10n()->t('Account Settings'),
762
763                 '$submit'       => DI::l10n()->t('Save Settings'),
764                 '$baseurl' => DI::baseUrl()->get(true),
765                 '$uid' => local_user(),
766                 '$form_security_token' => BaseModule::getFormSecurityToken("settings"),
767                 '$nickname_block' => $prof_addr,
768
769                 '$h_pass'       => DI::l10n()->t('Password Settings'),
770                 '$password1'=> ['password', DI::l10n()->t('New Password:'), '', DI::l10n()->t('Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces, accentuated letters and colon (:).')],
771                 '$password2'=> ['confirm', DI::l10n()->t('Confirm:'), '', DI::l10n()->t('Leave password fields blank unless changing')],
772                 '$password3'=> ['opassword', DI::l10n()->t('Current Password:'), '', DI::l10n()->t('Your current password to confirm the changes')],
773                 '$password4'=> ['mpassword', DI::l10n()->t('Password:'), '', DI::l10n()->t('Your current password to confirm the changes of the email address')],
774                 '$oid_enable' => (!DI::config()->get('system', 'no_openid')),
775                 '$openid'       => $openid_field,
776                 '$delete_openid' => ['delete_openid', DI::l10n()->t('Delete OpenID URL'), false, ''],
777
778                 '$h_basic'      => DI::l10n()->t('Basic Settings'),
779                 '$username' => ['username',  DI::l10n()->t('Full Name:'), $username, ''],
780                 '$email'        => ['email', DI::l10n()->t('Email Address:'), $email, '', '', '', 'email'],
781                 '$timezone' => ['timezone_select' , DI::l10n()->t('Your Timezone:'), Temporal::getTimezoneSelect($timezone), ''],
782                 '$language' => ['language', DI::l10n()->t('Your Language:'), $language, DI::l10n()->t('Set the language we use to show you friendica interface and to send you emails'), $lang_choices],
783                 '$defloc'       => ['defloc', DI::l10n()->t('Default Post Location:'), $defloc, ''],
784                 '$allowloc' => ['allow_location', DI::l10n()->t('Use Browser Location:'), ($user['allow_location'] == 1), ''],
785
786                 '$h_prv'                  => DI::l10n()->t('Security and Privacy Settings'),
787                 '$is_community'       => ($user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY),
788                 '$maxreq'                 => ['maxreq', DI::l10n()->t('Maximum Friend Requests/Day:'), $maxreq , DI::l10n()->t("\x28to prevent spam abuse\x29")],
789                 '$profile_in_dir'     => $profile_in_dir,
790                 '$profile_in_net_dir' => ['profile_in_netdirectory', DI::l10n()->t('Allow your profile to be searchable globally?'), $profile['net-publish'], DI::l10n()->t("Activate this setting if you want others to easily find and follow you. Your profile will be searchable on remote systems. This setting also determines whether Friendica will inform search engines that your profile should be indexed or not.") . $net_pub_desc],
791                 '$hide_friends'       => ['hide-friends', DI::l10n()->t('Hide your contact/friend list from viewers of your profile?'), $profile['hide-friends'], DI::l10n()->t('A list of your contacts is displayed on your profile page. Activate this option to disable the display of your contact list.')],
792                 '$hide_wall'          => ['hidewall', DI::l10n()->t('Hide your profile details from anonymous viewers?'), $user['hidewall'], DI::l10n()->t('Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Your public posts and replies will still be accessible by other means.')],
793                 '$unlisted'           => ['unlisted', DI::l10n()->t('Make public posts unlisted'), DI::pConfig()->get(local_user(), 'system', 'unlisted'), DI::l10n()->t('Your public posts will not appear on the community pages or in search results, nor be sent to relay servers. However they can still appear on public feeds on remote servers.')],
794                 '$accessiblephotos'   => ['accessible-photos', DI::l10n()->t('Make all posted pictures accessible'), DI::pConfig()->get(local_user(), 'system', 'accessible-photos'), DI::l10n()->t("This option makes every posted picture accessible via the direct link. This is a workaround for the problem that most other networks can't handle permissions on pictures. Non public pictures still won't be visible for the public on your photo albums though.")],
795                 '$blockwall'          => ['blockwall', DI::l10n()->t('Allow friends to post to your profile page?'), (intval($user['blockwall']) ? '0' : '1'), DI::l10n()->t('Your contacts may write posts on your profile wall. These posts will be distributed to your contacts')], // array('blockwall', DI::l10n()->t('Allow friends to post to your profile page:'), !$blockwall, ''),
796                 '$blocktags'          => ['blocktags', DI::l10n()->t('Allow friends to tag your posts?'), (intval($user['blocktags']) ? '0' : '1'), DI::l10n()->t('Your contacts can add additional tags to your posts.')], // array('blocktags', DI::l10n()->t('Allow friends to tag your posts:'), !$blocktags, ''),
797                 '$unkmail'            => ['unkmail', DI::l10n()->t('Permit unknown people to send you private mail?'), $unkmail, DI::l10n()->t('Friendica network users may send you private messages even if they are not in your contact list.')],
798                 '$cntunkmail'         => ['cntunkmail', DI::l10n()->t('Maximum private messages per day from unknown people:'), $cntunkmail , DI::l10n()->t("\x28to prevent spam abuse\x29")],
799                 '$group_select'       => Group::displayGroupSelection(local_user(), $user['def_gid']),
800                 '$permissions'        => DI::l10n()->t('Default Post Permissions'),
801                 '$aclselect'          => ACL::getFullSelectorHTML(DI::page(), $a->getLoggedInUserId()),
802
803                 '$expire' => [
804                         'label'        => DI::l10n()->t('Expiration settings'),
805                         'days'         => ['expire',  DI::l10n()->t("Automatically expire posts after this many days:"), $expire, DI::l10n()->t('If empty, posts will not expire. Expired posts will be deleted')],
806                         'items'        => ['expire_items', DI::l10n()->t('Expire posts'), $expire_items, DI::l10n()->t('When activated, posts and comments will be expired.')],
807                         'notes'        => ['expire_notes', DI::l10n()->t('Expire personal notes'), $expire_notes, DI::l10n()->t('When activated, the personal notes on your profile page will be expired.')],
808                         'starred'      => ['expire_starred', DI::l10n()->t('Expire starred posts'), $expire_starred, DI::l10n()->t('Starring posts keeps them from being expired. That behaviour is overwritten by this setting.')],
809                         'photos'       => ['expire_photos', DI::l10n()->t('Expire photos'), $expire_photos, DI::l10n()->t('When activated, photos will be expired.')],
810                         'network_only' => ['expire_network_only', DI::l10n()->t('Only expire posts by others'), $expire_network_only, DI::l10n()->t('When activated, your own posts never expire. Then the settings above are only valid for posts you received.')],
811                 ],
812
813                 '$h_not'        => DI::l10n()->t('Notification Settings'),
814                 '$lbl_not'      => DI::l10n()->t('Send a notification email when:'),
815                 '$notify1'      => ['notify1', DI::l10n()->t('You receive an introduction'), ($notify & Notification\Type::INTRO), Notification\Type::INTRO, ''],
816                 '$notify2'      => ['notify2', DI::l10n()->t('Your introductions are confirmed'), ($notify & Notification\Type::CONFIRM), Notification\Type::CONFIRM, ''],
817                 '$notify3'      => ['notify3', DI::l10n()->t('Someone writes on your profile wall'), ($notify & Notification\Type::WALL), Notification\Type::WALL, ''],
818                 '$notify4'      => ['notify4', DI::l10n()->t('Someone writes a followup comment'), ($notify & Notification\Type::COMMENT), Notification\Type::COMMENT, ''],
819                 '$notify5'      => ['notify5', DI::l10n()->t('You receive a private message'), ($notify & Notification\Type::MAIL), Notification\Type::MAIL, ''],
820                 '$notify6'  => ['notify6', DI::l10n()->t('You receive a friend suggestion'), ($notify & Notification\Type::SUGGEST), Notification\Type::SUGGEST, ''],
821                 '$notify7'  => ['notify7', DI::l10n()->t('You are tagged in a post'), ($notify & Notification\Type::TAG_SELF), Notification\Type::TAG_SELF, ''],
822                 '$notify8'  => ['notify8', DI::l10n()->t('You are poked/prodded/etc. in a post'), ($notify & Notification\Type::POKE), Notification\Type::POKE, ''],
823
824                 '$lbl_notify'      => DI::l10n()->t('Create a desktop notification when:'),
825                 '$notify_like'     => ['notify_like', DI::l10n()->t('Someone liked your content'), DI::pConfig()->get(local_user(), 'system', 'notify_like'), ''],
826                 '$notify_announce' => ['notify_announce', DI::l10n()->t('Someone shared your content'), DI::pConfig()->get(local_user(), 'system', 'notify_announce'), ''],
827
828                 '$desktop_notifications' => ['desktop_notifications', DI::l10n()->t('Activate desktop notifications') , false, DI::l10n()->t('Show desktop popup on new notifications')],
829
830                 '$email_textonly' => ['email_textonly', DI::l10n()->t('Text-only notification emails'),
831                                                                         DI::pConfig()->get(local_user(), 'system', 'email_textonly'),
832                                                                         DI::l10n()->t('Send text only notification emails, without the html part')],
833
834                 '$detailed_notif' => ['detailed_notif', DI::l10n()->t('Show detailled notifications'),
835                                                                         DI::pConfig()->get(local_user(), 'system', 'detailed_notif'),
836                                                                         DI::l10n()->t('Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed.')],
837
838                 '$notify_ignored' => ['notify_ignored', DI::l10n()->t('Show notifications of ignored contacts') ,
839                                                                         DI::pConfig()->get(local_user(), 'system', 'notify_ignored', true),
840                                                                         DI::l10n()->t("You don't see posts from ignored contacts. But you still see their comments. This setting controls if you want to still receive regular notifications that are caused by ignored contacts or not.")],
841
842                                                                         '$h_advn' => DI::l10n()->t('Advanced Account/Page Type Settings'),
843                 '$h_descadvn' => DI::l10n()->t('Change the behaviour of this account for special situations'),
844                 '$pagetype' => $pagetype,
845
846                 '$importcontact' => DI::l10n()->t('Import Contacts'),
847                 '$importcontact_text' => DI::l10n()->t('Upload a CSV file that contains the handle of your followed accounts in the first column you exported from the old account.'),
848                 '$importcontact_button' => DI::l10n()->t('Upload File'),
849                 '$importcontact_maxsize' => DI::config()->get('system', 'max_csv_file_size', 30720),
850                 '$relocate' => DI::l10n()->t('Relocate'),
851                 '$relocate_text' => DI::l10n()->t("If you have moved this profile from another server, and some of your contacts don't receive your updates, try pushing this button."),
852                 '$relocate_button' => DI::l10n()->t("Resend relocate message to contacts"),
853
854         ]);
855
856         Hook::callAll('settings_form', $o);
857
858         $o .= '</form>' . "\r\n";
859
860         return $o;
861
862 }