]> git.mxchange.org Git - friendica.git/blob - mod/settings.php
Merge pull request #11913 from tobiasd/2022.09-CHANGELOG
[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\Database\DBA;
30 use Friendica\DI;
31 use Friendica\Model\Item;
32 use Friendica\Model\User;
33 use Friendica\Module\BaseSettings;
34 use Friendica\Module\Security\Login;
35 use Friendica\Protocol\Email;
36
37 function settings_init(App $a)
38 {
39         if (!local_user()) {
40                 notice(DI::l10n()->t('Permission denied.'));
41                 return;
42         }
43
44         BaseSettings::createAside();
45 }
46
47 function settings_post(App $a)
48 {
49         if (!$a->isLoggedIn()) {
50                 notice(DI::l10n()->t('Permission denied.'));
51                 return;
52         }
53
54         if (!empty($_SESSION['submanage'])) {
55                 return;
56         }
57
58         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'addon')) {
59                 BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_addon');
60
61                 Hook::callAll('addon_settings_post', $_POST);
62                 DI::baseUrl()->redirect(DI::args()->getQueryString());
63                 return;
64         }
65
66         $user = User::getById($a->getLoggedInUserId());
67
68         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'connectors')) {
69                 BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_connectors');
70
71                 if (!empty($_POST['general-submit'])) {
72                         DI::pConfig()->set(local_user(), 'system', 'accept_only_sharer', intval($_POST['accept_only_sharer']));
73                         DI::pConfig()->set(local_user(), 'system', 'disable_cw', !intval($_POST['enable_cw']));
74                         DI::pConfig()->set(local_user(), 'system', 'no_intelligent_shortening', !intval($_POST['enable_smart_shortening']));
75                         DI::pConfig()->set(local_user(), 'system', 'simple_shortening', intval($_POST['simple_shortening']));
76                         DI::pConfig()->set(local_user(), 'system', 'attach_link_title', intval($_POST['attach_link_title']));
77                         DI::pConfig()->set(local_user(), 'ostatus', 'legacy_contact', $_POST['legacy_contact']);
78                 } elseif (!empty($_POST['mail-submit'])) {
79                         $mail_server       =                 $_POST['mail_server']       ?? '';
80                         $mail_port         =                 $_POST['mail_port']         ?? '';
81                         $mail_ssl          = strtolower(trim($_POST['mail_ssl']          ?? ''));
82                         $mail_user         =                 $_POST['mail_user']         ?? '';
83                         $mail_pass         =            trim($_POST['mail_pass']         ?? '');
84                         $mail_action       =            trim($_POST['mail_action']       ?? '');
85                         $mail_movetofolder =            trim($_POST['mail_movetofolder'] ?? '');
86                         $mail_replyto      =                 $_POST['mail_replyto']      ?? '';
87                         $mail_pubmail      =                 $_POST['mail_pubmail']      ?? '';
88
89                         if (function_exists('imap_open') && !DI::config()->get('system', 'imap_disabled')) {
90                                 if (!DBA::exists('mailacct', ['uid' => local_user()])) {
91                                         DBA::insert('mailacct', ['uid' => local_user()]);
92                                 }
93                                 if (strlen($mail_pass)) {
94                                         $pass = '';
95                                         openssl_public_encrypt($mail_pass, $pass, $user['pubkey']);
96                                         DBA::update('mailacct', ['pass' => bin2hex($pass)], ['uid' => local_user()]);
97                                 }
98
99                                 $r = DBA::update('mailacct', [
100                                         'server'       => $mail_server,
101                                         'port'         => $mail_port,
102                                         'ssltype'      => $mail_ssl,
103                                         'user'         => $mail_user,
104                                         'action'       => $mail_action,
105                                         'movetofolder' => $mail_movetofolder,
106                                         'mailbox'      => 'INBOX',
107                                         'reply_to'     => $mail_replyto,
108                                         'pubmail'      => $mail_pubmail
109                                 ], ['uid' => local_user()]);
110
111                                 Logger::debug('updating mailaccount', ['response' => $r]);
112                                 $mailacct = DBA::selectFirst('mailacct', [], ['uid' => local_user()]);
113                                 if (DBA::isResult($mailacct)) {
114                                         $mb = Email::constructMailboxName($mailacct);
115
116                                         if (strlen($mailacct['server'])) {
117                                                 $dcrpass = '';
118                                                 openssl_private_decrypt(hex2bin($mailacct['pass']), $dcrpass, $user['prvkey']);
119                                                 $mbox = Email::connect($mb, $mail_user, $dcrpass);
120                                                 unset($dcrpass);
121                                                 if (!$mbox) {
122                                                         notice(DI::l10n()->t('Failed to connect with email account using the settings provided.'));
123                                                 }
124                                         }
125                                 }
126                         }
127                 }
128
129                 Hook::callAll('connector_settings_post', $_POST);
130                 DI::baseUrl()->redirect(DI::args()->getQueryString());
131                 return;
132         }
133
134         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'features')) {
135                 BaseModule::checkFormSecurityTokenRedirectOnError('/settings/features', 'settings_features');
136                 foreach ($_POST as $k => $v) {
137                         if (strpos($k, 'feature_') === 0) {
138                                 DI::pConfig()->set(local_user(), 'feature', substr($k, 8), ((intval($v)) ? 1 : 0));
139                         }
140                 }
141                 return;
142         }
143 }
144
145 function settings_content(App $a)
146 {
147         $o = '';
148         Nav::setSelected('settings');
149
150         if (!local_user()) {
151                 //notice(DI::l10n()->t('Permission denied.'));
152                 return Login::form();
153         }
154
155         if (!empty($_SESSION['submanage'])) {
156                 notice(DI::l10n()->t('Permission denied.'));
157                 return '';
158         }
159
160         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'oauth')) {
161                 if ((DI::args()->getArgc() > 3) && (DI::args()->getArgv()[2] === 'delete')) {
162                         BaseModule::checkFormSecurityTokenRedirectOnError('/settings/oauth', 'settings_oauth', 't');
163
164                         DBA::delete('application-token', ['application-id' => DI::args()->getArgv()[3], 'uid' => local_user()]);
165                         DI::baseUrl()->redirect('settings/oauth/', true);
166                         return '';
167                 }
168
169                 $applications = DBA::selectToArray('application-view', ['id', 'uid', 'name', 'website', 'scopes', 'created_at'], ['uid' => local_user()]);
170
171                 $tpl = Renderer::getMarkupTemplate('settings/oauth.tpl');
172                 $o .= Renderer::replaceMacros($tpl, [
173                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_oauth"),
174                         '$baseurl'             => DI::baseUrl()->get(true),
175                         '$title'               => DI::l10n()->t('Connected Apps'),
176                         '$name'                => DI::l10n()->t('Name'),
177                         '$website'             => DI::l10n()->t('Home Page'),
178                         '$created_at'          => DI::l10n()->t('Created'),
179                         '$delete'              => DI::l10n()->t('Remove authorization'),
180                         '$apps'                => $applications,
181                 ]);
182                 return $o;
183         }
184
185         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'addon')) {
186                 $addon_settings_forms = [];
187                 foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'addon_settings']) as $hook) {
188                         $data = [];
189                         Hook::callSingle(DI::app(), 'addon_settings', [$hook['file'], $hook['function']], $data);
190
191                         if (!empty($data['href'])) {
192                                 $tpl = Renderer::getMarkupTemplate('settings/addon/link.tpl');
193                                 $addon_settings_forms[] = Renderer::replaceMacros($tpl, [
194                                         '$addon' => $data['addon'],
195                                         '$title' => $data['title'],
196                                         '$href'  => $data['href'],
197                                 ]);
198                         } elseif(!empty($data['addon'])) {
199                                 $tpl = Renderer::getMarkupTemplate('settings/addon/panel.tpl');
200                                 $addon_settings_forms[$data['addon']] = Renderer::replaceMacros($tpl, [
201                                         '$addon'  => $data['addon'],
202                                         '$title'  => $data['title'],
203                                         '$open'   => (DI::args()->getArgv()[2] ?? '') === $data['addon'],
204                                         '$html'   => $data['html'] ?? '',
205                                         '$submit' => $data['submit'] ?? DI::l10n()->t('Save Settings'),
206                                 ]);
207                         }
208                 }
209
210                 $tpl = Renderer::getMarkupTemplate('settings/addons.tpl');
211                 $o .= Renderer::replaceMacros($tpl, [
212                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_addon"),
213                         '$title'        => DI::l10n()->t('Addon Settings'),
214                         '$no_addons_settings_configured' => DI::l10n()->t('No Addon settings configured'),
215                         '$addon_settings_forms' => $addon_settings_forms,
216                 ]);
217                 return $o;
218         }
219
220         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'features')) {
221
222                 $arr = [];
223                 $features = Feature::get();
224                 foreach ($features as $fname => $fdata) {
225                         $arr[$fname] = [];
226                         $arr[$fname][0] = $fdata[0];
227                         foreach (array_slice($fdata,1) as $f) {
228                                 $arr[$fname][1][] = ['feature_' . $f[0], $f[1], Feature::isEnabled(local_user(), $f[0]), $f[2]];
229                         }
230                 }
231
232                 $tpl = Renderer::getMarkupTemplate('settings/features.tpl');
233                 $o .= Renderer::replaceMacros($tpl, [
234                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_features"),
235                         '$title'               => DI::l10n()->t('Additional Features'),
236                         '$features'            => $arr,
237                         '$submit'              => DI::l10n()->t('Save Settings'),
238                 ]);
239                 return $o;
240         }
241
242         if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'connectors')) {
243                 $accept_only_sharer        = intval(DI::pConfig()->get(local_user(), 'system', 'accept_only_sharer'));
244                 $enable_cw                 = !intval(DI::pConfig()->get(local_user(), 'system', 'disable_cw'));
245                 $enable_smart_shortening   = !intval(DI::pConfig()->get(local_user(), 'system', 'no_intelligent_shortening'));
246                 $simple_shortening         = intval(DI::pConfig()->get(local_user(), 'system', 'simple_shortening'));
247                 $attach_link_title         = intval(DI::pConfig()->get(local_user(), 'system', 'attach_link_title'));
248                 $legacy_contact            = DI::pConfig()->get(local_user(), 'ostatus', 'legacy_contact');
249
250                 if (!empty($legacy_contact)) {
251                         /// @todo Isn't it supposed to be a $a->internalRedirect() call?
252                         DI::page()['htmlhead'] = '<meta http-equiv="refresh" content="0; URL=' . DI::baseUrl().'/ostatus_subscribe?url=' . urlencode($legacy_contact) . '">';
253                 }
254
255                 $connector_settings_forms = [];
256                 foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'connector_settings']) as $hook) {
257                         $data = [];
258                         Hook::callSingle(DI::app(), 'connector_settings', [$hook['file'], $hook['function']], $data);
259
260                         $tpl = Renderer::getMarkupTemplate('settings/addon/connector.tpl');
261                         $connector_settings_forms[$data['connector']] = Renderer::replaceMacros($tpl, [
262                                 '$connector' => $data['connector'],
263                                 '$title'     => $data['title'],
264                                 '$image'     => $data['image'] ?? '',
265                                 '$enabled'   => $data['enabled'] ?? true,
266                                 '$open'      => (DI::args()->getArgv()[2] ?? '') === $data['connector'],
267                                 '$html'      => $data['html'] ?? '',
268                                 '$submit'    => $data['submit'] ?? DI::l10n()->t('Save Settings'),
269                         ]);
270                 }
271
272                 if ($a->isSiteAdmin()) {
273                         $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')));
274                         $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')));
275                 } else {
276                         $diasp_enabled = "";
277                         $ostat_enabled = "";
278                 }
279
280                 $mail_disabled = ((function_exists('imap_open') && (!DI::config()->get('system', 'imap_disabled'))) ? 0 : 1);
281                 if (!$mail_disabled) {
282                         $mailacct = DBA::selectFirst('mailacct', [], ['uid' => local_user()]);
283                 } else {
284                         $mailacct = null;
285                 }
286
287                 $mail_server       = $mailacct['server'] ?? '';
288                 $mail_port         = (!empty($mailacct['port']) && is_numeric($mailacct['port'])) ? (int)$mailacct['port'] : '';
289                 $mail_ssl          = $mailacct['ssltype'] ?? '';
290                 $mail_user         = $mailacct['user'] ?? '';
291                 $mail_replyto      = $mailacct['reply_to'] ?? '';
292                 $mail_pubmail      = $mailacct['pubmail'] ?? 0;
293                 $mail_action       = $mailacct['action'] ?? 0;
294                 $mail_movetofolder = $mailacct['movetofolder'] ?? '';
295                 $mail_chk          = $mailacct['last_check'] ?? DBA::NULL_DATETIME;
296
297
298                 $tpl = Renderer::getMarkupTemplate('settings/connectors.tpl');
299
300                 $mail_disabled_message = ($mail_disabled ? DI::l10n()->t('Email access is disabled on this site.') : '');
301
302                 $ssl_options = ['TLS' => 'TLS', 'SSL' => 'SSL'];
303
304                 if (DI::config()->get('system', 'insecure_imap')) {
305                         $ssl_options['notls'] = DI::l10n()->t('None');
306                 }
307
308                 $o .= Renderer::replaceMacros($tpl, [
309                         '$form_security_token' => BaseModule::getFormSecurityToken("settings_connectors"),
310
311                         '$title'        => DI::l10n()->t('Social Networks'),
312
313                         '$diasp_enabled' => $diasp_enabled,
314                         '$ostat_enabled' => $ostat_enabled,
315
316                         '$general_settings' => DI::l10n()->t('General Social Media Settings'),
317                         '$accept_only_sharer' => [
318                                 'accept_only_sharer',
319                                 DI::l10n()->t('Followed content scope'),
320                                 $accept_only_sharer,
321                                 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.'),
322                                 [
323                                         Item::COMPLETION_NONE    => DI::l10n()->t('Only conversations my follows started'),
324                                         Item::COMPLETION_COMMENT => DI::l10n()->t('Conversations my follows started or commented on (default)'),
325                                         Item::COMPLETION_LIKE    => DI::l10n()->t('Any conversation my follows interacted with, including likes'),
326                                 ]
327                         ],
328                         '$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.')],
329                         '$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.')],
330                         '$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.')],
331                         '$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.')],
332                         '$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.")],
333
334                         '$repair_ostatus_url' => DI::baseUrl() . '/repair_ostatus',
335                         '$repair_ostatus_text' => DI::l10n()->t('Repair OStatus subscriptions'),
336
337                         '$connector_settings_forms' => $connector_settings_forms,
338
339                         '$h_mail' => DI::l10n()->t('Email/Mailbox Setup'),
340                         '$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."),
341                         '$mail_lastcheck' => ['mail_lastcheck', DI::l10n()->t('Last successful email check:'), $mail_chk, ''],
342                         '$mail_disabled' => $mail_disabled_message,
343                         '$mail_server'  => ['mail_server',      DI::l10n()->t('IMAP server name:'), $mail_server, ''],
344                         '$mail_port'    => ['mail_port',        DI::l10n()->t('IMAP port:'), $mail_port, ''],
345                         '$mail_ssl'     => ['mail_ssl',         DI::l10n()->t('Security:'), strtoupper($mail_ssl), '', $ssl_options],
346                         '$mail_user'    => ['mail_user',        DI::l10n()->t('Email login name:'), $mail_user, ''],
347                         '$mail_pass'    => ['mail_pass',        DI::l10n()->t('Email password:'), '', ''],
348                         '$mail_replyto' => ['mail_replyto',     DI::l10n()->t('Reply-to address:'), $mail_replyto, 'Optional'],
349                         '$mail_pubmail' => ['mail_pubmail',     DI::l10n()->t('Send public posts to all email contacts:'), $mail_pubmail, ''],
350                         '$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')]],
351                         '$mail_movetofolder' => ['mail_movetofolder', DI::l10n()->t('Move to folder:'), $mail_movetofolder, ''],
352                         '$submit' => DI::l10n()->t('Save Settings'),
353                 ]);
354
355                 Hook::callAll('display_settings', $o);
356                 return $o;
357         }
358 }