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