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