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