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