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