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