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