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