]> git.mxchange.org Git - friendica.git/blob - mod/settings.php
UserSession class [2] - Refactor mod/ files
[friendica.git] / mod / settings.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 use Friendica\App;
23 use Friendica\BaseModule;
24 use Friendica\Content\Feature;
25 use Friendica\Content\Nav;
26 use Friendica\Core\Hook;
27 use Friendica\Core\Logger;
28 use Friendica\Core\Renderer;
29 use Friendica\Core\Session;
30 use Friendica\Database\DBA;
31 use Friendica\DI;
32 use Friendica\Model\Item;
33 use Friendica\Model\User;
34 use Friendica\Module\BaseSettings;
35 use Friendica\Module\Security\Login;
36 use Friendica\Protocol\Email;
37
38 function settings_init(App $a)
39 {
40         if (!DI::userSession()->getLocalUserId()) {
41                 DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
42                 return;
43         }
44
45         BaseSettings::createAside();
46 }
47
48 function settings_post(App $a)
49 {
50         if (!$a->isLoggedIn()) {
51                 DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
52                 return;
53         }
54
55         if (!empty($_SESSION['submanage'])) {
56                 return;
57         }
58
59         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'addon')) {
60                 BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_addon');
61
62                 Hook::callAll('addon_settings_post', $_POST);
63                 DI::baseUrl()->redirect(DI::args()->getQueryString());
64                 return;
65         }
66
67         $user = User::getById($a->getLoggedInUserId());
68
69         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'connectors')) {
70                 BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_connectors');
71
72                 if (!empty($_POST['general-submit'])) {
73                         DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'accept_only_sharer', intval($_POST['accept_only_sharer']));
74                         DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'disable_cw', !intval($_POST['enable_cw']));
75                         DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'no_intelligent_shortening', !intval($_POST['enable_smart_shortening']));
76                         DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'simple_shortening', intval($_POST['simple_shortening']));
77                         DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'attach_link_title', intval($_POST['attach_link_title']));
78                         DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'ostatus', 'legacy_contact', $_POST['legacy_contact']);
79                 } elseif (!empty($_POST['mail-submit'])) {
80                         $mail_server       =                 $_POST['mail_server']       ?? '';
81                         $mail_port         =                 $_POST['mail_port']         ?? '';
82                         $mail_ssl          = strtolower(trim($_POST['mail_ssl']          ?? ''));
83                         $mail_user         =                 $_POST['mail_user']         ?? '';
84                         $mail_pass         =            trim($_POST['mail_pass']         ?? '');
85                         $mail_action       =            trim($_POST['mail_action']       ?? '');
86                         $mail_movetofolder =            trim($_POST['mail_movetofolder'] ?? '');
87                         $mail_replyto      =                 $_POST['mail_replyto']      ?? '';
88                         $mail_pubmail      =                 $_POST['mail_pubmail']      ?? '';
89
90                         if (function_exists('imap_open') && !DI::config()->get('system', 'imap_disabled')) {
91                                 if (!DBA::exists('mailacct', ['uid' => DI::userSession()->getLocalUserId()])) {
92                                         DBA::insert('mailacct', ['uid' => DI::userSession()->getLocalUserId()]);
93                                 }
94                                 if (strlen($mail_pass)) {
95                                         $pass = '';
96                                         openssl_public_encrypt($mail_pass, $pass, $user['pubkey']);
97                                         DBA::update('mailacct', ['pass' => bin2hex($pass)], ['uid' => DI::userSession()->getLocalUserId()]);
98                                 }
99
100                                 $r = DBA::update('mailacct', [
101                                         'server'       => $mail_server,
102                                         'port'         => $mail_port,
103                                         'ssltype'      => $mail_ssl,
104                                         'user'         => $mail_user,
105                                         'action'       => $mail_action,
106                                         'movetofolder' => $mail_movetofolder,
107                                         'mailbox'      => 'INBOX',
108                                         'reply_to'     => $mail_replyto,
109                                         'pubmail'      => $mail_pubmail
110                                 ], ['uid' => DI::userSession()->getLocalUserId()]);
111
112                                 Logger::debug('updating mailaccount', ['response' => $r]);
113                                 $mailacct = DBA::selectFirst('mailacct', [], ['uid' => DI::userSession()->getLocalUserId()]);
114                                 if (DBA::isResult($mailacct)) {
115                                         $mb = Email::constructMailboxName($mailacct);
116
117                                         if (strlen($mailacct['server'])) {
118                                                 $dcrpass = '';
119                                                 openssl_private_decrypt(hex2bin($mailacct['pass']), $dcrpass, $user['prvkey']);
120                                                 $mbox = Email::connect($mb, $mail_user, $dcrpass);
121                                                 unset($dcrpass);
122                                                 if (!$mbox) {
123                                                         DI::sysmsg()->addNotice(DI::l10n()->t('Failed to connect with email account using the settings provided.'));
124                                                 }
125                                         }
126                                 }
127                         }
128                 }
129
130                 Hook::callAll('connector_settings_post', $_POST);
131                 DI::baseUrl()->redirect(DI::args()->getQueryString());
132                 return;
133         }
134
135         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'features')) {
136                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/features', 'settings_features');
137                 foreach ($_POST as $k => $v) {
138                         if (strpos($k, 'feature_') === 0) {
139                                 DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0));
140                         }
141                 }
142                 return;
143         }
144 }
145
146 function settings_content(App $a)
147 {
148         $o = '';
149         Nav::setSelected('settings');
150
151         if (!DI::userSession()->getLocalUserId()) {
152                 //DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
153                 return Login::form();
154         }
155
156         if (!empty($_SESSION['submanage'])) {
157                 DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
158                 return '';
159         }
160
161         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'oauth')) {
162                 if ((DI::args()->getArgc() > 3) && (DI::args()->getArgv()[2] === 'delete')) {
163                         BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth', 't');
164
165                         DBA::delete('application-token', ['application-id' => DI::args()->getArgv()[3], 'uid' => DI::userSession()->getLocalUserId()]);
166                         DI::baseUrl()->redirect('settings/oauth/', true);
167                         return '';
168                 }
169
170                 $applications = DBA::selectToArray('application-view', ['id', 'uid', 'name', 'website', 'scopes', 'created_at'], ['uid' => DI::userSession()->getLocalUserId()]);
171
172                 $tpl = Renderer::getMarkupTemplate('settings/oauth.tpl');
173                 $o .= Renderer::replaceMacros($tpl, [
174                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
175                         '$baseurl'             => DI::baseUrl()->get(true),
176                         '$title'               => DI::l10n()->t('Connected Apps'),
177                         '$name'                => DI::l10n()->t('Name'),
178                         '$website'             => DI::l10n()->t('Home Page'),
179                         '$created_at'          => DI::l10n()->t('Created'),
180                         '$delete'              => DI::l10n()->t('Remove authorization'),
181                         '$apps'                => $applications,
182                 ]);
183                 return $o;
184         }
185
186         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'addon')) {
187                 $addon_settings_forms = [];
188                 foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'addon_settings']) as $hook) {
189                         $data = [];
190                         Hook::callSingle(DI::app(), 'addon_settings', [$hook['file'], $hook['function']], $data);
191
192                         if (!empty($data['href'])) {
193                                 $tpl = Renderer::getMarkupTemplate('settings/addon/link.tpl');
194                                 $addon_settings_forms[] = Renderer::replaceMacros($tpl, [
195                                         '$addon' => $data['addon'],
196                                         '$title' => $data['title'],
197                                         '$href'  => $data['href'],
198                                 ]);
199                         } elseif(!empty($data['addon'])) {
200                                 $tpl = Renderer::getMarkupTemplate('settings/addon/panel.tpl');
201                                 $addon_settings_forms[$data['addon']] = Renderer::replaceMacros($tpl, [
202                                         '$addon'  => $data['addon'],
203                                         '$title'  => $data['title'],
204                                         '$open'   => (DI::args()->getArgv()[2] ?? '') === $data['addon'],
205                                         '$html'   => $data['html'] ?? '',
206                                         '$submit' => $data['submit'] ?? DI::l10n()->t('Save Settings'),
207                                 ]);
208                         }
209                 }
210
211                 $tpl = Renderer::getMarkupTemplate('settings/addons.tpl');
212                 $o .= Renderer::replaceMacros($tpl, [
213                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_addon"),
214                         '$title'        => DI::l10n()->t('Addon Settings'),
215                         '$no_addons_settings_configured' => DI::l10n()->t('No Addon settings configured'),
216                         '$addon_settings_forms' => $addon_settings_forms,
217                 ]);
218                 return $o;
219         }
220
221         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'features')) {
222
223                 $arr = [];
224                 $features = Feature::get();
225                 foreach ($features as $fname => $fdata) {
226                         $arr[$fname] = [];
227                         $arr[$fname][0] = $fdata[0];
228                         foreach (array_slice($fdata,1) as $f) {
229                                 $arr[$fname][1][] = ['feature_' . $f[0], $f[1], Feature::isEnabled(DI::userSession()->getLocalUserId(), $f[0]), $f[2]];
230                         }
231                 }
232
233                 $tpl = Renderer::getMarkupTemplate('settings/features.tpl');
234                 $o .= Renderer::replaceMacros($tpl, [
235                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_features"),
236                         '$title'               => DI::l10n()->t('Additional Features'),
237                         '$features'            => $arr,
238                         '$submit'              => DI::l10n()->t('Save Settings'),
239                 ]);
240                 return $o;
241         }
242
243         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'connectors')) {
244                 $accept_only_sharer        = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'accept_only_sharer'));
245                 $enable_cw                 = !intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'disable_cw'));
246                 $enable_smart_shortening   = !intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'no_intelligent_shortening'));
247                 $simple_shortening         = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'simple_shortening'));
248                 $attach_link_title         = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'attach_link_title'));
249                 $legacy_contact            = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'ostatus', 'legacy_contact');
250
251                 if (!empty($legacy_contact)) {
252                         /// @todo Isn't it supposed to be a $a->internalRedirect() call?
253                         DI::page()['htmlhead'] = '<meta http-equiv="refresh" content="0; URL=' . DI::baseUrl().'/ostatus_subscribe?url=' . urlencode($legacy_contact) . '">';
254                 }
255
256                 $connector_settings_forms = [];
257                 foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'connector_settings']) as $hook) {
258                         $data = [];
259                         Hook::callSingle(DI::app(), 'connector_settings', [$hook['file'], $hook['function']], $data);
260
261                         $tpl = Renderer::getMarkupTemplate('settings/addon/connector.tpl');
262                         $connector_settings_forms[$data['connector']] = Renderer::replaceMacros($tpl, [
263                                 '$connector' => $data['connector'],
264                                 '$title'     => $data['title'],
265                                 '$image'     => $data['image'] ?? '',
266                                 '$enabled'   => $data['enabled'] ?? true,
267                                 '$open'      => (DI::args()->getArgv()[2] ?? '') === $data['connector'],
268                                 '$html'      => $data['html'] ?? '',
269                                 '$submit'    => $data['submit'] ?? DI::l10n()->t('Save Settings'),
270                         ]);
271                 }
272
273                 if ($a->isSiteAdmin()) {
274                         $diasp_enabled = DI::l10n()->t('Built-in support for %s connectivity is %s', DI::l10n()->t('Diaspora (Socialhome, Hubzilla)'), ((DI::config()->get('system', 'diaspora_enabled')) ? DI::l10n()->t('enabled') : DI::l10n()->t('disabled')));
275                         $ostat_enabled = DI::l10n()->t('Built-in support for %s connectivity is %s', DI::l10n()->t('OStatus (GNU Social)'), ((DI::config()->get('system', 'ostatus_disabled')) ? DI::l10n()->t('disabled') : DI::l10n()->t('enabled')));
276                 } else {
277                         $diasp_enabled = "";
278                         $ostat_enabled = "";
279                 }
280
281                 $mail_disabled = ((function_exists('imap_open') && (!DI::config()->get('system', 'imap_disabled'))) ? 0 : 1);
282                 if (!$mail_disabled) {
283                         $mailacct = DBA::selectFirst('mailacct', [], ['uid' => DI::userSession()->getLocalUserId()]);
284                 } else {
285                         $mailacct = null;
286                 }
287
288                 $mail_server       = $mailacct['server'] ?? '';
289                 $mail_port         = (!empty($mailacct['port']) && is_numeric($mailacct['port'])) ? (int)$mailacct['port'] : '';
290                 $mail_ssl          = $mailacct['ssltype'] ?? '';
291                 $mail_user         = $mailacct['user'] ?? '';
292                 $mail_replyto      = $mailacct['reply_to'] ?? '';
293                 $mail_pubmail      = $mailacct['pubmail'] ?? 0;
294                 $mail_action       = $mailacct['action'] ?? 0;
295                 $mail_movetofolder = $mailacct['movetofolder'] ?? '';
296                 $mail_chk          = $mailacct['last_check'] ?? DBA::NULL_DATETIME;
297
298
299                 $tpl = Renderer::getMarkupTemplate('settings/connectors.tpl');
300
301                 $mail_disabled_message = ($mail_disabled ? DI::l10n()->t('Email access is disabled on this site.') : '');
302
303                 $ssl_options = ['TLS' => 'TLS', 'SSL' => 'SSL'];
304
305                 if (DI::config()->get('system', 'insecure_imap')) {
306                         $ssl_options['notls'] = DI::l10n()->t('None');
307                 }
308
309                 $o .= Renderer::replaceMacros($tpl, [
310                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_connectors"),
311
312                         '$title'        => DI::l10n()->t('Social Networks'),
313
314                         '$diasp_enabled' => $diasp_enabled,
315                         '$ostat_enabled' => $ostat_enabled,
316
317                         '$general_settings' => DI::l10n()->t('General Social Media Settings'),
318                         '$accept_only_sharer' => [
319                                 'accept_only_sharer',
320                                 DI::l10n()->t('Followed content scope'),
321                                 $accept_only_sharer,
322                                 DI::l10n()->t('By default, conversations in which your follows participated but didn\'t start will be shown in your timeline. You can turn this behavior off, or expand it to the conversations in which your follows liked a post.'),
323                                 [
324                                         Item::COMPLETION_NONE    => DI::l10n()->t('Only conversations my follows started'),
325                                         Item::COMPLETION_COMMENT => DI::l10n()->t('Conversations my follows started or commented on (default)'),
326                                         Item::COMPLETION_LIKE    => DI::l10n()->t('Any conversation my follows interacted with, including likes'),
327                                 ]
328                         ],
329                         '$enable_cw' => ['enable_cw', DI::l10n()->t('Enable Content Warning'), $enable_cw, DI::l10n()->t('Users on networks like Mastodon or Pleroma are able to set a content warning field which collapse their post by default. This enables the automatic collapsing instead of setting the content warning as the post title. Doesn\'t affect any other content filtering you eventually set up.')],
330                         '$enable_smart_shortening' => ['enable_smart_shortening', DI::l10n()->t('Enable intelligent shortening'), $enable_smart_shortening, DI::l10n()->t('Normally the system tries to find the best link to add to shortened posts. If disabled, every shortened post will always point to the original friendica post.')],
331                         '$simple_shortening' => ['simple_shortening', DI::l10n()->t('Enable simple text shortening'), $simple_shortening, DI::l10n()->t('Normally the system shortens posts at the next line feed. If this option is enabled then the system will shorten the text at the maximum character limit.')],
332                         '$attach_link_title' => ['attach_link_title', DI::l10n()->t('Attach the link title'), $attach_link_title, DI::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.')],
333                         '$legacy_contact' => ['legacy_contact', DI::l10n()->t('Your legacy ActivityPub/GNU Social account'), $legacy_contact, DI::l10n()->t("If you enter your old account name from an ActivityPub based system or your GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done.")],
334
335                         '$repair_ostatus_url' => DI::baseUrl() . '/repair_ostatus',
336                         '$repair_ostatus_text' => DI::l10n()->t('Repair OStatus subscriptions'),
337
338                         '$connector_settings_forms' => $connector_settings_forms,
339
340                         '$h_mail' => DI::l10n()->t('Email/Mailbox Setup'),
341                         '$mail_desc' => DI::l10n()->t("If you wish to communicate with email contacts using this service \x28optional\x29, please specify how to connect to your mailbox."),
342                         '$mail_lastcheck' => ['mail_lastcheck', DI::l10n()->t('Last successful email check:'), $mail_chk, ''],
343                         '$mail_disabled' => $mail_disabled_message,
344                         '$mail_server'  => ['mail_server',      DI::l10n()->t('IMAP server name:'), $mail_server, ''],
345                         '$mail_port'    => ['mail_port',        DI::l10n()->t('IMAP port:'), $mail_port, ''],
346                         '$mail_ssl'     => ['mail_ssl',         DI::l10n()->t('Security:'), strtoupper($mail_ssl), '', $ssl_options],
347                         '$mail_user'    => ['mail_user',        DI::l10n()->t('Email login name:'), $mail_user, ''],
348                         '$mail_pass'    => ['mail_pass',        DI::l10n()->t('Email password:'), '', ''],
349                         '$mail_replyto' => ['mail_replyto',     DI::l10n()->t('Reply-to address:'), $mail_replyto, 'Optional'],
350                         '$mail_pubmail' => ['mail_pubmail',     DI::l10n()->t('Send public posts to all email contacts:'), $mail_pubmail, ''],
351                         '$mail_action'  => ['mail_action',      DI::l10n()->t('Action after import:'), $mail_action, '', [0 => DI::l10n()->t('None'), 1 => DI::l10n()->t('Delete'), 2 => DI::l10n()->t('Mark as seen'), 3 => DI::l10n()->t('Move to folder')]],
352                         '$mail_movetofolder' => ['mail_movetofolder', DI::l10n()->t('Move to folder:'), $mail_movetofolder, ''],
353                         '$submit' => DI::l10n()->t('Save Settings'),
354                 ]);
355
356                 Hook::callAll('display_settings', $o);
357                 return $o;
358         }
359 }