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