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