]> git.mxchange.org Git - friendica.git/blob - mod/settings.php
Merge pull request #8300 from annando/expiry-settings
[friendica.git] / mod / settings.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2020, Friendica
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\Session;
31 use Friendica\Core\Theme;
32 use Friendica\Core\Worker;
33 use Friendica\Database\DBA;
34 use Friendica\DI;
35 use Friendica\Model\Contact;
36 use Friendica\Model\GContact;
37 use Friendica\Model\Group;
38 use Friendica\Model\Notify\Type;
39 use Friendica\Model\User;
40 use Friendica\Module\Security\Login;
41 use Friendica\Protocol\Email;
42 use Friendica\Util\Strings;
43 use Friendica\Util\Temporal;
44 use Friendica\Worker\Delivery;
45
46 function get_theme_config_file($theme)
47 {
48         $theme = Strings::sanitizeFilePathItem($theme);
49
50         $a = DI::app();
51         $base_theme = $a->theme_info['extends'] ?? '';
52
53         if (file_exists("view/theme/$theme/config.php")) {
54                 return "view/theme/$theme/config.php";
55         }
56         if ($base_theme && file_exists("view/theme/$base_theme/config.php")) {
57                 return "view/theme/$base_theme/config.php";
58         }
59         return null;
60 }
61
62 function settings_init(App $a)
63 {
64         if (!local_user()) {
65                 notice(DI::l10n()->t('Permission denied.') . EOL);
66                 return;
67         }
68
69         // These lines provide the javascript needed by the acl selector
70
71         $tpl = Renderer::getMarkupTemplate('settings/head.tpl');
72         DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl, [
73                 '$ispublic' => DI::l10n()->t('everybody')
74         ]);
75
76         $tabs = [
77                 [
78                         'label' => DI::l10n()->t('Account'),
79                         'url'   => 'settings',
80                         'selected'      =>  (($a->argc == 1) && ($a->argv[0] === 'settings')?'active':''),
81                         'accesskey' => 'o',
82                 ],
83         ];
84
85         $tabs[] = [
86                 'label' => DI::l10n()->t('Two-factor authentication'),
87                 'url' => 'settings/2fa',
88                 'selected' => (($a->argc > 1) && ($a->argv[1] === '2fa') ? 'active' : ''),
89                 'accesskey' => 'o',
90         ];
91
92         $tabs[] =       [
93                 'label' => DI::l10n()->t('Profile'),
94                 'url'   => 'settings/profile',
95                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'profile')?'active':''),
96                 'accesskey' => 'p',
97         ];
98
99         if (Feature::get()) {
100                 $tabs[] =       [
101                                         'label' => DI::l10n()->t('Additional features'),
102                                         'url'   => 'settings/features',
103                                         'selected'      => (($a->argc > 1) && ($a->argv[1] === 'features') ? 'active' : ''),
104                                         'accesskey' => 't',
105                                 ];
106         }
107
108         $tabs[] =       [
109                 'label' => DI::l10n()->t('Display'),
110                 'url'   => 'settings/display',
111                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'display')?'active':''),
112                 'accesskey' => 'i',
113         ];
114
115         $tabs[] =       [
116                 'label' => DI::l10n()->t('Social Networks'),
117                 'url'   => 'settings/connectors',
118                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'connectors')?'active':''),
119                 'accesskey' => 'w',
120         ];
121
122         $tabs[] =       [
123                 'label' => DI::l10n()->t('Addons'),
124                 'url'   => 'settings/addon',
125                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'addon')?'active':''),
126                 'accesskey' => 'l',
127         ];
128
129         $tabs[] =       [
130                 'label' => DI::l10n()->t('Delegations'),
131                 'url'   => 'settings/delegation',
132                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'delegation')?'active':''),
133                 'accesskey' => 'd',
134         ];
135
136         $tabs[] =       [
137                 'label' => DI::l10n()->t('Connected apps'),
138                 'url' => 'settings/oauth',
139                 'selected' => (($a->argc > 1) && ($a->argv[1] === 'oauth')?'active':''),
140                 'accesskey' => 'b',
141         ];
142
143         $tabs[] =       [
144                 'label' => DI::l10n()->t('Export personal data'),
145                 'url' => 'settings/userexport',
146                 'selected' => (($a->argc > 1) && ($a->argv[1] === 'userexport')?'active':''),
147                 'accesskey' => 'e',
148         ];
149
150         $tabs[] =       [
151                 'label' => DI::l10n()->t('Remove account'),
152                 'url' => 'removeme',
153                 'selected' => (($a->argc == 1) && ($a->argv[0] === 'removeme')?'active':''),
154                 'accesskey' => 'r',
155         ];
156
157
158         $tabtpl = Renderer::getMarkupTemplate("generic_links_widget.tpl");
159         DI::page()['aside'] = Renderer::replaceMacros($tabtpl, [
160                 '$title' => DI::l10n()->t('Settings'),
161                 '$class' => 'settings-widget',
162                 '$items' => $tabs,
163         ]);
164
165 }
166
167 function settings_post(App $a)
168 {
169         if (!local_user()) {
170                 return;
171         }
172
173         if (!empty($_SESSION['submanage'])) {
174                 return;
175         }
176
177         if (count($a->user) && !empty($a->user['uid']) && $a->user['uid'] != local_user()) {
178                 notice(DI::l10n()->t('Permission denied.') . EOL);
179                 return;
180         }
181
182         $old_page_flags = $a->user['page-flags'];
183
184         if (($a->argc > 1) && ($a->argv[1] === 'oauth') && !empty($_POST['remove'])) {
185                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth');
186
187                 $key = $_POST['remove'];
188                 DBA::delete('tokens', ['id' => $key, 'uid' => local_user()]);
189                 DI::baseUrl()->redirect('settings/oauth/', true);
190                 return;
191         }
192
193         if (($a->argc > 2) && ($a->argv[1] === 'oauth')  && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && !empty($_POST['submit'])) {
194                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth');
195
196                 $name     = $_POST['name']     ?? '';
197                 $key      = $_POST['key']      ?? '';
198                 $secret   = $_POST['secret']   ?? '';
199                 $redirect = $_POST['redirect'] ?? '';
200                 $icon     = $_POST['icon']     ?? '';
201
202                 if ($name == "" || $key == "" || $secret == "") {
203                         notice(DI::l10n()->t("Missing some important data!"));
204                 } else {
205                         if ($_POST['submit'] == DI::l10n()->t("Update")) {
206                                 q("UPDATE clients SET
207                                                         client_id='%s',
208                                                         pw='%s',
209                                                         name='%s',
210                                                         redirect_uri='%s',
211                                                         icon='%s',
212                                                         uid=%d
213                                                 WHERE client_id='%s'",
214                                         DBA::escape($key),
215                                         DBA::escape($secret),
216                                         DBA::escape($name),
217                                         DBA::escape($redirect),
218                                         DBA::escape($icon),
219                                         local_user(),
220                                         DBA::escape($key)
221                                 );
222                         } else {
223                                 q("INSERT INTO clients
224                                                         (client_id, pw, name, redirect_uri, icon, uid)
225                                                 VALUES ('%s', '%s', '%s', '%s', '%s',%d)",
226                                         DBA::escape($key),
227                                         DBA::escape($secret),
228                                         DBA::escape($name),
229                                         DBA::escape($redirect),
230                                         DBA::escape($icon),
231                                         local_user()
232                                 );
233                         }
234                 }
235                 DI::baseUrl()->redirect('settings/oauth/', true);
236                 return;
237         }
238
239         if (($a->argc > 1) && ($a->argv[1] == 'addon')) {
240                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/addon', 'settings_addon');
241
242                 Hook::callAll('addon_settings_post', $_POST);
243                 return;
244         }
245
246         if (($a->argc > 1) && ($a->argv[1] == 'connectors')) {
247                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/connectors', 'settings_connectors');
248
249                 if (!empty($_POST['general-submit'])) {
250                         DI::pConfig()->set(local_user(), 'system', 'accept_only_sharer', intval($_POST['accept_only_sharer']));
251                         DI::pConfig()->set(local_user(), 'system', 'disable_cw', intval($_POST['disable_cw']));
252                         DI::pConfig()->set(local_user(), 'system', 'no_intelligent_shortening', intval($_POST['no_intelligent_shortening']));
253                         DI::pConfig()->set(local_user(), 'system', 'attach_link_title', intval($_POST['attach_link_title']));
254                         DI::pConfig()->set(local_user(), 'system', 'ostatus_autofriend', intval($_POST['snautofollow']));
255                         DI::pConfig()->set(local_user(), 'ostatus', 'default_group', $_POST['group-selection']);
256                         DI::pConfig()->set(local_user(), 'ostatus', 'legacy_contact', $_POST['legacy_contact']);
257                 } elseif (!empty($_POST['imap-submit'])) {
258                         $mail_server       =                 $_POST['mail_server']       ?? '';
259                         $mail_port         =                 $_POST['mail_port']         ?? '';
260                         $mail_ssl          = strtolower(trim($_POST['mail_ssl']          ?? ''));
261                         $mail_user         =                 $_POST['mail_user']         ?? '';
262                         $mail_pass         =            trim($_POST['mail_pass']         ?? '');
263                         $mail_action       =            trim($_POST['mail_action']       ?? '');
264                         $mail_movetofolder =            trim($_POST['mail_movetofolder'] ?? '');
265                         $mail_replyto      =                 $_POST['mail_replyto']      ?? '';
266                         $mail_pubmail      =                 $_POST['mail_pubmail']      ?? '';
267
268                         if (
269                                 !DI::config()->get('system', 'dfrn_only')
270                                 && function_exists('imap_open')
271                                 && !DI::config()->get('system', 'imap_disabled')
272                         ) {
273                                 $failed = false;
274                                 $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
275                                         intval(local_user())
276                                 );
277                                 if (!DBA::isResult($r)) {
278                                         DBA::insert('mailacct', ['uid' => local_user()]);
279                                 }
280                                 if (strlen($mail_pass)) {
281                                         $pass = '';
282                                         openssl_public_encrypt($mail_pass, $pass, $a->user['pubkey']);
283                                         DBA::update('mailacct', ['pass' => bin2hex($pass)], ['uid' => local_user()]);
284                                 }
285                                 $r = q("UPDATE `mailacct` SET `server` = '%s', `port` = %d, `ssltype` = '%s', `user` = '%s',
286                                         `action` = %d, `movetofolder` = '%s',
287                                         `mailbox` = 'INBOX', `reply_to` = '%s', `pubmail` = %d WHERE `uid` = %d",
288                                         DBA::escape($mail_server),
289                                         intval($mail_port),
290                                         DBA::escape($mail_ssl),
291                                         DBA::escape($mail_user),
292                                         intval($mail_action),
293                                         DBA::escape($mail_movetofolder),
294                                         DBA::escape($mail_replyto),
295                                         intval($mail_pubmail),
296                                         intval(local_user())
297                                 );
298                                 Logger::log("mail: updating mailaccount. Response: ".print_r($r, true));
299                                 $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
300                                         intval(local_user())
301                                 );
302                                 if (DBA::isResult($r)) {
303                                         $eacct = $r[0];
304                                         $mb = Email::constructMailboxName($eacct);
305
306                                         if (strlen($eacct['server'])) {
307                                                 $dcrpass = '';
308                                                 openssl_private_decrypt(hex2bin($eacct['pass']), $dcrpass, $a->user['prvkey']);
309                                                 $mbox = Email::connect($mb, $mail_user, $dcrpass);
310                                                 unset($dcrpass);
311                                                 if (!$mbox) {
312                                                         $failed = true;
313                                                         notice(DI::l10n()->t('Failed to connect with email account using the settings provided.') . EOL);
314                                                 }
315                                         }
316                                 }
317                                 if (!$failed) {
318                                         info(DI::l10n()->t('Email settings updated.') . EOL);
319                                 }
320                         }
321                 }
322
323                 Hook::callAll('connector_settings_post', $_POST);
324                 return;
325         }
326
327         if (($a->argc > 1) && ($a->argv[1] === 'features')) {
328                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/features', 'settings_features');
329                 foreach ($_POST as $k => $v) {
330                         if (strpos($k, 'feature_') === 0) {
331                                 DI::pConfig()->set(local_user(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0));
332                         }
333                 }
334                 info(DI::l10n()->t('Features updated') . EOL);
335                 return;
336         }
337
338         if (($a->argc > 1) && ($a->argv[1] === 'display')) {
339                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/display', 'settings_display');
340
341                 $theme              = !empty($_POST['theme'])              ? Strings::escapeTags(trim($_POST['theme']))        : $a->user['theme'];
342                 $mobile_theme       = !empty($_POST['mobile_theme'])       ? Strings::escapeTags(trim($_POST['mobile_theme'])) : '';
343                 $nosmile            = !empty($_POST['nosmile'])            ? intval($_POST['nosmile'])            : 0;
344                 $first_day_of_week  = !empty($_POST['first_day_of_week'])  ? intval($_POST['first_day_of_week'])  : 0;
345                 $noinfo             = !empty($_POST['noinfo'])             ? intval($_POST['noinfo'])             : 0;
346                 $infinite_scroll    = !empty($_POST['infinite_scroll'])    ? intval($_POST['infinite_scroll'])    : 0;
347                 $no_auto_update     = !empty($_POST['no_auto_update'])     ? intval($_POST['no_auto_update'])     : 0;
348                 $bandwidth_saver    = !empty($_POST['bandwidth_saver'])    ? intval($_POST['bandwidth_saver'])    : 0;
349                 $no_smart_threading = !empty($_POST['no_smart_threading']) ? intval($_POST['no_smart_threading']) : 0;
350                 $nowarn_insecure    = !empty($_POST['nowarn_insecure'])    ? intval($_POST['nowarn_insecure'])    : 0;
351                 $browser_update     = !empty($_POST['browser_update'])     ? intval($_POST['browser_update'])     : 0;
352                 if ($browser_update != -1) {
353                         $browser_update = $browser_update * 1000;
354                         if ($browser_update < 10000) {
355                                 $browser_update = 10000;
356                         }
357                 }
358
359                 $itemspage_network = !empty($_POST['itemspage_network']) ?
360                         intval($_POST['itemspage_network']) :
361                         DI::config()->get('system', 'itemspage_network');
362                 if ($itemspage_network > 100) {
363                         $itemspage_network = 100;
364                 }
365                 $itemspage_mobile_network = !empty($_POST['itemspage_mobile_network']) ?
366                         intval($_POST['itemspage_mobile_network']) :
367                         DI::config()->get('system', 'itemspage_network_mobile');
368                 if ($itemspage_mobile_network > 100) {
369                         $itemspage_mobile_network = 100;
370                 }
371
372                 if ($mobile_theme !== '') {
373                         DI::pConfig()->set(local_user(), 'system', 'mobile_theme', $mobile_theme);
374                 }
375
376                 DI::pConfig()->set(local_user(), 'system', 'nowarn_insecure'         , $nowarn_insecure);
377                 DI::pConfig()->set(local_user(), 'system', 'update_interval'         , $browser_update);
378                 DI::pConfig()->set(local_user(), 'system', 'itemspage_network'       , $itemspage_network);
379                 DI::pConfig()->set(local_user(), 'system', 'itemspage_mobile_network', $itemspage_mobile_network);
380                 DI::pConfig()->set(local_user(), 'system', 'no_smilies'              , $nosmile);
381                 DI::pConfig()->set(local_user(), 'system', 'first_day_of_week'       , $first_day_of_week);
382                 DI::pConfig()->set(local_user(), 'system', 'ignore_info'             , $noinfo);
383                 DI::pConfig()->set(local_user(), 'system', 'infinite_scroll'         , $infinite_scroll);
384                 DI::pConfig()->set(local_user(), 'system', 'no_auto_update'          , $no_auto_update);
385                 DI::pConfig()->set(local_user(), 'system', 'bandwidth_saver'         , $bandwidth_saver);
386                 DI::pConfig()->set(local_user(), 'system', 'no_smart_threading'      , $no_smart_threading);
387
388                 if (in_array($theme, Theme::getAllowedList())) {
389                         if ($theme == $a->user['theme']) {
390                                 // call theme_post only if theme has not been changed
391                                 if (($themeconfigfile = get_theme_config_file($theme)) !== null) {
392                                         require_once $themeconfigfile;
393                                         theme_post($a);
394                                 }
395                         } else {
396                                 DBA::update('user', ['theme' => $theme], ['uid' => local_user()]);
397                         }
398                 } else {
399                         notice(DI::l10n()->t('The theme you chose isn\'t available.'));
400                 }
401
402                 Hook::callAll('display_settings_post', $_POST);
403                 DI::baseUrl()->redirect('settings/display');
404                 return; // NOTREACHED
405         }
406
407         BaseModule::checkFormSecurityTokenRedirectOnError('/settings', 'settings');
408
409         // Import Contacts from CSV file
410         if (!empty($_POST['importcontact-submit'])) {
411                 if (isset($_FILES['importcontact-filename'])) {
412                         // was there an error
413                         if ($_FILES['importcontact-filename']['error'] > 0) {
414                                 Logger::notice('Contact CSV file upload error');
415                                 info(DI::l10n()->t('Contact CSV file upload error'));
416                         } else {
417                                 $csvArray = array_map('str_getcsv', file($_FILES['importcontact-filename']['tmp_name']));
418                                 // import contacts
419                                 foreach ($csvArray as $csvRow) {
420                                         // The 1st row may, or may not contain the headers of the table
421                                         // We expect the 1st field of the row to contain either the URL
422                                         // or the handle of the account, therefore we check for either
423                                         // "http" or "@" to be present in the string.
424                                         // All other fields from the row will be ignored
425                                         if ((strpos($csvRow[0],'@') !== false) || (strpos($csvRow[0],'http') !== false)) {
426                                                 Worker::add(PRIORITY_LOW, 'AddContact', $_SESSION['uid'], $csvRow[0]);
427                                         }
428                                 }
429
430                                 info(DI::l10n()->t('Importing Contacts done'));
431                                 // delete temp file
432                                 unlink($_FILES['importcontact-filename']['tmp_name']);
433                         }
434                 }
435         }
436
437         if (!empty($_POST['resend_relocate'])) {
438                 Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, local_user());
439                 info(DI::l10n()->t("Relocate message has been send to your contacts"));
440                 DI::baseUrl()->redirect('settings');
441         }
442
443         Hook::callAll('settings_post', $_POST);
444
445         if (!empty($_POST['password']) || !empty($_POST['confirm'])) {
446                 $newpass = $_POST['password'];
447                 $confirm = $_POST['confirm'];
448
449                 try {
450                         if ($newpass != $confirm) {
451                                 throw new Exception(DI::l10n()->t('Passwords do not match.'));
452                         }
453
454                         //  check if the old password was supplied correctly before changing it to the new value
455                         User::getIdFromPasswordAuthentication(local_user(), $_POST['opassword']);
456
457                         $result = User::updatePassword(local_user(), $newpass);
458                         if (!DBA::isResult($result)) {
459                                 throw new Exception(DI::l10n()->t('Password update failed. Please try again.'));
460                         }
461
462                         info(DI::l10n()->t('Password changed.'));
463                 } catch (Exception $e) {
464                         notice($e->getMessage());
465                         notice(DI::l10n()->t('Password unchanged.'));
466                 }
467         }
468
469         $username         = (!empty($_POST['username'])   ? Strings::escapeTags(trim($_POST['username']))     : '');
470         $email            = (!empty($_POST['email'])      ? Strings::escapeTags(trim($_POST['email']))        : '');
471         $timezone         = (!empty($_POST['timezone'])   ? Strings::escapeTags(trim($_POST['timezone']))     : '');
472         $language         = (!empty($_POST['language'])   ? Strings::escapeTags(trim($_POST['language']))     : '');
473
474         $defloc           = (!empty($_POST['defloc'])     ? Strings::escapeTags(trim($_POST['defloc']))       : '');
475         $maxreq           = (!empty($_POST['maxreq'])     ? intval($_POST['maxreq'])             : 0);
476         $expire           = (!empty($_POST['expire'])     ? intval($_POST['expire'])             : 0);
477         $def_gid          = (!empty($_POST['group-selection']) ? intval($_POST['group-selection']) : 0);
478
479
480         $expire_items     = (!empty($_POST['expire_items']) ? intval($_POST['expire_items'])     : 0);
481         $expire_notes     = (!empty($_POST['expire_notes']) ? intval($_POST['expire_notes'])     : 0);
482         $expire_starred   = (!empty($_POST['expire_starred']) ? intval($_POST['expire_starred']) : 0);
483         $expire_photos    = (!empty($_POST['expire_photos'])? intval($_POST['expire_photos'])    : 0);
484         $expire_network_only    = (!empty($_POST['expire_network_only'])? intval($_POST['expire_network_only'])  : 0);
485
486         $delete_openid    = ((!empty($_POST['delete_openid']) && (intval($_POST['delete_openid']) == 1)) ? 1: 0);
487
488         $allow_location   = ((!empty($_POST['allow_location']) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
489         $publish          = ((!empty($_POST['profile_in_directory']) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
490         $net_publish      = ((!empty($_POST['profile_in_netdirectory']) && (intval($_POST['profile_in_netdirectory']) == 1)) ? 1: 0);
491         $old_visibility   = ((!empty($_POST['visibility']) && (intval($_POST['visibility']) == 1)) ? 1 : 0);
492         $account_type     = ((!empty($_POST['account-type']) && (intval($_POST['account-type']))) ? intval($_POST['account-type']) : 0);
493         $page_flags       = ((!empty($_POST['page-flags']) && (intval($_POST['page-flags']))) ? intval($_POST['page-flags']) : 0);
494         $blockwall        = ((!empty($_POST['blockwall']) && (intval($_POST['blockwall']) == 1)) ? 0: 1); // this setting is inverted!
495         $blocktags        = ((!empty($_POST['blocktags']) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
496         $unkmail          = ((!empty($_POST['unkmail']) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
497         $cntunkmail       = (!empty($_POST['cntunkmail']) ? intval($_POST['cntunkmail']) : 0);
498         $suggestme        = (!empty($_POST['suggestme']) ? intval($_POST['suggestme'])  : 0);
499         $hide_friends     = (($_POST['hide-friends'] == 1) ? 1: 0);
500         $hidewall         = (($_POST['hidewall'] == 1) ? 1: 0);
501
502         $email_textonly   = (($_POST['email_textonly'] == 1) ? 1 : 0);
503         $detailed_notif   = (($_POST['detailed_notif'] == 1) ? 1 : 0);
504
505         $notify = 0;
506
507         if (!empty($_POST['notify1'])) {
508                 $notify += intval($_POST['notify1']);
509         }
510         if (!empty($_POST['notify2'])) {
511                 $notify += intval($_POST['notify2']);
512         }
513         if (!empty($_POST['notify3'])) {
514                 $notify += intval($_POST['notify3']);
515         }
516         if (!empty($_POST['notify4'])) {
517                 $notify += intval($_POST['notify4']);
518         }
519         if (!empty($_POST['notify5'])) {
520                 $notify += intval($_POST['notify5']);
521         }
522         if (!empty($_POST['notify6'])) {
523                 $notify += intval($_POST['notify6']);
524         }
525         if (!empty($_POST['notify7'])) {
526                 $notify += intval($_POST['notify7']);
527         }
528         if (!empty($_POST['notify8'])) {
529                 $notify += intval($_POST['notify8']);
530         }
531
532         // Adjust the page flag if the account type doesn't fit to the page flag.
533         if (($account_type == User::ACCOUNT_TYPE_PERSON) && !in_array($page_flags, [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE])) {
534                 $page_flags = User::PAGE_FLAGS_NORMAL;
535         } elseif (($account_type == User::ACCOUNT_TYPE_ORGANISATION) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
536                 $page_flags = User::PAGE_FLAGS_SOAPBOX;
537         } elseif (($account_type == User::ACCOUNT_TYPE_NEWS) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
538                 $page_flags = User::PAGE_FLAGS_SOAPBOX;
539         } elseif (($account_type == User::ACCOUNT_TYPE_COMMUNITY) && !in_array($page_flags, [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP])) {
540                 $page_flags = User::PAGE_FLAGS_COMMUNITY;
541         }
542
543         $err = '';
544
545         if ($username != $a->user['username']) {
546                 if (strlen($username) > 40) {
547                         $err .= DI::l10n()->t(' Please use a shorter name.');
548                 }
549                 if (strlen($username) < 3) {
550                         $err .= DI::l10n()->t(' Name too short.');
551                 }
552         }
553
554         if ($email != $a->user['email']) {
555                 //  check for the correct password
556                 if (!User::authenticate(intval(local_user()), $_POST['mpassword'])) {
557                         $err .= DI::l10n()->t('Wrong Password') . EOL;
558                         $email = $a->user['email'];
559                 }
560                 //  check the email is valid
561                 if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
562                         $err .= DI::l10n()->t('Invalid email.');
563                 }
564                 //  ensure new email is not the admin mail
565                 if (DI::config()->get('config', 'admin_email')) {
566                         $adminlist = explode(",", str_replace(" ", "", strtolower(DI::config()->get('config', 'admin_email'))));
567                         if (in_array(strtolower($email), $adminlist)) {
568                                 $err .= DI::l10n()->t('Cannot change to that email.');
569                                 $email = $a->user['email'];
570                         }
571                 }
572         }
573
574         if (strlen($err)) {
575                 notice($err . EOL);
576                 return;
577         }
578
579         if (($timezone != $a->user['timezone']) && strlen($timezone)) {
580                 date_default_timezone_set($timezone);
581         }
582
583         $aclFormatter = DI::aclFormatter();
584
585         $str_group_allow   = !empty($_POST['group_allow'])   ? $aclFormatter->toString($_POST['group_allow'])   : '';
586         $str_contact_allow = !empty($_POST['contact_allow']) ? $aclFormatter->toString($_POST['contact_allow']) : '';
587         $str_group_deny    = !empty($_POST['group_deny'])    ? $aclFormatter->toString($_POST['group_deny'])    : '';
588         $str_contact_deny  = !empty($_POST['contact_deny'])  ? $aclFormatter->toString($_POST['contact_deny'])  : '';
589
590         DI::pConfig()->set(local_user(), 'expire', 'items', $expire_items);
591         DI::pConfig()->set(local_user(), 'expire', 'notes', $expire_notes);
592         DI::pConfig()->set(local_user(), 'expire', 'starred', $expire_starred);
593         DI::pConfig()->set(local_user(), 'expire', 'photos', $expire_photos);
594         DI::pConfig()->set(local_user(), 'expire', 'network_only', $expire_network_only);
595
596         DI::pConfig()->set(local_user(), 'system', 'suggestme', $suggestme);
597
598         DI::pConfig()->set(local_user(), 'system', 'email_textonly', $email_textonly);
599         DI::pConfig()->set(local_user(), 'system', 'detailed_notif', $detailed_notif);
600
601         if ($page_flags == User::PAGE_FLAGS_PRVGROUP) {
602                 $hidewall = 1;
603                 if (!$str_contact_allow && !$str_group_allow && !$str_contact_deny && !$str_group_deny) {
604                         if ($def_gid) {
605                                 info(DI::l10n()->t('Private forum has no privacy permissions. Using default privacy group.'). EOL);
606                                 $str_group_allow = '<' . $def_gid . '>';
607                         } else {
608                                 notice(DI::l10n()->t('Private forum has no privacy permissions and no default privacy group.') . EOL);
609                         }
610                 }
611         }
612
613         $fields = ['username' => $username, 'email' => $email, 'timezone' => $timezone,
614                 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_group_allow, 'deny_cid' => $str_contact_deny, 'deny_gid' => $str_group_deny,
615                 'notify-flags' => $notify, 'page-flags' => $page_flags, 'account-type' => $account_type, 'default-location' => $defloc,
616                 'allow_location' => $allow_location, 'maxreq' => $maxreq, 'expire' => $expire, 'def_gid' => $def_gid, 'blockwall' => $blockwall,
617                 'hidewall' => $hidewall, 'blocktags' => $blocktags, 'unkmail' => $unkmail, 'cntunkmail' => $cntunkmail, 'language' => $language];
618
619         if ($delete_openid) {
620                 $fields['openid'] = '';
621                 $fields['openidserver'] = '';
622         }
623
624         if (DBA::update('user', $fields, ['uid' => local_user()])) {
625                 info(DI::l10n()->t('Settings updated.') . EOL);
626         }
627
628         // clear session language
629         unset($_SESSION['language']);
630
631         q("UPDATE `profile`
632                 SET `publish` = %d,
633                 `name` = '%s',
634                 `net-publish` = %d,
635                 `hide-friends` = %d
636                 WHERE `uid` = %d",
637                 intval($publish),
638                 DBA::escape($username),
639                 intval($net_publish),
640                 intval($hide_friends),
641                 intval(local_user())
642         );
643
644         Contact::updateSelfFromUserID(local_user());
645
646         if (($old_visibility != $net_publish) || ($page_flags != $old_page_flags)) {
647                 // Update global directory in background
648                 $url = $_SESSION['my_url'];
649                 if ($url && strlen(DI::config()->get('system', 'directory'))) {
650                         Worker::add(PRIORITY_LOW, "Directory", $url);
651                 }
652         }
653
654         Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
655
656         // Update the global contact for the user
657         GContact::updateForUser(local_user());
658
659         DI::baseUrl()->redirect('settings');
660         return; // NOTREACHED
661 }
662
663
664 function settings_content(App $a)
665 {
666         $o = '';
667         Nav::setSelected('settings');
668
669         if (!local_user()) {
670                 //notice(DI::l10n()->t('Permission denied.') . EOL);
671                 return Login::form();
672         }
673
674         if (!empty($_SESSION['submanage'])) {
675                 notice(DI::l10n()->t('Permission denied.') . EOL);
676                 return;
677         }
678
679         if (($a->argc > 1) && ($a->argv[1] === 'oauth')) {
680                 if (($a->argc > 2) && ($a->argv[2] === 'add')) {
681                         $tpl = Renderer::getMarkupTemplate('settings/oauth_edit.tpl');
682                         $o .= Renderer::replaceMacros($tpl, [
683                                 '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
684                                 '$title'        => DI::l10n()->t('Add application'),
685                                 '$submit'       => DI::l10n()->t('Save Settings'),
686                                 '$cancel'       => DI::l10n()->t('Cancel'),
687                                 '$name'         => ['name', DI::l10n()->t('Name'), '', ''],
688                                 '$key'          => ['key', DI::l10n()->t('Consumer Key'), '', ''],
689                                 '$secret'       => ['secret', DI::l10n()->t('Consumer Secret'), '', ''],
690                                 '$redirect'     => ['redirect', DI::l10n()->t('Redirect'), '', ''],
691                                 '$icon'         => ['icon', DI::l10n()->t('Icon url'), '', ''],
692                         ]);
693                         return $o;
694                 }
695
696                 if (($a->argc > 3) && ($a->argv[2] === 'edit')) {
697                         $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
698                                         DBA::escape($a->argv[3]),
699                                         local_user());
700
701                         if (!DBA::isResult($r)) {
702                                 notice(DI::l10n()->t("You can't edit this application."));
703                                 return;
704                         }
705                         $app = $r[0];
706
707                         $tpl = Renderer::getMarkupTemplate('settings/oauth_edit.tpl');
708                         $o .= Renderer::replaceMacros($tpl, [
709                                 '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
710                                 '$title'        => DI::l10n()->t('Add application'),
711                                 '$submit'       => DI::l10n()->t('Update'),
712                                 '$cancel'       => DI::l10n()->t('Cancel'),
713                                 '$name'         => ['name', DI::l10n()->t('Name'), $app['name'] , ''],
714                                 '$key'          => ['key', DI::l10n()->t('Consumer Key'), $app['client_id'], ''],
715                                 '$secret'       => ['secret', DI::l10n()->t('Consumer Secret'), $app['pw'], ''],
716                                 '$redirect'     => ['redirect', DI::l10n()->t('Redirect'), $app['redirect_uri'], ''],
717                                 '$icon'         => ['icon', DI::l10n()->t('Icon url'), $app['icon'], ''],
718                         ]);
719                         return $o;
720                 }
721
722                 if (($a->argc > 3) && ($a->argv[2] === 'delete')) {
723                         BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth', 't');
724
725                         DBA::delete('clients', ['client_id' => $a->argv[3], 'uid' => local_user()]);
726                         DI::baseUrl()->redirect('settings/oauth/', true);
727                         return;
728                 }
729
730                 /// @TODO validate result with DBA::isResult()
731                 $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
732                                 FROM clients
733                                 LEFT JOIN tokens ON clients.client_id=tokens.client_id
734                                 WHERE clients.uid IN (%d, 0)",
735                                 local_user(),
736                                 local_user());
737
738
739                 $tpl = Renderer::getMarkupTemplate('settings/oauth.tpl');
740                 $o .= Renderer::replaceMacros($tpl, [
741                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
742                         '$baseurl'      => DI::baseUrl()->get(true),
743                         '$title'        => DI::l10n()->t('Connected Apps'),
744                         '$add'          => DI::l10n()->t('Add application'),
745                         '$edit'         => DI::l10n()->t('Edit'),
746                         '$delete'               => DI::l10n()->t('Delete'),
747                         '$consumerkey' => DI::l10n()->t('Client key starts with'),
748                         '$noname'       => DI::l10n()->t('No name'),
749                         '$remove'       => DI::l10n()->t('Remove authorization'),
750                         '$apps'         => $r,
751                 ]);
752                 return $o;
753         }
754
755         if (($a->argc > 1) && ($a->argv[1] === 'addon')) {
756                 $settings_addons = "";
757
758                 $r = q("SELECT * FROM `hook` WHERE `hook` = 'addon_settings' ");
759                 if (!DBA::isResult($r)) {
760                         $settings_addons = DI::l10n()->t('No Addon settings configured');
761                 }
762
763                 Hook::callAll('addon_settings', $settings_addons);
764
765
766                 $tpl = Renderer::getMarkupTemplate('settings/addons.tpl');
767                 $o .= Renderer::replaceMacros($tpl, [
768                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_addon"),
769                         '$title'        => DI::l10n()->t('Addon Settings'),
770                         '$settings_addons' => $settings_addons
771                 ]);
772                 return $o;
773         }
774
775         if (($a->argc > 1) && ($a->argv[1] === 'features')) {
776
777                 $arr = [];
778                 $features = Feature::get();
779                 foreach ($features as $fname => $fdata) {
780                         $arr[$fname] = [];
781                         $arr[$fname][0] = $fdata[0];
782                         foreach (array_slice($fdata,1) as $f) {
783                                 $arr[$fname][1][] = ['feature_' .$f[0], $f[1],((intval(Feature::isEnabled(local_user(), $f[0]))) ? "1" : ''), $f[2],[DI::l10n()->t('Off'), DI::l10n()->t('On')]];
784                         }
785                 }
786
787                 $tpl = Renderer::getMarkupTemplate('settings/features.tpl');
788                 $o .= Renderer::replaceMacros($tpl, [
789                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_features"),
790                         '$title'               => DI::l10n()->t('Additional Features'),
791                         '$features'            => $arr,
792                         '$submit'              => DI::l10n()->t('Save Settings'),
793                 ]);
794                 return $o;
795         }
796
797         if (($a->argc > 1) && ($a->argv[1] === 'connectors')) {
798                 $accept_only_sharer        = intval(DI::pConfig()->get(local_user(), 'system', 'accept_only_sharer'));
799                 $disable_cw                = intval(DI::pConfig()->get(local_user(), 'system', 'disable_cw'));
800                 $no_intelligent_shortening = intval(DI::pConfig()->get(local_user(), 'system', 'no_intelligent_shortening'));
801                 $attach_link_title         = intval(DI::pConfig()->get(local_user(), 'system', 'attach_link_title'));
802                 $ostatus_autofriend        = intval(DI::pConfig()->get(local_user(), 'system', 'ostatus_autofriend'));
803                 $default_group             = DI::pConfig()->get(local_user(), 'ostatus', 'default_group');
804                 $legacy_contact            = DI::pConfig()->get(local_user(), 'ostatus', 'legacy_contact');
805
806                 if (!empty($legacy_contact)) {
807                         /// @todo Isn't it supposed to be a $a->internalRedirect() call?
808                         DI::page()['htmlhead'] = '<meta http-equiv="refresh" content="0; URL=' . DI::baseUrl().'/ostatus_subscribe?url=' . urlencode($legacy_contact) . '">';
809                 }
810
811                 $settings_connectors = '';
812                 Hook::callAll('connector_settings', $settings_connectors);
813
814                 if (is_site_admin()) {
815                         $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')));
816                         $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')));
817                 } else {
818                         $diasp_enabled = "";
819                         $ostat_enabled = "";
820                 }
821
822                 $mail_disabled = ((function_exists('imap_open') && (!DI::config()->get('system', 'imap_disabled'))) ? 0 : 1);
823                 if (DI::config()->get('system', 'dfrn_only')) {
824                         $mail_disabled = 1;
825                 }
826                 if (!$mail_disabled) {
827                         $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
828                                 local_user()
829                         );
830                 } else {
831                         $r = null;
832                 }
833
834                 $mail_server       = ((DBA::isResult($r)) ? $r[0]['server'] : '');
835                 $mail_port         = ((DBA::isResult($r) && intval($r[0]['port'])) ? intval($r[0]['port']) : '');
836                 $mail_ssl          = ((DBA::isResult($r)) ? $r[0]['ssltype'] : '');
837                 $mail_user         = ((DBA::isResult($r)) ? $r[0]['user'] : '');
838                 $mail_replyto      = ((DBA::isResult($r)) ? $r[0]['reply_to'] : '');
839                 $mail_pubmail      = ((DBA::isResult($r)) ? $r[0]['pubmail'] : 0);
840                 $mail_action       = ((DBA::isResult($r)) ? $r[0]['action'] : 0);
841                 $mail_movetofolder = ((DBA::isResult($r)) ? $r[0]['movetofolder'] : '');
842                 $mail_chk          = ((DBA::isResult($r)) ? $r[0]['last_check'] : DBA::NULL_DATETIME);
843
844
845                 $tpl = Renderer::getMarkupTemplate('settings/connectors.tpl');
846
847                 $mail_disabled_message = ($mail_disabled ? DI::l10n()->t('Email access is disabled on this site.') : '');
848
849                 $ssl_options = ['TLS' => 'TLS', 'SSL' => 'SSL'];
850
851                 if (DI::config()->get('system', 'insecure_imap')) {
852                         $ssl_options['notls'] = DI::l10n()->t('None');
853                 }
854
855                 $o .= Renderer::replaceMacros($tpl, [
856                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_connectors"),
857
858                         '$title'        => DI::l10n()->t('Social Networks'),
859
860                         '$diasp_enabled' => $diasp_enabled,
861                         '$ostat_enabled' => $ostat_enabled,
862
863                         '$general_settings' => DI::l10n()->t('General Social Media Settings'),
864                         '$accept_only_sharer' => ['accept_only_sharer', DI::l10n()->t('Accept only top level posts by contacts you follow'), $accept_only_sharer, DI::l10n()->t('The system does an auto completion of threads when a comment arrives. This has got the side effect that you can receive posts that had been started by a non-follower but had been commented by someone you follow. This setting deactivates this behaviour. When activated, you strictly only will receive posts from people you really do follow.')],
865                         '$disable_cw' => ['disable_cw', DI::l10n()->t('Disable Content Warning'), $disable_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 disables the automatic collapsing and sets the content warning as the post title. Doesn\'t affect any other content filtering you eventually set up.')],
866                         '$no_intelligent_shortening' => ['no_intelligent_shortening', DI::l10n()->t('Disable intelligent shortening'), $no_intelligent_shortening, DI::l10n()->t('Normally the system tries to find the best link to add to shortened posts. If this option is enabled then every shortened post will always point to the original friendica post.')],
867                         '$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.')],
868                         '$ostatus_autofriend' => ['snautofollow', DI::l10n()->t("Automatically follow any GNU Social \x28OStatus\x29 followers/mentioners"), $ostatus_autofriend, DI::l10n()->t('If you receive a message from an unknown OStatus user, this option decides what to do. If it is checked, a new contact will be created for every unknown user.')],
869                         '$default_group' => Group::displayGroupSelection(local_user(), $default_group, DI::l10n()->t("Default group for OStatus contacts")),
870                         '$legacy_contact' => ['legacy_contact', DI::l10n()->t('Your legacy GNU Social account'), $legacy_contact, DI::l10n()->t("If you enter your old GNU Social/Statusnet account name here \x28in the format user@domain.tld\x29, your contacts will be added automatically. The field will be emptied when done.")],
871
872                         '$repair_ostatus_url' => DI::baseUrl() . '/repair_ostatus',
873                         '$repair_ostatus_text' => DI::l10n()->t('Repair OStatus subscriptions'),
874
875                         '$settings_connectors' => $settings_connectors,
876
877                         '$h_imap' => DI::l10n()->t('Email/Mailbox Setup'),
878                         '$imap_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."),
879                         '$imap_lastcheck' => ['imap_lastcheck', DI::l10n()->t('Last successful email check:'), $mail_chk, ''],
880                         '$mail_disabled' => $mail_disabled_message,
881                         '$mail_server'  => ['mail_server',      DI::l10n()->t('IMAP server name:'), $mail_server, ''],
882                         '$mail_port'    => ['mail_port',        DI::l10n()->t('IMAP port:'), $mail_port, ''],
883                         '$mail_ssl'     => ['mail_ssl',         DI::l10n()->t('Security:'), strtoupper($mail_ssl), '', $ssl_options],
884                         '$mail_user'    => ['mail_user',        DI::l10n()->t('Email login name:'), $mail_user, ''],
885                         '$mail_pass'    => ['mail_pass',        DI::l10n()->t('Email password:'), '', ''],
886                         '$mail_replyto' => ['mail_replyto',     DI::l10n()->t('Reply-to address:'), $mail_replyto, 'Optional'],
887                         '$mail_pubmail' => ['mail_pubmail',     DI::l10n()->t('Send public posts to all email contacts:'), $mail_pubmail, ''],
888                         '$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')]],
889                         '$mail_movetofolder' => ['mail_movetofolder', DI::l10n()->t('Move to folder:'), $mail_movetofolder, ''],
890                         '$submit' => DI::l10n()->t('Save Settings'),
891                 ]);
892
893                 Hook::callAll('display_settings', $o);
894                 return $o;
895         }
896
897         /*
898          * DISPLAY SETTINGS
899          */
900         if (($a->argc > 1) && ($a->argv[1] === 'display')) {
901                 $default_theme = DI::config()->get('system', 'theme');
902                 if (!$default_theme) {
903                         $default_theme = 'default';
904                 }
905                 $default_mobile_theme = DI::config()->get('system', 'mobile-theme');
906                 if (!$default_mobile_theme) {
907                         $default_mobile_theme = 'none';
908                 }
909
910                 $allowed_themes = Theme::getAllowedList();
911
912                 $themes = [];
913                 $mobile_themes = ["---" => DI::l10n()->t('No special theme for mobile devices')];
914                 foreach ($allowed_themes as $theme) {
915                         $is_experimental = file_exists('view/theme/' . $theme . '/experimental');
916                         $is_unsupported  = file_exists('view/theme/' . $theme . '/unsupported');
917                         $is_mobile       = file_exists('view/theme/' . $theme . '/mobile');
918                         if (!$is_experimental || ($is_experimental && (DI::config()->get('experimentals', 'exp_themes')==1 || is_null(DI::config()->get('experimentals', 'exp_themes'))))) {
919                                 $theme_name = ucfirst($theme);
920                                 if ($is_unsupported) {
921                                         $theme_name = DI::l10n()->t('%s - (Unsupported)', $theme_name);
922                                 } elseif ($is_experimental) {
923                                         $theme_name = DI::l10n()->t('%s - (Experimental)', $theme_name);
924                                 }
925
926                                 if ($is_mobile) {
927                                         $mobile_themes[$theme] = $theme_name;
928                                 } else {
929                                         $themes[$theme] = $theme_name;
930                                 }
931                         }
932                 }
933
934                 $theme_selected        = $a->user['theme'] ?: $default_theme;
935                 $mobile_theme_selected = Session::get('mobile-theme', $default_mobile_theme);
936
937                 $nowarn_insecure = intval(DI::pConfig()->get(local_user(), 'system', 'nowarn_insecure'));
938
939                 $browser_update = intval(DI::pConfig()->get(local_user(), 'system', 'update_interval'));
940                 if (intval($browser_update) != -1) {
941                         $browser_update = (($browser_update == 0) ? 40 : $browser_update / 1000); // default if not set: 40 seconds
942                 }
943
944                 $itemspage_network = intval(DI::pConfig()->get(local_user(), 'system', 'itemspage_network'));
945                 $itemspage_network = (($itemspage_network > 0 && $itemspage_network < 101) ? $itemspage_network : DI::config()->get('system', 'itemspage_network'));
946                 $itemspage_mobile_network = intval(DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network'));
947                 $itemspage_mobile_network = (($itemspage_mobile_network > 0 && $itemspage_mobile_network < 101) ? $itemspage_mobile_network : DI::config()->get('system', 'itemspage_network_mobile'));
948
949                 $nosmile = DI::pConfig()->get(local_user(), 'system', 'no_smilies', 0);
950                 $first_day_of_week = DI::pConfig()->get(local_user(), 'system', 'first_day_of_week', 0);
951                 $weekdays = [0 => DI::l10n()->t("Sunday"), 1 => DI::l10n()->t("Monday")];
952
953                 $noinfo = DI::pConfig()->get(local_user(), 'system', 'ignore_info', 0);
954                 $infinite_scroll = DI::pConfig()->get(local_user(), 'system', 'infinite_scroll', 0);
955                 $no_auto_update = DI::pConfig()->get(local_user(), 'system', 'no_auto_update', 0);
956                 $bandwidth_saver = DI::pConfig()->get(local_user(), 'system', 'bandwidth_saver', 0);
957                 $no_smart_threading = DI::pConfig()->get(local_user(), 'system', 'no_smart_threading', 0);
958
959                 $theme_config = "";
960                 if (($themeconfigfile = get_theme_config_file($theme_selected)) !== null) {
961                         require_once $themeconfigfile;
962                         $theme_config = theme_content($a);
963                 }
964
965                 $tpl = Renderer::getMarkupTemplate('settings/display.tpl');
966                 $o = Renderer::replaceMacros($tpl, [
967                         '$ptitle'       => DI::l10n()->t('Display Settings'),
968                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_display"),
969                         '$submit'       => DI::l10n()->t('Save Settings'),
970                         '$baseurl' => DI::baseUrl()->get(true),
971                         '$uid' => local_user(),
972
973                         '$theme'        => ['theme', DI::l10n()->t('Display Theme:'), $theme_selected, '', $themes, true],
974                         '$mobile_theme' => ['mobile_theme', DI::l10n()->t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, false],
975                         '$nowarn_insecure' => ['nowarn_insecure',  DI::l10n()->t('Suppress warning of insecure networks'), $nowarn_insecure, DI::l10n()->t("Should the system suppress the warning that the current group contains members of networks that can't receive non public postings.")],
976                         '$ajaxint'   => ['browser_update',  DI::l10n()->t("Update browser every xx seconds"), $browser_update, DI::l10n()->t('Minimum of 10 seconds. Enter -1 to disable it.')],
977                         '$itemspage_network'   => ['itemspage_network',  DI::l10n()->t("Number of items to display per page:"), $itemspage_network, DI::l10n()->t('Maximum of 100 items')],
978                         '$itemspage_mobile_network'   => ['itemspage_mobile_network',  DI::l10n()->t("Number of items to display per page when viewed from mobile device:"), $itemspage_mobile_network, DI::l10n()->t('Maximum of 100 items')],
979                         '$nosmile'      => ['nosmile', DI::l10n()->t("Don't show emoticons"), $nosmile, ''],
980                         '$calendar_title' => DI::l10n()->t('Calendar'),
981                         '$first_day_of_week'    => ['first_day_of_week', DI::l10n()->t('Beginning of week:'), $first_day_of_week, '', $weekdays, false],
982                         '$noinfo'       => ['noinfo', DI::l10n()->t("Don't show notices"), $noinfo, ''],
983                         '$infinite_scroll'      => ['infinite_scroll', DI::l10n()->t("Infinite scroll"), $infinite_scroll, ''],
984                         '$no_auto_update'       => ['no_auto_update', DI::l10n()->t("Automatic updates only at the top of the network page"), $no_auto_update, DI::l10n()->t('When disabled, the network page is updated all the time, which could be confusing while reading.')],
985                         '$bandwidth_saver' => ['bandwidth_saver', DI::l10n()->t('Bandwidth Saver Mode'), $bandwidth_saver, DI::l10n()->t('When enabled, embedded content is not displayed on automatic updates, they only show on page reload.')],
986                         '$no_smart_threading' => ['no_smart_threading', DI::l10n()->t('Disable Smart Threading'), $no_smart_threading, DI::l10n()->t('Disable the automatic suppression of extraneous thread indentation.')],
987
988                         '$d_tset' => DI::l10n()->t('General Theme Settings'),
989                         '$d_ctset' => DI::l10n()->t('Custom Theme Settings'),
990                         '$d_cset' => DI::l10n()->t('Content Settings'),
991                         'stitle' => DI::l10n()->t('Theme settings'),
992                         '$theme_config' => $theme_config,
993                 ]);
994
995                 return $o;
996         }
997
998
999         /*
1000          * ACCOUNT SETTINGS
1001          */
1002
1003         $profile = DBA::selectFirst('profile', [], ['uid' => local_user()]);
1004         if (!DBA::isResult($profile)) {
1005                 notice(DI::l10n()->t('Unable to find your profile. Please contact your admin.') . EOL);
1006                 return;
1007         }
1008
1009         $username   = $a->user['username'];
1010         $email      = $a->user['email'];
1011         $nickname   = $a->user['nickname'];
1012         $timezone   = $a->user['timezone'];
1013         $language   = $a->user['language'];
1014         $notify     = $a->user['notify-flags'];
1015         $defloc     = $a->user['default-location'];
1016         $openid     = $a->user['openid'];
1017         $maxreq     = $a->user['maxreq'];
1018         $expire     = ((intval($a->user['expire'])) ? $a->user['expire'] : '');
1019         $unkmail    = $a->user['unkmail'];
1020         $cntunkmail = $a->user['cntunkmail'];
1021
1022         $expire_items = DI::pConfig()->get(local_user(), 'expire', 'items', true);
1023         $expire_notes = DI::pConfig()->get(local_user(), 'expire', 'notes', true);
1024         $expire_starred = DI::pConfig()->get(local_user(), 'expire', 'starred', true);
1025         $expire_photos = DI::pConfig()->get(local_user(), 'expire', 'photos', false);
1026         $expire_network_only = DI::pConfig()->get(local_user(), 'expire', 'network_only', false);
1027         $suggestme = DI::pConfig()->get(local_user(), 'system', 'suggestme', false);
1028
1029         // nowarn_insecure
1030
1031         if (!strlen($a->user['timezone'])) {
1032                 $timezone = date_default_timezone_get();
1033         }
1034
1035         // Set the account type to "Community" when the page is a community page but the account type doesn't fit
1036         // This is only happening on the first visit after the update
1037         if (in_array($a->user['page-flags'], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]) &&
1038                 ($a->user['account-type'] != User::ACCOUNT_TYPE_COMMUNITY))
1039                 $a->user['account-type'] = User::ACCOUNT_TYPE_COMMUNITY;
1040
1041         $pageset_tpl = Renderer::getMarkupTemplate('settings/pagetypes.tpl');
1042
1043         $pagetype = Renderer::replaceMacros($pageset_tpl, [
1044                 '$account_types'        => DI::l10n()->t("Account Types"),
1045                 '$user'                 => DI::l10n()->t("Personal Page Subtypes"),
1046                 '$community'            => DI::l10n()->t("Community Forum Subtypes"),
1047                 '$account_type'         => $a->user['account-type'],
1048                 '$type_person'          => User::ACCOUNT_TYPE_PERSON,
1049                 '$type_organisation'    => User::ACCOUNT_TYPE_ORGANISATION,
1050                 '$type_news'            => User::ACCOUNT_TYPE_NEWS,
1051                 '$type_community'       => User::ACCOUNT_TYPE_COMMUNITY,
1052
1053                 '$account_person'       => ['account-type', DI::l10n()->t('Personal Page'), User::ACCOUNT_TYPE_PERSON,
1054                                                                         DI::l10n()->t('Account for a personal profile.'),
1055                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_PERSON)],
1056
1057                 '$account_organisation' => ['account-type', DI::l10n()->t('Organisation Page'), User::ACCOUNT_TYPE_ORGANISATION,
1058                                                                         DI::l10n()->t('Account for an organisation that automatically approves contact requests as "Followers".'),
1059                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_ORGANISATION)],
1060
1061                 '$account_news'         => ['account-type', DI::l10n()->t('News Page'), User::ACCOUNT_TYPE_NEWS,
1062                                                                         DI::l10n()->t('Account for a news reflector that automatically approves contact requests as "Followers".'),
1063                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_NEWS)],
1064
1065                 '$account_community'    => ['account-type', DI::l10n()->t('Community Forum'), User::ACCOUNT_TYPE_COMMUNITY,
1066                                                                         DI::l10n()->t('Account for community discussions.'),
1067                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY)],
1068
1069                 '$page_normal'          => ['page-flags', DI::l10n()->t('Normal Account Page'), User::PAGE_FLAGS_NORMAL,
1070                                                                         DI::l10n()->t('Account for a regular personal profile that requires manual approval of "Friends" and "Followers".'),
1071                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_NORMAL)],
1072
1073                 '$page_soapbox'         => ['page-flags', DI::l10n()->t('Soapbox Page'), User::PAGE_FLAGS_SOAPBOX,
1074                                                                         DI::l10n()->t('Account for a public profile that automatically approves contact requests as "Followers".'),
1075                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_SOAPBOX)],
1076
1077                 '$page_community'       => ['page-flags', DI::l10n()->t('Public Forum'), User::PAGE_FLAGS_COMMUNITY,
1078                                                                         DI::l10n()->t('Automatically approves all contact requests.'),
1079                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)],
1080
1081                 '$page_freelove'        => ['page-flags', DI::l10n()->t('Automatic Friend Page'), User::PAGE_FLAGS_FREELOVE,
1082                                                                         DI::l10n()->t('Account for a popular profile that automatically approves contact requests as "Friends".'),
1083                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_FREELOVE)],
1084
1085                 '$page_prvgroup'        => ['page-flags', DI::l10n()->t('Private Forum [Experimental]'), User::PAGE_FLAGS_PRVGROUP,
1086                                                                         DI::l10n()->t('Requires manual approval of contact requests.'),
1087                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_PRVGROUP)],
1088
1089
1090         ]);
1091
1092         $noid = DI::config()->get('system', 'no_openid');
1093
1094         if ($noid) {
1095                 $openid_field = false;
1096         } else {
1097                 $openid_field = ['openid_url', DI::l10n()->t('OpenID:'), $openid, DI::l10n()->t("\x28Optional\x29 Allow this OpenID to login to this account."), "", "readonly", "url"];
1098         }
1099
1100         $opt_tpl = Renderer::getMarkupTemplate("field_checkbox.tpl");
1101         if (DI::config()->get('system', 'publish_all')) {
1102                 $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
1103         } else {
1104                 $profile_in_dir = Renderer::replaceMacros($opt_tpl, [
1105                         '$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')]
1106                 ]);
1107         }
1108
1109         if (strlen(DI::config()->get('system', 'directory'))) {
1110                 $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'));
1111         } else {
1112                 $net_pub_desc = '';
1113         }
1114
1115         $profile_in_net_dir = Renderer::replaceMacros($opt_tpl, [
1116                 '$field' => ['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]
1117         ]);
1118
1119         $hide_friends = Renderer::replaceMacros($opt_tpl, [
1120                 '$field' => ['hide-friends', DI::l10n()->t('Hide your contact/friend list from viewers of your default profile?'), $profile['hide-friends'], DI::l10n()->t('Your contact list won\'t be shown in your default profile page. You can decide to show your contact list separately for each additional profile you create')],
1121         ]);
1122
1123         $hide_wall = Renderer::replaceMacros($opt_tpl, [
1124                 '$field' => ['hidewall', DI::l10n()->t('Hide your profile details from anonymous viewers?'), $a->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.')],
1125         ]);
1126
1127         $blockwall = Renderer::replaceMacros($opt_tpl, [
1128                 '$field' => ['blockwall', DI::l10n()->t('Allow friends to post to your profile page?'), (intval($a->user['blockwall']) ? '0' : '1'), DI::l10n()->t('Your contacts may write posts on your profile wall. These posts will be distributed to your contacts')],
1129         ]);
1130
1131         $blocktags = Renderer::replaceMacros($opt_tpl, [
1132                 '$field' => ['blocktags', DI::l10n()->t('Allow friends to tag your posts?'), (intval($a->user['blocktags']) ? '0' : '1'), DI::l10n()->t('Your contacts can add additional tags to your posts.')],
1133         ]);
1134
1135         $suggestme = Renderer::replaceMacros($opt_tpl, [
1136                 '$field' => ['suggestme', DI::l10n()->t('Allow us to suggest you as a potential friend to new members?'), $suggestme, DI::l10n()->t('If you like, Friendica may suggest new members to add you as a contact.')],
1137         ]);
1138
1139         $unkmail = Renderer::replaceMacros($opt_tpl, [
1140                 '$field' => ['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.')],
1141         ]);
1142
1143         $tpl_addr = Renderer::getMarkupTemplate('settings/nick_set.tpl');
1144
1145         $prof_addr = Renderer::replaceMacros($tpl_addr,[
1146                 '$desc' => DI::l10n()->t("Your Identity Address is <strong>'%s'</strong> or '%s'.", $nickname . '@' . DI::baseUrl()->getHostname() . DI::baseUrl()->getUrlPath(), DI::baseUrl() . '/profile/' . $nickname),
1147                 '$basepath' => DI::baseUrl()->getHostname()
1148         ]);
1149
1150         $stpl = Renderer::getMarkupTemplate('settings/settings.tpl');
1151
1152         $expire_arr = [
1153                 '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')],
1154                 'label' => DI::l10n()->t('Expiration settings'),
1155                 'items' => ['expire_items', DI::l10n()->t('Expire posts'), $expire_items, DI::l10n()->t('When activated, posts and comments will be expired.')],
1156                 '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.')],
1157                 '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.')],
1158                 'photos' => ['expire_photos', DI::l10n()->t('Expire photos'), $expire_photos, DI::l10n()->t('When activated, photos will be expired.')],
1159                 '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.')],
1160         ];
1161
1162         $group_select = Group::displayGroupSelection(local_user(), $a->user['def_gid']);
1163
1164         // Private/public post links for the non-JS ACL form
1165         $private_post = 1;
1166         if (!empty($_REQUEST['public']) && !$_REQUEST['public']) {
1167                 $private_post = 0;
1168         }
1169
1170         $query_str = DI::args()->getQueryString();
1171         if (strpos($query_str, 'public=1') !== false) {
1172                 $query_str = str_replace(['?public=1', '&public=1'], ['', ''], $query_str);
1173         }
1174
1175         // I think $a->query_string may never have ? in it, but I could be wrong
1176         // It looks like it's from the index.php?q=[etc] rewrite that the web
1177         // server does, which converts any ? to &, e.g. suggest&ignore=61 for suggest?ignore=61
1178         if (strpos($query_str, '?') === false) {
1179                 $public_post_link = '?public=1';
1180         } else {
1181                 $public_post_link = '&public=1';
1182         }
1183
1184         /* Installed langs */
1185         $lang_choices = DI::l10n()->getAvailableLanguages();
1186
1187         /// @TODO Fix indending (or so)
1188         $o .= Renderer::replaceMacros($stpl, [
1189                 '$ptitle'       => DI::l10n()->t('Account Settings'),
1190
1191                 '$submit'       => DI::l10n()->t('Save Settings'),
1192                 '$baseurl' => DI::baseUrl()->get(true),
1193                 '$uid' => local_user(),
1194                 '$form_security_token' => BaseModule::getFormSecurityToken("settings"),
1195                 '$nickname_block' => $prof_addr,
1196
1197                 '$h_pass'       => DI::l10n()->t('Password Settings'),
1198                 '$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 (:).')],
1199                 '$password2'=> ['confirm', DI::l10n()->t('Confirm:'), '', DI::l10n()->t('Leave password fields blank unless changing')],
1200                 '$password3'=> ['opassword', DI::l10n()->t('Current Password:'), '', DI::l10n()->t('Your current password to confirm the changes')],
1201                 '$password4'=> ['mpassword', DI::l10n()->t('Password:'), '', DI::l10n()->t('Your current password to confirm the changes')],
1202                 '$oid_enable' => (!DI::config()->get('system', 'no_openid')),
1203                 '$openid'       => $openid_field,
1204                 '$delete_openid' => ['delete_openid', DI::l10n()->t('Delete OpenID URL'), false, ''],
1205
1206                 '$h_basic'      => DI::l10n()->t('Basic Settings'),
1207                 '$username' => ['username',  DI::l10n()->t('Full Name:'), $username, ''],
1208                 '$email'        => ['email', DI::l10n()->t('Email Address:'), $email, '', '', '', 'email'],
1209                 '$timezone' => ['timezone_select' , DI::l10n()->t('Your Timezone:'), Temporal::getTimezoneSelect($timezone), ''],
1210                 '$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],
1211                 '$defloc'       => ['defloc', DI::l10n()->t('Default Post Location:'), $defloc, ''],
1212                 '$allowloc' => ['allow_location', DI::l10n()->t('Use Browser Location:'), ($a->user['allow_location'] == 1), ''],
1213
1214
1215                 '$h_prv'        => DI::l10n()->t('Security and Privacy Settings'),
1216
1217                 '$maxreq'       => ['maxreq', DI::l10n()->t('Maximum Friend Requests/Day:'), $maxreq , DI::l10n()->t("\x28to prevent spam abuse\x29")],
1218                 '$permissions' => DI::l10n()->t('Default Post Permissions'),
1219                 '$permdesc' => DI::l10n()->t("\x28click to open/close\x29"),
1220                 '$visibility' => $profile['net-publish'],
1221                 '$aclselect' => ACL::getFullSelectorHTML(DI::page(), $a->user),
1222                 '$suggestme' => $suggestme,
1223                 '$blockwall'=> $blockwall, // array('blockwall', DI::l10n()->t('Allow friends to post to your profile page:'), !$blockwall, ''),
1224                 '$blocktags'=> $blocktags, // array('blocktags', DI::l10n()->t('Allow friends to tag your posts:'), !$blocktags, ''),
1225
1226                 // ACL permissions box
1227                 '$group_perms' => DI::l10n()->t('Show to Groups'),
1228                 '$contact_perms' => DI::l10n()->t('Show to Contacts'),
1229                 '$private' => DI::l10n()->t('Default Private Post'),
1230                 '$public' => DI::l10n()->t('Default Public Post'),
1231                 '$is_private' => $private_post,
1232                 '$return_path' => $query_str,
1233                 '$public_link' => $public_post_link,
1234                 '$settings_perms' => DI::l10n()->t('Default Permissions for New Posts'),
1235
1236                 '$group_select' => $group_select,
1237
1238
1239                 '$expire'       => $expire_arr,
1240
1241                 '$profile_in_dir' => $profile_in_dir,
1242                 '$profile_in_net_dir' => $profile_in_net_dir,
1243                 '$hide_friends' => $hide_friends,
1244                 '$hide_wall' => $hide_wall,
1245                 '$unkmail' => $unkmail,
1246                 '$cntunkmail'   => ['cntunkmail', DI::l10n()->t('Maximum private messages per day from unknown people:'), $cntunkmail , DI::l10n()->t("\x28to prevent spam abuse\x29")],
1247
1248
1249                 '$h_not'        => DI::l10n()->t('Notification Settings'),
1250                 '$lbl_not'      => DI::l10n()->t('Send a notification email when:'),
1251                 '$notify1'      => ['notify1', DI::l10n()->t('You receive an introduction'), ($notify & Type::INTRO), Type::INTRO, ''],
1252                 '$notify2'      => ['notify2', DI::l10n()->t('Your introductions are confirmed'), ($notify & Type::CONFIRM), Type::CONFIRM, ''],
1253                 '$notify3'      => ['notify3', DI::l10n()->t('Someone writes on your profile wall'), ($notify & Type::WALL), Type::WALL, ''],
1254                 '$notify4'      => ['notify4', DI::l10n()->t('Someone writes a followup comment'), ($notify & Type::COMMENT), Type::COMMENT, ''],
1255                 '$notify5'      => ['notify5', DI::l10n()->t('You receive a private message'), ($notify & Type::MAIL), Type::MAIL, ''],
1256                 '$notify6'  => ['notify6', DI::l10n()->t('You receive a friend suggestion'), ($notify & Type::SUGGEST), Type::SUGGEST, ''],
1257                 '$notify7'  => ['notify7', DI::l10n()->t('You are tagged in a post'), ($notify & Type::TAG_SELF), Type::TAG_SELF, ''],
1258                 '$notify8'  => ['notify8', DI::l10n()->t('You are poked/prodded/etc. in a post'), ($notify & Type::POKE), Type::POKE, ''],
1259
1260                 '$desktop_notifications' => ['desktop_notifications', DI::l10n()->t('Activate desktop notifications') , false, DI::l10n()->t('Show desktop popup on new notifications')],
1261
1262                 '$email_textonly' => ['email_textonly', DI::l10n()->t('Text-only notification emails'),
1263                                                                         DI::pConfig()->get(local_user(), 'system', 'email_textonly'),
1264                                                                         DI::l10n()->t('Send text only notification emails, without the html part')],
1265
1266                 '$detailed_notif' => ['detailed_notif', DI::l10n()->t('Show detailled notifications'),
1267                                                                         DI::pConfig()->get(local_user(), 'system', 'detailed_notif'),
1268                                                                         DI::l10n()->t('Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed.')],
1269
1270                 '$h_advn' => DI::l10n()->t('Advanced Account/Page Type Settings'),
1271                 '$h_descadvn' => DI::l10n()->t('Change the behaviour of this account for special situations'),
1272                 '$pagetype' => $pagetype,
1273
1274                 '$importcontact' => DI::l10n()->t('Import Contacts'),
1275                 '$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.'),
1276                 '$importcontact_button' => DI::l10n()->t('Upload File'),
1277                 '$importcontact_maxsize' => DI::config()->get('system', 'max_csv_file_size', 30720), 
1278                 '$relocate' => DI::l10n()->t('Relocate'),
1279                 '$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."),
1280                 '$relocate_button' => DI::l10n()->t("Resend relocate message to contacts"),
1281
1282         ]);
1283
1284         Hook::callAll('settings_form', $o);
1285
1286         $o .= '</form>' . "\r\n";
1287
1288         return $o;
1289
1290 }