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