Merge pull request #4937 from astifter/install_theme_when_set
[friendica.git/.git] / mod / settings.php
1 <?php
2 /**
3  * @file mod/settings.php
4  */
5
6 use Friendica\App;
7 use Friendica\Content\Feature;
8 use Friendica\Content\Nav;
9 use Friendica\Core\ACL;
10 use Friendica\Core\Addon;
11 use Friendica\Core\Config;
12 use Friendica\Core\L10n;
13 use Friendica\Core\PConfig;
14 use Friendica\Core\System;
15 use Friendica\Core\Theme;
16 use Friendica\Core\Worker;
17 use Friendica\Database\DBM;
18 use Friendica\Model\Contact;
19 use Friendica\Model\GContact;
20 use Friendica\Model\Group;
21 use Friendica\Model\User;
22 use Friendica\Protocol\Email;
23 use Friendica\Util\Network;
24 use Friendica\Util\Temporal;
25
26 function get_theme_config_file($theme)
27 {
28         $a = get_app();
29         $base_theme = $a->theme_info['extends'];
30
31         if (file_exists("view/theme/$theme/config.php")) {
32                 return "view/theme/$theme/config.php";
33         }
34         if (file_exists("view/theme/$base_theme/config.php")) {
35                 return "view/theme/$base_theme/config.php";
36         }
37         return null;
38 }
39
40 function settings_init(App $a)
41 {
42         if (!local_user()) {
43                 notice(L10n::t('Permission denied.') . EOL);
44                 return;
45         }
46
47         // These lines provide the javascript needed by the acl selector
48
49         $tpl = get_markup_template('settings/head.tpl');
50         $a->page['htmlhead'] .= replace_macros($tpl, [
51                 '$ispublic' => L10n::t('everybody')
52         ]);
53
54         $tabs = [
55                 [
56                         'label' => L10n::t('Account'),
57                         'url'   => 'settings',
58                         'selected'      =>  (($a->argc == 1) && ($a->argv[0] === 'settings')?'active':''),
59                         'accesskey' => 'o',
60                 ],
61         ];
62
63         if (Feature::get()) {
64                 $tabs[] =       [
65                                         'label' => L10n::t('Additional features'),
66                                         'url'   => 'settings/features',
67                                         'selected'      => (($a->argc > 1) && ($a->argv[1] === 'features') ? 'active' : ''),
68                                         'accesskey' => 't',
69                                 ];
70         }
71
72         $tabs[] =       [
73                 'label' => L10n::t('Display'),
74                 'url'   => 'settings/display',
75                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'display')?'active':''),
76                 'accesskey' => 'i',
77         ];
78
79         $tabs[] =       [
80                 'label' => L10n::t('Social Networks'),
81                 'url'   => 'settings/connectors',
82                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'connectors')?'active':''),
83                 'accesskey' => 'w',
84         ];
85
86         $tabs[] =       [
87                 'label' => L10n::t('Addons'),
88                 'url'   => 'settings/addon',
89                 'selected'      => (($a->argc > 1) && ($a->argv[1] === 'addon')?'active':''),
90                 'accesskey' => 'l',
91         ];
92
93         $tabs[] =       [
94                 'label' => L10n::t('Delegations'),
95                 'url'   => 'delegate',
96                 'selected'      => (($a->argc == 1) && ($a->argv[0] === 'delegate')?'active':''),
97                 'accesskey' => 'd',
98         ];
99
100         $tabs[] =       [
101                 'label' => L10n::t('Connected apps'),
102                 'url' => 'settings/oauth',
103                 'selected' => (($a->argc > 1) && ($a->argv[1] === 'oauth')?'active':''),
104                 'accesskey' => 'b',
105         ];
106
107         $tabs[] =       [
108                 'label' => L10n::t('Export personal data'),
109                 'url' => 'uexport',
110                 'selected' => (($a->argc == 1) && ($a->argv[0] === 'uexport')?'active':''),
111                 'accesskey' => 'e',
112         ];
113
114         $tabs[] =       [
115                 'label' => L10n::t('Remove account'),
116                 'url' => 'removeme',
117                 'selected' => (($a->argc == 1) && ($a->argv[0] === 'removeme')?'active':''),
118                 'accesskey' => 'r',
119         ];
120
121
122         $tabtpl = get_markup_template("generic_links_widget.tpl");
123         $a->page['aside'] = replace_macros($tabtpl, [
124                 '$title' => L10n::t('Settings'),
125                 '$class' => 'settings-widget',
126                 '$items' => $tabs,
127         ]);
128
129 }
130
131 function settings_post(App $a)
132 {
133         if (!local_user()) {
134                 return;
135         }
136
137         if (x($_SESSION, 'submanage') && intval($_SESSION['submanage'])) {
138                 return;
139         }
140
141         if (count($a->user) && x($a->user, 'uid') && $a->user['uid'] != local_user()) {
142                 notice(L10n::t('Permission denied.') . EOL);
143                 return;
144         }
145
146         $old_page_flags = $a->user['page-flags'];
147
148         if (($a->argc > 1) && ($a->argv[1] === 'oauth') && x($_POST, 'remove')) {
149                 check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
150
151                 $key = $_POST['remove'];
152                 q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
153                         dbesc($key),
154                         local_user());
155                 goaway(System::baseUrl(true)."/settings/oauth/");
156                 return;
157         }
158
159         if (($a->argc > 2) && ($a->argv[1] === 'oauth')  && ($a->argv[2] === 'edit'||($a->argv[2] === 'add')) && x($_POST, 'submit')) {
160                 check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
161
162                 $name     = defaults($_POST, 'name'    , '');
163                 $key      = defaults($_POST, 'key'     , '');
164                 $secret   = defaults($_POST, 'secret'  , '');
165                 $redirect = defaults($_POST, 'redirect', '');
166                 $icon     = defaults($_POST, 'icon'    , '');
167
168                 if ($name == "" || $key == "" || $secret == "") {
169                         notice(L10n::t("Missing some important data!"));
170                 } else {
171                         if ($_POST['submit'] == L10n::t("Update")) {
172                                 q("UPDATE clients SET
173                                                         client_id='%s',
174                                                         pw='%s',
175                                                         name='%s',
176                                                         redirect_uri='%s',
177                                                         icon='%s',
178                                                         uid=%d
179                                                 WHERE client_id='%s'",
180                                         dbesc($key),
181                                         dbesc($secret),
182                                         dbesc($name),
183                                         dbesc($redirect),
184                                         dbesc($icon),
185                                         local_user(),
186                                         dbesc($key)
187                                 );
188                         } else {
189                                 q("INSERT INTO clients
190                                                         (client_id, pw, name, redirect_uri, icon, uid)
191                                                 VALUES ('%s', '%s', '%s', '%s', '%s',%d)",
192                                         dbesc($key),
193                                         dbesc($secret),
194                                         dbesc($name),
195                                         dbesc($redirect),
196                                         dbesc($icon),
197                                         local_user()
198                                 );
199                         }
200                 }
201                 goaway(System::baseUrl(true)."/settings/oauth/");
202                 return;
203         }
204
205         if (($a->argc > 1) && ($a->argv[1] == 'addon')) {
206                 check_form_security_token_redirectOnErr('/settings/addon', 'settings_addon');
207
208                 Addon::callHooks('addon_settings_post', $_POST);
209                 return;
210         }
211
212         if (($a->argc > 1) && ($a->argv[1] == 'connectors')) {
213                 check_form_security_token_redirectOnErr('/settings/connectors', 'settings_connectors');
214
215                 if (x($_POST, 'general-submit')) {
216                         PConfig::set(local_user(), 'system', 'disable_cw', intval($_POST['disable_cw']));
217                         PConfig::set(local_user(), 'system', 'no_intelligent_shortening', intval($_POST['no_intelligent_shortening']));
218                         PConfig::set(local_user(), 'system', 'ostatus_autofriend', intval($_POST['snautofollow']));
219                         PConfig::set(local_user(), 'ostatus', 'default_group', $_POST['group-selection']);
220                         PConfig::set(local_user(), 'ostatus', 'legacy_contact', $_POST['legacy_contact']);
221                 } elseif (x($_POST, 'imap-submit')) {
222
223                         $mail_server       = ((x($_POST, 'mail_server')) ? $_POST['mail_server'] : '');
224                         $mail_port         = ((x($_POST, 'mail_port')) ? $_POST['mail_port'] : '');
225                         $mail_ssl          = ((x($_POST, 'mail_ssl')) ? strtolower(trim($_POST['mail_ssl'])) : '');
226                         $mail_user         = ((x($_POST, 'mail_user')) ? $_POST['mail_user'] : '');
227                         $mail_pass         = ((x($_POST, 'mail_pass')) ? trim($_POST['mail_pass']) : '');
228                         $mail_action       = ((x($_POST, 'mail_action')) ? trim($_POST['mail_action']) : '');
229                         $mail_movetofolder = ((x($_POST, 'mail_movetofolder')) ? trim($_POST['mail_movetofolder']) : '');
230                         $mail_replyto      = ((x($_POST, 'mail_replyto')) ? $_POST['mail_replyto'] : '');
231                         $mail_pubmail      = ((x($_POST, 'mail_pubmail')) ? $_POST['mail_pubmail'] : '');
232
233
234                         $mail_disabled = ((function_exists('imap_open') && (!Config::get('system', 'imap_disabled'))) ? 0 : 1);
235                         if (Config::get('system', 'dfrn_only')) {
236                                 $mail_disabled = 1;
237                         }
238
239                         if (!$mail_disabled) {
240                                 $failed = false;
241                                 $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
242                                         intval(local_user())
243                                 );
244                                 if (!DBM::is_result($r)) {
245                                         dba::insert('mailacct', ['uid' => local_user()]);
246                                 }
247                                 if (strlen($mail_pass)) {
248                                         $pass = '';
249                                         openssl_public_encrypt($mail_pass, $pass, $a->user['pubkey']);
250                                         dba::update('mailacct', ['pass' => bin2hex($pass)], ['uid' => local_user()]);
251                                 }
252                                 $r = q("UPDATE `mailacct` SET `server` = '%s', `port` = %d, `ssltype` = '%s', `user` = '%s',
253                                         `action` = %d, `movetofolder` = '%s',
254                                         `mailbox` = 'INBOX', `reply_to` = '%s', `pubmail` = %d WHERE `uid` = %d",
255                                         dbesc($mail_server),
256                                         intval($mail_port),
257                                         dbesc($mail_ssl),
258                                         dbesc($mail_user),
259                                         intval($mail_action),
260                                         dbesc($mail_movetofolder),
261                                         dbesc($mail_replyto),
262                                         intval($mail_pubmail),
263                                         intval(local_user())
264                                 );
265                                 logger("mail: updating mailaccount. Response: ".print_r($r, true));
266                                 $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
267                                         intval(local_user())
268                                 );
269                                 if (DBM::is_result($r)) {
270                                         $eacct = $r[0];
271                                         $mb = Email::constructMailboxName($eacct);
272
273                                         if (strlen($eacct['server'])) {
274                                                 $dcrpass = '';
275                                                 openssl_private_decrypt(hex2bin($eacct['pass']), $dcrpass, $a->user['prvkey']);
276                                                 $mbox = Email::connect($mb, $mail_user, $dcrpass);
277                                                 unset($dcrpass);
278                                                 if (!$mbox) {
279                                                         $failed = true;
280                                                         notice(L10n::t('Failed to connect with email account using the settings provided.') . EOL);
281                                                 }
282                                         }
283                                 }
284                                 if (!$failed) {
285                                         info(L10n::t('Email settings updated.') . EOL);
286                                 }
287                         }
288                 }
289
290                 Addon::callHooks('connector_settings_post', $_POST);
291                 return;
292         }
293
294         if (($a->argc > 1) && ($a->argv[1] === 'features')) {
295                 check_form_security_token_redirectOnErr('/settings/features', 'settings_features');
296                 foreach ($_POST as $k => $v) {
297                         if (strpos($k, 'feature_') === 0) {
298                                 PConfig::set(local_user(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0));
299                         }
300                 }
301                 info(L10n::t('Features updated') . EOL);
302                 return;
303         }
304
305         if (($a->argc > 1) && ($a->argv[1] === 'display')) {
306                 check_form_security_token_redirectOnErr('/settings/display', 'settings_display');
307
308                 $theme             = x($_POST, 'theme')             ? notags(trim($_POST['theme']))        : $a->user['theme'];
309                 $mobile_theme      = x($_POST, 'mobile_theme')      ? notags(trim($_POST['mobile_theme'])) : '';
310                 $nosmile           = x($_POST, 'nosmile')           ? intval($_POST['nosmile'])            : 0;
311                 $first_day_of_week = x($_POST, 'first_day_of_week') ? intval($_POST['first_day_of_week'])  : 0;
312                 $noinfo            = x($_POST, 'noinfo')            ? intval($_POST['noinfo'])             : 0;
313                 $infinite_scroll   = x($_POST, 'infinite_scroll')   ? intval($_POST['infinite_scroll'])    : 0;
314                 $no_auto_update    = x($_POST, 'no_auto_update')    ? intval($_POST['no_auto_update'])     : 0;
315                 $bandwidth_saver   = x($_POST, 'bandwidth_saver')   ? intval($_POST['bandwidth_saver'])    : 0;
316                 $smart_threading   = x($_POST, 'smart_threading')   ? intval($_POST['smart_threading'])    : 0;
317                 $nowarn_insecure   = x($_POST, 'nowarn_insecure')   ? intval($_POST['nowarn_insecure'])    : 0;
318                 $browser_update    = x($_POST, 'browser_update')    ? intval($_POST['browser_update'])     : 0;
319                 if ($browser_update != -1) {
320                         $browser_update = $browser_update * 1000;
321                         if ($browser_update < 10000) {
322                                 $browser_update = 10000;
323                         }
324                 }
325
326                 $itemspage_network = x($_POST, 'itemspage_network')  ? intval($_POST['itemspage_network'])  : 40;
327                 if ($itemspage_network > 100) {
328                         $itemspage_network = 100;
329                 }
330                 $itemspage_mobile_network = x($_POST, 'itemspage_mobile_network') ? intval($_POST['itemspage_mobile_network']) : 20;
331                 if ($itemspage_mobile_network > 100) {
332                         $itemspage_mobile_network = 100;
333                 }
334
335                 if ($mobile_theme !== '') {
336                         PConfig::set(local_user(), 'system', 'mobile_theme', $mobile_theme);
337                 }
338
339                 PConfig::set(local_user(), 'system', 'nowarn_insecure'         , $nowarn_insecure);
340                 PConfig::set(local_user(), 'system', 'update_interval'         , $browser_update);
341                 PConfig::set(local_user(), 'system', 'itemspage_network'       , $itemspage_network);
342                 PConfig::set(local_user(), 'system', 'itemspage_mobile_network', $itemspage_mobile_network);
343                 PConfig::set(local_user(), 'system', 'no_smilies'              , $nosmile);
344                 PConfig::set(local_user(), 'system', 'first_day_of_week'       , $first_day_of_week);
345                 PConfig::set(local_user(), 'system', 'ignore_info'             , $noinfo);
346                 PConfig::set(local_user(), 'system', 'infinite_scroll'         , $infinite_scroll);
347                 PConfig::set(local_user(), 'system', 'no_auto_update'          , $no_auto_update);
348                 PConfig::set(local_user(), 'system', 'bandwidth_saver'         , $bandwidth_saver);
349                 PConfig::set(local_user(), 'system', 'smart_threading'         , $smart_threading);
350
351                 if ($theme == $a->user['theme']) {
352                         // call theme_post only if theme has not been changed
353                         if (($themeconfigfile = get_theme_config_file($theme)) !== null) {
354                                 require_once $themeconfigfile;
355                                 theme_post($a);
356                         }
357                 }
358                 Theme::install($theme);
359
360                 $r = q("UPDATE `user` SET `theme` = '%s' WHERE `uid` = %d",
361                                 dbesc($theme),
362                                 intval(local_user())
363                 );
364
365                 Addon::callHooks('display_settings_post', $_POST);
366                 goaway('settings/display');
367                 return; // NOTREACHED
368         }
369
370         check_form_security_token_redirectOnErr('/settings', 'settings');
371
372         if (x($_POST,'resend_relocate')) {
373                 Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', local_user());
374                 info(L10n::t("Relocate message has been send to your contacts"));
375                 goaway('settings');
376         }
377
378         Addon::callHooks('settings_post', $_POST);
379
380         if (x($_POST, 'password') || x($_POST, 'confirm')) {
381                 $newpass = $_POST['password'];
382                 $confirm = $_POST['confirm'];
383
384                 $err = false;
385                 if ($newpass != $confirm) {
386                         notice(L10n::t('Passwords do not match. Password unchanged.') . EOL);
387                         $err = true;
388                 }
389
390                 if (!x($newpass) || !x($confirm)) {
391                         notice(L10n::t('Empty passwords are not allowed. Password unchanged.') . EOL);
392                         $err = true;
393                 }
394
395                 if (!Config::get('system', 'disable_password_exposed', false) && User::isPasswordExposed($newpass)) {
396                         notice(L10n::t('The new password has been exposed in a public data dump, please choose another.') . EOL);
397                         $err = true;
398                 }
399
400                 //  check if the old password was supplied correctly before changing it to the new value
401                 if (!User::authenticate(intval(local_user()), $_POST['opassword'])) {
402                         notice(L10n::t('Wrong password.') . EOL);
403                         $err = true;
404                 }
405
406                 if (!$err) {
407                         $result = User::updatePassword(local_user(), $newpass);
408                         if (DBM::is_result($result)) {
409                                 info(L10n::t('Password changed.') . EOL);
410                         } else {
411                                 notice(L10n::t('Password update failed. Please try again.') . EOL);
412                         }
413                 }
414         }
415
416         $username         = ((x($_POST, 'username'))   ? notags(trim($_POST['username']))     : '');
417         $email            = ((x($_POST, 'email'))      ? notags(trim($_POST['email']))        : '');
418         $timezone         = ((x($_POST, 'timezone'))   ? notags(trim($_POST['timezone']))     : '');
419         $language         = ((x($_POST, 'language'))   ? notags(trim($_POST['language']))     : '');
420
421         $defloc           = ((x($_POST, 'defloc'))     ? notags(trim($_POST['defloc']))       : '');
422         $openid           = ((x($_POST, 'openid_url')) ? notags(trim($_POST['openid_url']))   : '');
423         $maxreq           = ((x($_POST, 'maxreq'))     ? intval($_POST['maxreq'])             : 0);
424         $expire           = ((x($_POST, 'expire'))     ? intval($_POST['expire'])             : 0);
425         $def_gid          = ((x($_POST, 'group-selection')) ? intval($_POST['group-selection']) : 0);
426
427
428         $expire_items     = ((x($_POST, 'expire_items')) ? intval($_POST['expire_items'])        : 0);
429         $expire_notes     = ((x($_POST, 'expire_notes')) ? intval($_POST['expire_notes'])        : 0);
430         $expire_starred   = ((x($_POST, 'expire_starred')) ? intval($_POST['expire_starred']) : 0);
431         $expire_photos    = ((x($_POST, 'expire_photos'))? intval($_POST['expire_photos'])       : 0);
432         $expire_network_only    = ((x($_POST, 'expire_network_only'))? intval($_POST['expire_network_only'])     : 0);
433
434         $allow_location   = (((x($_POST, 'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
435         $publish          = (((x($_POST, 'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
436         $net_publish      = (((x($_POST, 'profile_in_netdirectory')) && (intval($_POST['profile_in_netdirectory']) == 1)) ? 1: 0);
437         $old_visibility   = (((x($_POST, 'visibility')) && (intval($_POST['visibility']) == 1)) ? 1 : 0);
438         $account_type     = (((x($_POST, 'account-type')) && (intval($_POST['account-type']))) ? intval($_POST['account-type']) : 0);
439         $page_flags       = (((x($_POST, 'page-flags')) && (intval($_POST['page-flags']))) ? intval($_POST['page-flags']) : 0);
440         $blockwall        = (((x($_POST, 'blockwall')) && (intval($_POST['blockwall']) == 1)) ? 0: 1); // this setting is inverted!
441         $blocktags        = (((x($_POST, 'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
442         $unkmail          = (((x($_POST, 'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
443         $cntunkmail       = ((x($_POST, 'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
444         $suggestme        = ((x($_POST, 'suggestme')) ? intval($_POST['suggestme'])  : 0);
445         $hide_friends     = (($_POST['hide-friends'] == 1) ? 1: 0);
446         $hidewall         = (($_POST['hidewall'] == 1) ? 1: 0);
447         $post_newfriend   = (($_POST['post_newfriend'] == 1) ? 1: 0);
448         $post_joingroup   = (($_POST['post_joingroup'] == 1) ? 1: 0);
449         $post_profilechange   = (($_POST['post_profilechange'] == 1) ? 1: 0);
450
451         $email_textonly   = (($_POST['email_textonly'] == 1) ? 1 : 0);
452         $detailed_notif   = (($_POST['detailed_notif'] == 1) ? 1 : 0);
453
454         $notify = 0;
455
456         if (x($_POST, 'notify1')) {
457                 $notify += intval($_POST['notify1']);
458         }
459         if (x($_POST, 'notify2')) {
460                 $notify += intval($_POST['notify2']);
461         }
462         if (x($_POST, 'notify3')) {
463                 $notify += intval($_POST['notify3']);
464         }
465         if (x($_POST, 'notify4')) {
466                 $notify += intval($_POST['notify4']);
467         }
468         if (x($_POST, 'notify5')) {
469                 $notify += intval($_POST['notify5']);
470         }
471         if (x($_POST, 'notify6')) {
472                 $notify += intval($_POST['notify6']);
473         }
474         if (x($_POST, 'notify7')) {
475                 $notify += intval($_POST['notify7']);
476         }
477         if (x($_POST, 'notify8')) {
478                 $notify += intval($_POST['notify8']);
479         }
480
481         // Adjust the page flag if the account type doesn't fit to the page flag.
482         if (($account_type == ACCOUNT_TYPE_PERSON) && !in_array($page_flags, [PAGE_NORMAL, PAGE_SOAPBOX, PAGE_FREELOVE])) {
483                 $page_flags = PAGE_NORMAL;
484         } elseif (($account_type == ACCOUNT_TYPE_ORGANISATION) && !in_array($page_flags, [PAGE_SOAPBOX])) {
485                 $page_flags = PAGE_SOAPBOX;
486         } elseif (($account_type == ACCOUNT_TYPE_NEWS) && !in_array($page_flags, [PAGE_SOAPBOX])) {
487                 $page_flags = PAGE_SOAPBOX;
488         } elseif (($account_type == ACCOUNT_TYPE_COMMUNITY) && !in_array($page_flags, [PAGE_COMMUNITY, PAGE_PRVGROUP])) {
489                 $page_flags = PAGE_COMMUNITY;
490         }
491
492         $email_changed = false;
493
494         $err = '';
495
496         if ($username != $a->user['username']) {
497                 if (strlen($username) > 40) {
498                         $err .= L10n::t(' Please use a shorter name.');
499                 }
500                 if (strlen($username) < 3) {
501                         $err .= L10n::t(' Name too short.');
502                 }
503         }
504
505         if ($email != $a->user['email']) {
506                 $email_changed = true;
507                 //  check for the correct password
508                 if (!User::authenticate(intval(local_user()), $_POST['mpassword'])) {
509                         $err .= L10n::t('Wrong Password') . EOL;
510                         $email = $a->user['email'];
511                 }
512                 //  check the email is valid
513                 if (!valid_email($email)) {
514                         $err .= L10n::t('Invalid email.');
515                 }
516                 //  ensure new email is not the admin mail
517                 //if ((x($a->config, 'admin_email')) && (strcasecmp($email, $a->config['admin_email']) == 0)) {
518                 if (x($a->config, 'admin_email')) {
519                         $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
520                         if (in_array(strtolower($email), $adminlist)) {
521                                 $err .= L10n::t('Cannot change to that email.');
522                                 $email = $a->user['email'];
523                         }
524                 }
525         }
526
527         if (strlen($err)) {
528                 notice($err . EOL);
529                 return;
530         }
531
532         if (($timezone != $a->user['timezone']) && strlen($timezone)) {
533                 date_default_timezone_set($timezone);
534         }
535
536         $str_group_allow   = perms2str($_POST['group_allow']);
537         $str_contact_allow = perms2str($_POST['contact_allow']);
538         $str_group_deny    = perms2str($_POST['group_deny']);
539         $str_contact_deny  = perms2str($_POST['contact_deny']);
540
541         $openidserver = $a->user['openidserver'];
542         //$openid = normalise_openid($openid);
543
544         // If openid has changed or if there's an openid but no openidserver, try and discover it.
545         if ($openid != $a->user['openid'] || (strlen($openid) && (!strlen($openidserver)))) {
546                 if (Network::isUrlValid($openid)) {
547                         logger('updating openidserver');
548                         $open_id_obj = new LightOpenID;
549                         $open_id_obj->identity = $openid;
550                         $openidserver = $open_id_obj->discover($open_id_obj->identity);
551                 } else {
552                         $openidserver = '';
553                 }
554         }
555
556         PConfig::set(local_user(), 'expire', 'items', $expire_items);
557         PConfig::set(local_user(), 'expire', 'notes', $expire_notes);
558         PConfig::set(local_user(), 'expire', 'starred', $expire_starred);
559         PConfig::set(local_user(), 'expire', 'photos', $expire_photos);
560         PConfig::set(local_user(), 'expire', 'network_only', $expire_network_only);
561
562         PConfig::set(local_user(), 'system', 'suggestme', $suggestme);
563         PConfig::set(local_user(), 'system', 'post_newfriend', $post_newfriend);
564         PConfig::set(local_user(), 'system', 'post_joingroup', $post_joingroup);
565         PConfig::set(local_user(), 'system', 'post_profilechange', $post_profilechange);
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 == 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                         dbesc($username),
592                         dbesc($email),
593                         dbesc($openid),
594                         dbesc($timezone),
595                         dbesc($str_contact_allow),
596                         dbesc($str_group_allow),
597                         dbesc($str_contact_deny),
598                         dbesc($str_group_deny),
599                         intval($notify),
600                         intval($page_flags),
601                         intval($account_type),
602                         dbesc($defloc),
603                         intval($allow_location),
604                         intval($maxreq),
605                         intval($expire),
606                         dbesc($openidserver),
607                         intval($def_gid),
608                         intval($blockwall),
609                         intval($hidewall),
610                         intval($blocktags),
611                         intval($unkmail),
612                         intval($cntunkmail),
613                         dbesc($language),
614                         intval(local_user())
615         );
616         if (DBM::is_result($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                 dbesc($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         goaway('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;
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' => get_form_security_token("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                                         dbesc($a->argv[3]),
691                                         local_user());
692
693                         if (!DBM::is_result($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' => get_form_security_token("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                         check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't');
716
717                         q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
718                                         dbesc($a->argv[3]),
719                                         local_user());
720                         goaway(System::baseUrl(true)."/settings/oauth/");
721                         return;
722                 }
723
724                 /// @TODO validate result with DBM::is_result()
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 = get_markup_template('settings/oauth.tpl');
734                 $o .= replace_macros($tpl, [
735                         '$form_security_token' => get_form_security_token("settings_oauth"),
736                         '$baseurl'      => System::baseUrl(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 (!DBM::is_result($r)) {
754                         $settings_addons = L10n::t('No Addon settings configured');
755                 }
756
757                 Addon::callHooks('addon_settings', $settings_addons);
758
759
760                 $tpl = get_markup_template('settings/addons.tpl');
761                 $o .= replace_macros($tpl, [
762                         '$form_security_token' => get_form_security_token("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 = get_markup_template('settings/features.tpl');
782                 $o .= replace_macros($tpl, [
783                         '$form_security_token' => get_form_security_token("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 goaway() 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       = ((DBM::is_result($r)) ? $r[0]['server'] : '');
827                 $mail_port         = ((DBM::is_result($r) && intval($r[0]['port'])) ? intval($r[0]['port']) : '');
828                 $mail_ssl          = ((DBM::is_result($r)) ? $r[0]['ssltype'] : '');
829                 $mail_user         = ((DBM::is_result($r)) ? $r[0]['user'] : '');
830                 $mail_replyto      = ((DBM::is_result($r)) ? $r[0]['reply_to'] : '');
831                 $mail_pubmail      = ((DBM::is_result($r)) ? $r[0]['pubmail'] : 0);
832                 $mail_action       = ((DBM::is_result($r)) ? $r[0]['action'] : 0);
833                 $mail_movetofolder = ((DBM::is_result($r)) ? $r[0]['movetofolder'] : '');
834                 $mail_chk          = ((DBM::is_result($r)) ? $r[0]['last_check'] : NULL_DATE);
835
836
837                 $tpl = get_markup_template('settings/connectors.tpl');
838
839                 $mail_disabled_message = (($mail_disabled) ? L10n::t('Email access is disabled on this site.') : '');
840
841                 $o .= replace_macros($tpl, [
842                         '$form_security_token' => get_form_security_token("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 = get_markup_template('settings/display.tpl');
960                 $o = replace_macros($tpl, [
961                         '$ptitle'       => L10n::t('Display Settings'),
962                         '$form_security_token' => get_form_security_token("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('Bandwith 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                 $tpl = get_markup_template('settings/display_end.tpl');
990                 $a->page['end'] .= replace_macros($tpl, [
991                         '$theme'        => ['theme', L10n::t('Display Theme:'), $theme_selected, '', $themes]
992                 ]);
993
994                 return $o;
995         }
996
997
998         /*
999          * ACCOUNT SETTINGS
1000          */
1001
1002         $profile = dba::selectFirst('profile', [], ['is-default' => true, 'uid' => local_user()]);
1003         if (!DBM::is_result($profile)) {
1004                 notice(L10n::t('Unable to find your profile. Please contact your admin.') . EOL);
1005                 return;
1006         }
1007
1008         $username   = $a->user['username'];
1009         $email      = $a->user['email'];
1010         $nickname   = $a->user['nickname'];
1011         $timezone   = $a->user['timezone'];
1012         $language   = $a->user['language'];
1013         $notify     = $a->user['notify-flags'];
1014         $defloc     = $a->user['default-location'];
1015         $openid     = $a->user['openid'];
1016         $maxreq     = $a->user['maxreq'];
1017         $expire     = ((intval($a->user['expire'])) ? $a->user['expire'] : '');
1018         $unkmail    = $a->user['unkmail'];
1019         $cntunkmail = $a->user['cntunkmail'];
1020
1021         $expire_items = PConfig::get(local_user(), 'expire', 'items', true);
1022         $expire_notes = PConfig::get(local_user(), 'expire', 'notes', true);
1023         $expire_starred = PConfig::get(local_user(), 'expire', 'starred', true);
1024         $expire_photos = PConfig::get(local_user(), 'expire', 'photos', false);
1025         $expire_network_only = PConfig::get(local_user(), 'expire', 'network_only', false);
1026         $suggestme = PConfig::get(local_user(), 'system', 'suggestme', false);
1027         $post_newfriend = PConfig::get(local_user(), 'system', 'post_newfriend', false);
1028         $post_joingroup = PConfig::get(local_user(), 'system', 'post_joingroup', false);
1029         $post_profilechange = PConfig::get(local_user(), 'system', 'post_profilechange', false);
1030
1031         // nowarn_insecure
1032
1033         if (!strlen($a->user['timezone'])) {
1034                 $timezone = date_default_timezone_get();
1035         }
1036
1037         // Set the account type to "Community" when the page is a community page but the account type doesn't fit
1038         // This is only happening on the first visit after the update
1039         if (in_array($a->user['page-flags'], [PAGE_COMMUNITY, PAGE_PRVGROUP]) &&
1040                 ($a->user['account-type'] != ACCOUNT_TYPE_COMMUNITY))
1041                 $a->user['account-type'] = ACCOUNT_TYPE_COMMUNITY;
1042
1043         $pageset_tpl = get_markup_template('settings/pagetypes.tpl');
1044
1045         $pagetype = replace_macros($pageset_tpl, [
1046                 '$account_types'        => L10n::t("Account Types"),
1047                 '$user'                 => L10n::t("Personal Page Subtypes"),
1048                 '$community'            => L10n::t("Community Forum Subtypes"),
1049                 '$account_type'         => $a->user['account-type'],
1050                 '$type_person'          => ACCOUNT_TYPE_PERSON,
1051                 '$type_organisation'    => ACCOUNT_TYPE_ORGANISATION,
1052                 '$type_news'            => ACCOUNT_TYPE_NEWS,
1053                 '$type_community'       => ACCOUNT_TYPE_COMMUNITY,
1054
1055                 '$account_person'       => ['account-type', L10n::t('Personal Page'), ACCOUNT_TYPE_PERSON,
1056                                                                         L10n::t('Account for a personal profile.'),
1057                                                                         ($a->user['account-type'] == ACCOUNT_TYPE_PERSON)],
1058
1059                 '$account_organisation' => ['account-type', L10n::t('Organisation Page'), ACCOUNT_TYPE_ORGANISATION,
1060                                                                         L10n::t('Account for an organisation that automatically approves contact requests as "Followers".'),
1061                                                                         ($a->user['account-type'] == ACCOUNT_TYPE_ORGANISATION)],
1062
1063                 '$account_news'         => ['account-type', L10n::t('News Page'), ACCOUNT_TYPE_NEWS,
1064                                                                         L10n::t('Account for a news reflector that automatically approves contact requests as "Followers".'),
1065                                                                         ($a->user['account-type'] == ACCOUNT_TYPE_NEWS)],
1066
1067                 '$account_community'    => ['account-type', L10n::t('Community Forum'), ACCOUNT_TYPE_COMMUNITY,
1068                                                                         L10n::t('Account for community discussions.'),
1069                                                                         ($a->user['account-type'] == ACCOUNT_TYPE_COMMUNITY)],
1070
1071                 '$page_normal'          => ['page-flags', L10n::t('Normal Account Page'), PAGE_NORMAL,
1072                                                                         L10n::t('Account for a regular personal profile that requires manual approval of "Friends" and "Followers".'),
1073                                                                         ($a->user['page-flags'] == PAGE_NORMAL)],
1074
1075                 '$page_soapbox'         => ['page-flags', L10n::t('Soapbox Page'), PAGE_SOAPBOX,
1076                                                                         L10n::t('Account for a public profile that automatically approves contact requests as "Followers".'),
1077                                                                         ($a->user['page-flags'] == PAGE_SOAPBOX)],
1078
1079                 '$page_community'       => ['page-flags', L10n::t('Public Forum'), PAGE_COMMUNITY,
1080                                                                         L10n::t('Automatically approves all contact requests.'),
1081                                                                         ($a->user['page-flags'] == PAGE_COMMUNITY)],
1082
1083                 '$page_freelove'        => ['page-flags', L10n::t('Automatic Friend Page'), PAGE_FREELOVE,
1084                                                                         L10n::t('Account for a popular profile that automatically approves contact requests as "Friends".'),
1085                                                                         ($a->user['page-flags'] == PAGE_FREELOVE)],
1086
1087                 '$page_prvgroup'        => ['page-flags', L10n::t('Private Forum [Experimental]'), PAGE_PRVGROUP,
1088                                                                         L10n::t('Requires manual approval of contact requests.'),
1089                                                                         ($a->user['page-flags'] == PAGE_PRVGROUP)],
1090
1091
1092         ]);
1093
1094         $noid = Config::get('system', 'no_openid');
1095
1096         if ($noid) {
1097                 $openid_field = false;
1098         } else {
1099                 $openid_field = ['openid_url', L10n::t('OpenID:'), $openid, L10n::t("\x28Optional\x29 Allow this OpenID to login to this account."), "", "", "url"];
1100         }
1101
1102         $opt_tpl = get_markup_template("field_yesno.tpl");
1103         if (Config::get('system', 'publish_all')) {
1104                 $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
1105         } else {
1106                 $profile_in_dir = replace_macros($opt_tpl, [
1107                         '$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 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')]]
1108                 ]);
1109         }
1110
1111         if (strlen(Config::get('system', 'directory'))) {
1112                 $profile_in_net_dir = replace_macros($opt_tpl, [
1113                         '$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 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')]]
1114                 ]);
1115         } else {
1116                 $profile_in_net_dir = '';
1117         }
1118
1119         $hide_friends = replace_macros($opt_tpl, [
1120                 '$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')]],
1121         ]);
1122
1123         $hide_wall = replace_macros($opt_tpl, [
1124                 '$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. Disables posting public messages to Diaspora and other networks.'), [L10n::t('No'), L10n::t('Yes')]],
1125         ]);
1126
1127         $blockwall = replace_macros($opt_tpl, [
1128                 '$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')]],
1129         ]);
1130
1131         $blocktags = replace_macros($opt_tpl, [
1132                 '$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')]],
1133         ]);
1134
1135         $suggestme = replace_macros($opt_tpl, [
1136                 '$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')]],
1137         ]);
1138
1139         $unkmail = replace_macros($opt_tpl, [
1140                 '$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')]],
1141         ]);
1142
1143         if (!$profile['publish'] && !$profile['net-publish']) {
1144                 info(L10n::t('Profile is <strong>not published</strong>.') . EOL);
1145         }
1146
1147         $tpl_addr = get_markup_template('settings/nick_set.tpl');
1148
1149         $prof_addr = replace_macros($tpl_addr,[
1150                 '$desc' => L10n::t("Your Identity Address is <strong>'%s'</strong> or '%s'.", $nickname . '@' . $a->get_hostname() . $a->get_path(), System::baseUrl() . '/profile/' . $nickname),
1151                 '$basepath' => $a->get_hostname()
1152         ]);
1153
1154         $stpl = get_markup_template('settings/settings.tpl');
1155
1156         $expire_arr = [
1157                 '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')],
1158                 'advanced' => L10n::t('Advanced expiration settings'),
1159                 'label' => L10n::t('Advanced Expiration'),
1160                 'items' => ['expire_items',  L10n::t("Expire posts:"), $expire_items, '', [L10n::t('No'), L10n::t('Yes')]],
1161                 'notes' => ['expire_notes',  L10n::t("Expire personal notes:"), $expire_notes, '', [L10n::t('No'), L10n::t('Yes')]],
1162                 'starred' => ['expire_starred',  L10n::t("Expire starred posts:"), $expire_starred, '', [L10n::t('No'), L10n::t('Yes')]],
1163                 'photos' => ['expire_photos',  L10n::t("Expire photos:"), $expire_photos, '', [L10n::t('No'), L10n::t('Yes')]],
1164                 'network_only' => ['expire_network_only',  L10n::t("Only expire posts by others:"), $expire_network_only, '', [L10n::t('No'), L10n::t('Yes')]],
1165         ];
1166
1167         $group_select = Group::displayGroupSelection(local_user(), $a->user['def_gid']);
1168
1169         // Private/public post links for the non-JS ACL form
1170         $private_post = 1;
1171         if ($_REQUEST['public']) {
1172                 $private_post = 0;
1173         }
1174
1175         $query_str = $a->query_string;
1176         if (strpos($query_str, 'public=1') !== false) {
1177                 $query_str = str_replace(['?public=1', '&public=1'], ['', ''], $query_str);
1178         }
1179
1180         // I think $a->query_string may never have ? in it, but I could be wrong
1181         // It looks like it's from the index.php?q=[etc] rewrite that the web
1182         // server does, which converts any ? to &, e.g. suggest&ignore=61 for suggest?ignore=61
1183         if (strpos($query_str, '?') === false) {
1184                 $public_post_link = '?public=1';
1185         } else {
1186                 $public_post_link = '&public=1';
1187         }
1188
1189         /* Installed langs */
1190         $lang_choices = L10n::getAvailableLanguages();
1191
1192         /// @TODO Fix indending (or so)
1193         $o .= replace_macros($stpl, [
1194                 '$ptitle'       => L10n::t('Account Settings'),
1195
1196                 '$submit'       => L10n::t('Save Settings'),
1197                 '$baseurl' => System::baseUrl(true),
1198                 '$uid' => local_user(),
1199                 '$form_security_token' => get_form_security_token("settings"),
1200                 '$nickname_block' => $prof_addr,
1201
1202                 '$h_pass'       => L10n::t('Password Settings'),
1203                 '$password1'=> ['password', L10n::t('New Password:'), '', ''],
1204                 '$password2'=> ['confirm', L10n::t('Confirm:'), '', L10n::t('Leave password fields blank unless changing')],
1205                 '$password3'=> ['opassword', L10n::t('Current Password:'), '', L10n::t('Your current password to confirm the changes')],
1206                 '$password4'=> ['mpassword', L10n::t('Password:'), '', L10n::t('Your current password to confirm the changes')],
1207                 '$oid_enable' => (!Config::get('system', 'no_openid')),
1208                 '$openid'       => $openid_field,
1209
1210                 '$h_basic'      => L10n::t('Basic Settings'),
1211                 '$username' => ['username',  L10n::t('Full Name:'), $username, ''],
1212                 '$email'        => ['email', L10n::t('Email Address:'), $email, '', '', '', 'email'],
1213                 '$timezone' => ['timezone_select' , L10n::t('Your Timezone:'), Temporal::getTimezoneSelect($timezone), ''],
1214                 '$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],
1215                 '$defloc'       => ['defloc', L10n::t('Default Post Location:'), $defloc, ''],
1216                 '$allowloc' => ['allow_location', L10n::t('Use Browser Location:'), ($a->user['allow_location'] == 1), ''],
1217
1218
1219                 '$h_prv'        => L10n::t('Security and Privacy Settings'),
1220
1221                 '$maxreq'       => ['maxreq', L10n::t('Maximum Friend Requests/Day:'), $maxreq , L10n::t("\x28to prevent spam abuse\x29")],
1222                 '$permissions' => L10n::t('Default Post Permissions'),
1223                 '$permdesc' => L10n::t("\x28click to open/close\x29"),
1224                 '$visibility' => $profile['net-publish'],
1225                 '$aclselect' => ACL::getFullSelectorHTML($a->user),
1226                 '$suggestme' => $suggestme,
1227                 '$blockwall'=> $blockwall, // array('blockwall', L10n::t('Allow friends to post to your profile page:'), !$blockwall, ''),
1228                 '$blocktags'=> $blocktags, // array('blocktags', L10n::t('Allow friends to tag your posts:'), !$blocktags, ''),
1229
1230                 // ACL permissions box
1231                 '$group_perms' => L10n::t('Show to Groups'),
1232                 '$contact_perms' => L10n::t('Show to Contacts'),
1233                 '$private' => L10n::t('Default Private Post'),
1234                 '$public' => L10n::t('Default Public Post'),
1235                 '$is_private' => $private_post,
1236                 '$return_path' => $query_str,
1237                 '$public_link' => $public_post_link,
1238                 '$settings_perms' => L10n::t('Default Permissions for New Posts'),
1239
1240                 '$group_select' => $group_select,
1241
1242
1243                 '$expire'       => $expire_arr,
1244
1245                 '$profile_in_dir' => $profile_in_dir,
1246                 '$profile_in_net_dir' => $profile_in_net_dir,
1247                 '$hide_friends' => $hide_friends,
1248                 '$hide_wall' => $hide_wall,
1249                 '$unkmail' => $unkmail,
1250                 '$cntunkmail'   => ['cntunkmail', L10n::t('Maximum private messages per day from unknown people:'), $cntunkmail , L10n::t("\x28to prevent spam abuse\x29")],
1251
1252
1253                 '$h_not'        => L10n::t('Notification Settings'),
1254                 '$activity_options' => L10n::t('By default post a status message when:'),
1255                 '$post_newfriend' => ['post_newfriend',  L10n::t('accepting a friend request'), $post_newfriend, ''],
1256                 '$post_joingroup' => ['post_joingroup',  L10n::t('joining a forum/community'), $post_joingroup, ''],
1257                 '$post_profilechange' => ['post_profilechange',  L10n::t('making an <em>interesting</em> profile change'), $post_profilechange, ''],
1258                 '$lbl_not'      => L10n::t('Send a notification email when:'),
1259                 '$notify1'      => ['notify1', L10n::t('You receive an introduction'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, ''],
1260                 '$notify2'      => ['notify2', L10n::t('Your introductions are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, ''],
1261                 '$notify3'      => ['notify3', L10n::t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, ''],
1262                 '$notify4'      => ['notify4', L10n::t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, ''],
1263                 '$notify5'      => ['notify5', L10n::t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, ''],
1264                 '$notify6'  => ['notify6', L10n::t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, ''],
1265                 '$notify7'  => ['notify7', L10n::t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, ''],
1266                 '$notify8'  => ['notify8', L10n::t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, ''],
1267
1268                 '$desktop_notifications' => ['desktop_notifications', L10n::t('Activate desktop notifications') , false, L10n::t('Show desktop popup on new notifications')],
1269
1270                 '$email_textonly' => ['email_textonly', L10n::t('Text-only notification emails'),
1271                                                                         PConfig::get(local_user(), 'system', 'email_textonly'),
1272                                                                         L10n::t('Send text only notification emails, without the html part')],
1273
1274                 '$detailed_notif' => ['detailed_notif', L10n::t('Show detailled notifications'),
1275                                                                         PConfig::get(local_user(), 'system', 'detailed_notif'),
1276                                                                         L10n::t('Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed.')],
1277
1278                 '$h_advn' => L10n::t('Advanced Account/Page Type Settings'),
1279                 '$h_descadvn' => L10n::t('Change the behaviour of this account for special situations'),
1280                 '$pagetype' => $pagetype,
1281
1282                 '$relocate' => L10n::t('Relocate'),
1283                 '$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."),
1284                 '$relocate_button' => L10n::t("Resend relocate message to contacts"),
1285
1286         ]);
1287
1288         Addon::callHooks('settings_form', $o);
1289
1290         $o .= '</form>' . "\r\n";
1291
1292         return $o;
1293
1294 }