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