]> git.mxchange.org Git - friendica.git/blob - mod/settings.php
Merge pull request #8265 from nupplaphil/task/add_license
[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'])  ? intval($_POST['itemspage_network'])  : 40;
360                 if ($itemspage_network > 100) {
361                         $itemspage_network = 100;
362                 }
363                 $itemspage_mobile_network = !empty($_POST['itemspage_mobile_network']) ? intval($_POST['itemspage_mobile_network']) : 20;
364                 if ($itemspage_mobile_network > 100) {
365                         $itemspage_mobile_network = 100;
366                 }
367
368                 if ($mobile_theme !== '') {
369                         DI::pConfig()->set(local_user(), 'system', 'mobile_theme', $mobile_theme);
370                 }
371
372                 DI::pConfig()->set(local_user(), 'system', 'nowarn_insecure'         , $nowarn_insecure);
373                 DI::pConfig()->set(local_user(), 'system', 'update_interval'         , $browser_update);
374                 DI::pConfig()->set(local_user(), 'system', 'itemspage_network'       , $itemspage_network);
375                 DI::pConfig()->set(local_user(), 'system', 'itemspage_mobile_network', $itemspage_mobile_network);
376                 DI::pConfig()->set(local_user(), 'system', 'no_smilies'              , $nosmile);
377                 DI::pConfig()->set(local_user(), 'system', 'first_day_of_week'       , $first_day_of_week);
378                 DI::pConfig()->set(local_user(), 'system', 'ignore_info'             , $noinfo);
379                 DI::pConfig()->set(local_user(), 'system', 'infinite_scroll'         , $infinite_scroll);
380                 DI::pConfig()->set(local_user(), 'system', 'no_auto_update'          , $no_auto_update);
381                 DI::pConfig()->set(local_user(), 'system', 'bandwidth_saver'         , $bandwidth_saver);
382                 DI::pConfig()->set(local_user(), 'system', 'no_smart_threading'      , $no_smart_threading);
383
384                 if (in_array($theme, Theme::getAllowedList())) {
385                         if ($theme == $a->user['theme']) {
386                                 // call theme_post only if theme has not been changed
387                                 if (($themeconfigfile = get_theme_config_file($theme)) !== null) {
388                                         require_once $themeconfigfile;
389                                         theme_post($a);
390                                 }
391                         } else {
392                                 DBA::update('user', ['theme' => $theme], ['uid' => local_user()]);
393                         }
394                 } else {
395                         notice(DI::l10n()->t('The theme you chose isn\'t available.'));
396                 }
397
398                 Hook::callAll('display_settings_post', $_POST);
399                 DI::baseUrl()->redirect('settings/display');
400                 return; // NOTREACHED
401         }
402
403         BaseModule::checkFormSecurityTokenRedirectOnError('/settings', 'settings');
404
405         // Import Contacts from CSV file
406         if (!empty($_POST['importcontact-submit'])) {
407                 if (isset($_FILES['importcontact-filename'])) {
408                         // was there an error
409                         if ($_FILES['importcontact-filename']['error'] > 0) {
410                                 Logger::notice('Contact CSV file upload error');
411                                 info(DI::l10n()->t('Contact CSV file upload error'));
412                         } else {
413                                 $csvArray = array_map('str_getcsv', file($_FILES['importcontact-filename']['tmp_name']));
414                                 // import contacts
415                                 foreach ($csvArray as $csvRow) {
416                                         // The 1st row may, or may not contain the headers of the table
417                                         // We expect the 1st field of the row to contain either the URL
418                                         // or the handle of the account, therefore we check for either
419                                         // "http" or "@" to be present in the string.
420                                         // All other fields from the row will be ignored
421                                         if ((strpos($csvRow[0],'@') !== false) || (strpos($csvRow[0],'http') !== false)) {
422                                                 Worker::add(PRIORITY_LOW, 'AddContact', $_SESSION['uid'], $csvRow[0]);
423                                         }
424                                 }
425
426                                 info(DI::l10n()->t('Importing Contacts done'));
427                                 // delete temp file
428                                 unlink($_FILES['importcontact-filename']['tmp_name']);
429                         }
430                 }
431         }
432
433         if (!empty($_POST['resend_relocate'])) {
434                 Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, local_user());
435                 info(DI::l10n()->t("Relocate message has been send to your contacts"));
436                 DI::baseUrl()->redirect('settings');
437         }
438
439         Hook::callAll('settings_post', $_POST);
440
441         if (!empty($_POST['password']) || !empty($_POST['confirm'])) {
442                 $newpass = $_POST['password'];
443                 $confirm = $_POST['confirm'];
444
445                 try {
446                         if ($newpass != $confirm) {
447                                 throw new Exception(DI::l10n()->t('Passwords do not match.'));
448                         }
449
450                         //  check if the old password was supplied correctly before changing it to the new value
451                         User::getIdFromPasswordAuthentication(local_user(), $_POST['opassword']);
452
453                         $result = User::updatePassword(local_user(), $newpass);
454                         if (!DBA::isResult($result)) {
455                                 throw new Exception(DI::l10n()->t('Password update failed. Please try again.'));
456                         }
457
458                         info(DI::l10n()->t('Password changed.'));
459                 } catch (Exception $e) {
460                         notice($e->getMessage());
461                         notice(DI::l10n()->t('Password unchanged.'));
462                 }
463         }
464
465         $username         = (!empty($_POST['username'])   ? Strings::escapeTags(trim($_POST['username']))     : '');
466         $email            = (!empty($_POST['email'])      ? Strings::escapeTags(trim($_POST['email']))        : '');
467         $timezone         = (!empty($_POST['timezone'])   ? Strings::escapeTags(trim($_POST['timezone']))     : '');
468         $language         = (!empty($_POST['language'])   ? Strings::escapeTags(trim($_POST['language']))     : '');
469
470         $defloc           = (!empty($_POST['defloc'])     ? Strings::escapeTags(trim($_POST['defloc']))       : '');
471         $maxreq           = (!empty($_POST['maxreq'])     ? intval($_POST['maxreq'])             : 0);
472         $expire           = (!empty($_POST['expire'])     ? intval($_POST['expire'])             : 0);
473         $def_gid          = (!empty($_POST['group-selection']) ? intval($_POST['group-selection']) : 0);
474
475
476         $expire_items     = (!empty($_POST['expire_items']) ? intval($_POST['expire_items'])     : 0);
477         $expire_notes     = (!empty($_POST['expire_notes']) ? intval($_POST['expire_notes'])     : 0);
478         $expire_starred   = (!empty($_POST['expire_starred']) ? intval($_POST['expire_starred']) : 0);
479         $expire_photos    = (!empty($_POST['expire_photos'])? intval($_POST['expire_photos'])    : 0);
480         $expire_network_only    = (!empty($_POST['expire_network_only'])? intval($_POST['expire_network_only'])  : 0);
481
482         $delete_openid    = ((!empty($_POST['delete_openid']) && (intval($_POST['delete_openid']) == 1)) ? 1: 0);
483
484         $allow_location   = ((!empty($_POST['allow_location']) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
485         $publish          = ((!empty($_POST['profile_in_directory']) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
486         $net_publish      = ((!empty($_POST['profile_in_netdirectory']) && (intval($_POST['profile_in_netdirectory']) == 1)) ? 1: 0);
487         $old_visibility   = ((!empty($_POST['visibility']) && (intval($_POST['visibility']) == 1)) ? 1 : 0);
488         $account_type     = ((!empty($_POST['account-type']) && (intval($_POST['account-type']))) ? intval($_POST['account-type']) : 0);
489         $page_flags       = ((!empty($_POST['page-flags']) && (intval($_POST['page-flags']))) ? intval($_POST['page-flags']) : 0);
490         $blockwall        = ((!empty($_POST['blockwall']) && (intval($_POST['blockwall']) == 1)) ? 0: 1); // this setting is inverted!
491         $blocktags        = ((!empty($_POST['blocktags']) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
492         $unkmail          = ((!empty($_POST['unkmail']) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
493         $cntunkmail       = (!empty($_POST['cntunkmail']) ? intval($_POST['cntunkmail']) : 0);
494         $suggestme        = (!empty($_POST['suggestme']) ? intval($_POST['suggestme'])  : 0);
495         $hide_friends     = (($_POST['hide-friends'] == 1) ? 1: 0);
496         $hidewall         = (($_POST['hidewall'] == 1) ? 1: 0);
497
498         $email_textonly   = (($_POST['email_textonly'] == 1) ? 1 : 0);
499         $detailed_notif   = (($_POST['detailed_notif'] == 1) ? 1 : 0);
500
501         $notify = 0;
502
503         if (!empty($_POST['notify1'])) {
504                 $notify += intval($_POST['notify1']);
505         }
506         if (!empty($_POST['notify2'])) {
507                 $notify += intval($_POST['notify2']);
508         }
509         if (!empty($_POST['notify3'])) {
510                 $notify += intval($_POST['notify3']);
511         }
512         if (!empty($_POST['notify4'])) {
513                 $notify += intval($_POST['notify4']);
514         }
515         if (!empty($_POST['notify5'])) {
516                 $notify += intval($_POST['notify5']);
517         }
518         if (!empty($_POST['notify6'])) {
519                 $notify += intval($_POST['notify6']);
520         }
521         if (!empty($_POST['notify7'])) {
522                 $notify += intval($_POST['notify7']);
523         }
524         if (!empty($_POST['notify8'])) {
525                 $notify += intval($_POST['notify8']);
526         }
527
528         // Adjust the page flag if the account type doesn't fit to the page flag.
529         if (($account_type == User::ACCOUNT_TYPE_PERSON) && !in_array($page_flags, [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE])) {
530                 $page_flags = User::PAGE_FLAGS_NORMAL;
531         } elseif (($account_type == User::ACCOUNT_TYPE_ORGANISATION) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
532                 $page_flags = User::PAGE_FLAGS_SOAPBOX;
533         } elseif (($account_type == User::ACCOUNT_TYPE_NEWS) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
534                 $page_flags = User::PAGE_FLAGS_SOAPBOX;
535         } elseif (($account_type == User::ACCOUNT_TYPE_COMMUNITY) && !in_array($page_flags, [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP])) {
536                 $page_flags = User::PAGE_FLAGS_COMMUNITY;
537         }
538
539         $err = '';
540
541         if ($username != $a->user['username']) {
542                 if (strlen($username) > 40) {
543                         $err .= DI::l10n()->t(' Please use a shorter name.');
544                 }
545                 if (strlen($username) < 3) {
546                         $err .= DI::l10n()->t(' Name too short.');
547                 }
548         }
549
550         if ($email != $a->user['email']) {
551                 //  check for the correct password
552                 if (!User::authenticate(intval(local_user()), $_POST['mpassword'])) {
553                         $err .= DI::l10n()->t('Wrong Password') . EOL;
554                         $email = $a->user['email'];
555                 }
556                 //  check the email is valid
557                 if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
558                         $err .= DI::l10n()->t('Invalid email.');
559                 }
560                 //  ensure new email is not the admin mail
561                 if (DI::config()->get('config', 'admin_email')) {
562                         $adminlist = explode(",", str_replace(" ", "", strtolower(DI::config()->get('config', 'admin_email'))));
563                         if (in_array(strtolower($email), $adminlist)) {
564                                 $err .= DI::l10n()->t('Cannot change to that email.');
565                                 $email = $a->user['email'];
566                         }
567                 }
568         }
569
570         if (strlen($err)) {
571                 notice($err . EOL);
572                 return;
573         }
574
575         if (($timezone != $a->user['timezone']) && strlen($timezone)) {
576                 date_default_timezone_set($timezone);
577         }
578
579         $aclFormatter = DI::aclFormatter();
580
581         $str_group_allow   = !empty($_POST['group_allow'])   ? $aclFormatter->toString($_POST['group_allow'])   : '';
582         $str_contact_allow = !empty($_POST['contact_allow']) ? $aclFormatter->toString($_POST['contact_allow']) : '';
583         $str_group_deny    = !empty($_POST['group_deny'])    ? $aclFormatter->toString($_POST['group_deny'])    : '';
584         $str_contact_deny  = !empty($_POST['contact_deny'])  ? $aclFormatter->toString($_POST['contact_deny'])  : '';
585
586         DI::pConfig()->set(local_user(), 'expire', 'items', $expire_items);
587         DI::pConfig()->set(local_user(), 'expire', 'notes', $expire_notes);
588         DI::pConfig()->set(local_user(), 'expire', 'starred', $expire_starred);
589         DI::pConfig()->set(local_user(), 'expire', 'photos', $expire_photos);
590         DI::pConfig()->set(local_user(), 'expire', 'network_only', $expire_network_only);
591
592         DI::pConfig()->set(local_user(), 'system', 'suggestme', $suggestme);
593
594         DI::pConfig()->set(local_user(), 'system', 'email_textonly', $email_textonly);
595         DI::pConfig()->set(local_user(), 'system', 'detailed_notif', $detailed_notif);
596
597         if ($page_flags == User::PAGE_FLAGS_PRVGROUP) {
598                 $hidewall = 1;
599                 if (!$str_contact_allow && !$str_group_allow && !$str_contact_deny && !$str_group_deny) {
600                         if ($def_gid) {
601                                 info(DI::l10n()->t('Private forum has no privacy permissions. Using default privacy group.'). EOL);
602                                 $str_group_allow = '<' . $def_gid . '>';
603                         } else {
604                                 notice(DI::l10n()->t('Private forum has no privacy permissions and no default privacy group.') . EOL);
605                         }
606                 }
607         }
608
609         $fields = ['username' => $username, 'email' => $email, 'timezone' => $timezone,
610                 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_group_allow, 'deny_cid' => $str_contact_deny, 'deny_gid' => $str_group_deny,
611                 'notify-flags' => $notify, 'page-flags' => $page_flags, 'account-type' => $account_type, 'default-location' => $defloc,
612                 'allow_location' => $allow_location, 'maxreq' => $maxreq, 'expire' => $expire, 'def_gid' => $def_gid, 'blockwall' => $blockwall,
613                 'hidewall' => $hidewall, 'blocktags' => $blocktags, 'unkmail' => $unkmail, 'cntunkmail' => $cntunkmail, 'language' => $language];
614
615         if ($delete_openid) {
616                 $fields['openid'] = '';
617                 $fields['openidserver'] = '';
618         }
619
620         if (DBA::update('user', $fields, ['uid' => local_user()])) {
621                 info(DI::l10n()->t('Settings updated.') . EOL);
622         }
623
624         // clear session language
625         unset($_SESSION['language']);
626
627         q("UPDATE `profile`
628                 SET `publish` = %d,
629                 `name` = '%s',
630                 `net-publish` = %d,
631                 `hide-friends` = %d
632                 WHERE `uid` = %d",
633                 intval($publish),
634                 DBA::escape($username),
635                 intval($net_publish),
636                 intval($hide_friends),
637                 intval(local_user())
638         );
639
640         Contact::updateSelfFromUserID(local_user());
641
642         if (($old_visibility != $net_publish) || ($page_flags != $old_page_flags)) {
643                 // Update global directory in background
644                 $url = $_SESSION['my_url'];
645                 if ($url && strlen(DI::config()->get('system', 'directory'))) {
646                         Worker::add(PRIORITY_LOW, "Directory", $url);
647                 }
648         }
649
650         Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
651
652         // Update the global contact for the user
653         GContact::updateForUser(local_user());
654
655         DI::baseUrl()->redirect('settings');
656         return; // NOTREACHED
657 }
658
659
660 function settings_content(App $a)
661 {
662         $o = '';
663         Nav::setSelected('settings');
664
665         if (!local_user()) {
666                 //notice(DI::l10n()->t('Permission denied.') . EOL);
667                 return Login::form();
668         }
669
670         if (!empty($_SESSION['submanage'])) {
671                 notice(DI::l10n()->t('Permission denied.') . EOL);
672                 return;
673         }
674
675         if (($a->argc > 1) && ($a->argv[1] === 'oauth')) {
676                 if (($a->argc > 2) && ($a->argv[2] === 'add')) {
677                         $tpl = Renderer::getMarkupTemplate('settings/oauth_edit.tpl');
678                         $o .= Renderer::replaceMacros($tpl, [
679                                 '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
680                                 '$title'        => DI::l10n()->t('Add application'),
681                                 '$submit'       => DI::l10n()->t('Save Settings'),
682                                 '$cancel'       => DI::l10n()->t('Cancel'),
683                                 '$name'         => ['name', DI::l10n()->t('Name'), '', ''],
684                                 '$key'          => ['key', DI::l10n()->t('Consumer Key'), '', ''],
685                                 '$secret'       => ['secret', DI::l10n()->t('Consumer Secret'), '', ''],
686                                 '$redirect'     => ['redirect', DI::l10n()->t('Redirect'), '', ''],
687                                 '$icon'         => ['icon', DI::l10n()->t('Icon url'), '', ''],
688                         ]);
689                         return $o;
690                 }
691
692                 if (($a->argc > 3) && ($a->argv[2] === 'edit')) {
693                         $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d",
694                                         DBA::escape($a->argv[3]),
695                                         local_user());
696
697                         if (!DBA::isResult($r)) {
698                                 notice(DI::l10n()->t("You can't edit this application."));
699                                 return;
700                         }
701                         $app = $r[0];
702
703                         $tpl = Renderer::getMarkupTemplate('settings/oauth_edit.tpl');
704                         $o .= Renderer::replaceMacros($tpl, [
705                                 '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
706                                 '$title'        => DI::l10n()->t('Add application'),
707                                 '$submit'       => DI::l10n()->t('Update'),
708                                 '$cancel'       => DI::l10n()->t('Cancel'),
709                                 '$name'         => ['name', DI::l10n()->t('Name'), $app['name'] , ''],
710                                 '$key'          => ['key', DI::l10n()->t('Consumer Key'), $app['client_id'], ''],
711                                 '$secret'       => ['secret', DI::l10n()->t('Consumer Secret'), $app['pw'], ''],
712                                 '$redirect'     => ['redirect', DI::l10n()->t('Redirect'), $app['redirect_uri'], ''],
713                                 '$icon'         => ['icon', DI::l10n()->t('Icon url'), $app['icon'], ''],
714                         ]);
715                         return $o;
716                 }
717
718                 if (($a->argc > 3) && ($a->argv[2] === 'delete')) {
719                         BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth', 't');
720
721                         DBA::delete('clients', ['client_id' => $a->argv[3], 'uid' => local_user()]);
722                         DI::baseUrl()->redirect('settings/oauth/', true);
723                         return;
724                 }
725
726                 /// @TODO validate result with DBA::isResult()
727                 $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my
728                                 FROM clients
729                                 LEFT JOIN tokens ON clients.client_id=tokens.client_id
730                                 WHERE clients.uid IN (%d, 0)",
731                                 local_user(),
732                                 local_user());
733
734
735                 $tpl = Renderer::getMarkupTemplate('settings/oauth.tpl');
736                 $o .= Renderer::replaceMacros($tpl, [
737                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
738                         '$baseurl'      => DI::baseUrl()->get(true),
739                         '$title'        => DI::l10n()->t('Connected Apps'),
740                         '$add'          => DI::l10n()->t('Add application'),
741                         '$edit'         => DI::l10n()->t('Edit'),
742                         '$delete'               => DI::l10n()->t('Delete'),
743                         '$consumerkey' => DI::l10n()->t('Client key starts with'),
744                         '$noname'       => DI::l10n()->t('No name'),
745                         '$remove'       => DI::l10n()->t('Remove authorization'),
746                         '$apps'         => $r,
747                 ]);
748                 return $o;
749         }
750
751         if (($a->argc > 1) && ($a->argv[1] === 'addon')) {
752                 $settings_addons = "";
753
754                 $r = q("SELECT * FROM `hook` WHERE `hook` = 'addon_settings' ");
755                 if (!DBA::isResult($r)) {
756                         $settings_addons = DI::l10n()->t('No Addon settings configured');
757                 }
758
759                 Hook::callAll('addon_settings', $settings_addons);
760
761
762                 $tpl = Renderer::getMarkupTemplate('settings/addons.tpl');
763                 $o .= Renderer::replaceMacros($tpl, [
764                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_addon"),
765                         '$title'        => DI::l10n()->t('Addon Settings'),
766                         '$settings_addons' => $settings_addons
767                 ]);
768                 return $o;
769         }
770
771         if (($a->argc > 1) && ($a->argv[1] === 'features')) {
772
773                 $arr = [];
774                 $features = Feature::get();
775                 foreach ($features as $fname => $fdata) {
776                         $arr[$fname] = [];
777                         $arr[$fname][0] = $fdata[0];
778                         foreach (array_slice($fdata,1) as $f) {
779                                 $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')]];
780                         }
781                 }
782
783                 $tpl = Renderer::getMarkupTemplate('settings/features.tpl');
784                 $o .= Renderer::replaceMacros($tpl, [
785                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_features"),
786                         '$title'               => DI::l10n()->t('Additional Features'),
787                         '$features'            => $arr,
788                         '$submit'              => DI::l10n()->t('Save Settings'),
789                 ]);
790                 return $o;
791         }
792
793         if (($a->argc > 1) && ($a->argv[1] === 'connectors')) {
794                 $accept_only_sharer        = intval(DI::pConfig()->get(local_user(), 'system', 'accept_only_sharer'));
795                 $disable_cw                = intval(DI::pConfig()->get(local_user(), 'system', 'disable_cw'));
796                 $no_intelligent_shortening = intval(DI::pConfig()->get(local_user(), 'system', 'no_intelligent_shortening'));
797                 $attach_link_title         = intval(DI::pConfig()->get(local_user(), 'system', 'attach_link_title'));
798                 $ostatus_autofriend        = intval(DI::pConfig()->get(local_user(), 'system', 'ostatus_autofriend'));
799                 $default_group             = DI::pConfig()->get(local_user(), 'ostatus', 'default_group');
800                 $legacy_contact            = DI::pConfig()->get(local_user(), 'ostatus', 'legacy_contact');
801
802                 if (!empty($legacy_contact)) {
803                         /// @todo Isn't it supposed to be a $a->internalRedirect() call?
804                         DI::page()['htmlhead'] = '<meta http-equiv="refresh" content="0; URL=' . DI::baseUrl().'/ostatus_subscribe?url=' . urlencode($legacy_contact) . '">';
805                 }
806
807                 $settings_connectors = '';
808                 Hook::callAll('connector_settings', $settings_connectors);
809
810                 if (is_site_admin()) {
811                         $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')));
812                         $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')));
813                 } else {
814                         $diasp_enabled = "";
815                         $ostat_enabled = "";
816                 }
817
818                 $mail_disabled = ((function_exists('imap_open') && (!DI::config()->get('system', 'imap_disabled'))) ? 0 : 1);
819                 if (DI::config()->get('system', 'dfrn_only')) {
820                         $mail_disabled = 1;
821                 }
822                 if (!$mail_disabled) {
823                         $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
824                                 local_user()
825                         );
826                 } else {
827                         $r = null;
828                 }
829
830                 $mail_server       = ((DBA::isResult($r)) ? $r[0]['server'] : '');
831                 $mail_port         = ((DBA::isResult($r) && intval($r[0]['port'])) ? intval($r[0]['port']) : '');
832                 $mail_ssl          = ((DBA::isResult($r)) ? $r[0]['ssltype'] : '');
833                 $mail_user         = ((DBA::isResult($r)) ? $r[0]['user'] : '');
834                 $mail_replyto      = ((DBA::isResult($r)) ? $r[0]['reply_to'] : '');
835                 $mail_pubmail      = ((DBA::isResult($r)) ? $r[0]['pubmail'] : 0);
836                 $mail_action       = ((DBA::isResult($r)) ? $r[0]['action'] : 0);
837                 $mail_movetofolder = ((DBA::isResult($r)) ? $r[0]['movetofolder'] : '');
838                 $mail_chk          = ((DBA::isResult($r)) ? $r[0]['last_check'] : DBA::NULL_DATETIME);
839
840
841                 $tpl = Renderer::getMarkupTemplate('settings/connectors.tpl');
842
843                 $mail_disabled_message = ($mail_disabled ? DI::l10n()->t('Email access is disabled on this site.') : '');
844
845                 $ssl_options = ['TLS' => 'TLS', 'SSL' => 'SSL'];
846
847                 if (DI::config()->get('system', 'insecure_imap')) {
848                         $ssl_options['notls'] = DI::l10n()->t('None');
849                 }
850
851                 $o .= Renderer::replaceMacros($tpl, [
852                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_connectors"),
853
854                         '$title'        => DI::l10n()->t('Social Networks'),
855
856                         '$diasp_enabled' => $diasp_enabled,
857                         '$ostat_enabled' => $ostat_enabled,
858
859                         '$general_settings' => DI::l10n()->t('General Social Media Settings'),
860                         '$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.')],
861                         '$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.')],
862                         '$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.')],
863                         '$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.')],
864                         '$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.')],
865                         '$default_group' => Group::displayGroupSelection(local_user(), $default_group, DI::l10n()->t("Default group for OStatus contacts")),
866                         '$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.")],
867
868                         '$repair_ostatus_url' => DI::baseUrl() . '/repair_ostatus',
869                         '$repair_ostatus_text' => DI::l10n()->t('Repair OStatus subscriptions'),
870
871                         '$settings_connectors' => $settings_connectors,
872
873                         '$h_imap' => DI::l10n()->t('Email/Mailbox Setup'),
874                         '$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."),
875                         '$imap_lastcheck' => ['imap_lastcheck', DI::l10n()->t('Last successful email check:'), $mail_chk, ''],
876                         '$mail_disabled' => $mail_disabled_message,
877                         '$mail_server'  => ['mail_server',      DI::l10n()->t('IMAP server name:'), $mail_server, ''],
878                         '$mail_port'    => ['mail_port',        DI::l10n()->t('IMAP port:'), $mail_port, ''],
879                         '$mail_ssl'     => ['mail_ssl',         DI::l10n()->t('Security:'), strtoupper($mail_ssl), '', $ssl_options],
880                         '$mail_user'    => ['mail_user',        DI::l10n()->t('Email login name:'), $mail_user, ''],
881                         '$mail_pass'    => ['mail_pass',        DI::l10n()->t('Email password:'), '', ''],
882                         '$mail_replyto' => ['mail_replyto',     DI::l10n()->t('Reply-to address:'), $mail_replyto, 'Optional'],
883                         '$mail_pubmail' => ['mail_pubmail',     DI::l10n()->t('Send public posts to all email contacts:'), $mail_pubmail, ''],
884                         '$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')]],
885                         '$mail_movetofolder' => ['mail_movetofolder', DI::l10n()->t('Move to folder:'), $mail_movetofolder, ''],
886                         '$submit' => DI::l10n()->t('Save Settings'),
887                 ]);
888
889                 Hook::callAll('display_settings', $o);
890                 return $o;
891         }
892
893         /*
894          * DISPLAY SETTINGS
895          */
896         if (($a->argc > 1) && ($a->argv[1] === 'display')) {
897                 $default_theme = DI::config()->get('system', 'theme');
898                 if (!$default_theme) {
899                         $default_theme = 'default';
900                 }
901                 $default_mobile_theme = DI::config()->get('system', 'mobile-theme');
902                 if (!$default_mobile_theme) {
903                         $default_mobile_theme = 'none';
904                 }
905
906                 $allowed_themes = Theme::getAllowedList();
907
908                 $themes = [];
909                 $mobile_themes = ["---" => DI::l10n()->t('No special theme for mobile devices')];
910                 foreach ($allowed_themes as $theme) {
911                         $is_experimental = file_exists('view/theme/' . $theme . '/experimental');
912                         $is_unsupported  = file_exists('view/theme/' . $theme . '/unsupported');
913                         $is_mobile       = file_exists('view/theme/' . $theme . '/mobile');
914                         if (!$is_experimental || ($is_experimental && (DI::config()->get('experimentals', 'exp_themes')==1 || is_null(DI::config()->get('experimentals', 'exp_themes'))))) {
915                                 $theme_name = ucfirst($theme);
916                                 if ($is_unsupported) {
917                                         $theme_name = DI::l10n()->t('%s - (Unsupported)', $theme_name);
918                                 } elseif ($is_experimental) {
919                                         $theme_name = DI::l10n()->t('%s - (Experimental)', $theme_name);
920                                 }
921
922                                 if ($is_mobile) {
923                                         $mobile_themes[$theme] = $theme_name;
924                                 } else {
925                                         $themes[$theme] = $theme_name;
926                                 }
927                         }
928                 }
929
930                 $theme_selected        = $a->user['theme'] ?: $default_theme;
931                 $mobile_theme_selected = Session::get('mobile-theme', $default_mobile_theme);
932
933                 $nowarn_insecure = intval(DI::pConfig()->get(local_user(), 'system', 'nowarn_insecure'));
934
935                 $browser_update = intval(DI::pConfig()->get(local_user(), 'system', 'update_interval'));
936                 if (intval($browser_update) != -1) {
937                         $browser_update = (($browser_update == 0) ? 40 : $browser_update / 1000); // default if not set: 40 seconds
938                 }
939
940                 $itemspage_network = intval(DI::pConfig()->get(local_user(), 'system', 'itemspage_network'));
941                 $itemspage_network = (($itemspage_network > 0 && $itemspage_network < 101) ? $itemspage_network : 40); // default if not set: 40 items
942                 $itemspage_mobile_network = intval(DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network'));
943                 $itemspage_mobile_network = (($itemspage_mobile_network > 0 && $itemspage_mobile_network < 101) ? $itemspage_mobile_network : 20); // default if not set: 20 items
944
945                 $nosmile = DI::pConfig()->get(local_user(), 'system', 'no_smilies', 0);
946                 $first_day_of_week = DI::pConfig()->get(local_user(), 'system', 'first_day_of_week', 0);
947                 $weekdays = [0 => DI::l10n()->t("Sunday"), 1 => DI::l10n()->t("Monday")];
948
949                 $noinfo = DI::pConfig()->get(local_user(), 'system', 'ignore_info', 0);
950                 $infinite_scroll = DI::pConfig()->get(local_user(), 'system', 'infinite_scroll', 0);
951                 $no_auto_update = DI::pConfig()->get(local_user(), 'system', 'no_auto_update', 0);
952                 $bandwidth_saver = DI::pConfig()->get(local_user(), 'system', 'bandwidth_saver', 0);
953                 $no_smart_threading = DI::pConfig()->get(local_user(), 'system', 'no_smart_threading', 0);
954
955                 $theme_config = "";
956                 if (($themeconfigfile = get_theme_config_file($theme_selected)) !== null) {
957                         require_once $themeconfigfile;
958                         $theme_config = theme_content($a);
959                 }
960
961                 $tpl = Renderer::getMarkupTemplate('settings/display.tpl');
962                 $o = Renderer::replaceMacros($tpl, [
963                         '$ptitle'       => DI::l10n()->t('Display Settings'),
964                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_display"),
965                         '$submit'       => DI::l10n()->t('Save Settings'),
966                         '$baseurl' => DI::baseUrl()->get(true),
967                         '$uid' => local_user(),
968
969                         '$theme'        => ['theme', DI::l10n()->t('Display Theme:'), $theme_selected, '', $themes, true],
970                         '$mobile_theme' => ['mobile_theme', DI::l10n()->t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, false],
971                         '$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.")],
972                         '$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.')],
973                         '$itemspage_network'   => ['itemspage_network',  DI::l10n()->t("Number of items to display per page:"), $itemspage_network, DI::l10n()->t('Maximum of 100 items')],
974                         '$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')],
975                         '$nosmile'      => ['nosmile', DI::l10n()->t("Don't show emoticons"), $nosmile, ''],
976                         '$calendar_title' => DI::l10n()->t('Calendar'),
977                         '$first_day_of_week'    => ['first_day_of_week', DI::l10n()->t('Beginning of week:'), $first_day_of_week, '', $weekdays, false],
978                         '$noinfo'       => ['noinfo', DI::l10n()->t("Don't show notices"), $noinfo, ''],
979                         '$infinite_scroll'      => ['infinite_scroll', DI::l10n()->t("Infinite scroll"), $infinite_scroll, ''],
980                         '$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.')],
981                         '$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.')],
982                         '$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.')],
983
984                         '$d_tset' => DI::l10n()->t('General Theme Settings'),
985                         '$d_ctset' => DI::l10n()->t('Custom Theme Settings'),
986                         '$d_cset' => DI::l10n()->t('Content Settings'),
987                         'stitle' => DI::l10n()->t('Theme settings'),
988                         '$theme_config' => $theme_config,
989                 ]);
990
991                 return $o;
992         }
993
994
995         /*
996          * ACCOUNT SETTINGS
997          */
998
999         $profile = DBA::selectFirst('profile', [], ['uid' => local_user()]);
1000         if (!DBA::isResult($profile)) {
1001                 notice(DI::l10n()->t('Unable to find your profile. Please contact your admin.') . EOL);
1002                 return;
1003         }
1004
1005         $username   = $a->user['username'];
1006         $email      = $a->user['email'];
1007         $nickname   = $a->user['nickname'];
1008         $timezone   = $a->user['timezone'];
1009         $language   = $a->user['language'];
1010         $notify     = $a->user['notify-flags'];
1011         $defloc     = $a->user['default-location'];
1012         $openid     = $a->user['openid'];
1013         $maxreq     = $a->user['maxreq'];
1014         $expire     = ((intval($a->user['expire'])) ? $a->user['expire'] : '');
1015         $unkmail    = $a->user['unkmail'];
1016         $cntunkmail = $a->user['cntunkmail'];
1017
1018         $expire_items = DI::pConfig()->get(local_user(), 'expire', 'items', true);
1019         $expire_notes = DI::pConfig()->get(local_user(), 'expire', 'notes', true);
1020         $expire_starred = DI::pConfig()->get(local_user(), 'expire', 'starred', true);
1021         $expire_photos = DI::pConfig()->get(local_user(), 'expire', 'photos', false);
1022         $expire_network_only = DI::pConfig()->get(local_user(), 'expire', 'network_only', false);
1023         $suggestme = DI::pConfig()->get(local_user(), 'system', 'suggestme', false);
1024
1025         // nowarn_insecure
1026
1027         if (!strlen($a->user['timezone'])) {
1028                 $timezone = date_default_timezone_get();
1029         }
1030
1031         // Set the account type to "Community" when the page is a community page but the account type doesn't fit
1032         // This is only happening on the first visit after the update
1033         if (in_array($a->user['page-flags'], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]) &&
1034                 ($a->user['account-type'] != User::ACCOUNT_TYPE_COMMUNITY))
1035                 $a->user['account-type'] = User::ACCOUNT_TYPE_COMMUNITY;
1036
1037         $pageset_tpl = Renderer::getMarkupTemplate('settings/pagetypes.tpl');
1038
1039         $pagetype = Renderer::replaceMacros($pageset_tpl, [
1040                 '$account_types'        => DI::l10n()->t("Account Types"),
1041                 '$user'                 => DI::l10n()->t("Personal Page Subtypes"),
1042                 '$community'            => DI::l10n()->t("Community Forum Subtypes"),
1043                 '$account_type'         => $a->user['account-type'],
1044                 '$type_person'          => User::ACCOUNT_TYPE_PERSON,
1045                 '$type_organisation'    => User::ACCOUNT_TYPE_ORGANISATION,
1046                 '$type_news'            => User::ACCOUNT_TYPE_NEWS,
1047                 '$type_community'       => User::ACCOUNT_TYPE_COMMUNITY,
1048
1049                 '$account_person'       => ['account-type', DI::l10n()->t('Personal Page'), User::ACCOUNT_TYPE_PERSON,
1050                                                                         DI::l10n()->t('Account for a personal profile.'),
1051                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_PERSON)],
1052
1053                 '$account_organisation' => ['account-type', DI::l10n()->t('Organisation Page'), User::ACCOUNT_TYPE_ORGANISATION,
1054                                                                         DI::l10n()->t('Account for an organisation that automatically approves contact requests as "Followers".'),
1055                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_ORGANISATION)],
1056
1057                 '$account_news'         => ['account-type', DI::l10n()->t('News Page'), User::ACCOUNT_TYPE_NEWS,
1058                                                                         DI::l10n()->t('Account for a news reflector that automatically approves contact requests as "Followers".'),
1059                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_NEWS)],
1060
1061                 '$account_community'    => ['account-type', DI::l10n()->t('Community Forum'), User::ACCOUNT_TYPE_COMMUNITY,
1062                                                                         DI::l10n()->t('Account for community discussions.'),
1063                                                                         ($a->user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY)],
1064
1065                 '$page_normal'          => ['page-flags', DI::l10n()->t('Normal Account Page'), User::PAGE_FLAGS_NORMAL,
1066                                                                         DI::l10n()->t('Account for a regular personal profile that requires manual approval of "Friends" and "Followers".'),
1067                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_NORMAL)],
1068
1069                 '$page_soapbox'         => ['page-flags', DI::l10n()->t('Soapbox Page'), User::PAGE_FLAGS_SOAPBOX,
1070                                                                         DI::l10n()->t('Account for a public profile that automatically approves contact requests as "Followers".'),
1071                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_SOAPBOX)],
1072
1073                 '$page_community'       => ['page-flags', DI::l10n()->t('Public Forum'), User::PAGE_FLAGS_COMMUNITY,
1074                                                                         DI::l10n()->t('Automatically approves all contact requests.'),
1075                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)],
1076
1077                 '$page_freelove'        => ['page-flags', DI::l10n()->t('Automatic Friend Page'), User::PAGE_FLAGS_FREELOVE,
1078                                                                         DI::l10n()->t('Account for a popular profile that automatically approves contact requests as "Friends".'),
1079                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_FREELOVE)],
1080
1081                 '$page_prvgroup'        => ['page-flags', DI::l10n()->t('Private Forum [Experimental]'), User::PAGE_FLAGS_PRVGROUP,
1082                                                                         DI::l10n()->t('Requires manual approval of contact requests.'),
1083                                                                         ($a->user['page-flags'] == User::PAGE_FLAGS_PRVGROUP)],
1084
1085
1086         ]);
1087
1088         $noid = DI::config()->get('system', 'no_openid');
1089
1090         if ($noid) {
1091                 $openid_field = false;
1092         } else {
1093                 $openid_field = ['openid_url', DI::l10n()->t('OpenID:'), $openid, DI::l10n()->t("\x28Optional\x29 Allow this OpenID to login to this account."), "", "readonly", "url"];
1094         }
1095
1096         $opt_tpl = Renderer::getMarkupTemplate("field_checkbox.tpl");
1097         if (DI::config()->get('system', 'publish_all')) {
1098                 $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
1099         } else {
1100                 $profile_in_dir = Renderer::replaceMacros($opt_tpl, [
1101                         '$field' => ['profile_in_directory', DI::l10n()->t('Publish your default 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')]
1102                 ]);
1103         }
1104
1105         if (strlen(DI::config()->get('system', 'directory'))) {
1106                 $profile_in_net_dir = Renderer::replaceMacros($opt_tpl, [
1107                         '$field' => ['profile_in_netdirectory', DI::l10n()->t('Publish your default profile in the global social directory?'), $profile['net-publish'], DI::l10n()->t('Your profile will be published in the global friendica directories (e.g. <a href="%s">%s</a>). Your profile will be visible in public.', DI::config()->get('system', 'directory'), DI::config()->get('system', 'directory'))     . " " . DI::l10n()->t("This setting also determines whether Friendica will inform search engines that your profile should be indexed or not. Third-party search engines may or may not respect this setting.")]
1108                 ]);
1109         } else {
1110                 $profile_in_net_dir = '';
1111         }
1112
1113         $hide_friends = Renderer::replaceMacros($opt_tpl, [
1114                 '$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')],
1115         ]);
1116
1117         $hide_wall = Renderer::replaceMacros($opt_tpl, [
1118                 '$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.')],
1119         ]);
1120
1121         $blockwall = Renderer::replaceMacros($opt_tpl, [
1122                 '$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')],
1123         ]);
1124
1125         $blocktags = Renderer::replaceMacros($opt_tpl, [
1126                 '$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.')],
1127         ]);
1128
1129         $suggestme = Renderer::replaceMacros($opt_tpl, [
1130                 '$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.')],
1131         ]);
1132
1133         $unkmail = Renderer::replaceMacros($opt_tpl, [
1134                 '$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.')],
1135         ]);
1136
1137         if (!$profile['publish'] && !$profile['net-publish']) {
1138                 info(DI::l10n()->t('Profile is <strong>not published</strong>.') . EOL);
1139         }
1140
1141         $tpl_addr = Renderer::getMarkupTemplate('settings/nick_set.tpl');
1142
1143         $prof_addr = Renderer::replaceMacros($tpl_addr,[
1144                 '$desc' => DI::l10n()->t("Your Identity Address is <strong>'%s'</strong> or '%s'.", $nickname . '@' . DI::baseUrl()->getHostname() . DI::baseUrl()->getUrlPath(), DI::baseUrl() . '/profile/' . $nickname),
1145                 '$basepath' => DI::baseUrl()->getHostname()
1146         ]);
1147
1148         $stpl = Renderer::getMarkupTemplate('settings/settings.tpl');
1149
1150         $expire_arr = [
1151                 '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')],
1152                 'advanced' => DI::l10n()->t('Advanced expiration settings'),
1153                 'label' => DI::l10n()->t('Advanced Expiration'),
1154                 'items' => ['expire_items',  DI::l10n()->t("Expire posts:"), $expire_items],
1155                 'notes' => ['expire_notes',  DI::l10n()->t("Expire personal notes:"), $expire_notes],
1156                 'starred' => ['expire_starred',  DI::l10n()->t("Expire starred posts:"), $expire_starred],
1157                 'photos' => ['expire_photos',  DI::l10n()->t("Expire photos:"), $expire_photos],
1158                 'network_only' => ['expire_network_only',  DI::l10n()->t("Only expire posts by others:"), $expire_network_only],
1159         ];
1160
1161         $group_select = Group::displayGroupSelection(local_user(), $a->user['def_gid']);
1162
1163         // Private/public post links for the non-JS ACL form
1164         $private_post = 1;
1165         if (!empty($_REQUEST['public']) && !$_REQUEST['public']) {
1166                 $private_post = 0;
1167         }
1168
1169         $query_str = DI::args()->getQueryString();
1170         if (strpos($query_str, 'public=1') !== false) {
1171                 $query_str = str_replace(['?public=1', '&public=1'], ['', ''], $query_str);
1172         }
1173
1174         // I think $a->query_string may never have ? in it, but I could be wrong
1175         // It looks like it's from the index.php?q=[etc] rewrite that the web
1176         // server does, which converts any ? to &, e.g. suggest&ignore=61 for suggest?ignore=61
1177         if (strpos($query_str, '?') === false) {
1178                 $public_post_link = '?public=1';
1179         } else {
1180                 $public_post_link = '&public=1';
1181         }
1182
1183         /* Installed langs */
1184         $lang_choices = DI::l10n()->getAvailableLanguages();
1185
1186         /// @TODO Fix indending (or so)
1187         $o .= Renderer::replaceMacros($stpl, [
1188                 '$ptitle'       => DI::l10n()->t('Account Settings'),
1189
1190                 '$submit'       => DI::l10n()->t('Save Settings'),
1191                 '$baseurl' => DI::baseUrl()->get(true),
1192                 '$uid' => local_user(),
1193                 '$form_security_token' => BaseModule::getFormSecurityToken("settings"),
1194                 '$nickname_block' => $prof_addr,
1195
1196                 '$h_pass'       => DI::l10n()->t('Password Settings'),
1197                 '$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 (:).')],
1198                 '$password2'=> ['confirm', DI::l10n()->t('Confirm:'), '', DI::l10n()->t('Leave password fields blank unless changing')],
1199                 '$password3'=> ['opassword', DI::l10n()->t('Current Password:'), '', DI::l10n()->t('Your current password to confirm the changes')],
1200                 '$password4'=> ['mpassword', DI::l10n()->t('Password:'), '', DI::l10n()->t('Your current password to confirm the changes')],
1201                 '$oid_enable' => (!DI::config()->get('system', 'no_openid')),
1202                 '$openid'       => $openid_field,
1203                 '$delete_openid' => ['delete_openid', DI::l10n()->t('Delete OpenID URL'), false, ''],
1204
1205                 '$h_basic'      => DI::l10n()->t('Basic Settings'),
1206                 '$username' => ['username',  DI::l10n()->t('Full Name:'), $username, ''],
1207                 '$email'        => ['email', DI::l10n()->t('Email Address:'), $email, '', '', '', 'email'],
1208                 '$timezone' => ['timezone_select' , DI::l10n()->t('Your Timezone:'), Temporal::getTimezoneSelect($timezone), ''],
1209                 '$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],
1210                 '$defloc'       => ['defloc', DI::l10n()->t('Default Post Location:'), $defloc, ''],
1211                 '$allowloc' => ['allow_location', DI::l10n()->t('Use Browser Location:'), ($a->user['allow_location'] == 1), ''],
1212
1213
1214                 '$h_prv'        => DI::l10n()->t('Security and Privacy Settings'),
1215
1216                 '$maxreq'       => ['maxreq', DI::l10n()->t('Maximum Friend Requests/Day:'), $maxreq , DI::l10n()->t("\x28to prevent spam abuse\x29")],
1217                 '$permissions' => DI::l10n()->t('Default Post Permissions'),
1218                 '$permdesc' => DI::l10n()->t("\x28click to open/close\x29"),
1219                 '$visibility' => $profile['net-publish'],
1220                 '$aclselect' => ACL::getFullSelectorHTML(DI::page(), $a->user),
1221                 '$suggestme' => $suggestme,
1222                 '$blockwall'=> $blockwall, // array('blockwall', DI::l10n()->t('Allow friends to post to your profile page:'), !$blockwall, ''),
1223                 '$blocktags'=> $blocktags, // array('blocktags', DI::l10n()->t('Allow friends to tag your posts:'), !$blocktags, ''),
1224
1225                 // ACL permissions box
1226                 '$group_perms' => DI::l10n()->t('Show to Groups'),
1227                 '$contact_perms' => DI::l10n()->t('Show to Contacts'),
1228                 '$private' => DI::l10n()->t('Default Private Post'),
1229                 '$public' => DI::l10n()->t('Default Public Post'),
1230                 '$is_private' => $private_post,
1231                 '$return_path' => $query_str,
1232                 '$public_link' => $public_post_link,
1233                 '$settings_perms' => DI::l10n()->t('Default Permissions for New Posts'),
1234
1235                 '$group_select' => $group_select,
1236
1237
1238                 '$expire'       => $expire_arr,
1239
1240                 '$profile_in_dir' => $profile_in_dir,
1241                 '$profile_in_net_dir' => $profile_in_net_dir,
1242                 '$hide_friends' => $hide_friends,
1243                 '$hide_wall' => $hide_wall,
1244                 '$unkmail' => $unkmail,
1245                 '$cntunkmail'   => ['cntunkmail', DI::l10n()->t('Maximum private messages per day from unknown people:'), $cntunkmail , DI::l10n()->t("\x28to prevent spam abuse\x29")],
1246
1247
1248                 '$h_not'        => DI::l10n()->t('Notification Settings'),
1249                 '$lbl_not'      => DI::l10n()->t('Send a notification email when:'),
1250                 '$notify1'      => ['notify1', DI::l10n()->t('You receive an introduction'), ($notify & Type::INTRO), Type::INTRO, ''],
1251                 '$notify2'      => ['notify2', DI::l10n()->t('Your introductions are confirmed'), ($notify & Type::CONFIRM), Type::CONFIRM, ''],
1252                 '$notify3'      => ['notify3', DI::l10n()->t('Someone writes on your profile wall'), ($notify & Type::WALL), Type::WALL, ''],
1253                 '$notify4'      => ['notify4', DI::l10n()->t('Someone writes a followup comment'), ($notify & Type::COMMENT), Type::COMMENT, ''],
1254                 '$notify5'      => ['notify5', DI::l10n()->t('You receive a private message'), ($notify & Type::MAIL), Type::MAIL, ''],
1255                 '$notify6'  => ['notify6', DI::l10n()->t('You receive a friend suggestion'), ($notify & Type::SUGGEST), Type::SUGGEST, ''],
1256                 '$notify7'  => ['notify7', DI::l10n()->t('You are tagged in a post'), ($notify & Type::TAG_SELF), Type::TAG_SELF, ''],
1257                 '$notify8'  => ['notify8', DI::l10n()->t('You are poked/prodded/etc. in a post'), ($notify & Type::POKE), Type::POKE, ''],
1258
1259                 '$desktop_notifications' => ['desktop_notifications', DI::l10n()->t('Activate desktop notifications') , false, DI::l10n()->t('Show desktop popup on new notifications')],
1260
1261                 '$email_textonly' => ['email_textonly', DI::l10n()->t('Text-only notification emails'),
1262                                                                         DI::pConfig()->get(local_user(), 'system', 'email_textonly'),
1263                                                                         DI::l10n()->t('Send text only notification emails, without the html part')],
1264
1265                 '$detailed_notif' => ['detailed_notif', DI::l10n()->t('Show detailled notifications'),
1266                                                                         DI::pConfig()->get(local_user(), 'system', 'detailed_notif'),
1267                                                                         DI::l10n()->t('Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed.')],
1268
1269                 '$h_advn' => DI::l10n()->t('Advanced Account/Page Type Settings'),
1270                 '$h_descadvn' => DI::l10n()->t('Change the behaviour of this account for special situations'),
1271                 '$pagetype' => $pagetype,
1272
1273                 '$importcontact' => DI::l10n()->t('Import Contacts'),
1274                 '$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.'),
1275                 '$importcontact_button' => DI::l10n()->t('Upload File'),
1276                 '$importcontact_maxsize' => DI::config()->get('system', 'max_csv_file_size', 30720), 
1277                 '$relocate' => DI::l10n()->t('Relocate'),
1278                 '$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."),
1279                 '$relocate_button' => DI::l10n()->t("Resend relocate message to contacts"),
1280
1281         ]);
1282
1283         Hook::callAll('settings_form', $o);
1284
1285         $o .= '</form>' . "\r\n";
1286
1287         return $o;
1288
1289 }