]> git.mxchange.org Git - friendica.git/blobdiff - mod/admin.php
Merge pull request #4882 from annando/private-forums
[friendica.git] / mod / admin.php
index 34514f2075883ebedcfcbd6abc075770ecc8a499..3debb57bedf2072d2b1d02de3918df7ac9b5f093 100644 (file)
@@ -17,9 +17,11 @@ use Friendica\Core\Worker;
 use Friendica\Database\DBM;
 use Friendica\Database\DBStructure;
 use Friendica\Model\Contact;
-use Friendica\Model\User;
 use Friendica\Model\Item;
+use Friendica\Model\User;
 use Friendica\Module\Login;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Temporal;
 
 require_once 'include/enotify.php';
 require_once 'include/text.php';
@@ -107,6 +109,9 @@ function admin_post(App $a)
                                }
                                $return_path = 'admin/themes/' . $theme;
                                break;
+                       case 'tos':
+                               admin_page_tos_post($a);
+                               break;
                        case 'features':
                                admin_page_features_post($a);
                                break;
@@ -171,17 +176,32 @@ function admin_content(App $a)
        // array(url, name, extra css classes)
        // not part of $aside to make the template more adjustable
        $aside_sub = [
-               'site'         => ["admin/site/"        , L10n::t("Site")                 , "site"],
-               'users'        => ["admin/users/"       , L10n::t("Users")                , "users"],
-               'addons'       => ["admin/addons/"      , L10n::t("Addons")               , "addons"],
-               'themes'       => ["admin/themes/"      , L10n::t("Themes")               , "themes"],
-               'features'     => ["admin/features/"    , L10n::t("Additional features")  , "features"],
-               'dbsync'       => ["admin/dbsync/"      , L10n::t('DB updates')           , "dbsync"],
-               'queue'        => ["admin/queue/"       , L10n::t('Inspect Queue')        , "queue"],
-               'contactblock' => ["admin/contactblock/", L10n::t('Contact Blocklist')    , "contactblock"],
-               'blocklist'    => ["admin/blocklist/"   , L10n::t('Server Blocklist')     , "blocklist"],
-               'federation'   => ["admin/federation/"  , L10n::t('Federation Statistics'), "federation"],
-               'deleteitem'   => ["admin/deleteitem/"  , L10n::t('Delete Item')          , 'deleteitem'],
+               'information' => [ L10n::t('Information'), [
+                       "overview" => ["admin/", L10n::t("Overview"), "overview" ],
+                       'federation'   => ["admin/federation/"  , L10n::t('Federation Statistics'), "federation"] ]],
+               'configuration' => [ L10n::t('Configuration'), [
+                       'site'         => ["admin/site/"        , L10n::t("Site")                 , "site"],
+                       'users'        => ["admin/users/"       , L10n::t("Users")                , "users"],
+                       'addons'       => ["admin/addons/"      , L10n::t("Addons")               , "addons"],
+                       'themes'       => ["admin/themes/"      , L10n::t("Themes")               , "themes"],
+                       'features'     => ["admin/features/"    , L10n::t("Additional features")  , "features"],
+                       'tos'          => ["admin/tos/"         , L10n::t("Terms of Service")     , "tos"] ]],
+               'database' => [ L10n::t('Database'), [
+                       'dbsync'       => ["admin/dbsync/"      , L10n::t('DB updates')           , "dbsync"],
+                       'queue'        => ["admin/queue/"       , L10n::t('Inspect Queue')        , "queue"], ]],
+               'tools' => [ L10n::t('Tools'), [
+                       'contactblock' => ["admin/contactblock/", L10n::t('Contact Blocklist')    , "contactblock"],
+                       'blocklist'    => ["admin/blocklist/"   , L10n::t('Server Blocklist')     , "blocklist"],
+                       'deleteitem'   => ["admin/deleteitem/"  , L10n::t('Delete Item')          , 'deleteitem'], ]],
+               "logs" => [ L10n::t("Logs"), [
+                       "logsconfig" => ["admin/logs/", L10n::t("Logs"), "logs"],
+                       "logsview" => ["admin/viewlogs/", L10n::t("View Logs"), 'viewlogs']
+               ]],
+               "diagnostics" => [ L10n::t("Diagnostics"), [
+                       "phpinfo" => ['phpinfo/', L10n::t('PHP Info'), 'phpinfo'],
+                       "probe" => ['probe/', L10n::t('probe address'), 'probe'],
+                       "webfinger" =>['webfinger/', L10n::t('check webfinger'), 'webfinger']
+               ]]
        ];
 
        /* get addons admin page */
@@ -195,19 +215,12 @@ function admin_content(App $a)
                $a->addons_admin[] = $addon;
        }
 
-       $aside_tools['logs'] = ["admin/logs/", L10n::t("Logs"), "logs"];
-       $aside_tools['viewlogs'] = ["admin/viewlogs/", L10n::t("View Logs"), 'viewlogs'];
-       $aside_tools['diagnostics_probe'] = ['probe/', L10n::t('probe address'), 'probe'];
-       $aside_tools['diagnostics_webfinger'] = ['webfinger/', L10n::t('check webfinger'), 'webfinger'];
-
        $t = get_markup_template('admin/aside.tpl');
        $a->page['aside'] .= replace_macros($t, [
                '$admin' => $aside_tools,
                '$subpages' => $aside_sub,
                '$admtxt' => L10n::t('Admin'),
                '$plugadmtxt' => L10n::t('Addon Features'),
-               '$logtxt' => L10n::t('Logs'),
-               '$diagnosticstxt' => L10n::t('diagnostics'),
                '$h_pending' => L10n::t('User registrations waiting for confirmation'),
                '$admurl' => "admin/"
        ]);
@@ -256,6 +269,9 @@ function admin_content(App $a)
                        case 'deleteitem':
                                $o = admin_page_deleteitem($a);
                                break;
+                       case 'tos':
+                               $o = admin_page_tos($a);
+                               break;
                        default:
                                notice(L10n::t("Item not found."));
                }
@@ -272,6 +288,50 @@ function admin_content(App $a)
        }
 }
 
+/**
+ * @brief Subpage to define the display of a Terms of Usage page.
+ *
+ * @param App $a
+ * @return string
+ */
+function admin_page_tos(App $a)
+{
+       $t = get_markup_template('admin/tos.tpl');
+       return replace_macros($t, [
+               '$title' => L10n::t('Administration'),
+               '$page' => L10n::t('Terms of Service'),
+               '$displaytos' => ['displaytos', L10n::t('Display Terms of Service'), Config::get('system', 'tosdisplay'), L10n::t('Enable the Terms of Service page. If this is enabled a link to the terms will be added to the registration form and the general information page.')],
+               '$displayprivstatement' => ['displayprivstatement', L10n::t('Display Privacy Statement'), Config::get('system','tosprivstatement'), L10n::t('Show some informations regarding the needed information to operate the node according e.g. to <a href="%s" target="_blank">EU-GDPR</a>.','https://en.wikipedia.org/wiki/General_Data_Protection_Regulation')],
+               '$tostext' => ['tostext', L10n::t('The Terms of Service'), Config::get('system', 'tostext'), L10n::t('Enter the Terms of Service for your node here. You can use BBCode. Headers of sections should be [h2] and below.')],
+               '$form_security_token' => get_form_security_token("admin_tos"),
+               '$submit' => L10n::t('Save Settings'),
+       ]);
+}
+/**
+ * @brief Process send data from Admin TOS Page
+ *
+ * @param App $a
+ */
+function admin_page_tos_post(App $a)
+{
+       check_form_security_token_redirectOnErr('/admin/tos', 'admin_tos');
+
+       if (!x($_POST, "page_tos")) {
+               return;
+       }
+
+       $displaytos = ((x($_POST, 'displaytos')) ? True : False);
+       $displayprivstatement = ((x($_POST, 'displayprivstatement')) ? True : False);
+       $tostext = ((x($_POST, 'tostext')) ? strip_tags(trim($_POST['tostext'])) : '');
+
+       Config::set('system', 'tosdisplay', $displaytos);
+       Config::set('system', 'tosprivstatement', $displayprivstatement);
+       Config::set('system', 'tostext', $tostext);
+
+       goaway('admin/tos');
+
+       return; // NOTREACHED
+}
 /**
  * @brief Subpage to modify the server wide block list via the admin panel.
  *
@@ -375,12 +435,12 @@ function admin_page_contactblock_post(App $a)
        check_form_security_token_redirectOnErr('/admin/contactblock', 'admin_contactblock');
 
        if (x($_POST, 'page_contactblock_block')) {
-               $contact_id = Contact::getIdForURL($contact_url, 0);
+               $contact_id = Contact::getIdForURL($contact_url);
                if ($contact_id) {
                        Contact::block($contact_id);
                        notice(L10n::t('The contact has been blocked from the node'));
                } else {
-                       notice(L10n::t('Could not find any contact entry for this URL (%s)', $contact_url));
+                       notice(L10n::t("Could not find any contact entry for this URL \x28%s\x29", $contact_url));
                }
        }
        if (x($_POST, 'page_contactblock_unblock')) {
@@ -496,7 +556,7 @@ function admin_page_deleteitem_post(App $a)
                // associated threads.
                $r = dba::select('item', ['id'], ['guid' => $guid]);
                while ($row = dba::fetch($r)) {
-                       Item::delete($row['id']);
+                       Item::deleteById($row['id']);
                }
                dba::close($r);
        }
@@ -530,7 +590,7 @@ function admin_page_federation(App $a)
        // off one % two of them are needed in the query
        // Add more platforms if you like, when one returns 0 known nodes it is not
        // displayed on the stats page.
-       $platforms = ['Friendi%%a', 'Diaspora', '%%red%%', 'Hubzilla', 'BlaBlaNet', 'GNU Social', 'StatusNet', 'Mastodon', 'Pleroma', 'socialhome'];
+       $platforms = ['Friendi%%a', 'Diaspora', '%%red%%', 'Hubzilla', 'BlaBlaNet', 'GNU Social', 'StatusNet', 'Mastodon', 'Pleroma', 'socialhome', 'ganggo'];
        $colors = [
                'Friendi%%a' => '#ffc018', // orange from the logo
                'Diaspora'   => '#a1a1a1', // logo is black and white, makes a gray
@@ -541,7 +601,8 @@ function admin_page_federation(App $a)
                'StatusNet'  => '#789240', // the green from the logo (red and blue have already others
                'Mastodon'   => '#1a9df9', // blue from the Mastodon logo
                'Pleroma'    => '#E46F0F', // Orange from the text that is used on Pleroma instances
-               'socialhome' => '#52056b'  // lilac from the Django Image used at the Socialhome homepage
+               'socialhome' => '#52056b' , // lilac from the Django Image used at the Socialhome homepage
+               'ganggo'     => '#69d7e2' // from the favicon
        ];
        $counts = [];
        $total = 0;
@@ -625,8 +686,21 @@ function admin_page_federation(App $a)
                        $v = $newVv;
                }
 
-               foreach ($v as $key => $vv)
-                       $v[$key]["version"] = trim(strip_tags($vv["version"]));
+               // Assure that the versions are sorted correctly
+               $v2 = [];
+               $versions = [];
+               foreach ($v as $vv) {
+                       $version = trim(strip_tags($vv["version"]));
+                       $v2[$version] = $vv;
+                       $versions[] = $version;
+               }
+
+               usort($versions, 'version_compare');
+
+               $v = [];
+               foreach ($versions as $version) {
+                       $v[] = $v2[$version];
+               }
 
                // the 3rd array item is needed for the JavaScript graphs as JS does
                // not like some characters in the names of variables...
@@ -708,7 +782,7 @@ function admin_page_summary(App $a)
        $warningtext = [];
        if (DBM::is_result($r)) {
                $showwarning = true;
-               $warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php scripts/dbstructure.php toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
+               $warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php bin/console.php dbstructure toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
        }
        // Check if github.com/friendica/master/VERSION is higher then
        // the local version of Friendica. Check is opt-in, source may be master or devel branch
@@ -725,14 +799,14 @@ function admin_page_summary(App $a)
        }
        if (Config::get('system', 'dbupdate') == DB_UPDATE_FAILED) {
                $showwarning = true;
-               $warningtext[] = L10n::t('The database update failed. Please run "php scripts/dbstructure.php update" from the command line and have a look at the errors that might appear.');
+               $warningtext[] = L10n::t('The database update failed. Please run "php bin/console.php dbstructure update" from the command line and have a look at the errors that might appear.');
        }
 
        $last_worker_call = Config::get('system', 'last_poller_execution', false);
        if (!$last_worker_call) {
                $showwarning = true;
                $warningtext[] = L10n::t('The worker was never executed. Please check your database structure!');
-       } elseif ((strtotime(datetime_convert()) - strtotime($last_worker_call)) > 60 * 60) {
+       } elseif ((strtotime(DateTimeFormat::utcNow()) - strtotime($last_worker_call)) > 60 * 60) {
                $showwarning = true;
                $warningtext[] = L10n::t('The last worker execution was on %s UTC. This is older than one hour. Please check your crontab settings.', $last_worker_call);
        }
@@ -861,8 +935,9 @@ function admin_page_site_post(App $a)
                update_table("gcontact", ['connect', 'addr'], $old_host, $new_host);
 
                // update config
-               $a->set_baseurl($new_url);
+               Config::set('system', 'hostname', parse_url($new_url,  PHP_URL_HOST));
                Config::set('system', 'url', $new_url);
+               $a->set_baseurl($new_url);
 
                // send relocate
                $users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0");
@@ -896,7 +971,7 @@ function admin_page_site_post(App $a)
        $daily_registrations    =       ((x($_POST,'max_daily_registrations'))  ? intval(trim($_POST['max_daily_registrations']))       :0);
        $abandon_days           =       ((x($_POST,'abandon_days'))             ? intval(trim($_POST['abandon_days']))          :  0);
 
-       $register_text          =       ((x($_POST,'register_text'))            ? notags(trim($_POST['register_text']))         : '');
+       $register_text          =       ((x($_POST,'register_text'))            ? strip_tags(trim($_POST['register_text']))             : '');
 
        $allowed_sites          =       ((x($_POST,'allowed_sites'))            ? notags(trim($_POST['allowed_sites']))         : '');
        $allowed_email          =       ((x($_POST,'allowed_email'))            ? notags(trim($_POST['allowed_email']))         : '');
@@ -950,11 +1025,19 @@ function admin_page_site_post(App $a)
        $only_tag_search        =       ((x($_POST,'only_tag_search'))          ? True                                          : False);
        $rino                   =       ((x($_POST,'rino'))                     ? intval($_POST['rino'])                        : 0);
        $check_new_version_url  =       ((x($_POST, 'check_new_version_url'))   ?       notags(trim($_POST['check_new_version_url']))   : 'none');
+
        $worker_queues          =       ((x($_POST,'worker_queues'))            ? intval($_POST['worker_queues'])               : 4);
        $worker_dont_fork       =       ((x($_POST,'worker_dont_fork'))         ? True                                          : False);
        $worker_fastlane        =       ((x($_POST,'worker_fastlane'))          ? True                                          : False);
        $worker_frontend        =       ((x($_POST,'worker_frontend'))          ? True                                          : False);
 
+       $relay_directly         =       ((x($_POST,'relay_directly'))           ? True                                          : False);
+       $relay_server           =       ((x($_POST,'relay_server'))             ? notags(trim($_POST['relay_server']))          : '');
+       $relay_subscribe        =       ((x($_POST,'relay_subscribe'))          ? True                                          : False);
+       $relay_scope            =       ((x($_POST,'relay_scope'))              ? notags(trim($_POST['relay_scope']))           : '');
+       $relay_server_tags      =       ((x($_POST,'relay_server_tags'))        ? notags(trim($_POST['relay_server_tags']))     : '');
+       $relay_user_tags        =       ((x($_POST,'relay_user_tags'))          ? True                                          : False);
+
        // Has the directory url changed? If yes, then resubmit the existing profiles there
        if ($global_directory != Config::get('system', 'directory') && ($global_directory != '')) {
                Config::set('system', 'directory', $global_directory);
@@ -1108,10 +1191,19 @@ function admin_page_site_post(App $a)
        Config::set('system', 'basepath', $basepath);
        Config::set('system', 'proxy_disabled', $proxy_disabled);
        Config::set('system', 'only_tag_search', $only_tag_search);
+
        Config::set('system', 'worker_queues', $worker_queues);
        Config::set('system', 'worker_dont_fork', $worker_dont_fork);
        Config::set('system', 'worker_fastlane', $worker_fastlane);
        Config::set('system', 'frontend_worker', $worker_frontend);
+
+       Config::set('system', 'relay_directly', $relay_directly);
+       Config::set('system', 'relay_server', $relay_server);
+       Config::set('system', 'relay_subscribe', $relay_subscribe);
+       Config::set('system', 'relay_scope', $relay_scope);
+       Config::set('system', 'relay_server_tags', $relay_server_tags);
+       Config::set('system', 'relay_user_tags', $relay_user_tags);
+
        Config::set('system', 'rino_encrypt', $rino);
 
        info(L10n::t('Site settings updated.') . EOL);
@@ -1223,7 +1315,7 @@ function admin_page_site(App $a)
        $ssl_choices = [
                SSL_POLICY_NONE => L10n::t("No SSL policy, links will track page SSL state"),
                SSL_POLICY_FULL => L10n::t("Force all links to use SSL"),
-               SSL_POLICY_SELFSIGN => L10n::t("Self-signed certificate, use SSL for local links only (discouraged)")
+               SSL_POLICY_SELFSIGN => L10n::t("Self-signed certificate, use SSL for local links only \x28discouraged\x29")
        ];
 
        $check_git_version_choices = [
@@ -1260,6 +1352,7 @@ function admin_page_site(App $a)
                '$portable_contacts' => L10n::t('Auto Discovered Contact Directory'),
                '$performance' => L10n::t('Performance'),
                '$worker_title' => L10n::t('Worker'),
+               '$relay_title' => L10n::t('Message Relay'),
                '$relocate' => L10n::t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
                '$baseurl' => System::baseUrl(true),
                // name, label, value, help string, extra data...
@@ -1283,15 +1376,15 @@ function admin_page_site(App $a)
 
                '$register_policy'      => ['register_policy', L10n::t("Register policy"), $a->config['register_policy'], "", $register_choices],
                '$daily_registrations'  => ['max_daily_registrations', L10n::t("Maximum Daily Registrations"), Config::get('system', 'max_daily_registrations'), L10n::t("If registration is permitted above, this sets the maximum number of new user registrations to accept per day.  If register is set to closed, this setting has no effect.")],
-               '$register_text'        => ['register_text', L10n::t("Register text"), $a->config['register_text'], L10n::t("Will be displayed prominently on the registration page.")],
+               '$register_text'        => ['register_text', L10n::t("Register text"), $a->config['register_text'], L10n::t("Will be displayed prominently on the registration page. You can use BBCode here.")],
                '$abandon_days'         => ['abandon_days', L10n::t('Accounts abandoned after x days'), Config::get('system','account_abandon_days'), L10n::t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')],
                '$allowed_sites'        => ['allowed_sites', L10n::t("Allowed friend domains"), Config::get('system','allowed_sites'), L10n::t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")],
                '$allowed_email'        => ['allowed_email', L10n::t("Allowed email domains"), Config::get('system','allowed_email'), L10n::t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")],
-               '$no_oembed_rich_content' => ['no_oembed_rich_content', L10n::t("No OEmbed rich content"), Config::get('system','no_oembed_rich_content'), L10n::t("Don't show the rich content (e.g. embedded PDF), except from the domains listed below.")],
+               '$no_oembed_rich_content' => ['no_oembed_rich_content', L10n::t("No OEmbed rich content"), Config::get('system','no_oembed_rich_content'), L10n::t("Don't show the rich content \x28e.g. embedded PDF\x29, except from the domains listed below.")],
                '$allowed_oembed'       => ['allowed_oembed', L10n::t("Allowed OEmbed domains"), Config::get('system','allowed_oembed'), L10n::t("Comma separated list of domains which oembed content is allowed to be displayed. Wildcards are accepted.")],
                '$block_public'         => ['block_public', L10n::t("Block public"), Config::get('system','block_public'), L10n::t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")],
                '$force_publish'        => ['publish_all', L10n::t("Force publish"), Config::get('system','publish_all'), L10n::t("Check to force all profiles on this site to be listed in the site directory.")],
-               '$global_directory'     => ['directory', L10n::t("Global directory URL"), Config::get('system','directory'), L10n::t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")],
+               '$global_directory'     => ['directory', L10n::t("Global directory URL"), Config::get('system', 'directory', 'https://dir.friendica.social'), L10n::t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")],
                '$newuser_private'      => ['newuser_private', L10n::t("Private posts by default for new users"), Config::get('system','newuser_private'), L10n::t("Set default post permissions for all new members to the default privacy group rather than public.")],
                '$enotify_no_content'   => ['enotify_no_content', L10n::t("Don't include post content in email notifications"), Config::get('system','enotify_no_content'), L10n::t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")],
                '$private_addons'       => ['private_addons', L10n::t("Disallow public access to addons listed in the apps menu."), Config::get('config','private_addons'), L10n::t("Checking this box will restrict addons listed in the apps menu to members only.")],
@@ -1301,23 +1394,23 @@ function admin_page_site(App $a)
                '$no_openid'            => ['no_openid', L10n::t("OpenID support"), !Config::get('system','no_openid'), L10n::t("OpenID support for registration and logins.")],
                '$no_regfullname'       => ['no_regfullname', L10n::t("Fullname check"), !Config::get('system','no_regfullname'), L10n::t("Force users to register with a space between firstname and lastname in Full name, as an antispam measure")],
                '$community_page_style' => ['community_page_style', L10n::t("Community pages for visitors"), Config::get('system','community_page_style'), L10n::t("Which community pages should be available for visitors. Local users always see both pages."), $community_page_style_choices],
-               '$max_author_posts_community_page' => ['max_author_posts_community_page', L10n::t("Posts per user on community page"), Config::get('system','max_author_posts_community_page'), L10n::t("The maximum number of posts per user on the community page. (Not valid for 'Global Community')")],
+               '$max_author_posts_community_page' => ['max_author_posts_community_page', L10n::t("Posts per user on community page"), Config::get('system','max_author_posts_community_page'), L10n::t("The maximum number of posts per user on the community page. \x28Not valid for 'Global Community'\x29")],
                '$ostatus_disabled'     => ['ostatus_disabled', L10n::t("Enable OStatus support"), !Config::get('system','ostatus_disabled'), L10n::t("Provide built-in OStatus \x28StatusNet, GNU Social etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")],
                '$ostatus_full_threads' => ['ostatus_full_threads', L10n::t("Only import OStatus threads from our contacts"), Config::get('system','ostatus_full_threads'), L10n::t("Normally we import every content from our OStatus contacts. With this option we only store threads that are started by a contact that is known on our system.")],
                '$ostatus_not_able'     => L10n::t("OStatus support can only be enabled if threading is enabled."),
                '$diaspora_able'        => $diaspora_able,
                '$diaspora_not_able'    => L10n::t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),
-               '$diaspora_enabled'     => ['diaspora_enabled', L10n::t("Enable Diaspora support"), Config::get('system','diaspora_enabled'), L10n::t("Provide built-in Diaspora network compatibility.")],
+               '$diaspora_enabled'     => ['diaspora_enabled', L10n::t("Enable Diaspora support"), Config::get('system', 'diaspora_enabled', $diaspora_able), L10n::t("Provide built-in Diaspora network compatibility.")],
                '$dfrn_only'            => ['dfrn_only', L10n::t('Only allow Friendica contacts'), Config::get('system','dfrn_only'), L10n::t("All contacts must use Friendica protocols. All other built-in communication protocols disabled.")],
-               '$verifyssl'            => ['verifyssl', L10n::t("Verify SSL"), Config::get('system','verifyssl'), L10n::t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites.")],
+               '$verifyssl'            => ['verifyssl', L10n::t("Verify SSL"), Config::get('system','verifyssl'), L10n::t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect \x28at all\x29 to self-signed SSL sites.")],
                '$proxyuser'            => ['proxyuser', L10n::t("Proxy user"), Config::get('system','proxyuser'), ""],
                '$proxy'                => ['proxy', L10n::t("Proxy URL"), Config::get('system','proxy'), ""],
-               '$timeout'              => ['timeout', L10n::t("Network timeout"), (x(Config::get('system','curl_timeout'))?Config::get('system','curl_timeout'):60), L10n::t("Value is in seconds. Set to 0 for unlimited (not recommended).")],
-               '$maxloadavg'           => ['maxloadavg', L10n::t("Maximum Load Average"), ((intval(Config::get('system','maxloadavg')) > 0)?Config::get('system','maxloadavg'):50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")],
-               '$maxloadavg_frontend'  => ['maxloadavg_frontend', L10n::t("Maximum Load Average (Frontend)"), ((intval(Config::get('system','maxloadavg_frontend')) > 0)?Config::get('system','maxloadavg_frontend'):50), L10n::t("Maximum system load before the frontend quits service - default 50.")],
-               '$min_memory'           => ['min_memory', L10n::t("Minimal Memory"), ((intval(Config::get('system','min_memory')) > 0)?Config::get('system','min_memory'):0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 (deactivated).")],
-               '$optimize_max_tablesize'=> ['optimize_max_tablesize', L10n::t("Maximum table size for optimization"), $optimize_max_tablesize, L10n::t("Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it.")],
-               '$optimize_fragmentation'=> ['optimize_fragmentation', L10n::t("Minimum level of fragmentation"), ((intval(Config::get('system','optimize_fragmentation')) > 0)?Config::get('system','optimize_fragmentation'):30), L10n::t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")],
+               '$timeout'              => ['timeout', L10n::t("Network timeout"), Config::get('system', 'curl_timeout', 60), L10n::t("Value is in seconds. Set to 0 for unlimited \x28not recommended\x29.")],
+               '$maxloadavg'           => ['maxloadavg', L10n::t("Maximum Load Average"), Config::get('system', 'maxloadavg', 50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")],
+               '$maxloadavg_frontend'  => ['maxloadavg_frontend', L10n::t("Maximum Load Average \x28Frontend\x29"), Config::get('system', 'maxloadavg_frontend', 50), L10n::t("Maximum system load before the frontend quits service - default 50.")],
+               '$min_memory'           => ['min_memory', L10n::t("Minimal Memory"), Config::get('system', 'min_memory', 0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 \x28deactivated\x29.")],
+               '$optimize_max_tablesize'=> ['optimize_max_tablesize', L10n::t("Maximum table size for optimization"), $optimize_max_tablesize, L10n::t("Maximum table size \x28in MB\x29 for the automatic optimization - default 100 MB. Enter -1 to disable it.")],
+               '$optimize_fragmentation'=> ['optimize_fragmentation', L10n::t("Minimum level of fragmentation"), Config::get('system', 'optimize_fragmentation', 30), L10n::t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")],
 
                '$poco_completion'      => ['poco_completion', L10n::t("Periodical check of global contacts"), Config::get('system','poco_completion'), L10n::t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")],
                '$poco_requery_days'    => ['poco_requery_days', L10n::t("Days between requery"), Config::get('system','poco_requery_days'), L10n::t("Number of days after which a server is requeried for his contacts.")],
@@ -1330,7 +1423,7 @@ function admin_page_site(App $a)
                '$check_new_version_url' => ['check_new_version_url', L10n::t("Check upstream version"), Config::get('system', 'check_new_version_url'), L10n::t("Enables checking for new Friendica versions at github. If there is a new version, you will be informed in the admin panel overview."), $check_git_version_choices],
                '$suppress_tags'        => ['suppress_tags', L10n::t("Suppress Tags"), Config::get('system','suppress_tags'), L10n::t("Suppress showing a list of hashtags at the end of the posting.")],
                '$itemcache'            => ['itemcache', L10n::t("Path to item cache"), Config::get('system','itemcache'), L10n::t("The item caches buffers generated bbcode and external images.")],
-               '$itemcache_duration'   => ['itemcache_duration', L10n::t("Cache duration in seconds"), Config::get('system','itemcache_duration'), L10n::t("How long should the cache files be hold? Default value is 86400 seconds (One day). To disable the item cache, set the value to -1.")],
+               '$itemcache_duration'   => ['itemcache_duration', L10n::t("Cache duration in seconds"), Config::get('system','itemcache_duration'), L10n::t("How long should the cache files be hold? Default value is 86400 seconds \x28One day\x29. To disable the item cache, set the value to -1.")],
                '$max_comments'         => ['max_comments', L10n::t("Maximum numbers of comments per post"), Config::get('system','max_comments'), L10n::t("How much comments should be shown for each post? Default value is 100.")],
                '$temppath'             => ['temppath', L10n::t("Temp path"), Config::get('system','temppath'), L10n::t("If you have a restricted system where the webserver can't access the system temp path, enter another path here.")],
                '$basepath'             => ['basepath', L10n::t("Base path to installation"), Config::get('system','basepath'), L10n::t("If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot.")],
@@ -1339,12 +1432,19 @@ function admin_page_site(App $a)
 
                '$relocate_url'         => ['relocate_url', L10n::t("New base url"), System::baseUrl(), L10n::t("Change base url for this server. Sends relocate message to all Friendica and Diaspora* contacts of all users.")],
 
-               '$rino'                 => ['rino', L10n::t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), L10n::t("Encryption layer between nodes."), [0 => "Disabled", 1 => "Enabled"]],
+               '$rino'                 => ['rino', L10n::t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), L10n::t("Encryption layer between nodes."), [0 => L10n::t("Disabled"), 1 => L10n::t("Enabled")]],
 
                '$worker_queues'        => ['worker_queues', L10n::t("Maximum number of parallel workers"), Config::get('system','worker_queues'), L10n::t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")],
                '$worker_dont_fork'     => ['worker_dont_fork', L10n::t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), L10n::t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")],
                '$worker_fastlane'      => ['worker_fastlane', L10n::t("Enable fastlane"), Config::get('system','worker_fastlane'), L10n::t("When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.")],
-               '$worker_frontend'      => ['worker_frontend', L10n::t('Enable frontend worker'), Config::get('system','frontend_worker'), L10n::t('When enabled the Worker process is triggered when backend access is performed (e.g. messages being delivered). On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', System::baseUrl())],
+               '$worker_frontend'      => ['worker_frontend', L10n::t('Enable frontend worker'), Config::get('system','frontend_worker'), L10n::t('When enabled the Worker process is triggered when backend access is performed \x28e.g. messages being delivered\x29. On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', System::baseUrl())],
+
+               '$relay_subscribe'      => ['relay_subscribe', L10n::t("Subscribe to relay"), Config::get('system','relay_subscribe'), L10n::t("Enables the receiving of public posts from the relay. They will be included in the search, subscribed tags and on the global community page.")],
+               '$relay_server'         => ['relay_server', L10n::t("Relay server"), Config::get('system', 'relay_server', 'https://relay.diasp.org'), L10n::t("Address of the relay server where public posts should be send to. For example https://relay.diasp.org")],
+               '$relay_directly'       => ['relay_directly', L10n::t("Direct relay transfer"), Config::get('system','relay_directly'), L10n::t("Enables the direct transfer to other servers without using the relay servers")],
+               '$relay_scope'          => ['relay_scope', L10n::t("Relay scope"), Config::get('system','relay_scope'), L10n::t("Can be 'all' or 'tags'. 'all' means that every public post should be received. 'tags' means that only posts with selected tags should be received."), ['' => L10n::t('Disabled'), 'all' => L10n::t('all'), 'tags' => L10n::t('tags')]],
+               '$relay_server_tags'    => ['relay_server_tags', L10n::t("Server tags"), Config::get('system','relay_server_tags'), L10n::t("Comma separated list of tags for the 'tags' subscription.")],
+               '$relay_user_tags'      => ['relay_user_tags', L10n::t("Allow user tags"), Config::get('system', 'relay_user_tags', true), L10n::t("If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'.")],
 
                '$form_security_token'  => get_form_security_token("admin_site")
        ]);
@@ -1431,7 +1531,7 @@ function admin_page_dbsync(App $a)
                        '$base' => System::baseUrl(true),
                        '$banner' => L10n::t('Failed Updates'),
                        '$desc' => L10n::t('This does not include updates prior to 1139, which did not return a status.'),
-                       '$mark' => L10n::t('Mark success (if update was manually applied)'),
+                       '$mark' => L10n::t("Mark success \x28if update was manually applied\x29"),
                        '$apply' => L10n::t('Attempt to execute this update step automatically'),
                        '$failed' => $failed
                ]);
@@ -1487,10 +1587,10 @@ function admin_page_users_post(App $a)
                        Please take a few moments to review the other account settings on that page.
 
                        You may also wish to add some basic information to your default profile
-                       (on the "Profiles" page) so that other people can easily find you.
+                       ' . "\x28" . 'on the "Profiles" page' . "\x29" . ' so that other people can easily find you.
 
                        We recommend setting your full name, adding a profile photo,
-                       adding some profile "keywords" (very useful in making new friends) - and
+                       adding some profile "keywords" ' . "\x28" . 'very useful in making new friends' . "\x29" . ' - and
                        perhaps what country you live in; if you do not wish to be more specific
                        than that.
 
@@ -1498,6 +1598,8 @@ function admin_page_users_post(App $a)
                        If you are new and do not know anybody here, they may help
                        you to make some new and interesting friends.
 
+                       If you ever want to delete your account, you can do so at %1$s/removeme
+
                        Thank you and welcome to %4$s.'));
 
                $preamble = sprintf($preamble, $user['username'], $a->config['sitename']);
@@ -1558,7 +1660,7 @@ function admin_page_users(App $a)
        if ($a->argc > 2) {
                $uid = $a->argv[3];
                $user = dba::selectFirst('user', ['username', 'blocked'], ['uid' => $uid]);
-               if (DBM::is_result($user)) {
+               if (!DBM::is_result($user)) {
                        notice('User not found' . EOL);
                        goaway('admin/users');
                        return ''; // NOTREACHED
@@ -1633,20 +1735,35 @@ function admin_page_users(App $a)
 
        $adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
        $_setup_users = function ($e) use ($adminlist) {
-               $accounts = [
-                       L10n::t('Normal Account'),
-                       L10n::t('Automatic Follower Account'),
-                       L10n::t('Public Forum Account'),
-                       L10n::t('Automatic Friend Account')
+               $page_types = [
+                       PAGE_NORMAL => L10n::t('Normal Account Page'),
+                       PAGE_SOAPBOX => L10n::t('Soapbox Page'),
+                       PAGE_COMMUNITY => L10n::t('Public Forum'),
+                       PAGE_FREELOVE => L10n::t('Automatic Friend Page'),
+                       PAGE_PRVGROUP => L10n::t('Private Forum')
+               ];
+               $account_types = [
+                       ACCOUNT_TYPE_PERSON => L10n::t('Personal Page'),
+                       ACCOUNT_TYPE_ORGANISATION => L10n::t('Organisation Page'),
+                       ACCOUNT_TYPE_NEWS => L10n::t('News Page'),
+                       ACCOUNT_TYPE_COMMUNITY => L10n::t('Community Forum')
                ];
-               $e['page-flags'] = $accounts[$e['page-flags']];
-               $e['register_date'] = relative_date($e['register_date']);
-               $e['login_date'] = relative_date($e['login_date']);
-               $e['lastitem_date'] = relative_date($e['lastitem_date']);
+
+
+
+               $e['page-flags-raw'] = $e['page-flags'];
+               $e['page-flags'] = $page_types[$e['page-flags']];
+
+               $e['account-type-raw'] = ($e['page_flags_raw']==0) ? $e['account-type'] : -1;
+               $e['account-type'] = ($e['page_flags_raw']==0) ? $account_types[$e['account-type']] : "";
+
+               $e['register_date'] = Temporal::getRelativeDate($e['register_date']);
+               $e['login_date'] = Temporal::getRelativeDate($e['login_date']);
+               $e['lastitem_date'] = Temporal::getRelativeDate($e['lastitem_date']);
                //$e['is_admin'] = ($e['email'] === $a->config['admin_email']);
                $e['is_admin'] = in_array($e['email'], $adminlist);
                $e['is_deletable'] = (intval($e['uid']) != local_user());
-               $e['deleted'] = ($e['account_removed'] ? relative_date($e['account_expires_on']) : False);
+               $e['deleted'] = ($e['account_removed'] ? Temporal::getRelativeDate($e['account_expires_on']) : False);
                return $e;
        };
        $users = array_map($_setup_users, $users);
@@ -1676,8 +1793,7 @@ function admin_page_users(App $a)
                array_push($users, array_pop($tmp_users));
        }
 
-       $th_users = array_map(null, [L10n::t('Name'), L10n::t('Email'), L10n::t('Register date'), L10n::t('Last login'), L10n::t('Last item'), L10n::t('Account')], $valid_orders
-       );
+       $th_users = array_map(null, [L10n::t('Name'), L10n::t('Email'), L10n::t('Register date'), L10n::t('Last login'), L10n::t('Last item'), L10n::t('Type')], $valid_orders);
 
        $t = get_markup_template('admin/users.tpl');
        $o = replace_macros($t, [
@@ -2228,11 +2344,11 @@ function admin_page_viewlogs(App $a)
        $data = '';
 
        if (!file_exists($f)) {
-               $data = L10n::t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is readable.");
+               $data = L10n::t('Error trying to open <strong>%1$s</strong> log file.\r\n<br/>Check to see if file %1$s exist and is readable.', $f);
        } else {
                $fp = fopen($f, 'r');
                if (!$fp) {
-                       $data = L10n::t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
+                       $data = L10n::t('Couldn\'t open <strong>%1$s</strong> log file.\r\n<br/>Check to see if file %1$s is readable.', $f);
                } else {
                        $fstat = fstat($fp);
                        $size = $fstat['size'];