]> git.mxchange.org Git - friendica.git/commitdiff
Merge branch 'develop' of https://github.com/friendica/friendica into develop
authorRalf Thees <ralf@herrthees.de>
Sun, 14 Oct 2018 19:48:20 +0000 (21:48 +0200)
committerRalf Thees <ralf@herrthees.de>
Sun, 14 Oct 2018 19:48:20 +0000 (21:48 +0200)
218 files changed:
bin/auth_ejabberd.php
bin/composer.phar
bin/daemon.php
bin/worker.php
boot.php
composer.json
composer.lock
config/dbstructure.json
database.sql
doc/Addons.md
doc/Install.md
include/api.php
include/conversation.php
include/enotify.php
include/items.php
include/text.php
index.php
mod/acctlink.php [deleted file]
mod/acl.php
mod/admin.php
mod/allfriends.php
mod/babel.php
mod/cal.php
mod/common.php
mod/community.php
mod/contacts.php
mod/crepair.php
mod/dfrn_confirm.php
mod/dfrn_poll.php
mod/dfrn_request.php
mod/directory.php
mod/dirfind.php
mod/display.php
mod/editpost.php
mod/events.php
mod/feedtest.php
mod/filerm.php
mod/follow.php
mod/fsuggest.php
mod/hcard.php
mod/help.php
mod/home.php
mod/hostxrd.php
mod/install.php
mod/item.php
mod/match.php
mod/message.php
mod/network.php
mod/nodeinfo.php
mod/notes.php
mod/notifications.php
mod/notify.php
mod/openid.php
mod/opensearch.php
mod/ostatus_subscribe.php
mod/parse_url.php
mod/photo.php
mod/photos.php
mod/ping.php
mod/poke.php
mod/profile.php
mod/profile_photo.php
mod/profiles.php
mod/pubsubhubbub.php
mod/redir.php
mod/register.php
mod/repair_ostatus.php
mod/settings.php
mod/subthread.php
mod/tagger.php
mod/unfollow.php
mod/videos.php
mod/viewcontacts.php
mod/viewsrc.php
mod/wallmessage.php
mod/xrd.php
src/App.php
src/App/Mode.php [new file with mode: 0644]
src/BaseModule.php
src/Content/ContactSelector.php
src/Content/Nav.php
src/Content/Text/BBCode.php
src/Content/Text/Markdown.php
src/Content/Widget.php
src/Core/ACL.php
src/Core/Addon.php
src/Core/Cache.php
src/Core/Cache/AbstractCacheDriver.php
src/Core/Cache/ArrayCache.php
src/Core/Cache/DatabaseCacheDriver.php
src/Core/Cache/ICacheDriver.php
src/Core/Cache/MemcacheCacheDriver.php
src/Core/Cache/MemcachedCacheDriver.php
src/Core/Cache/RedisCacheDriver.php
src/Core/Config.php
src/Core/Console.php
src/Core/Console/ArchiveContact.php
src/Core/Console/AutomaticInstallation.php
src/Core/Console/Cache.php [new file with mode: 0644]
src/Core/Console/Config.php
src/Core/Console/DocBloxErrorChecker.php
src/Core/Console/GlobalCommunityBlock.php
src/Core/Console/GlobalCommunitySilence.php
src/Core/Console/Maintenance.php
src/Core/Console/NewPassword.php
src/Core/Console/PostUpdate.php
src/Core/Install.php
src/Core/NotificationsManager.php
src/Core/PConfig.php
src/Core/System.php
src/Core/Theme.php
src/Core/Worker.php
src/Database/DBA.php
src/Database/DBStructure.php
src/Model/APContact.php [new file with mode: 0644]
src/Model/Contact.php
src/Model/Conversation.php
src/Model/Event.php
src/Model/GContact.php
src/Model/Item.php
src/Model/Mail.php
src/Model/Photo.php
src/Model/Profile.php
src/Model/Term.php
src/Model/User.php
src/Module/Acctlink.php [new file with mode: 0644]
src/Module/Followers.php [new file with mode: 0644]
src/Module/Following.php [new file with mode: 0644]
src/Module/Inbox.php [new file with mode: 0644]
src/Module/Login.php
src/Module/Logout.php
src/Module/Magic.php
src/Module/Objects.php [new file with mode: 0644]
src/Module/Outbox.php [new file with mode: 0644]
src/Module/Owa.php
src/Module/Proxy.php
src/Network/CurlResult.php [new file with mode: 0644]
src/Network/Probe.php
src/Object/Image.php
src/Object/Post.php
src/Protocol/ActivityPub.php [new file with mode: 0644]
src/Protocol/ActivityPub/Processor.php [new file with mode: 0644]
src/Protocol/ActivityPub/Receiver.php [new file with mode: 0644]
src/Protocol/ActivityPub/Transmitter.php [new file with mode: 0644]
src/Protocol/DFRN.php
src/Protocol/Diaspora.php
src/Protocol/Feed.php
src/Protocol/OStatus.php
src/Protocol/PortableContact.php
src/Protocol/Salmon.php
src/Render/FriendicaSmarty.php
src/Util/ExAuth.php
src/Util/HTTPSignature.php
src/Util/JsonLD.php [new file with mode: 0644]
src/Util/LDSignature.php [new file with mode: 0644]
src/Util/Network.php
src/Util/ParseUrl.php
src/Util/Proxy.php
src/Worker/APDelivery.php [new file with mode: 0644]
src/Worker/Cron.php
src/Worker/CronJobs.php
src/Worker/Delivery.php
src/Worker/DiscoverPoCo.php
src/Worker/Notifier.php
src/Worker/OnePoll.php
src/Worker/ProfileUpdate.php
src/Worker/PubSubPublish.php
src/Worker/UpdateGContact.php
tests/ApiTest.php
tests/DatabaseTest.php
tests/Util/VFSTrait.php [new file with mode: 0644]
tests/bootstrap.php
tests/datasets/curl/about.body [new file with mode: 0644]
tests/datasets/curl/about.head [new file with mode: 0644]
tests/datasets/curl/about.redirect [new file with mode: 0644]
tests/src/App/ModeTest.php [new file with mode: 0644]
tests/src/Core/Cache/ArrayCacheDriverTest.php
tests/src/Core/Cache/CacheTest.php
tests/src/Core/Cache/DatabaseCacheDriverTest.php
tests/src/Core/Cache/MemcacheCacheDriverTest.php
tests/src/Core/Cache/MemcachedCacheDriverTest.php
tests/src/Core/Cache/MemoryCacheTest.php
tests/src/Core/Cache/RedisCacheDriverTest.php
tests/src/Core/Console/AutomaticInstallationConsoleTest.php
tests/src/Core/Console/ConsoleTest.php
tests/src/Core/InstallTest.php [new file with mode: 0644]
tests/src/Network/CurlResultTest.php [new file with mode: 0644]
util/messages.po
view/js/addon-hooks.js [deleted file]
view/js/main.js
view/lang/cs/messages.po
view/lang/cs/strings.php
view/lang/de/messages.po
view/lang/de/strings.php
view/lang/pl/messages.po
view/lang/pl/strings.php
view/templates/contact_end.tpl [deleted file]
view/templates/contacts-end.tpl [deleted file]
view/templates/cropend.tpl [deleted file]
view/templates/end.tpl [deleted file]
view/templates/event_end.tpl [deleted file]
view/templates/footer.tpl [new file with mode: 0644]
view/templates/head.tpl
view/templates/jot-end.tpl [deleted file]
view/templates/message-end.tpl [deleted file]
view/templates/msg-end.tpl [deleted file]
view/templates/profed_end.tpl [deleted file]
view/templates/videos_end.tpl [deleted file]
view/templates/wallmsg-end.tpl [deleted file]
view/theme/duepuntozero/theme.php
view/theme/frio/php/default.php
view/theme/frio/templates/contact_edit.tpl
view/theme/frio/templates/footer.tpl [new file with mode: 0644]
view/theme/frio/templates/head.tpl
view/theme/frio/templates/profile_edit.tpl
view/theme/frio/theme.php
view/theme/smoothly/theme.php
view/theme/vier/theme.php

index 7ad28c96f5660c3c8da843c91c97b3b308404426..1f03b94af90017fb164221b2d6eab38a5d391aa9 100755 (executable)
@@ -54,7 +54,7 @@ require_once "include/dba.php";
 
 $a = new App(dirname(__DIR__));
 
-if ($a->mode === App::MODE_NORMAL) {
+if ($a->getMode()->isNormal()) {
        $oAuth = new ExAuth();
        $oAuth->readStdin();
-}
\ No newline at end of file
+}
index c8152aded231addb003810c90db4694aed117490..96fa2df7bdbe24e62d2435a043fd8d5e6228d4a4 100755 (executable)
Binary files a/bin/composer.phar and b/bin/composer.phar differ
index 159b20e159503f3373b9836157c9b74513f0e34f..f0f5826d928fb04c97e36e12f57020dd8cd88ec2 100755 (executable)
@@ -34,7 +34,7 @@ require_once "include/dba.php";
 
 $a = new App(dirname(__DIR__));
 
-if ($a->isInstallMode()) {
+if ($a->getMode()->isInstall()) {
        die("Friendica isn't properly installed yet.\n");
 }
 
index ceab479cea93064af9074e1664f73c43c25bd0a9..cb09a4929da9fe0c445baca4361445902687531f 100755 (executable)
@@ -45,7 +45,7 @@ if (Config::get('system', 'maintenance', false, true)) {
        return;
 }
 
-$a->set_baseurl(Config::get('system', 'url'));
+$a->setBaseURL(Config::get('system', 'url'));
 
 Addon::loadHooks();
 
index 581bbb1817ae15a4df8ec1695faf222befd18f79..eda4ed1e8d9986c43f8bc702d137b38a6dd9045c 100644 (file)
--- a/boot.php
+++ b/boot.php
@@ -41,7 +41,7 @@ define('FRIENDICA_PLATFORM',     'Friendica');
 define('FRIENDICA_CODENAME',     'The Tazmans Flax-lily');
 define('FRIENDICA_VERSION',      '2018.12-dev');
 define('DFRN_PROTOCOL_VERSION',  '2.23');
-define('DB_UPDATE_VERSION',      1283);
+define('DB_UPDATE_VERSION',      1285);
 define('NEW_UPDATE_ROUTINE_VERSION', 1170);
 
 /**
@@ -475,44 +475,6 @@ function defaults() {
        return $return;
 }
 
-/**
- * @brief Returns the baseurl.
- *
- * @see System::baseUrl()
- *
- * @return string
- * @TODO Function is deprecated and only used in some addons
- */
-function z_root()
-{
-       return System::baseUrl();
-}
-
-/**
- * @brief Return absolut URL for given $path.
- *
- * @param string $path given path
- *
- * @return string
- */
-function absurl($path)
-{
-       if (strpos($path, '/') === 0) {
-               return z_path() . $path;
-       }
-       return $path;
-}
-
-/**
- * @brief Function to check if request was an AJAX (xmlhttprequest) request.
- *
- * @return boolean
- */
-function is_ajax()
-{
-       return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
-}
-
 /**
  * @brief Function to check if request was an AJAX (xmlhttprequest) request.
  *
@@ -556,7 +518,7 @@ function check_url(App $a)
        // and www.example.com vs example.com.
        // We will only change the url to an ip address if there is no existing setting
 
-       if (empty($url) || (!link_compare($url, System::baseUrl())) && (!preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $a->get_hostname()))) {
+       if (empty($url) || (!link_compare($url, System::baseUrl())) && (!preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $a->getHostName()))) {
                Config::set('system', 'url', System::baseUrl());
        }
 
@@ -673,62 +635,6 @@ function run_update_function($x, $prefix)
        }
 }
 
-/**
- * @brief Synchronise addons:
- *
- * system.addon contains a comma-separated list of names
- * of addons which are used on this system.
- * Go through the database list of already installed addons, and if we have
- * an entry, but it isn't in the config list, call the uninstall procedure
- * and mark it uninstalled in the database (for now we'll remove it).
- * Then go through the config list and if we have a addon that isn't installed,
- * call the install procedure and add it to the database.
- *
- * @param object $a App
- */
-function check_addons(App $a)
-{
-       $r = q("SELECT * FROM `addon` WHERE `installed` = 1");
-       if (DBA::isResult($r)) {
-               $installed = $r;
-       } else {
-               $installed = [];
-       }
-
-       $addons = Config::get('system', 'addon');
-       $addons_arr = [];
-
-       if ($addons) {
-               $addons_arr = explode(',', str_replace(' ', '', $addons));
-       }
-
-       $a->addons = $addons_arr;
-
-       $installed_arr = [];
-
-       if (count($installed)) {
-               foreach ($installed as $i) {
-                       if (!in_array($i['name'], $addons_arr)) {
-                               Addon::uninstall($i['name']);
-                       } else {
-                               $installed_arr[] = $i['name'];
-                       }
-               }
-       }
-
-       if (count($addons_arr)) {
-               foreach ($addons_arr as $p) {
-                       if (!in_array($p, $installed_arr)) {
-                               Addon::install($p);
-                       }
-               }
-       }
-
-       Addon::loadHooks();
-
-       return;
-}
-
 /**
  * @brief Used to end the current process, after saving session state.
  * @deprecated
@@ -1031,27 +937,27 @@ function get_temppath()
 
        $temppath = Config::get("system", "temppath");
 
-       if (($temppath != "") && App::directory_usable($temppath)) {
+       if (($temppath != "") && App::isDirectoryUsable($temppath)) {
                // We have a temp path and it is usable
-               return App::realpath($temppath);
+               return App::getRealPath($temppath);
        }
 
        // We don't have a working preconfigured temp path, so we take the system path.
        $temppath = sys_get_temp_dir();
 
        // Check if it is usable
-       if (($temppath != "") && App::directory_usable($temppath)) {
+       if (($temppath != "") && App::isDirectoryUsable($temppath)) {
                // Always store the real path, not the path through symlinks
-               $temppath = App::realpath($temppath);
+               $temppath = App::getRealPath($temppath);
 
                // To avoid any interferences with other systems we create our own directory
-               $new_temppath = $temppath . "/" . $a->get_hostname();
+               $new_temppath = $temppath . "/" . $a->getHostName();
                if (!is_dir($new_temppath)) {
                        /// @TODO There is a mkdir()+chmod() upwards, maybe generalize this (+ configurable) into a function/method?
                        mkdir($new_temppath);
                }
 
-               if (App::directory_usable($new_temppath)) {
+               if (App::isDirectoryUsable($new_temppath)) {
                        // The new path is usable, we are happy
                        Config::set("system", "temppath", $new_temppath);
                        return $new_temppath;
@@ -1133,8 +1039,8 @@ function get_itemcachepath()
        }
 
        $itemcache = Config::get('system', 'itemcache');
-       if (($itemcache != "") && App::directory_usable($itemcache)) {
-               return App::realpath($itemcache);
+       if (($itemcache != "") && App::isDirectoryUsable($itemcache)) {
+               return App::getRealPath($itemcache);
        }
 
        $temppath = get_temppath();
@@ -1145,7 +1051,7 @@ function get_itemcachepath()
                        mkdir($itemcache);
                }
 
-               if (App::directory_usable($itemcache)) {
+               if (App::isDirectoryUsable($itemcache)) {
                        Config::set("system", "itemcache", $itemcache);
                        return $itemcache;
                }
@@ -1161,7 +1067,7 @@ function get_itemcachepath()
 function get_spoolpath()
 {
        $spoolpath = Config::get('system', 'spoolpath');
-       if (($spoolpath != "") && App::directory_usable($spoolpath)) {
+       if (($spoolpath != "") && App::isDirectoryUsable($spoolpath)) {
                // We have a spool path and it is usable
                return $spoolpath;
        }
@@ -1176,7 +1082,7 @@ function get_spoolpath()
                        mkdir($spoolpath);
                }
 
-               if (App::directory_usable($spoolpath)) {
+               if (App::isDirectoryUsable($spoolpath)) {
                        // The new path is usable, we are happy
                        Config::set("system", "spoolpath", $spoolpath);
                        return $spoolpath;
@@ -1231,46 +1137,6 @@ function validate_include(&$file)
        return $valid;
 }
 
-function current_load()
-{
-       if (!function_exists('sys_getloadavg')) {
-               return false;
-       }
-
-       $load_arr = sys_getloadavg();
-
-       if (!is_array($load_arr)) {
-               return false;
-       }
-
-       return max($load_arr[0], $load_arr[1]);
-}
-
-/**
- * @brief get c-style args
- *
- * @return int
- */
-function argc()
-{
-       return get_app()->argc;
-}
-
-/**
- * @brief Returns the value of a argv key
- *
- * @param int $x argv key
- * @return string Value of the argv key
- */
-function argv($x)
-{
-       if (array_key_exists($x, get_app()->argv)) {
-               return get_app()->argv[$x];
-       }
-
-       return '';
-}
-
 /**
  * @brief Get the data which is needed for infinite scroll
  *
index c717775506f74ca26e145e6f8332d77c03195963..5df9a5355b866d4fdc1a259024d9e9e09617b55a 100644 (file)
@@ -18,6 +18,7 @@
                "asika/simple-console": "^1.0",
                "divineomega/password_exposed": "^2.4",
                "ezyang/htmlpurifier": "~4.7.0",
+               "friendica/json-ld": "^1.0",
                "league/html-to-markdown": "~4.8.0",
                "lightopenid/lightopenid": "dev-master",
                "michelf/php-markdown": "^1.7",
@@ -42,7 +43,7 @@
        "repositories": [
                {
                        "type": "vcs",
-                       "url": "https://github.com/pear/Text_Highlighter"
+                       "url": "https://git.friendi.ca/friendica/php-json-ld"
                }
        ],
        "autoload": {
@@ -74,7 +75,8 @@
                "phpunit/dbunit": "^2.0",
                "phpdocumentor/reflection-docblock": "^3.0.2",
                "phpunit/php-token-stream": "^1.4.2",
-               "mikey179/vfsStream": "^1.6"
+               "mikey179/vfsStream": "^1.6",
+               "mockery/mockery": "^1.2"
        },
        "scripts": {
                "test": "phpunit"
index b0ff745c681f2eaf75187c29fdda973dc68959ad..9230bb4db93c59e4efc260483ba603fa2cdd2ef3 100644 (file)
@@ -1,10 +1,10 @@
 {
     "_readme": [
         "This file locks the dependencies of your project to a known state",
-        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "5f6a43237dc52758484cd21cd76e8ce6",
+    "content-hash": "9f0dbeccbae197460a0ce74a940177cd",
     "packages": [
         {
             "name": "asika/simple-console",
         },
         {
             "name": "bower-asset/Chart-js",
-            "version": "v2.7.1",
+            "version": "v2.7.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/chartjs/Chart.js.git",
-                "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff"
+                "reference": "98f104cdd03617f1300b417b3d60c23d4e3e3403"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/0fead21939b92c15093c1b7d5ee2627fb5900fff",
-                "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff",
+                "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/98f104cdd03617f1300b417b3d60c23d4e3e3403",
+                "reference": "98f104cdd03617f1300b417b3d60c23d4e3e3403",
                 "shasum": ""
             },
             "type": "bower-asset-library",
@@ -69,7 +69,7 @@
                 "MIT"
             ],
             "description": "Simple HTML5 charts using the canvas element.",
-            "time": "2017-10-28T15:01:52+00:00"
+            "time": "2018-03-01T21:45:21+00:00"
         },
         {
             "name": "bower-asset/base64",
         },
         {
             "name": "bower-asset/vue",
-            "version": "v2.5.16",
+            "version": "v2.5.17",
             "source": {
                 "type": "git",
                 "url": "https://github.com/vuejs/vue.git",
-                "reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6"
+                "reference": "636c9b4ef17f2062720b677cbbe613f146f4d4db"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/vuejs/vue/zipball/25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6",
-                "reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6",
+                "url": "https://api.github.com/repos/vuejs/vue/zipball/636c9b4ef17f2062720b677cbbe613f146f4d4db",
+                "reference": "636c9b4ef17f2062720b677cbbe613f146f4d4db",
                 "shasum": ""
             },
             "type": "bower-asset-library"
         },
+        {
+            "name": "divineomega/do-file-cache",
+            "version": "v2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/DivineOmega/DO-File-Cache.git",
+                "reference": "261c6e30a0de8cd325f826d08b2e51b2e367a1a3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/DivineOmega/DO-File-Cache/zipball/261c6e30a0de8cd325f826d08b2e51b2e367a1a3",
+                "reference": "261c6e30a0de8cd325f826d08b2e51b2e367a1a3",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "^2.1",
+                "phpunit/phpunit": "^6.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "DivineOmega\\DOFileCache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-3.0-only"
+            ],
+            "description": "DO File Cache is a PHP File-based Caching Library. Its syntax is designed to closely resemble the PHP memcache extension.",
+            "keywords": [
+                "cache",
+                "caching",
+                "caching library",
+                "file cache",
+                "library",
+                "php"
+            ],
+            "time": "2018-09-12T23:08:34+00:00"
+        },
+        {
+            "name": "divineomega/do-file-cache-psr-6",
+            "version": "v2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/DivineOmega/DO-File-Cache-PSR-6.git",
+                "reference": "18f9807d0491d093e9a12741afb40257d92f017e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/DivineOmega/DO-File-Cache-PSR-6/zipball/18f9807d0491d093e9a12741afb40257d92f017e",
+                "reference": "18f9807d0491d093e9a12741afb40257d92f017e",
+                "shasum": ""
+            },
+            "require": {
+                "divineomega/do-file-cache": "^2.0.0",
+                "psr/cache": "^1.0"
+            },
+            "require-dev": {
+                "cache/integration-tests": "^0.16.0",
+                "php-coveralls/php-coveralls": "^2.1",
+                "phpunit/phpunit": "^5.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "DivineOmega\\DOFileCachePSR6\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-3.0-only"
+            ],
+            "authors": [
+                {
+                    "name": "Jordan Hall",
+                    "email": "jordan@hall05.co.uk"
+                }
+            ],
+            "description": "PSR-6 adapter for DO File Cache",
+            "time": "2018-07-13T08:32:36+00:00"
+        },
         {
             "name": "divineomega/password_exposed",
-            "version": "v2.5.1",
+            "version": "v2.5.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/DivineOmega/password_exposed.git",
-                "reference": "c928bf722eb02398df11076add60df070cb55581"
+                "reference": "1f1b49e3ec55b0f07115d342b145091368b081c4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/c928bf722eb02398df11076add60df070cb55581",
-                "reference": "c928bf722eb02398df11076add60df070cb55581",
+                "url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/1f1b49e3ec55b0f07115d342b145091368b081c4",
+                "reference": "1f1b49e3ec55b0f07115d342b145091368b081c4",
                 "shasum": ""
             },
             "require": {
+                "divineomega/do-file-cache-psr-6": "^2.0",
                 "guzzlehttp/guzzle": "^6.3",
                 "paragonie/certainty": "^1",
-                "php": ">=5.6",
-                "rapidwebltd/rw-file-cache-psr-6": "^1.0"
+                "php": ">=5.6"
             },
             "require-dev": {
                 "fzaninotto/faker": "^1.7",
+                "php-coveralls/php-coveralls": "^2.1",
                 "phpunit/phpunit": "^5.7",
-                "satooshi/php-coveralls": "^2.0",
                 "vimeo/psalm": "^1"
             },
             "type": "library",
                 }
             ],
             "description": "This PHP package provides a `password_exposed` helper function, that uses the haveibeenpwned.com API to check if a password has been exposed in a data breach.",
-            "time": "2018-04-02T18:16:36+00:00"
+            "time": "2018-07-12T22:09:43+00:00"
         },
         {
             "name": "ezyang/htmlpurifier",
             ],
             "time": "2015-08-05T01:03:42+00:00"
         },
+        {
+            "name": "friendica/json-ld",
+            "version": "1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://git.friendi.ca/friendica/php-json-ld",
+                "reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1"
+            },
+            "require": {
+                "ext-json": "*",
+                "php": ">=5.4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "jsonld.php"
+                ]
+            },
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Digital Bazaar, Inc.",
+                    "email": "support@digitalbazaar.com",
+                    "homepage": "http://digitalbazaar.com/"
+                },
+                {
+                    "name": "Friendica Team",
+                    "homepage": "https://friendi.ca/"
+                }
+            ],
+            "description": "A JSON-LD Processor and API implementation in PHP.",
+            "homepage": "https://git.friendi.ca/friendica/php-json-ld",
+            "keywords": [
+                "JSON",
+                "JSON-LD",
+                "Linked Data",
+                "RDF",
+                "Semantic Web",
+                "jsonld"
+            ],
+            "time": "2018-10-08T20:41:00+00:00"
+        },
         {
             "name": "fxp/composer-asset-plugin",
-            "version": "v1.4.2",
+            "version": "v1.4.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/fxpio/composer-asset-plugin.git",
-                "reference": "61352d99940d2b2392a5d2db83b8c0ef5faf222a"
+                "reference": "0d07328eef6e6f3753aa835fd2faef7fed1717bf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/61352d99940d2b2392a5d2db83b8c0ef5faf222a",
-                "reference": "61352d99940d2b2392a5d2db83b8c0ef5faf222a",
+                "url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/0d07328eef6e6f3753aa835fd2faef7fed1717bf",
+                "reference": "0d07328eef6e6f3753aa835fd2faef7fed1717bf",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "require-dev": {
-                "composer/composer": "^1.4.0"
+                "composer/composer": "^1.6.0"
             },
             "type": "composer-plugin",
             "extra": {
                 "npm",
                 "package"
             ],
-            "time": "2017-10-20T06:53:56+00:00"
+            "time": "2018-07-02T11:37:17+00:00"
         },
         {
             "name": "guzzlehttp/guzzle",
-            "version": "6.3.0",
+            "version": "6.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/guzzle.git",
-                "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699"
+                "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699",
-                "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699",
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
+                "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
                 "shasum": ""
             },
             "require": {
             },
             "require-dev": {
                 "ext-curl": "*",
-                "phpunit/phpunit": "^4.0 || ^5.0",
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
                 "psr/log": "^1.0"
             },
             "suggest": {
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "6.2-dev"
+                    "dev-master": "6.3-dev"
                 }
             },
             "autoload": {
                 "rest",
                 "web service"
             ],
-            "time": "2017-06-22T18:50:49+00:00"
+            "time": "2018-04-22T15:46:56+00:00"
         },
         {
             "name": "guzzlehttp/promises",
         },
         {
             "name": "mobiledetect/mobiledetectlib",
-            "version": "2.8.30",
+            "version": "2.8.33",
             "source": {
                 "type": "git",
                 "url": "https://github.com/serbanghita/Mobile-Detect.git",
-                "reference": "5500bbbf312fe77ef0c7223858dad84fe49ee0c3"
+                "reference": "cd385290f9a0d609d2eddd165a1e44ec1bf12102"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/5500bbbf312fe77ef0c7223858dad84fe49ee0c3",
-                "reference": "5500bbbf312fe77ef0c7223858dad84fe49ee0c3",
+                "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/cd385290f9a0d609d2eddd165a1e44ec1bf12102",
+                "reference": "cd385290f9a0d609d2eddd165a1e44ec1bf12102",
                 "shasum": ""
             },
             "require": {
                 "mobile detector",
                 "php mobile detect"
             ],
-            "time": "2017-12-18T10:38:51+00:00"
+            "time": "2018-09-01T15:05:15+00:00"
         },
         {
             "name": "npm-asset/cropperjs",
         },
         {
             "name": "npm-asset/fullcalendar",
-            "version": "3.8.2",
+            "version": "3.9.0",
             "dist": {
                 "type": "tar",
-                "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.8.2.tgz",
+                "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.9.0.tgz",
                 "reference": null,
-                "shasum": "ef7dc77b89134bbe6163e51136f7a1f8bfc1d807"
+                "shasum": "b608a9989f3416f0b1d526c6bdfeeaf2ac79eda5"
             },
             "require": {
                 "npm-asset/jquery": ">=2,<4.0",
-                "npm-asset/moment": ">=2.9.0,<3.0.0"
-            },
-            "require-dev": {
-                "npm-asset/awesome-typescript-loader": ">=3.3.0,<4.0.0",
-                "npm-asset/bootstrap": ">=3.3.7,<4.0.0",
-                "npm-asset/components-jqueryui": "dev-github:components/jqueryui",
-                "npm-asset/css-loader": ">=0.28.7,<0.29.0",
-                "npm-asset/del": ">=2.2.1,<3.0.0",
-                "npm-asset/dts-generator": ">=2.1.0,<3.0.0",
-                "npm-asset/eslint": ">=4.13.1,<5.0.0",
-                "npm-asset/eslint-config-standard": ">=11.0.0-beta.0,<12.0.0",
-                "npm-asset/eslint-plugin-import": ">=2.8.0,<3.0.0",
-                "npm-asset/eslint-plugin-node": ">=5.2.1,<6.0.0",
-                "npm-asset/eslint-plugin-promise": ">=3.6.0,<4.0.0",
-                "npm-asset/eslint-plugin-standard": ">=3.0.1,<4.0.0",
-                "npm-asset/extract-text-webpack-plugin": ">=3.0.2,<4.0.0",
-                "npm-asset/glob": ">=7.1.2,<8.0.0",
-                "npm-asset/gulp": ">=3.9.1,<4.0.0",
-                "npm-asset/gulp-cssmin": ">=0.1.7,<0.2.0",
-                "npm-asset/gulp-eslint": ">=4.0.0,<5.0.0",
-                "npm-asset/gulp-filter": ">=4.0.0,<5.0.0",
-                "npm-asset/gulp-modify-file": ">=1.0.0,<2.0.0",
-                "npm-asset/gulp-rename": ">=1.2.2,<2.0.0",
-                "npm-asset/gulp-shell": ">=0.6.5,<0.7.0",
-                "npm-asset/gulp-tslint": ">=8.1.2,<9.0.0",
-                "npm-asset/gulp-uglify": ">=2.0.0,<3.0.0",
-                "npm-asset/gulp-util": ">=3.0.7,<4.0.0",
-                "npm-asset/gulp-watch": ">=4.3.11,<5.0.0",
-                "npm-asset/gulp-zip": ">=3.2.0,<4.0.0",
-                "npm-asset/jasmine-core": "2.5.2",
-                "npm-asset/jasmine-fixture": ">=2.0.0,<3.0.0",
-                "npm-asset/jasmine-jquery": ">=2.1.1,<3.0.0",
-                "npm-asset/jquery-mockjax": ">=2.2.0,<3.0.0",
-                "npm-asset/jquery-simulate": "dev-github:jquery/jquery-simulate",
-                "npm-asset/karma": ">=0.13.22,<0.14.0",
-                "npm-asset/karma-jasmine": ">=1.0.2,<2.0.0",
-                "npm-asset/karma-phantomjs-launcher": ">=1.0.0,<2.0.0",
-                "npm-asset/karma-sourcemap-loader": ">=0.3.7,<0.4.0",
-                "npm-asset/karma-verbose-reporter": "0.0.6",
-                "npm-asset/moment-timezone": ">=0.5.5,<0.6.0",
-                "npm-asset/native-promise-only": ">=0.8.1,<0.9.0",
-                "npm-asset/node-sass": ">=4.7.2,<5.0.0",
-                "npm-asset/phantomjs-prebuilt": ">=2.1.7,<3.0.0",
-                "npm-asset/sass-loader": ">=6.0.6,<7.0.0",
-                "npm-asset/tslib": ">=1.8.0,<2.0.0",
-                "npm-asset/tslint": ">=5.8.0,<6.0.0",
-                "npm-asset/tslint-config-standard": ">=7.0.0,<8.0.0",
-                "npm-asset/types--jquery": "2.0.47",
-                "npm-asset/typescript": ">=2.6.2,<3.0.0",
-                "npm-asset/webpack": ">=3.8.1,<4.0.0",
-                "npm-asset/webpack-stream": ">=4.0.0,<5.0.0",
-                "npm-asset/yargs": ">=4.8.1,<5.0.0"
+                "npm-asset/moment": ">=2.20.1,<3.0.0"
             },
             "type": "npm-asset-library",
             "extra": {
                 "full-sized",
                 "jquery-plugin"
             ],
-            "time": "2018-01-30T23:49:01+00:00"
+            "time": "2018-03-05T03:30:23+00:00"
         },
         {
             "name": "npm-asset/imagesloaded",
         },
         {
             "name": "npm-asset/jquery-datetimepicker",
-            "version": "2.5.17",
+            "version": "2.5.20",
             "dist": {
                 "type": "tar",
-                "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.17.tgz",
+                "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.20.tgz",
                 "reference": null,
-                "shasum": "8857a631f248081d4072563bde40fa8c17e407b1"
+                "shasum": "687d6204b90b03dc93f725f8df036e1d061f37ac"
             },
             "require": {
                 "npm-asset/jquery": ">=1.7.2",
                 "npm-asset/jquery-mousewheel": ">=3.1.13",
                 "npm-asset/php-date-formatter": ">=1.3.4,<2.0.0"
             },
-            "require-dev": {
-                "npm-asset/concat": "dev-github:azer/concat",
-                "npm-asset/concat-cli": ">=4.0.0,<5.0.0",
-                "npm-asset/uglifycss": ">=0.0.27,<0.0.28",
-                "npm-asset/uglifyjs": ">=2.4.10,<3.0.0"
-            },
             "type": "npm-asset-library",
             "extra": {
                 "npm-asset-bugs": {
                     "url": "git+https://github.com/xdan/datetimepicker.git"
                 },
                 "npm-asset-scripts": {
-                    "test": "echo \"Error: no test specified\" && exit 1",
+                    "test": "karma start --browsers Firefox karma.conf.js --single-run",
                     "concat": "concat-cli -f node_modules/php-date-formatter/js/php-date-formatter.min.js jquery.datetimepicker.js node_modules/jquery-mousewheel/jquery.mousewheel.js -o build/jquery.datetimepicker.full.js",
                     "minify": "uglifyjs jquery.datetimepicker.js -c -m -o build/jquery.datetimepicker.min.js && uglifycss jquery.datetimepicker.css > build/jquery.datetimepicker.min.css",
                     "minifyconcat": "uglifyjs build/jquery.datetimepicker.full.js -c -m -o build/jquery.datetimepicker.full.min.js",
                     "github": "git add --all  && git commit -m \"New version %npm_package_version% \" && git tag %npm_package_version% && git push --tags origin HEAD:master && npm publish",
                     "build": "npm run minify && npm run concat && npm run minifyconcat",
-                    "public": "npm version patch --no-git-tag-version && npm run build && npm run github"
+                    "public": "npm run test && npm version patch --no-git-tag-version && npm run build && npm run github"
                 }
             },
             "license": [
                 {
                     "name": "Chupurnov",
                     "email": "chupurnov@gmail.com",
-                    "url": "http://xdsoft.net/"
+                    "url": "https://xdsoft.net/"
                 }
             ],
             "description": "jQuery Plugin DateTimePicker it is DatePicker and TimePicker in one",
                 "time",
                 "timepicker"
             ],
-            "time": "2018-01-23T05:56:50+00:00"
+            "time": "2018-03-21T16:26:39+00:00"
         },
         {
             "name": "npm-asset/jquery-mousewheel",
         },
         {
             "name": "npm-asset/moment",
-            "version": "2.20.1",
+            "version": "2.22.2",
             "dist": {
                 "type": "tar",
-                "url": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
+                "url": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
                 "reference": null,
-                "shasum": "d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd"
-            },
-            "require-dev": {
-                "npm-asset/benchmark": "dev-default|*",
-                "npm-asset/coveralls": ">=2.11.2,<3.0.0",
-                "npm-asset/es6-promise": "dev-default|*",
-                "npm-asset/grunt": "~0.4",
-                "npm-asset/grunt-benchmark": "dev-default|*",
-                "npm-asset/grunt-cli": "dev-default|*",
-                "npm-asset/grunt-contrib-clean": "dev-default|*",
-                "npm-asset/grunt-contrib-concat": "dev-default|*",
-                "npm-asset/grunt-contrib-copy": "dev-default|*",
-                "npm-asset/grunt-contrib-jshint": "dev-default|*",
-                "npm-asset/grunt-contrib-uglify": "dev-default|*",
-                "npm-asset/grunt-contrib-watch": "dev-default|*",
-                "npm-asset/grunt-env": "dev-default|*",
-                "npm-asset/grunt-exec": "dev-default|*",
-                "npm-asset/grunt-jscs": "dev-default|*",
-                "npm-asset/grunt-karma": "dev-default|*",
-                "npm-asset/grunt-nuget": "dev-default|*",
-                "npm-asset/grunt-string-replace": "dev-default|*",
-                "npm-asset/karma": "dev-default|*",
-                "npm-asset/karma-chrome-launcher": "dev-default|*",
-                "npm-asset/karma-firefox-launcher": "dev-default|*",
-                "npm-asset/karma-qunit": "dev-default|*",
-                "npm-asset/karma-sauce-launcher": "dev-default|*",
-                "npm-asset/load-grunt-tasks": "dev-default|*",
-                "npm-asset/nyc": ">=2.1.4,<3.0.0",
-                "npm-asset/qunit": ">=0.7.5,<0.8.0",
-                "npm-asset/qunit-cli": ">=0.1.4,<0.2.0",
-                "npm-asset/rollup": "dev-default|*",
-                "npm-asset/spacejam": "dev-default|*",
-                "npm-asset/typescript": ">=1.8.10,<2.0.0",
-                "npm-asset/uglify-js": "dev-default|*"
+                "shasum": "3c257f9839fc0e93ff53149632239eb90783ff66"
             },
             "type": "npm-asset-library",
             "extra": {
                 "time",
                 "validate"
             ],
-            "time": "2017-12-19T04:44:18+00:00"
+            "time": "2018-06-01T06:58:41+00:00"
         },
         {
             "name": "npm-asset/php-date-formatter",
-            "version": "1.3.4",
+            "version": "v1.3.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/kartik-v/php-date-formatter.git",
+                "reference": "d842e1c4e6a8d6108017b726321c305bb5ae4fb5"
+            },
             "dist": {
-                "type": "tar",
-                "url": "https://registry.npmjs.org/php-date-formatter/-/php-date-formatter-1.3.4.tgz",
-                "reference": null,
-                "shasum": "09a15ae0766ba0beb1900c27c1ec319ef2e4563e"
+                "type": "zip",
+                "url": "https://api.github.com/repos/kartik-v/php-date-formatter/zipball/d842e1c4e6a8d6108017b726321c305bb5ae4fb5",
+                "reference": "d842e1c4e6a8d6108017b726321c305bb5ae4fb5",
+                "shasum": ""
             },
             "type": "npm-asset-library",
             "extra": {
                 },
                 "npm-asset-repository": {
                     "type": "git",
-                    "url": "git+https://github.com/kartik-v/php-date-formatter.git"
-                },
-                "npm-asset-scripts": []
+                    "url": "https://github.com/kartik-v/php-date-formatter.git"
+                }
             },
             "license": [
                 "BSD-3-Clause"
             ],
             "authors": [
-                {
-                    "name": "Kartik Visweswaran",
-                    "email": "kartikv2@gmail.com"
-                }
+                "Kartik Visweswaran <kartikv2@gmail.com>"
             ],
             "description": "A Javascript datetime formatting and manipulation library using PHP date-time formats.",
             "homepage": "https://github.com/kartik-v/php-date-formatter",
-            "time": "2016-02-18T15:15:55+00:00"
+            "time": "2018-07-13T06:56:46+00:00"
         },
         {
             "name": "paragonie/certainty",
-            "version": "v1.0.2",
+            "version": "v1.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/certainty.git",
-                "reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32"
+                "reference": "d0f22c0fe579cf0e4f8ee301de5bc97ab124faac"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/certainty/zipball/a2d14f5b0b85c58329dee248d77d34e7e1202a32",
-                "reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32",
+                "url": "https://api.github.com/repos/paragonie/certainty/zipball/d0f22c0fe579cf0e4f8ee301de5bc97ab124faac",
+                "reference": "d0f22c0fe579cf0e4f8ee301de5bc97ab124faac",
                 "shasum": ""
             },
             "require": {
                 "ssl",
                 "tls"
             ],
-            "time": "2018-03-12T18:34:23+00:00"
+            "time": "2018-04-09T07:21:55+00:00"
         },
         {
             "name": "paragonie/constant_time_encoding",
-            "version": "v1.0.2",
+            "version": "v1.0.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/constant_time_encoding.git",
-                "reference": "6111a38faf6fdebc14e36652d22036f379ba58d3"
+                "reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/6111a38faf6fdebc14e36652d22036f379ba58d3",
-                "reference": "6111a38faf6fdebc14e36652d22036f379ba58d3",
+                "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
+                "reference": "2132f0f293d856026d7d11bd81b9f4a23a1dc1f6",
                 "shasum": ""
             },
             "require": {
                 "php": "^5.3|^7"
             },
             "require-dev": {
-                "paragonie/random_compat": "^1|^2",
+                "paragonie/random_compat": "^1.4|^2",
                 "phpunit/phpunit": "4.*|5.*",
-                "vimeo/psalm": "^1"
+                "vimeo/psalm": "^0.3|^1"
             },
             "type": "library",
             "autoload": {
                 "hex2bin",
                 "rfc4648"
             ],
-            "time": "2018-03-10T19:46:06+00:00"
+            "time": "2018-04-30T17:57:16+00:00"
         },
         {
             "name": "paragonie/random_compat",
-            "version": "v2.0.11",
+            "version": "v2.0.17",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/random_compat.git",
-                "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8"
+                "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8",
-                "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d",
+                "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d",
                 "shasum": ""
             },
             "require": {
             "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
             "keywords": [
                 "csprng",
+                "polyfill",
                 "pseudorandom",
                 "random"
             ],
-            "time": "2017-09-27T21:40:39+00:00"
+            "time": "2018-07-04T16:31:37+00:00"
         },
         {
             "name": "paragonie/sodium_compat",
-            "version": "v1.6.0",
+            "version": "v1.7.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/paragonie/sodium_compat.git",
-                "reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432"
+                "reference": "7b73005be3c224f12c47bd75a23ce24b762e47e8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/1f6e5682eff4a5a6a394b14331a1904f1740e432",
-                "reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432",
+                "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/7b73005be3c224f12c47bd75a23ce24b762e47e8",
+                "reference": "7b73005be3c224f12c47bd75a23ce24b762e47e8",
                 "shasum": ""
             },
             "require": {
-                "paragonie/random_compat": "^1|^2",
+                "paragonie/random_compat": ">=1",
                 "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7"
             },
             "require-dev": {
                 "secret-key cryptography",
                 "side-channel resistant"
             ],
-            "time": "2018-02-15T05:50:20+00:00"
+            "time": "2018-09-22T03:59:58+00:00"
         },
         {
             "name": "pear/text_languagedetect",
             ],
             "time": "2016-08-06T14:39:51+00:00"
         },
-        {
-            "name": "rapidwebltd/rw-file-cache",
-            "version": "v1.2.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/rapidwebltd/RW-File-Cache.git",
-                "reference": "4a1d5aaefa6ffafec8e2d60787f12bcd9890977e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/rapidwebltd/RW-File-Cache/zipball/4a1d5aaefa6ffafec8e2d60787f12bcd9890977e",
-                "reference": "4a1d5aaefa6ffafec8e2d60787f12bcd9890977e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.2.1"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^5.7"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "rapidweb\\RWFileCache\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "LGPL-3.0-only"
-            ],
-            "description": "RW File Cache is a PHP File-based Caching Library. Its syntax is designed to closely resemble the PHP memcache extension.",
-            "homepage": "https://github.com/rapidwebltd/RW-File-Cache",
-            "keywords": [
-                "cache",
-                "caching",
-                "caching library",
-                "file cache",
-                "library",
-                "php"
-            ],
-            "time": "2018-01-23T17:20:58+00:00"
-        },
-        {
-            "name": "rapidwebltd/rw-file-cache-psr-6",
-            "version": "v1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/rapidwebltd/RW-File-Cache-PSR-6.git",
-                "reference": "b74ea201d4c964f0e6db0fb036d1ab28a570df66"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/rapidwebltd/RW-File-Cache-PSR-6/zipball/b74ea201d4c964f0e6db0fb036d1ab28a570df66",
-                "reference": "b74ea201d4c964f0e6db0fb036d1ab28a570df66",
-                "shasum": ""
-            },
-            "require": {
-                "psr/cache": "^1.0",
-                "rapidwebltd/rw-file-cache": "^1.2.3"
-            },
-            "require-dev": {
-                "cache/integration-tests": "^0.16.0",
-                "phpunit/phpunit": "^5.7"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "rapidweb\\RWFileCachePSR6\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "LGPL-3.0-only"
-            ],
-            "authors": [
-                {
-                    "name": "Jordan Hall",
-                    "email": "jordan.hall@rapidweb.biz"
-                }
-            ],
-            "description": "PSR-6 adapter for RW File Cache",
-            "time": "2018-01-30T19:13:45+00:00"
-        },
         {
             "name": "seld/cli-prompt",
             "version": "1.0.3",
         },
         {
             "name": "smarty/smarty",
-            "version": "v3.1.31",
+            "version": "v3.1.33",
             "source": {
                 "type": "git",
                 "url": "https://github.com/smarty-php/smarty.git",
-                "reference": "c7d42e4a327c402897dd587871434888fde1e7a9"
+                "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/smarty-php/smarty/zipball/c7d42e4a327c402897dd587871434888fde1e7a9",
-                "reference": "c7d42e4a327c402897dd587871434888fde1e7a9",
+                "url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f",
+                "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f",
                 "shasum": ""
             },
             "require": {
             "keywords": [
                 "templating"
             ],
-            "time": "2016-12-14T21:57:25+00:00"
+            "time": "2018-09-12T20:54:16+00:00"
         }
     ],
     "packages-dev": [
             ],
             "time": "2015-06-14T21:17:01+00:00"
         },
+        {
+            "name": "hamcrest/hamcrest-php",
+            "version": "v2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/hamcrest/hamcrest-php.git",
+                "reference": "776503d3a8e85d4f9a1148614f95b7a608b046ad"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/776503d3a8e85d4f9a1148614f95b7a608b046ad",
+                "reference": "776503d3a8e85d4f9a1148614f95b7a608b046ad",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3|^7.0"
+            },
+            "replace": {
+                "cordoval/hamcrest-php": "*",
+                "davedevelopment/hamcrest-php": "*",
+                "kodova/hamcrest-php": "*"
+            },
+            "require-dev": {
+                "phpunit/php-file-iterator": "1.3.3",
+                "phpunit/phpunit": "~4.0",
+                "satooshi/php-coveralls": "^1.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "hamcrest"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD"
+            ],
+            "description": "This is the PHP port of Hamcrest Matchers",
+            "keywords": [
+                "test"
+            ],
+            "time": "2016-01-20T08:20:44+00:00"
+        },
         {
             "name": "mikey179/vfsStream",
             "version": "v1.6.5",
             "homepage": "http://vfs.bovigo.org/",
             "time": "2017-08-01T08:02:14+00:00"
         },
+        {
+            "name": "mockery/mockery",
+            "version": "1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/mockery/mockery.git",
+                "reference": "100633629bf76d57430b86b7098cd6beb996a35a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/mockery/mockery/zipball/100633629bf76d57430b86b7098cd6beb996a35a",
+                "reference": "100633629bf76d57430b86b7098cd6beb996a35a",
+                "shasum": ""
+            },
+            "require": {
+                "hamcrest/hamcrest-php": "~2.0",
+                "lib-pcre": ">=7.0",
+                "php": ">=5.6.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~5.7.10|~6.5|~7.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Mockery": "library/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Pádraic Brady",
+                    "email": "padraic.brady@gmail.com",
+                    "homepage": "http://blog.astrumfutura.com"
+                },
+                {
+                    "name": "Dave Marshall",
+                    "email": "dave.marshall@atstsolutions.co.uk",
+                    "homepage": "http://davedevelopment.co.uk"
+                }
+            ],
+            "description": "Mockery is a simple yet flexible PHP mock object framework",
+            "homepage": "https://github.com/mockery/mockery",
+            "keywords": [
+                "BDD",
+                "TDD",
+                "library",
+                "mock",
+                "mock objects",
+                "mockery",
+                "stub",
+                "test",
+                "test double",
+                "testing"
+            ],
+            "time": "2018-10-02T21:52:37+00:00"
+        },
         {
             "name": "myclabs/deep-copy",
             "version": "1.7.0",
             ],
             "time": "2017-10-19T19:58:43+00:00"
         },
-        {
-            "name": "phar-io/version",
-            "version": "1.0.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phar-io/version.git",
-                "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df",
-                "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.6 || ^7.0"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Arne Blankerts",
-                    "email": "arne@blankerts.de",
-                    "role": "Developer"
-                },
-                {
-                    "name": "Sebastian Heuer",
-                    "email": "sebastian@phpeople.de",
-                    "role": "Developer"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "Developer"
-                }
-            ],
-            "description": "Library for handling version information and constraints",
-            "time": "2017-03-05T17:38:23+00:00"
-        },
         {
             "name": "phpdocumentor/reflection-common",
             "version": "1.0.1",
         },
         {
             "name": "phpspec/prophecy",
-            "version": "1.7.6",
+            "version": "1.8.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpspec/prophecy.git",
-                "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712"
+                "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712",
-                "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
+                "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
                 "shasum": ""
             },
             "require": {
             },
             "require-dev": {
                 "phpspec/phpspec": "^2.5|^3.2",
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5"
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.7.x-dev"
+                    "dev-master": "1.8.x-dev"
                 }
             },
             "autoload": {
                 "spy",
                 "stub"
             ],
-            "time": "2018-04-18T13:57:24+00:00"
+            "time": "2018-08-05T17:53:17+00:00"
         },
         {
             "name": "phpunit/dbunit",
                 }
             ],
             "description": "Provides the functionality to compare PHP values for equality",
-            "homepage": "http://www.github.com/sebastianbergmann/comparator",
+            "homepage": "https://github.com/sebastianbergmann/comparator",
             "keywords": [
                 "comparator",
                 "compare",
                 }
             ],
             "description": "Provides functionality to handle HHVM/PHP environments",
-            "homepage": "http://www.github.com/sebastianbergmann/environment",
+            "homepage": "https://github.com/sebastianbergmann/environment",
             "keywords": [
                 "Xdebug",
                 "environment",
                 }
             ],
             "description": "Provides the functionality to export PHP variables for visualization",
-            "homepage": "http://www.github.com/sebastianbergmann/exporter",
+            "homepage": "https://github.com/sebastianbergmann/exporter",
             "keywords": [
                 "export",
                 "exporter"
                 }
             ],
             "description": "Snapshotting of global state",
-            "homepage": "http://www.github.com/sebastianbergmann/global-state",
+            "homepage": "https://github.com/sebastianbergmann/global-state",
             "keywords": [
                 "global state"
             ],
                 }
             ],
             "description": "Provides functionality to recursively process PHP variables",
-            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+            "homepage": "https://github.com/sebastianbergmann/recursion-context",
             "time": "2016-11-19T07:33:16+00:00"
         },
         {
             "homepage": "https://github.com/sebastianbergmann/version",
             "time": "2016-10-03T07:35:21+00:00"
         },
+        {
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-ctype.git",
+                "reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
+                "reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-ctype": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                },
+                {
+                    "name": "Gert de Pagter",
+                    "email": "BackEndTea@gmail.com"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "time": "2018-08-06T14:22:27+00:00"
+        },
         {
             "name": "symfony/yaml",
-            "version": "v3.4.8",
+            "version": "v3.4.16",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/yaml.git",
-                "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0"
+                "reference": "61973ecda60e9f3561e929e19c07d4878b960fc1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0",
-                "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/61973ecda60e9f3561e929e19c07d4878b960fc1",
+                "reference": "61973ecda60e9f3561e929e19c07d4878b960fc1",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.5.9|>=7.0.8"
+                "php": "^5.5.9|>=7.0.8",
+                "symfony/polyfill-ctype": "~1.8"
             },
             "conflict": {
                 "symfony/console": "<3.4"
             ],
             "description": "Symfony Yaml Component",
             "homepage": "https://symfony.com",
-            "time": "2018-04-03T05:14:20+00:00"
+            "time": "2018-09-24T08:15:45+00:00"
         },
         {
             "name": "webmozart/assert",
index c467ba6bc7644a062c896289a806362b584df9ac..443f9bd75505da9895e473dd4d210fc933d6eacc 100644 (file)
                        "name": ["UNIQUE", "name"]
                }
        },
+       "apcontact": {
+               "comment": "ActivityPub compatible contacts - used in the ActivityPub implementation",
+               "fields": {
+                       "url": {"type": "varbinary(255)", "not null": "1", "primary": "1", "comment": "URL of the contact"},
+                       "uuid": {"type": "varchar(255)", "comment": ""},
+                       "type": {"type": "varchar(20)", "not null": "1", "comment": ""},
+                       "following": {"type": "varchar(255)", "comment": ""},
+                       "followers": {"type": "varchar(255)", "comment": ""},
+                       "inbox": {"type": "varchar(255)", "not null": "1", "comment": ""},
+                       "outbox": {"type": "varchar(255)", "comment": ""},
+                       "sharedinbox": {"type": "varchar(255)", "comment": ""},
+                       "nick": {"type": "varchar(255)", "not null": "1", "default": "", "comment": ""},
+                       "name": {"type": "varchar(255)", "comment": ""},
+                       "about": {"type": "text", "comment": ""},
+                       "photo": {"type": "varchar(255)", "comment": ""},
+                       "addr": {"type": "varchar(255)", "comment": ""},
+                       "alias": {"type": "varchar(255)", "comment": ""},
+                       "pubkey": {"type": "text", "comment": ""},
+                       "baseurl": {"type": "varchar(255)", "comment": "baseurl of the ap contact"},
+                       "updated": {"type": "datetime", "not null": "1", "default": "0001-01-01 00:00:00", "comment": ""}
+
+               },
+               "indexes": {
+                       "PRIMARY": ["url"],
+                       "addr": ["addr(32)"],
+                       "url": ["followers(190)"]
+               }
+       },
        "attach": {
                "comment": "file attachments",
                "fields": {
                        "hidden": {"type": "boolean", "not null": "1", "default": "0", "comment": ""},
                        "archive": {"type": "boolean", "not null": "1", "default": "0", "comment": ""},
                        "pending": {"type": "boolean", "not null": "1", "default": "1", "comment": ""},
+                       "deleted": {"type": "boolean", "not null": "1", "default": "0", "comment": "Contact has been deleted"},
                        "rating": {"type": "tinyint", "not null": "1", "default": "0", "comment": ""},
                        "reason": {"type": "text", "comment": ""},
                        "closeness": {"type": "tinyint unsigned", "not null": "1", "default": "99", "comment": ""},
                        "reply-to-uri": {"type": "varbinary(255)", "not null": "1", "default": "", "comment": "URI to which this item is a reply"},
                        "conversation-uri": {"type": "varbinary(255)", "not null": "1", "default": "", "comment": "GNU Social conversation URI"},
                        "conversation-href": {"type": "varbinary(255)", "not null": "1", "default": "", "comment": "GNU Social conversation link"},
-                       "protocol": {"type": "tinyint unsigned", "not null": "1", "default": "0", "comment": "The protocol of the item"},
+                       "protocol": {"type": "tinyint unsigned", "not null": "1", "default": "255", "comment": "The protocol of the item"},
                        "source": {"type": "mediumtext", "comment": "Original source"},
                        "received": {"type": "datetime", "not null": "1", "default": "0001-01-01 00:00:00", "comment": "Receiving date"}
                },
index 718855804214984dd43913b0a3bc571b2aff0752..341ee5a858ad793834e867b971a9f83501aca958 100644 (file)
@@ -1,6 +1,6 @@
 -- ------------------------------------------
 -- Friendica 2018.12-dev (The Tazmans Flax-lily)
--- DB_UPDATE_VERSION 1283
+-- DB_UPDATE_VERSION 1285
 -- ------------------------------------------
 
 
@@ -19,6 +19,32 @@ CREATE TABLE IF NOT EXISTS `addon` (
         UNIQUE INDEX `name` (`name`)
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='registered addons';
 
+--
+-- TABLE apcontact
+--
+CREATE TABLE IF NOT EXISTS `apcontact` (
+       `url` varbinary(255) NOT NULL COMMENT 'URL of the contact',
+       `uuid` varchar(255) COMMENT '',
+       `type` varchar(20) NOT NULL COMMENT '',
+       `following` varchar(255) COMMENT '',
+       `followers` varchar(255) COMMENT '',
+       `inbox` varchar(255) NOT NULL COMMENT '',
+       `outbox` varchar(255) COMMENT '',
+       `sharedinbox` varchar(255) COMMENT '',
+       `nick` varchar(255) NOT NULL DEFAULT '' COMMENT '',
+       `name` varchar(255) COMMENT '',
+       `about` text COMMENT '',
+       `photo` varchar(255) COMMENT '',
+       `addr` varchar(255) COMMENT '',
+       `alias` varchar(255) COMMENT '',
+       `pubkey` text COMMENT '',
+       `baseurl` varchar(255) COMMENT 'baseurl of the ap contact',
+       `updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+        PRIMARY KEY(`url`),
+        INDEX `addr` (`addr`(32)),
+        INDEX `url` (`followers`(190))
+) DEFAULT COLLATE utf8mb4_general_ci COMMENT='ActivityPub compatible contacts - used in the ActivityPub implementation';
+
 --
 -- TABLE attach
 --
@@ -163,6 +189,7 @@ CREATE TABLE IF NOT EXISTS `contact` (
        `hidden` boolean NOT NULL DEFAULT '0' COMMENT '',
        `archive` boolean NOT NULL DEFAULT '0' COMMENT '',
        `pending` boolean NOT NULL DEFAULT '1' COMMENT '',
+       `deleted` boolean NOT NULL DEFAULT '0' COMMENT 'Contact has been deleted',
        `rating` tinyint NOT NULL DEFAULT 0 COMMENT '',
        `reason` text COMMENT '',
        `closeness` tinyint unsigned NOT NULL DEFAULT 99 COMMENT '',
@@ -212,7 +239,7 @@ CREATE TABLE IF NOT EXISTS `conversation` (
        `reply-to-uri` varbinary(255) NOT NULL DEFAULT '' COMMENT 'URI to which this item is a reply',
        `conversation-uri` varbinary(255) NOT NULL DEFAULT '' COMMENT 'GNU Social conversation URI',
        `conversation-href` varbinary(255) NOT NULL DEFAULT '' COMMENT 'GNU Social conversation link',
-       `protocol` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'The protocol of the item',
+       `protocol` tinyint unsigned NOT NULL DEFAULT 255 COMMENT 'The protocol of the item',
        `source` mediumtext COMMENT 'Original source',
        `received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Receiving date',
         PRIMARY KEY(`item-uri`),
index 2465db7307f0654cf5ffa400c5fd48a2312e9ab7..011bca0737a6f96a2c4f6667c49cdd9d8f9129b9 100644 (file)
@@ -67,55 +67,67 @@ $b can be called anything you like.
 This is information specific to the hook currently being processed, and generally contains information that is being immediately processed or acted on that you can use, display, or alter.
 Remember to declare it with `&` if you wish to alter it.
 
-## JavaScript addon hooks
+## Global stylesheets
 
-### PHP part
+If your addon requires adding a stylesheet on all pages of Friendica, add the following hook:
 
-Make sure your JavaScript addon file (addon/*addon_name*/*addon_name*.js) is listed in the document response.
+```php
+function <addon>_install()
+{
+       Addon::registerHook('head', __FILE__, '<addon>_head');
+       ...
+}
 
-In your addon install function, add:
 
-```php
-Addon::registerHook('template_vars', __FILE__, '<addon_name>_template_vars');
+function <addon>_head(App $a)
+{
+       $a->registerStylesheet(__DIR__ . '/relative/path/to/addon/stylesheet.css');
+}
 ```
 
-In your addon uninstall function, add:
+`__DIR__` is the folder path of your addon.
 
-```php
-Addon::unregisterHook('template_vars', __FILE__, '<addon_name>_template_vars');
-```
+## JavaScript
+
+### Global scripts
+
+If your addon requires adding a script on all pages of Friendica, add the following hook:
 
-Then, add your addon name to the *addon_hooks* template variable array:
 
 ```php
-function <addon_name>_template_vars($a, &$arr)
+function <addon>_install()
 {
-       if (!array_key_exists('addon_hooks', $arr['vars']))
-       {
-               $arr['vars']['addon_hooks'] = array();
-       }
-       $arr['vars']['addon_hooks'][] = "<addon_name>";
+       Addon::registerHook('footer', __FILE__, '<addon>_footer');
+       ...
+}
+
+function <addon>_footer(App $a)
+{
+       $a->registerFooterScript(__DIR__ . '/relative/path/to/addon/script.js');
 }
 ```
 
-### JavaScript part
+`__DIR__` is the folder path of your addon.
+
+### JavaScript hooks
 
-Register your addon hooks in file `addon/*addon_name*/*addon_name*.js`.
+The main Friendica script provides hooks via events dispatched on the `document` property.
+In your Javascript file included as described above, add your event listener like this:
 
 ```js
-Addon_registerHook(type, hookfnstr);
+document.addEventListener(name, callback);
 ```
 
-*type* is the name of the hook and corresponds to a known Friendica JavaScript hook.
-*hookfnstr* is the name of your JavaScript function to execute.
+- *name* is the name of the hook and corresponds to a known Friendica JavaScript hook.
+- *callback* is a JavaScript anonymous function to execute.
 
-No arguments are provided to your JavaScript callback function. Example:
+More info about Javascript event listeners: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
 
-```javascript
-function myhook_function() {
+#### Current JavaScript hooks
 
-}
-```
+##### postprocess_liveupdate
+Called at the end of the live update process (XmlHttpRequest) and on a post preview.
+No additional data is provided.
 
 ## Modules
 
@@ -260,6 +272,11 @@ Called after conversion of bbcode to HTML.
 Called after tag conversion of HTML to bbcode (e.g. remote message posting)
 `$b` is a string converted text
 
+### head
+Called when building the `<head>` sections.
+Stylesheets should be registered using this hook.
+`$b` is an HTML string of the `<head>` tag.
+
 ### page_header
 Called after building the page navigation section.
 `$b` is a string HTML of nav region.
@@ -294,6 +311,11 @@ No hook data.
 Called after HTML content functions have completed.
 `$b` is (string) HTML of content div.
 
+### footer
+Called after HTML content functions have completed.
+Deferred Javascript files should be registered using this hook.
+`$b` is (string) HTML of footer div/element.
+
 ### avatar_lookup
 Called when looking up the avatar. `$b` is an array:
 
@@ -389,14 +411,9 @@ Hook data:
     visitor => array with the contact record of the visitor
     url => the query string
 
-## Current JavaScript hooks
-
-### postprocess_liveupdate
-Called at the end of the live update process (XmlHttpRequest)
-
 ## Complete list of hook callbacks
 
-Here is a complete list of all hook callbacks with file locations (as of 01-Apr-2018). Please see the source for details of any hooks not documented above.
+Here is a complete list of all hook callbacks with file locations (as of 24-Sep-2018). Please see the source for details of any hooks not documented above.
 
 ### index.php
 
@@ -571,6 +588,8 @@ Here is a complete list of all hook callbacks with file locations (as of 01-Apr-
 ### src/App.php
 
     Addon::callHooks('load_config');
+    Addon::callHooks('head');
+    Addon::callHooks('footer');
 
 ### src/Model/Item.php
 
@@ -704,4 +723,4 @@ Here is a complete list of all hook callbacks with file locations (as of 01-Apr-
 
 ### view/js/main.js
 
-    callAddonHooks("postprocess_liveupdate");
+    document.dispatchEvent(new Event('postprocess_liveupdate'));
index 3854c32bcef66635797019bd4ebbc9ae465a16b6..427299c3ea6dbd07197263d6850dd3e7cb4f4267 100644 (file)
@@ -164,6 +164,7 @@ if you don't use the option `--savedb` during installation, the DB credentials w
 This variables wont be used at normal Friendica runtime.
 Instead, they get saved into `config/local.ini.php`. 
 
+-      `FRIENDICA_URL_PATH` The URL path of Friendica (f.e. '/friendica')
 -      `FRIENDICA_PHP_PATH` The path of the PHP binary
 -      `FRIENDICA_ADMIN_MAIL` The admin email address of Friendica (this email will be used for admin access)
 -      `FRIENDICA_TZ` The timezone of Friendica
@@ -182,7 +183,8 @@ All options will be saved in the `config/local.ini.php` and are overruling the a
 -      `-U|--dbuser <username>` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`)
 -      `-P|--dbpass <password>` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`)
 -      `-d|--dbdata <database>` The name of the mysql/mariadb database (env `MYSQL_DATABASE`)
--      `-b|--phppath <path>` The path of the PHP binary (env `FRIENDICA_PHP_PATH`)
+-      `-u|--urlpath <url_path>` The URL path of Friendica - f.e. '/friendica' (env `FRIENDICA_URL_PATH`)
+-      `-b|--phppath <php_path>` The path of the PHP binary (env `FRIENDICA_PHP_PATH`)
 -      `-A|--admin <mail>` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`)
 -      `-T|--tz <timezone>` The timezone of Friendica (env `FRIENDICA_TZ`)
 -      `-L|--land <language>` The language of Friendica (env `FRIENDICA_LANG`)
index 5510eddb4f1bc98d44e238d93145b939945058d5..01cb93a3b8226f5f7940733a6502ac74e6470b8a 100644 (file)
@@ -819,7 +819,7 @@ function api_item_get_user(App $a, $item)
        $status_user["protected"] = defaults($item, 'private', 0);
 
        if (defaults($item, 'thr-parent', '') == defaults($item, 'uri', '')) {
-               $owner_user = api_get_user($a, defaults($item, 'author-id', null));
+               $owner_user = api_get_user($a, defaults($item, 'owner-id', null));
        } else {
                $owner_user = $status_user;
        }
@@ -2351,7 +2351,7 @@ function api_format_messages($item, $recipient, $sender)
        // standard meta information
        $ret = [
                'id'                    => $item['id'],
-               'sender_id'             => $sender['id'] ,
+               'sender_id'             => $sender['id'],
                'text'                  => "",
                'recipient_id'          => $recipient['id'],
                'created_at'            => api_date(defaults($item, 'created', DateTimeFormat::utcNow())),
@@ -2732,7 +2732,7 @@ function api_contactlink_to_array($txt)
  *                     likes => int count,
  *                     dislikes => int count
  */
-function api_format_items_activities(&$item, $type = "json")
+function api_format_items_activities($item, $type = "json")
 {
        $a = get_app();
 
@@ -2747,13 +2747,13 @@ function api_format_items_activities(&$item, $type = "json")
        $condition = ['uid' => $item['uid'], 'thr-parent' => $item['uri']];
        $ret = Item::selectForUser($item['uid'], ['author-id', 'verb'], $condition);
 
-       while ($item = Item::fetch($ret)) {
+       while ($parent_item = Item::fetch($ret)) {
                // not used as result should be structured like other user data
                //builtin_activity_puller($i, $activities);
 
                // get user data and add it to the array of the activity
-               $user = api_get_user($a, $item['author-id']);
-               switch ($item['verb']) {
+               $user = api_get_user($a, $parent_item['author-id']);
+               switch ($parent_item['verb']) {
                        case ACTIVITY_LIKE:
                                $activities['like'][] = $user;
                                break;
@@ -2893,7 +2893,7 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
                        'in_reply_to_screen_name' => $in_reply_to['screen_name'],
                        $geo => null,
                        'favorited' => $item['starred'] ? true : false,
-                       'user' =>  $status_user ,
+                       'user' =>  $status_user,
                        'friendica_owner' => $owner_user,
                        'friendica_private' => $item['private'] == 1,
                        //'entities' => NULL,
@@ -3344,7 +3344,7 @@ function api_statusnet_config($type)
        $a = get_app();
 
        $name      = Config::get('config', 'sitename');
-       $server    = $a->get_hostname();
+       $server    = $a->getHostName();
        $logo      = System::baseUrl() . '/images/friendica-64.png';
        $email     = Config::get('config', 'admin_email');
        $closed    = intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 'true' : 'false';
@@ -3401,7 +3401,7 @@ api_register_func('api/statusnet/version', 'api_statusnet_version', false);
  */
 function api_ff_ids($type)
 {
-       if (! api_user()) {
+       if (!api_user()) {
                throw new ForbiddenException();
        }
 
@@ -3629,6 +3629,84 @@ function api_direct_messages_destroy($type)
 /// @TODO move to top of file or somewhere better
 api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy', true, API_METHOD_DELETE);
 
+/**
+ * Unfollow Contact
+ *
+ * @brief unfollow contact 
+ *
+ * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+ * @return string|array
+ * @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy.html
+ */
+function api_friendships_destroy($type)
+{
+       $uid = api_user();
+
+       if ($uid === false) {
+               throw new ForbiddenException();
+       }
+
+       $contact_id = defaults($_REQUEST, 'user_id');
+
+       if (empty($contact_id)) {
+               logger("No user_id specified", LOGGER_DEBUG);
+               throw new BadRequestException("no user_id specified");
+       }
+
+       // Get Contact by given id
+       $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => 0, 'self' => false]);
+
+       if(!DBA::isResult($contact)) {
+               logger("No contact found for ID" . $contact_id, LOGGER_DEBUG);
+               throw new NotFoundException("no contact found to given ID");
+       }
+
+       $url = $contact["url"];
+
+       $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?)",
+                       $uid, Contact::SHARING, Contact::FRIEND, normalise_link($url),
+                       normalise_link($url), $url];
+       $contact = DBA::selectFirst('contact', [], $condition);
+
+       if (!DBA::isResult($contact)) {
+               logger("Not following Contact", LOGGER_DEBUG);
+               throw new NotFoundException("Not following Contact");
+       }
+
+       if (!in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
+               logger("Not supported", LOGGER_DEBUG);
+               throw new ExpectationFailedException("Not supported");
+       }
+
+       $dissolve = ($contact['rel'] == Contact::SHARING);
+
+       $owner = User::getOwnerDataById($uid);
+       if ($owner) {
+               Contact::terminateFriendship($owner, $contact, $dissolve);
+       }
+       else {
+               logger("No owner found", LOGGER_DEBUG);
+               throw new NotFoundException("Error Processing Request");
+       }
+
+       // Sharing-only contacts get deleted as there no relationship any more
+       if ($dissolve) {
+               Contact::remove($contact['id']);
+       } else {
+               DBA::update('contact', ['rel' => Contact::FOLLOWER], ['id' => $contact['id']]);
+       }
+
+       // "uid" and "self" are only needed for some internal stuff, so remove it from here
+       unset($contact["uid"]);
+       unset($contact["self"]);
+
+       // Set screen_name since Twidere requests it
+       $contact["screen_name"] = $contact["nick"];
+
+       return api_format_data("friendships-destroy", $type, ['user' => $contact]);
+}
+api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, API_METHOD_POST);
+
 /**
  *
  * @param string $type Return type (atom, rss, xml, json)
@@ -4427,7 +4505,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
        // create Photo instance with the data of the image
        $imagedata = @file_get_contents($src);
        $Image = new Image($imagedata, $filetype);
-       if (! $Image->isValid()) {
+       if (!$Image->isValid()) {
                throw new InternalServerErrorException("unable to process image data");
        }
 
@@ -4437,7 +4515,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
 
        // check max length of images on server
        $max_length = Config::get('system', 'max_image_length');
-       if (! $max_length) {
+       if (!$max_length) {
                $max_length = MAX_IMAGE_LENGTH;
        }
        if ($max_length > 0) {
@@ -4455,13 +4533,13 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
                logger("photo upload: starting new photo upload", LOGGER_DEBUG);
 
                $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 0, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
-               if (! $r) {
+               if (!$r) {
                        logger("photo upload: image upload with scale 0 (original size) failed");
                }
                if ($width > 640 || $height > 640) {
                        $Image->scaleDown(640);
                        $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 1, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
-                       if (! $r) {
+                       if (!$r) {
                                logger("photo upload: image upload with scale 1 (640x640) failed");
                        }
                }
@@ -4469,7 +4547,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
                if ($width > 320 || $height > 320) {
                        $Image->scaleDown(320);
                        $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 2, 0, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
-                       if (! $r) {
+                       if (!$r) {
                                logger("photo upload: image upload with scale 2 (320x320) failed");
                        }
                }
@@ -4481,7 +4559,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
                if ($width > 175 || $height > 175) {
                        $Image->scaleDown(175);
                        $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 4, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
-                       if (! $r) {
+                       if (!$r) {
                                logger("photo upload: profile image upload with scale 4 (175x175) failed");
                        }
                }
@@ -4489,7 +4567,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
                if ($width > 80 || $height > 80) {
                        $Image->scaleDown(80);
                        $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 5, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
-                       if (! $r) {
+                       if (!$r) {
                                logger("photo upload: profile image upload with scale 5 (80x80) failed");
                        }
                }
@@ -4497,7 +4575,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
                if ($width > 48 || $height > 48) {
                        $Image->scaleDown(48);
                        $r = Photo::store($Image, local_user(), $visitor, $hash, $filename, $album, 6, $profile, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $desc);
-                       if (! $r) {
+                       if (!$r) {
                                logger("photo upload: profile image upload with scale 6 (48x48) failed");
                        }
                }
@@ -4534,7 +4612,7 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
        $owner_record = DBA::selectFirst('contact', [], ['uid' => api_user(), 'self' => true]);
 
        $arr = [];
-       $arr['guid']          = System::createGUID(32);
+       $arr['guid']          = System::createUUID();
        $arr['uid']           = intval(api_user());
        $arr['uri']           = $uri;
        $arr['parent-uri']    = $uri;
@@ -4749,77 +4827,86 @@ function api_share_as_retweet(&$item)
 {
        $body = trim($item["body"]);
 
-       if (Diaspora::isReshare($body, false)===false) {
-               return false;
+       if (Diaspora::isReshare($body, false) === false) {
+               if ($item['author-id'] == $item['owner-id']) {
+                       return false;
+               } else {
+                       // Reshares from OStatus, ActivityPub and Twitter
+                       $reshared_item = $item;
+                       $reshared_item['owner-id'] = $reshared_item['author-id'];
+                       $reshared_item['owner-link'] = $reshared_item['author-link'];
+                       $reshared_item['owner-name'] = $reshared_item['author-name'];
+                       $reshared_item['owner-avatar'] = $reshared_item['author-avatar'];
+                       return $reshared_item;
+               }
        }
 
        /// @TODO "$1" should maybe mean '$1' ?
        $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body);
        /*
-               * Skip if there is no shared message in there
-               * we already checked this in diaspora::isReshare()
-               * but better one more than one less...
-               */
-       if ($body == $attributes) {
+        * Skip if there is no shared message in there
+        * we already checked this in diaspora::isReshare()
+        * but better one more than one less...
+        */
+       if (($body == $attributes) || empty($attributes)) {
                return false;
        }
 
-
        // build the fake reshared item
        $reshared_item = $item;
 
        $author = "";
        preg_match("/author='(.*?)'/ism", $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $author = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
        }
 
        preg_match('/author="(.*?)"/ism', $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $author = $matches[1];
        }
 
        $profile = "";
        preg_match("/profile='(.*?)'/ism", $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $profile = $matches[1];
        }
 
        preg_match('/profile="(.*?)"/ism', $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $profile = $matches[1];
        }
 
        $avatar = "";
        preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $avatar = $matches[1];
        }
 
        preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $avatar = $matches[1];
        }
 
        $link = "";
        preg_match("/link='(.*?)'/ism", $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $link = $matches[1];
        }
 
        preg_match('/link="(.*?)"/ism', $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $link = $matches[1];
        }
 
        $posted = "";
        preg_match("/posted='(.*?)'/ism", $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $posted = $matches[1];
        }
 
        preg_match('/posted="(.*?)"/ism', $attributes, $matches);
-       if ($matches[1] != "") {
+       if (!empty($matches[1])) {
                $posted = $matches[1];
        }
 
index e41b697b547824d869ad487107b05503bb80e956..43854bb40f7b7e8d1486edb47d41e3a092fa7063 100644 (file)
@@ -556,7 +556,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
                if (in_array($mode, ['community', 'contacts'])) {
                        $writable = true;
                } else {
-                       $writable = ($items[0]['uid'] == 0) && in_array($items[0]['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
+                       $writable = ($items[0]['uid'] == 0) && in_array($items[0]['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
                }
 
                if (!local_user()) {
@@ -657,7 +657,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
                                        'id' => ($preview ? 'P0' : $item['id']),
                                        'guid' => ($preview ? 'Q0' : $item['guid']),
                                        'network' => $item['network'],
-                                       'network_name' => ContactSelector::networkToName($item['network'], $profile_link),
+                                       'network_name' => ContactSelector::networkToName($item['network'], $item['author-link']),
                                        'linktitle' => L10n::t('View %s\'s profile @ %s', $profile_name, $item['author-link']),
                                        'profile_url' => $profile_link,
                                        'item_photo_menu' => item_photo_menu($item),
@@ -807,7 +807,7 @@ function conversation_add_children(array $parents, $block_authors, $order, $uid)
 
        foreach ($items as $index => $item) {
                if ($item['uid'] == 0) {
-                       $items[$index]['writable'] = in_array($item['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
+                       $items[$index]['writable'] = in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
                }
        }
 
@@ -877,7 +877,7 @@ function item_photo_menu($item) {
                }
 
                if ((($cid == 0) || ($rel == Contact::FOLLOWER)) &&
-                       in_array($item['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) {
+                       in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) {
                        $menu[L10n::t('Connect/Follow')] = 'follow?url=' . urlencode($item['author-link']);
                }
        } else {
@@ -1091,21 +1091,6 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
                '$delitems'  => L10n::t("Delete item\x28s\x29?")
        ]);
 
-       $tpl = get_markup_template('jot-end.tpl');
-       $a->page['end'] .= replace_macros($tpl, [
-               '$newpost'   => 'true',
-               '$baseurl'   => System::baseUrl(true),
-               '$geotag'    => $geotag,
-               '$nickname'  => $x['nickname'],
-               '$ispublic'  => L10n::t('Visible to <strong>everybody</strong>'),
-               '$linkurl'   => L10n::t('Please enter a link URL:'),
-               '$vidurl'    => L10n::t("Please enter a video link/URL:"),
-               '$audurl'    => L10n::t("Please enter an audio link/URL:"),
-               '$term'      => L10n::t('Tag term:'),
-               '$fileas'    => L10n::t('Save to Folder:'),
-               '$whereareu' => L10n::t('Where are you right now?')
-       ]);
-
        $jotplugins = '';
        Addon::callHooks('jot_tool', $jotplugins);
 
index 70abce584547ea3986a25b2d6f89029dc0c99408..b184a6935e08add322c137ccfa63cba6c2c469ff 100644 (file)
@@ -61,7 +61,7 @@ function notification($params)
        }
 
        $sender_name = $sitename;
-       $hostname = $a->get_hostname();
+       $hostname = $a->getHostName();
        if (strpos($hostname, ':')) {
                $hostname = substr($hostname, 0, strpos($hostname, ':'));
        }
index 9fd557a77885838ee1cd7b415eacac99b67a75d0..27a7db767b4d16c6ee8a8a8a57abc02507524a27 100644 (file)
@@ -316,9 +316,9 @@ function subscribe_to_hub($url, array $importer, array $contact, $hubmode = 'sub
                DBA::update('contact', ['hub-verify' => $verify_token], ['id' => $contact['id']]);
        }
 
-       Network::post($url, $params);
+       $postResult = Network::post($url, $params);
 
-       logger('subscribe_to_hub: returns: ' . $a->get_curl_code(), LOGGER_DEBUG);
+       logger('subscribe_to_hub: returns: ' . $postResult->getReturnCode(), LOGGER_DEBUG);
 
        return;
 
@@ -349,12 +349,12 @@ function drop_item($id)
 
        // locate item to be deleted
 
-       $fields = ['id', 'uid', 'contact-id', 'deleted'];
+       $fields = ['id', 'uid', 'guid', 'contact-id', 'deleted'];
        $item = Item::selectFirstForUser(local_user(), $fields, ['id' => $id]);
 
        if (!DBA::isResult($item)) {
                notice(L10n::t('Item not found.') . EOL);
-               goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
+               goaway('/network');
        }
 
        if ($item['deleted']) {
@@ -401,17 +401,17 @@ function drop_item($id)
                }
                // Now check how the user responded to the confirmation query
                if (!empty($_REQUEST['canceled'])) {
-                       goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
+                       goaway('/display/' . $item['guid']);
                }
 
                // delete the item
                Item::deleteForUser(['id' => $item['id']], local_user());
 
-               goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
+               goaway('/network');
                //NOTREACHED
        } else {
                notice(L10n::t('Permission denied.') . EOL);
-               goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
+               goaway('/display/' . $item['guid']);
                //NOTREACHED
        }
 }
index 97baee7f60b551a76089ba31efbd66e573bb3412..5a18529d93ab68837560d1cb927fcbc131ff2bb7 100644 (file)
@@ -42,7 +42,7 @@ function replace_macros($s, $r) {
        // pass $baseurl to all templates
        $r['$baseurl'] = System::baseUrl();
 
-       $t = $a->template_engine();
+       $t = $a->getTemplateEngine();
        try {
                $output = $t->replaceMacros($s, $r);
        } catch (Exception $e) {
@@ -50,7 +50,7 @@ function replace_macros($s, $r) {
                killme();
        }
 
-       $a->save_timestamp($stamp1, "rendering");
+       $a->saveTimestamp($stamp1, "rendering");
 
        return $output;
 }
@@ -473,7 +473,7 @@ function get_markup_template($s, $root = '') {
        $stamp1 = microtime(true);
 
        $a = get_app();
-       $t = $a->template_engine();
+       $t = $a->getTemplateEngine();
        try {
                $template = $t->getTemplateFile($s, $root);
        } catch (Exception $e) {
@@ -481,7 +481,7 @@ function get_markup_template($s, $root = '') {
                killme();
        }
 
-       $a->save_timestamp($stamp1, "file");
+       $a->saveTimestamp($stamp1, "file");
 
        return $template;
 }
@@ -574,7 +574,7 @@ function logger($msg, $level = LOGGER_INFO) {
 
        $stamp1 = microtime(true);
        @file_put_contents($logfile, $logline, FILE_APPEND);
-       $a->save_timestamp($stamp1, "file");
+       $a->saveTimestamp($stamp1, "file");
 }
 
 /**
@@ -634,7 +634,7 @@ function dlogger($msg, $level = LOGGER_INFO) {
 
        $stamp1 = microtime(true);
        @file_put_contents($logfile, $logline, FILE_APPEND);
-       $a->save_timestamp($stamp1, "file");
+       $a->saveTimestamp($stamp1, "file");
 }
 
 
@@ -1191,9 +1191,6 @@ function prepare_body(array &$item, $attach = false, $is_preview = false)
                                $a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [
                                        '$baseurl' => System::baseUrl(),
                                ]);
-                               $a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
-                                       '$baseurl' => System::baseUrl(),
-                               ]);
                        }
 
                        $url_parts = explode('/', $the_url);
@@ -1417,7 +1414,7 @@ function get_plink($item) {
                        ];
 
                if (x($item, 'plink')) {
-                       $ret["href"] = $a->remove_baseurl($item['plink']);
+                       $ret["href"] = $a->removeBaseURL($item['plink']);
                        $ret["title"] = L10n::t('link to source');
                }
 
index 8b0bd472513fd9c5a1ca9bbd457a60ce963682d3..6ab405c632a3f092db5914db9f146f6f457b7ab1 100644 (file)
--- a/index.php
+++ b/index.php
@@ -23,11 +23,9 @@ use Friendica\Module\Login;
 
 require_once 'boot.php';
 
-$a = new App(__DIR__);
-
 // We assume that the index.php is called by a frontend process
 // The value is set to "true" by default in boot.php
-$a->backend = false;
+$a = new App(__DIR__, false);
 
 /**
  * Try to open the database;
@@ -36,7 +34,7 @@ $a->backend = false;
 require_once "include/dba.php";
 
 // Missing DB connection: ERROR
-if ($a->mode & App::MODE_LOCALCONFIGPRESENT && !($a->mode & App::MODE_DBAVAILABLE)) {
+if ($a->getMode()->has(App\Mode::LOCALCONFIGPRESENT) && !$a->getMode()->has(App\Mode::DBAVAILABLE)) {
        System::httpExit(500, ['title' => 'Error 500 - Internal Server Error', 'description' => 'Apologies but the website is unavailable at the moment.']);
 }
 
@@ -48,8 +46,12 @@ if ($a->isMaxProcessesReached() || $a->isMaxLoadReached()) {
        System::httpExit(503, ['title' => 'Error 503 - Service Temporarily Unavailable', 'description' => 'System is currently overloaded. Please try again later.']);
 }
 
-if (!$a->isInstallMode()) {
-       if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http")
+if (strstr($a->query_string, '.well-known/host-meta') && ($a->query_string != '.well-known/host-meta')) {
+       System::httpExit(404);
+}
+
+if (!$a->getMode()->isInstall()) {
+       if (Config::get('system', 'force_ssl') && ($a->getScheme() == "http")
                && (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL)
                && (substr(System::baseUrl(), 0, 8) == "https://")
                && ($_SERVER['REQUEST_METHOD'] == 'GET')) {
@@ -78,10 +80,10 @@ L10n::loadTranslationTable($lang);
  */
 
 // Exclude the backend processes from the session management
-if (!$a->is_backend()) {
+if (!$a->isBackend()) {
        $stamp1 = microtime(true);
        session_start();
-       $a->save_timestamp($stamp1, "parser");
+       $a->saveTimestamp($stamp1, "parser");
 } else {
        $_SESSION = [];
        Worker::executeIfIdle();
@@ -91,7 +93,7 @@ if (!$a->is_backend()) {
  * Language was set earlier, but we can over-ride it in the session.
  * We have to do it here because the session was just now opened.
  */
-if (x($_SESSION, 'authenticated') && !x($_SESSION, 'language')) {
+if (!empty($_SESSION['authenticated']) && empty($_SESSION['language'])) {
        $_SESSION['language'] = $lang;
        // we haven't loaded user data yet, but we need user language
        if (!empty($_SESSION['uid'])) {
@@ -102,12 +104,12 @@ if (x($_SESSION, 'authenticated') && !x($_SESSION, 'language')) {
        }
 }
 
-if (x($_SESSION, 'language') && ($_SESSION['language'] !== $lang)) {
+if (!empty($_SESSION['language']) && $_SESSION['language'] !== $lang) {
        $lang = $_SESSION['language'];
        L10n::loadTranslationTable($lang);
 }
 
-if (!empty($_GET['zrl']) && $a->mode == App::MODE_NORMAL) {
+if (!empty($_GET['zrl']) && $a->getMode()->isNormal()) {
        $a->query_string = Profile::stripZrls($a->query_string);
        if (!local_user()) {
                // Only continue when the given profile link seems valid
@@ -125,12 +127,12 @@ if (!empty($_GET['zrl']) && $a->mode == App::MODE_NORMAL) {
                        logger("Invalid ZRL parameter " . $_GET['zrl'], LOGGER_DEBUG);
                        header('HTTP/1.1 403 Forbidden');
                        echo "<h1>403 Forbidden</h1>";
-                       killme();
+                       exit();
                }
        }
 }
 
-if ((x($_GET,'owt')) && $a->mode == App::MODE_NORMAL) {
+if (!empty($_GET['owt']) && $a->getMode()->isNormal()) {
        $token = $_GET['owt'];
        $a->query_string = Profile::stripQueryParam($a->query_string, 'owt');
        Profile::openWebAuthInit($token);
@@ -149,14 +151,10 @@ if ((x($_GET,'owt')) && $a->mode == App::MODE_NORMAL) {
 
 Login::sessionAuth();
 
-if (! x($_SESSION, 'authenticated')) {
+if (empty($_SESSION['authenticated'])) {
        header('X-Account-Management-Status: none');
 }
 
-/* set up page['htmlhead'] and page['end'] for the modules to use */
-$a->page['htmlhead'] = '';
-$a->page['end'] = '';
-
 $_SESSION['sysmsg']       = defaults($_SESSION, 'sysmsg'      , []);
 $_SESSION['sysmsg_info']  = defaults($_SESSION, 'sysmsg_info' , []);
 $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []);
@@ -169,14 +167,14 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []);
 
 // in install mode, any url loads install module
 // but we need "view" module for stylesheet
-if ($a->isInstallMode() && $a->module!="view") {
+if ($a->getMode()->isInstall() && $a->module != 'view') {
        $a->module = 'install';
-} elseif (!($a->mode & App::MODE_MAINTENANCEDISABLED) && $a->module != "view") {
+} elseif (!$a->getMode()->has(App\Mode::MAINTENANCEDISABLED) && $a->module != 'view') {
        $a->module = 'maintenance';
 } else {
        check_url($a);
        check_db(false);
-       check_addons($a);
+       Addon::check();
 }
 
 Nav::setSelected('nothing');
@@ -295,11 +293,11 @@ if (strlen($a->module)) {
 
        if (! $a->module_loaded) {
                // Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
-               if ((x($_SERVER, 'QUERY_STRING')) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
+               if (!empty($_SERVER['QUERY_STRING']) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
                        killme();
                }
 
-               if ((x($_SERVER, 'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
+               if (!empty($_SERVER['QUERY_STRING']) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
                        logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
                        goaway(System::baseUrl() . $_SERVER['REQUEST_URI']);
                }
@@ -307,11 +305,9 @@ if (strlen($a->module)) {
                logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG);
                header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . L10n::t('Not Found'));
                $tpl = get_markup_template("404.tpl");
-               $a->page['content'] = replace_macros(
-                       $tpl,
-                       [
-                       '$message' =>  L10n::t('Page not found.')]
-               );
+               $a->page['content'] = replace_macros($tpl, [
+                       '$message' =>  L10n::t('Page not found.')
+               ]);
        }
 }
 
@@ -326,11 +322,7 @@ if (file_exists($theme_info_file)) {
 
 /* initialise content region */
 
-if (! x($a->page, 'content')) {
-       $a->page['content'] = '';
-}
-
-if ($a->mode == App::MODE_NORMAL) {
+if ($a->getMode()->isNormal()) {
        Addon::callHooks('page_content_top', $a->page['content']);
 }
 
@@ -342,15 +334,21 @@ if ($a->module_loaded) {
        $a->page['page_title'] = $a->module;
        $placeholder = '';
 
+       Addon::callHooks($a->module . '_mod_init', $placeholder);
+
        if ($a->module_class) {
-               Addon::callHooks($a->module . '_mod_init', $placeholder);
                call_user_func([$a->module_class, 'init']);
        } else if (function_exists($a->module . '_init')) {
-               Addon::callHooks($a->module . '_mod_init', $placeholder);
                $func = $a->module . '_init';
                $func($a);
        }
 
+       // "rawContent" is especially meant for technical endpoints.
+       // This endpoint doesn't need any theme initialization or other comparable stuff.
+       if (!$a->error && $a->module_class) {
+               call_user_func([$a->module_class, 'rawContent']);
+       }
+
        if (function_exists(str_replace('-', '_', $a->getCurrentTheme()) . '_init')) {
                $func = str_replace('-', '_', $a->getCurrentTheme()) . '_init';
                $func($a);
@@ -405,24 +403,13 @@ if ($a->module_loaded) {
  * theme choices made by the modules can take effect.
  */
 
-$a->init_pagehead();
+$a->initHead();
 
 /*
  * Build the page ending -- this is stuff that goes right before
  * the closing </body> tag
  */
-$a->init_page_end();
-
-// If you're just visiting, let javascript take you home
-if (x($_SESSION, 'visitor_home')) {
-       $homebase = $_SESSION['visitor_home'];
-} elseif (local_user()) {
-       $homebase = 'profile/' . $a->user['nickname'];
-}
-
-if (isset($homebase)) {
-       $a->page['content'] .= '<script>var homebase="' . $homebase . '" ; </script>';
-}
+$a->initFooter();
 
 /*
  * now that we've been through the module content, see if the page reported
@@ -444,36 +431,9 @@ if ($a->module != 'install' && $a->module != 'maintenance') {
        Nav::build($a);
 }
 
-/*
- * Add a "toggle mobile" link if we're using a mobile device
- */
-if ($a->is_mobile || $a->is_tablet) {
-       if (isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
-               $link = 'toggle_mobile?address=' . curPageURL();
-       } else {
-               $link = 'toggle_mobile?off=1&address=' . curPageURL();
-       }
-       $a->page['footer'] = replace_macros(
-               get_markup_template("toggle_mobile_footer.tpl"),
-               [
-                       '$toggle_link' => $link,
-                       '$toggle_text' => L10n::t('toggle mobile')]
-       );
-}
-
 /**
  * Build the page - now that we have all the components
  */
-
-if (!$a->theme['stylesheet']) {
-       $stylesheet = $a->getCurrentThemeStylesheetPath();
-} else {
-       $stylesheet = $a->theme['stylesheet'];
-}
-
-$a->page['htmlhead'] = str_replace('{{$stylesheet}}', $stylesheet, $a->page['htmlhead']);
-//$a->page['htmlhead'] = replace_macros($a->page['htmlhead'], array('$stylesheet' => $stylesheet));
-
 if (isset($_GET["mode"]) && (($_GET["mode"] == "raw") || ($_GET["mode"] == "minimal"))) {
        $doc = new DOMDocument();
 
@@ -502,7 +462,7 @@ if (isset($_GET["mode"]) && ($_GET["mode"] == "raw")) {
 
        echo substr($target->saveHTML(), 6, -8);
 
-       killme();
+       exit();
 }
 
 $page    = $a->page;
@@ -540,5 +500,3 @@ if (empty($template)) {
 
 /// @TODO Looks unsafe (remote-inclusion), is maybe not but Theme::getPathForFile() uses file_exists() but does not escape anything
 require_once $template;
-
-killme();
diff --git a/mod/acctlink.php b/mod/acctlink.php
deleted file mode 100644 (file)
index fb8cfd4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-use Friendica\App;
-use Friendica\Network\Probe;
-
-function acctlink_init()
-{
-       if (x($_GET, 'addr')) {
-               $addr = trim($_GET['addr']);
-               $res = Probe::uri($addr);
-               if ($res['url']) {
-                       goaway($res['url']);
-                       killme();
-               }
-       }
-}
index f9589598dda5b1ef0a5b4715a814c2c5cee68df9..48c45f2934bd3009d3dda04a3cecc1b666fc634e 100644 (file)
@@ -83,8 +83,9 @@ function acl_content(App $a)
                                WHERE `uid` = %d AND NOT `self`
                                AND NOT `blocked` AND NOT `pending` AND NOT `archive`
                                AND `success_update` >= `failure_update`
-                               AND `network` IN ('%s', '%s') $sql_extra2",
+                               AND `network` IN ('%s', '%s', '%s') $sql_extra2",
                        intval(local_user()),
+                       DBA::escape(Protocol::ACTIVITYPUB),
                        DBA::escape(Protocol::DFRN),
                        DBA::escape(Protocol::DIASPORA)
                );
@@ -169,10 +170,11 @@ function acl_content(App $a)
        } elseif ($type == 'm') {
                $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
                                WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
-                               AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s')
+                               AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s', '%s')
                                $sql_extra2
                                ORDER BY `name` ASC ",
                        intval(local_user()),
+                       DBA::escape(Protocol::ACTIVITYPUB),
                        DBA::escape(Protocol::DFRN),
                        DBA::escape(Protocol::DIASPORA)
                );
index 562845ecc80b69851f9c70ff52d6fccea4f1ed69..d0e8ab0e38e65bbe22e2e2063944f638d3bcdcfe 100644 (file)
@@ -77,7 +77,7 @@ function admin_post(App $a)
                                break;
                        case 'themes':
                                if ($a->argc < 2) {
-                                       if (is_ajax()) {
+                                       if ($a->isAjax()) {
                                                return;
                                        }
                                        goaway('admin/');
@@ -107,7 +107,7 @@ function admin_post(App $a)
                                }
 
                                info(L10n::t('Theme settings updated.'));
-                               if (is_ajax()) {
+                               if ($a->isAjax()) {
                                        return;
                                }
                                $return_path = 'admin/themes/' . $theme;
@@ -286,7 +286,7 @@ function admin_content(App $a)
                $o = admin_page_summary($a);
        }
 
-       if (is_ajax()) {
+       if ($a->isAjax()) {
                echo $o;
                killme();
                return '';
@@ -475,8 +475,8 @@ function admin_page_contactblock(App $a)
 
        $total = DBA::count('contact', $condition);
 
-       $a->set_pager_total($total);
-       $a->set_pager_itemspage(30);
+       $a->setPagerTotal($total);
+       $a->setPagerItemsPage(30);
 
        $statement = DBA::select('contact', [], $condition, ['limit' => [$a->pager['start'], $a->pager['itemspage']]]);
 
@@ -866,15 +866,15 @@ function admin_page_summary(App $a)
        // Legacy config file warning
        if (file_exists('.htconfig.php')) {
                $showwarning = true;
-               $warningtext[] = L10n::t('Friendica\'s configuration now is stored in config/local.ini.php, please copy config/local-sample.ini.php and move your config from <code>.htconfig.php</code>. See <a href="%s">the Config help page</a> for help with the transition.', $a->get_baseurl() . '/help/Config');
+               $warningtext[] = L10n::t('Friendica\'s configuration now is stored in config/local.ini.php, please copy config/local-sample.ini.php and move your config from <code>.htconfig.php</code>. See <a href="%s">the Config help page</a> for help with the transition.', $a->getBaseURL() . '/help/Config');
        }
 
        // Check server vitality
        if (!admin_page_server_vital()) {
                $showwarning = true;
-               $well_known = $a->get_baseurl() . '/.well-known/host-meta';
+               $well_known = $a->getBaseURL() . '/.well-known/host-meta';
                $warningtext[] = L10n::t('<a href="%s">%s</a> is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See <a href="%s">the installation page</a> for help.',
-                       $well_known, $well_known, $a->get_baseurl() . '/help/Install');
+                       $well_known, $well_known, $a->getBaseURL() . '/help/Install');
        }
 
        $r = q("SELECT `page-flags`, COUNT(`uid`) AS `count` FROM `user` GROUP BY `page-flags`");
@@ -1012,7 +1012,7 @@ function admin_page_site_post(App $a)
                // update config
                Config::set('system', 'hostname', parse_url($new_url,  PHP_URL_HOST));
                Config::set('system', 'url', $new_url);
-               $a->set_baseurl($new_url);
+               $a->setBaseURL($new_url);
 
                // send relocate
                $users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0");
@@ -1124,7 +1124,7 @@ function admin_page_site_post(App $a)
                Worker::add(PRIORITY_LOW, 'Directory');
        }
 
-       if ($a->get_path() != "") {
+       if ($a->getURLPath() != "") {
                $diaspora_enabled = false;
        }
        if ($ssl_policy != intval(Config::get('system', 'ssl_policy'))) {
@@ -1261,7 +1261,7 @@ function admin_page_site_post(App $a)
        Config::set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
 
        if ($itemcache != '') {
-               $itemcache = App::realpath($itemcache);
+               $itemcache = App::getRealPath($itemcache);
        }
 
        Config::set('system', 'itemcache', $itemcache);
@@ -1269,13 +1269,13 @@ function admin_page_site_post(App $a)
        Config::set('system', 'max_comments', $max_comments);
 
        if ($temppath != '') {
-               $temppath = App::realpath($temppath);
+               $temppath = App::getRealPath($temppath);
        }
 
        Config::set('system', 'temppath', $temppath);
 
        if ($basepath != '') {
-               $basepath = App::realpath($basepath);
+               $basepath = App::getRealPath($basepath);
        }
 
        Config::set('system', 'basepath', $basepath);
@@ -1419,9 +1419,9 @@ function admin_page_site(App $a)
        ];
 
        if (empty(Config::get('config', 'hostname'))) {
-               Config::set('config', 'hostname', $a->get_hostname());
+               Config::set('config', 'hostname', $a->getHostName());
        }
-       $diaspora_able = ($a->get_path() == "");
+       $diaspora_able = ($a->getURLPath() == "");
 
        $optimize_max_tablesize = Config::get('system', 'optimize_max_tablesize', -1);
 
@@ -1488,7 +1488,7 @@ function admin_page_site(App $a)
                '$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. \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_full_threads' => ['ostatus_full_threads', L10n::t("Only import OStatus/ActivityPub threads from our contacts"), Config::get('system','ostatus_full_threads'), L10n::t("Normally we import every content from our OStatus and ActivityPub 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."),
@@ -1801,8 +1801,8 @@ function admin_page_users(App $a)
        /* get users */
        $total = q("SELECT COUNT(*) AS `total` FROM `user` WHERE 1");
        if (count($total)) {
-               $a->set_pager_total($total[0]['total']);
-               $a->set_pager_itemspage(100);
+               $a->setPagerTotal($total[0]['total']);
+               $a->setPagerItemsPage(100);
        }
 
        /* ordering */
@@ -2536,7 +2536,7 @@ function admin_page_features_post(App $a)
  */
 function admin_page_features(App $a)
 {
-       if ((argc() > 1) && (argv(1) === 'features')) {
+       if (($a->argc > 1) && ($a->getArgumentValue(1) === 'features')) {
                $arr = [];
                $features = Feature::get(false);
 
@@ -2567,6 +2567,5 @@ function admin_page_features(App $a)
 function admin_page_server_vital()
 {
        // Fetch the host-meta to check if this really is a vital server
-       $serverret = Network::curl(System::baseUrl() . '/.well-known/host-meta');
-       return $serverret["success"];
+       return Network::curl(System::baseUrl() . '/.well-known/host-meta')->isSuccess();
 }
index 7623a9cd06ca4cbba5be8bb9e15d4fe547b6729b..b41d0c891be7ec7feceb100b80404882f5c7cbe4 100644 (file)
@@ -46,7 +46,7 @@ function allfriends_content(App $a)
 
        $total = GContact::countAllFriends(local_user(), $cid);
 
-       $a->set_pager_total($total);
+       $a->setPagerTotal($total);
 
        $r = GContact::allFriends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']);
        if (!DBA::isResult($r)) {
index e5ae96be70489556dd683a3ce3340b469d7a6b6b..65287b9f2b590eeeabdf66c36d797998170edb59 100644 (file)
@@ -114,6 +114,17 @@ function babel_content()
                                        'content' => visible_whitespace($bbcode)
                                ];
 
+                               $html2 = Text\BBCode::convert($bbcode);
+                               $results[] = [
+                                       'title' => L10n::t('HTML::toBBCode => BBCode::convert'),
+                                       'content' => $html2
+                               ];
+
+                               $results[] = [
+                                       'title' => L10n::t('HTML::toBBCode => BBCode::convert (raw HTML)'),
+                                       'content' => htmlspecialchars($html2)
+                               ];
+
                                $markdown = Text\HTML::toMarkdown($html);
                                $results[] = [
                                        'title' => L10n::t('HTML::toMarkdown'),
index bdedaaacfa8afb99d1d3b3d1952728eafa3cec18..ae1060c47ad5d36a1a76e774857ffd6c4f25e939 100644 (file)
@@ -94,11 +94,6 @@ function cal_content(App $a)
                '$i18n' => $i18n,
        ]);
 
-       $etpl = get_markup_template('event_end.tpl');
-       $a->page['end'] .= replace_macros($etpl, [
-               '$baseurl' => System::baseUrl(),
-       ]);
-
        $mode = 'view';
        $y = 0;
        $m = 0;
index afe78ce460270fdd06a44bf2b02543883ac87042..d694527b8600979c4c74817e1663c39d07b8e4b2 100644 (file)
@@ -88,7 +88,7 @@ function common_content(App $a)
        }
 
        if ($t > 0) {
-               $a->set_pager_total($t);
+               $a->setPagerTotal($t);
        } else {
                notice(L10n::t('No contacts in common.') . EOL);
                return $o;
index 9c9fb4390038fed56110a1465f73e176f31c5c0f..d1432b7bbbf5c19dbd780a6f7eecbc59e7123063 100644 (file)
@@ -153,7 +153,7 @@ function community_content(App $a, $update = 0)
                $itemspage_network = $a->force_max_items;
        }
 
-       $a->set_pager_itemspage($itemspage_network);
+       $a->setPagerItemsPage($itemspage_network);
 
        $r = community_getitems($a->pager['start'], $a->pager['itemspage'], $content, $accounttype);
 
index 1604f0b6605ec43d6f0e936972ad2394a45c11f2..4e149ab74fa4c448cc0e1fcaa847e1551ce18dfb 100644 (file)
@@ -22,6 +22,7 @@ use Friendica\Network\Probe;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Proxy as ProxyUtils;
 use Friendica\Core\ACL;
+use Friendica\Module\Login;
 
 function contacts_init(App $a)
 {
@@ -117,12 +118,6 @@ function contacts_init(App $a)
                '$baseurl' => System::baseUrl(true),
                '$base' => $base
        ]);
-
-       $tpl = get_markup_template("contacts-end.tpl");
-       $a->page['end'] .= replace_macros($tpl, [
-               '$baseurl' => System::baseUrl(true),
-               '$base' => $base
-       ]);
 }
 
 function contacts_batch_actions(App $a)
@@ -168,11 +163,7 @@ function contacts_batch_actions(App $a)
                info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions));
        }
 
-       if (x($_SESSION, 'return_url')) {
-               goaway('' . $_SESSION['return_url']);
-       } else {
-               goaway('contacts');
-       }
+       goaway('contacts');
 }
 
 function contacts_post(App $a)
@@ -385,7 +376,7 @@ function contacts_content(App $a, $update = 0)
 
        if (!local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               return;
+               return Login::form();
        }
 
        if ($a->argc == 3) {
@@ -476,20 +467,13 @@ function contacts_content(App $a, $update = 0)
                        }
                        // Now check how the user responded to the confirmation query
                        if (x($_REQUEST, 'canceled')) {
-                               if (x($_SESSION, 'return_url')) {
-                                       goaway('' . $_SESSION['return_url']);
-                               } else {
-                                       goaway('contacts');
-                               }
+                               goaway('contacts');
                        }
 
                        _contact_drop($orig_record);
                        info(L10n::t('Contact has been removed.') . EOL);
-                       if (x($_SESSION, 'return_url')) {
-                               goaway('' . $_SESSION['return_url']);
-                       } else {
-                               goaway('contacts');
-                       }
+
+                       goaway('contacts');
                        return; // NOTREACHED
                }
                if ($cmd === 'posts') {
@@ -509,9 +493,6 @@ function contacts_content(App $a, $update = 0)
                $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [
                        '$baseurl' => System::baseUrl(true),
                ]);
-               $a->page['end'] .= replace_macros(get_markup_template('contact_end.tpl'), [
-                       '$baseurl' => System::baseUrl(true),
-               ]);
 
                $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user());
                $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user());
@@ -542,7 +523,7 @@ function contacts_content(App $a, $update = 0)
                        $relation_text = '';
                }
 
-               if (!in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) {
+               if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) {
                        $relation_text = "";
                }
 
@@ -655,15 +636,15 @@ function contacts_content(App $a, $update = 0)
                        '$follow_text' => $follow_text,
                        '$profile_select' => $profile_select,
                        '$contact_id' => $contact['id'],
-                       '$block_text' => (($contact['blocked']) ? L10n::t('Unblock') : L10n::t('Block') ),
-                       '$ignore_text' => (($contact['readonly']) ? L10n::t('Unignore') : L10n::t('Ignore') ),
-                       '$insecure' => (($contact['network'] !== Protocol::DFRN && $contact['network'] !== Protocol::MAIL && $contact['network'] !== Protocol::DIASPORA) ? $insecure : ''),
+                       '$block_text' => ($contact['blocked'] ? L10n::t('Unblock') : L10n::t('Block')),
+                       '$ignore_text' => ($contact['readonly'] ? L10n::t('Unignore') : L10n::t('Ignore')),
+                       '$insecure' => (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA]) ? '' : $insecure),
                        '$info' => $contact['info'],
                        '$cinfo' => ['info', '', $contact['info'], ''],
-                       '$blocked' => (($contact['blocked']) ? L10n::t('Currently blocked') : ''),
-                       '$ignored' => (($contact['readonly']) ? L10n::t('Currently ignored') : ''),
-                       '$archived' => (($contact['archive']) ? L10n::t('Currently archived') : ''),
-                       '$pending' => (($contact['pending']) ? L10n::t('Awaiting connection acknowledge') : ''),
+                       '$blocked' => ($contact['blocked'] ? L10n::t('Currently blocked') : ''),
+                       '$ignored' => ($contact['readonly'] ? L10n::t('Currently ignored') : ''),
+                       '$archived' => ($contact['archive'] ? L10n::t('Currently archived') : ''),
+                       '$pending' => ($contact['pending'] ? L10n::t('Awaiting connection acknowledge') : ''),
                        '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts <strong>may</strong> still be visible')],
                        '$notify' => ['notify', L10n::t('Notification for new posts'), ($contact['notify_new_posts'] == 1), L10n::t('Send a notification of every new post of this contact')],
                        '$fetch_further_information' => $fetch_further_information,
@@ -812,7 +793,7 @@ function contacts_content(App $a, $update = 0)
                intval($_SESSION['uid'])
        );
        if (DBA::isResult($r)) {
-               $a->set_pager_total($r[0]['total']);
+               $a->setPagerTotal($r[0]['total']);
                $total = $r[0]['total'];
        }
 
@@ -975,7 +956,7 @@ function contact_conversations(App $a, $contact_id, $update)
                $profiledata = Contact::getDetailsByURL($contact["url"]);
 
                if (local_user()) {
-                       if (in_array($profiledata["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
+                       if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
                                $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]);
                        }
                }
@@ -999,7 +980,7 @@ function contact_posts(App $a, $contact_id)
                $profiledata = Contact::getDetailsByURL($contact["url"]);
 
                if (local_user()) {
-                       if (in_array($profiledata["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
+                       if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
                                $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]);
                        }
                }
@@ -1080,7 +1061,7 @@ function _contact_detail_for_template(array $rr)
  */
 function contact_actions($contact)
 {
-       $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
+       $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
        $contact_actions = [];
 
        // Provide friend suggestion only for Friendica contacts
@@ -1105,7 +1086,7 @@ function contact_actions($contact)
        }
 
        $contact_actions['block'] = [
-               'label' => (intval($contact['blocked']) ? L10n::t('Unblock') : L10n::t('Block') ),
+               'label' => (intval($contact['blocked']) ? L10n::t('Unblock') : L10n::t('Block')),
                'url'   => 'contacts/' . $contact['id'] . '/block',
                'title' => L10n::t('Toggle Blocked status'),
                'sel'   => (intval($contact['blocked']) ? 'active' : ''),
@@ -1113,7 +1094,7 @@ function contact_actions($contact)
        ];
 
        $contact_actions['ignore'] = [
-               'label' => (intval($contact['readonly']) ? L10n::t('Unignore') : L10n::t('Ignore') ),
+               'label' => (intval($contact['readonly']) ? L10n::t('Unignore') : L10n::t('Ignore')),
                'url'   => 'contacts/' . $contact['id'] . '/ignore',
                'title' => L10n::t('Toggle Ignored status'),
                'sel'   => (intval($contact['readonly']) ? 'active' : ''),
@@ -1122,7 +1103,7 @@ function contact_actions($contact)
 
        if ($contact['uid'] != 0) {
                $contact_actions['archive'] = [
-                       'label' => (intval($contact['archive']) ? L10n::t('Unarchive') : L10n::t('Archive') ),
+                       'label' => (intval($contact['archive']) ? L10n::t('Unarchive') : L10n::t('Archive')),
                        'url'   => 'contacts/' . $contact['id'] . '/archive',
                        'title' => L10n::t('Toggle Archive status'),
                        'sel'   => (intval($contact['archive']) ? 'active' : ''),
index 076c611db42a11e462e19c2862c8dbaa0b1bceb6..d8c6b35f5ad03d69e80dc76327a5109d128c172e 100644 (file)
@@ -133,7 +133,7 @@ function crepair_content(App $a)
                $remote_self_options = ['0' => L10n::t('No mirroring'), '2' => L10n::t('Mirror as my own posting')];
        }
 
-       $update_profile = in_array($contact['network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]);
+       $update_profile = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]);
 
        $tab_str = contacts_tab($a, $contact, 5);
 
index 41b5e0ef54f16587dae6e2935ad40916b801e519..969e2286c864076a8b5770300612c6f7f3dd6857 100644 (file)
@@ -28,6 +28,7 @@ use Friendica\Model\Group;
 use Friendica\Model\User;
 use Friendica\Network\Probe;
 use Friendica\Protocol\Diaspora;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Util\Crypto;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
@@ -220,7 +221,7 @@ function dfrn_confirm_post(App $a, $handsfree = null)
                         *
                         */
 
-                       $res = Network::post($dfrn_confirm, $params, null, $redirects, 120);
+                       $res = Network::post($dfrn_confirm, $params, null, $redirects, 120)->getBody();
 
                        logger(' Confirm: received data: ' . $res, LOGGER_DATA);
 
@@ -335,10 +336,17 @@ function dfrn_confirm_post(App $a, $handsfree = null)
                                intval($contact_id)
                        );
                } else {
+                       if ($network == Protocol::ACTIVITYPUB) {
+                               ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $uid);
+                               $pending = true;
+                       } else {
+                               $pending = false;
+                       }
+
                        // $network !== Protocol::DFRN
                        $network = defaults($contact, 'network', Protocol::OSTATUS);
 
-                       $arr = Probe::uri($contact['url']);
+                       $arr = Probe::uri($contact['url'], $network);
 
                        $notify  = defaults($contact, 'notify' , $arr['notify']);
                        $poll    = defaults($contact, 'poll'   , $arr['poll']);
@@ -348,7 +356,7 @@ function dfrn_confirm_post(App $a, $handsfree = null)
                        $new_relation = $contact['rel'];
                        $writable = $contact['writable'];
 
-                       if ($network === Protocol::DIASPORA) {
+                       if (in_array($network, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
                                if ($duplex) {
                                        $new_relation = Contact::FRIEND;
                                } else {
@@ -362,30 +370,12 @@ function dfrn_confirm_post(App $a, $handsfree = null)
 
                        DBA::delete('intro', ['id' => $intro_id]);
 
-                       $r = q("UPDATE `contact` SET `name-date` = '%s',
-                               `uri-date` = '%s',
-                               `addr` = '%s',
-                               `notify` = '%s',
-                               `poll` = '%s',
-                               `blocked` = 0,
-                               `pending` = 0,
-                               `network` = '%s',
-                               `writable` = %d,
-                               `hidden` = %d,
-                               `rel` = %d
-                               WHERE `id` = %d
-                       ",
-                               DBA::escape(DateTimeFormat::utcNow()),
-                               DBA::escape(DateTimeFormat::utcNow()),
-                               DBA::escape($addr),
-                               DBA::escape($notify),
-                               DBA::escape($poll),
-                               DBA::escape($network),
-                               intval($writable),
-                               intval($hidden),
-                               intval($new_relation),
-                               intval($contact_id)
-                       );
+                       $fields = ['name-date' => DateTimeFormat::utcNow(),
+                               'uri-date' => DateTimeFormat::utcNow(), 'addr' => $addr,
+                               'notify' => $notify, 'poll' => $poll, 'blocked' => false,
+                               'pending' => $pending, 'network' => $network,
+                               'writable' => $writable, 'hidden' => $hidden, 'rel' => $new_relation];
+                       DBA::update('contact', $fields, ['id' => $contact_id]);
                }
 
                if (!DBA::isResult($r)) {
@@ -403,6 +393,10 @@ function dfrn_confirm_post(App $a, $handsfree = null)
 
                Group::addMember(User::getDefaultGroup($uid, $contact["network"]), $contact['id']);
 
+               if ($network == Protocol::ACTIVITYPUB && $duplex) {
+                       ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $uid);
+               }
+
                // Let's send our user to the contact editor in case they want to
                // do anything special with this new friend.
                if ($handsfree === null) {
index 54539ee03d7bd4cc580bb7845b9fa34b59734488..af597d76ff7a6c55d3be3b29a5fc77c5f9ee62fb 100644 (file)
@@ -502,7 +502,7 @@ function dfrn_poll_content(App $a)
                                        'dfrn_version' => DFRN_PROTOCOL_VERSION,
                                        'challenge' => $challenge,
                                        'sec' => $sec
-                               ]);
+                               ])->getBody();
                        }
 
                        $profile = ((DBA::isResult($r) && $r[0]['nickname']) ? $r[0]['nickname'] : $nickname);
index 25fe69066fb3d51619c2de82353b927b9951e786..e611458281e8e64759882786ae7ec0233651f76d 100644 (file)
@@ -451,10 +451,10 @@ function dfrn_request_post(App $a)
                        // Diaspora needs the uri in the format user@domain.tld
                        // Diaspora will support the remote subscription in a future version
                        if ($network == Protocol::DIASPORA) {
-                               $uri = $nickname . '@' . $a->get_hostname();
+                               $uri = $nickname . '@' . $a->getHostName();
 
-                               if ($a->get_path()) {
-                                       $uri .= '/' . $a->get_path();
+                               if ($a->getURLPath()) {
+                                       $uri .= '/' . $a->getURLPath();
                                }
 
                                $uri = urlencode($uri);
@@ -609,7 +609,7 @@ function dfrn_request_content(App $a)
                } elseif (x($_GET, 'address') && ($_GET['address'] != "")) {
                        $myaddr = $_GET['address'];
                } elseif (local_user()) {
-                       if (strlen($a->urlpath)) {
+                       if (strlen($a->getURLPath())) {
                                $myaddr = System::baseUrl() . '/profile/' . $a->user['nickname'];
                        } else {
                                $myaddr = $a->user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
index 411024dc1aace31a38e12b6f735d5a693a5a0fd7..202132e3667abeb7a86c4ae36153a8b4040eb1ab 100644 (file)
@@ -16,7 +16,7 @@ use Friendica\Util\Proxy as ProxyUtils;
 
 function directory_init(App $a)
 {
-       $a->set_pager_itemspage(60);
+       $a->setPagerItemsPage(60);
 
        if (local_user()) {
                $a->page['aside'] .= Widget::findPeople();
@@ -87,7 +87,7 @@ function directory_content(App $a)
                                LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
                                WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` $sql_extra");
        if (DBA::isResult($cnt)) {
-               $a->set_pager_total($cnt['total']);
+               $a->setPagerTotal($cnt['total']);
        }
 
        $order = " ORDER BY `name` ASC ";
index 332fe90f6c48cf5af9b0a170fb8e6783b2b2581a..5fe9ae13af32adacf7b8d0e8c34fb25b10fcf1bf 100644 (file)
@@ -54,7 +54,7 @@ function dirfind_content(App $a, $prefix = "") {
                if ((valid_email($search) && Network::isEmailDomainValid($search)) ||
                        (substr(normalise_link($search), 0, 7) == "http://")) {
                        $user_data = Probe::uri($search);
-                       $discover_user = (in_array($user_data["network"], [Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]));
+                       $discover_user = (in_array($user_data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA]));
                }
        }
 
@@ -188,8 +188,8 @@ function dirfind_content(App $a, $prefix = "") {
                }
 
                if ($j->total) {
-                       $a->set_pager_total($j->total);
-                       $a->set_pager_itemspage($j->items_page);
+                       $a->setPagerTotal($j->total);
+                       $a->setPagerItemsPage($j->items_page);
                }
 
                if (!empty($j->results)) {
index 907bf8ebba50d16b54ff34e341fe56c9e3da9408..a03b918372efd61636961fbbf488f486aec18ddc 100644 (file)
@@ -17,6 +17,7 @@ use Friendica\Model\Group;
 use Friendica\Model\Item;
 use Friendica\Model\Profile;
 use Friendica\Protocol\DFRN;
+use Friendica\Protocol\ActivityPub;
 
 function display_init(App $a)
 {
@@ -43,7 +44,7 @@ function display_init(App $a)
 
        $item = null;
 
-       $fields = ['id', 'parent', 'author-id', 'body', 'uid'];
+       $fields = ['id', 'parent', 'author-id', 'body', 'uid', 'guid'];
 
        // If there is only one parameter, then check if this parameter could be a guid
        if ($a->argc == 2) {
@@ -76,6 +77,10 @@ function display_init(App $a)
                displayShowFeed($item["id"], false);
        }
 
+       if (ActivityPub::isRequest()) {
+               goaway(str_replace('display/', 'objects/', $a->query_string));
+       }
+
        if ($item["id"] != $item["parent"]) {
                $item = Item::selectFirstForUser(local_user(), $fields, ['id' => $item["parent"]]);
        }
@@ -360,7 +365,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
        $title = trim(HTML::toPlaintext(BBCode::convert($item["title"], false), 0, true));
        $author_name = $item["author-name"];
 
-       $image = $a->remove_baseurl($item["author-avatar"]);
+       $image = $a->removeBaseURL($item["author-avatar"]);
 
        if ($title == "") {
                $title = $author_name;
index 9f4aee31d6c63421a2692990b123a3926ac17ec8..d6493b3c0c1a8aa34f4d9c547ca1688fe3ca8759 100644 (file)
@@ -57,15 +57,6 @@ function editpost_content(App $a)
                '$nickname' => $a->user['nickname']
        ]);
 
-       $tpl = get_markup_template('jot-end.tpl');
-       $a->page['end'] .= replace_macros($tpl, [
-               '$baseurl' => System::baseUrl(),
-               '$ispublic' => '&nbsp;', // L10n::t('Visible to <strong>everybody</strong>'),
-               '$geotag' => $geotag,
-               '$nickname' => $a->user['nickname']
-       ]);
-
-
        $tpl = get_markup_template("jot.tpl");
 
        if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
index 38b632cf49e46d9a0fa0eda12966d61c0235af06..d6ad97eac67910c0671a3678853f04b80280742a 100644 (file)
@@ -17,6 +17,7 @@ use Friendica\Model\Item;
 use Friendica\Model\Profile;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Temporal;
+use Friendica\Module\Login;
 
 require_once 'include/items.php';
 
@@ -186,14 +187,14 @@ function events_post(App $a)
                Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id);
        }
 
-       goaway($_SESSION['return_url']);
+       goaway('/events');
 }
 
 function events_content(App $a)
 {
        if (!local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               return;
+               return Login::form();
        }
 
        if ($a->argc == 1) {
@@ -231,11 +232,6 @@ function events_content(App $a)
                '$i18n' => $i18n,
        ]);
 
-       $etpl = get_markup_template('event_end.tpl');
-       $a->page['end'] .= replace_macros($etpl, [
-               '$baseurl' => System::baseUrl(),
-       ]);
-
        $o = '';
        $tabs = '';
        // tabs
index d9a9abb91fc670c7a7545a1636610d6ccb383fd7..e75e7a1b8ec3cafebfdd9c814f40507e3fa9cb48 100644 (file)
@@ -32,8 +32,7 @@ function feedtest_content(App $a)
 
                $contact = DBA::selectFirst('contact', [], ['id' => $contact_id]);
 
-               $ret = Network::curl($contact['poll']);
-               $xml = $ret['body'];
+               $xml = Network::fetchUrl($contact['poll']);
 
                $dummy = null;
                $import_result = Feed::import($xml, $importer, $contact, $dummy, true);
index bd46a8bfea2cc540eac71b44b24a9d0637654195..7fb978ae6952e8aeebfeccdbc7c517163481f50e 100644 (file)
@@ -25,9 +25,7 @@ function filerm_content(App $a) {
                file_tag_unsave_file(local_user(),$item_id,$term, $category);
        }
 
-       if (x($_SESSION,'return_url')) {
-               goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
-       }
+       //goaway('/network');
 
        killme();
 }
index 627ab52033049065a9d737fdf8c725068215c121..04c279c5b6ab707f5995aa0c229e412613082d50 100644 (file)
@@ -20,12 +20,12 @@ function follow_post(App $a)
        }
 
        if (isset($_REQUEST['cancel'])) {
-               goaway($_SESSION['return_url']);
+               goaway('contacts');
        }
 
        $uid = local_user();
        $url = notags(trim($_REQUEST['url']));
-       $return_url = $_SESSION['return_url'];
+       $return_url = 'contacts';
 
        // Makes the connection request for friendica contacts easier
        // This is just a precaution if maybe this page is called somewhere directly via POST
@@ -39,7 +39,7 @@ function follow_post(App $a)
                }
                goaway($return_url);
        } elseif ($result['cid']) {
-               goaway(System::baseUrl() . '/contacts/' . $result['cid']);
+               goaway('contacts/' . $result['cid']);
        }
 
        info(L10n::t('The contact could not be added.'));
@@ -50,9 +50,11 @@ function follow_post(App $a)
 
 function follow_content(App $a)
 {
+       $return_url = 'contacts';
+
        if (!local_user()) {
                notice(L10n::t('Permission denied.'));
-               goaway($_SESSION['return_url']);
+               goaway($return_url);
                // NOTREACHED
        }
 
@@ -116,7 +118,7 @@ function follow_content(App $a)
 
        if (!$r) {
                notice(L10n::t('Permission denied.'));
-               goaway($_SESSION['return_url']);
+               goaway($return_url);
                // NOTREACHED
        }
 
index 8fc0f07deef7b8b6becee9cd7f2d2a849c6cfbf7..35710bb338d0139717ed133228d3bcaf3bd53222 100644 (file)
@@ -36,7 +36,7 @@ function fsuggest_post(App $a)
 
        $hash = random_string();
 
-       $note = escape_tags(trim($_POST['note']));
+       $note = escape_tags(trim(defaults($_POST, 'note', '')));
 
        if ($new_contact) {
                $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
index 0c046da54092d6c621a1e036328c5992beed0b51..7e5c2cc08add11cb7739eeafe7fe79cc4dbb0e18 100644 (file)
@@ -50,7 +50,7 @@ function hcard_init(App $a)
 
        $a->page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . (($a->profile['net-publish']) ? 'true' : 'false') . '" />' . "\r\n" ;
        $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/dfrn_poll/' . $which .'" />' . "\r\n" ;
-       $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->get_hostname() . (($a->urlpath) ? '/' . $a->urlpath : ''));
+       $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . (($a->getURLPath()) ? '/' . $a->getURLPath() : ''));
        $a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . System::baseUrl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
        header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
 
index 5db74c15e8f68c9cee6c7e58c49cd0bba8fc1fd9..53118544fb1a72781e73090f1266f550817c134d 100644 (file)
@@ -36,12 +36,12 @@ function help_content(App $a)
                $path = '';
                // looping through the argv keys bigger than 0 to build
                // a path relative to /help
-               for ($x = 1; $x < argc(); $x ++) {
+               for ($x = 1; $x < $a->argc; $x ++) {
                        if (strlen($path)) {
                                $path .= '/';
                        }
 
-                       $path .= argv($x);
+                       $path .= $a->getArgumentValue($x);
                }
                $title = basename($path);
                $filename = $path;
index d28bf3cb43a9fc62b694fae2c2af0d59806b6c97..33d736a4e1cba2793efd62c8e576a90135f5740f 100644 (file)
@@ -38,8 +38,8 @@ function home_content(App $a) {
        $customhome = false;
        $defaultheader = '<h1>' . (Config::get('config', 'sitename') ? L10n::t('Welcome to %s', Config::get('config', 'sitename')) : '') . '</h1>';
 
-       $homefilepath = $a->basepath . "/home.html";
-       $cssfilepath = $a->basepath . "/home.css";
+       $homefilepath = $a->getBasePath() . "/home.html";
+       $cssfilepath = $a->getBasePath() . "/home.css";
        if (file_exists($homefilepath)) {
                $customhome = $homefilepath;
                if (file_exists($cssfilepath)) {
index 16f132fe092ff2a871fcc3a0e15fe67cffbe84c6..30343381c393c9ff119c4cc637a93bf121a17ac1 100644 (file)
@@ -23,7 +23,7 @@ function hostxrd_init(App $a)
 
        $tpl = get_markup_template('xrd_host.tpl');
        echo replace_macros($tpl, [
-               '$zhost' => $a->get_hostname(),
+               '$zhost' => $a->getHostName(),
                '$zroot' => System::baseUrl(),
                '$domain' => System::baseUrl(),
                '$bigkey' => Salmon::salmonKey(Config::get('system', 'site_pubkey'))]
index d2d322b3b93cdb7eb83805c72bded8e636d64029..5a0794b354696978d08164ecf8584964050745ec 100644 (file)
@@ -8,6 +8,7 @@ use Friendica\Core\Install;
 use Friendica\Core\L10n;
 use Friendica\Core\System;
 use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
 use Friendica\Util\Temporal;
 
 $install_wizard_pass = 1;
@@ -42,7 +43,6 @@ function install_post(App $a) {
                        return;
                        break; // just in case return don't return :)
                case 3:
-                       $urlpath = $a->get_path();
                        $dbhost = notags(trim($_POST['dbhost']));
                        $dbuser = notags(trim($_POST['dbuser']));
                        $dbpass = notags(trim($_POST['dbpass']));
@@ -57,7 +57,7 @@ function install_post(App $a) {
                        return;
                        break;
                case 4:
-                       $urlpath = $a->get_path();
+                       $urlpath = $a->getURLPath();
                        $dbhost = notags(trim($_POST['dbhost']));
                        $dbuser = notags(trim($_POST['dbuser']));
                        $dbpass = notags(trim($_POST['dbpass']));
@@ -70,14 +70,16 @@ function install_post(App $a) {
                        // connect to db
                        DBA::connect($dbhost, $dbuser, $dbpass, $dbdata);
 
-                       $errors = Install::createConfig($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail);
+                       $install = new Install();
 
-                       if ($errors) {
-                               $a->data['db_failed'] = $errors;
+                       $errors = $install->createConfig($phpath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $a->getBasePath());
+
+                       if ($errors !== true) {
+                               $a->data['data'] = $errors;
                                return;
                        }
 
-                       $errors = Install::installDatabaseStructure();
+                       $errors = DBStructure::update(false, true, true);
 
                        if ($errors) {
                                $a->data['db_failed'] = $errors;
@@ -97,8 +99,6 @@ function install_content(App $a) {
        $wizard_status = "";
        $install_title = L10n::t('Friendica Communications Server - Setup');
 
-
-
        if (x($a->data, 'db_conn_failed')) {
                $install_wizard_pass = 2;
                $wizard_status = L10n::t('Could not connect to database.');
@@ -125,13 +125,8 @@ function install_content(App $a) {
        if (DBA::$connected) {
                $r = q("SELECT COUNT(*) as `total` FROM `user`");
                if (DBA::isResult($r) && $r[0]['total']) {
-                       $tpl = get_markup_template('install.tpl');
-                       return replace_macros($tpl, [
-                               '$title' => $install_title,
-                               '$pass' => '',
-                               '$status' => L10n::t('Database already in use.'),
-                               '$text' => '',
-                       ]);
+                       $install_wizard_pass = 2;
+                       $wizard_status = L10n::t('Database already in use.');
                }
        }
 
@@ -153,19 +148,21 @@ function install_content(App $a) {
 
                        $phpath = defaults($_POST, 'phpath', 'php');
 
-                       list($checks, $checkspassed) = Install::check($phpath);
+                       $install = new Install($phpath);
+
+                       $status = $install->checkAll($a->getBasePath(), $a->getBaseURL());
 
                        $tpl = get_markup_template('install_checks.tpl');
                        $o .= replace_macros($tpl, [
                                '$title' => $install_title,
                                '$pass' => L10n::t('System check'),
-                               '$checks' => $checks,
-                               '$passed' => $checkspassed,
+                               '$checks' => $install->getChecks(),
+                               '$passed' => $status,
                                '$see_install' => L10n::t('Please see the file "INSTALL.txt".'),
                                '$next' => L10n::t('Next'),
                                '$reload' => L10n::t('Check again'),
                                '$phpath' => $phpath,
-                               '$baseurl' => System::baseUrl(),
+                               '$baseurl' => $a->getBaseURL(),
                        ]);
                        return $o;
                }; break;
@@ -197,7 +194,7 @@ function install_content(App $a) {
 
                                '$lbl_10' => L10n::t('Please select a default timezone for your website'),
 
-                               '$baseurl' => System::baseUrl(),
+                               '$baseurl' => $a->getBaseURL(),
 
                                '$phpath' => $phpath,
 
@@ -235,9 +232,7 @@ function install_content(App $a) {
 
                                '$timezone' => Temporal::getTimezoneField('timezone', L10n::t('Please select a default timezone for your website'), $timezone, ''),
                                '$language' => ['language', L10n::t('System Language:'), 'en', L10n::t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices],
-                               '$baseurl' => System::baseUrl(),
-
-
+                               '$baseurl' => $a->getBaseURL(),
 
                                '$submit' => L10n::t('Submit'),
 
index 213a9907898bf0cafa98de592528716c2018bd23..053a00c977ba77f45482aebe52dda7c86154c102 100644 (file)
@@ -159,7 +159,7 @@ function item_post(App $a) {
        }
 
        // Allow commenting if it is an answer to a public post
-       $allow_comment = local_user() && ($profile_uid == 0) && $parent && in_array($parent_item['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
+       $allow_comment = local_user() && ($profile_uid == 0) && $parent && in_array($parent_item['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
 
        // Now check that valid personal details have been provided
        if (!can_write_wall($profile_uid) && !$allow_comment) {
@@ -240,7 +240,7 @@ function item_post(App $a) {
                $emailcc           =      notags(trim(defaults($_REQUEST, 'emailcc' , '')));
                $body              = escape_tags(trim(defaults($_REQUEST, 'body'    , '')));
                $network           =      notags(trim(defaults($_REQUEST, 'network' , Protocol::DFRN)));
-               $guid              =      System::createGUID(32);
+               $guid              =      System::createUUID();
 
                $postopts = defaults($_REQUEST, 'postopts', '');
 
@@ -343,20 +343,11 @@ function item_post(App $a) {
 
        $tags = get_tags($body);
 
-       // Add a tag if the parent contact is from OStatus (This will notify them during delivery)
-       if ($parent) {
-               if ($thr_parent_contact['network'] == Protocol::OSTATUS) {
-                       $contact = '@[url=' . $thr_parent_contact['url'] . ']' . $thr_parent_contact['nick'] . '[/url]';
-                       if (!stripos(implode($tags), '[url=' . $thr_parent_contact['url'] . ']')) {
-                               $tags[] = $contact;
-                       }
-               }
-
-               if ($parent_contact['network'] == Protocol::OSTATUS) {
-                       $contact = '@[url=' . $parent_contact['url'] . ']' . $parent_contact['nick'] . '[/url]';
-                       if (!stripos(implode($tags), '[url=' . $parent_contact['url'] . ']')) {
-                               $tags[] = $contact;
-                       }
+       // Add a tag if the parent contact is from ActivityPub or OStatus (This will notify them)
+       if ($parent && in_array($thr_parent_contact['network'], [Protocol::OSTATUS, Protocol::ACTIVITYPUB])) {
+               $contact = '@[url=' . $thr_parent_contact['url'] . ']' . $thr_parent_contact['nick'] . '[/url]';
+               if (!stripos(implode($tags), '[url=' . $thr_parent_contact['url'] . ']')) {
+                       $tags[] = $contact;
                }
        }
 
@@ -885,13 +876,13 @@ function item_content(App $a)
        $o = '';
 
        if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) {
-               if (is_ajax()) {
+               if ($a->isAjax()) {
                        $o = Item::deleteForUser(['id' => $a->argv[2]], local_user());
                } else {
                        $o = drop_item($a->argv[2]);
                }
 
-               if (is_ajax()) {
+               if ($a->isAjax()) {
                        // ajax return: [<item id>, 0 (no perm) | <owner id>]
                        echo json_encode([intval($a->argv[2]), intval($o)]);
                        killme();
@@ -1026,8 +1017,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n
                        $alias   = $contact["alias"];
                        $newname = $contact["nick"];
 
-                       if (($newname == "") || (($contact["network"] != Protocol::OSTATUS) && ($contact["network"] != Protocol::TWITTER)
-                               && ($contact["network"] != Protocol::STATUSNET))) {
+                       if (($newname == "") || !in_array($contact["network"], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::TWITTER, Protocol::STATUSNET])) {
                                $newname = $contact["name"];
                        }
                }
index caa4c944cae6a660e0398098dc33836a1b16af22..7e805d5baf4c4d9272e462f5c62a7a365bfd8549 100644 (file)
@@ -59,16 +59,16 @@ function match_content(App $a)
                }
 
                if (strlen(Config::get('system', 'directory'))) {
-                       $x = Network::post(get_server().'/msearch', $params);
+                       $x = Network::post(get_server().'/msearch', $params)->getBody();
                } else {
-                       $x = Network::post(System::baseUrl() . '/msearch', $params);
+                       $x = Network::post(System::baseUrl() . '/msearch', $params)->getBody();
                }
 
                $j = json_decode($x);
 
                if ($j->total) {
-                       $a->set_pager_total($j->total);
-                       $a->set_pager_itemspage($j->items_page);
+                       $a->setPagerTotal($j->total);
+                       $a->setPagerItemsPage($j->items_page);
                }
 
                if (count($j->results)) {
index d0a583967b047c3a61a6261f5dd10f9f6657693c..f9c5c29ec773a934f3795453c8c6a15b257848f3 100644 (file)
@@ -16,6 +16,7 @@ use Friendica\Model\Mail;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Proxy as ProxyUtils;
 use Friendica\Util\Temporal;
+use Friendica\Module\Login;
 
 require_once 'include/conversation.php';
 
@@ -46,12 +47,6 @@ function message_init(App $a)
                '$baseurl' => System::baseUrl(true),
                '$base' => $base
        ]);
-
-       $end_tpl = get_markup_template('message-end.tpl');
-       $a->page['end'] .= replace_macros($end_tpl, [
-               '$baseurl' => System::baseUrl(true),
-               '$base' => $base
-       ]);
 }
 
 function message_post(App $a)
@@ -103,7 +98,7 @@ function message_content(App $a)
 
        if (!local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               return;
+               return Login::form();
        }
 
        $myprofile = System::baseUrl() . '/profile/' . $a->user['nickname'];
@@ -160,17 +155,28 @@ function message_content(App $a)
 
                // Now check how the user responded to the confirmation query
                if (!empty($_REQUEST['canceled'])) {
-                       goaway($_SESSION['return_url']);
+                       goaway('/message');
                }
 
                $cmd = $a->argv[1];
                if ($cmd === 'drop') {
+                       $message = DBA::selectFirst('mail', ['convid'], ['id' => $a->argv[2], 'uid' => local_user()]);
+                       if(!DBA::isResult($message)){
+                               info(L10n::t('Conversation not found.') . EOL);
+                               goaway('/message');
+                       }
+
                        if (DBA::delete('mail', ['id' => $a->argv[2], 'uid' => local_user()])) {
                                info(L10n::t('Message deleted.') . EOL);
                        }
 
-                       //goaway(System::baseUrl(true) . '/message' );
-                       goaway($_SESSION['return_url']);
+                       $conversation = DBA::selectFirst('mail', ['id'], ['convid' => $message['convid'], 'uid' => local_user()]);
+                       if(!DBA::isResult($conversation)){
+                               info(L10n::t('Conversation removed.') . EOL);
+                               goaway('/message');
+                       }
+
+                       goaway('/message/' . $conversation['id'] );
                } else {
                        $r = q("SELECT `parent-uri`,`convid` FROM `mail` WHERE `id` = %d AND `uid` = %d LIMIT 1",
                                intval($a->argv[2]),
@@ -184,8 +190,7 @@ function message_content(App $a)
                                        info(L10n::t('Conversation removed.') . EOL);
                                }
                        }
-                       //goaway(System::baseUrl(true) . '/message' );
-                       goaway($_SESSION['return_url']);
+                       goaway('/message' );
                }
        }
 
@@ -199,13 +204,6 @@ function message_content(App $a)
                        '$linkurl' => L10n::t('Please enter a link URL:')
                ]);
 
-               $tpl = get_markup_template('msg-end.tpl');
-               $a->page['end'] .= replace_macros($tpl, [
-                       '$baseurl' => System::baseUrl(true),
-                       '$nickname' => $a->user['nickname'],
-                       '$linkurl' => L10n::t('Please enter a link URL:')
-               ]);
-
                $preselect = isset($a->argv[2]) ? [$a->argv[2]] : [];
 
                $prename = $preurl = $preid = '';
@@ -281,7 +279,7 @@ function message_content(App $a)
                );
 
                if (DBA::isResult($r)) {
-                       $a->set_pager_total($r[0]['total']);
+                       $a->setPagerTotal($r[0]['total']);
                }
 
                $r = get_messages(local_user(), $a->pager['start'], $a->pager['itemspage']);
@@ -344,13 +342,6 @@ function message_content(App $a)
                        '$linkurl' => L10n::t('Please enter a link URL:')
                ]);
 
-               $tpl = get_markup_template('msg-end.tpl');
-               $a->page['end'] .= replace_macros($tpl, [
-                       '$baseurl' => System::baseUrl(true),
-                       '$nickname' => $a->user['nickname'],
-                       '$linkurl' => L10n::t('Please enter a link URL:')
-               ]);
-
                $mails = [];
                $seen = 0;
                $unknown = false;
index c630beb25f42c6a9e16b59fe4953a46da624645e..fb0093849e1ef4b618641c51bf33de99cb65c905 100644 (file)
@@ -302,7 +302,7 @@ function networkPager($a, $update)
                $itemspage_network = $a->force_max_items;
        }
 
-       $a->set_pager_itemspage($itemspage_network);
+       $a->setPagerItemsPage($itemspage_network);
 
        return sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage']));
 }
@@ -721,7 +721,7 @@ function networkThreadedView(App $a, $update, $parent)
                        if ($last_received != '') {
                                $last_date = $last_received;
                                $sql_range .= sprintf(" AND $sql_table.`received` < '%s'", DBA::escape($last_received));
-                               $a->set_pager_page(1);
+                               $a->setPagerPage(1);
                                $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage']));
                        }
                        break;
@@ -729,7 +729,7 @@ function networkThreadedView(App $a, $update, $parent)
                        if ($last_commented != '') {
                                $last_date = $last_commented;
                                $sql_range .= sprintf(" AND $sql_table.`commented` < '%s'", DBA::escape($last_commented));
-                               $a->set_pager_page(1);
+                               $a->setPagerPage(1);
                                $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage']));
                        }
                        break;
@@ -737,14 +737,14 @@ function networkThreadedView(App $a, $update, $parent)
                        if ($last_created != '') {
                                $last_date = $last_created;
                                $sql_range .= sprintf(" AND $sql_table.`created` < '%s'", DBA::escape($last_created));
-                               $a->set_pager_page(1);
+                               $a->setPagerPage(1);
                                $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage']));
                        }
                        break;
                case 'id':
                        if (($last_id > 0) && ($sql_table == '`thread`')) {
                                $sql_range .= sprintf(" AND $sql_table.`iid` < '%s'", DBA::escape($last_id));
-                               $a->set_pager_page(1);
+                               $a->setPagerPage(1);
                                $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage']));
                        }
                        break;
@@ -810,7 +810,7 @@ function networkThreadedView(App $a, $update, $parent)
        }
 
        // Only show it when unfiltered (no groups, no networks, ...)
-       if (in_array($nets, ['', Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]) && (strlen($sql_extra . $sql_extra2 . $sql_extra3) == 0)) {
+       if (in_array($nets, ['', Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]) && (strlen($sql_extra . $sql_extra2 . $sql_extra3) == 0)) {
                if (DBA::isResult($r)) {
                        $top_limit = current($r)['order_date'];
                        $bottom_limit = end($r)['order_date'];
index 072986cc5ebf8a8e8203cef909dc1f9635ab9a5e..ed0166838fdc3df1733d15328234051a80a8a23e 100644 (file)
@@ -215,7 +215,7 @@ function nodeinfo_cron() {
        logger('local_comments: ' . $local_comments, LOGGER_DEBUG);
 
        // Now trying to register
-       $url = 'http://the-federation.info/register/'.$a->get_hostname();
+       $url = 'http://the-federation.info/register/'.$a->getHostName();
        logger('registering url: '.$url, LOGGER_DEBUG);
        $ret = Network::fetchUrl($url);
        logger('registering answer: '.$ret, LOGGER_DEBUG);
index 01f283870ef8ec2ed119d84a458fd2db67d7e33d..da8352966e721e3f2c7698dc51668efa33db5967 100644 (file)
@@ -61,7 +61,7 @@ function notes_content(App $a, $update = false)
        $condition = ['uid' => local_user(), 'post-type' => Item::PT_PERSONAL_NOTE, 'gravity' => GRAVITY_PARENT,
                'wall' => false, 'contact-id'=> $a->contact['id']];
 
-       $a->set_pager_itemspage(40);
+       $a->setPagerItemsPage(40);
 
        $params = ['order' => ['created' => true],
                'limit' => [$a->pager['start'], $a->pager['itemspage']]];
index 3934a32357b5c9989ab355bb9a237de758e53f6a..1885f96447c9f7e54276cd059bd26cddcaa2482c 100644 (file)
@@ -12,6 +12,7 @@ use Friendica\Core\NotificationsManager;
 use Friendica\Core\Protocol;
 use Friendica\Core\System;
 use Friendica\Database\DBA;
+use Friendica\Module\Login;
 
 function notifications_post(App $a)
 {
@@ -65,7 +66,7 @@ function notifications_content(App $a)
 {
        if (!local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               return;
+               return Login::form();
        }
 
        $page = defaults($_REQUEST, 'page', 1);
@@ -119,7 +120,7 @@ function notifications_content(App $a)
        }
 
        // Set the pager
-       $a->set_pager_itemspage($perpage);
+       $a->setPagerItemsPage($perpage);
 
        // Add additional informations (needed for json output)
        $notifs['items_page'] = $a->pager['itemspage'];
index 458d0140a64130f28e2f383d392692b75da64f2e..a277e59813ecb53a11907a2a7e9736a609408cdb 100644 (file)
@@ -27,7 +27,7 @@ function notify_init(App $a)
                        $nm->setSeen($note);
 
                        // The friendica client has problems with the GUID. this is some workaround
-                       if ($a->is_friendica_app()) {
+                       if ($a->isFriendicaApp()) {
                                require_once("include/items.php");
                                $urldata = parse_url($note['link']);
                                $guid = basename($urldata["path"]);
index 41d45c1f608a887889abc087baa6119f40b67113..63b29684b3c5eded4a1fa651470a76ee192dc8b5 100644 (file)
@@ -19,7 +19,7 @@ function openid_content(App $a) {
 
        if((x($_GET,'openid_mode')) && (x($_SESSION,'openid'))) {
 
-               $openid = new LightOpenID($a->get_hostname());
+               $openid = new LightOpenID($a->getHostName());
 
                if($openid->validate()) {
 
index 8a427908bc244277bfca2e10c7602102b5151bf4..541002410076f22c7409a5a6ef72b715b2a03e36 100644 (file)
@@ -11,7 +11,7 @@ function opensearch_content(App $a) {
 
        $o = replace_macros($tpl, [
                '$baseurl' => System::baseUrl(),
-               '$nodename' => $a->get_hostname(),
+               '$nodename' => $a->getHostName(),
        ]);
 
        echo $o;
index 987f31699e588539727d545a6f113ba967399d29..7012ecd4bcc58f35e3cf9aba74050270e1eed1fd 100644 (file)
@@ -15,7 +15,7 @@ function ostatus_subscribe_content(App $a) {
 
        if (! local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               goaway($_SESSION['return_url']);
+               goaway('/ostatus_subscribe');
                // NOTREACHED
        }
 
@@ -44,14 +44,14 @@ function ostatus_subscribe_content(App $a) {
                $api = $contact["baseurl"]."/api/";
 
                // Fetching friends
-               $data = Network::curl($api."statuses/friends.json?screen_name=".$contact["nick"]);
+               $curlResult = Network::curl($api."statuses/friends.json?screen_name=".$contact["nick"]);
 
-               if (!$data["success"]) {
+               if (!$curlResult->isSuccess()) {
                        PConfig::delete($uid, "ostatus", "legacy_contact");
                        return $o.L10n::t("Couldn't fetch friends for contact.");
                }
 
-               PConfig::set($uid, "ostatus", "legacy_friends", $data["body"]);
+               PConfig::set($uid, "ostatus", "legacy_friends", $curlResult->getBody());
        }
 
        $friends = json_decode(PConfig::get($uid, "ostatus", "legacy_friends"));
@@ -72,8 +72,8 @@ function ostatus_subscribe_content(App $a) {
 
        $o .= "<p>".$counter."/".$total.": ".$url;
 
-       $data = Probe::uri($url);
-       if ($data["network"] == Protocol::OSTATUS) {
+       $curlResult = Probe::uri($url);
+       if ($curlResult["network"] == Protocol::OSTATUS) {
                $result = Contact::createFromProbe($uid, $url, true, Protocol::OSTATUS);
                if ($result["success"]) {
                        $o .= " - ".L10n::t("success");
index ebe34875b76937221baa98bdf6b33044b9ae9ae3..40eddc3bdd5053afcd93e1581048d4f13f9baf1f 100644 (file)
@@ -60,12 +60,12 @@ function parse_url_content(App $a)
        // the URL with the corresponding BBCode media tag
        $redirects = 0;
        // Fetch the header of the URL
-       $result = Network::curl($url, false, $redirects, ['novalidate' => true, 'nobody' => true]);
+       $curlResponse = Network::curl($url, false, $redirects, ['novalidate' => true, 'nobody' => true]);
 
-       if ($result['success']) {
+       if ($curlResponse->isSuccess()) {
                // Convert the header fields into an array
                $hdrs = [];
-               $h = explode("\n", $result['header']);
+               $h = explode("\n", $curlResponse->getHeader());
                foreach ($h as $l) {
                        $header = array_map('trim', explode(':', trim($l), 2));
                        if (count($header) == 2) {
index 6d456b349e9c496ff7168407bde68dcdf5ca9565..b1dd9a5c3a3c60863c5fb71b5c7fc2f194016581 100644 (file)
@@ -192,7 +192,7 @@ function photo_init(App $a)
        // If the photo is public and there is an existing photo directory store the photo there
        if ($public and $file != '') {
                // If the photo path isn't there, try to create it
-               $basepath = $a->get_basepath();
+               $basepath = $a->getBasePath();
                if (!is_dir($basepath . "/photo")) {
                        if (is_writable($basepath)) {
                                mkdir($basepath . "/photo");
index e205d72c6d93114d13b2c10708f4b80bcdefe684..259209ed4041ede16cf179b0c688030eaf10d4a8 100644 (file)
@@ -472,7 +472,7 @@ function photos_post(App $a)
                        $uri = Item::newURI($page_owner_uid);
 
                        $arr = [];
-                       $arr['guid']          = System::createGUID(32);
+                       $arr['guid']          = System::createUUID();
                        $arr['uid']           = $page_owner_uid;
                        $arr['uri']           = $uri;
                        $arr['parent-uri']    = $uri;
@@ -651,7 +651,7 @@ function photos_post(App $a)
                                        $uri = Item::newURI($page_owner_uid);
 
                                        $arr = [];
-                                       $arr['guid']          = System::createGUID(32);
+                                       $arr['guid']          = System::createUUID();
                                        $arr['uid']           = $page_owner_uid;
                                        $arr['uri']           = $uri;
                                        $arr['parent-uri']    = $uri;
@@ -889,7 +889,7 @@ function photos_post(App $a)
                $arr['coord'] = $lat . ' ' . $lon;
        }
 
-       $arr['guid']          = System::createGUID(32);
+       $arr['guid']          = System::createUUID();
        $arr['uid']           = $page_owner_uid;
        $arr['uri']           = $uri;
        $arr['parent-uri']    = $uri;
@@ -1143,8 +1143,8 @@ function photos_content(App $a)
                        DBA::escape($album)
                );
                if (DBA::isResult($r)) {
-                       $a->set_pager_total(count($r));
-                       $a->set_pager_itemspage(20);
+                       $a->setPagerTotal(count($r));
+                       $a->setPagerItemsPage(20);
                }
 
                /// @TODO I have seen this many times, maybe generalize it script-wide and encapsulate it?
@@ -1393,7 +1393,7 @@ function photos_content(App $a)
                        $link_item = Item::selectFirst([], ['id' => $linked_items[0]['id']]);
 
                        $condition = ["`parent` = ? AND `parent` != `id`",  $link_item['parent']];
-                       $a->set_pager_total(DBA::count('item', $condition));
+                       $a->setPagerTotal(DBA::count('item', $condition));
 
                        $params = ['order' => ['id'], 'limit' => [$a->pager['start'], $a->pager['itemspage']]];
                        $result = Item::selectForUser($link_item['uid'], Item::ITEM_FIELDLIST, $condition, $params);
@@ -1655,8 +1655,8 @@ function photos_content(App $a)
        );
 
        if (DBA::isResult($r)) {
-               $a->set_pager_total(count($r));
-               $a->set_pager_itemspage(20);
+               $a->setPagerTotal(count($r));
+               $a->setPagerItemsPage(20);
        }
 
        $r = q("SELECT `resource-id`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`filename`) AS `filename`,
index 968751a7da1819c0d9e261a0b87cac95800218f7..ff0139f28f9d3b405f0b148ccf694b8ba03f0171 100644 (file)
@@ -350,7 +350,7 @@ function ping_init(App $a)
                        $regularnotifications = (!empty($_GET['uid']) && !empty($_GET['_']));
 
                        foreach ($notifs as $notif) {
-                               if ($a->is_friendica_app() || !$regularnotifications) {
+                               if ($a->isFriendicaApp() || !$regularnotifications) {
                                        $notif['message'] = str_replace("{0}", $notif['name'], $notif['message']);
                                }
 
index 91f33c0def2fd43a2991fb1aef40b41109f0f9da..6ebb8632c18b3a24bc229b2c300fc1a8e346e97f 100644 (file)
@@ -97,7 +97,7 @@ function poke_init(App $a)
 
        $arr = [];
 
-       $arr['guid']          = System::createGUID(32);
+       $arr['guid']          = System::createUUID();
        $arr['uid']           = $uid;
        $arr['uri']           = $uri;
        $arr['parent-uri']    = (!empty($parent_uri) ? $parent_uri : $uri);
index 2e3ccd28c52a8769f57c36df7160c841f96c5e45..aa284d1669a0184a1e6fdf05c84074d76e02ce46 100644 (file)
@@ -20,6 +20,7 @@ use Friendica\Model\Profile;
 use Friendica\Module\Login;
 use Friendica\Protocol\DFRN;
 use Friendica\Util\DateTimeFormat;
+use Friendica\Protocol\ActivityPub;
 
 function profile_init(App $a)
 {
@@ -49,6 +50,16 @@ function profile_init(App $a)
                DFRN::autoRedir($a, $which);
        }
 
+       if (ActivityPub::isRequest()) {
+               $user = DBA::selectFirst('user', ['uid'], ['nickname' => $which]);
+               if (DBA::isResult($user)) {
+                       $data = ActivityPub\Transmitter::getProfile($user['uid']);
+                       echo json_encode($data);
+                       header('Content-Type: application/activity+json');
+                       exit();
+               }
+       }
+
        Profile::load($a, $which, $profile);
 
        $blocked   = !local_user() && !remote_user() && Config::get('system', 'block_public');
@@ -80,7 +91,7 @@ function profile_init(App $a)
        $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/feed/' . $which . '/" title="' . L10n::t('%s\'s posts', $a->profile['username']) . '"/>' . "\r\n";
        $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/feed/' . $which . '/comments" title="' . L10n::t('%s\'s comments', $a->profile['username']) . '"/>' . "\r\n";
        $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/feed/' . $which . '/activity" title="' . L10n::t('%s\'s timeline', $a->profile['username']) . '"/>' . "\r\n";
-       $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->get_hostname() . ($a->urlpath ? '/' . $a->urlpath : ''));
+       $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . ($a->getURLPath() ? '/' . $a->getURLPath() : ''));
        $a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . System::baseUrl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
        header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
 
@@ -296,7 +307,7 @@ function profile_content(App $a, $update = 0)
                        $itemspage_network = $a->force_max_items;
                }
 
-               $a->set_pager_itemspage($itemspage_network);
+               $a->setPagerItemsPage($itemspage_network);
 
                $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage']));
 
index 567a7f3a2512b3e05c79edb68a57546637a47f76..984ebfed6f39fc27bfa6bc157d903e5be905953a 100644 (file)
@@ -317,7 +317,6 @@ function profile_photo_crop_ui_head(App $a, Image $image)
        }
 
        $a->page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []);
-       $a->page['end'] .= replace_macros(get_markup_template("cropend.tpl"), []);
 
        $imagecrop = [
                'hash'       => $hash,
index d951a470d7605db79ea8f97af1eeba3278b39c0e..3e6bd1cb0d0ff29bacf720540dcf125cd2132e1c 100644 (file)
@@ -20,6 +20,7 @@ use Friendica\Model\Profile;
 use Friendica\Network\Probe;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Temporal;
+use Friendica\Module\Login;
 
 function profiles_init(App $a) {
 
@@ -509,7 +510,7 @@ function profiles_content(App $a) {
 
        if (! local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               return;
+               return Login::form();
        }
 
        $o = '';
@@ -527,9 +528,6 @@ function profiles_content(App $a) {
                $a->page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), [
                        '$baseurl' => System::baseUrl(true),
                ]);
-               $a->page['end'] .= replace_macros(get_markup_template('profed_end.tpl'), [
-                       '$baseurl' => System::baseUrl(true),
-               ]);
 
                $opt_tpl = get_markup_template("profile-hide-friends.tpl");
                $hide_friends = replace_macros($opt_tpl,[
@@ -618,10 +616,10 @@ function profiles_content(App $a) {
                        '$country_name' => ['country_name', L10n::t('Country:'), $r[0]['country-name']],
                        '$age' => ((intval($r[0]['dob'])) ? '(' . L10n::t('Age: ') . Temporal::getAgeByTimezone($r[0]['dob'],$a->user['timezone'],$a->user['timezone']) . ')' : ''),
                        '$gender' => ContactSelector::gender($r[0]['gender']),
-                       '$marital' => ContactSelector::maritalStatus($r[0]['marital']),
+                       '$marital' => ['selector' => ContactSelector::maritalStatus($r[0]['marital']), 'value' => $r[0]['marital']],
                        '$with' => ['with', L10n::t("Who: \x28if applicable\x29"), strip_tags($r[0]['with']), L10n::t('Examples: cathy123, Cathy Williams, cathy@example.com')],
                        '$howlong' => ['howlong', L10n::t('Since [date]:'), ($r[0]['howlong'] <= NULL_DATE ? '' : DateTimeFormat::local($r[0]['howlong']))],
-                       '$sexual' => ContactSelector::sexualPreference($r[0]['sexual']),
+                       '$sexual' => ['selector' => ContactSelector::sexualPreference($r[0]['sexual']), 'value' => $r[0]['sexual']],
                        '$about' => ['about', L10n::t('Tell us about yourself...'), $r[0]['about']],
                        '$xmpp' => ['xmpp', L10n::t("XMPP \x28Jabber\x29 address:"), $r[0]['xmpp'], L10n::t("The XMPP address will be propagated to your contacts so that they can follow you.")],
                        '$homepage' => ['homepage', L10n::t('Homepage URL:'), $r[0]['homepage']],
@@ -669,7 +667,7 @@ function profiles_content(App $a) {
                        $profiles = '';
                        foreach ($r as $rr) {
                                $profiles .= replace_macros($tpl, [
-                                       '$photo'        => $a->remove_baseurl($rr['thumb']),
+                                       '$photo'        => $a->removeBaseURL($rr['thumb']),
                                        '$id'           => $rr['id'],
                                        '$alt'          => L10n::t('Profile Image'),
                                        '$profile_name' => $rr['profile-name'],
index 8f9478d8aa51d0a322e6299156cca5968b9751b3..d7b204e89c4f9622e081fd30507673eb729b94e2 100644 (file)
@@ -104,8 +104,9 @@ function pubsubhubbub_init(App $a) {
                // we don't actually enforce the lease time because GNU
                // Social/StatusNet doesn't honour it (yet)
 
-               $body = Network::fetchUrl($hub_callback . "?" . $params);
-               $ret = $a->get_curl_code();
+               $fetchResult = Network::fetchUrlFull($hub_callback . "?" . $params);
+               $body = $fetchResult->getBody();
+               $ret = $fetchResult->getReturnCode();
 
                // give up if the HTTP return code wasn't a success (2xx)
                if ($ret < 200 || $ret > 299) {
index 3acf960dab7b2556218dd2ed7a2a52d1501ff4fe..e989ad015a83045b5f98ce9e202e416bce03731a 100644 (file)
@@ -57,7 +57,7 @@ function redir_init(App $a) {
                }
 
                if (remote_user()) {
-                       $host = substr(System::baseUrl() . ($a->urlpath ? '/' . $a->urlpath : ''), strpos(System::baseUrl(), '://') + 3);
+                       $host = substr(System::baseUrl() . ($a->getURLPath() ? '/' . $a->getURLPath() : ''), strpos(System::baseUrl(), '://') + 3);
                        $remotehost = substr($contact['addr'], strpos($contact['addr'], '@') + 1);
 
                        // On a local instance we have to check if the local user has already authenticated
index b851faf2d6225f471e5cec43e93270b4beab3978..454062d89b6c90c874f7511a1acd8d0ca003fc93 100644 (file)
@@ -274,7 +274,7 @@ function register_content(App $a)
                '$passwords' => $passwords,
                '$password1' => ['password1', L10n::t('New Password:'), '', L10n::t('Leave empty for an auto generated password.')],
                '$password2' => ['confirm', L10n::t('Confirm:'), '', ''],
-               '$nickdesc'  => L10n::t('Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be \'<strong>nickname@%s</strong>\'.', $a->get_hostname()),
+               '$nickdesc'  => L10n::t('Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be \'<strong>nickname@%s</strong>\'.', $a->getHostName()),
                '$nicklabel' => L10n::t('Choose a nickname: '),
                '$photo'     => $photo,
                '$publish'   => $profile_publish,
@@ -283,7 +283,7 @@ function register_content(App $a)
                '$email'     => $email,
                '$nickname'  => $nickname,
                '$license'   => $license,
-               '$sitename'  => $a->get_hostname(),
+               '$sitename'  => $a->getHostName(),
                '$importh'   => L10n::t('Import'),
                '$importt'   => L10n::t('Import your profile to this friendica instance'),
                '$showtoslink' => Config::get('system', 'tosdisplay'),
index 3acaa687a712942a959edbfaee62e5141a79cb91..4499220817449b83684020ca1da731e3a6d170e9 100644 (file)
@@ -14,7 +14,7 @@ function repair_ostatus_content(App $a) {
 
        if (! local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
-               goaway($_SESSION['return_url']);
+               goaway('/ostatus_repair');
                // NOTREACHED
        }
 
index 84bc230e30ec23c0c943d4d3af8e27ff1d727845..5632193e3bddcf4255713060a28ac05e2d98bbd8 100644 (file)
@@ -22,6 +22,7 @@ use Friendica\Model\User;
 use Friendica\Protocol\Email;
 use Friendica\Util\Network;
 use Friendica\Util\Temporal;
+use Friendica\Module\Login;
 
 function get_theme_config_file($theme)
 {
@@ -546,7 +547,7 @@ function settings_post(App $a)
        if ($openid != $a->user['openid'] || (strlen($openid) && (!strlen($openidserver)))) {
                if (Network::isUrlValid($openid)) {
                        logger('updating openidserver');
-                       $open_id_obj = new LightOpenID($a->get_hostname());
+                       $open_id_obj = new LightOpenID($a->getHostName());
                        $open_id_obj->identity = $openid;
                        $openidserver = $open_id_obj->discover($open_id_obj->identity);
                } else {
@@ -658,7 +659,7 @@ function settings_content(App $a)
 
        if (!local_user()) {
                //notice(L10n::t('Permission denied.') . EOL);
-               return;
+               return Login::form();
        }
 
        if (x($_SESSION, 'submanage') && intval($_SESSION['submanage'])) {
@@ -982,11 +983,6 @@ function settings_content(App $a)
                        '$theme_config' => $theme_config,
                ]);
 
-               $tpl = get_markup_template('settings/display_end.tpl');
-               $a->page['end'] .= replace_macros($tpl, [
-                       '$theme'        => ['theme', L10n::t('Display Theme:'), $theme_selected, '', $themes]
-               ]);
-
                return $o;
        }
 
@@ -1140,8 +1136,8 @@ function settings_content(App $a)
        $tpl_addr = get_markup_template('settings/nick_set.tpl');
 
        $prof_addr = replace_macros($tpl_addr,[
-               '$desc' => L10n::t("Your Identity Address is <strong>'%s'</strong> or '%s'.", $nickname . '@' . $a->get_hostname() . $a->get_path(), System::baseUrl() . '/profile/' . $nickname),
-               '$basepath' => $a->get_hostname()
+               '$desc' => L10n::t("Your Identity Address is <strong>'%s'</strong> or '%s'.", $nickname . '@' . $a->getHostName() . $a->getURLPath(), System::baseUrl() . '/profile/' . $nickname),
+               '$basepath' => $a->getHostName()
        ]);
 
        $stpl = get_markup_template('settings/settings.tpl');
index 1153f2147d7c5efcb11f2f71b141fda086640253..105cf60feb7f1e3d3a3ba458c3b37625a149f29c 100644 (file)
@@ -108,7 +108,7 @@ EOT;
 
        $arr = [];
 
-       $arr['guid'] = System::createGUID(32);
+       $arr['guid'] = System::createUUID();
        $arr['uri'] = $uri;
        $arr['uid'] = $owner_uid;
        $arr['contact-id'] = $contact['id'];
index 959394c07881a1e8b0b9c7dd43623d77b000eac3..fd79d54150df6d60defe34a7b88f7616d278ad86 100644 (file)
@@ -115,7 +115,7 @@ EOT;
 
        $arr = [];
 
-       $arr['guid'] = System::createGUID(32);
+       $arr['guid'] = System::createUUID();
        $arr['uri'] = $uri;
        $arr['uid'] = $owner_uid;
        $arr['contact-id'] = $contact['id'];
index b80263a3ecd33349047e177f8ff964547b4c56d8..9b0e206904bad703e608d2a460d993a72f39909c 100644 (file)
@@ -14,18 +14,14 @@ use Friendica\Model\User;
 
 function unfollow_post()
 {
-       $return_url = $_SESSION['return_url'];
+       $return_url = 'contacts';
 
        if (!local_user()) {
                notice(L10n::t('Permission denied.'));
-               goaway($return_url);
+               goaway('/login');
                // NOTREACHED
        }
 
-       if (!empty($_REQUEST['cancel'])) {
-               goaway($return_url);
-       }
-
        $uid = local_user();
        $url = notags(trim(defaults($_REQUEST, 'url', '')));
 
@@ -40,9 +36,13 @@ function unfollow_post()
                // NOTREACHED
        }
 
+       if (!empty($_REQUEST['cancel'])) {
+               goaway($return_url . '/' . $contact['id']);
+       }
+
        if (!in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
                notice(L10n::t('Unfollowing is currently not supported by your network.'));
-               goaway($return_url);
+               goaway($return_url . '/' . $contact['id']);
                // NOTREACHED
        }
 
@@ -69,9 +69,11 @@ function unfollow_post()
 
 function unfollow_content(App $a)
 {
+       $return_url = 'contacts';
+
        if (!local_user()) {
                notice(L10n::t('Permission denied.'));
-               goaway($_SESSION['return_url']);
+               goaway('/login');
                // NOTREACHED
        }
 
@@ -86,7 +88,7 @@ function unfollow_content(App $a)
 
        if (!DBA::isResult($contact)) {
                notice(L10n::t("You aren't following this contact."));
-               goaway('contacts');
+               goaway($return_url);
                // NOTREACHED
        }
 
@@ -103,7 +105,7 @@ function unfollow_content(App $a)
 
        if (!DBA::isResult($self)) {
                notice(L10n::t('Permission denied.'));
-               goaway($_SESSION['return_url']);
+               goaway($return_url);
                // NOTREACHED
        }
 
index e00df10a24b48d171fa05287c7456b86875a795d..e52c78cab11f794a0b5f2e4fdd7ab30dfd35c2a0 100644 (file)
@@ -105,12 +105,6 @@ function videos_init(App $a)
                $a->page['htmlhead'] .= replace_macros($tpl,[
                        '$baseurl' => System::baseUrl(),
                ]);
-
-               $tpl = get_markup_template("videos_end.tpl");
-               $a->page['end'] .= replace_macros($tpl,[
-                       '$baseurl' => System::baseUrl(),
-               ]);
-
        }
 
        return;
@@ -347,8 +341,8 @@ function videos_content(App $a)
        );
 
        if (DBA::isResult($r)) {
-               $a->set_pager_total(count($r));
-               $a->set_pager_itemspage(20);
+               $a->setPagerTotal(count($r));
+               $a->setPagerItemsPage(20);
        }
 
        $r = q("SELECT hash, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`created`) AS `created`,
index 9446470e1b03df21f2e9eeb649e4235504d21337..563c13c6d4ada9ccc0242731ff29f650147e38e3 100644 (file)
@@ -71,7 +71,7 @@ function viewcontacts_content(App $a)
                DBA::escape(Protocol::OSTATUS)
        );
        if (DBA::isResult($r)) {
-               $a->set_pager_total($r[0]['total']);
+               $a->setPagerTotal($r[0]['total']);
        }
 
        $r = q("SELECT * FROM `contact`
index afdcaada2235480620838ceddf53d6d1a1148b36..7ed029aa78100f6cc118c05de0a4450644ce9b3a 100644 (file)
@@ -26,7 +26,7 @@ function viewsrc_content(App $a)
        $item = Item::selectFirst(['body'], ['uid' => local_user(), 'id' => $item_id]);
 
        if (DBA::isResult($item)) {
-               if (is_ajax()) {
+               if ($a->isAjax()) {
                        echo str_replace("\n", '<br />', $item['body']);
                        killme();
                } else {
index 5606b6feede6a6ed35c26f5512ae5cf7cb403303..5e08420ecb109f6cd16767574f51815982038c9e 100644 (file)
@@ -120,13 +120,6 @@ function wallmessage_content(App $a) {
                '$linkurl' => L10n::t('Please enter a link URL:')
        ]);
 
-       $tpl = get_markup_template('wallmsg-end.tpl');
-       $a->page['end'] .= replace_macros($tpl, [
-               '$baseurl' => System::baseUrl(true),
-               '$nickname' => $user['nickname'],
-               '$linkurl' => L10n::t('Please enter a link URL:')
-       ]);
-
        $tpl = get_markup_template('wallmessage.tpl');
        $o = replace_macros($tpl, [
                '$header' => L10n::t('Send Private Message'),
index 61505f29966e99d2ea4f66f27d2cb091a8bf16cc..1d29d7904a9d5705e77deac205f0dbfc0fdb2cde 100644 (file)
@@ -13,7 +13,7 @@ function xrd_init(App $a)
 {
        if ($a->argv[0] == 'xrd') {
                if (empty($_GET['uri'])) {
-                       killme();
+                       System::httpExit(404);
                }
 
                $uri = urldecode(notags(trim($_GET['uri'])));
@@ -24,7 +24,7 @@ function xrd_init(App $a)
                }
        } else {
                if (empty($_GET['resource'])) {
-                       killme();
+                       System::httpExit(404);
                }
 
                $uri = urldecode(notags(trim($_GET['resource'])));
@@ -48,16 +48,16 @@ function xrd_init(App $a)
 
        $user = DBA::selectFirst('user', [], ['nickname' => $name]);
        if (!DBA::isResult($user)) {
-               killme();
+               System::httpExit(404);
        }
 
        $profile_url = System::baseUrl().'/profile/'.$user['nickname'];
 
        $alias = str_replace('/profile/', '/~', $profile_url);
 
-       $addr = 'acct:'.$user['nickname'].'@'.$a->get_hostname();
-       if ($a->get_path()) {
-               $addr .= '/'.$a->get_path();
+       $addr = 'acct:'.$user['nickname'].'@'.$a->getHostName();
+       if ($a->getURLPath()) {
+               $addr .= '/'.$a->getURLPath();
        }
 
        if ($mode == 'xml') {
@@ -80,6 +80,7 @@ function xrd_json($a, $uri, $alias, $profile_url, $r)
                        ['rel' => NAMESPACE_DFRN, 'href' => $profile_url],
                        ['rel' => NAMESPACE_FEED, 'type' => 'application/atom+xml', 'href' => System::baseUrl().'/dfrn_poll/'.$r['nickname']],
                        ['rel' => 'http://webfinger.net/rel/profile-page', 'type' => 'text/html', 'href' => $profile_url],
+                       ['rel' => 'self', 'type' => 'application/activity+json', 'href' => $profile_url],
                        ['rel' => 'http://microformats.org/profile/hcard', 'type' => 'text/html', 'href' => System::baseUrl().'/hcard/'.$r['nickname']],
                        ['rel' => NAMESPACE_POCO, 'href' => System::baseUrl().'/poco/'.$r['nickname']],
                        ['rel' => 'http://webfinger.net/rel/avatar', 'type' => 'image/jpeg', 'href' => System::baseUrl().'/photo/profile/'.$r['uid'].'.jpg'],
@@ -92,6 +93,7 @@ function xrd_json($a, $uri, $alias, $profile_url, $r)
                        ['rel' => 'http://purl.org/openwebauth/v1', 'type' => 'application/x-dfrn+json', 'href' => System::baseUrl().'/owa']
                ]
        ];
+
        echo json_encode($json);
        killme();
 }
index 0dc4b86b95f6520f14bb966e45f552ff6e8ad511..97c193b3b7f4937ec68fe62fc390dd1787ba04d2 100644 (file)
@@ -11,6 +11,7 @@ use Friendica\Core\L10n;
 use Friendica\Core\PConfig;
 use Friendica\Core\System;
 use Friendica\Database\DBA;
+use Friendica\Network\HTTPException\InternalServerErrorException;
 
 require_once 'boot.php';
 require_once 'include/dba.php';
@@ -31,21 +32,6 @@ require_once 'include/text.php';
  */
 class App
 {
-       const MODE_LOCALCONFIGPRESENT = 1;
-       const MODE_DBAVAILABLE = 2;
-       const MODE_DBCONFIGAVAILABLE = 4;
-       const MODE_MAINTENANCEDISABLED = 8;
-
-       /**
-        * @deprecated since version 2008.08 Use App->isInstallMode() instead to check for install mode.
-        */
-       const MODE_INSTALL = 0;
-
-       /**
-        * @deprecated since version 2008.08 Use the precise mode constant to check for a specific capability instead.
-        */
-       const MODE_NORMAL = App::MODE_LOCALCONFIGPRESENT | App::MODE_DBAVAILABLE | App::MODE_DBCONFIGAVAILABLE | App::MODE_MAINTENANCEDISABLED;
-
        public $module_loaded = false;
        public $module_class = null;
        public $query_string = '';
@@ -67,10 +53,7 @@ class App
        public $argv;
        public $argc;
        public $module;
-       public $mode = App::MODE_INSTALL;
        public $strings;
-       public $basepath;
-       public $urlpath;
        public $hooks = [];
        public $timezone;
        public $interactive = true;
@@ -80,11 +63,9 @@ class App
        public $identities;
        public $is_mobile = false;
        public $is_tablet = false;
-       public $is_friendica_app;
        public $performance = [];
        public $callstack = [];
        public $theme_info = [];
-       public $backend = true;
        public $nav_sel;
        public $category;
        // Allow themes to control internal parameters
@@ -96,6 +77,76 @@ class App
        public $force_max_items = 0;
        public $theme_events_in_profile = true;
 
+       public $stylesheets = [];
+       public $footerScripts = [];
+
+       /**
+        * @var App\Mode The Mode of the Application
+        */
+       private $mode;
+
+       /**
+        * @var string The App base path
+        */
+       private $basePath;
+
+       /**
+        * @var string The App URL path
+        */
+       private $urlPath;
+
+       /**
+        * @var bool true, if the call is from the Friendica APP, otherwise false
+        */
+       private $isFriendicaApp;
+
+       /**
+        * @var bool true, if the call is from an backend node (f.e. worker)
+        */
+       private $isBackend;
+
+       /**
+        * @var string The name of the current theme
+        */
+       private $currentTheme;
+
+       /**
+        * @var bool check if request was an AJAX (xmlhttprequest) request
+        */
+       private $isAjax;
+
+       /**
+        * Register a stylesheet file path to be included in the <head> tag of every page.
+        * Inclusion is done in App->initHead().
+        * The path can be absolute or relative to the Friendica installation base folder.
+        *
+        * @see App->initHead()
+        *
+        * @param string $path
+        */
+       public function registerStylesheet($path)
+       {
+               $url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path);
+
+               $this->stylesheets[] = trim($url, '/');
+       }
+
+       /**
+        * Register a javascript file path to be included in the <footer> tag of every page.
+        * Inclusion is done in App->initFooter().
+        * The path can be absolute or relative to the Friendica installation base folder.
+        *
+        * @see App->initFooter()
+        *
+        * @param string $path
+        */
+       public function registerFooterScript($path)
+       {
+               $url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path);
+
+               $this->footerScripts[] = trim($url, '/');
+       }
+
        /**
         * @brief An array for all theme-controllable parameters
         *
@@ -132,26 +183,26 @@ class App
        ];
        private $scheme;
        private $hostname;
-       private $curl_code;
-       private $curl_content_type;
-       private $curl_headers;
 
        /**
         * @brief App constructor.
         *
-        * @param string $basepath Path to the app base folder
+        * @param string $basePath Path to the app base folder
+        * @param bool $backend true, if the call is from backend, otherwise set to true (Default true)
         *
         * @throws Exception if the Basepath is not usable
         */
-       public function __construct($basepath)
+       public function __construct($basePath, $backend = true)
        {
-               if (!static::directory_usable($basepath, false)) {
-                       throw new Exception('Basepath ' . $basepath . ' isn\'t usable.');
+               if (!static::isDirectoryUsable($basePath, false)) {
+                       throw new Exception('Basepath ' . $basePath . ' isn\'t usable.');
                }
 
                BaseObject::setApp($this);
 
-               $this->basepath = rtrim($basepath, DIRECTORY_SEPARATOR);
+               $this->basePath = rtrim($basePath, DIRECTORY_SEPARATOR);
+               $this->checkBackend($backend);
+               $this->checkFriendicaApp();
 
                $this->performance['start'] = microtime(true);
                $this->performance['database'] = 0;
@@ -174,6 +225,8 @@ class App
                $this->callstack['rendering'] = [];
                $this->callstack['parser'] = [];
 
+               $this->mode = new App\Mode($basePath);
+
                $this->reload();
 
                set_time_limit(0);
@@ -203,9 +256,9 @@ class App
 
                set_include_path(
                        get_include_path() . PATH_SEPARATOR
-                       . $this->basepath . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
-                       . $this->basepath . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
-                       . $this->basepath);
+                       . $this->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
+                       . $this->getBasePath(). DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
+                       . $this->getBasePath());
 
                if ((x($_SERVER, 'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'], 0, 9) === 'pagename=') {
                        $this->query_string = substr($_SERVER['QUERY_STRING'], 9);
@@ -274,11 +327,26 @@ class App
                $this->is_mobile = $mobile_detect->isMobile();
                $this->is_tablet = $mobile_detect->isTablet();
 
-               // Friendica-Client
-               $this->is_friendica_app = isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'Apache-HttpClient/UNAVAILABLE (java 1.4)';
+               $this->isAjax = strtolower(defaults($_SERVER, 'HTTP_X_REQUESTED_WITH', '')) == 'xmlhttprequest';
 
                // Register template engines
-               $this->register_template_engine('Friendica\Render\FriendicaSmartyEngine');
+               $this->registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine');
+       }
+
+       /**
+        * Returns the Mode of the Application
+        *
+        * @return App\Mode The Application Mode
+        *
+        * @throws InternalServerErrorException when the mode isn't created
+        */
+       public function getMode()
+       {
+               if (empty($this->mode)) {
+                       throw new InternalServerErrorException('Mode of the Application is not defined');
+               }
+
+               return $this->mode;
        }
 
        /**
@@ -291,13 +359,13 @@ class App
 
                $this->loadDatabase();
 
-               $this->determineMode();
+               $this->getMode()->determine($this->getBasePath());
 
-               $this->determineUrlPath();
+               $this->determineURLPath();
 
                Config::load();
 
-               if ($this->mode & self::MODE_DBAVAILABLE) {
+               if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
                        Core\Addon::loadHooks();
 
                        $this->loadAddonConfig();
@@ -309,7 +377,6 @@ class App
                        'aside' => '',
                        'bottom' => '',
                        'content' => '',
-                       'end' => '',
                        'footer' => '',
                        'htmlhead' => '',
                        'nav' => '',
@@ -330,20 +397,20 @@ class App
         */
        private function loadConfigFiles()
        {
-               $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.ini.php');
-               $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'settings.ini.php');
+               $this->loadConfigFile($this->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.ini.php');
+               $this->loadConfigFile($this->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'settings.ini.php');
 
                // Legacy .htconfig.php support
-               if (file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htpreconfig.php')) {
+               if (file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . '.htpreconfig.php')) {
                        $a = $this;
-                       include $this->basepath . DIRECTORY_SEPARATOR . '.htpreconfig.php';
+                       include $this->getBasePath() . DIRECTORY_SEPARATOR . '.htpreconfig.php';
                }
 
                // Legacy .htconfig.php support
-               if (file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
+               if (file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . '.htconfig.php')) {
                        $a = $this;
 
-                       include $this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php';
+                       include $this->getBasePath() . DIRECTORY_SEPARATOR . '.htconfig.php';
 
                        $this->setConfigValue('database', 'hostname', $db_host);
                        $this->setConfigValue('database', 'username', $db_user);
@@ -371,8 +438,8 @@ class App
                        }
                }
 
-               if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
-                       $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', true);
+               if (file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
+                       $this->loadConfigFile($this->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', true);
                }
        }
 
@@ -390,7 +457,7 @@ class App
         * INI;
         * // Keep this line
         *
-        * @param type $filepath
+        * @param string $filepath
         * @param bool $overwrite Force value overwrite if the config key already exists
         * @throws Exception
         */
@@ -431,8 +498,8 @@ class App
                Core\Addon::callHooks('load_config');
 
                // Load the local addon config file to overwritten default addon config values
-               if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php')) {
-                       $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php', true);
+               if (file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php')) {
+                       $this->loadConfigFile($this->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php', true);
                }
        }
 
@@ -460,69 +527,39 @@ class App
        /**
         * Figure out if we are running at the top of a domain or in a sub-directory and adjust accordingly
         */
-       private function determineUrlPath()
+       private function determineURLPath()
        {
-               $this->urlpath = $this->getConfigValue('system', 'urlpath');
+               /* Relative script path to the web server root
+                * Not all of those $_SERVER properties can be present, so we do by inverse priority order
+                */
+               $relative_script_path = '';
+               $relative_script_path = defaults($_SERVER, 'REDIRECT_URL'       , $relative_script_path);
+               $relative_script_path = defaults($_SERVER, 'REDIRECT_URI'       , $relative_script_path);
+               $relative_script_path = defaults($_SERVER, 'REDIRECT_SCRIPT_URL', $relative_script_path);
+               $relative_script_path = defaults($_SERVER, 'SCRIPT_URL'         , $relative_script_path);
+
+               $this->urlPath = $this->getConfigValue('system', 'urlpath');
 
-               /* SCRIPT_URL gives /path/to/friendica/module/parameter
+               /* $relative_script_path gives /relative/path/to/friendica/module/parameter
                 * QUERY_STRING gives pagename=module/parameter
                 *
-                * To get /path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
+                * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
                 */
-               if (!empty($_SERVER['SCRIPT_URL'])) {
+               if (!empty($relative_script_path)) {
                        // Module
                        if (!empty($_SERVER['QUERY_STRING'])) {
-                               $path = trim(dirname($_SERVER['SCRIPT_URL'], substr_count(trim($_SERVER['QUERY_STRING'], '/'), '/') + 1), '/');
+                               $path = trim(dirname($relative_script_path, substr_count(trim($_SERVER['QUERY_STRING'], '/'), '/') + 1), '/');
                        } else {
                                // Root page
-                               $path = trim($_SERVER['SCRIPT_URL'], '/');
+                               $path = trim($relative_script_path, '/');
                        }
 
-                       if ($path && $path != $this->urlpath) {
-                               $this->urlpath = $path;
+                       if ($path && $path != $this->urlPath) {
+                               $this->urlPath = $path;
                        }
                }
        }
 
-       /**
-        * Sets the App mode
-        *
-        * - App::MODE_INSTALL    : Either the database connection can't be established or the config table doesn't exist
-        * - App::MODE_MAINTENANCE: The maintenance mode has been set
-        * - App::MODE_NORMAL     : Normal run with all features enabled
-        *
-        * @return type
-        */
-       private function determineMode()
-       {
-               $this->mode = 0;
-
-               if (!file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')
-                       && !file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
-                       return;
-               }
-
-               $this->mode |= App::MODE_LOCALCONFIGPRESENT;
-
-               if (!DBA::connected()) {
-                       return;
-               }
-
-               $this->mode |= App::MODE_DBAVAILABLE;
-
-               if (DBA::fetchFirst("SHOW TABLES LIKE 'config'") === false) {
-                       return;
-               }
-
-               $this->mode |= App::MODE_DBCONFIGAVAILABLE;
-
-               if (Config::get('system', 'maintenance')) {
-                       return;
-               }
-
-               $this->mode |= App::MODE_MAINTENANCEDISABLED;
-       }
-
        public function loadDatabase()
        {
                if (DBA::connected()) {
@@ -559,17 +596,7 @@ class App
                DBA::connect($db_host, $db_user, $db_pass, $db_data, $charset);
                unset($db_host, $db_user, $db_pass, $db_data, $charset);
 
-               $this->save_timestamp($stamp1, 'network');
-       }
-
-       /**
-        * Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
-        *
-        * @return bool
-        */
-       public function isInstallMode()
-       {
-               return !($this->mode & App::MODE_LOCALCONFIGPRESENT) || !($this->mode & App::MODE_DBCONFIGAVAILABLE);
+               $this->saveTimestamp($stamp1, 'network');
        }
 
        /**
@@ -580,9 +607,9 @@ class App
         *
         * @return string
         */
-       public function get_basepath()
+       public function getBasePath()
        {
-               $basepath = $this->basepath;
+               $basepath = $this->basePath;
 
                if (!$basepath) {
                        $basepath = Config::get('system', 'basepath');
@@ -596,7 +623,7 @@ class App
                        $basepath = $_SERVER['PWD'];
                }
 
-               return self::realpath($basepath);
+               return self::getRealPath($basepath);
        }
 
        /**
@@ -609,7 +636,7 @@ class App
         * @param string $path The path that is about to be normalized
         * @return string normalized path - when possible
         */
-       public static function realpath($path)
+       public static function getRealPath($path)
        {
                $normalized = realpath($path);
 
@@ -620,7 +647,7 @@ class App
                }
        }
 
-       public function get_scheme()
+       public function getScheme()
        {
                return $this->scheme;
        }
@@ -639,7 +666,7 @@ class App
         * @param bool $ssl Whether to append http or https under SSL_POLICY_SELFSIGN
         * @return string Friendica server base URL
         */
-       public function get_baseurl($ssl = false)
+       public function getBaseURL($ssl = false)
        {
                $scheme = $this->scheme;
 
@@ -662,7 +689,7 @@ class App
                        $this->hostname = Config::get('config', 'hostname');
                }
 
-               return $scheme . '://' . $this->hostname . (!empty($this->urlpath) ? '/' . $this->urlpath : '' );
+               return $scheme . '://' . $this->hostname . (!empty($this->getURLPath()) ? '/' . $this->getURLPath() : '' );
        }
 
        /**
@@ -672,7 +699,7 @@ class App
         *
         * @param string $url
         */
-       public function set_baseurl($url)
+       public function setBaseURL($url)
        {
                $parsed = @parse_url($url);
                $hostname = '';
@@ -690,11 +717,11 @@ class App
                                $hostname .= ':' . $parsed['port'];
                        }
                        if (x($parsed, 'path')) {
-                               $this->urlpath = trim($parsed['path'], '\\/');
+                               $this->urlPath = trim($parsed['path'], '\\/');
                        }
 
-                       if (file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htpreconfig.php')) {
-                               include $this->basepath . DIRECTORY_SEPARATOR . '.htpreconfig.php';
+                       if (file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . '.htpreconfig.php')) {
+                               include $this->getBasePath() . DIRECTORY_SEPARATOR . '.htpreconfig.php';
                        }
 
                        if (Config::get('config', 'hostname') != '') {
@@ -707,7 +734,7 @@ class App
                }
        }
 
-       public function get_hostname()
+       public function getHostName()
        {
                if (Config::get('config', 'hostname') != '') {
                        $this->hostname = Config::get('config', 'hostname');
@@ -716,29 +743,39 @@ class App
                return $this->hostname;
        }
 
-       public function get_path()
+       public function getURLPath()
        {
-               return $this->urlpath;
+               return $this->urlPath;
        }
 
-       public function set_pager_total($n)
+       public function setPagerTotal($n)
        {
                $this->pager['total'] = intval($n);
        }
 
-       public function set_pager_itemspage($n)
+       public function setPagerItemsPage($n)
        {
                $this->pager['itemspage'] = ((intval($n) > 0) ? intval($n) : 0);
                $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
        }
 
-       public function set_pager_page($n)
+       public function setPagerPage($n)
        {
                $this->pager['page'] = $n;
                $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
        }
 
-       public function init_pagehead()
+       /**
+        * Initializes App->page['htmlhead'].
+        *
+        * Includes:
+        * - Page title
+        * - Favicons
+        * - Registered stylesheets (through App->registerStylesheet())
+        * - Infinite scroll data
+        * - head.tpl template
+        */
+       public function initHead()
        {
                $interval = ((local_user()) ? PConfig::get(local_user(), 'system', 'update_interval') : 40000);
 
@@ -759,24 +796,14 @@ class App
                        $this->page['title'] = $this->config['sitename'];
                }
 
-               /* put the head template at the beginning of page['htmlhead']
-                * since the code added by the modules frequently depends on it
-                * being first
-                */
-               if (!isset($this->page['htmlhead'])) {
-                       $this->page['htmlhead'] = '';
-               }
-
-               // If we're using Smarty, then doing replace_macros() will replace
-               // any unrecognized variables with a blank string. Since we delay
-               // replacing $stylesheet until later, we need to replace it now
-               // with another variable name
-               if ($this->theme['template_engine'] === 'smarty3') {
-                       $stylesheet = $this->get_template_ldelim('smarty3') . '$stylesheet' . $this->get_template_rdelim('smarty3');
+               if (!empty($this->theme['stylesheet'])) {
+                       $stylesheet = $this->theme['stylesheet'];
                } else {
-                       $stylesheet = '$stylesheet';
+                       $stylesheet = $this->getCurrentThemeStylesheetPath();
                }
 
+               $this->registerStylesheet($stylesheet);
+
                $shortcut_icon = Config::get('system', 'shortcut_icon');
                if ($shortcut_icon == '') {
                        $shortcut_icon = 'images/friendica-32.png';
@@ -788,11 +815,17 @@ class App
                }
 
                // get data wich is needed for infinite scroll on the network page
-               $invinite_scroll = infinite_scroll_data($this->module);
+               $infinite_scroll = infinite_scroll_data($this->module);
+
+               Core\Addon::callHooks('head', $this->page['htmlhead']);
 
                $tpl = get_markup_template('head.tpl');
+               /* put the head template at the beginning of page['htmlhead']
+                * since the code added by the modules frequently depends on it
+                * being first
+                */
                $this->page['htmlhead'] = replace_macros($tpl, [
-                       '$baseurl'         => $this->get_baseurl(),
+                       '$baseurl'         => $this->getBaseURL(),
                        '$local_user'      => local_user(),
                        '$generator'       => 'Friendica' . ' ' . FRIENDICA_VERSION,
                        '$delitem'         => L10n::t('Delete this item?'),
@@ -801,70 +834,75 @@ class App
                        '$update_interval' => $interval,
                        '$shortcut_icon'   => $shortcut_icon,
                        '$touch_icon'      => $touch_icon,
-                       '$stylesheet'      => $stylesheet,
-                       '$infinite_scroll' => $invinite_scroll,
+                       '$infinite_scroll' => $infinite_scroll,
                        '$block_public'    => intval(Config::get('system', 'block_public')),
+                       '$stylesheets'     => $this->stylesheets,
                ]) . $this->page['htmlhead'];
        }
 
-       public function init_page_end()
+       /**
+        * Initializes App->page['footer'].
+        *
+        * Includes:
+        * - Javascript homebase
+        * - Mobile toggle link
+        * - Registered footer scripts (through App->registerFooterScript())
+        * - footer.tpl template
+        */
+       public function initFooter()
        {
-               if (!isset($this->page['end'])) {
-                       $this->page['end'] = '';
+               // If you're just visiting, let javascript take you home
+               if (!empty($_SESSION['visitor_home'])) {
+                       $homebase = $_SESSION['visitor_home'];
+               } elseif (local_user()) {
+                       $homebase = 'profile/' . $this->user['nickname'];
                }
-               $tpl = get_markup_template('end.tpl');
-               $this->page['end'] = replace_macros($tpl, [
-                       '$baseurl' => $this->get_baseurl()
-               ]) . $this->page['end'];
-       }
-
-       public function set_curl_code($code)
-       {
-               $this->curl_code = $code;
-       }
 
-       public function get_curl_code()
-       {
-               return $this->curl_code;
-       }
-
-       public function set_curl_content_type($content_type)
-       {
-               $this->curl_content_type = $content_type;
-       }
+               if (isset($homebase)) {
+                       $this->page['footer'] .= '<script>var homebase="' . $homebase . '";</script>' . "\n";
+               }
 
-       public function get_curl_content_type()
-       {
-               return $this->curl_content_type;
-       }
+               /*
+                * Add a "toggle mobile" link if we're using a mobile device
+                */
+               if ($this->is_mobile || $this->is_tablet) {
+                       if (isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
+                               $link = 'toggle_mobile?address=' . curPageURL();
+                       } else {
+                               $link = 'toggle_mobile?off=1&address=' . curPageURL();
+                       }
+                       $this->page['footer'] .= replace_macros(get_markup_template("toggle_mobile_footer.tpl"), [
+                               '$toggle_link' => $link,
+                               '$toggle_text' => Core\L10n::t('toggle mobile')
+                       ]);
+               }
 
-       public function set_curl_headers($headers)
-       {
-               $this->curl_headers = $headers;
-       }
+               Core\Addon::callHooks('footer', $this->page['footer']);
 
-       public function get_curl_headers()
-       {
-               return $this->curl_headers;
+               $tpl = get_markup_template('footer.tpl');
+               $this->page['footer'] = replace_macros($tpl, [
+                       '$baseurl' => $this->getBaseURL(),
+                       '$footerScripts' => $this->footerScripts,
+               ]) . $this->page['footer'];
        }
 
        /**
         * @brief Removes the base url from an url. This avoids some mixed content problems.
         *
-        * @param string $orig_url
+        * @param string $origURL
         *
         * @return string The cleaned url
         */
-       public function remove_baseurl($orig_url)
+       public function removeBaseURL($origURL)
        {
                // Remove the hostname from the url if it is an internal link
-               $nurl = normalise_link($orig_url);
-               $base = normalise_link($this->get_baseurl());
+               $nurl = normalise_link($origURL);
+               $base = normalise_link($this->getBaseURL());
                $url = str_replace($base . '/', '', $nurl);
 
                // if it is an external link return the orignal value
-               if ($url == normalise_link($orig_url)) {
-                       return $orig_url;
+               if ($url == normalise_link($origURL)) {
+                       return $origURL;
                } else {
                        return $url;
                }
@@ -875,7 +913,7 @@ class App
         *
         * @param string $class
         */
-       private function register_template_engine($class)
+       private function registerTemplateEngine($class)
        {
                $v = get_class_vars($class);
                if (x($v, 'name')) {
@@ -895,7 +933,7 @@ class App
         *
         * @return object Template Engine instance
         */
-       public function template_engine()
+       public function getTemplateEngine()
        {
                $template_engine = 'smarty3';
                if (x($this->theme, 'template_engine')) {
@@ -920,35 +958,69 @@ class App
        /**
         * @brief Returns the active template engine.
         *
-        * @return string
+        * @return string the active template engine
         */
-       public function get_template_engine()
+       public function getActiveTemplateEngine()
        {
                return $this->theme['template_engine'];
        }
 
-       public function set_template_engine($engine = 'smarty3')
+       /**
+        * sets the active template engine
+        *
+        * @param string $engine the template engine (default is Smarty3)
+        */
+       public function setActiveTemplateEngine($engine = 'smarty3')
        {
                $this->theme['template_engine'] = $engine;
        }
 
-       public function get_template_ldelim($engine = 'smarty3')
+       /**
+        * Gets the right delimiter for a template engine
+        *
+        * Currently:
+        * Internal = ''
+        * Smarty3 = '{{'
+        *
+        * @param string $engine The template engine (default is Smarty3)
+        *
+        * @return string the right delimiter
+        */
+       public function getTemplateLeftDelimiter($engine = 'smarty3')
        {
                return $this->ldelim[$engine];
        }
 
-       public function get_template_rdelim($engine = 'smarty3')
+       /**
+        * Gets the left delimiter for a template engine
+        *
+        * Currently:
+        * Internal = ''
+        * Smarty3 = '}}'
+        *
+        * @param string $engine The template engine (default is Smarty3)
+        *
+        * @return string the left delimiter
+        */
+       public function getTemplateRightDelimiter($engine = 'smarty3')
        {
                return $this->rdelim[$engine];
        }
 
-       public function save_timestamp($stamp, $value)
+       /**
+        * Saves a timestamp for a value - f.e. a call
+        * Necessary for profiling Friendica
+        *
+        * @param int $timestamp the Timestamp
+        * @param string $value A value to profile
+        */
+       public function saveTimestamp($timestamp, $value)
        {
                if (!isset($this->config['system']['profiler']) || !$this->config['system']['profiler']) {
                        return;
                }
 
-               $duration = (float) (microtime(true) - $stamp);
+               $duration = (float) (microtime(true) - $timestamp);
 
                if (!isset($this->performance[$value])) {
                        // Prevent ugly E_NOTICE
@@ -968,19 +1040,41 @@ class App
                $this->callstack[$value][$callstack] += (float) $duration;
        }
 
-       public function get_useragent()
+       /**
+        * Returns the current UserAgent as a String
+        *
+        * @return string the UserAgent as a String
+        */
+       public function getUserAgent()
        {
                return
                        FRIENDICA_PLATFORM . " '" .
                        FRIENDICA_CODENAME . "' " .
                        FRIENDICA_VERSION . '-' .
                        DB_UPDATE_VERSION . '; ' .
-                       $this->get_baseurl();
+                       $this->getBaseURL();
        }
 
-       public function is_friendica_app()
+       /**
+        * Checks, if the call is from the Friendica App
+        *
+        * Reason:
+        * The friendica client has problems with the GUID in the notify. this is some workaround
+        */
+       private function checkFriendicaApp()
        {
-               return $this->is_friendica_app;
+               // Friendica-Client
+               $this->isFriendicaApp = isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'Apache-HttpClient/UNAVAILABLE (java 1.4)';
+       }
+
+       /**
+        *      Is the call via the Friendica app? (not a "normale" call)
+        *
+        * @return bool true if it's from the Friendica app
+        */
+       public function isFriendicaApp()
+       {
+               return $this->isFriendicaApp;
        }
 
        /**
@@ -989,10 +1083,10 @@ class App
         * This isn't a perfect solution. But we need this check very early.
         * So we cannot wait until the modules are loaded.
         *
-        * @return bool Is it a known backend?
+        * @param string $backend true, if the backend flag was set during App initialization
+        *
         */
-       public function is_backend()
-       {
+       private function checkBackend($backend) {
                static $backends = [
                        '_well_known',
                        'api',
@@ -1016,7 +1110,17 @@ class App
                ];
 
                // Check if current module is in backend or backend flag is set
-               return (in_array($this->module, $backends) || $this->backend);
+               $this->isBackend = (in_array($this->module, $backends) || $backend || $this->isBackend);
+       }
+
+       /**
+        * Returns true, if the call is from a backend node (f.e. from a worker)
+        *
+        * @return bool Is it a known backend?
+        */
+       public function isBackend()
+       {
+               return $this->isBackend;
        }
 
        /**
@@ -1064,7 +1168,7 @@ class App
         *
         * @return bool Is the memory limit reached?
         */
-       public function min_memory_reached()
+       public function isMinMemoryReached()
        {
                $min_memory = Config::get('system', 'min_memory', 0);
                if ($min_memory == 0) {
@@ -1110,7 +1214,7 @@ class App
         */
        public function isMaxLoadReached()
        {
-               if ($this->is_backend()) {
+               if ($this->isBackend()) {
                        $process = 'backend';
                        $maxsysload = intval(Config::get('system', 'maxloadavg'));
                        if ($maxsysload < 1) {
@@ -1124,7 +1228,7 @@ class App
                        }
                }
 
-               $load = current_load();
+               $load = System::currentLoad();
                if ($load) {
                        if (intval($load) > $maxsysload) {
                                logger('system: load ' . $load . ' for ' . $process . ' tasks (' . $maxsysload . ') too high.');
@@ -1159,14 +1263,14 @@ class App
                        }
                }
 
-               if ($this->min_memory_reached()) {
+               if ($this->isMinMemoryReached()) {
                        return;
                }
 
                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
-                       $resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->get_basepath());
+                       $resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->getBasePath());
                } else {
-                       $resource = proc_open($cmdline . ' &', [], $foo, $this->get_basepath());
+                       $resource = proc_open($cmdline . ' &', [], $foo, $this->getBasePath());
                }
                if (!is_resource($resource)) {
                        logger('We got no resource for command ' . $cmdline, LOGGER_DEBUG);
@@ -1182,7 +1286,7 @@ class App
         *
         * @return string system username
         */
-       private static function systemuser()
+       private static function getSystemUser()
        {
                if (!function_exists('posix_getpwuid') || !function_exists('posix_geteuid')) {
                        return '';
@@ -1197,7 +1301,7 @@ class App
         *
         * @return boolean the directory is usable
         */
-       public static function directory_usable($directory, $check_writable = true)
+       public static function isDirectoryUsable($directory, $check_writable = true)
        {
                if ($directory == '') {
                        logger('Directory is empty. This shouldn\'t happen.', LOGGER_DEBUG);
@@ -1205,22 +1309,22 @@ class App
                }
 
                if (!file_exists($directory)) {
-                       logger('Path "' . $directory . '" does not exist for user ' . self::systemuser(), LOGGER_DEBUG);
+                       logger('Path "' . $directory . '" does not exist for user ' . self::getSystemUser(), LOGGER_DEBUG);
                        return false;
                }
 
                if (is_file($directory)) {
-                       logger('Path "' . $directory . '" is a file for user ' . self::systemuser(), LOGGER_DEBUG);
+                       logger('Path "' . $directory . '" is a file for user ' . self::getSystemUser(), LOGGER_DEBUG);
                        return false;
                }
 
                if (!is_dir($directory)) {
-                       logger('Path "' . $directory . '" is not a directory for user ' . self::systemuser(), LOGGER_DEBUG);
+                       logger('Path "' . $directory . '" is not a directory for user ' . self::getSystemUser(), LOGGER_DEBUG);
                        return false;
                }
 
                if ($check_writable && !is_writable($directory)) {
-                       logger('Path "' . $directory . '" is not writable for user ' . self::systemuser(), LOGGER_DEBUG);
+                       logger('Path "' . $directory . '" is not writable for user ' . self::getSystemUser(), LOGGER_DEBUG);
                        return false;
                }
 
@@ -1231,6 +1335,8 @@ class App
         * @param string $cat     Config category
         * @param string $k       Config key
         * @param mixed  $default Default value if it isn't set
+        *
+        * @return string Returns the value of the Config entry
         */
        public function getConfigValue($cat, $k, $default = null)
        {
@@ -1313,6 +1419,8 @@ class App
         * @param string $cat     Config category
         * @param string $k       Config key
         * @param mixed  $default Default value if key isn't set
+        *
+        * @return string The value of the config entry
         */
        public function getPConfigValue($uid, $cat, $k, $default = null)
        {
@@ -1374,7 +1482,7 @@ class App
        {
                $sender_email = Config::get('config', 'sender_email');
                if (empty($sender_email)) {
-                       $hostname = $this->get_hostname();
+                       $hostname = $this->getHostName();
                        if (strpos($hostname, ':')) {
                                $hostname = substr($hostname, 0, strpos($hostname, ':'));
                        }
@@ -1388,11 +1496,11 @@ class App
        /**
         * Returns the current theme name.
         *
-        * @return string
+        * @return string the name of the current theme
         */
        public function getCurrentTheme()
        {
-               if ($this->isInstallMode()) {
+               if ($this->getMode()->isInstall()) {
                        return '';
                }
 
@@ -1401,7 +1509,7 @@ class App
                /// https://github.com/friendica/friendica/issues/5092)
                $this->computeCurrentTheme();
 
-               return $this->current_theme;
+               return $this->currentTheme;
        }
 
        /**
@@ -1417,7 +1525,7 @@ class App
                }
 
                // Sane default
-               $this->current_theme = $system_theme;
+               $this->currentTheme = $system_theme;
 
                $allowed_themes = explode(',', Config::get('system', 'allowed_themes', $system_theme));
 
@@ -1456,7 +1564,7 @@ class App
                        && (file_exists('view/theme/' . $theme_name . '/style.css')
                        || file_exists('view/theme/' . $theme_name . '/style.php'))
                ) {
-                       $this->current_theme = $theme_name;
+                       $this->currentTheme = $theme_name;
                }
        }
 
@@ -1471,4 +1579,32 @@ class App
        {
                return Core\Theme::getStylesheetPath($this->getCurrentTheme());
        }
+
+       /**
+        * Check if request was an AJAX (xmlhttprequest) request.
+        *
+        * @return boolean true if it was an AJAX request
+        */
+       public function isAjax()
+       {
+               return $this->isAjax;
+       }
+
+       /**
+        * Returns the value of a argv key
+        * TODO there are a lot of $a->argv usages in combination with defaults() which can be replaced with this method
+        *
+        * @param int $position the position of the argument
+        * @param mixed $default the default value if not found
+        *
+        * @return mixed returns the value of the argument
+        */
+       public function getArgumentValue($position, $default = '')
+       {
+               if (array_key_exists($position, $this->argv)) {
+                       return $this->argv[$position];
+               }
+
+               return $default;
+       }
 }
diff --git a/src/App/Mode.php b/src/App/Mode.php
new file mode 100644 (file)
index 0000000..d9f5cdb
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+
+namespace Friendica\App;
+
+use Friendica\Core\Config;
+use Friendica\Database\DBA;
+
+/**
+ * Mode of the current Friendica Node
+ *
+ * @package Friendica\App
+ */
+class Mode
+{
+       const LOCALCONFIGPRESENT = 1;
+       const DBAVAILABLE = 2;
+       const DBCONFIGAVAILABLE = 4;
+       const MAINTENANCEDISABLED = 8;
+
+       /***
+        * @var int the mode of this Application
+        *
+        */
+       private $mode;
+
+       /**
+        * @var string the basepath of the application
+        */
+       private $basepath;
+
+       public function __construct($basepath = '')
+       {
+               $this->basepath = $basepath;
+               $this->mode = 0;
+       }
+
+       /**
+        * Sets the App mode
+        *
+        * - App::MODE_INSTALL    : Either the database connection can't be established or the config table doesn't exist
+        * - App::MODE_MAINTENANCE: The maintenance mode has been set
+        * - App::MODE_NORMAL     : Normal run with all features enabled
+        *
+        * @param string $basepath the Basepath of the Application
+        *
+        */
+       public function determine($basepath = null)
+       {
+               if (!empty($basepath)) {
+                       $this->basepath = $basepath;
+               }
+
+               $this->mode = 0;
+
+               if (!file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')
+                       && !file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
+                       return;
+               }
+
+               $this->mode |= Mode::LOCALCONFIGPRESENT;
+
+               if (!DBA::connected()) {
+                       return;
+               }
+
+               $this->mode |= Mode::DBAVAILABLE;
+
+               if (DBA::fetchFirst("SHOW TABLES LIKE 'config'") === false) {
+                       return;
+               }
+
+               $this->mode |= Mode::DBCONFIGAVAILABLE;
+
+               if (Config::get('system', 'maintenance')) {
+                       return;
+               }
+
+               $this->mode |= Mode::MAINTENANCEDISABLED;
+       }
+
+       /**
+        * Checks, if the Friendica Node has the given mode
+        *
+        * @param int $mode A mode to test
+        *
+        * @return bool returns true, if the mode is set
+        */
+       public function has($mode)
+       {
+               return ($this->mode & $mode) > 0;
+       }
+
+
+       /**
+        * Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
+        *
+        * @return bool
+        */
+       public function isInstall()
+       {
+               return !$this->has(Mode::LOCALCONFIGPRESENT) ||
+                       !$this->has(MODE::DBCONFIGAVAILABLE);
+       }
+
+       /**
+        * Normal mode is when the local config file is set, the DB schema is installed and the maintenance mode is off.
+        *
+        * @return bool
+        */
+       public function isNormal()
+       {
+               return $this->has(Mode::LOCALCONFIGPRESENT) &&
+                       $this->has(Mode::DBAVAILABLE) &&
+                       $this->has(Mode::DBCONFIGAVAILABLE) &&
+                       $this->has(Mode::MAINTENANCEDISABLED);
+       }
+}
index 3ad4a4f055a7be33ebba9b3a1dfe42556ca7f11c..1da9397a7833da42e8ab778f8268544c02344f17 100644 (file)
@@ -21,7 +21,16 @@ abstract class BaseModule extends BaseObject
         */
        public static function init()
        {
+       }
 
+       /**
+        * @brief Module GET method to display raw content from technical endpoints
+        *
+        * Extend this method if the module is supposed to return communication data,
+        * e.g. from protocol implementations.
+        */
+       public static function rawContent()
+       {
        }
 
        /**
index d5efecb8060d420564ea2020417fd70cb5432ed8..298f2512edf349f5089556f9dfcc1dadc7e9c7ff 100644 (file)
@@ -7,7 +7,9 @@ namespace Friendica\Content;
 use Friendica\Core\Addon;
 use Friendica\Core\L10n;
 use Friendica\Core\Protocol;
+use Friendica\Core\System;
 use Friendica\Database\DBA;
+use Friendica\Util\Network;
 
 /**
  * @brief ContactSelector class
@@ -68,28 +70,29 @@ class ContactSelector
        }
 
        /**
-        * @param string $s       network
+        * @param string $network network
         * @param string $profile optional, default empty
         * @return string
         */
-       public static function networkToName($s, $profile = "")
+       public static function networkToName($network, $profile = "")
        {
                $nets = [
-                       Protocol::DFRN      => L10n::t('Friendica'),
-                       Protocol::OSTATUS   => L10n::t('OStatus'),
-                       Protocol::FEED      => L10n::t('RSS/Atom'),
-                       Protocol::MAIL      => L10n::t('Email'),
-                       Protocol::DIASPORA  => L10n::t('Diaspora'),
-                       Protocol::ZOT       => L10n::t('Zot!'),
-                       Protocol::LINKEDIN  => L10n::t('LinkedIn'),
-                       Protocol::XMPP      => L10n::t('XMPP/IM'),
-                       Protocol::MYSPACE   => L10n::t('MySpace'),
-                       Protocol::GPLUS     => L10n::t('Google+'),
-                       Protocol::PUMPIO    => L10n::t('pump.io'),
-                       Protocol::TWITTER   => L10n::t('Twitter'),
-                       Protocol::DIASPORA2 => L10n::t('Diaspora Connector'),
-                       Protocol::STATUSNET => L10n::t('GNU Social Connector'),
-                       Protocol::PNUT      => L10n::t('pnut'),
+                       Protocol::DFRN      =>   L10n::t('Friendica'),
+                       Protocol::OSTATUS   =>   L10n::t('OStatus'),
+                       Protocol::FEED      =>   L10n::t('RSS/Atom'),
+                       Protocol::MAIL      =>   L10n::t('Email'),
+                       Protocol::DIASPORA  =>   L10n::t('Diaspora'),
+                       Protocol::ZOT       =>   L10n::t('Zot!'),
+                       Protocol::LINKEDIN  =>   L10n::t('LinkedIn'),
+                       Protocol::XMPP      =>   L10n::t('XMPP/IM'),
+                       Protocol::MYSPACE   =>   L10n::t('MySpace'),
+                       Protocol::GPLUS     =>   L10n::t('Google+'),
+                       Protocol::PUMPIO    =>   L10n::t('pump.io'),
+                       Protocol::TWITTER   =>   L10n::t('Twitter'),
+                       Protocol::DIASPORA2 =>   L10n::t('Diaspora Connector'),
+                       Protocol::STATUSNET =>   L10n::t('GNU Social Connector'),
+                       Protocol::ACTIVITYPUB => L10n::t('ActivityPub'),
+                       Protocol::PNUT      =>   L10n::t('pnut'),
                ];
 
                Addon::callHooks('network_to_name', $nets);
@@ -97,15 +100,37 @@ class ContactSelector
                $search  = array_keys($nets);
                $replace = array_values($nets);
 
-               $networkname = str_replace($search, $replace, $s);
+               $networkname = str_replace($search, $replace, $network);
 
-               if ((in_array($s, [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) && ($profile != "")) {
-                       $r = DBA::fetchFirst("SELECT `gserver`.`platform` FROM `gcontact`
-                                       INNER JOIN `gserver` ON `gserver`.`nurl` = `gcontact`.`server_url`
-                                       WHERE `gcontact`.`nurl` = ? AND `platform` != ''", normalise_link($profile));
+               if ((in_array($network, [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) && ($profile != "")) {
+                       // Create the server url out of the profile url
+                       $parts = parse_url($profile);
+                       unset($parts['path']);
+                       $server_url = [normalise_link(Network::unparseURL($parts))];
 
-                       if (DBA::isResult($r)) {
-                               $networkname = $r['platform'];
+                       // Fetch the server url
+                       $gcontact = DBA::selectFirst('gcontact', ['server_url'], ['nurl' => normalise_link($profile)]);
+                       if (!empty($gcontact) && !empty($gcontact['server_url'])) {
+                               $server_url[] = normalise_link($gcontact['server_url']);
+                       }
+
+                       // Now query the GServer for the platform name
+                       $gserver = DBA::selectFirst('gserver', ['platform', 'network'], ['nurl' => $server_url]);
+
+                       if (DBA::isResult($gserver)) {
+                               if (!empty($gserver['platform'])) {
+                                       $platform = $gserver['platform'];
+                               } elseif (!empty($gserver['network']) && ($gserver['network'] != Protocol::ACTIVITYPUB)) {
+                                       $platform = self::networkToName($gserver['network']);
+                               }
+
+                               if (!empty($platform)) {
+                                       $networkname = $platform;
+
+                                       if ($network == Protocol::ACTIVITYPUB) {
+                                               $networkname .= ' (AP)';
+                                       }
+                               }
                        }
                }
 
index 99decc92bb2e645dbade209f754626ef02cd1056..7a1a149a2fffd0a88540da451ee37be1f4daa18e 100644 (file)
@@ -107,7 +107,7 @@ class Nav
                        // user info
                        $contact = DBA::selectFirst('contact', ['micro'], ['uid' => $a->user['uid'], 'self' => true]);
                        $userinfo = [
-                               'icon' => (DBA::isResult($contact) ? $a->remove_baseurl($contact['micro']) : 'images/person-48.jpg'),
+                               'icon' => (DBA::isResult($contact) ? $a->removeBaseURL($contact['micro']) : 'images/person-48.jpg'),
                                'name' => $a->user['username'],
                        ];
                } else {
index c3453bcf727bda8baf6f51517838e4403e7d43a6..c903ee6945790fcd96e85c476af168c4ff124c91 100644 (file)
@@ -1060,11 +1060,11 @@ class BBCode extends BaseObject
                        $ch = @curl_init($match[1]);
                        @curl_setopt($ch, CURLOPT_NOBODY, true);
                        @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-                       @curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+                       @curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
                        @curl_exec($ch);
                        $curl_info = @curl_getinfo($ch);
 
-                       $a->save_timestamp($stamp1, "network");
+                       $a->saveTimestamp($stamp1, "network");
 
                        if (substr($curl_info["content_type"], 0, 6) == "image/") {
                                $text = "[url=" . $match[1] . "]" . $match[1] . "[/url]";
@@ -1119,11 +1119,11 @@ class BBCode extends BaseObject
                        $ch = @curl_init($match[1]);
                        @curl_setopt($ch, CURLOPT_NOBODY, true);
                        @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-                       @curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+                       @curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
                        @curl_exec($ch);
                        $curl_info = @curl_getinfo($ch);
 
-                       $a->save_timestamp($stamp1, "network");
+                       $a->saveTimestamp($stamp1, "network");
 
                        // if its a link to a picture then embed this picture
                        if (substr($curl_info["content_type"], 0, 6) == "image/") {
@@ -1265,9 +1265,6 @@ class BBCode extends BaseObject
                $text = preg_replace("/\s?\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "[share$1]$2[/share]", $text);
                $text = preg_replace("/\s?\[quote(.*?)\]\s?(.*?)\s?\[\/quote\]\s?/ism", "[quote$1]$2[/quote]", $text);
 
-               $text = preg_replace("/\n\[code\]/ism", "[code]", $text);
-               $text = preg_replace("/\[\/code\]\n/ism", "[/code]", $text);
-
                // when the content is meant exporting to other systems then remove the avatar picture since this doesn't really look good on these systems
                if (!$try_oembed) {
                        $text = preg_replace("/\[share(.*?)avatar\s?=\s?'.*?'\s?(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "\n[share$1$2]$3[/share]", $text);
@@ -1717,18 +1714,6 @@ class BBCode extends BaseObject
                        $text = Smilies::replace($text, false, true);
                }
 
-               // Replace inline code blocks
-               $text = preg_replace_callback("|(?!<br[^>]*>)<code>([^<]*)</code>(?!<br[^>]*>)|ism",
-                       function ($match) use ($simple_html) {
-                               $return = '<key>' . $match[1] . '</key>';
-                               // Use <code> for Diaspora inline code blocks
-                               if ($simple_html === 3) {
-                                       $return = '<code>' . $match[1] . '</code>';
-                               }
-                               return $return;
-                       }
-               , $text);
-
                // Unhide all [noparse] contained bbtags unspacefying them
                // and triming the [noparse] tag.
 
@@ -1946,7 +1931,7 @@ class BBCode extends BaseObject
                // unmask the special chars back to HTML
                $text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['&lt;', '&gt;', '&amp;'], $text);
 
-               $a->save_timestamp($stamp1, "parser");
+               $a->saveTimestamp($stamp1, "parser");
 
                // Libertree has a problem with escaped hashtags.
                $text = str_replace(['\#'], ['#'], $text);
index 0687b5377b0e82bf408251bcecdc7562d2deb652..2289bee869ee5ca42b885eea7b0defb903ab974d 100644 (file)
@@ -35,7 +35,7 @@ class Markdown extends BaseObject
                $MarkdownParser->code_class_prefix = 'language-';
                $html = $MarkdownParser->transform($text);
 
-               self::getApp()->save_timestamp($stamp1, "parser");
+               self::getApp()->saveTimestamp($stamp1, "parser");
 
                return $html;
        }
index f245f0d95e064819b1b6d4ae4a37cc4540f07a72..faba55b7a860b483e28022e98909d85eaa2cb899 100644 (file)
@@ -142,10 +142,7 @@ class Widget
 
                $nets = array();
                while ($rr = DBA::fetch($r)) {
-                       /// @TODO If 'network' is not there, this triggers an E_NOTICE
-                       if ($rr['network']) {
-                               $nets[] = array('ref' => $rr['network'], 'name' => ContactSelector::networkToName($rr['network']), 'selected' => (($selected == $rr['network']) ? 'selected' : '' ));
-                       }
+                       $nets[] = array('ref' => $rr['network'], 'name' => ContactSelector::networkToName($rr['network']), 'selected' => (($selected == $rr['network']) ? 'selected' : '' ));
                }
                DBA::close($r);
 
index ffe11363f573f0006043a7716f899386ef4045f2..8f630409ff5da42e6aad7d8f228adbe52aea6637 100644 (file)
@@ -51,14 +51,14 @@ class ACL extends BaseObject
                                break;
 
                        case 'PRIVATE':
-                               $networks = [Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA];
+                               $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA];
                                break;
 
                        case 'TWO_WAY':
                                if (!empty($a->user['prvnets'])) {
-                                       $networks = [Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA];
+                                       $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA];
                                } else {
-                                       $networks = [Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA, Protocol::OSTATUS];
+                                       $networks = [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA, Protocol::OSTATUS];
                                }
                                break;
 
@@ -344,9 +344,9 @@ class ACL extends BaseObject
                        $a = self::getApp();
                        $p = $a->pager['page'] != 1 ? '&p=' . $a->pager['page'] : '';
 
-                       $response = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
-                       if ($response['success']) {
-                               $lsearch = json_decode($response['body'], true);
+                       $curlResult = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
+                       if ($curlResult->isSuccess()) {
+                               $lsearch = json_decode($curlResult->getBody(), true);
                                if (!empty($lsearch['results'])) {
                                        $return = $lsearch['results'];
                                }
index 4c20c96ad4705546ed0ab6c429c0e64351a74f9b..d2f89ce279de91867fe1edf9de53c3a8c8514620 100644 (file)
@@ -5,6 +5,7 @@
 namespace Friendica\Core;
 
 use Friendica\App;
+use Friendica\BaseObject;
 use Friendica\Database\DBA;
 
 require_once 'include/dba.php';
@@ -12,8 +13,65 @@ require_once 'include/dba.php';
 /**
  * Some functions to handle addons
  */
-class Addon
+class Addon extends BaseObject
 {
+       /**
+        * @brief Synchronise addons:
+        *
+        * system.addon contains a comma-separated list of names
+        * of addons which are used on this system.
+        * Go through the database list of already installed addons, and if we have
+        * an entry, but it isn't in the config list, call the uninstall procedure
+        * and mark it uninstalled in the database (for now we'll remove it).
+        * Then go through the config list and if we have a addon that isn't installed,
+        * call the install procedure and add it to the database.
+        *
+        */
+       public static function check()
+       {
+               $a = self::getApp();
+
+               $r = DBA::select('addon', [], ['installed' => 1]);
+               if (DBA::isResult($r)) {
+                       $installed = DBA::toArray($r);
+               } else {
+                       $installed = [];
+               }
+
+               $addons = Config::get('system', 'addon');
+               $addons_arr = [];
+
+               if ($addons) {
+                       $addons_arr = explode(',', str_replace(' ', '', $addons));
+               }
+
+               $a->addons = $addons_arr;
+
+               $installed_arr = [];
+
+               if (count($installed)) {
+                       foreach ($installed as $i) {
+                               if (!in_array($i['name'], $addons_arr)) {
+                                       self::uninstall($i['name']);
+                               } else {
+                                       $installed_arr[] = $i['name'];
+                               }
+                       }
+               }
+
+               if (count($addons_arr)) {
+                       foreach ($addons_arr as $p) {
+                               if (!in_array($p, $installed_arr)) {
+                                       self::install($p);
+                               }
+                       }
+               }
+
+               self::loadHooks();
+
+               return;
+       }
+
        /**
         * @brief uninstalls an addon.
         *
@@ -139,7 +197,7 @@ class Addon
         */
        public static function registerHook($hook, $file, $function, $priority = 0)
        {
-               $file = str_replace(get_app()->get_basepath() . DIRECTORY_SEPARATOR, '', $file);
+               $file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
 
                $condition = ['hook' => $hook, 'file' => $file, 'function' => $function];
                $exists = DBA::exists('hook', $condition);
@@ -162,7 +220,7 @@ class Addon
         */
        public static function unregisterHook($hook, $file, $function)
        {
-               $relative_file = str_replace(get_app()->get_basepath() . DIRECTORY_SEPARATOR, '', $file);
+               $relative_file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
 
                // This here is only needed for fixing a problem that existed on the develop branch
                $condition = ['hook' => $hook, 'file' => $file, 'function' => $function];
@@ -178,7 +236,7 @@ class Addon
         */
        public static function loadHooks()
        {
-               $a = get_app();
+               $a = self::getApp();
                $a->hooks = [];
                $r = DBA::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]);
 
@@ -201,7 +259,7 @@ class Addon
         */
        public static function forkHooks($priority, $name, $data = null)
        {
-               $a = get_app();
+               $a = self::getApp();
 
                if (is_array($a->hooks) && array_key_exists($name, $a->hooks)) {
                        foreach ($a->hooks[$name] as $hook) {
@@ -221,7 +279,7 @@ class Addon
         */
        public static function callHooks($name, &$data = null)
        {
-               $a = get_app();
+               $a = self::getApp();
 
                if (is_array($a->hooks) && array_key_exists($name, $a->hooks)) {
                        foreach ($a->hooks[$name] as $hook) {
@@ -262,7 +320,7 @@ class Addon
         */
        public static function isApp($name)
        {
-               $a = get_app();
+               $a = self::getApp();
 
                if (is_array($a->hooks) && (array_key_exists('app_menu', $a->hooks))) {
                        foreach ($a->hooks['app_menu'] as $hook) {
@@ -293,7 +351,7 @@ class Addon
         */
        public static function getInfo($addon)
        {
-               $a = get_app();
+               $a = self::getApp();
 
                $info = [
                        'name' => $addon,
@@ -310,7 +368,7 @@ class Addon
 
                $stamp1 = microtime(true);
                $f = file_get_contents("addon/$addon/$addon.php");
-               $a->save_timestamp($stamp1, "file");
+               $a->saveTimestamp($stamp1, "file");
 
                $r = preg_match("|/\*.*\*/|msU", $f, $m);
 
index cc77d9bfd0dc7e35598130af672287454ffdd25c..0fb328aaee8368f86c3e1ec3fbbc2853e453592e 100644 (file)
@@ -23,13 +23,15 @@ class Cache extends \Friendica\BaseObject
        /**
         * @var Cache\ICacheDriver
         */
-       private static $driver = null;
+       private static $driver       = null;
+       public  static $driver_class = null;
+       public  static $driver_name  = null;
 
        public static function init()
        {
-               $driver_name = Config::get('system', 'cache_driver', 'database');
-
-               self::$driver = CacheDriverFactory::create($driver_name);
+               self::$driver_name  = Config::get('system', 'cache_driver', 'database');
+               self::$driver       = CacheDriverFactory::create(self::$driver_name);
+               self::$driver_class = get_class(self::$driver);
        }
 
        /**
@@ -46,6 +48,24 @@ class Cache extends \Friendica\BaseObject
                return self::$driver;
        }
 
+       /**
+        * @brief Returns all the cache keys sorted alphabetically
+        *
+        * @param string $prefix Prefix of the keys (optional)
+        *
+        * @return array Empty if the driver doesn't support this feature
+        */
+       public static function getAllKeys($prefix = null)
+       {
+               $time = microtime(true);
+
+               $return = self::getDriver()->getAllKeys($prefix);
+
+               self::getApp()->saveTimestamp($time, 'cache');
+
+               return $return;
+       }
+
        /**
         * @brief Fetch cached data according to the key
         *
@@ -59,7 +79,7 @@ class Cache extends \Friendica\BaseObject
 
                $return = self::getDriver()->get($key);
 
-               self::getApp()->save_timestamp($time, 'cache');
+               self::getApp()->saveTimestamp($time, 'cache');
 
                return $return;
        }
@@ -81,7 +101,7 @@ class Cache extends \Friendica\BaseObject
 
                $return = self::getDriver()->set($key, $value, $duration);
 
-               self::getApp()->save_timestamp($time, 'cache_write');
+               self::getApp()->saveTimestamp($time, 'cache_write');
 
                return $return;
        }
@@ -99,7 +119,7 @@ class Cache extends \Friendica\BaseObject
 
                $return = self::getDriver()->delete($key);
 
-               self::getApp()->save_timestamp($time, 'cache_write');
+               self::getApp()->saveTimestamp($time, 'cache_write');
 
                return $return;
        }
@@ -107,12 +127,12 @@ class Cache extends \Friendica\BaseObject
        /**
         * @brief Remove outdated data from the cache
         *
-        * @param integer $max_level The maximum cache level that is to be cleared
+        * @param boolean $outdated just remove outdated values
         *
         * @return void
         */
-       public static function clear()
+       public static function clear($outdated = true)
        {
-               return self::getDriver()->clear();
+               return self::getDriver()->clear($outdated);
        }
 }
index 15b822dc3b519f8e0fac9412429991a1f06384f7..c2628551ef47be5dee31908af0b883e0520a37e4 100644 (file)
@@ -17,8 +17,56 @@ abstract class AbstractCacheDriver extends BaseObject
         * @param string $key   The original key
         * @return string               The cache key used for the cache
         */
-       protected function getCacheKey($key) {
+       protected function getCacheKey($key)
+       {
                // We fetch with the hostname as key to avoid problems with other applications
-               return self::getApp()->get_hostname() . ":" . $key;
+               return self::getApp()->getHostName() . ":" . $key;
+       }
+
+       /**
+        * @param array $keys   A list of cached keys
+        * @return array        A list of original keys
+        */
+       protected function getOriginalKeys($keys)
+       {
+               if (empty($keys)) {
+                       return [];
+               } else {
+                       // Keys are prefixed with the node hostname, let's remove it
+                       array_walk($keys, function (&$value) {
+                               $value = preg_replace('/^' . self::getApp()->getHostName() . ':/', '', $value);
+                       });
+
+                       sort($keys);
+
+                       return $keys;
+               }
+       }
+
+       /**
+        * Filters the keys of an array with a given prefix
+        * Returns the filtered keys as an new array
+        *
+        * @param array $array The array, which should get filtered
+        * @param string|null $prefix The prefix (if null, all keys will get returned)
+        *
+        * @return array The filtered array with just the keys
+        */
+       protected function filterArrayKeysByPrefix($array, $prefix = null)
+       {
+               if (empty($prefix)) {
+                       return array_keys($array);
+               } else {
+                       $result = [];
+
+                       foreach (array_keys($array) as $key) {
+                               if (strpos($key, $prefix) === 0) {
+                                       array_push($result, $key);
+                               }
+                       }
+
+                       return $result;
+               }
+
        }
 }
index d1302c1d6ec327d5f04a0a570b58c4da747954b5..a99b05788f64e75e46d5d8e4df8c230bdcf6c414 100644 (file)
@@ -19,6 +19,14 @@ class ArrayCache extends AbstractCacheDriver implements IMemoryCacheDriver
        /** @var array Array with the cached data */
        protected $cachedData = array();
 
+       /**
+        * (@inheritdoc)
+        */
+       public function getAllKeys($prefix = null)
+       {
+               return $this->filterArrayKeysByPrefix($this->cachedData, $prefix);
+       }
+
        /**
         * (@inheritdoc)
         */
index ca4842a4686db98247fa41fb19bf06da3ffa11de..d90c6e4f18180f6777a316dbe1cf2d70249ce85f 100644 (file)
@@ -13,6 +13,31 @@ use Friendica\Util\DateTimeFormat;
  */
 class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver
 {
+       /**
+        * (@inheritdoc)
+        */
+       public function getAllKeys($prefix = null)
+       {
+               if (empty($prefix)) {
+                       $where = ['`expires` >= ?', DateTimeFormat::utcNow()];
+               } else {
+                       $where = ['`expires` >= ? AND `k` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix];
+               }
+
+               $stmt = DBA::select('cache', ['k'], $where);
+
+               $keys = [];
+               while ($key = DBA::fetch($stmt)) {
+                       array_push($keys, $key['k']);
+               }
+               DBA::close($stmt);
+
+               return $keys;
+       }
+
+       /**
+        * (@inheritdoc)
+        */
        public function get($key)
        {
                $cache = DBA::selectFirst('cache', ['v'], ['`k` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
@@ -32,6 +57,9 @@ class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver
                return null;
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function set($key, $value, $ttl = Cache::FIVE_MINUTES)
        {
                $fields = [
@@ -43,11 +71,17 @@ class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver
                return DBA::update('cache', $fields, ['k' => $key], true);
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function delete($key)
        {
                return DBA::delete('cache', ['k' => $key]);
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function clear($outdated = true)
        {
                if ($outdated) {
index 9ddcf5ad1fe8d530c44bb6ca628e813d1b147fb2..2c04c5992578588611fd08fdefc1dd0d0ffb87f6 100644 (file)
@@ -11,6 +11,15 @@ use Friendica\Core\Cache;
  */
 interface ICacheDriver
 {
+       /**
+        * Lists all cache keys
+        *
+        * @param string prefix optional a prefix to search
+        *
+        * @return array Empty if it isn't supported by the cache driver
+        */
+       public function getAllKeys($prefix = null);
+
        /**
         * Fetches cached data according to the key
         *
index 4ca5aa38db066c3ed35c2a0b5ac132eeb8f30620..fd928c6fcc15ed2a5245f2bca27c664a6f696531 100644 (file)
@@ -22,6 +22,11 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri
         */
        private $memcache;
 
+       /**
+        * @param string $memcache_host
+        * @param int    $memcache_port
+        * @throws Exception
+        */
        public function __construct($memcache_host, $memcache_port)
        {
                if (!class_exists('Memcache', false)) {
@@ -35,6 +40,30 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri
                }
        }
 
+       /**
+        * (@inheritdoc)
+        */
+       public function getAllKeys($prefix = null)
+       {
+               $keys = [];
+               $allSlabs = $this->memcache->getExtendedStats('slabs');
+               foreach ($allSlabs as $slabs) {
+                       foreach (array_keys($slabs) as $slabId) {
+                               $cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId);
+                               foreach ($cachedump as $key => $arrVal) {
+                                       if (!is_array($arrVal)) {
+                                               continue;
+                                       }
+                                       $keys = array_merge($keys, array_keys($arrVal));
+                               }
+                       }
+               }
+
+               $keys = $this->getOriginalKeys($keys);
+
+               return $this->filterArrayKeysByPrefix($keys, $prefix);
+       }
+
        /**
         * (@inheritdoc)
         */
index 9e9c00f0b89f25f9ffbc943ccce6aa7f4673dec2..1a6b2a9aefbfa7d25e9d7369fe6e77b8147e1a91 100644 (file)
@@ -5,6 +5,7 @@ namespace Friendica\Core\Cache;
 use Friendica\Core\Cache;
 
 use Exception;
+use Friendica\Network\HTTPException\InternalServerErrorException;
 use Memcached;
 
 /**
@@ -53,6 +54,24 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
                }
        }
 
+       /**
+        * (@inheritdoc)
+        */
+       public function getAllKeys($prefix = null)
+       {
+               $keys = $this->getOriginalKeys($this->memcached->getAllKeys());
+
+               if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) {
+                       return $this->filterArrayKeysByPrefix($keys, $prefix);
+               } else {
+                       logger('Memcached \'getAllKeys\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL);
+                       return [];
+               }
+       }
+
+       /**
+        * (@inheritdoc)
+        */
        public function get($key)
        {
                $return = null;
@@ -63,11 +82,16 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
 
                if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) {
                        $return = $value;
+               } else {
+                       logger('Memcached \'get\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL);
                }
 
                return $return;
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function set($key, $value, $ttl = Cache::FIVE_MINUTES)
        {
                $cachekey = $this->getCacheKey($key);
@@ -85,15 +109,20 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
                                $value
                        );
                }
-
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function delete($key)
        {
                $cachekey = $this->getCacheKey($key);
                return $this->memcached->delete($cachekey);
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function clear($outdated = true)
        {
                if ($outdated) {
@@ -104,12 +133,7 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr
        }
 
        /**
-        * @brief Sets a value if it's not already stored
-        *
-        * @param string $key      The cache key
-        * @param mixed  $value    The old value we know from the cache
-        * @param int    $ttl      The cache lifespan, must be one of the Cache constants
-        * @return bool
+        * (@inheritdoc)
         */
        public function add($key, $value, $ttl = Cache::FIVE_MINUTES)
        {
index 2c2a3e5d7cb27a99bc896f8816f8ed5571efc475..fcbfab548a6b2bfba0e74e150a7d7b5f505dd9e1 100644 (file)
@@ -20,6 +20,11 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
         */
        private $redis;
 
+       /**
+        * @param string $redis_host
+        * @param int    $redis_port
+        * @throws Exception
+        */
        public function __construct($redis_host, $redis_port)
        {
                if (!class_exists('Redis', false)) {
@@ -33,6 +38,25 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
                }
        }
 
+       /**
+        * (@inheritdoc)
+        */
+       public function getAllKeys($prefix = null)
+       {
+               if (empty($prefix)) {
+                       $search = '*';
+               } else {
+                       $search = $prefix . '*';
+               }
+
+               $list = $this->redis->keys($this->getCacheKey($search));
+
+               return $this->getOriginalKeys($list);
+       }
+
+       /**
+        * (@inheritdoc)
+        */
        public function get($key)
        {
                $return = null;
@@ -55,6 +79,9 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
                return $return;
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function set($key, $value, $ttl = Cache::FIVE_MINUTES)
        {
                $cachekey = $this->getCacheKey($key);
@@ -75,12 +102,18 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
                }
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function delete($key)
        {
                $cachekey = $this->getCacheKey($key);
                return ($this->redis->delete($cachekey) > 0);
        }
 
+       /**
+        * (@inheritdoc)
+        */
        public function clear($outdated = true)
        {
                if ($outdated) {
@@ -127,6 +160,7 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
                $this->redis->unwatch();
                return false;
        }
+
        /**
         * (@inheritdoc)
         */
index f71522d068b9c63e6dbc4a7cd158fcf4d0a7df29..a07bbd31c9130fa76ad0bd9ae8dfe808ce191498 100644 (file)
@@ -31,7 +31,7 @@ class Config extends BaseObject
        public static function init()
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return;
                }
 
@@ -55,7 +55,7 @@ class Config extends BaseObject
        public static function load($family = "config")
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return;
                }
 
@@ -88,7 +88,7 @@ class Config extends BaseObject
        public static function get($family, $key, $default_value = null, $refresh = false)
        {
                // Database isn't ready or populated yet, fallback to file config
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return self::getApp()->getConfigValue($family, $key, $default_value);
                }
 
@@ -116,7 +116,7 @@ class Config extends BaseObject
        public static function set($family, $key, $value)
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return false;
                }
 
@@ -141,7 +141,7 @@ class Config extends BaseObject
        public static function delete($family, $key)
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return false;
                }
 
index 29ccd795b826078fcc1c85035d81d1458eeade71..9edc12b64c93b690646f75786589f52a16c0e136 100644 (file)
@@ -14,6 +14,7 @@ class Console extends \Asika\SimpleConsole\Console
        protected $customHelpOptions = ['h', 'help', '?'];
 
        protected $subConsoles = [
+               'cache'                  => __NAMESPACE__ . '\Console\Cache',
                'config'                 => __NAMESPACE__ . '\Console\Config',
                'createdoxygen'          => __NAMESPACE__ . '\Console\CreateDoxygen',
                'docbloxerrorchecker'    => __NAMESPACE__ . '\Console\DocBloxErrorChecker',
@@ -37,6 +38,7 @@ class Console extends \Asika\SimpleConsole\Console
 Usage: bin/console [--version] [-h|--help|-?] <command> [<args>] [-v]
 
 Commands:
+       cache                  Manage node cache
        config                 Edit site config
        createdoxygen          Generate Doxygen headers
        dbstructure            Do database updates
index acdacbed1de9ac57b6bf2024a08855db51ba97bb..481037a5f6a2d6e6696461f0e85bb45400002964 100644 (file)
@@ -39,7 +39,7 @@ HELP;
 
        protected function doExecute()
        {
-               $a = get_app();
+               $a = \Friendica\BaseObject::getApp();
 
                if ($this->getOption('v')) {
                        $this->out('Class: ' . __CLASS__);
@@ -56,7 +56,7 @@ HELP;
                        throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
                }
 
-               if ($a->mode === App::MODE_INSTALL) {
+               if ($a->getMode()->isInstall()) {
                        throw new RuntimeException('Friendica isn\'t properly installed yet.');
                }
 
index f0f3def2a0eda8e1fc87b5d18b124cd2f023883e..c4e542e762738a674e3f3213f68d88b69c875273 100644 (file)
@@ -3,15 +3,14 @@
 namespace Friendica\Core\Console;
 
 use Asika\SimpleConsole\Console;
-use Friendica\App;
 use Friendica\BaseObject;
 use Friendica\Core\Config;
 use Friendica\Core\Install;
 use Friendica\Core\Theme;
 use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
 use RuntimeException;
 
-require_once 'mod/install.php';
 require_once 'include/dba.php';
 
 class AutomaticInstallation extends Console
@@ -30,20 +29,21 @@ Notes
     Not checking .htaccess/URL-Rewrite during CLI installation.
 
 Options
-    -h|--help|-?           Show help information
-    -v                     Show more debug information.
-    -a                     All setup checks are required (except .htaccess)
-    -f|--file <config>     prepared config file (e.g. "config/local.ini.php" itself) which will override every other config option - except the environment variables)
-    -s|--savedb            Save the DB credentials to the file (if environment variables is used)
-    -H|--dbhost <host>     The host of the mysql/mariadb database (env MYSQL_HOST)
-    -p|--dbport <port>     The port of the mysql/mariadb database (env MYSQL_PORT)
-    -d|--dbdata <database> The name of the mysql/mariadb database (env MYSQL_DATABASE)
-    -U|--dbuser <username> The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
-    -P|--dbpass <password> The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
-    -b|--phppath <path>    The path of the PHP binary (env FRIENDICA_PHP_PATH) 
-    -A|--admin <mail>      The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL)
-    -T|--tz <timezone>     The timezone of Friendica (env FRIENDICA_TZ)
-    -L|--lang <language>   The language of Friendica (env FRIENDICA_LANG)
+    -h|--help|-?            Show help information
+    -v                      Show more debug information.
+    -a                      All setup checks are required (except .htaccess)
+    -f|--file <config>      prepared config file (e.g. "config/local.ini.php" itself) which will override every other config option - except the environment variables)
+    -s|--savedb             Save the DB credentials to the file (if environment variables is used)
+    -H|--dbhost <host>      The host of the mysql/mariadb database (env MYSQL_HOST)
+    -p|--dbport <port>      The port of the mysql/mariadb database (env MYSQL_PORT)
+    -d|--dbdata <database>  The name of the mysql/mariadb database (env MYSQL_DATABASE)
+    -U|--dbuser <username>  The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
+    -P|--dbpass <password>  The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
+    -u|--urlpath <url_path> The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) 
+    -b|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH) 
+    -A|--admin <mail>       The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL)
+    -T|--tz <timezone>      The timezone of Friendica (env FRIENDICA_TZ)
+    -L|--lang <language>    The language of Friendica (env FRIENDICA_LANG)
  
 Environment variables
    MYSQL_HOST                  The host of the mysql/mariadb database (mandatory if mysql and environment is used)
@@ -51,6 +51,7 @@ Environment variables
    MYSQL_USERNAME|MYSQL_USER   The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb)
    MYSQL_PASSWORD              The password of the mysql/mariadb database login
    MYSQL_DATABASE              The name of the mysql/mariadb database
+   FRIENDICA_URL_PATH          The URL path of Friendica (f.e. '/friendica')
    FRIENDICA_PHP_PATH          The path of the PHP binary
    FRIENDICA_ADMIN_MAIL        The admin email address of Friendica (this email will be used for admin access)
    FRIENDICA_TZ                The timezone of Friendica
@@ -75,6 +76,8 @@ HELP;
 
                $a = BaseObject::getApp();
 
+               $install = new Install();
+
                // if a config file is set,
                $config_file = $this->getOption(['f', 'file']);
 
@@ -82,8 +85,8 @@ HELP;
                        if ($config_file != 'config' . DIRECTORY_SEPARATOR . 'local.ini.php') {
                                // Copy config file
                                $this->out("Copying config file...\n");
-                               if (!copy($a->basepath . DIRECTORY_SEPARATOR . $config_file, $a->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
-                                       throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '$a->basepath" . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "local.ini.php' manually.\n");
+                               if (!copy($a->getBasePath() . DIRECTORY_SEPARATOR . $config_file, $a->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
+                                       throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '" . $a->getBasePath() . "'"  . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "local.ini.php' manually.\n");
                                }
                        }
 
@@ -102,21 +105,23 @@ HELP;
                        $db_data = $this->getOption(['d', 'dbdata'], ($save_db) ? getenv('MYSQL_DATABASE') : '');
                        $db_user = $this->getOption(['U', 'dbuser'], ($save_db) ? getenv('MYSQL_USER') . getenv('MYSQL_USERNAME') : '');
                        $db_pass = $this->getOption(['P', 'dbpass'], ($save_db) ? getenv('MYSQL_PASSWORD') : '');
-                       $php_path = $this->getOption(['b', 'phppath'], (!empty('FRIENDICA_PHP_PATH')) ? getenv('FRIENDICA_PHP_PATH') : '');
+                       $url_path = $this->getOption(['u', 'urlpath'], (!empty('FRIENDICA_URL_PATH')) ? getenv('FRIENDICA_URL_PATH') : null);
+                       $php_path = $this->getOption(['b', 'phppath'], (!empty('FRIENDICA_PHP_PATH')) ? getenv('FRIENDICA_PHP_PATH') : null);
                        $admin_mail = $this->getOption(['A', 'admin'], (!empty('FRIENDICA_ADMIN_MAIL')) ? getenv('FRIENDICA_ADMIN_MAIL') : '');
                        $tz = $this->getOption(['T', 'tz'], (!empty('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : '');
                        $lang = $this->getOption(['L', 'lang'], (!empty('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : '');
 
-                       Install::createConfig(
+                       $install->createConfig(
                                $php_path,
+                               $url_path,
                                ((!empty($db_port)) ? $db_host . ':' . $db_port : $db_host),
                                $db_user,
                                $db_pass,
                                $db_data,
-                               $php_path,
                                $tz,
                                $lang,
-                               $admin_mail
+                               $admin_mail,
+                               $a->getBasePath()
                        );
                }
 
@@ -126,7 +131,10 @@ HELP;
                $this->out("Checking basic setup...\n");
 
                $checkResults = [];
-               $checkResults['basic'] = $this->runBasicChecks($a);
+
+               $this->runBasicChecks($install);
+
+               $checkResults['basic'] = $install->getChecks();
                $errorMessage = $this->extractErrors($checkResults['basic']);
 
                if ($errorMessage !== '') {
@@ -151,7 +159,7 @@ HELP;
                // Install database
                $this->out("Inserting data into database...\n");
 
-               $checkResults['data'] = Install::installDatabaseStructure();
+               $checkResults['data'] = DBStructure::update(false, true, true);
 
                if ($checkResults['data'] !== '') {
                        throw new RuntimeException("ERROR: DB Database creation error. Is the DB empty?\n");
@@ -174,28 +182,26 @@ HELP;
        }
 
        /**
-        * @param App $app
-        * @return array
+        * @param Install $install the Installer instance
         */
-       private function runBasicChecks($app)
+       private function runBasicChecks(Install $install)
        {
-               $checks = [];
-
-               Install::checkFunctions($checks);
-               Install::checkImagick($checks);
-               Install::checkLocalIni($checks);
-               Install::checkSmarty3($checks);
-               Install::checkKeys($checks);
+               $install->resetChecks();
+               $install->checkFunctions();
+               $install->checkImagick();
+               $install->checkLocalIni();
+               $install->checkSmarty3();
+               $install->checkKeys();
 
                if (!empty(Config::get('config', 'php_path'))) {
-                       Install::checkPHP(Config::get('config', 'php_path'), $checks);
+                       if (!$install->checkPHP(Config::get('config', 'php_path'), true)) {
+                               throw new RuntimeException(" ERROR: The php_path is not valid in the config.\n");
+                       }
                } else {
                        throw new RuntimeException(" ERROR: The php_path is not set in the config.\n");
                }
 
                $this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n");
-
-               return $checks;
        }
 
        /**
@@ -203,6 +209,7 @@ HELP;
         * @param $db_user
         * @param $db_pass
         * @param $db_data
+        *
         * @return array
         */
        private function runDatabaseCheck($db_host, $db_user, $db_pass, $db_data)
diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php
new file mode 100644 (file)
index 0000000..510c05b
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+
+namespace Friendica\Core\Console;
+
+use Asika\SimpleConsole\CommandArgsException;
+use Friendica\App;
+use Friendica\Core;
+use RuntimeException;
+
+/**
+ * @brief tool to access the cache from the CLI
+ *
+ * With this script you can access the cache of your node from the CLI.
+ * You can read current values stored in the cache and set new values
+ * in cache keys.
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class Cache extends \Asika\SimpleConsole\Console
+{
+       protected $helpOptions = ['h', 'help', '?'];
+
+       protected function getHelp()
+       {
+               $help = <<<HELP
+console cache - Manage node cache
+Synopsis
+       bin/console cache list [-h|--help|-?] [-v]
+       bin/console cache get <key> [-h|--help|-?] [-v]
+       bin/console cache set <key> <value> [-h|--help|-?] [-v]
+       bin/console cache flush [-h|--help|-?] [-v]
+       bin/console cache clear [-h|--help|-?] [-v]
+
+Description
+       bin/console cache list [<prefix>]
+               List all cache keys, optionally filtered by a prefix
+
+       bin/console cache get <key>
+               Shows the value of the provided cache key
+
+       bin/console cache set <key> <value> [<ttl>]
+               Sets the value of the provided cache key, optionally with the provided TTL (time to live) with a default of five minutes.
+
+       bin/console cache flush
+               Clears expired cache keys
+
+       bin/console cache clear
+               Clears all cache keys
+
+Options
+    -h|--help|-? Show help information
+    -v           Show more debug information.
+HELP;
+               return $help;
+       }
+
+       protected function doExecute()
+       {
+               $a = \Friendica\BaseObject::getApp();
+
+               if ($this->getOption('v')) {
+                       $this->out('Executable: ' . $this->executable);
+                       $this->out('Class: ' . __CLASS__);
+                       $this->out('Arguments: ' . var_export($this->args, true));
+                       $this->out('Options: ' . var_export($this->options, true));
+               }
+
+               if ($a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
+                       $this->out('Database isn\'t ready or populated yet, database cache won\'t be available');
+               }
+
+               Core\Cache::init();
+
+               if ($this->getOption('v')) {
+                       $this->out('Cache Driver Name: ' . Core\Cache::$driver_name);
+                       $this->out('Cache Driver Class: ' . Core\Cache::$driver_class);
+               }
+
+               switch ($this->getArgument(0)) {
+                       case 'list':
+                               $this->executeList();
+                               break;
+                       case 'get':
+                               $this->executeGet();
+                               break;
+                       case 'set':
+                               $this->executeSet();
+                               break;
+                       case 'flush':
+                               $this->executeFlush();
+                               break;
+                       case 'clear':
+                               $this->executeClear();
+                               break;
+               }
+
+               if (count($this->args) == 0) {
+                       $this->out($this->getHelp());
+                       return 0;
+               }
+
+               return 0;
+       }
+
+       private function executeList()
+       {
+               $prefix = $this->getArgument(1);
+               $keys = Core\Cache::getAllKeys($prefix);
+
+               if (empty($prefix)) {
+                       $this->out('Listing all cache keys:');
+               } else {
+                       $this->out('Listing all cache keys starting with "' . $prefix . '":');
+               }
+
+               $count = 0;
+               foreach ($keys as $key) {
+                       $this->out($key);
+                       $count++;
+               }
+
+               $this->out($count . ' keys found');
+       }
+
+       private function executeGet()
+       {
+               if (count($this->args) >= 2) {
+                       $key = $this->getArgument(1);
+                       $value = Core\Cache::get($key);
+
+                       $this->out("{$key} => " . var_export($value, true));
+               } else {
+                       throw new CommandArgsException('Too few arguments for get');
+               }
+       }
+
+       private function executeSet()
+       {
+               if (count($this->args) >= 3) {
+                       $key = $this->getArgument(1);
+                       $value = $this->getArgument(2);
+                       $duration = intval($this->getArgument(3, Core\Cache::FIVE_MINUTES));
+
+                       if (is_array(Core\Cache::get($key))) {
+                               throw new RuntimeException("$key is an array and can't be set using this command.");
+                       }
+
+                       $result = Core\Cache::set($key, $value, $duration);
+                       if ($result) {
+                               $this->out("{$key} <= " . Core\Cache::get($key));
+                       } else {
+                               $this->out("Unable to set {$key}");
+                       }
+               } else {
+                       throw new CommandArgsException('Too few arguments for set');
+               }
+       }
+
+       private function executeFlush()
+       {
+               $result = Core\Cache::clear();
+               if ($result) {
+                       $this->out('Cache successfully flushed');
+               } else {
+                       $this->out('Unable to flush the cache');
+               }
+       }
+
+       private function executeClear()
+       {
+               $result = Core\Cache::clear(false);
+               if ($result) {
+                       $this->out('Cache successfully cleared');
+               } else {
+                       $this->out('Unable to flush the cache');
+               }
+       }
+}
index da2d20fd13fda2ec63fa9b80aeea5c89f44cbf5d..3b92d5a784a5e7aa69fb8842d94592fb3a054664 100644 (file)
@@ -1,11 +1,5 @@
 <?php
 
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
 namespace Friendica\Core\Console;
 
 use Asika\SimpleConsole\CommandArgsException;
@@ -13,9 +7,6 @@ use Friendica\App;
 use Friendica\Core;
 use RuntimeException;
 
-require_once 'include/dba.php';
-require_once 'include/text.php';
-
 /**
  * @brief tool to access the system config from the CLI
  *
@@ -80,7 +71,7 @@ HELP;
 
        protected function doExecute()
        {
-               $a = get_app();
+               $a = \Friendica\BaseObject::getApp();
 
                if ($this->getOption('v')) {
                        $this->out('Executable: ' . $this->executable);
@@ -93,7 +84,7 @@ HELP;
                        throw new CommandArgsException('Too many arguments');
                }
 
-               if (!($a->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        $this->out('Database isn\'t ready or populated yet, showing file config only');
                }
 
@@ -152,7 +143,7 @@ HELP;
                if (count($this->args) == 0) {
                        Core\Config::load();
 
-                       if (Core\Config::get('system', 'config_adapter') == 'jit' && $a->mode & App::MODE_DBCONFIGAVAILABLE) {
+                       if (Core\Config::get('system', 'config_adapter') == 'jit' && $a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                                $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only');
                        }
 
index b29f8e2baaf9e41e190f814077e95c35570df7a4..421f913bb8ab1d4f397180a6f470acd3bd97cb07 100644 (file)
@@ -60,7 +60,7 @@ HELP;
                }
 
                //return from util folder to frindica base dir
-               $dir = get_app()->get_basepath();
+               $dir = get_app()->getBasePath();
 
                //stack for dirs to search
                $dirstack = [];
index f51ed95fe2b4f49d93406317dca55d47c6e7eb3e..2a19a9e7f3f0343a3b79da58ec189e65b0dbb0c3 100644 (file)
@@ -56,7 +56,7 @@ HELP;
                        throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
                }
 
-               if ($a->isInstallMode()) {
+               if ($a->getMode()->isInstall()) {
                        throw new \RuntimeException('Database isn\'t ready or populated yet');
                }
 
index 03101cdf0f3ec4da192a2436f0ec1fa74a747046..3ea6b415544b6a2f94105d5d15320d9ef43aa2c2 100644 (file)
@@ -65,7 +65,7 @@ HELP;
                        throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
                }
 
-               if ($a->isInstallMode()) {
+               if ($a->getMode()->isInstall()) {
                        throw new RuntimeException('Database isn\'t ready or populated yet');
                }
 
index a3e3b80a7eb33f3feae05807a426291f4ca6f59c..212edabcc1db21a9965203875fe9d76097fbf689 100644 (file)
@@ -47,7 +47,7 @@ HELP;
 
        protected function doExecute()
        {
-               $a = get_app();
+               $a = \Friendica\BaseObject::getApp();
 
                if ($this->getOption('v')) {
                        $this->out('Class: ' . __CLASS__);
@@ -64,7 +64,7 @@ HELP;
                        throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
                }
 
-               if ($a->isInstallMode()) {
+               if ($a->getMode()->isInstall()) {
                        throw new \RuntimeException('Database isn\'t ready or populated yet');
                }
 
index 2581d81cd06cd3e2da76fdc3afffa8bbe0e05201..54d10af2077768edf4735a787efd3175ab6b9ef9 100644 (file)
@@ -57,7 +57,7 @@ HELP;
                        throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
                }
 
-               if ($a->isInstallMode()) {
+               if ($a->getMode()->isInstall()) {
                        throw new RuntimeException('Database isn\'t ready or populated yet');
                }
 
index 24ed514b5e46ef3c992ecf548c1388efca2123b8..1215591a20ebadf1ff66606889d04beee4b97149 100644 (file)
@@ -33,7 +33,7 @@ HELP;
 
        protected function doExecute()
        {
-               $a = get_app();
+               $a = \Friendica\BaseObject::getApp();
 
                if ($this->getOption($this->helpOptions)) {
                        $this->out($this->getHelp());
@@ -50,7 +50,7 @@ HELP;
                        return 0;
                }
 
-               if ($a->isInstallMode()) {
+               if ($a->getMode()->isInstall()) {
                        throw new \RuntimeException('Database isn\'t ready or populated yet');
                }
 
index ba3a97ea6c376fb64f36a61bda128bd3bfb719e3..daf90b9fff65de12b2620d9e2815a5c349e171dd 100644 (file)
@@ -6,52 +6,90 @@ namespace Friendica\Core;
 
 use DOMDocument;
 use Exception;
-use Friendica\BaseObject;
-use Friendica\Database\DBStructure;
 use Friendica\Object\Image;
 use Friendica\Util\Network;
 
 /**
  * Contains methods for installation purpose of Friendica
  */
-class Install extends BaseObject
+class Install
 {
        /**
-        * Checks the current installation environment. There are optional and mandatory checks.
+        * @var array the check outcomes
+        */
+       private $checks;
+
+       /**
+        * Returns all checks made
         *
-        * @param string $phpath Optional path to the PHP binary (Default is 'php')
+        * @return array the checks
+        */
+       public function getChecks()
+       {
+               return $this->checks;
+       }
+
+       /**
+        * Resets all checks
+        */
+       public function resetChecks()
+       {
+               $this->checks = [];
+       }
+
+       /**
+        * Install constructor.
         *
-        * @return array First element is a list of all checks and their results,
-        *               the second element is a list of passed checks
         */
-       public static function check($phpath = 'php')
+       public function __construct()
        {
-               $checks = [];
+               $this->checks = [];
+       }
 
-               self::checkFunctions($checks);
+       /**
+        * Checks the current installation environment. There are optional and mandatory checks.
+        *
+        * @param string $basepath    The basepath of Friendica
+        * @param string $baseurl     The baseurl of Friendica
+        * @param string $phpath      Optional path to the PHP binary
+        *
+        * @return bool if the check succeed
+        */
+       public function checkAll($basepath, $baseurl, $phpath = null)
+       {
+               $returnVal = true;
 
-               self::checkImagick($checks);
+               if (isset($phpath)) {
+                       if (!$this->checkPHP($phpath)) {
+                               $returnVal = false;
+                       }
+               }
 
-               self::checkLocalIni($checks);
+               if (!$this->checkFunctions()) {
+                       $returnVal = false;
+               }
 
-               self::checkSmarty3($checks);
+               if (!$this->checkImagick()) {
+                       $returnVal = false;
+               }
 
-               self::checkKeys($checks);
+               if (!$this->checkLocalIni()) {
+                       $returnVal = false;
+               }
 
-               self::checkPHP($phpath, $checks);
+               if (!$this->checkSmarty3()) {
+                       $returnVal = false;
+               }
 
-               self::checkHtAccess($checks);
+               if (!$this->checkKeys()) {
+                       $returnVal = false;
+               }
 
-               $checkspassed = array_reduce($checks,
-                       function ($v, $c) {
-                               if (!empty($c['require'])) {
-                                       $v = $v && $c['status'];
-                               }
-                               return $v;
-                       },
-                       true);
+               if (!$this->checkHtAccess($basepath, $baseurl)) {
+                       $returnVal = false;
+               }
 
-               return array($checks, $checkspassed);
+               return $returnVal;
        }
 
        /**
@@ -64,15 +102,19 @@ class Install extends BaseObject
         * @param string        $dbuser         Username of the Database connection credentials
         * @param string        $dbpass         Password of the Database connection credentials
         * @param string        $dbdata         Name of the Database
-        * @param string        $phpath         Path to the PHP-Binary (e.g. 'php' or '/usr/bin/php')
         * @param string        $timezone       Timezone of the Friendica Installaton (e.g. 'Europe/Berlin')
         * @param string        $language       2-letter ISO 639-1 code (eg. 'en')
         * @param string        $adminmail      Mail-Adress of the administrator
+        * @param string        $basepath   The basepath of Friendica
+        * @param string        $phpath         Path to the PHP-Binary (optional, if not set e.g. 'php' or '/usr/bin/php')
+        *
+        * @return bool|string true if the config was created, the text if something went wrong
         */
-       public static function createConfig($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail)
+       public function createConfig($phppath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $basepath)
        {
                $tpl = get_markup_template('local.ini.tpl');
                $txt = replace_macros($tpl,[
+                       '$phpath' => $phppath,
                        '$dbhost' => $dbhost,
                        '$dbuser' => $dbuser,
                        '$dbpass' => $dbpass,
@@ -80,37 +122,36 @@ class Install extends BaseObject
                        '$timezone' => $timezone,
                        '$language' => $language,
                        '$urlpath' => $urlpath,
-                       '$phpath' => $phpath,
                        '$adminmail' => $adminmail,
                ]);
 
-               $app = self::getApp();
+               $result = file_put_contents($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', $txt);
 
-               $result = file_put_contents($app->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', $txt);
                if (!$result) {
-                       $app->data['txt'] = $txt;
+                       return $txt;
+               } else {
+                       return true;
                }
        }
 
        /**
         * Adds new checks to the array $checks
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
         * @param string $title The title of the current check
         * @param bool $status 1 = check passed, 0 = check not passed
         * @param bool $required 1 = check is mandatory, 0 = check is optional
         * @param string $help A help-string for the current check
         * @param string $error_msg Optional. A error message, if the current check failed
         */
-       private static function addCheck(&$checks, $title, $status, $required, $help, $error_msg = "")
+       private function addCheck($title, $status, $required, $help, $error_msg = "")
        {
-               $checks[] = [
+               array_push($this->checks, [
                        'title' => $title,
                        'status' => $status,
                        'required' => $required,
                        'help' => $help,
                        'error_msg' => $error_msg,
-               ];
+               ]);
        }
 
        /**
@@ -122,18 +163,21 @@ class Install extends BaseObject
         * - Checks if it is the CLI version
         * - Checks if "register_argc_argv" is enabled
         *
-        * @param string $phpath Optional. The Path to the PHP-Binary
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @param string $phppath Optional. The Path to the PHP-Binary
+        * @param bool   $required Optional. If set to true, the PHP-Binary has to exist (Default false)
+        *
+        * @return bool false if something required failed
         */
-       public static function checkPHP($phpath, &$checks)
+       public function checkPHP($phppath = null, $required = false)
        {
                $passed = $passed2 = $passed3 = false;
-               if (strlen($phpath)) {
-                       $passed = file_exists($phpath);
+               if (isset($phppath)) {
+                       $passed = file_exists($phppath);
                } else {
-                       $phpath = trim(shell_exec('which php'));
-                       $passed = strlen($phpath);
+                       $phppath = trim(shell_exec('which php'));
+                       $passed = strlen($phppath);
                }
+
                $help = "";
                if (!$passed) {
                        $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL;
@@ -141,15 +185,15 @@ class Install extends BaseObject
                        $help .= EOL . EOL;
                        $tpl = get_markup_template('field_input.tpl');
                        $help .= replace_macros($tpl, [
-                               '$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')],
+                               '$field' => ['phpath', L10n::t('PHP executable path'), $phppath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')],
                        ]);
-                       $phpath = "";
+                       $phppath = "";
                }
 
-               self::addCheck($checks, L10n::t('Command line PHP').($passed?" (<tt>$phpath</tt>)":""), $passed, false, $help);
+               $this->addCheck(L10n::t('Command line PHP') . ($passed ? " (<tt>$phppath</tt>)" : ""), $passed, false, $help);
 
                if ($passed) {
-                       $cmd = "$phpath -v";
+                       $cmd = "$phppath -v";
                        $result = trim(shell_exec($cmd));
                        $passed2 = (strpos($result, "(cli)") !== false);
                        list($result) = explode("\n", $result);
@@ -158,21 +202,30 @@ class Install extends BaseObject
                                $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL;
                                $help .= L10n::t('Found PHP version: ') . "<tt>$result</tt>";
                        }
-                       self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help);
+                       $this->addCheck(L10n::t('PHP cli binary'), $passed2, true, $help);
+               } else {
+                       // return if it was required
+                       return $required;
                }
 
                if ($passed2) {
                        $str = autoname(8);
-                       $cmd = "$phpath testargs.php $str";
+                       $cmd = "$phppath testargs.php $str";
                        $result = trim(shell_exec($cmd));
                        $passed3 = $result == $str;
                        $help = "";
                        if (!$passed3) {
                                $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL;
                                $help .= L10n::t('This is required for message delivery to work.');
+                       } else {
+                               $this->phppath = $phppath;
                        }
-                       self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help);
+
+                       $this->addCheck(L10n::t('PHP register_argc_argv'), $passed3, true, $help);
                }
+
+               // passed2 & passed3 are required if first check passed
+               return $passed2 && $passed3;
        }
 
        /**
@@ -182,12 +235,13 @@ class Install extends BaseObject
         *
         * - Checks, if the command "openssl_pkey_new" is available
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @return bool false if something required failed
         */
-       public static function checkKeys(&$checks)
+       public function checkKeys()
        {
                $help = '';
                $res = false;
+               $status = true;
 
                if (function_exists('openssl_pkey_new')) {
                        $res = openssl_pkey_new([
@@ -201,8 +255,34 @@ class Install extends BaseObject
                if (!$res) {
                        $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL;
                        $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
+                       $status = false;
+               }
+               $this->addCheck(L10n::t('Generate encryption keys'), $res, true, $help);
+
+               return $status;
+       }
+
+       /**
+        * PHP basic function check
+        *
+        * @param string $name The name of the function
+        * @param string $title The (localized) title of the function
+        * @param string $help The (localized) help of the function
+        * @param boolean $required If true, this check is required
+        *
+        * @return bool false, if the check failed
+        */
+       private function checkFunction($name, $title, $help, $required)
+       {
+               $currHelp = '';
+               $status = true;
+               if (!function_exists($name)) {
+                       $currHelp = $help;
+                       $status = false;
                }
-               self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help);
+               $this->addCheck($title, $status, $required, $currHelp);
+
+               return $status || (!$status && !$required);
        }
 
        /**
@@ -218,70 +298,93 @@ class Install extends BaseObject
         * - iconv
         * - POSIX
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @return bool false if something required failed
         */
-       public static function checkFunctions(&$checks)
+       public function checkFunctions()
        {
-               $ck_funcs = [];
-               self::addCheck($ck_funcs, L10n::t('libCurl PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('GD graphics PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('mb_string PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('XML PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('iconv PHP module'), true, true, "");
-               self::addCheck($ck_funcs, L10n::t('POSIX PHP module'), true, true, "");
+               $returnVal = true;
 
+               $help = '';
+               $status = true;
                if (function_exists('apache_get_modules')) {
-                       if (! in_array('mod_rewrite',apache_get_modules())) {
-                               self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.'));
-                       } else {
-                               self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, "");
+                       if (!in_array('mod_rewrite', apache_get_modules())) {
+                               $help = L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.');
+                               $status = false;
+                               $returnVal = false;
                        }
                }
+               $this->addCheck(L10n::t('Apache mod_rewrite module'), $status, true, $help);
 
-               if (!function_exists('curl_init')) {
-                       $ck_funcs[0]['status'] = false;
-                       $ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.');
-               }
-               if (!function_exists('imagecreatefromjpeg')) {
-                       $ck_funcs[1]['status'] = false;
-                       $ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.');
-               }
-               if (!function_exists('openssl_public_encrypt')) {
-                       $ck_funcs[2]['status'] = false;
-                       $ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.');
-               }
+               $help = '';
+               $status = true;
                if (!function_exists('mysqli_connect') && !class_exists('pdo')) {
-                       $ck_funcs[3]['status'] = false;
-                       $ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.');
-               }
-               if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) {
-                       $ck_funcs[3]['status'] = false;
-                       $ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.');
-               }
-               if (!function_exists('mb_strlen')) {
-                       $ck_funcs[4]['status'] = false;
-                       $ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.');
-               }
-               if (!function_exists('iconv_strlen')) {
-                       $ck_funcs[6]['status'] = false;
-                       $ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.');
-               }
-               if (!function_exists('posix_kill')) {
-                       $ck_funcs[7]['status'] = false;
-                       $ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.');
+                       $status = false;
+                       $help = L10n::t('Error: PDO or MySQLi PHP module required but not installed.');
+                       $returnVal = false;
+               } else {
+                       if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) {
+                               $status = false;
+                               $help = L10n::t('Error: The MySQL driver for PDO is not installed.');
+                               $returnVal = false;
+                       }
                }
-
-               $checks = array_merge($checks, $ck_funcs);
+               $this->addCheck(L10n::t('PDO or MySQLi PHP module'), $status, true, $help);
 
                // check for XML DOM Documents being able to be generated
+               $help = '';
+               $status = true;
                try {
                        $xml = new DOMDocument();
                } catch (Exception $e) {
-                       $ck_funcs[5]['status'] = false;
-                       $ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.');
+                       $help = L10n::t('Error, XML PHP module required but not installed.');
+                       $status = false;
+                       $returnVal = false;
                }
+               $this->addCheck(L10n::t('XML PHP module'), $status, true, $help);
+
+               $status = $this->checkFunction('curl_init',
+                       L10n::t('libCurl PHP module'),
+                       L10n::t('Error: libCURL PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('imagecreatefromjpeg',
+                       L10n::t('GD graphics PHP module'),
+                       L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('openssl_public_encrypt',
+                       L10n::t('OpenSSL PHP module'),
+                       L10n::t('Error: openssl PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('mb_strlen',
+                       L10n::t('mb_string PHP module'),
+                       L10n::t('Error: mb_string PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('iconv_strlen',
+                       L10n::t('iconv PHP module'),
+                       L10n::t('Error: iconv PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('posix_kill',
+                       L10n::t('POSIX PHP module'),
+                       L10n::t('Error: POSIX PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               return $returnVal;
        }
 
        /**
@@ -289,9 +392,9 @@ class Install extends BaseObject
         *
         * Checks if it's possible to create the "config/local.ini.php"
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @return bool false if something required failed
         */
-       public static function checkLocalIni(&$checks)
+       public function checkLocalIni()
        {
                $status = true;
                $help = "";
@@ -305,8 +408,10 @@ class Install extends BaseObject
                        $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL;
                }
 
-               self::addCheck($checks, L10n::t('config/local.ini.php is writable'), $status, false, $help);
+               $this->addCheck(L10n::t('config/local.ini.php is writable'), $status, false, $help);
 
+               // Local INI File is not required
+               return true;
        }
 
        /**
@@ -314,9 +419,9 @@ class Install extends BaseObject
         *
         * Checks, if the directory of Smarty3 is writable
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @return bool false if something required failed
         */
-       public static function checkSmarty3(&$checks)
+       public function checkSmarty3()
        {
                $status = true;
                $help = "";
@@ -329,7 +434,9 @@ class Install extends BaseObject
                        $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL;
                }
 
-               self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help);
+               $this->addCheck(L10n::t('view/smarty3 is writable'), $status, true, $help);
+
+               return $status;
        }
 
        /**
@@ -337,34 +444,39 @@ class Install extends BaseObject
         *
         * Checks, if "url_rewrite" is enabled in the ".htaccess" file
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @param string $basepath   The basepath of the app
+        * @param string $baseurl    The baseurl of the app
+        * @return bool false if something required failed
         */
-       public static function checkHtAccess(&$checks)
+       public function checkHtAccess($basepath, $baseurl)
        {
                $status = true;
                $help = "";
                $error_msg = "";
                if (function_exists('curl_init')) {
-                       $test = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite");
+                       $fetchResult = Network::fetchUrlFull($basepath . "/install/testrewrite");
 
-                       $url = normalise_link(System::baseUrl() . "/install/testrewrite");
-                       if ($test['body'] != "ok") {
-                               $test = Network::fetchUrlFull($url);
+                       $url = normalise_link($baseurl . "/install/testrewrite");
+                       if ($fetchResult->getBody() != "ok") {
+                               $fetchResult = Network::fetchUrlFull($url);
                        }
 
-                       if ($test['body'] != "ok") {
+                       if ($fetchResult->getBody() != "ok") {
                                $status = false;
                                $help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.');
                                $error_msg = [];
                                $error_msg['head'] = L10n::t('Error message from Curl when fetching');
-                               $error_msg['url'] = $test['redirect_url'];
-                               $error_msg['msg'] = defaults($test, 'error', '');
+                               $error_msg['url'] = $fetchResult->getRedirectUrl();
+                               $error_msg['msg'] = $fetchResult->getError();
                        }
-                       self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help, $error_msg);
+
+                       $this->addCheck(L10n::t('Url rewrite is working'), $status, true, $help, $error_msg);
                } else {
                        // cannot check modrewrite if libcurl is not installed
                        /// @TODO Maybe issue warning here?
                }
+
+               return $status;
        }
 
        /**
@@ -372,9 +484,9 @@ class Install extends BaseObject
         *
         * Checks, if the imagick module is available
         *
-        * @param array $checks The list of all checks (by-ref parameter!)
+        * @return bool false if something required failed
         */
-       public static function checkImagick(&$checks)
+       public function checkImagick()
        {
                $imagick = false;
                $gif = false;
@@ -386,25 +498,16 @@ class Install extends BaseObject
                                $gif = true;
                        }
                }
-               if ($imagick == false) {
-                       self::addCheck($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, "");
+               if (!$imagick) {
+                       $this->addCheck(L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, "");
                } else {
-                       self::addCheck($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, "");
+                       $this->addCheck(L10n::t('ImageMagick PHP extension is installed'), $imagick, false, "");
                        if ($imagick) {
-                               self::addCheck($checks, L10n::t('ImageMagick supports GIF'), $gif, false, "");
+                               $this->addCheck(L10n::t('ImageMagick supports GIF'), $gif, false, "");
                        }
                }
-       }
-
-       /**
-        * Installs the Database structure
-        *
-        * @return string A possible error
-        */
-       public static function installDatabaseStructure()
-       {
-               $errors = DBStructure::update(false, true, true);
 
-               return $errors;
+               // Imagick is not required
+               return true;
        }
 }
index f8c4ee3f86dc9798fe2eac29867229f6292ec44c..fb77605730b1069501c751c382a4f2ee46448cfe 100644 (file)
@@ -631,7 +631,7 @@ class NotificationsManager extends BaseObject
                        // We have to distinguish between these two because they use different data.
                        // Contact suggestions
                        if ($it['fid']) {
-                               $return_addr = bin2hex(self::getApp()->user['nickname'] . '@' . self::getApp()->get_hostname() . ((self::getApp()->urlpath) ? '/' . self::getApp()->urlpath : ''));
+                               $return_addr = bin2hex(self::getApp()->user['nickname'] . '@' . self::getApp()->getHostName() . ((self::getApp()->getURLPath()) ? '/' . self::getApp()->getURLPath() : ''));
 
                                $intro = [
                                        'label' => 'friend_suggestion',
index 2b6618930097c1c2ddf6c149b2a8d9286372331d..2080f716ceb5cfac2b329108cd004535210ecfa3 100644 (file)
@@ -29,12 +29,14 @@ class PConfig extends BaseObject
 
        public static function init($uid)
        {
+               $a = self::getApp();
+
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return;
                }
 
-               if (self::getApp()->getConfigValue('system', 'config_adapter') == 'preload') {
+               if ($a->getConfigValue('system', 'config_adapter') == 'preload') {
                        self::$adapter = new Config\PreloadPConfigAdapter($uid);
                } else {
                        self::$adapter = new Config\JITPConfigAdapter($uid);
@@ -55,7 +57,7 @@ class PConfig extends BaseObject
        public static function load($uid, $family)
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return;
                }
 
@@ -84,7 +86,7 @@ class PConfig extends BaseObject
        public static function get($uid, $family, $key, $default_value = null, $refresh = false)
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return;
                }
 
@@ -113,7 +115,7 @@ class PConfig extends BaseObject
        public static function set($uid, $family, $key, $value)
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return false;
                }
 
@@ -139,7 +141,7 @@ class PConfig extends BaseObject
        public static function delete($uid, $family, $key)
        {
                // Database isn't ready or populated yet
-               if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) {
+               if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
                        return false;
                }
 
index 88b89cda27ac60189375854ecca2a103439ff4d2..5b5fac82f01b520e4f31e86e70904932d719a709 100644 (file)
@@ -27,7 +27,7 @@ class System extends BaseObject
         */
        public static function baseUrl($ssl = false)
        {
-               return self::getApp()->get_baseurl($ssl);
+               return self::getApp()->getBaseURL($ssl);
        }
 
        /**
@@ -39,7 +39,7 @@ class System extends BaseObject
         */
        public static function removedBaseUrl($orig_url)
        {
-               return self::getApp()->remove_baseurl($orig_url);
+               return self::getApp()->removeBaseURL($orig_url);
        }
 
        /**
@@ -161,6 +161,18 @@ class System extends BaseObject
                killme();
        }
 
+       /**
+        * Generates a random string in the UUID format
+        *
+        * @param bool|string  $prefix   A given prefix (default is empty)
+        * @return string a generated UUID
+        */
+       public static function createUUID($prefix = '')
+       {
+               $guid = System::createGUID(32, $prefix);
+               return substr($guid, 0, 8). '-' . substr($guid, 8, 4) . '-' . substr($guid, 12, 4) . '-' . substr($guid, 16, 4) . '-' . substr($guid, 20, 12);
+       }
+
        /**
         * Generates a GUID with the given parameters
         *
@@ -173,7 +185,7 @@ class System extends BaseObject
                if (is_bool($prefix) && !$prefix) {
                        $prefix = '';
                } elseif (empty($prefix)) {
-                       $prefix = hash('crc32', self::getApp()->get_hostname());
+                       $prefix = hash('crc32', self::getApp()->getHostName());
                }
 
                while (strlen($prefix) < ($size - 13)) {
@@ -204,6 +216,26 @@ class System extends BaseObject
                return substr($trailer . uniqid('') . mt_rand(), 0, 26);
        }
 
+       /**
+        * Returns the current Load of the System
+        *
+        * @return integer
+        */
+       public static function currentLoad()
+       {
+               if (!function_exists('sys_getloadavg')) {
+                       return false;
+               }
+
+               $load_arr = sys_getloadavg();
+
+               if (!is_array($load_arr)) {
+                       return false;
+               }
+
+               return max($load_arr[0], $load_arr[1]);
+       }
+
        /// @todo Move the following functions from boot.php
        /*
        function killme()
@@ -220,6 +252,5 @@ class System extends BaseObject
        function get_cachefile($file, $writemode = true)
        function get_itemcachepath()
        function get_spoolpath()
-       function current_load()
        */
 }
index c64ed08d3babdd315dd570c041878c89b8ea644d..7e5b89d2f9c506146c2f8c96fd788c4627a0602f 100644 (file)
@@ -50,7 +50,7 @@ class Theme
                $a = get_app();
                $stamp1 = microtime(true);
                $theme_file = file_get_contents("view/theme/$theme/theme.php");
-               $a->save_timestamp($stamp1, "file");
+               $a->saveTimestamp($stamp1, "file");
 
                $result = preg_match("|/\*.*\*/|msU", $theme_file, $matches);
 
index 3400f00ae1755229a24a20e16fc6844f1c7592c5..bf7e9f3bc895943a6f31c4d9c48c02893416552f 100644 (file)
@@ -62,7 +62,7 @@ class Worker
                }
 
                // Do we have too few memory?
-               if ($a->min_memory_reached()) {
+               if ($a->isMinMemoryReached()) {
                        logger('Pre check: Memory limit reached, quitting.', LOGGER_DEBUG);
                        return;
                }
@@ -122,7 +122,7 @@ class Worker
                                }
 
                                // Check free memory
-                               if ($a->min_memory_reached()) {
+                               if ($a->isMinMemoryReached()) {
                                        logger('Memory limit reached, quitting.', LOGGER_DEBUG);
                                        Lock::release('worker');
                                        return;
@@ -618,7 +618,7 @@ class Worker
                $active = self::activeWorkers();
 
                // Decrease the number of workers at higher load
-               $load = current_load();
+               $load = System::currentLoad();
                if ($load) {
                        $maxsysload = intval(Config::get("system", "maxloadavg", 50));
 
index ab856ef9d05da6fd2c1205fcf07e2029d8fdce02..c33fa2152fb5aebfd5b9ad84ac04ed4dd3d57776 100644 (file)
@@ -570,7 +570,7 @@ class DBA
                        self::$errorno = $errorno;
                }
 
-               $a->save_timestamp($stamp1, 'database');
+               $a->saveTimestamp($stamp1, 'database');
 
                if ($a->getConfigValue('system', 'db_log')) {
                        $stamp2 = microtime(true);
@@ -641,7 +641,7 @@ class DBA
                        self::$errorno = $errorno;
                }
 
-               $a->save_timestamp($stamp, "database_write");
+               $a->saveTimestamp($stamp, "database_write");
 
                return $retval;
        }
@@ -809,7 +809,7 @@ class DBA
                                }
                }
 
-               $a->save_timestamp($stamp1, 'database');
+               $a->saveTimestamp($stamp1, 'database');
 
                return $columns;
        }
@@ -1547,7 +1547,7 @@ class DBA
                                break;
                }
 
-               $a->save_timestamp($stamp1, 'database');
+               $a->saveTimestamp($stamp1, 'database');
 
                return $ret;
        }
index d6cd66aafa94a02f8171ae549ba2a460e451b3e4..0472d753ddba2620a831ce6618fe85ed1fd57954 100644 (file)
@@ -842,7 +842,7 @@ class DBStructure
        public static function definition() {
                $a = \Friendica\BaseObject::getApp();
 
-               $filename = $a->get_basepath() . '/config/dbstructure.json';
+               $filename = $a->getBasePath() . '/config/dbstructure.json';
 
                if (!is_readable($filename)) {
                        throw new Exception('Missing database structure config file config/dbstructure.json');
diff --git a/src/Model/APContact.php b/src/Model/APContact.php
new file mode 100644 (file)
index 0000000..4593e03
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+
+/**
+ * @file src/Model/APContact.php
+ */
+
+namespace Friendica\Model;
+
+use Friendica\BaseObject;
+use Friendica\Database\DBA;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Util\Network;
+use Friendica\Util\JsonLD;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Content\Text\HTML;
+
+require_once 'boot.php';
+
+class APContact extends BaseObject
+{
+       /**
+        * Resolves the profile url from the address by using webfinger
+        *
+        * @param string $addr profile address (user@domain.tld)
+        * @return string url
+        */
+       private static function addrToUrl($addr)
+       {
+               $addr_parts = explode('@', $addr);
+               if (count($addr_parts) != 2) {
+                       return false;
+               }
+
+               $webfinger = 'https://' . $addr_parts[1] . '/.well-known/webfinger?resource=acct:' . urlencode($addr);
+
+               $curlResult = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']);
+               if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
+                       return false;
+               }
+
+               $data = json_decode($curlResult->getBody(), true);
+
+               if (empty($data['links'])) {
+                       return false;
+               }
+
+               foreach ($data['links'] as $link) {
+                       if (empty($link['href']) || empty($link['rel']) || empty($link['type'])) {
+                               continue;
+                       }
+
+                       if (($link['rel'] == 'self') && ($link['type'] == 'application/activity+json')) {
+                               return $link['href'];
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Fetches a profile from a given url
+        *
+        * @param string  $url    profile url
+        * @param boolean $update true = always update, false = never update, null = update when not found
+        * @return array profile array
+        */
+       public static function getByURL($url, $update = null)
+       {
+               if (empty($url)) {
+                       return false;
+               }
+
+               if (empty($update)) {
+                       $apcontact = DBA::selectFirst('apcontact', [], ['url' => $url]);
+                       if (DBA::isResult($apcontact)) {
+                               return $apcontact;
+                       }
+
+                       $apcontact = DBA::selectFirst('apcontact', [], ['alias' => $url]);
+                       if (DBA::isResult($apcontact)) {
+                               return $apcontact;
+                       }
+
+                       $apcontact = DBA::selectFirst('apcontact', [], ['addr' => $url]);
+                       if (DBA::isResult($apcontact)) {
+                               return $apcontact;
+                       }
+
+                       if (!is_null($update)) {
+                               return false;
+                       }
+               }
+
+               if (empty(parse_url($url, PHP_URL_SCHEME))) {
+                       $url = self::addrToUrl($url);
+                       if (empty($url)) {
+                               return false;
+                       }
+               }
+
+               $data = ActivityPub::fetchContent($url);
+
+               if (empty($data) || empty($data['id']) || empty($data['inbox'])) {
+                       return false;
+               }
+
+               $apcontact = [];
+               $apcontact['url'] = $data['id'];
+               $apcontact['uuid'] = defaults($data, 'diaspora:guid', null);
+               $apcontact['type'] = defaults($data, 'type', null);
+               $apcontact['following'] = defaults($data, 'following', null);
+               $apcontact['followers'] = defaults($data, 'followers', null);
+               $apcontact['inbox'] = defaults($data, 'inbox', null);
+               $apcontact['outbox'] = defaults($data, 'outbox', null);
+               $apcontact['sharedinbox'] = JsonLD::fetchElement($data, 'endpoints', 'sharedInbox');
+               $apcontact['nick'] = defaults($data, 'preferredUsername', null);
+               $apcontact['name'] = defaults($data, 'name', $apcontact['nick']);
+               $apcontact['about'] = HTML::toBBCode(defaults($data, 'summary', ''));
+               $apcontact['photo'] = JsonLD::fetchElement($data, 'icon', 'url');
+               $apcontact['alias'] = JsonLD::fetchElement($data, 'url', 'href');
+
+               $parts = parse_url($apcontact['url']);
+               unset($parts['scheme']);
+               unset($parts['path']);
+               $apcontact['addr'] = $apcontact['nick'] . '@' . str_replace('//', '', Network::unparseURL($parts));
+
+               $apcontact['pubkey'] = trim(JsonLD::fetchElement($data, 'publicKey', 'publicKeyPem'));
+
+               // To-Do
+               // manuallyApprovesFollowers
+
+               // Unhandled
+               // @context, tag, attachment, image, nomadicLocations, signature, following, followers, featured, movedTo, liked
+
+               // Unhandled from Misskey
+               // sharedInbox, isCat
+
+               // Unhandled from Kroeg
+               // kroeg:blocks, updated
+
+               // Check if the address is resolvable
+               if (self::addrToUrl($apcontact['addr']) == $apcontact['url']) {
+                       $parts = parse_url($apcontact['url']);
+                       unset($parts['path']);
+                       $apcontact['baseurl'] = Network::unparseURL($parts);
+               } else {
+                       $apcontact['addr'] = null;
+                       $apcontact['baseurl'] = null;
+               }
+
+               if ($apcontact['url'] == $apcontact['alias']) {
+                       $apcontact['alias'] = null;
+               }
+
+               $apcontact['updated'] = DateTimeFormat::utcNow();
+
+               DBA::update('apcontact', $apcontact, ['url' => $url], true);
+
+               // Update some data in the contact table with various ways to catch them all
+               $contact_fields = ['name' => $apcontact['name'], 'about' => $apcontact['about']];
+               DBA::update('contact', $contact_fields, ['nurl' => normalise_link($url)]);
+
+               $contacts = DBA::select('contact', ['uid', 'id'], ['nurl' => normalise_link($url)]);
+               while ($contact = DBA::fetch($contacts)) {
+                       Contact::updateAvatar($apcontact['photo'], $contact['uid'], $contact['id']);
+               }
+               DBA::close($contacts);
+
+               // Update the gcontact table
+               DBA::update('gcontact', $contact_fields, ['nurl' => normalise_link($url)]);
+
+               logger('Updated profile for ' . $url, LOGGER_DEBUG);
+
+               return $apcontact;
+       }
+}
index 1bbc0228a806a46dc7729ef1a852e7d12d53cb81..f1260c7c44f090087b84d1080af7014f499d7f1b 100644 (file)
@@ -16,6 +16,7 @@ use Friendica\Database\DBA;
 use Friendica\Model\Profile;
 use Friendica\Network\Probe;
 use Friendica\Object\Image;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Diaspora;
 use Friendica\Protocol\DFRN;
 use Friendica\Protocol\OStatus;
@@ -520,7 +521,7 @@ class Contact extends BaseObject
                }
 
                // Archive the contact
-               DBA::update('contact', ['archive' => true, 'network' => Protocol::PHANTOM], ['id' => $id]);
+               DBA::update('contact', ['archive' => true, 'network' => Protocol::PHANTOM, 'deleted' => true], ['id' => $id]);
 
                // Delete it in the background
                Worker::add(PRIORITY_LOW, 'RemoveContact', $id);
@@ -555,6 +556,12 @@ class Contact extends BaseObject
                        }
                } elseif ($contact['network'] == Protocol::DIASPORA) {
                        Diaspora::sendUnshare($user, $contact);
+               } elseif ($contact['network'] == Protocol::ACTIVITYPUB) {
+                       ActivityPub\Transmitter::sendContactUndo($contact['url'], $user['uid']);
+
+                       if ($dissolve) {
+                               ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $user['uid']);
+                       }
                }
        }
 
@@ -775,7 +782,7 @@ class Contact extends BaseObject
                }
 
                if ((empty($profile["addr"]) || empty($profile["name"])) && (defaults($profile, "gid", 0) != 0)
-                       && in_array($profile["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])
+                       && in_array($profile["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])
                ) {
                        Worker::add(PRIORITY_LOW, "UpdateGContact", $profile["gid"]);
                }
@@ -818,7 +825,7 @@ class Contact extends BaseObject
                // Fetch contact data from the contact table for the given user
                $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`,
                        `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`
-                       FROM `contact` WHERE `addr` = '%s' AND `uid` = %d",
+                       FROM `contact` WHERE `addr` = '%s' AND `uid` = %d AND NOT `deleted`",
                        DBA::escape($addr),
                        intval($uid)
                );
@@ -826,7 +833,7 @@ class Contact extends BaseObject
                if (!DBA::isResult($r)) {
                        $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`,
                                `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`
-                               FROM `contact` WHERE `addr` = '%s' AND `uid` = 0",
+                               FROM `contact` WHERE `addr` = '%s' AND `uid` = 0 AND NOT `deleted`",
                                DBA::escape($addr)
                        );
                }
@@ -1029,18 +1036,18 @@ class Contact extends BaseObject
 
                /// @todo Verify if we can't use Contact::getDetailsByUrl instead of the following
                // We first try the nurl (http://server.tld/nick), most common case
-               $contact = DBA::selectFirst('contact', ['id', 'avatar', 'avatar-date'], ['nurl' => normalise_link($url), 'uid' => $uid]);
+               $contact = DBA::selectFirst('contact', ['id', 'avatar', 'avatar-date'], ['nurl' => normalise_link($url), 'uid' => $uid, 'deleted' => false]);
 
                // Then the addr (nick@server.tld)
                if (!DBA::isResult($contact)) {
-                       $contact = DBA::selectFirst('contact', ['id', 'avatar', 'avatar-date'], ['addr' => $url, 'uid' => $uid]);
+                       $contact = DBA::selectFirst('contact', ['id', 'avatar', 'avatar-date'], ['addr' => $url, 'uid' => $uid, 'deleted' => false]);
                }
 
                // Then the alias (which could be anything)
                if (!DBA::isResult($contact)) {
                        // The link could be provided as http although we stored it as https
                        $ssl_url = str_replace('http://', 'https://', $url);
-                       $condition = ['`alias` IN (?, ?, ?) AND `uid` = ?', $url, normalise_link($url), $ssl_url, $uid];
+                       $condition = ['`alias` IN (?, ?, ?) AND `uid` = ? AND NOT `deleted`', $url, normalise_link($url), $ssl_url, $uid];
                        $contact = DBA::selectFirst('contact', ['id', 'avatar', 'avatar-date'], $condition);
                }
 
@@ -1054,7 +1061,6 @@ class Contact extends BaseObject
                        if (!x($contact, 'avatar')) {
                                $update_contact = true;
                        }
-
                        if (!$update_contact || $no_update) {
                                return $contact_id;
                        }
@@ -1088,7 +1094,7 @@ class Contact extends BaseObject
                }
 
                // Last try in gcontact for unsupported networks
-               if (!in_array($data["network"], [Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::PUMPIO, Protocol::MAIL, Protocol::FEED])) {
+               if (!in_array($data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::PUMPIO, Protocol::MAIL, Protocol::FEED])) {
                        if ($uid != 0) {
                                return 0;
                        }
@@ -1316,33 +1322,27 @@ class Contact extends BaseObject
 
                require_once 'include/conversation.php';
 
-               // There are no posts with "uid = 0" with connector networks
-               // This speeds up the query a lot
-               $r = q("SELECT `network`, `id` AS `author-id`, `contact-type` FROM `contact`
-                       WHERE `contact`.`nurl` = '%s' AND `contact`.`uid` = 0",
-                       DBA::escape(normalise_link($contact_url))
-               );
+               $cid = Self::getIdForURL($contact_url);
 
-               if (!DBA::isResult($r)) {
+               $contact = DBA::selectFirst('contact', ['contact-type', 'network'], ['id' => $cid]);
+               if (!DBA::isResult($contact)) {
                        return '';
                }
 
-               if (in_array($r[0]["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""])) {
+               if (in_array($contact["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""])) {
                        $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`))";
                } else {
                        $sql = "`item`.`uid` = ?";
                }
 
-               $author_id = intval($r[0]["author-id"]);
-
-               $contact = ($r[0]["contact-type"] == self::ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id');
+               $contact_field = ($contact["contact-type"] == self::ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id');
 
                if ($thread_mode) {
-                       $condition = ["`$contact` = ? AND `gravity` = ? AND " . $sql,
-                               $author_id, GRAVITY_PARENT, local_user()];
+                       $condition = ["`$contact_field` = ? AND `gravity` = ? AND " . $sql,
+                               $cid, GRAVITY_PARENT, local_user()];
                } else {
-                       $condition = ["`$contact` = ? AND `gravity` IN (?, ?) AND " . $sql,
-                               $author_id, GRAVITY_PARENT, GRAVITY_COMMENT, local_user()];
+                       $condition = ["`$contact_field` = ? AND `gravity` IN (?, ?) AND " . $sql,
+                               $cid, GRAVITY_PARENT, GRAVITY_COMMENT, local_user()];
                }
 
                $params = ['order' => ['created' => true],
@@ -1495,10 +1495,11 @@ class Contact extends BaseObject
        }
 
        /**
-        * @param integer $id contact id
+        * @param integer $id      contact id
+        * @param string  $network Optional network we are probing for
         * @return boolean
         */
-       public static function updateFromProbe($id)
+       public static function updateFromProbe($id, $network = '')
        {
                /*
                  Warning: Never ever fetch the public key via Probe::uri and write it into the contacts.
@@ -1511,10 +1512,10 @@ class Contact extends BaseObject
                        return false;
                }
 
-               $ret = Probe::uri($contact["url"]);
+               $ret = Probe::uri($contact["url"], $network);
 
                // If Probe::uri fails the network code will be different
-               if ($ret["network"] != $contact["network"]) {
+               if (($ret["network"] != $contact["network"]) && !in_array($ret["network"], [Protocol::ACTIVITYPUB, $network])) {
                        return false;
                }
 
@@ -1537,14 +1538,15 @@ class Contact extends BaseObject
 
                DBA::update(
                        'contact', [
-                               'url'    => $ret['url'],
-                               'nurl'   => normalise_link($ret['url']),
-                               'addr'   => $ret['addr'],
-                               'alias'  => $ret['alias'],
-                               'batch'  => $ret['batch'],
-                               'notify' => $ret['notify'],
-                               'poll'   => $ret['poll'],
-                               'poco'   => $ret['poco']
+                               'url'     => $ret['url'],
+                               'nurl'    => normalise_link($ret['url']),
+                               'network' => $ret['network'],
+                               'addr'    => $ret['addr'],
+                               'alias'   => $ret['alias'],
+                               'batch'   => $ret['batch'],
+                               'notify'  => $ret['notify'],
+                               'poll'    => $ret['poll'],
+                               'poco'    => $ret['poco']
                        ],
                        ['id' => $id]
                );
@@ -1630,10 +1632,10 @@ class Contact extends BaseObject
 
                if (($ret['network'] === Protocol::DFRN) && !DBA::isResult($contact)) {
                        if ($interactive) {
-                               if (strlen($a->urlpath)) {
+                               if (strlen($a->getURLPath())) {
                                        $myaddr = bin2hex(System::baseUrl() . '/profile/' . $a->user['nickname']);
                                } else {
-                                       $myaddr = bin2hex($a->user['nickname'] . '@' . $a->get_hostname());
+                                       $myaddr = bin2hex($a->user['nickname'] . '@' . $a->getHostName());
                                }
 
                                goaway($ret['request'] . "&addr=$myaddr");
@@ -1686,7 +1688,7 @@ class Contact extends BaseObject
 
                $hidden = (($ret['network'] === Protocol::MAIL) ? 1 : 0);
 
-               if (in_array($ret['network'], [Protocol::MAIL, Protocol::DIASPORA])) {
+               if (in_array($ret['network'], [Protocol::MAIL, Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
                        $writeable = 1;
                }
 
@@ -1766,6 +1768,9 @@ class Contact extends BaseObject
                        } elseif ($contact['network'] == Protocol::DIASPORA) {
                                $ret = Diaspora::sendShare($a->user, $contact);
                                logger('share returns: ' . $ret);
+                       } elseif ($contact['network'] == Protocol::ACTIVITYPUB) {
+                               $ret = ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $uid);
+                               logger('Follow returns: ' . $ret);
                        }
                }
 
@@ -1814,7 +1819,7 @@ class Contact extends BaseObject
                return $contact;
        }
 
-       public static function addRelationship($importer, $contact, $datarray, $item, $sharing = false) {
+       public static function addRelationship($importer, $contact, $datarray, $item = '', $sharing = false) {
                // Should always be set
                if (empty($datarray['author-id'])) {
                        return;
@@ -1827,7 +1832,7 @@ class Contact extends BaseObject
                        return;
                }
 
-               $url = $pub_contact['url'];
+               $url = defaults($datarray, 'author-link', $pub_contact['url']);
                $name = $pub_contact['name'];
                $photo = $pub_contact['photo'];
                $nick = $pub_contact['nick'];
@@ -1839,13 +1844,17 @@ class Contact extends BaseObject
                                DBA::update('contact', ['rel' => self::FRIEND, 'writable' => true],
                                                ['id' => $contact['id'], 'uid' => $importer['uid']]);
                        }
+
+                       if ($contact['network'] == Protocol::ACTIVITYPUB) {
+                               ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']);
+                       }
+
                        // send email notification to owner?
                } else {
                        if (DBA::exists('contact', ['nurl' => normalise_link($url), 'uid' => $importer['uid'], 'pending' => true])) {
                                logger('ignoring duplicated connection request from pending contact ' . $url);
                                return;
                        }
-
                        // create contact record
                        q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,
                                `blocked`, `readonly`, `pending`, `writable`)
@@ -1908,6 +1917,12 @@ class Contact extends BaseObject
                        } elseif (DBA::isResult($user) && in_array($user['page-flags'], [self::PAGE_SOAPBOX, self::PAGE_FREELOVE, self::PAGE_COMMUNITY])) {
                                $condition = ['uid' => $importer['uid'], 'url' => $url, 'pending' => true];
                                DBA::update('contact', ['pending' => false], $condition);
+
+                               $contact = DBA::selectFirst('contact', ['url', 'network', 'hub-verify'], ['id' => $contact_record['id']]);
+
+                               if ($contact['network'] == Protocol::ACTIVITYPUB) {
+                                       ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']);
+                               }
                        }
                }
        }
index 0692a7341234f66f81530474270af6e4a64f85e8..be1eaf2295582a7e1bb1e0777cd7410a63e56f83 100644 (file)
@@ -17,13 +17,14 @@ class Conversation
         * These constants represent the parcel format used to transport a conversation independently of the message protocol.
         * It currently is stored in the "protocol" field for legacy reasons.
         */
-       const PARCEL_UNKNOWN            = 0;
+       const PARCEL_ACTIVITYPUB        = 0;
        const PARCEL_DFRN               = 1;
        const PARCEL_DIASPORA           = 2;
        const PARCEL_SALMON             = 3;
        const PARCEL_FEED               = 4; // Deprecated
        const PARCEL_SPLIT_CONVERSATION = 6;
        const PARCEL_TWITTER            = 67;
+       const PARCEL_UNKNOWN            = 255;
 
        /**
         * @brief Store the conversation data
@@ -34,7 +35,7 @@ class Conversation
        public static function insert(array $arr)
        {
                if (in_array(defaults($arr, 'network', Protocol::PHANTOM),
-                               [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, Protocol::TWITTER]) && !empty($arr['uri'])) {
+                       [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, Protocol::TWITTER]) && !empty($arr['uri'])) {
                        $conversation = ['item-uri' => $arr['uri'], 'received' => DateTimeFormat::utcNow()];
 
                        if (isset($arr['parent-uri']) && ($arr['parent-uri'] != $arr['uri'])) {
@@ -70,7 +71,8 @@ class Conversation
                                        unset($old_conv['source']);
                                }
                                // Update structure data all the time but the source only when its from a better protocol.
-                               if (isset($conversation['protocol']) && isset($conversation['source']) && ($old_conv['protocol'] < $conversation['protocol']) && ($old_conv['protocol'] != 0)) {
+                               if (empty($conversation['source']) || (!empty($old_conv['source']) &&
+                                       ($old_conv['protocol'] < defaults($conversation, 'protocol', PARCEL_UNKNOWN)))) {
                                        unset($conversation['protocol']);
                                        unset($conversation['source']);
                                }
index 016d1f8d9e3974a47ec0197223a1ec4fda5ece83..452017e69d3a04bcfbd2269d851b1db69340f9ee 100644 (file)
@@ -314,7 +314,7 @@ class Event extends BaseObject
 
                        Addon::callHooks('event_updated', $event['id']);
                } else {
-                       $event['guid']  = defaults($arr, 'guid', System::createGUID(32));
+                       $event['guid']  = defaults($arr, 'guid', System::createUUID());
 
                        // New event. Store it.
                        DBA::insert('event', $event);
index 18d817161507b6f245d3e7b83367eb164837535d..26cb11175c5b48573f638ec1d7e3eec9bb8a2e42 100644 (file)
@@ -61,11 +61,11 @@ class GContact
                $search .= "%";
 
                $results = DBA::p("SELECT `nurl` FROM `gcontact`
-                       WHERE NOT `hide` AND `network` IN (?, ?, ?) AND
+                       WHERE NOT `hide` AND `network` IN (?, ?, ?, ?) AND
                                ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
                                (`addr` LIKE ? OR `name` LIKE ? OR `nick` LIKE ?) $extra_sql
                                GROUP BY `nurl` ORDER BY `nurl` DESC LIMIT 1000",
-                       Protocol::DFRN, $ostatus, $diaspora, $search, $search, $search
+                       Protocol::DFRN, Protocol::ACTIVITYPUB, $ostatus, $diaspora, $search, $search, $search
                );
 
                $gcontacts = [];
@@ -138,7 +138,7 @@ class GContact
                }
 
                // Assure that there are no parameter fragments in the profile url
-               if (in_array($gcontact['network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""])) {
+               if (in_array($gcontact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""])) {
                        $gcontact['url'] = self::cleanContactUrl($gcontact['url']);
                }
 
@@ -214,7 +214,7 @@ class GContact
                        throw new Exception('No name and photo for URL '.$gcontact['url']);
                }
 
-               if (!in_array($gcontact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) {
+               if (!in_array($gcontact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) {
                        throw new Exception('No federated network ('.$gcontact['network'].') detected for URL '.$gcontact['url']);
                }
 
@@ -651,7 +651,7 @@ class GContact
                self::fixAlternateContactAddress($contact);
 
                // Remove unwanted parts from the contact url (e.g. "?zrl=...")
-               if (in_array($contact["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
+               if (in_array($contact["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
                        $contact["url"] = self::cleanContactUrl($contact["url"]);
                }
 
@@ -957,12 +957,12 @@ class GContact
 
                $url = $server."/main/statistics";
 
-               $result = Network::curl($url);
-               if (!$result["success"]) {
+               $curlResult = Network::curl($url);
+               if (!$curlResult->isSuccess()) {
                        return false;
                }
 
-               $statistics = json_decode($result["body"]);
+               $statistics = json_decode($curlResult->getBody());
 
                if (!empty($statistics->config)) {
                        if ($statistics->config->instance_with_ssl) {
index 748dccadfab598c0385d23fbf2e83e924aa95917..ed80f4e9e802acf735b6adf4e47225afd6a33f86 100644 (file)
@@ -176,7 +176,7 @@ class Item extends BaseObject
 
                // We can always comment on posts from these networks
                if (array_key_exists('writable', $row) &&
-                       in_array($row['internal-network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
+                       in_array($row['internal-network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
                        $row['writable'] = true;
                }
 
@@ -1081,9 +1081,8 @@ class Item extends BaseObject
 
                DBA::delete('item-delivery-data', ['iid' => $item['id']]);
 
-               if (!empty($item['iaid']) && !self::exists(['iaid' => $item['iaid'], 'deleted' => false])) {
-                       DBA::delete('item-activity', ['id' => $item['iaid']], ['cascade' => false]);
-               }
+               // We don't delete the item-activity here, since we need some of the data for ActivityPub
+
                if (!empty($item['icid']) && !self::exists(['icid' => $item['icid'], 'deleted' => false])) {
                        DBA::delete('item-content', ['id' => $item['icid']], ['cascade' => false]);
                }
@@ -1167,7 +1166,7 @@ class Item extends BaseObject
                if ($notify) {
                        // We have to avoid duplicates. So we create the GUID in form of a hash of the plink or uri.
                        // We add the hash of our own host because our host is the original creator of the post.
-                       $prefix_host = get_app()->get_hostname();
+                       $prefix_host = get_app()->getHostName();
                } else {
                        $prefix_host = '';
 
@@ -1205,7 +1204,7 @@ class Item extends BaseObject
                } elseif (!empty($item['uri'])) {
                        $guid = self::guidFromUri($item['uri'], $prefix_host);
                } else {
-                       $guid = System::createGUID(32, hash('crc32', $prefix_host));
+                       $guid = System::createUUID(hash('crc32', $prefix_host));
                }
 
                return $guid;
@@ -1290,17 +1289,16 @@ class Item extends BaseObject
                 */
 
                $dsprsig = null;
-               if (x($item, 'dsprsig')) {
+               if (isset($item['dsprsig'])) {
                        $encoded_signature = $item['dsprsig'];
                        $dsprsig = json_decode(base64_decode($item['dsprsig']));
                        unset($item['dsprsig']);
                }
 
-               if (!empty($item['diaspora_signed_text'])) {
+               $diaspora_signed_text = '';
+               if (isset($item['diaspora_signed_text'])) {
                        $diaspora_signed_text = $item['diaspora_signed_text'];
                        unset($item['diaspora_signed_text']);
-               } else {
-                       $diaspora_signed_text = '';
                }
 
                // Converting the plink
@@ -1352,7 +1350,7 @@ class Item extends BaseObject
                 * We have to check several networks since Friendica posts could be repeated
                 * via OStatus (maybe Diasporsa as well)
                 */
-               if (in_array($item['network'], [Protocol::DIASPORA, Protocol::DFRN, Protocol::OSTATUS, ""])) {
+               if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DIASPORA, Protocol::DFRN, Protocol::OSTATUS, ""])) {
                        $condition = ["`uri` = ? AND `uid` = ? AND `network` IN (?, ?, ?)",
                                trim($item['uri']), $item['uid'],
                                Protocol::DIASPORA, Protocol::DFRN, Protocol::OSTATUS];
@@ -1489,6 +1487,7 @@ class Item extends BaseObject
                $deny_gid  = '';
 
                if ($item['parent-uri'] === $item['uri']) {
+                       $diaspora_signed_text = '';
                        $parent_id = 0;
                        $parent_deleted = 0;
                        $allow_cid = $item['allow_cid'];
@@ -1535,6 +1534,10 @@ class Item extends BaseObject
                                $item['wall']    = $parent['wall'];
                                $notify_type    = 'comment-new';
 
+                               if (!$parent['origin']) {
+                                       $diaspora_signed_text = '';
+                               }
+
                                /*
                                 * If the parent is private, force privacy for the entire conversation
                                 * This differs from the above settings as it subtly allows comments from
@@ -1575,6 +1578,7 @@ class Item extends BaseObject
                                        $parent_id = 0;
                                        $item['parent-uri'] = $item['uri'];
                                        $item['gravity'] = GRAVITY_PARENT;
+                                       $diaspora_signed_text = '';
                                } else {
                                        logger('item parent '.$item['parent-uri'].' for '.$item['uid'].' was not found - ignoring item');
                                        return 0;
@@ -2054,7 +2058,7 @@ class Item extends BaseObject
 
                // Only distribute public items from native networks
                $condition = ['id' => $itemid, 'uid' => 0,
-                       'network' => [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""],
+                       'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""],
                        'visible' => true, 'deleted' => false, 'moderated' => false, 'private' => false];
                $item = self::selectFirst(self::ITEM_FIELDLIST, ['id' => $itemid]);
                if (!DBA::isResult($item)) {
@@ -2072,14 +2076,46 @@ class Item extends BaseObject
 
                $users = [];
 
-               $condition = ["`nurl` IN (SELECT `nurl` FROM `contact` WHERE `id` = ?) AND `uid` != 0 AND NOT `blocked` AND `rel` IN (?, ?)",
-                       $parent['owner-id'], Contact::SHARING,  Contact::FRIEND];
+               /// @todo add a field "pcid" in the contact table that referrs to the public contact id.
+               $owner = DBA::selectFirst('contact', ['url', 'nurl', 'alias'], ['id' => $parent['owner-id']]);
+               if (!DBA::isResult($owner)) {
+                       return;
+               }
 
+               $condition = ['nurl' => $owner['nurl'], 'rel' => [Contact::SHARING, Contact::FRIEND]];
                $contacts = DBA::select('contact', ['uid'], $condition);
+               while ($contact = DBA::fetch($contacts)) {
+                       if ($contact['uid'] == 0) {
+                               continue;
+                       }
 
+                       $users[$contact['uid']] = $contact['uid'];
+               }
+               DBA::close($contacts);
+
+               $condition = ['alias' => $owner['url'], 'rel' => [Contact::SHARING, Contact::FRIEND]];
+               $contacts = DBA::select('contact', ['uid'], $condition);
                while ($contact = DBA::fetch($contacts)) {
+                       if ($contact['uid'] == 0) {
+                               continue;
+                       }
+
                        $users[$contact['uid']] = $contact['uid'];
                }
+               DBA::close($contacts);
+
+               if (!empty($owner['alias'])) {
+                       $condition = ['url' => $owner['alias'], 'rel' => [Contact::SHARING, Contact::FRIEND]];
+                       $contacts = DBA::select('contact', ['uid'], $condition);
+                       while ($contact = DBA::fetch($contacts)) {
+                               if ($contact['uid'] == 0) {
+                                       continue;
+                               }
+
+                               $users[$contact['uid']] = $contact['uid'];
+                       }
+                       DBA::close($contacts);
+               }
 
                $origin_uid = 0;
 
@@ -2176,7 +2212,7 @@ class Item extends BaseObject
                }
 
                // is it an entry from a connector? Only add an entry for natively connected networks
-               if (!in_array($item["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""])) {
+               if (!in_array($item["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, ""])) {
                        return;
                }
 
@@ -2327,16 +2363,10 @@ class Item extends BaseObject
        public static function newURI($uid, $guid = "")
        {
                if ($guid == "") {
-                       $guid = System::createGUID(32);
+                       $guid = System::createUUID();
                }
 
-               $hostname = self::getApp()->get_hostname();
-
-               $user = DBA::selectFirst('user', ['nickname'], ['uid' => $uid]);
-
-               $uri = "urn:X-dfrn:" . $hostname . ':' . $user['nickname'] . ':' . $guid;
-
-               return $uri;
+               return self::getApp()->getBaseURL() . '/objects/' . $guid;
        }
 
        /**
@@ -2619,7 +2649,7 @@ class Item extends BaseObject
                }
 
                // Prevent to forward already forwarded posts
-               if ($datarray["app"] == $a->get_hostname()) {
+               if ($datarray["app"] == $a->getHostName()) {
                        logger('Already forwarded (second test)', LOGGER_DEBUG);
                        return false;
                }
@@ -2660,7 +2690,7 @@ class Item extends BaseObject
                        }
 
                        if ($contact['network'] != Protocol::FEED) {
-                               $datarray["guid"] = System::createGUID(32);
+                               $datarray["guid"] = System::createUUID();
                                unset($datarray["plink"]);
                                $datarray["uri"] = self::newURI($contact['uid'], $datarray["guid"]);
                                $datarray["parent-uri"] = $datarray["uri"];
@@ -2826,7 +2856,7 @@ class Item extends BaseObject
        }
 
        // returns an array of contact-ids that are allowed to see this object
-       private static function enumeratePermissions($obj)
+       public static function enumeratePermissions($obj)
        {
                $allow_people = expand_acl($obj['allow_cid']);
                $allow_groups = Group::expand(expand_acl($obj['allow_gid']));
@@ -3086,10 +3116,10 @@ class Item extends BaseObject
                        return true;
                }
 
-               $objtype = $item['resource-id'] ? ACTIVITY_OBJ_IMAGE : ACTIVITY_OBJ_NOTE ;
+               $objtype = $item['resource-id'] ? ACTIVITY_OBJ_IMAGE : ACTIVITY_OBJ_NOTE;
 
                $new_item = [
-                       'guid'          => System::createGUID(32),
+                       'guid'          => System::createUUID(),
                        'uri'           => self::newURI($item['uid']),
                        'uid'           => $item['uid'],
                        'contact-id'    => $item_contact_id,
@@ -3100,7 +3130,7 @@ class Item extends BaseObject
                        'parent'        => $item['id'],
                        'parent-uri'    => $item['uri'],
                        'thr-parent'    => $item['uri'],
-                       'owner-id'      => $item['owner-id'],
+                       'owner-id'      => $author_id,
                        'author-id'     => $author_id,
                        'body'          => $activity,
                        'verb'          => $activity,
index 24a174b6b58251df7c5dd674c4ad75d207c50b46..49247ca69dfb1385eabd53cae08fd9144c4baab6 100644 (file)
@@ -46,7 +46,7 @@ class Mail
                        return -2;
                }
 
-               $guid = System::createGUID(32);
+               $guid = System::createUUID();
                $uri = 'urn:X-dfrn:' . System::baseUrl() . ':' . local_user() . ':' . $guid;
 
                $convid = 0;
@@ -73,7 +73,7 @@ class Mail
                        $recip_handle = (($contact['addr']) ? $contact['addr'] : $contact['nick'] . '@' . $recip_host);
                        $sender_handle = $a->user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
 
-                       $conv_guid = System::createGUID(32);
+                       $conv_guid = System::createUUID();
                        $convuri = $recip_handle . ':' . $conv_guid;
 
                        $handles = $recip_handle . ';' . $sender_handle;
@@ -171,7 +171,7 @@ class Mail
                        $subject = L10n::t('[no subject]');
                }
 
-               $guid = System::createGUID(32);
+               $guid = System::createUUID();
                $uri = 'urn:X-dfrn:' . System::baseUrl() . ':' . local_user() . ':' . $guid;
 
                $me = Probe::uri($replyto);
@@ -180,7 +180,7 @@ class Mail
                        return -2;
                }
 
-               $conv_guid = System::createGUID(32);
+               $conv_guid = System::createUUID();
 
                $recip_handle = $recipient['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
 
index 555df80e63df689fea8f056f22586783857f0574..e64158e175ced54a67d79fecf190be2965c561b5 100644 (file)
@@ -146,7 +146,7 @@ class Photo
 
                        // Remove the cached photo
                        $a = get_app();
-                       $basepath = $a->get_basepath();
+                       $basepath = $a->getBasePath();
 
                        if (is_dir($basepath . "/photo")) {
                                $filename = $basepath . '/photo/' . $hash . '-4.' . $Image->getExt();
index 3a014517da9b158875c176c4654c0428e3686f95..28736750bdd9638d80b24cf961f431fc7afca291 100644 (file)
@@ -28,6 +28,19 @@ require_once 'include/dba.php';
 
 class Profile
 {
+       /**
+        * @brief Returns default profile for a given user id
+        *
+        * @param integer User ID
+        *
+        * @return array Profile data
+        */
+       public static function getByUID($uid)
+       {
+               $profile = DBA::selectFirst('profile', [], ['uid' => $uid, 'is-default' => true]);
+               return $profile;
+       }
+
        /**
         * @brief Returns a formatted location string from the given profile array
         *
@@ -149,7 +162,7 @@ class Profile
                * load/reload current theme info
                */
 
-               $a->set_template_engine(); // reset the template engine to the default in case the user's theme doesn't specify one
+               $a->setActiveTemplateEngine(); // reset the template engine to the default in case the user's theme doesn't specify one
 
                $theme_info_file = 'view/theme/' . $a->getCurrentTheme() . '/theme.php';
                if (file_exists($theme_info_file)) {
@@ -1043,7 +1056,7 @@ class Profile
                                if ($basepath != System::baseUrl() && !strstr($dest, '/magic') && !strstr($dest, '/rmagic')) {
                                        $magic_path = $basepath . '/magic' . '?f=&owa=1&dest=' . $dest;
                                        $serverret = Network::curl($magic_path);
-                                       if (!empty($serverret['success'])) {
+                                       if ($serverret->isSuccess()) {
                                                goaway($magic_path);
                                        }
                                }
@@ -1103,7 +1116,7 @@ class Profile
 
                $a->contact = $arr['visitor'];
 
-               info(L10n::t('OpenWebAuth: %1$s welcomes %2$s', $a->get_hostname(), $visitor['name']));
+               info(L10n::t('OpenWebAuth: %1$s welcomes %2$s', $a->getHostName(), $visitor['name']));
 
                logger('OpenWebAuth: auth success from ' . $visitor['addr'], LOGGER_DEBUG);
        }
index a81241cb42af31298fe95bea2d64753d3d04c79f..854861ccb589b022609d48000a7b21f0d2ce286c 100644 (file)
@@ -33,6 +33,17 @@ class Term
                return $tag_text;
        }
 
+       public static function tagArrayFromItemId($itemid, $type = [TERM_HASHTAG, TERM_MENTION])
+       {
+               $condition = ['otype' => TERM_OBJ_POST, 'oid' => $itemid, 'type' => $type];
+               $tags = DBA::select('term', ['type', 'term', 'url'], $condition);
+               if (!DBA::isResult($tags)) {
+                       return [];
+               }
+
+               return DBA::toArray($tags);
+       }
+
        public static function fileTextFromItemId($itemid)
        {
                $file_text = '';
@@ -99,6 +110,18 @@ class Term
                $pattern = '/\W([\#@])\[url\=(.*?)\](.*?)\[\/url\]/ism';
                if (preg_match_all($pattern, $data, $matches, PREG_SET_ORDER)) {
                        foreach ($matches as $match) {
+
+                               if ($match[1] == '@') {
+                                       $contact = Contact::getDetailsByURL($match[2], 0);
+                                       if (!empty($contact['addr'])) {
+                                               $match[3] = $contact['addr'];
+                                       }
+
+                                       if (!empty($contact['url'])) {
+                                               $match[2] = $contact['url'];
+                                       }
+                               }
+
                                $tags[$match[1] . trim($match[3], ',.:;[]/\"?!')] = $match[2];
                        }
                }
@@ -119,12 +142,22 @@ class Term
                                $term = substr($tag, 1);
                        } elseif (substr(trim($tag), 0, 1) == '@') {
                                $type = TERM_MENTION;
-                               $term = substr($tag, 1);
+
+                               $contact = Contact::getDetailsByURL($link, 0);
+                               if (!empty($contact['name'])) {
+                                       $term = $contact['name'];
+                               } else {
+                                       $term = substr($tag, 1);
+                               }
                        } else { // This shouldn't happen
                                $type = TERM_HASHTAG;
                                $term = $tag;
                        }
 
+                       if (DBA::exists('term', ['uid' => $message['uid'], 'otype' => TERM_OBJ_POST, 'oid' => $itemid, 'url' => $link])) {
+                               continue;
+                       }
+
                        if ($message['uid'] == 0) {
                                $global = true;
                                DBA::update('term', ['global' => true], ['otype' => TERM_OBJ_POST, 'guid' => $message['guid']]);
index d65e7d8f9699e41aabadb406bd3034bd7da2266f..b8b694de87194a6bd6e143c9672c4b49782e9e2d 100644 (file)
@@ -31,6 +31,23 @@ require_once 'include/text.php';
  */
 class User
 {
+       /**
+        * @brief Returns the user id of a given profile url
+        *
+        * @param string $profile
+        *
+        * @return integer user id
+        */
+       public static function getIdForURL($url)
+       {
+               $self = DBA::selectFirst('contact', ['uid'], ['nurl' => normalise_link($url), 'self' => true]);
+               if (!DBA::isResult($self)) {
+                       return false;
+               } else {
+                       return $self['uid'];
+               }
+       }
+
        /**
         * @brief Get owner data by user id
         *
@@ -397,7 +414,7 @@ class User
                                $_SESSION['register'] = 1;
                                $_SESSION['openid'] = $openid_url;
 
-                               $openid = new LightOpenID($a->get_hostname());
+                               $openid = new LightOpenID($a->getHostName());
                                $openid->identity = $openid_url;
                                $openid->returnUrl = System::baseUrl() . '/openid';
                                $openid->required = ['namePerson/friendly', 'contact/email', 'namePerson'];
@@ -495,7 +512,7 @@ class User
                $spubkey = $sres['pubkey'];
 
                $insert_result = DBA::insert('user', [
-                       'guid'     => System::createGUID(32),
+                       'guid'     => System::createUUID(),
                        'username' => $username,
                        'password' => $new_password_encoded,
                        'email'    => $email,
diff --git a/src/Module/Acctlink.php b/src/Module/Acctlink.php
new file mode 100644 (file)
index 0000000..29aa991
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Network\Probe;
+
+/**
+ * Redirects to another URL based on the parameter 'addr'
+ */
+class Acctlink extends BaseModule
+{
+       public static function content()
+       {
+               $addr = defaults($_GET, 'addr', false);
+
+               if ($addr) {
+                       $url = defaults(Probe::uri(trim($addr)), 'url', false);
+
+                       if ($url) {
+                               goaway($url);
+                               exit();
+                       }
+               }
+       }
+}
diff --git a/src/Module/Followers.php b/src/Module/Followers.php
new file mode 100644 (file)
index 0000000..56160ae
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @file src/Module/Followers.php
+ */
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Core\System;
+use Friendica\Model\User;
+
+/**
+ * ActivityPub Followers
+ */
+class Followers extends BaseModule
+{
+       public static function rawContent()
+       {
+               $a = self::getApp();
+
+               if (empty($a->argv[1])) {
+                       System::httpExit(404);
+               }
+
+               $owner = User::getOwnerDataByNick($a->argv[1]);
+               if (empty($owner)) {
+                       System::httpExit(404);
+               }
+
+               $page = defaults($_REQUEST, 'page', null);
+
+               $followers = ActivityPub\Transmitter::getFollowers($owner, $page);
+
+               header('Content-Type: application/activity+json');
+               echo json_encode($followers);
+               exit();
+       }
+}
diff --git a/src/Module/Following.php b/src/Module/Following.php
new file mode 100644 (file)
index 0000000..71e6613
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @file src/Module/Following.php
+ */
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Core\System;
+use Friendica\Model\User;
+
+/**
+ * ActivityPub Following
+ */
+class Following extends BaseModule
+{
+       public static function rawContent()
+       {
+               $a = self::getApp();
+
+               if (empty($a->argv[1])) {
+                       System::httpExit(404);
+               }
+
+               $owner = User::getOwnerDataByNick($a->argv[1]);
+               if (empty($owner)) {
+                       System::httpExit(404);
+               }
+
+               $page = defaults($_REQUEST, 'page', null);
+
+               $Following = ActivityPub\Transmitter::getFollowing($owner, $page);
+
+               header('Content-Type: application/activity+json');
+               echo json_encode($Following);
+               exit();
+       }
+}
diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php
new file mode 100644 (file)
index 0000000..c190be4
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @file src/Module/Inbox.php
+ */
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Core\System;
+use Friendica\Database\DBA;
+use Friendica\Util\HTTPSignature;
+
+/**
+ * ActivityPub Inbox
+ */
+class Inbox extends BaseModule
+{
+       public static function rawContent()
+       {
+               $a = self::getApp();
+
+               $postdata = file_get_contents('php://input');
+
+               if (empty($postdata)) {
+                       System::httpExit(400);
+               }
+
+// Enable for test purposes
+/*
+               if (HTTPSignature::getSigner($postdata, $_SERVER)) {
+                       $filename = 'signed-activitypub';
+               } else {
+                       $filename = 'failed-activitypub';
+               }
+
+               $tempfile = tempnam(get_temppath(), $filename);
+               file_put_contents($tempfile, json_encode(['argv' => $a->argv, 'header' => $_SERVER, 'body' => $postdata], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
+
+               logger('Incoming message stored under ' . $tempfile);
+*/
+               if (!empty($a->argv[1])) {
+                       $user = DBA::selectFirst('user', ['uid'], ['nickname' => $a->argv[1]]);
+                       if (!DBA::isResult($user)) {
+                               System::httpExit(404);
+                       }
+                       $uid = $user['uid'];
+               } else {
+                       $uid = 0;
+               }
+
+               ActivityPub\Receiver::processInbox($postdata, $_SERVER, $uid);
+
+               System::httpExit(202);
+       }
+}
index fadfb206612c3bd728f00efa276b453372ba280a..15505a38be61295c8118d9b449a4da51b2daed7b 100644 (file)
@@ -39,15 +39,18 @@ class Login extends BaseModule
                }
 
                if (local_user()) {
-                       goaway(self::getApp()->get_baseurl());
+                       goaway(self::getApp()->getBaseURL());
                }
 
-               return self::form(self::getApp()->get_baseurl(), intval(Config::get('config', 'register_policy')) !== REGISTER_CLOSED);
+               return self::form($_SESSION['return_url'], intval(Config::get('config', 'register_policy')) !== REGISTER_CLOSED);
        }
 
        public static function post()
        {
+               $return_url = $_SESSION['return_url'];
                session_unset();
+               $_SESSION['return_url'] = $return_url;
+               
                // OpenId Login
                if (
                        empty($_POST['password'])
@@ -83,18 +86,18 @@ class Login extends BaseModule
                // if it's an email address or doesn't resolve to a URL, fail.
                if ($noid || strpos($openid_url, '@') || !Network::isUrlValid($openid_url)) {
                        notice(L10n::t('Login failed.') . EOL);
-                       goaway(self::getApp()->get_baseurl());
+                       goaway(self::getApp()->getBaseURL());
                        // NOTREACHED
                }
 
                // Otherwise it's probably an openid.
                try {
                        $a = get_app();
-                       $openid = new LightOpenID($a->get_hostname());
+                       $openid = new LightOpenID($a->getHostName());
                        $openid->identity = $openid_url;
                        $_SESSION['openid'] = $openid_url;
                        $_SESSION['remember'] = $remember;
-                       $openid->returnUrl = self::getApp()->get_baseurl(true) . '/openid';
+                       $openid->returnUrl = self::getApp()->getBaseURL(true) . '/openid';
                        goaway($openid->authUrl());
                } catch (Exception $e) {
                        notice(L10n::t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.') . '<br /><br >' . L10n::t('The error message was:') . ' ' . $e->getMessage());
@@ -140,8 +143,8 @@ class Login extends BaseModule
                        }
                } catch (Exception $e) {
                        logger('authenticate: failed login attempt: ' . notags($username) . ' from IP ' . $_SERVER['REMOTE_ADDR']);
-                       notice($e->getMessage() . EOL);
-                       goaway(self::getApp()->get_baseurl() . '/login');
+                       info('Login failed. Please check your credentials.' . EOL);
+                       goaway('/');
                }
 
                if (!$remember) {
@@ -188,7 +191,7 @@ class Login extends BaseModule
                                        if ($data->hash != cookie_hash($user)) {
                                                logger("Hash for user " . $data->uid . " doesn't fit.");
                                                nuke_session();
-                                               goaway(self::getApp()->get_baseurl());
+                                               goaway(self::getApp()->getBaseURL());
                                        }
 
                                        // Renew the cookie
@@ -225,7 +228,7 @@ class Login extends BaseModule
                                        logger('Session address changed. Paranoid setting in effect, blocking session. ' .
                                                $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
                                        nuke_session();
-                                       goaway(self::getApp()->get_baseurl());
+                                       goaway(self::getApp()->getBaseURL());
                                }
 
                                $user = DBA::selectFirst('user', [],
@@ -239,7 +242,7 @@ class Login extends BaseModule
                                );
                                if (!DBA::isResult($user)) {
                                        nuke_session();
-                                       goaway(self::getApp()->get_baseurl());
+                                       goaway(self::getApp()->getBaseURL());
                                }
 
                                // Make sure to refresh the last login time for the user if the user
@@ -294,7 +297,7 @@ class Login extends BaseModule
                        $a->page['htmlhead'] .= replace_macros(
                                get_markup_template('login_head.tpl'),
                                [
-                                       '$baseurl' => $a->get_baseurl(true)
+                                       '$baseurl' => $a->getBaseURL(true)
                                ]
                        );
 
@@ -305,7 +308,7 @@ class Login extends BaseModule
                $o .= replace_macros(
                        $tpl,
                        [
-                               '$dest_url'     => self::getApp()->get_baseurl(true) . '/login',
+                               '$dest_url'     => self::getApp()->getBaseURL(true) . '/login',
                                '$logout'       => L10n::t('Logout'),
                                '$login'        => L10n::t('Login'),
 
index bfa917a393fa427f3b574aa285a21246aabefbf6..cbfd245f302f47f276cff27f8ee1ab1e192d0459 100644 (file)
@@ -26,6 +26,6 @@ class Logout extends BaseModule
                Addon::callHooks("logging_out");
                nuke_session();
                info(L10n::t('Logged out.') . EOL);
-               goaway(self::getApp()->get_baseurl());
+               goaway(self::getApp()->getBaseURL());
        }
 }
index cf77482e5a8eec13d719bade0afdf9ada4bc2064..768fe69ebbedb94e410f2d6de19e8ba9e55d82ba 100644 (file)
@@ -47,7 +47,7 @@ class Magic extends BaseModule
                $contact = DBA::selectFirst('contact', ['id', 'nurl', 'url'], ['id' => $cid]);
 
                // Redirect if the contact is already authenticated on this site.
-               if (!empty($a->contact) && array_key_exists('id', $a->contact) && strpos($contact['nurl'], normalise_link(self::getApp()->get_baseurl())) !== false) {
+               if (!empty($a->contact) && array_key_exists('id', $a->contact) && strpos($contact['nurl'], normalise_link(self::getApp()->getBaseURL())) !== false) {
                        if ($test) {
                                $ret['success'] = true;
                                $ret['message'] .= 'Local site - you are already authenticated.' . EOL;
@@ -76,20 +76,16 @@ class Magic extends BaseModule
 
                                // Create a header that is signed with the local users private key.
                                $headers = HTTPSignature::createSig(
-                                       '',
                                        $headers,
                                        $user['prvkey'],
-                                       'acct:' . $user['nickname'] . '@' . $a->get_hostname() . ($a->urlpath ? '/' . $a->urlpath : ''),
-                                       false,
-                                       true,
-                                       'sha512'
+                                       'acct:' . $user['nickname'] . '@' . $a->getHostName() . ($a->getURLPath() ? '/' . $a->getURLPath() : '')
                                );
 
                                // Try to get an authentication token from the other instance.
-                               $x = Network::curl($basepath . '/owa', false, $redirects, ['headers' => $headers]);
+                               $curlResult = Network::curl($basepath . '/owa', false, $redirects, ['headers' => $headers]);
 
-                               if ($x['success']) {
-                                       $j = json_decode($x['body'], true);
+                               if ($curlResult->isSuccess()) {
+                                       $j = json_decode($curlResult->getBody(), true);
 
                                        if ($j['success']) {
                                                $token = '';
diff --git a/src/Module/Objects.php b/src/Module/Objects.php
new file mode 100644 (file)
index 0000000..ba9dace
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @file src/Module/Objects.php
+ */
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Core\System;
+use Friendica\Model\Item;
+use Friendica\Database\DBA;
+
+/**
+ * ActivityPub Objects
+ */
+class Objects extends BaseModule
+{
+       public static function rawContent()
+       {
+               $a = self::getApp();
+
+               if (empty($a->argv[1])) {
+                       System::httpExit(404);
+               }
+
+               if (!ActivityPub::isRequest()) {
+                       goaway(str_replace('objects/', 'display/', $a->query_string));
+               }
+
+               $item = Item::selectFirst(['id'], ['guid' => $a->argv[1], 'wall' => true, 'private' => false]);
+               if (!DBA::isResult($item)) {
+                       System::httpExit(404);
+               }
+
+               $data = ActivityPub\Transmitter::createObjectFromItemID($item['id']);
+
+               header('Content-Type: application/activity+json');
+               echo json_encode($data);
+               exit();
+       }
+}
diff --git a/src/Module/Outbox.php b/src/Module/Outbox.php
new file mode 100644 (file)
index 0000000..681d1cc
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @file src/Module/Outbox.php
+ */
+namespace Friendica\Module;
+
+use Friendica\BaseModule;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Core\System;
+use Friendica\Model\User;
+
+/**
+ * ActivityPub Outbox
+ */
+class Outbox extends BaseModule
+{
+       public static function rawContent()
+       {
+               $a = self::getApp();
+
+               if (empty($a->argv[1])) {
+                       System::httpExit(404);
+               }
+
+               $owner = User::getOwnerDataByNick($a->argv[1]);
+               if (empty($owner)) {
+                       System::httpExit(404);
+               }
+
+               $page = defaults($_REQUEST, 'page', null);
+
+               $outbox = ActivityPub\Transmitter::getOutbox($owner, $page);
+
+               header('Content-Type: application/activity+json');
+               echo json_encode($outbox);
+               exit();
+       }
+}
index 1d6b1332dcec81bdcf8ff5bd8aba3111343338c4..7a5fe128c8424cea51c99de816e95dfae501a01b 100644 (file)
@@ -54,7 +54,7 @@ class Owa extends BaseModule
                                                if (DBA::isResult($contact)) {
                                                        // Try to verify the signed header with the public key of the contact record
                                                        // we have found.
-                                                       $verified = HTTPSignature::verify('', $contact['pubkey']);
+                                                       $verified = HTTPSignature::verifyMagic($contact['pubkey']);
 
                                                        if ($verified && $verified['header_signed'] && $verified['header_valid']) {
                                                                logger('OWA header: ' . print_r($verified, true), LOGGER_DATA);
index 0de45b332518e433b58df1e0990f0242e257ab3a..776dcccb35b63276ed4be75bcf1b1f89a52423f1 100644 (file)
@@ -71,7 +71,7 @@ class Proxy extends BaseModule
                $thumb = false;
                $size = 1024;
                $sizetype = '';
-               $basepath = $a->get_basepath();
+               $basepath = $a->getBasePath();
 
                // If the cache path isn't there, try to create it
                if (!is_dir($basepath . '/proxy') && is_writable($basepath)) {
@@ -188,7 +188,8 @@ class Proxy extends BaseModule
                        // It shouldn't happen but it does - spaces in URL
                        $_REQUEST['url'] = str_replace(' ', '+', $_REQUEST['url']);
                        $redirects = 0;
-                       $img_str = Network::fetchUrl($_REQUEST['url'], true, $redirects, 10);
+                       $fetchResult = Network::fetchUrlFull($_REQUEST['url'], true, $redirects, 10);
+                       $img_str = $fetchResult->getBody();
 
                        $tempfile = tempnam(get_temppath(), 'cache');
                        file_put_contents($tempfile, $img_str);
@@ -196,7 +197,7 @@ class Proxy extends BaseModule
                        unlink($tempfile);
 
                        // If there is an error then return a blank image
-                       if ((substr($a->get_curl_code(), 0, 1) == '4') || (!$img_str)) {
+                       if ((substr($fetchResult->getReturnCode(), 0, 1) == '4') || (!$img_str)) {
                                $img_str = file_get_contents('images/blank.png');
                                $mime = 'image/png';
                                $cachefile = ''; // Clear the cachefile so that the dummy isn't stored
diff --git a/src/Network/CurlResult.php b/src/Network/CurlResult.php
new file mode 100644 (file)
index 0000000..e246f4f
--- /dev/null
@@ -0,0 +1,296 @@
+<?php
+
+namespace Friendica\Network;
+
+
+use Friendica\Network\HTTPException\InternalServerErrorException;
+
+/**
+ * A content class for Curl call results
+ */
+class CurlResult
+{
+       /**
+        * @var int HTTP return code or 0 if timeout or failure
+        */
+       private $returnCode;
+
+       /**
+        * @var string the content type of the Curl call
+        */
+       private $contentType;
+
+       /**
+        * @var string the HTTP headers of the Curl call
+        */
+       private $header;
+
+       /**
+        * @var boolean true (if HTTP 2xx result) or false
+        */
+       private $isSuccess;
+
+       /**
+        * @var string the URL which was called
+        */
+       private $url;
+
+       /**
+        * @var string in case of redirect, content was finally retrieved from this URL
+        */
+       private $redirectUrl;
+
+       /**
+        * @var string fetched content
+        */
+       private $body;
+
+       /**
+        * @var array some informations about the fetched data
+        */
+       private $info;
+
+       /**
+        * @var boolean true if the URL has a redirect
+        */
+       private $isRedirectUrl;
+
+       /**
+        * @var boolean true if the curl request timed out
+        */
+       private $isTimeout;
+
+       /**
+        * @var int the error number or 0 (zero) if no error
+        */
+       private $errorNumber;
+
+       /**
+        * @var string the error message or '' (the empty string) if no
+        */
+       private $error;
+
+       /**
+        * Creates an errored CURL response
+        *
+        * @param string $url optional URL
+        *
+        * @return CurlResult a CURL with error response
+        */
+       public static function createErrorCurl($url = '')
+       {
+               return new CurlResult($url, '', ['http_code' => 0]);
+       }
+
+       /**
+        * Curl constructor.
+        * @param string $url the URL which was called
+        * @param string $result the result of the curl execution
+        * @param array $info an additional info array
+        * @param int $errorNumber the error number or 0 (zero) if no error
+        * @param string $error the error message or '' (the empty string) if no
+        *
+        * @throws InternalServerErrorException when HTTP code of the CURL response is missing
+        */
+       public function __construct($url, $result, $info, $errorNumber = 0, $error = '')
+       {
+               if (!array_key_exists('http_code', $info)) {
+                       throw new InternalServerErrorException('CURL response doesn\'t contains a response HTTP code');
+               }
+
+               $this->returnCode = $info['http_code'];
+               $this->url = $url;
+               $this->info = $info;
+               $this->errorNumber = $errorNumber;
+               $this->error = $error;
+
+               logger($url . ': ' . $this->returnCode . " " . $result, LOGGER_DATA);
+
+               $this->parseBodyHeader($result);
+               $this->checkSuccess();
+               $this->checkRedirect();
+               $this->checkInfo();
+       }
+
+       private function parseBodyHeader($result)
+       {
+               // Pull out multiple headers, e.g. proxy and continuation headers
+               // allow for HTTP/2.x without fixing code
+
+               $header = '';
+               $base = $result;
+               while (preg_match('/^HTTP\/.+? \d+/', $base)) {
+                       $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
+                       $header .= $chunk;
+                       $base = substr($base, strlen($chunk));
+               }
+
+               $this->body = substr($result, strlen($header));
+               $this->header = $header;
+       }
+
+       private function checkSuccess()
+       {
+               $this->isSuccess = ($this->returnCode >= 200 && $this->returnCode <= 299) || $this->errorNumber == 0;
+
+               if (!$this->isSuccess) {
+                       logger('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, LOGGER_INFO);
+                       logger('debug: ' . print_r($this->info, true), LOGGER_DATA);
+               }
+
+               if (!$this->isSuccess && $this->errorNumber == CURLE_OPERATION_TIMEDOUT) {
+                       $this->isTimeout = true;
+               } else {
+                       $this->isTimeout = false;
+               }
+       }
+
+       private function checkRedirect()
+       {
+               if (!array_key_exists('url', $this->info)) {
+                       $this->redirectUrl = '';
+               } else {
+                       $this->redirectUrl = $this->info['url'];
+               }
+
+               if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode== 307) {
+                       $new_location_info = (!array_key_exists('redirect_url', $this->info) ? '' : @parse_url($this->info['redirect_url']));
+                       $old_location_info = (!array_key_exists('url', $this->info) ? '' : @parse_url($this->info['url']));
+
+                       $this->redirectUrl = $new_location_info;
+
+                       if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
+                               $this->redirectUrl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
+                       }
+
+                       $matches = [];
+
+                       if (preg_match('/(Location:|URI:)(.*?)\n/i', $this->header, $matches)) {
+                               $this->redirectUrl = trim(array_pop($matches));
+                       }
+                       if (strpos($this->redirectUrl, '/') === 0) {
+                               $this->redirectUrl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $this->redirectUrl;
+                       }
+                       $old_location_query = @parse_url($this->url, PHP_URL_QUERY);
+
+                       if ($old_location_query != '') {
+                               $this->redirectUrl .= '?' . $old_location_query;
+                       }
+
+                       $this->isRedirectUrl = filter_var($this->redirectUrl, FILTER_VALIDATE_URL) !== false;
+               } else {
+                       $this->isRedirectUrl = false;
+               }
+       }
+
+       private function checkInfo()
+       {
+               if (isset($this->info['content_type'])) {
+                       $this->contentType = $this->info['content_type'];
+               } else {
+                       $this->contentType = '';
+               }
+       }
+
+       /**
+        * Gets the Curl Code
+        *
+        * @return string The Curl Code
+        */
+       public function getReturnCode()
+       {
+               return $this->returnCode;
+       }
+
+       /**
+        * Returns the Curl Content Type
+        *
+        * @return string the Curl Content Type
+        */
+       public function getContentType()
+       {
+               return $this->contentType;
+       }
+
+       /**
+        * Returns the Curl headers
+        *
+        * @return string the Curl headers
+        */
+       public function getHeader()
+       {
+               return $this->header;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isSuccess()
+       {
+               return $this->isSuccess;
+       }
+
+       /**
+        * @return string
+        */
+       public function getUrl()
+       {
+               return $this->url;
+       }
+
+       /**
+        * @return string
+        */
+       public function getRedirectUrl()
+       {
+               return $this->redirectUrl;
+       }
+
+       /**
+        * @return string
+        */
+       public function getBody()
+       {
+               return $this->body;
+       }
+
+       /**
+        * @return array
+        */
+       public function getInfo()
+       {
+               return $this->info;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isRedirectUrl()
+       {
+               return $this->isRedirectUrl;
+       }
+
+       /**
+        * @return int
+        */
+       public function getErrorNumber()
+       {
+               return $this->errorNumber;
+       }
+
+       /**
+        * @return string
+        */
+       public function getError()
+       {
+               return $this->error;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isTimeout()
+       {
+               return $this->isTimeout;
+       }
+}
index 75231f44ff0bc9e2e1061704cdcbdecc1df1783a..2c42643b44a07fae9389c4ac738aa3ebac54c82c 100644 (file)
@@ -19,6 +19,7 @@ use Friendica\Model\Contact;
 use Friendica\Model\Profile;
 use Friendica\Protocol\Email;
 use Friendica\Protocol\Feed;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Util\Crypto;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
@@ -73,7 +74,7 @@ class Probe
         */
        private static function ownHost($host)
        {
-               $own_host = get_app()->get_hostname();
+               $own_host = get_app()->getHostName();
 
                $parts = parse_url($host);
 
@@ -111,20 +112,20 @@ class Probe
                logger("Probing for ".$host, LOGGER_DEBUG);
                $xrd = null;
 
-               $ret = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
-               if ($ret['success']) {
-                       $xml = $ret['body'];
+               $curlResult = Network::curl($ssl_url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
+               if ($curlResult->isSuccess()) {
+                       $xml = $curlResult->getBody();
                        $xrd = XML::parseString($xml, false);
                        $host_url = 'https://'.$host;
                }
 
                if (!is_object($xrd)) {
-                       $ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
-                       if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
-                               logger("Probing timeout for ".$url, LOGGER_DEBUG);
+                       $curlResult = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => 'application/xrd+xml']);
+                       if ($curlResult->isTimeout()) {
+                               logger("Probing timeout for " . $url, LOGGER_DEBUG);
                                return false;
                        }
-                       $xml = $ret['body'];
+                       $xml = $curlResult->getBody();
                        $xrd = XML::parseString($xml, false);
                        $host_url = 'http://'.$host;
                }
@@ -328,7 +329,17 @@ class Probe
                        $uid = local_user();
                }
 
-               $data = self::detect($uri, $network, $uid);
+               if ($network != Protocol::ACTIVITYPUB) {
+                       $data = self::detect($uri, $network, $uid);
+               } else {
+                       $data = null;
+               }
+
+               $ap_profile = ActivityPub::probeProfile($uri);
+
+               if (!empty($ap_profile) && (defaults($data, 'network', '') != Protocol::DFRN)) {
+                       $data = $ap_profile;
+               }
 
                if (!isset($data["url"])) {
                        $data["url"] = $uri;
@@ -731,11 +742,11 @@ class Probe
                $xrd_timeout = Config::get('system', 'xrd_timeout', 20);
                $redirects = 0;
 
-               $ret = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
-               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+               $curlResult = Network::curl($url, false, $redirects, ['timeout' => $xrd_timeout, 'accept_content' => $type]);
+               if ($curlResult->isTimeout()) {
                        return false;
                }
-               $data = $ret['body'];
+               $data = $curlResult->getBody();
 
                $webfinger = json_decode($data, true);
                if (is_array($webfinger)) {
@@ -798,11 +809,11 @@ class Probe
         */
        private static function pollNoscrape($noscrape_url, $data)
        {
-               $ret = Network::curl($noscrape_url);
-               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+               $curlResult = Network::curl($noscrape_url);
+               if ($curlResult->isTimeout()) {
                        return false;
                }
-               $content = $ret['body'];
+               $content = $curlResult->getBody();
                if (!$content) {
                        logger("Empty body for ".$noscrape_url, LOGGER_DEBUG);
                        return false;
@@ -1043,11 +1054,11 @@ class Probe
         */
        private static function pollHcard($hcard_url, $data, $dfrn = false)
        {
-               $ret = Network::curl($hcard_url);
-               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+               $curlResult = Network::curl($hcard_url);
+               if ($curlResult->isTimeout()) {
                        return false;
                }
-               $content = $ret['body'];
+               $content = $curlResult->getBody();
                if (!$content) {
                        return false;
                }
@@ -1290,11 +1301,11 @@ class Probe
                                                        $pubkey = substr($pubkey, 5);
                                                }
                                        } elseif (normalise_link($pubkey) == 'http://') {
-                                               $ret = Network::curl($pubkey);
-                                               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+                                               $curlResult = Network::curl($pubkey);
+                                               if ($curlResult->isTimeout()) {
                                                        return false;
                                                }
-                                               $pubkey = $ret['body'];
+                                               $pubkey = $curlResult['body'];
                                        }
 
                                        $key = explode(".", $pubkey);
@@ -1322,11 +1333,11 @@ class Probe
                }
 
                // Fetch all additional data from the feed
-               $ret = Network::curl($data["poll"]);
-               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+               $curlResult = Network::curl($data["poll"]);
+               if ($curlResult->isTimeout()) {
                        return false;
                }
-               $feed = $ret['body'];
+               $feed = $curlResult->getBody();
                $dummy1 = null;
                $dummy2 = null;
                $dummy2 = null;
@@ -1532,11 +1543,11 @@ class Probe
         */
        private static function feed($url, $probe = true)
        {
-               $ret = Network::curl($url);
-               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+               $curlResult = Network::curl($url);
+               if ($curlResult->isTimeout()) {
                        return false;
                }
-               $feed = $ret['body'];
+               $feed = $curlResult->getBody();
                $dummy1 = $dummy2 = $dummy3 = null;
                $feed_data = Feed::import($feed, $dummy1, $dummy2, $dummy3, true);
 
index 620929df5104a4e4e07dc4f22378fb8ad4003405..a76599223d0bbad165f72ee3611f5452869002c1 100644 (file)
@@ -655,7 +655,7 @@ class Image
 
                $stamp1 = microtime(true);
                file_put_contents($path, $string);
-               $a->save_timestamp($stamp1, "file");
+               $a->saveTimestamp($stamp1, "file");
        }
 
        /**
@@ -720,17 +720,18 @@ class Image
         *
         * @param string  $filename Image filename
         * @param boolean $fromcurl Check Content-Type header from curl request
+        * @param string $header passed headers to take into account
         *
         * @return object
         */
-       public static function guessType($filename, $fromcurl = false)
+       public static function guessType($filename, $fromcurl = false, $header = '')
        {
                logger('Image: guessType: '.$filename . ($fromcurl?' from curl headers':''), LOGGER_DEBUG);
                $type = null;
                if ($fromcurl) {
                        $a = get_app();
                        $headers=[];
-                       $h = explode("\n", $a->get_curl_headers());
+                       $h = explode("\n", $header);
                        foreach ($h as $l) {
                                $data = array_map("trim", explode(":", trim($l), 2));
                                if (count($data) > 1) {
@@ -799,7 +800,7 @@ class Image
                                        $a = get_app();
                                        $stamp1 = microtime(true);
                                        file_put_contents($tempfile, $img_str);
-                                       $a->save_timestamp($stamp1, "file");
+                                       $a->saveTimestamp($stamp1, "file");
 
                                        $data = getimagesize($tempfile);
                                        unlink($tempfile);
@@ -907,7 +908,7 @@ class Image
 
                        $stamp1 = microtime(true);
                        $imagedata = @file_get_contents($url);
-                       $a->save_timestamp($stamp1, "file");
+                       $a->saveTimestamp($stamp1, "file");
                }
 
                $maximagesize = Config::get('system', 'maximagesize');
@@ -921,7 +922,7 @@ class Image
 
                $stamp1 = microtime(true);
                file_put_contents($tempfile, $imagedata);
-               $a->save_timestamp($stamp1, "file");
+               $a->saveTimestamp($stamp1, "file");
 
                $data = getimagesize($tempfile);
 
index c52078e521ef046150abb72fcb96782bb2ef0603..48ffe65b74ed16b1b59fc8cd381d75a0604bfd2c 100644 (file)
@@ -324,7 +324,7 @@ class Post extends BaseObject
                $owner_name_e = $this->getOwnerName();
 
                // Disable features that aren't available in several networks
-               if (!in_array($item["network"], [Protocol::DFRN, Protocol::DIASPORA]) && isset($buttons["dislike"])) {
+               if (!in_array($item["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA]) && isset($buttons["dislike"])) {
                        unset($buttons["dislike"]);
                        $isevent = false;
                        $tagger = '';
@@ -368,7 +368,7 @@ class Post extends BaseObject
                        'profile_url'     => $profile_link,
                        'item_photo_menu' => item_photo_menu($item),
                        'name'            => $name_e,
-                       'thumb'           => $a->remove_baseurl(ProxyUtils::proxifyUrl($item['author-avatar'], false, ProxyUtils::SIZE_THUMB)),
+                       'thumb'           => $a->removeBaseURL(ProxyUtils::proxifyUrl($item['author-avatar'], false, ProxyUtils::SIZE_THUMB)),
                        'osparkle'        => $osparkle,
                        'sparkle'         => $sparkle,
                        'title'           => $title_e,
@@ -381,7 +381,7 @@ class Post extends BaseObject
                        'indent'          => $indent,
                        'shiny'           => $shiny,
                        'owner_url'       => $this->getOwnerUrl(),
-                       'owner_photo'     => $a->remove_baseurl(ProxyUtils::proxifyUrl($item['owner-avatar'], false, ProxyUtils::SIZE_THUMB)),
+                       'owner_photo'     => $a->removeBaseURL(ProxyUtils::proxifyUrl($item['owner-avatar'], false, ProxyUtils::SIZE_THUMB)),
                        'owner_name'      => htmlentities($owner_name_e),
                        'plink'           => get_plink($item),
                        'edpost'          => Feature::isEnabled($conv->getProfileOwner(), 'edit_posts') ? $edpost : '',
@@ -402,7 +402,7 @@ class Post extends BaseObject
                        'thread_level'    => $thread_level,
                        'edited'          => $edited,
                        'network'         => $item["network"],
-                       'network_name'    => ContactSelector::networkToName($item['network'], $profile_link),
+                       'network_name'    => ContactSelector::networkToName($item['network'], $item['author-link']),
                        'received'        => $item['received'],
                        'commented'       => $item['commented'],
                        'created_date'    => $item['created'],
@@ -788,9 +788,9 @@ class Post extends BaseObject
                                '$parent'      => $this->getId(),
                                '$qcomment'    => $qcomment,
                                '$profile_uid' => $uid,
-                               '$mylink'      => $a->remove_baseurl($a->contact['url']),
+                               '$mylink'      => $a->removeBaseURL($a->contact['url']),
                                '$mytitle'     => L10n::t('This is you'),
-                               '$myphoto'     => $a->remove_baseurl($a->contact['thumb']),
+                               '$myphoto'     => $a->removeBaseURL($a->contact['thumb']),
                                '$comment'     => L10n::t('Comment'),
                                '$submit'      => L10n::t('Submit'),
                                '$edbold'      => L10n::t('Bold'),
diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php
new file mode 100644 (file)
index 0000000..0af8ee5
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/**
+ * @file src/Protocol/ActivityPub.php
+ */
+namespace Friendica\Protocol;
+
+use Friendica\Util\Network;
+use Friendica\Core\Protocol;
+use Friendica\Model\APContact;
+
+/**
+ * @brief ActivityPub Protocol class
+ * The ActivityPub Protocol is a message exchange protocol defined by the W3C.
+ * https://www.w3.org/TR/activitypub/
+ * https://www.w3.org/TR/activitystreams-core/
+ * https://www.w3.org/TR/activitystreams-vocabulary/
+ *
+ * https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/
+ * https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/
+ *
+ * Digest: https://tools.ietf.org/html/rfc5843
+ * https://tools.ietf.org/html/draft-cavage-http-signatures-10#ref-15
+ *
+ * Mastodon implementation of supported activities:
+ * https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/activity.rb#L26
+ *
+ * Funkwhale:
+ * http://docs-funkwhale-funkwhale-549-music-federation-documentation.preview.funkwhale.audio/federation/index.html
+ *
+ * To-do:
+ * - Polling the outboxes for missing content?
+ */
+class ActivityPub
+{
+       const PUBLIC_COLLECTION = 'https://www.w3.org/ns/activitystreams#Public';
+       const CONTEXT = ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1',
+               ['vcard' => 'http://www.w3.org/2006/vcard/ns#',
+               'diaspora' => 'https://diasporafoundation.org/ns/',
+               'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
+               'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag']];
+       const ACCOUNT_TYPES = ['Person', 'Organization', 'Service', 'Group', 'Application'];
+       /**
+        * Checks if the web request is done for the AP protocol
+        *
+        * @return is it AP?
+        */
+       public static function isRequest()
+       {
+               return stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/activity+json') ||
+                       stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/ld+json');
+       }
+
+       /**
+        * Fetches ActivityPub content from the given url
+        *
+        * @param string $url content url
+        * @return array
+        */
+       public static function fetchContent($url)
+       {
+               $curlResult = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json, application/ld+json']);
+               if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
+                       return false;
+               }
+
+               return json_decode($curlResult->getBody(), true);
+       }
+
+       /**
+        * Fetches a profile from the given url into an array that is compatible to Probe::uri
+        *
+        * @param string $url profile url
+        * @return array
+        */
+       public static function probeProfile($url)
+       {
+               $apcontact = APContact::getByURL($url, true);
+               if (empty($apcontact)) {
+                       return false;
+               }
+
+               $profile = ['network' => Protocol::ACTIVITYPUB];
+               $profile['nick'] = $apcontact['nick'];
+               $profile['name'] = $apcontact['name'];
+               $profile['guid'] = $apcontact['uuid'];
+               $profile['url'] = $apcontact['url'];
+               $profile['addr'] = $apcontact['addr'];
+               $profile['alias'] = $apcontact['alias'];
+               $profile['photo'] = $apcontact['photo'];
+               // $profile['community']
+               // $profile['keywords']
+               // $profile['location']
+               $profile['about'] = $apcontact['about'];
+               $profile['batch'] = $apcontact['sharedinbox'];
+               $profile['notify'] = $apcontact['inbox'];
+               $profile['poll'] = $apcontact['outbox'];
+               $profile['pubkey'] = $apcontact['pubkey'];
+               $profile['baseurl'] = $apcontact['baseurl'];
+
+               // Remove all "null" fields
+               foreach ($profile as $field => $content) {
+                       if (is_null($content)) {
+                               unset($profile[$field]);
+                       }
+               }
+
+               return $profile;
+       }
+
+       /**
+        * Fetches activities from the outbox of a given profile and processes it
+        *
+        * @param string $url
+        * @param integer $uid User ID
+        */
+       public static function fetchOutbox($url, $uid)
+       {
+               $data = self::fetchContent($url);
+               if (empty($data)) {
+                       return;
+               }
+
+               if (!empty($data['orderedItems'])) {
+                       $items = $data['orderedItems'];
+               } elseif (!empty($data['first']['orderedItems'])) {
+                       $items = $data['first']['orderedItems'];
+               } elseif (!empty($data['first'])) {
+                       self::fetchOutbox($data['first'], $uid);
+                       return;
+               } else {
+                       $items = [];
+               }
+
+               foreach ($items as $activity) {
+                       $ldactivity = JsonLD::compact($activity);
+                       ActivityPub\Receiver::processActivity($ldactivity, '', $uid, true);
+               }
+       }
+}
diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php
new file mode 100644 (file)
index 0000000..c481423
--- /dev/null
@@ -0,0 +1,498 @@
+<?php
+/**
+ * @file src/Protocol/ActivityPub/Processor.php
+ */
+namespace Friendica\Protocol\ActivityPub;
+
+use Friendica\Database\DBA;
+use Friendica\Core\Protocol;
+use Friendica\Model\Conversation;
+use Friendica\Model\Contact;
+use Friendica\Model\APContact;
+use Friendica\Model\Item;
+use Friendica\Model\User;
+use Friendica\Content\Text\HTML;
+use Friendica\Util\JsonLD;
+use Friendica\Core\Config;
+use Friendica\Protocol\ActivityPub;
+
+/**
+ * ActivityPub Protocol class
+ *
+ * To-Do:
+ * - Store Diaspora signature
+ */
+class Processor
+{
+       /**
+        * Converts mentions from Pleroma into the Friendica format
+        *
+        * @param string $body
+        *
+        * @return converted body
+        */
+       private static function convertMentions($body)
+       {
+               $URLSearchString = "^\[\]";
+               $body = preg_replace("/\[url\=([$URLSearchString]*)\]([#@!])(.*?)\[\/url\]/ism", '$2[url=$1]$3[/url]', $body);
+
+               return $body;
+       }
+
+       /**
+        * Constructs a string with tags for a given tag array
+        *
+        * @param array $tags
+        * @param boolean $sensitive
+        *
+        * @return string with tags
+        */
+       private static function constructTagList($tags, $sensitive)
+       {
+               if (empty($tags)) {
+                       return '';
+               }
+
+               $tag_text = '';
+               foreach ($tags as $tag) {
+                       if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag'])) {
+                               if (!empty($tag_text)) {
+                                       $tag_text .= ',';
+                               }
+
+                               $tag_text .= substr($tag['name'], 0, 1) . '[url=' . $tag['href'] . ']' . substr($tag['name'], 1) . '[/url]';
+                       }
+               }
+
+               /// @todo add nsfw for $sensitive
+
+               return $tag_text;
+       }
+
+       /**
+        * Add attachment data to the item array
+        *
+        * @param array $attachments
+        * @param array $item
+        *
+        * @return item array
+        */
+       private static function constructAttachList($attachments, $item)
+       {
+               if (empty($attachments)) {
+                       return $item;
+               }
+
+               foreach ($attachments as $attach) {
+                       $filetype = strtolower(substr($attach['mediaType'], 0, strpos($attach['mediaType'], '/')));
+                       if ($filetype == 'image') {
+                               $item['body'] .= "\n[img]" . $attach['url'] . '[/img]';
+                       } else {
+                               if (!empty($item["attach"])) {
+                                       $item["attach"] .= ',';
+                               } else {
+                                       $item["attach"] = '';
+                               }
+                               if (!isset($attach['length'])) {
+                                       $attach['length'] = "0";
+                               }
+                               $item["attach"] .= '[attach]href="'.$attach['url'].'" length="'.$attach['length'].'" type="'.$attach['mediaType'].'" title="'.defaults($attach, 'name', '').'"[/attach]';
+                       }
+               }
+
+               return $item;
+       }
+
+       /**
+        * Prepares data for a message
+        *
+        * @param array  $activity Activity array
+        */
+       public static function createItem($activity)
+       {
+               $item = [];
+               $item['verb'] = ACTIVITY_POST;
+               $item['parent-uri'] = $activity['reply-to-id'];
+
+               if ($activity['reply-to-id'] == $activity['id']) {
+                       $item['gravity'] = GRAVITY_PARENT;
+                       $item['object-type'] = ACTIVITY_OBJ_NOTE;
+               } else {
+                       $item['gravity'] = GRAVITY_COMMENT;
+                       $item['object-type'] = ACTIVITY_OBJ_COMMENT;
+               }
+
+               if (($activity['id'] != $activity['reply-to-id']) && !Item::exists(['uri' => $activity['reply-to-id']])) {
+                       logger('Parent ' . $activity['reply-to-id'] . ' not found. Try to refetch it.');
+                       self::fetchMissingActivity($activity['reply-to-id'], $activity);
+               }
+
+               self::postItem($activity, $item);
+       }
+
+       /**
+        * Prepare the item array for a "like"
+        *
+        * @param array  $activity Activity array
+        */
+       public static function likeItem($activity)
+       {
+               $item = [];
+               $item['verb'] = ACTIVITY_LIKE;
+               $item['parent-uri'] = $activity['object_id'];
+               $item['gravity'] = GRAVITY_ACTIVITY;
+               $item['object-type'] = ACTIVITY_OBJ_NOTE;
+
+               self::postItem($activity, $item);
+       }
+
+       /**
+        * Delete items
+        *
+        * @param array $activity
+        */
+       public static function deleteItem($activity)
+       {
+               $owner = Contact::getIdForURL($activity['actor']);
+
+               logger('Deleting item ' . $activity['object_id'] . ' from ' . $owner, LOGGER_DEBUG);
+               Item::delete(['uri' => $activity['object_id'], 'owner-id' => $owner]);
+       }
+
+       /**
+        * Prepare the item array for a "dislike"
+        *
+        * @param array  $activity Activity array
+        */
+       public static function dislikeItem($activity)
+       {
+               $item = [];
+               $item['verb'] = ACTIVITY_DISLIKE;
+               $item['parent-uri'] = $activity['object_id'];
+               $item['gravity'] = GRAVITY_ACTIVITY;
+               $item['object-type'] = ACTIVITY_OBJ_NOTE;
+
+               self::postItem($activity, $item);
+       }
+
+       /**
+        * Creates an item post
+        *
+        * @param array  $activity Activity data
+        * @param array  $item     item array
+        */
+       private static function postItem($activity, $item)
+       {
+               /// @todo What to do with $activity['context']?
+
+               if (($item['gravity'] != GRAVITY_PARENT) && !Item::exists(['uri' => $item['parent-uri']])) {
+                       logger('Parent ' . $item['parent-uri'] . ' not found, message will be discarded.', LOGGER_DEBUG);
+                       return;
+               }
+
+               $item['network'] = Protocol::ACTIVITYPUB;
+               $item['private'] = !in_array(0, $activity['receiver']);
+               $item['author-link'] = $activity['author'];
+               $item['author-id'] = Contact::getIdForURL($activity['author'], 0, true);
+
+               if (empty($activity['thread-completion'])) {
+                       $item['owner-link'] = $activity['actor'];
+                       $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
+               } else {
+                       logger('Ignoring actor because of thread completion.', LOGGER_DEBUG);
+                       $item['owner-link'] = $item['author-link'];
+                       $item['owner-id'] = $item['author-id'];
+               }
+
+               $item['uri'] = $activity['id'];
+               $item['created'] = $activity['published'];
+               $item['edited'] = $activity['updated'];
+               $item['guid'] = $activity['diaspora:guid'];
+               $item['title'] = HTML::toBBCode($activity['name']);
+               $item['content-warning'] = HTML::toBBCode($activity['summary']);
+               $item['body'] = self::convertMentions(HTML::toBBCode($activity['content']));
+
+               if (($activity['object_type'] == 'as:Video') && !empty($activity['alternate-url'])) {
+                       $item['body'] .= "\n[video]" . $activity['alternate-url'] . '[/video]';
+               }
+
+               $item['location'] = $activity['location'];
+
+               if (!empty($item['latitude']) && !empty($item['longitude'])) {
+                       $item['coord'] = $item['latitude'] . ' ' . $item['longitude'];
+               }
+
+               $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']);
+               $item['app'] = $activity['generator'];
+               $item['plink'] = defaults($activity, 'alternate-url', $item['uri']);
+               $item['diaspora_signed_text'] = defaults($activity, 'diaspora:comment', '');
+
+               $item = self::constructAttachList($activity['attachments'], $item);
+
+               if (!empty($activity['source'])) {
+                       $item['body'] = $activity['source'];
+               }
+
+               foreach ($activity['receiver'] as $receiver) {
+                       $item['uid'] = $receiver;
+                       $item['contact-id'] = Contact::getIdForURL($activity['author'], $receiver, true);
+
+                       if (($receiver != 0) && empty($item['contact-id'])) {
+                               $item['contact-id'] = Contact::getIdForURL($activity['author'], 0, true);
+                       }
+
+                       $item_id = Item::insert($item);
+                       logger('Storing for user ' . $item['uid'] . ': ' . $item_id);
+               }
+       }
+
+       /**
+        * Fetches missing posts
+        *
+        * @param $url
+        * @param $child
+        */
+       private static function fetchMissingActivity($url, $child)
+       {
+               if (Config::get('system', 'ostatus_full_threads')) {
+                       return;
+               }
+
+               $object = ActivityPub::fetchContent($url);
+               if (empty($object)) {
+                       logger('Activity ' . $url . ' was not fetchable, aborting.');
+                       return;
+               }
+
+               $activity = [];
+               $activity['@context'] = $object['@context'];
+               unset($object['@context']);
+               $activity['id'] = $object['id'];
+               $activity['to'] = defaults($object, 'to', []);
+               $activity['cc'] = defaults($object, 'cc', []);
+               $activity['actor'] = $child['author'];
+               $activity['object'] = $object;
+               $activity['published'] = $object['published'];
+               $activity['type'] = 'Create';
+
+               $ldactivity = JsonLD::compact($activity);
+
+               $ldactivity['thread-completion'] = true;
+
+               ActivityPub\Receiver::processActivity($ldactivity);
+               logger('Activity ' . $url . ' had been fetched and processed.');
+       }
+
+       /**
+        * perform a "follow" request
+        *
+        * @param array $activity
+        */
+       public static function followUser($activity)
+       {
+               $uid = User::getIdForURL($activity['object_id']);
+               if (empty($uid)) {
+                       return;
+               }
+
+               $owner = User::getOwnerDataById($uid);
+
+               $cid = Contact::getIdForURL($activity['actor'], $uid);
+               if (!empty($cid)) {
+                       self::switchContact($cid);
+                       $contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]);
+               } else {
+                       $contact = false;
+               }
+
+               $item = ['author-id' => Contact::getIdForURL($activity['actor']),
+                       'author-link' => $activity['actor']];
+
+               // Ensure that the contact has got the right network type
+               self::switchContact($item['author-id']);
+
+               Contact::addRelationship($owner, $contact, $item);
+               $cid = Contact::getIdForURL($activity['actor'], $uid);
+               if (empty($cid)) {
+                       return;
+               }
+
+               DBA::update('contact', ['hub-verify' => $activity['id']], ['id' => $cid]);
+               logger('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']);
+       }
+
+       /**
+        * Update the given profile
+        *
+        * @param array $activity
+        */
+       public static function updatePerson($activity)
+       {
+               if (empty($activity['object_id'])) {
+                       return;
+               }
+
+               logger('Updating profile for ' . $activity['object_id'], LOGGER_DEBUG);
+               APContact::getByURL($activity['object_id'], true);
+       }
+
+       /**
+        * Delete the given profile
+        *
+        * @param array $activity
+        */
+       public static function deletePerson($activity)
+       {
+               if (empty($activity['object_id']) || empty($activity['actor'])) {
+                       logger('Empty object id or actor.', LOGGER_DEBUG);
+                       return;
+               }
+
+               if ($activity['object_id'] != $activity['actor']) {
+                       logger('Object id does not match actor.', LOGGER_DEBUG);
+                       return;
+               }
+
+               $contacts = DBA::select('contact', ['id'], ['nurl' => normalise_link($activity['object_id'])]);
+               while ($contact = DBA::fetch($contacts)) {
+                       Contact::remove($contact['id']);
+               }
+               DBA::close($contacts);
+
+               logger('Deleted contact ' . $activity['object_id'], LOGGER_DEBUG);
+       }
+
+       /**
+        * Accept a follow request
+        *
+        * @param array $activity
+        */
+       public static function acceptFollowUser($activity)
+       {
+               $uid = User::getIdForURL($activity['object_actor']);
+               if (empty($uid)) {
+                       return;
+               }
+
+               $owner = User::getOwnerDataById($uid);
+
+               $cid = Contact::getIdForURL($activity['actor'], $uid);
+               if (empty($cid)) {
+                       logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG);
+                       return;
+               }
+
+               self::switchContact($cid);
+
+               $fields = ['pending' => false];
+
+               $contact = DBA::selectFirst('contact', ['rel'], ['id' => $cid]);
+               if ($contact['rel'] == Contact::FOLLOWER) {
+                       $fields['rel'] = Contact::FRIEND;
+               }
+
+               $condition = ['id' => $cid];
+               DBA::update('contact', $fields, $condition);
+               logger('Accept contact request from contact ' . $cid . ' for user ' . $uid, LOGGER_DEBUG);
+       }
+
+       /**
+        * Reject a follow request
+        *
+        * @param array $activity
+        */
+       public static function rejectFollowUser($activity)
+       {
+               $uid = User::getIdForURL($activity['object_actor']);
+               if (empty($uid)) {
+                       return;
+               }
+
+               $owner = User::getOwnerDataById($uid);
+
+               $cid = Contact::getIdForURL($activity['actor'], $uid);
+               if (empty($cid)) {
+                       logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG);
+                       return;
+               }
+
+               self::switchContact($cid);
+
+               if (DBA::exists('contact', ['id' => $cid, 'rel' => Contact::SHARING, 'pending' => true])) {
+                       Contact::remove($cid);
+                       logger('Rejected contact request from contact ' . $cid . ' for user ' . $uid . ' - contact had been removed.', LOGGER_DEBUG);
+               } else {
+                       logger('Rejected contact request from contact ' . $cid . ' for user ' . $uid . '.', LOGGER_DEBUG);
+               }
+       }
+
+       /**
+        * Undo activity like "like" or "dislike"
+        *
+        * @param array $activity
+        */
+       public static function undoActivity($activity)
+       {
+               if (empty($activity['object_id'])) {
+                       return;
+               }
+
+               if (empty($activity['object_actor'])) {
+                       return;
+               }
+
+               $author_id = Contact::getIdForURL($activity['object_actor']);
+               if (empty($author_id)) {
+                       return;
+               }
+
+               Item::delete(['uri' => $activity['object_id'], 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]);
+       }
+
+       /**
+        * Activity to remove a follower
+        *
+        * @param array $activity
+        */
+       public static function undoFollowUser($activity)
+       {
+               $uid = User::getIdForURL($activity['object_object']);
+               if (empty($uid)) {
+                       return;
+               }
+
+               $owner = User::getOwnerDataById($uid);
+
+               $cid = Contact::getIdForURL($activity['actor'], $uid);
+               if (empty($cid)) {
+                       logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG);
+                       return;
+               }
+
+               self::switchContact($cid);
+
+               $contact = DBA::selectFirst('contact', [], ['id' => $cid]);
+               if (!DBA::isResult($contact)) {
+                       return;
+               }
+
+               Contact::removeFollower($owner, $contact);
+               logger('Undo following request from contact ' . $cid . ' for user ' . $uid, LOGGER_DEBUG);
+       }
+
+       /**
+        * Switches a contact to AP if needed
+        *
+        * @param integer $cid Contact ID
+        */
+       private static function switchContact($cid)
+       {
+               $contact = DBA::selectFirst('contact', ['network'], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]);
+               if (!DBA::isResult($contact) || ($contact['network'] == Protocol::ACTIVITYPUB)) {
+                       return;
+               }
+
+               logger('Change existing contact ' . $cid . ' from ' . $contact['network'] . ' to ActivityPub.');
+               Contact::updateFromProbe($cid, Protocol::ACTIVITYPUB);
+       }
+}
diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php
new file mode 100644 (file)
index 0000000..04da5fa
--- /dev/null
@@ -0,0 +1,735 @@
+<?php
+/**
+ * @file src/Protocol/ActivityPub/Receiver.php
+ */
+namespace Friendica\Protocol\ActivityPub;
+
+use Friendica\Database\DBA;
+use Friendica\Util\HTTPSignature;
+use Friendica\Core\Protocol;
+use Friendica\Model\Contact;
+use Friendica\Model\APContact;
+use Friendica\Model\Item;
+use Friendica\Model\User;
+use Friendica\Util\JsonLD;
+use Friendica\Util\LDSignature;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Model\Conversation;
+use Friendica\Util\DateTimeFormat;
+
+/**
+ * @brief ActivityPub Receiver Protocol class
+ *
+ * To-Do:
+ * - Update (Image, Video, Article, Note)
+ * - Event
+ * - Undo Announce
+ *
+ * Check what this is meant to do:
+ * - Add
+ * - Block
+ * - Flag
+ * - Remove
+ * - Undo Block
+ * - Undo Accept (Problem: This could invert a contact accept or an event accept)
+ */
+class Receiver
+{
+       const PUBLIC_COLLECTION = 'as:Public';
+       const ACCOUNT_TYPES = ['as:Person', 'as:Organization', 'as:Service', 'as:Group', 'as:Application'];
+       const CONTENT_TYPES = ['as:Note', 'as:Article', 'as:Video', 'as:Image'];
+       const ACTIVITY_TYPES = ['as:Like', 'as:Dislike', 'as:Accept', 'as:Reject', 'as:TentativeAccept'];
+
+       /**
+        * Checks if the web request is done for the AP protocol
+        *
+        * @return is it AP?
+        */
+       public static function isRequest()
+       {
+               return stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/activity+json') ||
+                       stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/ld+json');
+       }
+
+       /**
+        * Checks incoming message from the inbox
+        *
+        * @param $body
+        * @param $header
+        * @param integer $uid User ID
+        */
+       public static function processInbox($body, $header, $uid)
+       {
+               $http_signer = HTTPSignature::getSigner($body, $header);
+               if (empty($http_signer)) {
+                       logger('Invalid HTTP signature, message will be discarded.', LOGGER_DEBUG);
+                       return;
+               } else {
+                       logger('HTTP signature is signed by ' . $http_signer, LOGGER_DEBUG);
+               }
+
+               $activity = json_decode($body, true);
+
+               if (empty($activity)) {
+                       logger('Invalid body.', LOGGER_DEBUG);
+                       return;
+               }
+
+               $ldactivity = JsonLD::compact($activity);
+
+               $actor = JsonLD::fetchElement($ldactivity, 'as:actor');
+
+               logger('Message for user ' . $uid . ' is from actor ' . $actor, LOGGER_DEBUG);
+
+               if (LDSignature::isSigned($activity)) {
+                       $ld_signer = LDSignature::getSigner($activity);
+                       if (empty($ld_signer)) {
+                               logger('Invalid JSON-LD signature from ' . $actor, LOGGER_DEBUG);
+                       }
+                       if (!empty($ld_signer && ($actor == $http_signer))) {
+                               logger('The HTTP and the JSON-LD signature belong to ' . $ld_signer, LOGGER_DEBUG);
+                               $trust_source = true;
+                       } elseif (!empty($ld_signer)) {
+                               logger('JSON-LD signature is signed by ' . $ld_signer, LOGGER_DEBUG);
+                               $trust_source = true;
+                       } elseif ($actor == $http_signer) {
+                               logger('Bad JSON-LD signature, but HTTP signer fits the actor.', LOGGER_DEBUG);
+                               $trust_source = true;
+                       } else {
+                               logger('Invalid JSON-LD signature and the HTTP signer is different.', LOGGER_DEBUG);
+                               $trust_source = false;
+                       }
+               } elseif ($actor == $http_signer) {
+                       logger('Trusting post without JSON-LD signature, The actor fits the HTTP signer.', LOGGER_DEBUG);
+                       $trust_source = true;
+               } else {
+                       logger('No JSON-LD signature, different actor.', LOGGER_DEBUG);
+                       $trust_source = false;
+               }
+
+               self::processActivity($ldactivity, $body, $uid, $trust_source);
+       }
+
+       /**
+        * Fetches the object type for a given object id
+        *
+        * @param array  $activity
+        * @param string $object_id Object ID of the the provided object
+        *
+        * @return string with object type
+        */
+       private static function fetchObjectType($activity, $object_id)
+       {
+
+               $object_type = JsonLD::fetchElement($activity['as:object'], '@type');
+               if (!empty($object_type)) {
+                       return $object_type;
+               }
+
+               if (Item::exists(['uri' => $object_id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]])) {
+                       // We just assume "note" since it doesn't make a difference for the further processing
+                       return 'as:Note';
+               }
+
+               $profile = APContact::getByURL($object_id);
+               if (!empty($profile['type'])) {
+                       return 'as:' . $profile['type'];
+               }
+
+               $data = ActivityPub::fetchContent($object_id);
+               if (!empty($data)) {
+                       $object = JsonLD::compact($data);
+                       $type = JsonLD::fetchElement($object, '@type');
+                       if (!empty($type)) {
+                               return $type;
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Prepare the object array
+        *
+        * @param array $activity
+        * @param integer $uid User ID
+        * @param $trust_source
+        *
+        * @return array with object data
+        */
+       private static function prepareObjectData($activity, $uid, &$trust_source)
+       {
+               $actor = JsonLD::fetchElement($activity, 'as:actor');
+               if (empty($actor)) {
+                       logger('Empty actor', LOGGER_DEBUG);
+                       return [];
+               }
+
+               $type = JsonLD::fetchElement($activity, '@type');
+
+               // Fetch all receivers from to, cc, bto and bcc
+               $receivers = self::getReceivers($activity, $actor);
+
+               // When it is a delivery to a personal inbox we add that user to the receivers
+               if (!empty($uid)) {
+                       $owner = User::getOwnerDataById($uid);
+                       $additional = ['uid:' . $uid => $uid];
+                       $receivers = array_merge($receivers, $additional);
+               }
+
+               logger('Receivers: ' . json_encode($receivers), LOGGER_DEBUG);
+
+               $object_id = JsonLD::fetchElement($activity, 'as:object');
+               if (empty($object_id)) {
+                       logger('No object found', LOGGER_DEBUG);
+                       return [];
+               }
+
+               $object_type = self::fetchObjectType($activity, $object_id);
+
+               // Fetch the content only on activities where this matters
+               if (in_array($type, ['as:Create', 'as:Announce'])) {
+                       if ($type == 'as:Announce') {
+                               $trust_source = false;
+                       }
+                       $object_data = self::fetchObject($object_id, $activity['as:object'], $trust_source);
+                       if (empty($object_data)) {
+                               logger("Object data couldn't be processed", LOGGER_DEBUG);
+                               return [];
+                       }
+                       // We had been able to retrieve the object data - so we can trust the source
+                       $trust_source = true;
+               } elseif (in_array($type, ['as:Like', 'as:Dislike'])) {
+                       // Create a mostly empty array out of the activity data (instead of the object).
+                       // This way we later don't have to check for the existence of ech individual array element.
+                       $object_data = self::processObject($activity);
+                       $object_data['name'] = $type;
+                       $object_data['author'] = JsonLD::fetchElement($activity, 'as:actor');
+                       $object_data['object_id'] = $object_id;
+                       $object_data['object_type'] = ''; // Since we don't fetch the object, we don't know the type
+               } else {
+                       $object_data = [];
+                       $object_data['id'] = JsonLD::fetchElement($activity, '@id');
+                       $object_data['object_id'] = JsonLD::fetchElement($activity, 'as:object');
+                       $object_data['object_actor'] = JsonLD::fetchElement($activity['as:object'], 'as:actor');
+                       $object_data['object_object'] = JsonLD::fetchElement($activity['as:object'], 'as:object');
+                       $object_data['object_type'] = JsonLD::fetchElement($activity['as:object'], '@type');
+               }
+
+               $object_data = self::addActivityFields($object_data, $activity);
+
+               if (empty($object_data['object_type'])) {
+                       $object_data['object_type'] = $object_type;
+               }
+
+               $object_data['type'] = $type;
+               $object_data['actor'] = $actor;
+               $object_data['receiver'] = array_merge(defaults($object_data, 'receiver', []), $receivers);
+
+               logger('Processing ' . $object_data['type'] . ' ' . $object_data['object_type'] . ' ' . $object_data['id'], LOGGER_DEBUG);
+
+               return $object_data;
+       }
+
+       /**
+        * Store the unprocessed data into the conversation table
+        * This has to be done outside the regular function,
+        * since we store everything - not only item posts.
+        *
+        * @param array  $activity Array with activity data
+        * @param string $body     The raw message
+        */
+       private static function storeConversation($activity, $body)
+       {
+               if (empty($body) || empty($activity['id'])) {
+                       return;
+               }
+
+               $conversation = [
+                       'protocol' => Conversation::PARCEL_ACTIVITYPUB,
+                       'item-uri' => $activity['id'],
+                       'reply-to-uri' => defaults($activity, 'reply-to-id', ''),
+                       'conversation-href' => defaults($activity, 'context', ''),
+                       'conversation-uri' => defaults($activity, 'conversation', ''),
+                       'source' => $body,
+                       'received' => DateTimeFormat::utcNow()];
+
+               DBA::insert('conversation', $conversation, true);
+       }
+
+       /**
+        * Processes the activity object
+        *
+        * @param array   $activity     Array with activity data
+        * @param string  $body
+        * @param integer $uid          User ID
+        * @param boolean $trust_source Do we trust the source?
+        */
+       public static function processActivity($activity, $body = '', $uid = null, $trust_source = false)
+       {
+               $type = JsonLD::fetchElement($activity, '@type');
+               if (!$type) {
+                       logger('Empty type', LOGGER_DEBUG);
+                       return;
+               }
+
+               if (!JsonLD::fetchElement($activity, 'as:object')) {
+                       logger('Empty object', LOGGER_DEBUG);
+                       return;
+               }
+
+               if (!JsonLD::fetchElement($activity, 'as:actor')) {
+                       logger('Empty actor', LOGGER_DEBUG);
+                       return;
+
+               }
+
+               // $trust_source is called by reference and is set to true if the content was retrieved successfully
+               $object_data = self::prepareObjectData($activity, $uid, $trust_source);
+               if (empty($object_data)) {
+                       logger('No object data found', LOGGER_DEBUG);
+                       return;
+               }
+
+               if (!$trust_source) {
+                       logger('No trust for activity type "' . $type . '", so we quit now.', LOGGER_DEBUG);
+                       return;
+               }
+
+               self::storeConversation($object_data, $body);
+
+               // Internal flag for thread completion. See Processor.php
+               if (!empty($activity['thread-completion'])) {
+                       $object_data['thread-completion'] = $activity['thread-completion'];
+               }
+
+               switch ($type) {
+                       case 'as:Create':
+                       case 'as:Announce':
+                               ActivityPub\Processor::createItem($object_data);
+                               break;
+
+                       case 'as:Like':
+                               ActivityPub\Processor::likeItem($object_data);
+                               break;
+
+                       case 'as:Dislike':
+                               ActivityPub\Processor::dislikeItem($object_data);
+                               break;
+
+                       case 'as:Update':
+                               if (in_array($object_data['object_type'], self::CONTENT_TYPES)) {
+                                       /// @todo
+                               } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) {
+                                       ActivityPub\Processor::updatePerson($object_data, $body);
+                               }
+                               break;
+
+                       case 'as:Delete':
+                               if ($object_data['object_type'] == 'as:Tombstone') {
+                                       ActivityPub\Processor::deleteItem($object_data, $body);
+                               } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) {
+                                       ActivityPub\Processor::deletePerson($object_data, $body);
+                               }
+                               break;
+
+                       case 'as:Follow':
+                               ActivityPub\Processor::followUser($object_data);
+                               break;
+
+                       case 'as:Accept':
+                               if ($object_data['object_type'] == 'as:Follow') {
+                                       ActivityPub\Processor::acceptFollowUser($object_data);
+                               }
+                               break;
+
+                       case 'as:Reject':
+                               if ($object_data['object_type'] == 'as:Follow') {
+                                       ActivityPub\Processor::rejectFollowUser($object_data);
+                               }
+                               break;
+
+                       case 'as:Undo':
+                               if ($object_data['object_type'] == 'as:Follow') {
+                                       ActivityPub\Processor::undoFollowUser($object_data);
+                               } elseif (in_array($object_data['object_type'], self::ACTIVITY_TYPES)) {
+                                       ActivityPub\Processor::undoActivity($object_data);
+                               }
+                               break;
+
+                       default:
+                               logger('Unknown activity: ' . $type, LOGGER_DEBUG);
+                               break;
+               }
+       }
+
+       /**
+        * Fetch the receiver list from an activity array
+        *
+        * @param array $activity
+        * @param string $actor
+        *
+        * @return array with receivers (user id)
+        */
+       private static function getReceivers($activity, $actor)
+       {
+               $receivers = [];
+
+               // When it is an answer, we inherite the receivers from the parent
+               $replyto = JsonLD::fetchElement($activity, 'as:inReplyTo');
+               if (!empty($replyto)) {
+                       $parents = Item::select(['uid'], ['uri' => $replyto]);
+                       while ($parent = Item::fetch($parents)) {
+                               $receivers['uid:' . $parent['uid']] = $parent['uid'];
+                       }
+               }
+
+               if (!empty($actor)) {
+                       $profile = APContact::getByURL($actor);
+                       $followers = defaults($profile, 'followers', '');
+
+                       logger('Actor: ' . $actor . ' - Followers: ' . $followers, LOGGER_DEBUG);
+               } else {
+                       logger('Empty actor', LOGGER_DEBUG);
+                       $followers = '';
+               }
+
+               foreach (['as:to', 'as:cc', 'as:bto', 'as:bcc'] as $element) {
+                       $receiver_list = JsonLD::fetchElementArray($activity, $element);
+                       if (empty($receiver_list)) {
+                               continue;
+                       }
+
+                       foreach ($receiver_list as $receiver) {
+                               if ($receiver == self::PUBLIC_COLLECTION) {
+                                       $receivers['uid:0'] = 0;
+                               }
+
+                               if (($receiver == self::PUBLIC_COLLECTION) && !empty($actor)) {
+                                       // This will most likely catch all OStatus connections to Mastodon
+                                       $condition = ['alias' => [$actor, normalise_link($actor)], 'rel' => [Contact::SHARING, Contact::FRIEND]
+                                               , 'archive' => false, 'pending' => false];
+                                       $contacts = DBA::select('contact', ['uid'], $condition);
+                                       while ($contact = DBA::fetch($contacts)) {
+                                               if ($contact['uid'] != 0) {
+                                                       $receivers['uid:' . $contact['uid']] = $contact['uid'];
+                                               }
+                                       }
+                                       DBA::close($contacts);
+                               }
+
+                               if (in_array($receiver, [$followers, self::PUBLIC_COLLECTION]) && !empty($actor)) {
+                                       $condition = ['nurl' => normalise_link($actor), 'rel' => [Contact::SHARING, Contact::FRIEND],
+                                               'network' => Protocol::ACTIVITYPUB, 'archive' => false, 'pending' => false];
+                                       $contacts = DBA::select('contact', ['uid'], $condition);
+                                       while ($contact = DBA::fetch($contacts)) {
+                                               if ($contact['uid'] != 0) {
+                                                       $receivers['uid:' . $contact['uid']] = $contact['uid'];
+                                               }
+                                       }
+                                       DBA::close($contacts);
+                                       continue;
+                               }
+
+                               $condition = ['self' => true, 'nurl' => normalise_link($receiver)];
+                               $contact = DBA::selectFirst('contact', ['uid'], $condition);
+                               if (!DBA::isResult($contact)) {
+                                       continue;
+                               }
+                               $receivers['uid:' . $contact['uid']] = $contact['uid'];
+                       }
+               }
+
+               self::switchContacts($receivers, $actor);
+
+               return $receivers;
+       }
+
+       /**
+        * Switches existing contacts to ActivityPub
+        *
+        * @param integer $cid Contact ID
+        * @param integer $uid User ID
+        * @param string $url Profile URL
+        */
+       public static function switchContact($cid, $uid, $url)
+       {
+               $profile = ActivityPub::probeProfile($url);
+               if (empty($profile)) {
+                       return;
+               }
+
+               logger('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' to ActivityPub');
+
+               $photo = $profile['photo'];
+               unset($profile['photo']);
+               unset($profile['baseurl']);
+
+               $profile['nurl'] = normalise_link($profile['url']);
+               DBA::update('contact', $profile, ['id' => $cid]);
+
+               Contact::updateAvatar($photo, $uid, $cid);
+
+               // Send a new follow request to be sure that the connection still exists
+               if (($uid != 0) && DBA::exists('contact', ['id' => $cid, 'rel' => [Contact::SHARING, Contact::FRIEND]])) {
+                       ActivityPub\Transmitter::sendActivity('Follow', $profile['url'], $uid);
+                       logger('Send a new follow request to ' . $profile['url'] . ' for user ' . $uid, LOGGER_DEBUG);
+               }
+       }
+
+       /**
+        * 
+        *
+        * @param $receivers
+        * @param $actor
+        */
+       private static function switchContacts($receivers, $actor)
+       {
+               if (empty($actor)) {
+                       return;
+               }
+
+               foreach ($receivers as $receiver) {
+                       $contact = DBA::selectFirst('contact', ['id'], ['uid' => $receiver, 'network' => Protocol::OSTATUS, 'nurl' => normalise_link($actor)]);
+                       if (DBA::isResult($contact)) {
+                               self::switchContact($contact['id'], $receiver, $actor);
+                       }
+
+                       $contact = DBA::selectFirst('contact', ['id'], ['uid' => $receiver, 'network' => Protocol::OSTATUS, 'alias' => [normalise_link($actor), $actor]]);
+                       if (DBA::isResult($contact)) {
+                               self::switchContact($contact['id'], $receiver, $actor);
+                       }
+               }
+       }
+
+       /**
+        * 
+        *
+        * @param $object_data
+        * @param array $activity
+        *
+        * @return 
+        */
+       private static function addActivityFields($object_data, $activity)
+       {
+               if (!empty($activity['published']) && empty($object_data['published'])) {
+                       $object_data['published'] = JsonLD::fetchElement($activity, 'as:published', '@value');
+               }
+
+               if (!empty($activity['diaspora:guid']) && empty($object_data['diaspora:guid'])) {
+                       $object_data['diaspora:guid'] = JsonLD::fetchElement($activity, 'diaspora:guid');
+               }
+
+               $object_data['service'] = JsonLD::fetchElement($activity, 'as:instrument', 'as:name', '@type', 'as:Service');
+
+               return $object_data;
+       }
+
+       /**
+        * Fetches the object data from external ressources if needed
+        *
+        * @param string  $object_id    Object ID of the the provided object
+        * @param array   $object       The provided object array
+        * @param boolean $trust_source Do we trust the provided object?
+        *
+        * @return array with trusted and valid object data
+        */
+       private static function fetchObject($object_id, $object = [], $trust_source = false)
+       {
+               // By fetching the type we check if the object is complete.
+               $type = JsonLD::fetchElement($object, '@type');
+
+               if (!$trust_source || empty($type)) {
+                       $data = ActivityPub::fetchContent($object_id);
+                       if (!empty($data)) {
+                               $object = JsonLD::compact($data);
+                               logger('Fetched content for ' . $object_id, LOGGER_DEBUG);
+                       } else {
+                               logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG);
+
+                               $item = Item::selectFirst([], ['uri' => $object_id]);
+                               if (!DBA::isResult($item)) {
+                                       logger('Object with url ' . $object_id . ' was not found locally.', LOGGER_DEBUG);
+                                       return false;
+                               }
+                               logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG);
+                               $data = ActivityPub\Transmitter::createNote($item);
+                               $object = JsonLD::compact($data);
+                       }
+               } else {
+                       logger('Using original object for url ' . $object_id, LOGGER_DEBUG);
+               }
+
+               $type = JsonLD::fetchElement($object, '@type');
+
+               if (empty($type)) {
+                       logger('Empty type', LOGGER_DEBUG);
+                       return false;
+               }
+
+               if (in_array($type, self::CONTENT_TYPES)) {
+                       return self::processObject($object);
+               }
+
+               if ($type == 'as:Announce') {
+                       $object_id = JsonLD::fetchElement($object, 'object');
+                       if (empty($object_id)) {
+                               return false;
+                       }
+                       return self::fetchObject($object_id);
+               }
+
+               logger('Unhandled object type: ' . $type, LOGGER_DEBUG);
+       }
+
+       /**
+        * Convert tags from JSON-LD format into a simplified format
+        *
+        * @param array $tags Tags in JSON-LD format
+        *
+        * @return array with tags in a simplified format
+        */
+       private static function processTags($tags)
+       {
+               $taglist = [];
+
+               if (empty($tags)) {
+                       return [];
+               }
+
+               foreach ($tags as $tag) {
+                       if (empty($tag)) {
+                               continue;
+                       }
+
+                       $taglist[] = ['type' => str_replace('as:', '', JsonLD::fetchElement($tag, '@type')),
+                               'href' => JsonLD::fetchElement($tag, 'as:href'),
+                               'name' => JsonLD::fetchElement($tag, 'as:name')];
+               }
+               return $taglist;
+       }
+
+       /**
+        * Convert attachments from JSON-LD format into a simplified format
+        *
+        * @param array $attachments Attachments in JSON-LD format
+        *
+        * @return array with attachmants in a simplified format
+        */
+       private static function processAttachments($attachments)
+       {
+               $attachlist = [];
+
+               if (empty($attachments)) {
+                       return [];
+               }
+
+               foreach ($attachments as $attachment) {
+                       if (empty($attachment)) {
+                               continue;
+                       }
+
+                       $attachlist[] = ['type' => str_replace('as:', '', JsonLD::fetchElement($attachment, '@type')),
+                               'mediaType' => JsonLD::fetchElement($attachment, 'as:mediaType'),
+                               'name' => JsonLD::fetchElement($attachment, 'as:name'),
+                               'url' => JsonLD::fetchElement($attachment, 'as:url')];
+               }
+               return $attachlist;
+       }
+
+       /**
+        * Fetches data from the object part of an activity
+        *
+        * @param array $object
+        *
+        * @return array
+        */
+       private static function processObject($object)
+       {
+               if (!JsonLD::fetchElement($object, '@id')) {
+                       return false;
+               }
+
+               $object_data = [];
+               $object_data['object_type'] = JsonLD::fetchElement($object, '@type');
+               $object_data['id'] = JsonLD::fetchElement($object, '@id');
+
+               $object_data['reply-to-id'] = JsonLD::fetchElement($object, 'as:inReplyTo');
+
+               if (empty($object_data['reply-to-id'])) {
+                       $object_data['reply-to-id'] = $object_data['id'];
+               }
+
+               $object_data['published'] = JsonLD::fetchElement($object, 'as:published', '@value');
+               $object_data['updated'] = JsonLD::fetchElement($object, 'as:updated', '@value');
+
+               if (empty($object_data['updated'])) {
+                       $object_data['updated'] = $object_data['published'];
+               }
+
+               if (empty($object_data['published']) && !empty($object_data['updated'])) {
+                       $object_data['published'] = $object_data['updated'];
+               }
+
+               $actor = JsonLD::fetchElement($object, 'as:attributedTo');
+               if (empty($actor)) {
+                       $actor = JsonLD::fetchElement($object, 'as:actor');
+               }
+
+               $object_data['diaspora:guid'] = JsonLD::fetchElement($object, 'diaspora:guid');
+               $object_data['diaspora:comment'] = JsonLD::fetchElement($object, 'diaspora:comment');
+               $object_data['actor'] = $object_data['author'] = $actor;
+               $object_data['context'] = JsonLD::fetchElement($object, 'as:context');
+               $object_data['conversation'] = JsonLD::fetchElement($object, 'ostatus:conversation');
+               $object_data['sensitive'] = JsonLD::fetchElement($object, 'as:sensitive');
+               $object_data['name'] = JsonLD::fetchElement($object, 'as:name');
+               $object_data['summary'] = JsonLD::fetchElement($object, 'as:summary');
+               $object_data['content'] = JsonLD::fetchElement($object, 'as:content');
+               $object_data['source'] = JsonLD::fetchElement($object, 'as:source', 'as:content', 'as:mediaType', 'text/bbcode');
+               $object_data['location'] = JsonLD::fetchElement($object, 'as:location', 'as:name', '@type', 'as:Place');
+               $object_data['latitude'] = JsonLD::fetchElement($object, 'as:location', 'as:latitude', '@type', 'as:Place');
+               $object_data['latitude'] = JsonLD::fetchElement($object_data, 'latitude', '@value');
+               $object_data['longitude'] = JsonLD::fetchElement($object, 'as:location', 'as:longitude', '@type', 'as:Place');
+               $object_data['longitude'] = JsonLD::fetchElement($object_data, 'longitude', '@value');
+               $object_data['attachments'] = self::processAttachments(JsonLD::fetchElementArray($object, 'as:attachment'));
+               $object_data['tags'] = self::processTags(JsonLD::fetchElementArray($object, 'as:tag'));
+               $object_data['generator'] = JsonLD::fetchElement($object, 'as:generator', 'as:name', '@type', 'as:Application');
+               $object_data['alternate-url'] = JsonLD::fetchElement($object, 'as:url');
+
+               // Special treatment for Hubzilla links
+               if (is_array($object_data['alternate-url'])) {
+                       $object_data['alternate-url'] = JsonLD::fetchElement($object_data['alternate-url'], 'as:href');
+
+                       if (!is_string($object_data['alternate-url'])) {
+                               $object_data['alternate-url'] = JsonLD::fetchElement($object['as:url'], 'as:href');
+                       }
+               }
+
+               $object_data['receiver'] = self::getReceivers($object, $object_data['actor']);
+
+               // Common object data:
+
+               // Unhandled
+               // @context, type, actor, signature, mediaType, duration, replies, icon
+
+               // Also missing: (Defined in the standard, but currently unused)
+               // audience, preview, endTime, startTime, image
+
+               // Data in Notes:
+
+               // Unhandled
+               // contentMap, announcement_count, announcements, context_id, likes, like_count
+               // inReplyToStatusId, shares, quoteUrl, statusnetConversationId
+
+               // Data in video:
+
+               // To-Do?
+               // category, licence, language, commentsEnabled
+
+               // Unhandled
+               // views, waitTranscoding, state, support, subtitleLanguage
+               // likes, dislikes, shares, comments
+
+               return $object_data;
+       }
+}
diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php
new file mode 100644 (file)
index 0000000..9ddcc1d
--- /dev/null
@@ -0,0 +1,1089 @@
+<?php
+/**
+ * @file src/Protocol/ActivityPub/Transmitter.php
+ */
+namespace Friendica\Protocol\ActivityPub;
+
+use Friendica\BaseObject;
+use Friendica\Database\DBA;
+use Friendica\Core\System;
+use Friendica\Util\HTTPSignature;
+use Friendica\Core\Protocol;
+use Friendica\Model\Conversation;
+use Friendica\Model\Contact;
+use Friendica\Model\APContact;
+use Friendica\Model\Item;
+use Friendica\Model\Term;
+use Friendica\Model\User;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Content\Text\BBCode;
+use Friendica\Util\JsonLD;
+use Friendica\Util\LDSignature;
+use Friendica\Model\Profile;
+use Friendica\Core\Config;
+use Friendica\Object\Image;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Protocol\Diaspora;
+use Friendica\Core\Cache;
+use Friendica\Util\Map;
+
+require_once 'include/api.php';
+
+/**
+ * @brief ActivityPub Transmitter Protocol class
+ *
+ * To-Do:
+ *
+ * Missing object types:
+ * - Event
+ *
+ * Complicated object types:
+ * - Undo Announce
+ *
+ * General:
+ * - Queueing unsucessful deliveries
+ */
+class Transmitter
+{
+       /**
+        * collects the lost of followers of the given owner
+        *
+        * @param array $owner Owner array
+        * @param integer $page Page number
+        *
+        * @return array of owners
+        */
+       public static function getFollowers($owner, $page = null)
+       {
+               $condition = ['rel' => [Contact::FOLLOWER, Contact::FRIEND], 'network' => Protocol::NATIVE_SUPPORT, 'uid' => $owner['uid'],
+                       'self' => false, 'hidden' => false, 'archive' => false, 'pending' => false];
+               $count = DBA::count('contact', $condition);
+
+               $data = ['@context' => ActivityPub::CONTEXT];
+               $data['id'] = System::baseUrl() . '/followers/' . $owner['nickname'];
+               $data['type'] = 'OrderedCollection';
+               $data['totalItems'] = $count;
+
+               // When we hide our friends we will only show the pure number but don't allow more.
+               $profile = Profile::getByUID($owner['uid']);
+               if (!empty($profile['hide-friends'])) {
+                       return $data;
+               }
+
+               if (empty($page)) {
+                       $data['first'] = System::baseUrl() . '/followers/' . $owner['nickname'] . '?page=1';
+               } else {
+                       $list = [];
+
+                       $contacts = DBA::select('contact', ['url'], $condition, ['limit' => [($page - 1) * 100, 100]]);
+                       while ($contact = DBA::fetch($contacts)) {
+                               $list[] = $contact['url'];
+                       }
+
+                       if (!empty($list)) {
+                               $data['next'] = System::baseUrl() . '/followers/' . $owner['nickname'] . '?page=' . ($page + 1);
+                       }
+
+                       $data['partOf'] = System::baseUrl() . '/followers/' . $owner['nickname'];
+
+                       $data['orderedItems'] = $list;
+               }
+
+               return $data;
+       }
+
+       /**
+        * Create list of following contacts
+        *
+        * @param array $owner Owner array
+        * @param integer $page Page numbe
+        *
+        * @return array of following contacts
+        */
+       public static function getFollowing($owner, $page = null)
+       {
+               $condition = ['rel' => [Contact::SHARING, Contact::FRIEND], 'network' => Protocol::NATIVE_SUPPORT, 'uid' => $owner['uid'],
+                       'self' => false, 'hidden' => false, 'archive' => false, 'pending' => false];
+               $count = DBA::count('contact', $condition);
+
+               $data = ['@context' => ActivityPub::CONTEXT];
+               $data['id'] = System::baseUrl() . '/following/' . $owner['nickname'];
+               $data['type'] = 'OrderedCollection';
+               $data['totalItems'] = $count;
+
+               // When we hide our friends we will only show the pure number but don't allow more.
+               $profile = Profile::getByUID($owner['uid']);
+               if (!empty($profile['hide-friends'])) {
+                       return $data;
+               }
+
+               if (empty($page)) {
+                       $data['first'] = System::baseUrl() . '/following/' . $owner['nickname'] . '?page=1';
+               } else {
+                       $list = [];
+
+                       $contacts = DBA::select('contact', ['url'], $condition, ['limit' => [($page - 1) * 100, 100]]);
+                       while ($contact = DBA::fetch($contacts)) {
+                               $list[] = $contact['url'];
+                       }
+
+                       if (!empty($list)) {
+                               $data['next'] = System::baseUrl() . '/following/' . $owner['nickname'] . '?page=' . ($page + 1);
+                       }
+
+                       $data['partOf'] = System::baseUrl() . '/following/' . $owner['nickname'];
+
+                       $data['orderedItems'] = $list;
+               }
+
+               return $data;
+       }
+
+       /**
+        * Public posts for the given owner
+        *
+        * @param array $owner Owner array
+        * @param integer $page Page numbe
+        *
+        * @return array of posts
+        */
+       public static function getOutbox($owner, $page = null)
+       {
+               $public_contact = Contact::getIdForURL($owner['url'], 0, true);
+
+               $condition = ['uid' => 0, 'contact-id' => $public_contact, 'author-id' => $public_contact,
+                       'private' => false, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
+                       'deleted' => false, 'visible' => true];
+               $count = DBA::count('item', $condition);
+
+               $data = ['@context' => ActivityPub::CONTEXT];
+               $data['id'] = System::baseUrl() . '/outbox/' . $owner['nickname'];
+               $data['type'] = 'OrderedCollection';
+               $data['totalItems'] = $count;
+
+               if (empty($page)) {
+                       $data['first'] = System::baseUrl() . '/outbox/' . $owner['nickname'] . '?page=1';
+               } else {
+                       $list = [];
+
+                       $condition['parent-network'] = Protocol::NATIVE_SUPPORT;
+
+                       $items = Item::select(['id'], $condition, ['limit' => [($page - 1) * 20, 20], 'order' => ['created' => true]]);
+                       while ($item = Item::fetch($items)) {
+                               $object = self::createObjectFromItemID($item['id']);
+                               unset($object['@context']);
+                               $list[] = $object;
+                       }
+
+                       if (!empty($list)) {
+                               $data['next'] = System::baseUrl() . '/outbox/' . $owner['nickname'] . '?page=' . ($page + 1);
+                       }
+
+                       $data['partOf'] = System::baseUrl() . '/outbox/' . $owner['nickname'];
+
+                       $data['orderedItems'] = $list;
+               }
+
+               return $data;
+       }
+
+       /**
+        * Return the ActivityPub profile of the given user
+        *
+        * @param integer $uid User ID
+        * @return array with profile data
+        */
+       public static function getProfile($uid)
+       {
+               $condition = ['uid' => $uid, 'blocked' => false, 'account_expired' => false,
+                       'account_removed' => false, 'verified' => true];
+               $fields = ['guid', 'nickname', 'pubkey', 'account-type', 'page-flags'];
+               $user = DBA::selectFirst('user', $fields, $condition);
+               if (!DBA::isResult($user)) {
+                       return [];
+               }
+
+               $fields = ['locality', 'region', 'country-name'];
+               $profile = DBA::selectFirst('profile', $fields, ['uid' => $uid, 'is-default' => true]);
+               if (!DBA::isResult($profile)) {
+                       return [];
+               }
+
+               $fields = ['name', 'url', 'location', 'about', 'avatar', 'photo'];
+               $contact = DBA::selectFirst('contact', $fields, ['uid' => $uid, 'self' => true]);
+               if (!DBA::isResult($contact)) {
+                       return [];
+               }
+
+               // On old installations and never changed contacts this might not be filled
+               if (empty($contact['avatar'])) {
+                       $contact['avatar'] = $contact['photo'];
+               }
+
+               $data = ['@context' => ActivityPub::CONTEXT];
+               $data['id'] = $contact['url'];
+               $data['diaspora:guid'] = $user['guid'];
+               $data['type'] = ActivityPub::ACCOUNT_TYPES[$user['account-type']];
+               $data['following'] = System::baseUrl() . '/following/' . $user['nickname'];
+               $data['followers'] = System::baseUrl() . '/followers/' . $user['nickname'];
+               $data['inbox'] = System::baseUrl() . '/inbox/' . $user['nickname'];
+               $data['outbox'] = System::baseUrl() . '/outbox/' . $user['nickname'];
+               $data['preferredUsername'] = $user['nickname'];
+               $data['name'] = $contact['name'];
+               $data['vcard:hasAddress'] = ['@type' => 'vcard:Home', 'vcard:country-name' => $profile['country-name'],
+                       'vcard:region' => $profile['region'], 'vcard:locality' => $profile['locality']];
+               $data['summary'] = $contact['about'];
+               $data['url'] = $contact['url'];
+               $data['manuallyApprovesFollowers'] = in_array($user['page-flags'], [Contact::PAGE_NORMAL, Contact::PAGE_PRVGROUP]);
+               $data['publicKey'] = ['id' => $contact['url'] . '#main-key',
+                       'owner' => $contact['url'],
+                       'publicKeyPem' => $user['pubkey']];
+               $data['endpoints'] = ['sharedInbox' => System::baseUrl() . '/inbox'];
+               $data['icon'] = ['type' => 'Image',
+                       'url' => $contact['avatar']];
+
+               // tags: https://kitty.town/@inmysocks/100656097926961126.json
+               return $data;
+       }
+
+       /**
+        * Returns an array with permissions of a given item array
+        *
+        * @param array $item
+        *
+        * @return array with permissions
+        */
+       private static function fetchPermissionBlockFromConversation($item)
+       {
+               if (empty($item['thr-parent'])) {
+                       return [];
+               }
+
+               $condition = ['item-uri' => $item['thr-parent'], 'protocol' => Conversation::PARCEL_ACTIVITYPUB];
+               $conversation = DBA::selectFirst('conversation', ['source'], $condition);
+               if (!DBA::isResult($conversation)) {
+                       return [];
+               }
+
+               $activity = json_decode($conversation['source'], true);
+
+               $actor = JsonLD::fetchElement($activity, 'actor', 'id');
+               $profile = APContact::getByURL($actor);
+
+               $item_profile = APContact::getByURL($item['author-link']);
+               $exclude[] = $item['author-link'];
+
+               if ($item['gravity'] == GRAVITY_PARENT) {
+                       $exclude[] = $item['owner-link'];
+               }
+
+               $permissions['to'][] = $actor;
+
+               foreach (['to', 'cc', 'bto', 'bcc'] as $element) {
+                       if (empty($activity[$element])) {
+                               continue;
+                       }
+                       if (is_string($activity[$element])) {
+                               $activity[$element] = [$activity[$element]];
+                       }
+
+                       foreach ($activity[$element] as $receiver) {
+                               if ($receiver == $profile['followers'] && !empty($item_profile['followers'])) {
+                                       $receiver = $item_profile['followers'];
+                               }
+                               if (!in_array($receiver, $exclude)) {
+                                       $permissions[$element][] = $receiver;
+                               }
+                       }
+               }
+               return $permissions;
+       }
+
+       /**
+        * Creates an array of permissions from an item thread
+        *
+        * @param array $item
+        *
+        * @return array with permission data
+        */
+       private static function createPermissionBlockForItem($item)
+       {
+               $data = ['to' => [], 'cc' => []];
+
+               $data = array_merge($data, self::fetchPermissionBlockFromConversation($item));
+
+               $actor_profile = APContact::getByURL($item['author-link']);
+
+               $terms = Term::tagArrayFromItemId($item['id'], TERM_MENTION);
+
+               $contacts[$item['author-link']] = $item['author-link'];
+
+               if (!$item['private']) {
+                       $data['to'][] = ActivityPub::PUBLIC_COLLECTION;
+                       if (!empty($actor_profile['followers'])) {
+                               $data['cc'][] = $actor_profile['followers'];
+                       }
+
+                       foreach ($terms as $term) {
+                               $profile = APContact::getByURL($term['url'], false);
+                               if (!empty($profile) && empty($contacts[$profile['url']])) {
+                                       $data['to'][] = $profile['url'];
+                                       $contacts[$profile['url']] = $profile['url'];
+
+                                       if (($key = array_search($profile['url'], $data['cc'])) !== false) {
+                                               unset($data['cc'][$key]);
+                                       }
+                               }
+                       }
+               } else {
+                       $receiver_list = Item::enumeratePermissions($item);
+
+                       $mentioned = [];
+
+                       foreach ($terms as $term) {
+                               $cid = Contact::getIdForURL($term['url'], $item['uid']);
+                               if (!empty($cid) && in_array($cid, $receiver_list)) {
+                                       $contact = DBA::selectFirst('contact', ['url'], ['id' => $cid, 'network' => Protocol::ACTIVITYPUB]);
+                                       $data['to'][] = $contact['url'];
+                                       $contacts[$contact['url']] = $contact['url'];
+
+                                       if (($key = array_search($profile['url'], $data['cc'])) !== false) {
+                                               unset($data['cc'][$key]);
+                                       }
+                               }
+                       }
+
+                       foreach ($receiver_list as $receiver) {
+                               $contact = DBA::selectFirst('contact', ['url'], ['id' => $receiver, 'network' => Protocol::ACTIVITYPUB]);
+                               if (empty($contacts[$contact['url']])) {
+                                       $data['cc'][] = $contact['url'];
+                                       $contacts[$contact['url']] = $contact['url'];
+                               }
+                       }
+               }
+
+               $parents = Item::select(['id', 'author-link', 'owner-link', 'gravity', 'uri'], ['parent' => $item['parent']]);
+               while ($parent = Item::fetch($parents)) {
+                       // Don't include data from future posts
+                       if ($parent['id'] >= $item['id']) {
+                               continue;
+                       }
+
+                       $profile = APContact::getByURL($parent['author-link'], false);
+                       if (!empty($profile) && ($parent['uri'] == $item['thr-parent'])) {
+                               $data['to'][] = $profile['url'];
+                               $contacts[$profile['url']] = $profile['url'];
+
+                               if (($key = array_search($profile['url'], $data['cc'])) !== false) {
+                                       unset($data['cc'][$key]);
+                               }
+                       }
+
+                       if (!empty($profile) && empty($contacts[$profile['url']])) {
+                               $data['cc'][] = $profile['url'];
+                               $contacts[$profile['url']] = $profile['url'];
+                       }
+
+                       if ($item['gravity'] != GRAVITY_PARENT) {
+                               continue;
+                       }
+
+                       $profile = APContact::getByURL($parent['owner-link'], false);
+                       if (!empty($profile) && empty($contacts[$profile['url']])) {
+                               $data['cc'][] = $profile['url'];
+                               $contacts[$profile['url']] = $profile['url'];
+                       }
+               }
+               DBA::close($parents);
+
+               if (($key = array_search($item['author-link'], $data['to'])) !== false) {
+                       unset($data['to'][$key]);
+               }
+
+               if (($key = array_search($item['author-link'], $data['cc'])) !== false) {
+                       unset($data['cc'][$key]);
+               }
+
+               return ['to' => array_values(array_unique($data['to'])), 'cc' => array_values(array_unique($data['cc']))];
+       }
+
+       /**
+        * Fetches a list of inboxes of followers of a given user
+        *
+        * @param integer $uid User ID
+        *
+        * @return array of follower inboxes
+        */
+       public static function fetchTargetInboxesforUser($uid)
+       {
+               $inboxes = [];
+
+               $condition = ['uid' => $uid, 'network' => Protocol::ACTIVITYPUB, 'archive' => false, 'pending' => false];
+
+               if (!empty($uid)) {
+                       $condition['rel'] = [Contact::FOLLOWER, Contact::FRIEND];
+               }
+
+               $contacts = DBA::select('contact', ['notify', 'batch'], $condition);
+               while ($contact = DBA::fetch($contacts)) {
+                       $contact = defaults($contact, 'batch', $contact['notify']);
+                       $inboxes[$contact] = $contact;
+               }
+               DBA::close($contacts);
+
+               return $inboxes;
+       }
+
+       /**
+        * Fetches an array of inboxes for the given item and user
+        *
+        * @param array $item
+        * @param integer $uid User ID
+        *
+        * @return array with inboxes
+        */
+       public static function fetchTargetInboxes($item, $uid)
+       {
+               $permissions = self::createPermissionBlockForItem($item);
+               if (empty($permissions)) {
+                       return [];
+               }
+
+               $inboxes = [];
+
+               if ($item['gravity'] == GRAVITY_ACTIVITY) {
+                       $item_profile = APContact::getByURL($item['author-link']);
+               } else {
+                       $item_profile = APContact::getByURL($item['owner-link']);
+               }
+
+               foreach (['to', 'cc', 'bto', 'bcc'] as $element) {
+                       if (empty($permissions[$element])) {
+                               continue;
+                       }
+
+                       foreach ($permissions[$element] as $receiver) {
+                               if ($receiver == $item_profile['followers']) {
+                                       $inboxes = self::fetchTargetInboxesforUser($uid);
+                               } else {
+                                       $profile = APContact::getByURL($receiver);
+                                       if (!empty($profile)) {
+                                               $target = defaults($profile, 'sharedinbox', $profile['inbox']);
+                                               $inboxes[$target] = $target;
+                                       }
+                               }
+                       }
+               }
+
+               return $inboxes;
+       }
+
+       /**
+        * Returns the activity type of a given item
+        *
+        * @param array $item
+        *
+        * @return string with activity type
+        */
+       private static function getTypeOfItem($item)
+       {
+               if (!empty(Diaspora::isReshare($item['body'], false))) {
+                       $type = 'Announce';
+               } elseif ($item['verb'] == ACTIVITY_POST) {
+                       if ($item['created'] == $item['edited']) {
+                               $type = 'Create';
+                       } else {
+                               $type = 'Update';
+                       }
+               } elseif ($item['verb'] == ACTIVITY_LIKE) {
+                       $type = 'Like';
+               } elseif ($item['verb'] == ACTIVITY_DISLIKE) {
+                       $type = 'Dislike';
+               } elseif ($item['verb'] == ACTIVITY_ATTEND) {
+                       $type = 'Accept';
+               } elseif ($item['verb'] == ACTIVITY_ATTENDNO) {
+                       $type = 'Reject';
+               } elseif ($item['verb'] == ACTIVITY_ATTENDMAYBE) {
+                       $type = 'TentativeAccept';
+               } else {
+                       $type = '';
+               }
+
+               return $type;
+       }
+
+       /**
+        * Creates the activity or fetches it from the cache
+        *
+        * @param integer $item_id
+        *
+        * @return array with the activity
+        */
+       public static function createCachedActivityFromItem($item_id)
+       {
+               $cachekey = 'APDelivery:createActivity:' . $item_id;
+               $data = Cache::get($cachekey);
+               if (!is_null($data)) {
+                       return $data;
+               }
+
+               $data = ActivityPub\Transmitter::createActivityFromItem($item_id);
+
+               Cache::set($cachekey, $data, CACHE_QUARTER_HOUR);
+               return $data;
+       }
+
+       /**
+        * Creates an activity array for a given item id
+        *
+        * @param integer $item_id
+        * @param boolean $object_mode Is the activity item is used inside another object?
+        *
+        * @return array of activity
+        */
+       public static function createActivityFromItem($item_id, $object_mode = false)
+       {
+               $item = Item::selectFirst([], ['id' => $item_id, 'parent-network' => Protocol::NATIVE_SUPPORT]);
+
+               if (!DBA::isResult($item)) {
+                       return false;
+               }
+
+               $condition = ['item-uri' => $item['uri'], 'protocol' => Conversation::PARCEL_ACTIVITYPUB];
+               $conversation = DBA::selectFirst('conversation', ['source'], $condition);
+               if (DBA::isResult($conversation)) {
+                       $data = json_decode($conversation['source']);
+                       if (!empty($data)) {
+                               return $data;
+                       }
+               }
+
+               $type = self::getTypeOfItem($item);
+
+               if (!$object_mode) {
+                       $data = ['@context' => ActivityPub::CONTEXT];
+
+                       if ($item['deleted'] && ($item['gravity'] == GRAVITY_ACTIVITY)) {
+                               $type = 'Undo';
+                       } elseif ($item['deleted']) {
+                               $type = 'Delete';
+                       }
+               } else {
+                       $data = [];
+               }
+
+               $data['id'] = $item['uri'] . '#' . $type;
+               $data['type'] = $type;
+               $data['actor'] = $item['owner-link'];
+
+               $data['published'] = DateTimeFormat::utc($item['created'] . '+00:00', DateTimeFormat::ATOM);
+
+               $data['instrument'] = ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()];
+
+               $data = array_merge($data, self::createPermissionBlockForItem($item));
+
+               if (in_array($data['type'], ['Create', 'Update', 'Delete'])) {
+                       $data['object'] = self::createNote($item);
+               } elseif ($data['type'] == 'Announce') {
+                       $data['object'] = self::createAnnounce($item);
+               } elseif ($data['type'] == 'Undo') {
+                       $data['object'] = self::createActivityFromItem($item_id, true);
+               } else {
+                       $data['diaspora:guid'] = $item['guid'];
+                       $data['object'] = $item['thr-parent'];
+               }
+
+               $owner = User::getOwnerDataById($item['uid']);
+
+               if (!$object_mode) {
+                       return LDSignature::sign($data, $owner);
+               } else {
+                       return $data;
+               }
+
+               /// @todo Create "conversation" entry
+       }
+
+       /**
+        * Creates an object array for a given item id
+        *
+        * @param integer $item_id
+        *
+        * @return array with the object data
+        */
+       public static function createObjectFromItemID($item_id)
+       {
+               $item = Item::selectFirst([], ['id' => $item_id, 'parent-network' => Protocol::NATIVE_SUPPORT]);
+
+               if (!DBA::isResult($item)) {
+                       return false;
+               }
+
+               $data = ['@context' => ActivityPub::CONTEXT];
+               $data = array_merge($data, self::createNote($item));
+
+               return $data;
+       }
+
+       /**
+        * Creates a location entry for a given item array
+        *
+        * @param array $item
+        *
+        * @return array with location array
+        */
+       private static function createLocation($item)
+       {
+               $location = ['type' => 'Place'];
+
+               if (!empty($item['location'])) {
+                       $location['name'] = $item['location'];
+               }
+
+               $coord = [];
+
+               if (empty($item['coord'])) {
+                       $coord = Map::getCoordinates($item['location']);
+               } else {
+                       $coords = explode(' ', $item['coord']);
+                       if (count($coords) == 2) {
+                               $coord = ['lat' => $coords[0], 'lon' => $coords[1]];
+                       }
+               }
+
+               if (!empty($coord['lat']) && !empty($coord['lon'])) {
+                       $location['latitude'] = $coord['lat'];
+                       $location['longitude'] = $coord['lon'];
+               }
+
+               return $location;
+       }
+
+       /**
+        * Returns a tag array for a given item array
+        *
+        * @param array $item
+        *
+        * @return array of tags
+        */
+       private static function createTagList($item)
+       {
+               $tags = [];
+
+               $terms = Term::tagArrayFromItemId($item['id']);
+               foreach ($terms as $term) {
+                       if ($term['type'] == TERM_HASHTAG) {
+                               $tags[] = ['type' => 'Hashtag', 'href' => $term['url'], 'name' => '#' . $term['term']];
+                       } elseif ($term['type'] == TERM_MENTION) {
+                               $contact = Contact::getDetailsByURL($term['url']);
+                               if (!empty($contact['addr'])) {
+                                       $mention = '@' . $contact['addr'];
+                               } else {
+                                       $mention = '@' . $term['url'];
+                               }
+
+                               $tags[] = ['type' => 'Mention', 'href' => $term['url'], 'name' => $mention];
+                       }
+               }
+               return $tags;
+       }
+
+       /**
+        * Adds attachment data to the JSON document
+        *
+        * @param array $item Data of the item that is to be posted
+        * @param text $type Object type
+        *
+        * @return array with attachment data
+        */
+       private static function createAttachmentList($item, $type)
+       {
+               $attachments = [];
+
+               $arr = explode('[/attach],', $item['attach']);
+               if (count($arr)) {
+                       foreach ($arr as $r) {
+                               $matches = false;
+                               $cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|', $r, $matches);
+                               if ($cnt) {
+                                       $attributes = ['type' => 'Document',
+                                                       'mediaType' => $matches[3],
+                                                       'url' => $matches[1],
+                                                       'name' => null];
+
+                                       if (trim($matches[4]) != '') {
+                                               $attributes['name'] = trim($matches[4]);
+                                       }
+
+                                       $attachments[] = $attributes;
+                               }
+                       }
+               }
+
+               if ($type != 'Note') {
+                       return $attachments;
+               }
+
+               // Simplify image codes
+               $body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $item['body']);
+
+               // Grab all pictures and create attachments out of them
+               if (preg_match_all("/\[img\]([^\[\]]*)\[\/img\]/Usi", $body, $pictures)) {
+                       foreach ($pictures[1] as $picture) {
+                               $imgdata = Image::getInfoFromURL($picture);
+                               if ($imgdata) {
+                                       $attachments[] = ['type' => 'Document',
+                                               'mediaType' => $imgdata['mime'],
+                                               'url' => $picture,
+                                               'name' => null];
+                               }
+                       }
+               }
+
+               return $attachments;
+       }
+
+       /**
+        * Remove image elements and replaces them with links to the image
+        *
+        * @param string $body
+        *
+        * @return string with replaced elements
+        */
+       private static function removePictures($body)
+       {
+               // Simplify image codes
+               $body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
+
+               $body = preg_replace("/\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]/Usi", '[url]$1[/url]', $body);
+               $body = preg_replace("/\[img\]([^\[\]]*)\[\/img\]/Usi", '[url]$1[/url]', $body);
+
+               return $body;
+       }
+
+       /**
+        * Fetches the "context" value for a givem item array from the "conversation" table
+        *
+        * @param array $item
+        *
+        * @return string with context url
+        */
+       private static function fetchContextURLForItem($item)
+       {
+               $conversation = DBA::selectFirst('conversation', ['conversation-href', 'conversation-uri'], ['item-uri' => $item['parent-uri']]);
+               if (DBA::isResult($conversation) && !empty($conversation['conversation-href'])) {
+                       $context_uri = $conversation['conversation-href'];
+               } elseif (DBA::isResult($conversation) && !empty($conversation['conversation-uri'])) {
+                       $context_uri = $conversation['conversation-uri'];
+               } else {
+                       $context_uri = $item['parent-uri'] . '#context';
+               }
+               return $context_uri;
+       }
+
+       /**
+        * Returns if the post contains sensitive content ("nsfw")
+        *
+        * @param integer $item_id
+        *
+        * @return boolean
+        */
+       private static function isSensitive($item_id)
+       {
+               $condition = ['otype' => TERM_OBJ_POST, 'oid' => $item_id, 'type' => TERM_HASHTAG, 'term' => 'nsfw'];
+               return DBA::exists('term', $condition);
+       }
+
+       /**
+        * Creates a note/article object array
+        *
+        * @param array $item
+        *
+        * @return array with the object data
+        */
+       public static function createNote($item)
+       {
+               if (!empty($item['title'])) {
+                       $type = 'Article';
+               } else {
+                       $type = 'Note';
+               }
+
+               if ($item['deleted']) {
+                       $type = 'Tombstone';
+               }
+
+               $data = [];
+               $data['id'] = $item['uri'];
+               $data['type'] = $type;
+
+               if ($item['deleted']) {
+                       return $data;
+               }
+
+               $data['summary'] = null; // Ignore by now
+
+               if ($item['uri'] != $item['thr-parent']) {
+                       $data['inReplyTo'] = $item['thr-parent'];
+               } else {
+                       $data['inReplyTo'] = null;
+               }
+
+               $data['diaspora:guid'] = $item['guid'];
+               $data['published'] = DateTimeFormat::utc($item['created'] . '+00:00', DateTimeFormat::ATOM);
+
+               if ($item['created'] != $item['edited']) {
+                       $data['updated'] = DateTimeFormat::utc($item['edited'] . '+00:00', DateTimeFormat::ATOM);
+               }
+
+               $data['url'] = $item['plink'];
+               $data['attributedTo'] = $item['author-link'];
+               $data['sensitive'] = self::isSensitive($item['id']);
+               $data['context'] = self::fetchContextURLForItem($item);
+
+               if (!empty($item['title'])) {
+                       $data['name'] = BBCode::toPlaintext($item['title'], false);
+               }
+
+               $body = $item['body'];
+
+               if ($type == 'Note') {
+                       $body = self::removePictures($body);
+               }
+
+               $data['content'] = BBCode::convert($body, false, 7);
+               $data['source'] = ['content' => $item['body'], 'mediaType' => "text/bbcode"];
+
+               if (!empty($item['signed_text']) && ($item['uri'] != $item['thr-parent'])) {
+                       $data['diaspora:comment'] = $item['signed_text'];
+               }
+
+               $data['attachment'] = self::createAttachmentList($item, $type);
+               $data['tag'] = self::createTagList($item);
+
+               if (!empty($item['coord']) || !empty($item['location'])) {
+                       $data['location'] = self::createLocation($item);
+               }
+
+               if (!empty($item['app'])) {
+                       $data['generator'] = ['type' => 'Application', 'name' => $item['app']];
+               }
+
+               $data = array_merge($data, self::createPermissionBlockForItem($item));
+
+               return $data;
+       }
+
+       /**
+        * Creates an announce object entry
+        *
+        * @param array $item
+        *
+        * @return string with announced object url
+        */
+       public static function createAnnounce($item)
+       {
+               $announce = api_share_as_retweet($item);
+               if (empty($announce['plink'])) {
+                       return self::createNote($item);
+               }
+
+               return $announce['plink'];
+       }
+
+       /**
+        * Transmits a contact suggestion to a given inbox
+        *
+        * @param integer $uid User ID
+        * @param string $inbox Target inbox
+        * @param integer $suggestion_id Suggestion ID
+        */
+       public static function sendContactSuggestion($uid, $inbox, $suggestion_id)
+       {
+               $owner = User::getOwnerDataById($uid);
+               $profile = APContact::getByURL($owner['url']);
+
+               $suggestion = DBA::selectFirst('fsuggest', ['url', 'note', 'created'], ['id' => $suggestion_id]);
+
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => System::baseUrl() . '/activity/' . System::createGUID(),
+                       'type' => 'Announce',
+                       'actor' => $owner['url'],
+                       'object' => $suggestion['url'],
+                       'content' => $suggestion['note'],
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => [ActivityPub::PUBLIC_COLLECTION],
+                       'cc' => []];
+
+               $signed = LDSignature::sign($data, $owner);
+
+               logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG);
+               HTTPSignature::transmit($signed, $inbox, $uid);
+       }
+
+       /**
+        * Transmits a profile deletion to a given inbox
+        *
+        * @param integer $uid User ID
+        * @param string $inbox Target inbox
+        */
+       public static function sendProfileDeletion($uid, $inbox)
+       {
+               $owner = User::getOwnerDataById($uid);
+               $profile = APContact::getByURL($owner['url']);
+
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => System::baseUrl() . '/activity/' . System::createGUID(),
+                       'type' => 'Delete',
+                       'actor' => $owner['url'],
+                       'object' => $owner['url'],
+                       'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => [ActivityPub::PUBLIC_COLLECTION],
+                       'cc' => []];
+
+               $signed = LDSignature::sign($data, $owner);
+
+               logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG);
+               HTTPSignature::transmit($signed, $inbox, $uid);
+       }
+
+       /**
+        * Transmits a profile change to a given inbox
+        *
+        * @param integer $uid User ID
+        * @param string $inbox Target inbox
+        */
+       public static function sendProfileUpdate($uid, $inbox)
+       {
+               $owner = User::getOwnerDataById($uid);
+               $profile = APContact::getByURL($owner['url']);
+
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => System::baseUrl() . '/activity/' . System::createGUID(),
+                       'type' => 'Update',
+                       'actor' => $owner['url'],
+                       'object' => self::getProfile($uid),
+                       'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => [$profile['followers']],
+                       'cc' => []];
+
+               $signed = LDSignature::sign($data, $owner);
+
+               logger('Deliver profile update for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG);
+               HTTPSignature::transmit($signed, $inbox, $uid);
+       }
+
+       /**
+        * Transmits a given activity to a target
+        *
+        * @param array $activity
+        * @param string $target Target profile
+        * @param integer $uid User ID
+        */
+       public static function sendActivity($activity, $target, $uid)
+       {
+               $profile = APContact::getByURL($target);
+
+               $owner = User::getOwnerDataById($uid);
+
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => System::baseUrl() . '/activity/' . System::createGUID(),
+                       'type' => $activity,
+                       'actor' => $owner['url'],
+                       'object' => $profile['url'],
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => $profile['url']];
+
+               logger('Sending activity ' . $activity . ' to ' . $target . ' for user ' . $uid, LOGGER_DEBUG);
+
+               $signed = LDSignature::sign($data, $owner);
+               HTTPSignature::transmit($signed, $profile['inbox'], $uid);
+       }
+
+       /**
+        * Transmit a message that the contact request had been accepted
+        *
+        * @param string $target Target profile
+        * @param $id
+        * @param integer $uid User ID
+        */
+       public static function sendContactAccept($target, $id, $uid)
+       {
+               $profile = APContact::getByURL($target);
+
+               $owner = User::getOwnerDataById($uid);
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => System::baseUrl() . '/activity/' . System::createGUID(),
+                       'type' => 'Accept',
+                       'actor' => $owner['url'],
+                       'object' => ['id' => $id, 'type' => 'Follow',
+                               'actor' => $profile['url'],
+                               'object' => $owner['url']],
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => $profile['url']];
+
+               logger('Sending accept to ' . $target . ' for user ' . $uid . ' with id ' . $id, LOGGER_DEBUG);
+
+               $signed = LDSignature::sign($data, $owner);
+               HTTPSignature::transmit($signed, $profile['inbox'], $uid);
+       }
+
+       /**
+        * Reject a contact request or terminates the contact relation
+        *
+        * @param string $target Target profile
+        * @param $id
+        * @param integer $uid User ID
+        */
+       public static function sendContactReject($target, $id, $uid)
+       {
+               $profile = APContact::getByURL($target);
+
+               $owner = User::getOwnerDataById($uid);
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => System::baseUrl() . '/activity/' . System::createGUID(),
+                       'type' => 'Reject',
+                       'actor' => $owner['url'],
+                       'object' => ['id' => $id, 'type' => 'Follow',
+                               'actor' => $profile['url'],
+                               'object' => $owner['url']],
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => $profile['url']];
+
+               logger('Sending reject to ' . $target . ' for user ' . $uid . ' with id ' . $id, LOGGER_DEBUG);
+
+               $signed = LDSignature::sign($data, $owner);
+               HTTPSignature::transmit($signed, $profile['inbox'], $uid);
+       }
+
+       /**
+        * Transmits a message that we don't want to follow this contact anymore
+        *
+        * @param string $target Target profile
+        * @param integer $uid User ID
+        */
+       public static function sendContactUndo($target, $uid)
+       {
+               $profile = APContact::getByURL($target);
+
+               $id = System::baseUrl() . '/activity/' . System::createGUID();
+
+               $owner = User::getOwnerDataById($uid);
+               $data = ['@context' => 'https://www.w3.org/ns/activitystreams',
+                       'id' => $id,
+                       'type' => 'Undo',
+                       'actor' => $owner['url'],
+                       'object' => ['id' => $id, 'type' => 'Follow',
+                               'actor' => $owner['url'],
+                               'object' => $profile['url']],
+                       'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()],
+                       'to' => $profile['url']];
+
+               logger('Sending undo to ' . $target . ' for user ' . $uid . ' with id ' . $id, LOGGER_DEBUG);
+
+               $signed = LDSignature::sign($data, $owner);
+               HTTPSignature::transmit($signed, $profile['inbox'], $uid);
+       }
+}
index 1ab4d8f9e4959592cf887e9f09f651989de53455..f92d1401dfe49f7c5365217f35a1fa1cabfd507d 100644 (file)
@@ -1170,10 +1170,10 @@ class DFRN
 
                // At first try the Diaspora transport layer
                if (!$dissolve && !$legacy_transport) {
-                       $ret = self::transmit($owner, $contact, $atom);
-                       if ($ret >= 200) {
-                               logger('Delivery via Diaspora transport layer was successful with status ' . $ret);
-                               return $ret;
+                       $curlResult = self::transmit($owner, $contact, $atom);
+                       if ($curlResult >= 200) {
+                               logger('Delivery via Diaspora transport layer was successful with status ' . $curlResult);
+                               return $curlResult;
                        }
                }
 
@@ -1211,16 +1211,16 @@ class DFRN
 
                logger('dfrn_deliver: ' . $url);
 
-               $ret = Network::curl($url);
+               $curlResult = Network::curl($url);
 
-               if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+               if ($curlResult->isTimeout()) {
                        Contact::markForArchival($contact);
                        return -2; // timed out
                }
 
-               $xml = $ret['body'];
+               $xml = $curlResult->getBody();
 
-               $curl_stat = $a->get_curl_code();
+               $curl_stat = $curlResult->getReturnCode();
                if (empty($curl_stat)) {
                        Contact::markForArchival($contact);
                        return -3; // timed out
@@ -1368,17 +1368,19 @@ class DFRN
 
                logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars, true), LOGGER_DATA);
 
-               $xml = Network::post($contact['notify'], $postvars);
+               $postResult = Network::post($contact['notify'], $postvars);
+
+               $xml = $postResult->getBody();
 
                logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA);
 
-               $curl_stat = $a->get_curl_code();
+               $curl_stat = $postResult->getReturnCode();
                if (empty($curl_stat) || empty($xml)) {
                        Contact::markForArchival($contact);
                        return -9; // timed out
                }
 
-               if (($curl_stat == 503) && stristr($a->get_curl_headers(), 'retry-after')) {
+               if (($curl_stat == 503) && stristr($postResult->getHeader(), 'retry-after')) {
                        Contact::markForArchival($contact);
                        return -10;
                }
@@ -1467,16 +1469,17 @@ class DFRN
 
                $content_type = ($public_batch ? "application/magic-envelope+xml" : "application/json");
 
-               $xml = Network::post($dest_url, $envelope, ["Content-Type: ".$content_type]);
+               $postResult = Network::post($dest_url, $envelope, ["Content-Type: ".$content_type]);
+               $xml = $postResult->getBody();
 
-               $curl_stat = $a->get_curl_code();
+               $curl_stat = $postResult->getReturnCode();
                if (empty($curl_stat) || empty($xml)) {
                        logger('Empty answer from ' . $contact['id'] . ' - ' . $dest_url);
                        Contact::markForArchival($contact);
                        return -9; // timed out
                }
 
-               if (($curl_stat == 503) && (stristr($a->get_curl_headers(), 'retry-after'))) {
+               if (($curl_stat == 503) && (stristr($postResult->getHeader(), 'retry-after'))) {
                        Contact::markForArchival($contact);
                        return -10;
                }
@@ -2349,6 +2352,12 @@ class DFRN
                                if (Item::exists($condition)) {
                                        return false;
                                }
+
+                               // The owner of an activity must be the author
+                               $item["owner-name"] = $item["author-name"];
+                               $item["owner-link"] = $item["author-link"];
+                               $item["owner-avatar"] = $item["author-avatar"];
+                               $item["owner-id"] = $item["author-id"];
                        } else {
                                $is_like = false;
                        }
@@ -2490,7 +2499,7 @@ class DFRN
 
                /// @todo Do we really need this check for HTML elements? (It was copied from the old function)
                if ((strpos($item['body'], '<') !== false) && (strpos($item['body'], '>') !== false)) {
-                       $base_url = get_app()->get_baseurl();
+                       $base_url = get_app()->getBaseURL();
                        $item['body'] = reltoabs($item['body'], $base_url);
 
                        $item['body'] = html2bb_video($item['body']);
index 27cfdccd853af83b89d026ddaf6fb5e741e25605..eb52c05037d1f6db0c1d897f01105dc248d2a061 100644 (file)
@@ -1592,17 +1592,13 @@ class Diaspora
                if (DBA::isResult($item)) {
                        return $item["uri"];
                } elseif (!$onlyfound) {
-                       $contact = Contact::getDetailsByAddr($author, 0);
-                       if (!empty($contact['network'])) {
-                               $prefix = 'urn:X-' . $contact['network'] . ':';
-                       } else {
-                               // This fallback should happen most unlikely
-                               $prefix = 'urn:X-dspr:';
-                       }
+                       $person = self::personByHandle($author);
 
-                       $author_parts = explode('@', $author);
+                       $parts = parse_url($person['url']);
+                       unset($parts['path']);
+                       $host_url = Network::unparseURL($parts);
 
-                       return $prefix . $author_parts[1] . ':' . $author_parts[0] . ':'. $guid;
+                       return $host_url . '/objects/' . $guid;
                }
 
                return "";
@@ -1973,11 +1969,8 @@ class Diaspora
                $datarray["contact-id"] = $author_contact["cid"];
                $datarray["network"]  = $author_contact["network"];
 
-               $datarray["author-link"] = $person["url"];
-               $datarray["author-id"] = Contact::getIdForURL($person["url"], 0);
-
-               $datarray["owner-link"] = $contact["url"];
-               $datarray["owner-id"] = Contact::getIdForURL($contact["url"], 0);
+               $datarray["owner-link"] = $datarray["author-link"] = $person["url"];
+               $datarray["owner-id"] = $datarray["author-id"] = Contact::getIdForURL($person["url"], 0);
 
                $datarray["guid"] = $guid;
                $datarray["uri"] = self::getUriFromGuid($author, $guid);
@@ -3086,8 +3079,8 @@ class Diaspora
                        if (!intval(Config::get("system", "diaspora_test"))) {
                                $content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json");
 
-                               Network::post($dest_url."/", $envelope, ["Content-Type: ".$content_type]);
-                               $return_code = $a->get_curl_code();
+                               $postResult = Network::post($dest_url."/", $envelope, ["Content-Type: ".$content_type]);
+                               $return_code = $postResult->getReturnCode();
                        } else {
                                logger("test_mode");
                                return 200;
@@ -3096,7 +3089,7 @@ class Diaspora
 
                logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code);
 
-               if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
+               if (!$return_code || (($return_code == 503) && (stristr($postResult->getHeader(), "retry-after")))) {
                        if (!$no_queue && !empty($contact['contact-type']) && ($contact['contact-type'] != Contact::ACCOUNT_TYPE_RELAY)) {
                                logger("queue message");
                                // queue message for redelivery
@@ -3204,7 +3197,7 @@ class Diaspora
                $author = self::myHandle($owner);
 
                $message = ["author" => $author,
-                               "guid" => System::createGUID(32),
+                               "guid" => System::createUUID(),
                                "parent_type" => "Post",
                                "parent_guid" => $item["guid"]];
 
index 0709a9550ea23b44c20468930c1d30369f1b65ea..39b272a42210bda09c4339ecafba228be96324ba 100644 (file)
@@ -430,7 +430,7 @@ class Feed {
                                // Distributed items should have a well formatted URI.
                                // Additionally we have to avoid conflicts with identical URI between imported feeds and these items.
                                if ($notify) {
-                                       $item['guid'] = Item::guidFromUri($orig_plink, $a->get_hostname());
+                                       $item['guid'] = Item::guidFromUri($orig_plink, $a->getHostName());
                                        unset($item['uri']);
                                        unset($item['parent-uri']);
 
index ece265c99b391dff3ba23c1c2f545cbebe281b58..f589d3827f0bbc5ad85cf699df7cdb5552fa29f5 100644 (file)
@@ -736,21 +736,21 @@ class OStatus
 
                self::$conv_list[$conversation] = true;
 
-               $conversation_data = Network::curl($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
+               $curlResult = Network::curl($conversation, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
 
-               if (!$conversation_data['success']) {
+               if (!$curlResult->isSuccess()) {
                        return;
                }
 
                $xml = '';
 
-               if (stristr($conversation_data['header'], 'Content-Type: application/atom+xml')) {
-                       $xml = $conversation_data['body'];
+               if (stristr($curlResult->getHeader(), 'Content-Type: application/atom+xml')) {
+                       $xml = $curlResult->getBody();
                }
 
                if ($xml == '') {
                        $doc = new DOMDocument();
-                       if (!@$doc->loadHTML($conversation_data['body'])) {
+                       if (!@$doc->loadHTML($curlResult->getBody())) {
                                return;
                        }
                        $xpath = new DOMXPath($doc);
@@ -767,8 +767,8 @@ class OStatus
                                if ($file != '') {
                                        $conversation_atom = Network::curl($attribute['href']);
 
-                                       if ($conversation_atom['success']) {
-                                               $xml = $conversation_atom['body'];
+                                       if ($conversation_atom->isSuccess()) {
+                                               $xml = $conversation_atom->getBody();
                                        }
                                }
                        }
@@ -880,15 +880,15 @@ class OStatus
                        return;
                }
 
-               $self_data = Network::curl($self);
+               $curlResult = Network::curl($self);
 
-               if (!$self_data['success']) {
+               if (!$curlResult->isSuccess()) {
                        return;
                }
 
                // We reformat the XML to make it better readable
                $doc = new DOMDocument();
-               $doc->loadXML($self_data['body']);
+               $doc->loadXML($curlResult->getBody());
                $doc->preserveWhiteSpace = false;
                $doc->formatOutput = true;
                $xml = $doc->saveXML();
@@ -925,22 +925,22 @@ class OStatus
                }
 
                $stored = false;
-               $related_data = Network::curl($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
+               $curlResult = Network::curl($related, false, $redirects, ['accept_content' => 'application/atom+xml, text/html']);
 
-               if (!$related_data['success']) {
+               if (!$curlResult->isSuccess()) {
                        return;
                }
 
                $xml = '';
 
-               if (stristr($related_data['header'], 'Content-Type: application/atom+xml')) {
-                       logger('Directly fetched XML for URI '.$related_uri, LOGGER_DEBUG);
-                       $xml = $related_data['body'];
+               if (stristr($curlResult->getHeader(), 'Content-Type: application/atom+xml')) {
+                       logger('Directly fetched XML for URI ' . $related_uri, LOGGER_DEBUG);
+                       $xml = $curlResult->getBody();
                }
 
                if ($xml == '') {
                        $doc = new DOMDocument();
-                       if (!@$doc->loadHTML($related_data['body'])) {
+                       if (!@$doc->loadHTML($curlResult->getBody())) {
                                return;
                        }
                        $xpath = new DOMXPath($doc);
@@ -956,11 +956,11 @@ class OStatus
                                        }
                                }
                                if ($atom_file != '') {
-                                       $related_atom = Network::curl($atom_file);
+                                       $curlResult = Network::curl($atom_file);
 
-                                       if ($related_atom['success']) {
-                                               logger('Fetched XML for URI '.$related_uri, LOGGER_DEBUG);
-                                               $xml = $related_atom['body'];
+                                       if ($curlResult->isSuccess()) {
+                                               logger('Fetched XML for URI ' . $related_uri, LOGGER_DEBUG);
+                                               $xml = $curlResult->getBody();
                                        }
                                }
                        }
@@ -968,22 +968,22 @@ class OStatus
 
                // Workaround for older GNU Social servers
                if (($xml == '') && strstr($related, '/notice/')) {
-                       $related_atom = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related).'.atom');
+                       $curlResult = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related).'.atom');
 
-                       if ($related_atom['success']) {
-                               logger('GNU Social workaround to fetch XML for URI '.$related_uri, LOGGER_DEBUG);
-                               $xml = $related_atom['body'];
+                       if ($curlResult->isSuccess()) {
+                               logger('GNU Social workaround to fetch XML for URI ' . $related_uri, LOGGER_DEBUG);
+                               $xml = $curlResult->getBody();
                        }
                }
 
                // Even more worse workaround for GNU Social ;-)
                if ($xml == '') {
                        $related_guess = OStatus::convertHref($related_uri);
-                       $related_atom = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom');
+                       $curlResult = Network::curl(str_replace('/notice/', '/api/statuses/show/', $related_guess).'.atom');
 
-                       if ($related_atom['success']) {
-                               logger('GNU Social workaround 2 to fetch XML for URI '.$related_uri, LOGGER_DEBUG);
-                               $xml = $related_atom['body'];
+                       if ($curlResult->isSuccess()) {
+                               logger('GNU Social workaround 2 to fetch XML for URI ' . $related_uri, LOGGER_DEBUG);
+                               $xml = $curlResult->getBody();
                        }
                }
 
@@ -1830,7 +1830,7 @@ class OStatus
                }
 
                $item["uri"] = $item['parent-uri'] = $item['thr-parent']
-                               = 'tag:'.get_app()->get_hostname().
+                               = 'tag:'.get_app()->getHostName().
                                ','.date('Y-m-d').':'.$action.':'.$owner['uid'].
                                ':person:'.$connect_id.':'.$item['created'];
 
@@ -2004,8 +2004,7 @@ class OStatus
                }
 
                if (intval($item["parent"]) > 0) {
-                       $conversation_href = System::baseUrl()."/display/".$owner["nick"]."/".$item["parent"];
-                       $conversation_uri = $conversation_href;
+                       $conversation_href = $conversation_uri = str_replace('/objects/', '/context/', $item['parent-uri']);
 
                        if (isset($parent_item)) {
                                $conversation = DBA::selectFirst('conversation', ['conversation-uri', 'conversation-href'], ['item-uri' => $parent_item]);
index 2939f69e55c2cbe42727cd76e7b41952df811bda..0e4d58d1c19348f67aa2af88510bcd2aa265c908 100644 (file)
@@ -86,13 +86,14 @@ class PortableContact
 
                logger('load: ' . $url, LOGGER_DEBUG);
 
-               $s = Network::fetchUrl($url);
+               $fetchresult = Network::fetchUrlFull($url);
+               $s = $fetchresult->getBody();
 
                logger('load: returns ' . $s, LOGGER_DATA);
 
-               logger('load: return code: ' . $a->get_curl_code(), LOGGER_DEBUG);
+               logger('load: return code: ' . $fetchresult->getReturnCode(), LOGGER_DEBUG);
 
-               if (($a->get_curl_code() > 299) || (! $s)) {
+               if (($fetchresult->getReturnCode() > 299) || (! $s)) {
                        return;
                }
 
@@ -290,8 +291,8 @@ class PortableContact
                }
 
                // Fetch the host-meta to check if this really is a server
-               $serverret = Network::curl($server_url."/.well-known/host-meta");
-               if (!$serverret["success"]) {
+               $curlResult = Network::curl($server_url."/.well-known/host-meta");
+               if (!$curlResult->isSuccess()) {
                        return "";
                }
 
@@ -333,7 +334,7 @@ class PortableContact
                        $server_url = normalise_link(self::detectServer($profile));
                }
 
-               if (!in_array($gcontacts[0]["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::FEED, Protocol::OSTATUS, ""])) {
+               if (!in_array($gcontacts[0]["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::FEED, Protocol::OSTATUS, ""])) {
                        logger("Profile ".$profile.": Network type ".$gcontacts[0]["network"]." can't be checked", LOGGER_DEBUG);
                        return false;
                }
@@ -370,10 +371,10 @@ class PortableContact
                        $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", DBA::escape(normalise_link($server_url)));
 
                        if ($server) {
-                               $noscraperet = Network::curl($server[0]["noscrape"]."/".$gcontacts[0]["nick"]);
+                               $curlResult = Network::curl($server[0]["noscrape"]."/".$gcontacts[0]["nick"]);
 
-                               if ($noscraperet["success"] && ($noscraperet["body"] != "")) {
-                                       $noscrape = json_decode($noscraperet["body"], true);
+                               if ($curlResult->isSuccess() && ($curlResult->getBody() != "")) {
+                                       $noscrape = json_decode($curlResult->getBody(), true);
 
                                        if (is_array($noscrape)) {
                                                $contact["network"] = $server[0]["network"];
@@ -484,9 +485,9 @@ class PortableContact
 
                GContact::update($contact);
 
-               $feedret = Network::curl($data["poll"]);
+               $curlResult = Network::curl($data["poll"]);
 
-               if (!$feedret["success"]) {
+               if (!$curlResult->isSuccess()) {
                        $fields = ['last_failure' => DateTimeFormat::utcNow()];
                        DBA::update('gcontact', $fields, ['nurl' => normalise_link($profile)]);
 
@@ -496,7 +497,7 @@ class PortableContact
 
                $doc = new DOMDocument();
                /// @TODO Avoid error supression here
-               @$doc->loadXML($feedret["body"]);
+               @$doc->loadXML($curlResult->getBody());
 
                $xpath = new DOMXPath($doc);
                $xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
@@ -645,12 +646,12 @@ class PortableContact
         */
        private static function fetchNodeinfo($server_url)
        {
-               $serverret = Network::curl($server_url."/.well-known/nodeinfo");
-               if (!$serverret["success"]) {
+               $curlResult = Network::curl($server_url."/.well-known/nodeinfo");
+               if (!$curlResult->isSuccess()) {
                        return false;
                }
 
-               $nodeinfo = json_decode($serverret['body'], true);
+               $nodeinfo = json_decode($curlResult->getBody(), true);
 
                if (!is_array($nodeinfo) || !isset($nodeinfo['links'])) {
                        return false;
@@ -698,13 +699,13 @@ class PortableContact
         */
        private static function parseNodeinfo1($nodeinfo_url)
        {
-               $serverret = Network::curl($nodeinfo_url);
+               $curlResult = Network::curl($nodeinfo_url);
 
-               if (!$serverret["success"]) {
+               if (!$curlResult->isSuccess()) {
                        return false;
                }
 
-               $nodeinfo = json_decode($serverret['body'], true);
+               $nodeinfo = json_decode($curlResult->getBody(), true);
 
                if (!is_array($nodeinfo)) {
                        return false;
@@ -782,12 +783,12 @@ class PortableContact
         */
        private static function parseNodeinfo2($nodeinfo_url)
        {
-               $serverret = Network::curl($nodeinfo_url);
-               if (!$serverret["success"]) {
+               $curlResult = Network::curl($nodeinfo_url);
+               if (!$curlResult->isSuccess()) {
                        return false;
                }
 
-               $nodeinfo = json_decode($serverret['body'], true);
+               $nodeinfo = json_decode($curlResult->getBody(), true);
 
                if (!is_array($nodeinfo)) {
                        return false;
@@ -997,38 +998,38 @@ class PortableContact
                $server_url = str_replace("http://", "https://", $server_url);
 
                // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
-               $serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
+               $curlResult = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
 
                // Quit if there is a timeout.
                // But we want to make sure to only quit if we are mostly sure that this server url fits.
                if (DBA::isResult($gserver) && ($orig_server_url == $server_url) &&
-                       (!empty($serverret["errno"]) && ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT))) {
+                       ($curlResult->isTimeout())) {
                        logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
                        DBA::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]);
                        return false;
                }
 
                // Maybe the page is unencrypted only?
-               $xmlobj = @simplexml_load_string($serverret["body"], 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
-               if (!$serverret["success"] || ($serverret["body"] == "") || empty($xmlobj) || !is_object($xmlobj)) {
+               $xmlobj = @simplexml_load_string($curlResult->getBody(), 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
+               if (!$curlResult->isSuccess() || ($curlResult->getBody() == "") || empty($xmlobj) || !is_object($xmlobj)) {
                        $server_url = str_replace("https://", "http://", $server_url);
 
                        // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital
-                       $serverret = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
+                       $curlResult = Network::curl($server_url."/.well-known/host-meta", false, $redirects, ['timeout' => 20]);
 
                        // Quit if there is a timeout
-                       if (!empty($serverret["errno"]) && ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
-                               logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
+                       if ($curlResult->isTimeout()) {
+                               logger("Connection to server " . $server_url . " timed out.", LOGGER_DEBUG);
                                DBA::update('gserver', ['last_failure' => DateTimeFormat::utcNow()], ['nurl' => normalise_link($server_url)]);
                                return false;
                        }
 
-                       $xmlobj = @simplexml_load_string($serverret["body"], 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
+                       $xmlobj = @simplexml_load_string($curlResult->getBody(), 'SimpleXMLElement', 0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
                }
 
-               if (!$serverret["success"] || ($serverret["body"] == "") || empty($xmlobj) || !is_object($xmlobj)) {
+               if (!$curlResult->isSuccess() || ($curlResult->getBody() == "") || empty($xmlobj) || !is_object($xmlobj)) {
                        // Workaround for bad configured servers (known nginx problem)
-                       if (!empty($serverret["debug"]) && !in_array($serverret["debug"]["http_code"], ["403", "404"])) {
+                       if (!empty($curlResult->getInfo()) && !in_array($curlResult->getInfo()["http_code"], ["403", "404"])) {
                                $failure = true;
                        }
 
@@ -1051,10 +1052,10 @@ class PortableContact
 
                // Look for poco
                if (!$failure) {
-                       $serverret = Network::curl($server_url."/poco");
+                       $curlResult = Network::curl($server_url."/poco");
 
-                       if ($serverret["success"]) {
-                               $data = json_decode($serverret["body"], true);
+                       if ($curlResult->isSuccess()) {
+                               $data = json_decode($curlResult->getBody(), true);
 
                                if (isset($data['totalResults'])) {
                                        $registered_users = $data['totalResults'];
@@ -1083,12 +1084,12 @@ class PortableContact
 
                if (!$failure) {
                        // Test for Diaspora, Hubzilla, Mastodon or older Friendica servers
-                       $serverret = Network::curl($server_url);
+                       $curlResult = Network::curl($server_url);
 
-                       if (!$serverret["success"] || ($serverret["body"] == "")) {
+                       if (!$curlResult->isSuccess() || ($curlResult->getBody() == "")) {
                                $failure = true;
                        } else {
-                               $server = self::detectServerType($serverret["body"]);
+                               $server = self::detectServerType($curlResult->getBody());
 
                                if (!empty($server)) {
                                        $platform = $server['platform'];
@@ -1097,7 +1098,7 @@ class PortableContact
                                        $site_name = $server['site_name'];
                                }
 
-                               $lines = explode("\n", $serverret["header"]);
+                               $lines = explode("\n", $curlResult->getHeader());
 
                                if (count($lines)) {
                                        foreach ($lines as $line) {
@@ -1125,35 +1126,35 @@ class PortableContact
                        // Test for Statusnet
                        // Will also return data for Friendica and GNU Social - but it will be overwritten later
                        // The "not implemented" is a special treatment for really, really old Friendica versions
-                       $serverret = Network::curl($server_url."/api/statusnet/version.json");
+                       $curlResult = Network::curl($server_url."/api/statusnet/version.json");
 
-                       if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') &&
-                               ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) {
+                       if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
+                               ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
                                $platform = "StatusNet";
                                // Remove junk that some GNU Social servers return
-                               $version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
+                               $version = str_replace(chr(239).chr(187).chr(191), "", $curlResult->getBody());
                                $version = trim($version, '"');
                                $network = Protocol::OSTATUS;
                        }
 
                        // Test for GNU Social
-                       $serverret = Network::curl($server_url."/api/gnusocial/version.json");
+                       $curlResult = Network::curl($server_url."/api/gnusocial/version.json");
 
-                       if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') &&
-                               ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) {
+                       if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
+                               ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
                                $platform = "GNU Social";
                                // Remove junk that some GNU Social servers return
-                               $version = str_replace(chr(239) . chr(187) . chr(191), "", $serverret["body"]);
+                               $version = str_replace(chr(239) . chr(187) . chr(191), "", $curlResult->getBody());
                                $version = trim($version, '"');
                                $network = Protocol::OSTATUS;
                        }
 
                        // Test for Mastodon
                        $orig_version = $version;
-                       $serverret = Network::curl($server_url . "/api/v1/instance");
+                       $curlResult = Network::curl($server_url . "/api/v1/instance");
 
-                       if ($serverret["success"] && ($serverret["body"] != '')) {
-                               $data = json_decode($serverret["body"], true);
+                       if ($curlResult->isSuccess() && ($curlResult->getBody() != '')) {
+                               $data = json_decode($curlResult->getBody(), true);
 
                                if (isset($data['version'])) {
                                        $platform = "Mastodon";
@@ -1176,10 +1177,10 @@ class PortableContact
 
                if (!$failure) {
                        // Test for Hubzilla and Red
-                       $serverret = Network::curl($server_url . "/siteinfo.json");
+                       $curlResult = Network::curl($server_url . "/siteinfo.json");
 
-                       if ($serverret["success"]) {
-                               $data = json_decode($serverret["body"], true);
+                       if ($curlResult->isSuccess()) {
+                               $data = json_decode($curlResult->getBody(), true);
 
                                if (isset($data['url'])) {
                                        $platform = $data['platform'];
@@ -1213,10 +1214,10 @@ class PortableContact
                                }
                        } else {
                                // Test for Hubzilla, Redmatrix or Friendica
-                               $serverret = Network::curl($server_url."/api/statusnet/config.json");
+                               $curlResult = Network::curl($server_url."/api/statusnet/config.json");
 
-                               if ($serverret["success"]) {
-                                       $data = json_decode($serverret["body"], true);
+                               if ($curlResult->isSuccess()) {
+                                       $data = json_decode($curlResult->getBody(), true);
 
                                        if (isset($data['site']['server'])) {
                                                if (isset($data['site']['platform'])) {
@@ -1286,10 +1287,10 @@ class PortableContact
 
                // Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix
                if (!$failure) {
-                       $serverret = Network::curl($server_url . "/statistics.json");
+                       $curlResult = Network::curl($server_url . "/statistics.json");
 
-                       if ($serverret["success"]) {
-                               $data = json_decode($serverret["body"], true);
+                       if ($curlResult->isSuccess()) {
+                               $data = json_decode($curlResult->getBody(), true);
 
                                if (isset($data['version'])) {
                                        $version = $data['version'];
@@ -1350,14 +1351,14 @@ class PortableContact
                // Check for noscrape
                // Friendica servers could be detected as OStatus servers
                if (!$failure && in_array($network, [Protocol::DFRN, Protocol::OSTATUS])) {
-                       $serverret = Network::curl($server_url . "/friendica/json");
+                       $curlResult = Network::curl($server_url . "/friendica/json");
 
-                       if (!$serverret["success"]) {
-                               $serverret = Network::curl($server_url . "/friendika/json");
+                       if (!$curlResult->isSuccess()) {
+                               $curlResult = Network::curl($server_url . "/friendika/json");
                        }
 
-                       if ($serverret["success"]) {
-                               $data = json_decode($serverret["body"], true);
+                       if ($curlResult->isSuccess()) {
+                               $data = json_decode($curlResult->getBody(), true);
 
                                if (isset($data['version'])) {
                                        $network = Protocol::DFRN;
@@ -1442,13 +1443,13 @@ class PortableContact
        {
                logger("Discover relay data for server " . $server_url, LOGGER_DEBUG);
 
-               $serverret = Network::curl($server_url . "/.well-known/x-social-relay");
+               $curlResult = Network::curl($server_url . "/.well-known/x-social-relay");
 
-               if (!$serverret["success"]) {
+               if (!$curlResult->isSuccess()) {
                        return;
                }
 
-               $data = json_decode($serverret['body'], true);
+               $data = json_decode($curlResult->getBody(), true);
 
                if (!is_array($data)) {
                        return;
@@ -1538,13 +1539,13 @@ class PortableContact
         */
        private static function fetchServerlist($poco)
        {
-               $serverret = Network::curl($poco . "/@server");
+               $curlResult = Network::curl($poco . "/@server");
 
-               if (!$serverret["success"]) {
+               if (!$curlResult->isSuccess()) {
                        return;
                }
 
-               $serverlist = json_decode($serverret['body'], true);
+               $serverlist = json_decode($curlResult->getBody(), true);
 
                if (!is_array($serverlist)) {
                        return;
@@ -1575,10 +1576,10 @@ class PortableContact
                }
 
                // Discover Friendica, Hubzilla and Diaspora servers
-               $serverdata = Network::fetchUrl("http://the-federation.info/pods.json");
+               $curlResult = Network::fetchUrl("http://the-federation.info/pods.json");
 
-               if (!empty($serverdata)) {
-                       $servers = json_decode($serverdata, true);
+               if (!empty($curlResult)) {
+                       $servers = json_decode($curlResult, true);
 
                        if (!empty($servers['pods'])) {
                                foreach ($servers['pods'] as $server) {
@@ -1594,10 +1595,10 @@ class PortableContact
                        if (!empty($accesstoken)) {
                                $api = 'https://instances.social/api/1.0/instances/list?count=0';
                                $header = ['Authorization: Bearer '.$accesstoken];
-                               $serverdata = Network::curl($api, false, $redirects, ['headers' => $header]);
+                               $curlResult = Network::curl($api, false, $redirects, ['headers' => $header]);
 
-                               if ($serverdata['success']) {
-                                       $servers = json_decode($serverdata['body'], true);
+                               if ($curlResult->isSuccess()) {
+                                       $servers = json_decode($curlResult->getBody(), true);
 
                                        foreach ($servers['instances'] as $server) {
                                                $url = (is_null($server['https_score']) ? 'http' : 'https') . '://' . $server['name'];
@@ -1613,9 +1614,9 @@ class PortableContact
                //if (!Config::get('system','ostatus_disabled')) {
                //      $serverdata = "http://gstools.org/api/get_open_instances/";
 
-               //      $result = Network::curl($serverdata);
-               //      if ($result["success"]) {
-               //              $servers = json_decode($result["body"], true);
+               //      $curlResult = Network::curl($serverdata);
+               //      if ($curlResult->isSuccess()) {
+               //              $servers = json_decode($result->getBody(), true);
 
                //              foreach($servers['data'] as $server)
                //                      self::checkServer($server['instance_address']);
@@ -1643,10 +1644,10 @@ class PortableContact
 
                logger("Fetch all users from the server " . $server["url"], LOGGER_DEBUG);
 
-               $retdata = Network::curl($url);
+               $curlResult = Network::curl($url);
 
-               if ($retdata["success"] && !empty($retdata["body"])) {
-                       $data = json_decode($retdata["body"], true);
+               if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
+                       $data = json_decode($curlResult->getBody(), true);
 
                        if (!empty($data)) {
                                self::discoverServer($data, 2);
@@ -1666,11 +1667,11 @@ class PortableContact
 
                                $success = false;
 
-                               $retdata = Network::curl($url);
+                               $curlResult = Network::curl($url);
 
-                               if ($retdata["success"] && !empty($retdata["body"])) {
+                               if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
                                        logger("Fetch all global contacts from the server " . $server["nurl"], LOGGER_DEBUG);
-                                       $data = json_decode($retdata["body"], true);
+                                       $data = json_decode($curlResult->getBody(), true);
 
                                        if (!empty($data)) {
                                                $success = self::discoverServer($data);
@@ -1766,10 +1767,10 @@ class PortableContact
                                // Fetch all contacts from a given user from the other server
                                $url = $server['poco'] . '/' . $username . '/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation';
 
-                               $retdata = Network::curl($url);
+                               $curlResult = Network::curl($url);
 
-                               if (!empty($retdata['success'])) {
-                                       $data = json_decode($retdata["body"], true);
+                               if ($curlResult->isSuccess()) {
+                                       $data = json_decode($curlResult["body"], true);
 
                                        if (!empty($data)) {
                                                self::discoverServer($data, 3);
index f30488ce140eeef304b7dd99eb8258707c11c014..e3407844a66590b2e2e82c35f177c4285779b5ab 100644 (file)
@@ -133,13 +133,12 @@ class Salmon
                $salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
 
                // slap them
-               Network::post($url, $salmon, [
+               $postResult = Network::post($url, $salmon, [
                        'Content-type: application/magic-envelope+xml',
                        'Content-length: ' . strlen($salmon)
                ]);
 
-               $a = get_app();
-               $return_code = $a->get_curl_code();
+               $return_code = $postResult->getReturnCode();
 
                // check for success, e.g. 2xx
 
@@ -159,11 +158,11 @@ class Salmon
                        $salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
 
                        // slap them
-                       Network::post($url, $salmon, [
+                       $postResult = Network::post($url, $salmon, [
                                'Content-type: application/magic-envelope+xml',
                                'Content-length: ' . strlen($salmon)
                        ]);
-                       $return_code = $a->get_curl_code();
+                       $return_code = $postResult->getReturnCode();
                }
 
                if ($return_code > 299) {
@@ -182,10 +181,10 @@ class Salmon
                        $salmon = XML::fromArray($xmldata, $xml, false, $namespaces);
 
                        // slap them
-                       Network::post($url, $salmon, [
+                       $postResult = Network::post($url, $salmon, [
                                'Content-type: application/magic-envelope+xml',
                                'Content-length: ' . strlen($salmon)]);
-                       $return_code = $a->get_curl_code();
+                       $return_code = $postResult->getReturnCode();
                }
 
                logger('slapper for '.$url.' returned ' . $return_code);
@@ -194,7 +193,7 @@ class Salmon
                        return -1;
                }
 
-               if (($return_code == 503) && (stristr($a->get_curl_headers(), 'retry-after'))) {
+               if (($return_code == 503) && (stristr($postResult->getHeader(), 'retry-after'))) {
                        return -1;
                }
 
index f4c6a8ed27623372428db861cf8a35634c3b51c0..2052aa9e87a6f5627948d99d18b6464dcb3af8a9 100644 (file)
@@ -38,8 +38,8 @@ class FriendicaSmarty extends Smarty
                $this->setConfigDir('view/smarty3/config/');
                $this->setCacheDir('view/smarty3/cache/');
 
-               $this->left_delimiter = $a->get_template_ldelim('smarty3');
-               $this->right_delimiter = $a->get_template_rdelim('smarty3');
+               $this->left_delimiter = $a->getTemplateLeftDelimiter('smarty3');
+               $this->right_delimiter = $a->getTemplateRightDelimiter('smarty3');
 
                // Don't report errors so verbosely
                $this->error_reporting = E_ALL & ~E_NOTICE;
index 92f3f56f85eac0abd4574d92dbb337a404e18638..8d38b336612e8ed736e2e32d9dfbec37f251c426 100644 (file)
@@ -141,7 +141,7 @@ class ExAuth
                $sUser = str_replace(['%20', '(a)'], [' ', '@'], $aCommand[1]);
 
                // Does the hostname match? So we try directly
-               if ($a->get_hostname() == $aCommand[2]) {
+               if ($a->getHostName() == $aCommand[2]) {
                        $this->writeLog(LOG_INFO, 'internal user check for ' . $sUser . '@' . $aCommand[2]);
                        $found = DBA::exists('user', ['nickname' => $sUser]);
                } else {
@@ -179,17 +179,17 @@ class ExAuth
 
                $url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user;
 
-               $data = Network::curl($url);
+               $curlResult = Network::curl($url);
 
-               if (!is_array($data)) {
+               if (!$curlResult->isSuccess()) {
                        return false;
                }
 
-               if ($data['return_code'] != '200') {
+               if ($curlResult->getReturnCode() != 200) {
                        return false;
                }
 
-               $json = @json_decode($data['body']);
+               $json = @json_decode($curlResult->getBody());
                if (!is_object($json)) {
                        return false;
                }
@@ -221,7 +221,7 @@ class ExAuth
                $sUser = str_replace(['%20', '(a)'], [' ', '@'], $aCommand[1]);
 
                // Does the hostname match? So we try directly
-               if ($a->get_hostname() == $aCommand[2]) {
+               if ($a->getHostName() == $aCommand[2]) {
                        $this->writeLog(LOG_INFO, 'internal auth for ' . $sUser . '@' . $aCommand[2]);
 
                        $aUser = DBA::selectFirst('user', ['uid', 'password', 'legacy_password'], ['nickname' => $sUser]);
index 911de4308e5f7eb0b371f6c277f48d88386232e8..503cbff0ade45b0af04c35d039380f28ff267cbc 100644 (file)
@@ -5,94 +5,64 @@
  */
 namespace Friendica\Util;
 
+use Friendica\BaseObject;
 use Friendica\Core\Config;
 use Friendica\Database\DBA;
+use Friendica\Model\User;
+use Friendica\Model\APContact;
+use Friendica\Protocol\ActivityPub;
 
 /**
  * @brief Implements HTTP Signatures per draft-cavage-http-signatures-07.
  *
  * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/Zotlabs/Web/HTTPSig.php
  *
+ * Other parts of the code for HTTP signing are taken from the Osada project.
+ * https://framagit.org/macgirvin/osada
+ *
  * @see https://tools.ietf.org/html/draft-cavage-http-signatures-07
  */
 
 class HTTPSignature
 {
+       // See draft-cavage-http-signatures-08
        /**
-        * @brief RFC5843
-        *
-        * Disabled until Friendica's ActivityPub implementation
-        * is ready.
+        * @brief Verifies a magic request
         *
-        * @see https://tools.ietf.org/html/rfc5843
+        * @param $key
         *
-        * @param string  $body The value to create the digest for
-        * @param boolean $set  (optional, default true)
-        *   If set send a Digest HTTP header
-        *
-        * @return string The generated digest of $body
+        * @return array with verification data
         */
-//     public static function generateDigest($body, $set = true)
-//     {
-//             $digest = base64_encode(hash('sha256', $body, true));
-//
-//             if($set) {
-//                     header('Digest: SHA-256=' . $digest);
-//             }
-//             return $digest;
-//     }
-
-       // See draft-cavage-http-signatures-08
-       public static function verify($data, $key = '')
+       public static function verifyMagic($key)
        {
-               $body      = $data;
                $headers   = null;
                $spoofable = false;
                $result = [
                        'signer'         => '',
                        'header_signed'  => false,
-                       'header_valid'   => false,
-                       'content_signed' => false,
-                       'content_valid'  => false
+                       'header_valid'   => false
                ];
 
                // Decide if $data arrived via controller submission or curl.
-               if (is_array($data) && $data['header']) {
-                       if (!$data['success']) {
-                               return $result;
-                       }
+               $headers = [];
+               $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']).' '.$_SERVER['REQUEST_URI'];
 
-                       $h = new HTTPHeaders($data['header']);
-                       $headers = $h->fetch();
-                       $body = $data['body'];
-               } else {
-                       $headers = [];
-                       $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']).' '.$_SERVER['REQUEST_URI'];
-
-                       foreach ($_SERVER as $k => $v) {
-                               if (strpos($k, 'HTTP_') === 0) {
-                                       $field = str_replace('_', '-', strtolower(substr($k, 5)));
-                                       $headers[$field] = $v;
-                               }
+               foreach ($_SERVER as $k => $v) {
+                       if (strpos($k, 'HTTP_') === 0) {
+                               $field = str_replace('_', '-', strtolower(substr($k, 5)));
+                               $headers[$field] = $v;
                        }
                }
 
                $sig_block = null;
 
-               if (array_key_exists('signature', $headers)) {
-                       $sig_block = self::parseSigheader($headers['signature']);
-               } elseif (array_key_exists('authorization', $headers)) {
-                       $sig_block = self::parseSigheader($headers['authorization']);
-               }
+               $sig_block = self::parseSigheader($headers['authorization']);
 
                if (!$sig_block) {
                        logger('no signature provided.');
                        return $result;
                }
 
-               // Warning: This log statement includes binary data
-               // logger('sig_block: ' . print_r($sig_block,true), LOGGER_DATA);
-
                $result['header_signed'] = true;
 
                $signed_headers = $sig_block['headers'];
@@ -112,13 +82,7 @@ class HTTPSignature
 
                $signed_data = rtrim($signed_data, "\n");
 
-               $algorithm = null;
-               if ($sig_block['algorithm'] === 'rsa-sha256') {
-                       $algorithm = 'sha256';
-               }
-               if ($sig_block['algorithm'] === 'rsa-sha512') {
-                       $algorithm = 'sha512';
-               }
+               $algorithm = 'sha512';
 
                if ($key && function_exists($key)) {
                        $result['signer'] = $sig_block['keyId'];
@@ -127,12 +91,6 @@ class HTTPSignature
 
                logger('Got keyID ' . $sig_block['keyId']);
 
-               // We don't use Activity Pub at the moment.
-//             if (!$key) {
-//                     $result['signer'] = $sig_block['keyId'];
-//                     $key = self::getActivitypubKey($sig_block['keyId']);
-//             }
-
                if (!$key) {
                        return $result;
                }
@@ -149,130 +107,39 @@ class HTTPSignature
                        $result['header_valid'] = true;
                }
 
-               if (in_array('digest', $signed_headers)) {
-                       $result['content_signed'] = true;
-                       $digest = explode('=', $headers['digest']);
-
-                       if ($digest[0] === 'SHA-256') {
-                               $hashalg = 'sha256';
-                       }
-                       if ($digest[0] === 'SHA-512') {
-                               $hashalg = 'sha512';
-                       }
-
-                       // The explode operation will have stripped the '=' padding, so compare against unpadded base64.
-                       if (rtrim(base64_encode(hash($hashalg, $body, true)), '=') === $digest[1]) {
-                               $result['content_valid'] = true;
-                       }
-               }
-
-               logger('Content_Valid: ' . $result['content_valid']);
-
                return $result;
        }
 
-       /**
-        * Fetch the public key for Activity Pub contact.
-        *
-        * @param string|int The identifier (contact addr or contact ID).
-        * @return string|boolean The public key or false on failure.
-        */
-       private static function getActivitypubKey($id)
-       {
-               if (strpos($id, 'acct:') === 0) {
-                       $contact = DBA::selectFirst('contact', ['pubkey'], ['uid' => 0, 'addr' => str_replace('acct:', '', $id)]);
-               } else {
-                       $contact = DBA::selectFirst('contact', ['pubkey'], ['id' => $id, 'network' => 'activitypub']);
-               }
-
-               if (DBA::isResult($contact)) {
-                       return $contact['pubkey'];
-               }
-
-               if(function_exists('as_fetch')) {
-                       $r = as_fetch($id);
-               }
-
-               if ($r) {
-                       $j = json_decode($r, true);
-
-                       if (array_key_exists('publicKey', $j) && array_key_exists('publicKeyPem', $j['publicKey'])) {
-                               if ((array_key_exists('id', $j['publicKey']) && $j['publicKey']['id'] !== $id) && $j['id'] !== $id) {
-                                       return false;
-                               }
-
-                               return $j['publicKey']['publicKeyPem'];
-                       }
-               }
-
-               return false;
-       }
-
        /**
         * @brief
         *
-        * @param string  $request
         * @param array   $head
         * @param string  $prvkey
         * @param string  $keyid (optional, default 'Key')
-        * @param boolean $send_headers (optional, default false)
-        *   If set send a HTTP header
-        * @param boolean $auth (optional, default false)
-        * @param string  $alg (optional, default 'sha256')
-        * @param string  $crypt_key (optional, default null)
-        * @param string  $crypt_algo (optional, default 'aes256ctr')
         *
         * @return array
         */
-       public static function createSig($request, $head, $prvkey, $keyid = 'Key', $send_headers = false, $auth = false, $alg = 'sha256', $crypt_key = null, $crypt_algo = 'aes256ctr')
+       public static function createSig($head, $prvkey, $keyid = 'Key')
        {
                $return_headers = [];
 
-               if ($alg === 'sha256') {
-                       $algorithm = 'rsa-sha256';
-               }
-
-               if ($alg === 'sha512') {
-                       $algorithm = 'rsa-sha512';
-               }
+               $alg = 'sha512';
+               $algorithm = 'rsa-sha512';
 
-               $x = self::sign($request, $head, $prvkey, $alg);
+               $x = self::sign($head, $prvkey, $alg);
 
                $headerval = 'keyId="' . $keyid . '",algorithm="' . $algorithm
                        . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
 
-               if ($crypt_key) {
-                       $x = Crypto::encapsulate($headerval, $crypt_key, $crypt_algo);
-                       $headerval = 'iv="' . $x['iv'] . '",key="' . $x['key'] . '",alg="' . $x['alg'] . '",data="' . $x['data'] . '"';
-               }
-
-               if ($auth) {
-                       $sighead = 'Authorization: Signature ' . $headerval;
-               } else {
-                       $sighead = 'Signature: ' . $headerval;
-               }
+               $sighead = 'Authorization: Signature ' . $headerval;
 
                if ($head) {
                        foreach ($head as $k => $v) {
-                               if ($send_headers) {
-                                       // This is for ActivityPub implementation.
-                                       // Since the Activity Pub implementation isn't
-                                       // ready at the moment, we comment it out.
-                                       // header($k . ': ' . $v);
-                               } else {
-                                       $return_headers[] = $k . ': ' . $v;
-                               }
+                               $return_headers[] = $k . ': ' . $v;
                        }
                }
 
-               if ($send_headers) {
-                       // This is for ActivityPub implementation.
-                       // Since the Activity Pub implementation isn't
-                       // ready at the moment, we comment it out.
-                       // header($sighead);
-               } else {
-                       $return_headers[] = $sighead;
-               }
+               $return_headers[] = $sighead;
 
                return $return_headers;
        }
@@ -280,35 +147,27 @@ class HTTPSignature
        /**
         * @brief
         *
-        * @param string $request
         * @param array  $head
         * @param string $prvkey
         * @param string $alg (optional) default 'sha256'
         *
         * @return array
         */
-       private static function sign($request, $head, $prvkey, $alg = 'sha256')
+       private static function sign($head, $prvkey, $alg = 'sha256')
        {
                $ret = [];
                $headers = '';
                $fields  = '';
 
-               if ($request) {
-                       $headers = '(request-target)' . ': ' . trim($request) . "\n";
-                       $fields = '(request-target)';
-               }
-
-               if ($head) {
-                       foreach ($head as $k => $v) {
-                               $headers .= strtolower($k) . ': ' . trim($v) . "\n";
-                               if ($fields) {
-                                       $fields .= ' ';
-                               }
-                               $fields .= strtolower($k);
+               foreach ($head as $k => $v) {
+                       $headers .= strtolower($k) . ': ' . trim($v) . "\n";
+                       if ($fields) {
+                               $fields .= ' ';
                        }
-                       // strip the trailing linefeed
-                       $headers = rtrim($headers, "\n");
+                       $fields .= strtolower($k);
                }
+               // strip the trailing linefeed
+               $headers = rtrim($headers, "\n");
 
                $sig = base64_encode(Crypto::rsaSign($headers, $prvkey, $alg));
 
@@ -405,4 +264,177 @@ class HTTPSignature
 
                return '';
        }
+
+       /*
+        * Functions for ActivityPub
+        */
+
+       /**
+        * @brief Transmit given data to a target for a user
+        *
+        * @param $data
+        * @param $target
+        * @param $uid
+        */
+       public static function transmit($data, $target, $uid)
+       {
+               $owner = User::getOwnerDataById($uid);
+
+               if (!$owner) {
+                       return;
+               }
+
+               $content = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+
+               // Header data that is about to be signed.
+               $host = parse_url($target, PHP_URL_HOST);
+               $path = parse_url($target, PHP_URL_PATH);
+               $digest = 'SHA-256=' . base64_encode(hash('sha256', $content, true));
+               $content_length = strlen($content);
+
+               $headers = ['Content-Length: ' . $content_length, 'Digest: ' . $digest, 'Host: ' . $host];
+
+               $signed_data = "(request-target): post " . $path . "\ncontent-length: " . $content_length . "\ndigest: " . $digest . "\nhost: " . $host;
+
+               $signature = base64_encode(Crypto::rsaSign($signed_data, $owner['uprvkey'], 'sha256'));
+
+               $headers[] = 'Signature: keyId="' . $owner['url'] . '#main-key' . '",algorithm="rsa-sha256",headers="(request-target) content-length digest host",signature="' . $signature . '"';
+
+               $headers[] = 'Content-Type: application/activity+json';
+
+               $postResult = Network::post($target, $content, $headers);
+
+               logger('Transmit to ' . $target . ' returned ' . $postResult->getReturnCode());
+       }
+
+       /**
+        * @brief Gets a signer from a given HTTP request
+        *
+        * @param $content
+        * @param $http_headers
+        *
+        * @return signer string
+        */
+       public static function getSigner($content, $http_headers)
+       {
+               $object = json_decode($content, true);
+
+               if (empty($object)) {
+                       return false;
+               }
+
+               $actor = JsonLD::fetchElement($object, 'actor', 'id');
+
+               $headers = [];
+               $headers['(request-target)'] = strtolower($http_headers['REQUEST_METHOD']) . ' ' . $http_headers['REQUEST_URI'];
+
+               // First take every header
+               foreach ($http_headers as $k => $v) {
+                       $field = str_replace('_', '-', strtolower($k));
+                       $headers[$field] = $v;
+               }
+
+               // Now add every http header
+               foreach ($http_headers as $k => $v) {
+                       if (strpos($k, 'HTTP_') === 0) {
+                               $field = str_replace('_', '-', strtolower(substr($k, 5)));
+                               $headers[$field] = $v;
+                       }
+               }
+
+               $sig_block = self::parseSigHeader($http_headers['HTTP_SIGNATURE']);
+
+               if (empty($sig_block) || empty($sig_block['headers']) || empty($sig_block['keyId'])) {
+                       return false;
+               }
+
+               $signed_data = '';
+               foreach ($sig_block['headers'] as $h) {
+                       if (array_key_exists($h, $headers)) {
+                               $signed_data .= $h . ': ' . $headers[$h] . "\n";
+                       }
+               }
+               $signed_data = rtrim($signed_data, "\n");
+
+               if (empty($signed_data)) {
+                       return false;
+               }
+
+               $algorithm = null;
+
+               if ($sig_block['algorithm'] === 'rsa-sha256') {
+                       $algorithm = 'sha256';
+               }
+
+               if ($sig_block['algorithm'] === 'rsa-sha512') {
+                       $algorithm = 'sha512';
+               }
+
+               if (empty($algorithm)) {
+                       return false;
+               }
+
+               $key = self::fetchKey($sig_block['keyId'], $actor);
+
+               if (empty($key)) {
+                       return false;
+               }
+
+               if (!Crypto::rsaVerify($signed_data, $sig_block['signature'], $key['pubkey'], $algorithm)) {
+                       return false;
+               }
+
+               // Check the digest when it is part of the signed data
+               if (in_array('digest', $sig_block['headers'])) {
+                       $digest = explode('=', $headers['digest'], 2);
+                       if ($digest[0] === 'SHA-256') {
+                               $hashalg = 'sha256';
+                       }
+                       if ($digest[0] === 'SHA-512') {
+                               $hashalg = 'sha512';
+                       }
+
+                       /// @todo add all hashes from the rfc
+
+                       if (!empty($hashalg) && base64_encode(hash($hashalg, $content, true)) != $digest[1]) {
+                               return false;
+                       }
+               }
+
+               // Check the content-length when it is part of the signed data
+               if (in_array('content-length', $sig_block['headers'])) {
+                       if (strlen($content) != $headers['content-length']) {
+                               return false;
+                       }
+               }
+
+               return $key['url'];
+       }
+
+       /**
+        * @brief fetches a key for a given id and actor
+        *
+        * @param $id
+        * @param $actor
+        *
+        * @return array with actor url and public key
+        */
+       private static function fetchKey($id, $actor)
+       {
+               $url = (strpos($id, '#') ? substr($id, 0, strpos($id, '#')) : $id);
+
+               $profile = APContact::getByURL($url);
+               if (!empty($profile)) {
+                       logger('Taking key from id ' . $id, LOGGER_DEBUG);
+                       return ['url' => $url, 'pubkey' => $profile['pubkey']];
+               } elseif ($url != $actor) {
+                       $profile = APContact::getByURL($actor);
+                       if (!empty($profile)) {
+                               logger('Taking key from actor ' . $actor, LOGGER_DEBUG);
+                               return ['url' => $actor, 'pubkey' => $profile['pubkey']];
+                       }
+               }
+
+               return false;
+       }
 }
diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php
new file mode 100644 (file)
index 0000000..5380c3c
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+/**
+ * @file src/Util/JsonLD.php
+ */
+namespace Friendica\Util;
+
+use Friendica\Core\Cache;
+use Exception;
+
+/**
+ * @brief This class contain methods to work with JsonLD data
+ */
+class JsonLD
+{
+       /**
+        * @brief Loader for LD-JSON validation
+        *
+        * @param $url
+        *
+        * @return the loaded data
+        */
+       public static function documentLoader($url)
+       {
+               $recursion = 0;
+
+               $x = debug_backtrace();
+               if ($x) {
+                       foreach ($x as $n) {
+                               if ($n['function'] === __FUNCTION__)  {
+                                       $recursion ++;
+                               }
+                       }
+               }
+
+               if ($recursion > 5) {
+                       logger('jsonld bomb detected at: ' . $url);
+                       exit();
+               }
+
+               $result = Cache::get('documentLoader:' . $url);
+               if (!is_null($result)) {
+                       return $result;
+               }
+
+               $data = jsonld_default_document_loader($url);
+               Cache::set('documentLoader:' . $url, $data, CACHE_DAY);
+               return $data;
+       }
+
+       /**
+        * @brief Normalises a given JSON array
+        *
+        * @param array $json
+        *
+        * @return normalized JSON string
+        */
+       public static function normalize($json)
+       {
+               jsonld_set_document_loader('Friendica\Util\JsonLD::documentLoader');
+
+               $jsonobj = json_decode(json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
+
+               try {
+                       $normalized = jsonld_normalize($jsonobj, array('algorithm' => 'URDNA2015', 'format' => 'application/nquads'));
+               }
+               catch (Exception $e) {
+                       $normalized = false;
+                       logger('normalise error:' . print_r($e, true), LOGGER_DEBUG);
+               }
+
+               return $normalized;
+       }
+
+       /**
+        * @brief Compacts a given JSON array
+        *
+        * @param array $json
+        *
+        * @return comacted JSON array
+        */
+       public static function compact($json)
+       {
+               jsonld_set_document_loader('Friendica\Util\JsonLD::documentLoader');
+
+               $context = (object)['as' => 'https://www.w3.org/ns/activitystreams#',
+                       'w3id' => 'https://w3id.org/security#',
+                       'vcard' => (object)['@id' => 'http://www.w3.org/2006/vcard/ns#', '@type' => '@id'],
+                       'ostatus' => (object)['@id' => 'http://ostatus.org#', '@type' => '@id'],
+                       'diaspora' => (object)['@id' => 'https://diasporafoundation.org/ns/', '@type' => '@id'],
+                       'dc' => (object)['@id' => 'http://purl.org/dc/terms/', '@type' => '@id'],
+                       'uuid' => (object)['@id' => 'http://schema.org/identifier', '@type' => '@id']];
+
+               $jsonobj = json_decode(json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
+
+
+               try {
+                       $compacted = jsonld_compact($jsonobj, $context);
+               }
+               catch (Exception $e) {
+                       $compacted = false;
+                       logger('compacting error:' . print_r($e, true), LOGGER_DEBUG);
+               }
+
+               return json_decode(json_encode($compacted, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), true);
+       }
+
+       /**
+        * @brief Fetches an element array from a JSON array
+        *
+        * @param $array
+        * @param $element
+        * @param $key
+        *
+        * @return fetched element array
+        */
+       public static function fetchElementArray($array, $element, $key = '@id')
+       {
+               if (empty($array)) {
+                       return null;
+               }
+
+               if (!isset($array[$element])) {
+                       return null;
+               }
+
+               // If it isn't an array yet, make it to one
+               if (!is_int(key($array[$element]))) {
+                       $array[$element] = [$array[$element]];
+               }
+
+               $elements = [];
+
+               foreach ($array[$element] as $entry) {
+                       if (!is_array($entry)) {
+                               $elements[] = $entry;
+                       } elseif (!empty($entry[$key])) {
+                               $elements[] = $entry[$key];
+                       } elseif (!empty($entry) || !is_array($entry)) {
+                               $elements[] = $entry;
+                       }
+               }
+
+               return $elements;
+       }
+
+       /**
+        * @brief Fetches an element from a JSON array
+        *
+        * @param $array
+        * @param $element
+        * @param $key
+        * @param $type
+        * @param $type_value
+        *
+        * @return fetched element
+        */
+       public static function fetchElement($array, $element, $key = '@id', $type = null, $type_value = null)
+       {
+               if (empty($array)) {
+                       return null;
+               }
+
+               if (!isset($array[$element])) {
+                       return null;
+               }
+
+               if (!is_array($array[$element])) {
+                       return $array[$element];
+               }
+
+               if (is_null($type) || is_null($type_value)) {
+                       $element_array = self::fetchElementArray($array, $element, $key);
+                       if (is_null($element_array)) {
+                               return null;
+                       }
+
+                       return array_shift($element_array);
+               }
+
+               $element_array = self::fetchElementArray($array, $element);
+               if (is_null($element_array)) {
+                       return null;
+               }
+
+               foreach ($element_array as $entry) {
+                       if (isset($entry[$key]) && isset($entry[$type]) && ($entry[$type] == $type_value)) {
+                               return $entry[$key];
+                       }
+               }
+
+               return null;
+       }
+}
diff --git a/src/Util/LDSignature.php b/src/Util/LDSignature.php
new file mode 100644 (file)
index 0000000..7776ec9
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+
+namespace Friendica\Util;
+
+use Friendica\Util\JsonLD;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Model\APContact;
+
+/**
+ * @brief Implements JSON-LD signatures
+ *
+ * Ported from Osada: https://framagit.org/macgirvin/osada
+ */
+class LDSignature
+{
+       public static function isSigned($data)
+       {
+               return !empty($data['signature']);
+       }
+
+       public static function getSigner($data)
+       {
+               if (!self::isSigned($data)) {
+                       return false;
+               }
+
+               $actor = JsonLD::fetchElement($data, 'actor', 'id');
+               if (empty($actor)) {
+                       return false;
+               }
+
+               $profile = APContact::getByURL($actor);
+               if (empty($profile['pubkey'])) {
+                       return false;
+               }
+               $pubkey = $profile['pubkey'];
+
+               $ohash = self::hash(self::signableOptions($data['signature']));
+               $dhash = self::hash(self::signableData($data));
+
+               $x = Crypto::rsaVerify($ohash . $dhash, base64_decode($data['signature']['signatureValue']), $pubkey);
+               logger('LD-verify: ' . intval($x));
+
+               if (empty($x)) {
+                       return false;
+               } else {
+                       return $actor;
+               }
+       }
+
+       public static function sign($data, $owner)
+       {
+               $options = [
+                       'type' => 'RsaSignature2017',
+                       'nonce' => random_string(64),
+                       'creator' => $owner['url'] . '#main-key',
+                       'created' => DateTimeFormat::utcNow(DateTimeFormat::ATOM)
+               ];
+
+               $ohash = self::hash(self::signableOptions($options));
+               $dhash = self::hash(self::signableData($data));
+               $options['signatureValue'] = base64_encode(Crypto::rsaSign($ohash . $dhash, $owner['uprvkey']));
+
+               return array_merge($data, ['signature' => $options]);
+       }
+
+       private static function signableData($data)
+       {
+               unset($data['signature']);
+               return $data;
+       }
+
+       private static function signableOptions($options)
+       {
+               $newopts = ['@context' => 'https://w3id.org/identity/v1'];
+
+               unset($options['type']);
+               unset($options['id']);
+               unset($options['signatureValue']);
+
+               return array_merge($newopts, $options);
+       }
+
+       private static function hash($obj)
+       {
+               return hash('sha256', JsonLD::normalize($obj));
+       }
+}
index 0de96618597cae89b0408677329d18c8720729b1..1038fa3f0430fd9f89af68f0f827404fa809c0e5 100644 (file)
@@ -4,14 +4,10 @@
  */
 namespace Friendica\Util;
 
-use Friendica\App;
 use Friendica\Core\Addon;
-use Friendica\Core\L10n;
 use Friendica\Core\System;
 use Friendica\Core\Config;
-use Friendica\Network\Probe;
-use Friendica\Object\Image;
-use Friendica\Util\XML;
+use Friendica\Network\CurlResult;
 use DOMDocument;
 use DomXPath;
 
@@ -35,11 +31,11 @@ class Network
         *
         * @return string The fetched content
         */
-       public static function fetchUrl($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = 0)
+       public static function fetchUrl($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '')
        {
                $ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar);
 
-               return $ret['body'];
+               return $ret->getBody();
        }
 
        /**
@@ -57,9 +53,9 @@ class Network
         * @param string  $accept_content supply Accept: header with 'accept_content' as the value
         * @param string  $cookiejar      Path to cookie jar file
         *
-        * @return array With all relevant information, 'body' contains the actual fetched content.
+        * @return CurlResult With all relevant information, 'body' contains the actual fetched content.
         */
-       public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = 0)
+       public static function fetchUrlFull($url, $binary = false, &$redirects = 0, $timeout = 0, $accept_content = null, $cookiejar = '')
        {
                return self::curl(
                        $url,
@@ -87,12 +83,7 @@ class Network
         *                           'nobody' => only return the header
         *                           'cookiejar' => path to cookie jar file
         *
-        * @return array an assoziative array with:
-        *    int 'return_code' => HTTP return code or 0 if timeout or failure
-        *    boolean 'success' => boolean true (if HTTP 2xx result) or false
-        *    string 'redirect_url' => in case of redirect, content was finally retrieved from this URL
-        *    string 'header' => HTTP headers
-        *    string 'body' => fetched content
+        * @return CurlResult
         */
        public static function curl($url, $binary = false, &$redirects = 0, $opts = [])
        {
@@ -105,24 +96,24 @@ class Network
                $parts = parse_url($url);
                $path_parts = explode('/', defaults($parts, 'path', ''));
                foreach ($path_parts as $part) {
-                       if (strlen($part) <> mb_strlen($part)) {
+                       if (strlen($part) <> mb_strlen($part)) {
                                $parts2[] = rawurlencode($part);
-                       } else {
-                               $parts2[] = $part;
-                       }
+                       } else {
+                               $parts2[] = $part;
+                       }
                }
-               $parts['path'] =  implode('/', $parts2);
+               $parts['path'] = implode('/', $parts2);
                $url = self::unparseURL($parts);
 
                if (self::isUrlBlocked($url)) {
                        logger('domain of ' . $url . ' is blocked', LOGGER_DATA);
-                       return $ret;
+                       return CurlResult::createErrorCurl($url);
                }
 
                $ch = @curl_init($url);
 
                if (($redirects > 8) || (!$ch)) {
-                       return $ret;
+                       return CurlResult::createErrorCurl($url);
                }
 
                @curl_setopt($ch, CURLOPT_HEADER, true);
@@ -145,7 +136,7 @@ class Network
                }
 
                @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-               @curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+               @curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
 
                $range = intval(Config::get('system', 'curl_range_bytes', 0));
 
@@ -203,8 +194,6 @@ class Network
                        @curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
                }
 
-               $a->set_curl_code(0);
-
                // don't let curl abort the entire application
                // if it throws any errors.
 
@@ -219,91 +208,20 @@ class Network
                        $curl_info = @curl_getinfo($ch);
                }
 
-               if (curl_errno($ch) !== CURLE_OK) {
-                       logger('error fetching ' . $url . ': ' . curl_error($ch), LOGGER_INFO);
-               }
-
-               $ret['errno'] = curl_errno($ch);
-
-               $base = $s;
-               $ret['info'] = $curl_info;
-
-               $http_code = $curl_info['http_code'];
-
-               logger($url . ': ' . $http_code . " " . $s, LOGGER_DATA);
-               $header = '';
-
-               // Pull out multiple headers, e.g. proxy and continuation headers
-               // allow for HTTP/2.x without fixing code
-
-               while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
-                       $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
-                       $header .= $chunk;
-                       $base = substr($base, strlen($chunk));
-               }
-
-               $a->set_curl_code($http_code);
-               $a->set_curl_content_type($curl_info['content_type']);
-               $a->set_curl_headers($header);
-
-               if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
-                       $new_location_info = @parse_url($curl_info['redirect_url']);
-                       $old_location_info = @parse_url($curl_info['url']);
-
-                       $newurl = $curl_info['redirect_url'];
-
-                       if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
-                               $newurl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
-                       }
-
-                       $matches = [];
-
-                       if (preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches)) {
-                               $newurl = trim(array_pop($matches));
-                       }
-                       if (strpos($newurl, '/') === 0) {
-                               $newurl = $old_location_info["scheme"]."://".$old_location_info["host"].$newurl;
-                       }
-                       $old_location_query = @parse_url($url, PHP_URL_QUERY);
-
-                       if ($old_location_query != '') {
-                               $newurl .= '?' . $old_location_query;
-                       }
-
-                       if (filter_var($newurl, FILTER_VALIDATE_URL)) {
-                               $redirects++;
-                               @curl_close($ch);
-                               return self::curl($newurl, $binary, $redirects, $opts);
-                       }
-               }
-
-               $a->set_curl_code($http_code);
-               $a->set_curl_content_type($curl_info['content_type']);
-
-               $rc = intval($http_code);
-               $ret['return_code'] = $rc;
-               $ret['success'] = (($rc >= 200 && $rc <= 299) ? true : false);
-               $ret['redirect_url'] = $url;
-
-               if (!$ret['success']) {
-                       $ret['error'] = curl_error($ch);
-                       $ret['debug'] = $curl_info;
-                       logger('error: '.$url.': '.$ret['return_code'].' - '.$ret['error'], LOGGER_DEBUG);
-                       logger('debug: '.print_r($curl_info, true), LOGGER_DATA);
-               }
-
-               $ret['body'] = substr($s, strlen($header));
-               $ret['header'] = $header;
+               $curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
 
-               if (x($opts, 'debug')) {
-                       $ret['debug'] = $curl_info;
+               if ($curlResponse->isRedirectUrl()) {
+                       $redirects++;
+                       logger('curl: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
+                       @curl_close($ch);
+                       return self::curl($curlResponse->getRedirectUrl(), $binary, $redirects, $opts);
                }
 
                @curl_close($ch);
 
-               $a->save_timestamp($stamp1, 'network');
+               $a->saveTimestamp($stamp1, 'network');
 
-               return($ret);
+               return $curlResponse;
        }
 
        /**
@@ -315,7 +233,7 @@ class Network
         * @param integer $redirects Recursion counter for internal use - default = 0
         * @param integer $timeout   The timeout in seconds, default system config value or 60 seconds
         *
-        * @return string The content
+        * @return CurlResult The content
         */
        public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0)
        {
@@ -323,14 +241,14 @@ class Network
 
                if (self::isUrlBlocked($url)) {
                        logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA);
-                       return false;
+                       return CurlResult::createErrorCurl($url);
                }
 
                $a = get_app();
                $ch = curl_init($url);
 
                if (($redirects > 8) || (!$ch)) {
-                       return false;
+                       return CurlResult::createErrorCurl($url);
                }
 
                logger('post_url: start ' . $url, LOGGER_DATA);
@@ -339,7 +257,7 @@ class Network
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
-               curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+               curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
 
                if (Config::get('system', 'ipv4_resolve', false)) {
                        curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
@@ -384,8 +302,6 @@ class Network
                        }
                }
 
-               $a->set_curl_code(0);
-
                // don't let curl abort the entire application
                // if it throws any errors.
 
@@ -393,53 +309,23 @@ class Network
 
                $base = $s;
                $curl_info = curl_getinfo($ch);
-               $http_code = $curl_info['http_code'];
 
-               logger('post_url: result ' . $http_code . ' - ' . $url, LOGGER_DATA);
+               $curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch));
 
-               $header = '';
-
-               // Pull out multiple headers, e.g. proxy and continuation headers
-               // allow for HTTP/2.x without fixing code
-
-               while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) {
-                       $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
-                       $header .= $chunk;
-                       $base = substr($base, strlen($chunk));
-               }
-
-               if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
-                       $matches = [];
-                       $new_location_info = @parse_url($curl_info['redirect_url']);
-                       $old_location_info = @parse_url($curl_info['url']);
-
-                       preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
-                       $newurl = trim(array_pop($matches));
-
-                       if (strpos($newurl, '/') === 0) {
-                               $newurl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $newurl;
-                       }
-
-                       if (filter_var($newurl, FILTER_VALIDATE_URL)) {
-                               $redirects++;
-                               logger('post_url: redirect ' . $url . ' to ' . $newurl);
-                               return self::post($newurl, $params, $headers, $redirects, $timeout);
-                       }
+               if ($curlResponse->isRedirectUrl()) {
+                       $redirects++;
+                       logger('post_url: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl());
+                       curl_close($ch);
+                       return self::post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout);
                }
 
-               $a->set_curl_code($http_code);
-
-               $body = substr($s, strlen($header));
-
-               $a->set_curl_headers($header);
-
                curl_close($ch);
 
-               $a->save_timestamp($stamp1, 'network');
+               $a->saveTimestamp($stamp1, 'network');
 
                logger('post_url: end ' . $url, LOGGER_DATA);
 
-               return $body;
+               return $curlResponse;
        }
 
        /**
@@ -729,14 +615,14 @@ class Network
                curl_setopt($ch, CURLOPT_NOBODY, 1);
                curl_setopt($ch, CURLOPT_TIMEOUT, 10);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-               curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+               curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
 
                curl_exec($ch);
                $curl_info = @curl_getinfo($ch);
                $http_code = $curl_info['http_code'];
                curl_close($ch);
 
-               $a->save_timestamp($stamp1, "network");
+               $a->saveTimestamp($stamp1, "network");
 
                if ($http_code == 0) {
                        return $url;
@@ -773,12 +659,12 @@ class Network
                curl_setopt($ch, CURLOPT_NOBODY, 0);
                curl_setopt($ch, CURLOPT_TIMEOUT, 10);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-               curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+               curl_setopt($ch, CURLOPT_USERAGENT, $a->getUserAgent());
 
                $body = curl_exec($ch);
                curl_close($ch);
 
-               $a->save_timestamp($stamp1, "network");
+               $a->saveTimestamp($stamp1, "network");
 
                if (trim($body) == "") {
                        return $url;
index 00eac139026c1fe06a14d3f4ea129916ed492674..f2a5eccd395247956c9e39a4e22c037d9c0567fa 100644 (file)
@@ -135,23 +135,23 @@ class ParseUrl
                $siteinfo['url'] = $url;
                $siteinfo['type'] = 'link';
 
-               $data = Network::curl($url);
-               if (!$data['success']) {
+               $curlResult = Network::curl($url);
+               if (!$curlResult->isSuccess()) {
                        return $siteinfo;
                }
 
                // If the file is too large then exit
-               if ($data['info']['download_content_length'] > 1000000) {
+               if ($curlResult->getInfo()['download_content_length'] > 1000000) {
                        return $siteinfo;
                }
 
                // If it isn't a HTML file then exit
-               if (($data['info']['content_type'] != '') && !strstr(strtolower($data['info']['content_type']), 'html')) {
+               if (($curlResult->getContentType() != '') && !strstr(strtolower($curlResult->getContentType()), 'html')) {
                        return $siteinfo;
                }
 
-               $header = $data['header'];
-               $body = $data['body'];
+               $header = $curlResult->getHeader();
+               $body = $curlResult->getBody();
 
                if ($do_oembed) {
                        $oembed_data = OEmbed::fetchURL($url);
index 3473e8d167ddf9b578d8390f02d5b4d3fe7af83a..0bb7537f78bda42a52edb9535d43a4eea453ab7a 100644 (file)
@@ -91,7 +91,7 @@ class Proxy
                $url = html_entity_decode($url, ENT_NOQUOTES, 'utf-8');
 
                // Creating a sub directory to reduce the amount of files in the cache directory
-               $basepath = $a->get_basepath() . '/proxy';
+               $basepath = $a->getBasePath() . '/proxy';
 
                $shortpath = hash('md5', $url);
                $longpath = substr($shortpath, 0, 2);
diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php
new file mode 100644 (file)
index 0000000..7b1ad76
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @file src/Worker/APDelivery.php
+ */
+namespace Friendica\Worker;
+
+use Friendica\BaseObject;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Model\Item;
+use Friendica\Util\HTTPSignature;
+
+class APDelivery extends BaseObject
+{
+       /**
+        * @brief Delivers ActivityPub messages
+        *
+        * @param string $cmd
+        * @param integer $item_id
+        * @param string $inbox
+        * @param integer $uid
+        */
+       public static function execute($cmd, $item_id, $inbox, $uid)
+       {
+               logger('Invoked: ' . $cmd . ': ' . $item_id . ' to ' . $inbox, LOGGER_DEBUG);
+
+               if ($cmd == Delivery::MAIL) {
+               } elseif ($cmd == Delivery::SUGGESTION) {
+                       ActivityPub\Transmitter::sendContactSuggestion($uid, $inbox, $item_id);
+               } elseif ($cmd == Delivery::RELOCATION) {
+               } elseif ($cmd == Delivery::REMOVAL) {
+                       ActivityPub\Transmitter::sendProfileDeletion($uid, $inbox);
+               } elseif ($cmd == Delivery::PROFILEUPDATE) {
+                       ActivityPub\Transmitter::sendProfileUpdate($uid, $inbox);
+               } else {
+                       $data = ActivityPub\Transmitter::createCachedActivityFromItem($item_id);
+                       if (!empty($data)) {
+                               HTTPSignature::transmit($data, $inbox, $uid);
+                       }
+               }
+       }
+}
index 61077ae734f2d69a20498f905a7f6c466b61ed2c..b6dd896cd77e9770c54354e62a92caeaee8f6ddc 100644 (file)
@@ -115,7 +115,7 @@ class Cron
 
                // Ensure to have a .htaccess file.
                // this is a precaution for systems that update automatically
-               $basepath = $a->get_basepath();
+               $basepath = $a->getBasePath();
                if (!file_exists($basepath . '/.htaccess')) {
                        copy($basepath . '/.htaccess-dist', $basepath . '/.htaccess');
                }
index 098bce4d96a0407a19be9bdbb3a2b20323fef4ea..bd34449729392f575ad53169dc1750cb590ce5ad 100644 (file)
@@ -157,14 +157,14 @@ class CronJobs
                clear_cache();
 
                // clear cache for photos
-               clear_cache($a->get_basepath(), $a->get_basepath() . "/photo");
+               clear_cache($a->getBasePath(), $a->getBasePath() . "/photo");
 
                // clear smarty cache
-               clear_cache($a->get_basepath() . "/view/smarty3/compiled", $a->get_basepath() . "/view/smarty3/compiled");
+               clear_cache($a->getBasePath() . "/view/smarty3/compiled", $a->getBasePath() . "/view/smarty3/compiled");
 
                // clear cache for image proxy
                if (!Config::get("system", "proxy_disabled")) {
-                       clear_cache($a->get_basepath(), $a->get_basepath() . "/proxy");
+                       clear_cache($a->getBasePath(), $a->getBasePath() . "/proxy");
 
                        $cachetime = Config::get('system', 'proxy_cache_time');
 
index 3a93d92f7b37366047dfc551e4c792081c9fb65e..f2951cce1ff2bf13deb7aec6e112f16bfcb655f8 100644 (file)
@@ -22,13 +22,14 @@ require_once 'include/items.php';
 
 class Delivery extends BaseObject
 {
-       const MAIL =       'mail';
-       const SUGGESTION = 'suggest';
-       const RELOCATION = 'relocate';
-       const DELETION =   'drop';
-       const POST =       'wall-new';
-       const COMMENT =    'comment-new';
-       const REMOVAL =    'removeme';
+       const MAIL          = 'mail';
+       const SUGGESTION    = 'suggest';
+       const RELOCATION    = 'relocate';
+       const DELETION      = 'drop';
+       const POST          = 'wall-new';
+       const COMMENT       = 'comment-new';
+       const REMOVAL       = 'removeme';
+       const PROFILEUPDATE = 'profileupdate';
 
        public static function execute($cmd, $item_id, $contact_id)
        {
@@ -111,7 +112,7 @@ class Delivery extends BaseObject
                        // if $parent['wall'] == 1 we will already have the parent message in our array
                        // and we will relay the whole lot.
 
-                       $localhost = self::getApp()->get_hostname();
+                       $localhost = self::getApp()->getHostName();
                        if (strpos($localhost, ':')) {
                                $localhost = substr($localhost, 0, strpos($localhost, ':'));
                        }
@@ -434,7 +435,7 @@ class Delivery extends BaseObject
                                $headers  = 'From: ' . Email::encodeHeader($local_user['username'],'UTF-8').' <' . $local_user['email'] . '>' . "\n";
                        }
                } else {
-                       $headers  = 'From: '. Email::encodeHeader($local_user['username'], 'UTF-8') . ' <noreply@' . self::getApp()->get_hostname() . '>' . "\n";
+                       $headers  = 'From: '. Email::encodeHeader($local_user['username'], 'UTF-8') . ' <noreply@' . self::getApp()->getHostName() . '>' . "\n";
                }
 
                $headers .= 'Message-Id: <' . Email::iri2msgid($target_item['uri']) . '>' . "\n";
index e6fc8391ffa044d686c59f1b47e84dfcd125b7f7..497684497fbd4cc778558cc7627626a5bc5c1ce6 100644 (file)
@@ -274,12 +274,12 @@ class DiscoverPoCo
 
                $url = "http://gstools.org/api/users_search/".urlencode($search);
 
-               $result = Network::curl($url);
-               if (!$result["success"]) {
+               $curlResult = Network::curl($url);
+               if (!$curlResult->isSuccess()) {
                        return false;
                }
 
-               $contacts = json_decode($result["body"]);
+               $contacts = json_decode($curlResult->getBody());
 
                if ($contacts->status == 'ERROR') {
                        return false;
index 61eaba388b2d365a58829bcf4abddcb1bda54874..ad33c3245d4be9d33e1381cb9d1cb00b40851842 100644 (file)
@@ -16,9 +16,11 @@ use Friendica\Model\Item;
 use Friendica\Model\PushSubscriber;
 use Friendica\Model\User;
 use Friendica\Network\Probe;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Diaspora;
 use Friendica\Protocol\OStatus;
 use Friendica\Protocol\Salmon;
+use Friendica\Model\Conversation;
 
 require_once 'include/dba.php';
 require_once 'include/items.php';
@@ -98,6 +100,14 @@ class Notifier
                        foreach ($r as $contact) {
                                Contact::terminateFriendship($user, $contact, true);
                        }
+
+                       $inboxes = ActivityPub\Transmitter::fetchTargetInboxesforUser(0);
+                       foreach ($inboxes as $inbox) {
+                               logger('Account removal for user ' . $item_id . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG);
+                               Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true],
+                                       'APDelivery', Delivery::REMOVAL, '', $inbox, $item_id);
+                       }
+
                        return;
                } elseif ($cmd == Delivery::RELOCATION) {
                        $normal_mode = false;
@@ -167,6 +177,8 @@ class Notifier
                if (!in_array($cmd, [Delivery::MAIL, Delivery::SUGGESTION, Delivery::RELOCATION])) {
                        $parent = $items[0];
 
+                       self::activityPubDelivery($a, $cmd, $item_id, $uid, $target_item, $parent);
+
                        $fields = ['network', 'author-id', 'owner-id'];
                        $condition = ['uri' => $target_item["thr-parent"], 'uid' => $target_item["uid"]];
                        $thr_parent = Item::selectFirst($fields, $condition);
@@ -182,7 +194,7 @@ class Notifier
                        // if $parent['wall'] == 1 we will already have the parent message in our array
                        // and we will relay the whole lot.
 
-                       $localhost = str_replace('www.','',$a->get_hostname());
+                       $localhost = str_replace('www.','',$a->getHostName());
                        if (strpos($localhost,':')) {
                                $localhost = substr($localhost,0,strpos($localhost,':'));
                        }
@@ -497,6 +509,41 @@ class Notifier
                return;
        }
 
+       private static function activityPubDelivery($a, $cmd, $item_id, $uid, $target_item, $parent)
+       {
+               $inboxes = [];
+
+               if ($target_item['origin']) {
+                       $inboxes = ActivityPub\Transmitter::fetchTargetInboxes($target_item, $uid);
+                       logger('Origin item ' . $item_id . ' with URL ' . $target_item['uri'] . ' will be distributed.', LOGGER_DEBUG);
+               } elseif (!DBA::exists('conversation', ['item-uri' => $target_item['uri'], 'protocol' => Conversation::PARCEL_ACTIVITYPUB])) {
+                       logger('Remote item ' . $item_id . ' with URL ' . $target_item['uri'] . ' is no AP post. It will not be distributed.', LOGGER_DEBUG);
+                       return;
+               } else {
+                       logger('Remote item ' . $item_id . ' with URL ' . $target_item['uri'] . ' will be distributed.', LOGGER_DEBUG);
+               }
+
+               if ($parent['origin']) {
+                       $parent_inboxes = ActivityPub\Transmitter::fetchTargetInboxes($parent, $uid);
+                       $inboxes = array_merge($inboxes, $parent_inboxes);
+               }
+
+               if (empty($inboxes)) {
+                       logger('No inboxes found for item ' . $item_id . ' with URL ' . $target_item['uri'] . '. It will not be distributed.', LOGGER_DEBUG);
+                       return;
+               }
+
+               // Fill the item cache
+               ActivityPub\Transmitter::createCachedActivityFromItem($item_id);
+
+               foreach ($inboxes as $inbox) {
+                       logger('Deliver ' . $item_id .' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG);
+
+                       Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true],
+                                       'APDelivery', $cmd, $item_id, $inbox, $uid);
+               }
+       }
+
        private static function isForumPost($item, $owner) {
                if (($item['author-id'] == $item['owner-id']) ||
                        ($owner['id'] == $item['contact-id']) ||
index 01b63e98e03a494478dca3fb00995562c49aa642..3c16af75f86334ddec6cd0777e75b4f0c5e96bde 100644 (file)
@@ -13,6 +13,7 @@ use Friendica\Database\DBA;
 use Friendica\Model\Contact;
 use Friendica\Model\Item;
 use Friendica\Protocol\Email;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\PortableContact;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
@@ -55,6 +56,17 @@ class OnePoll
 
                $importer_uid = $contact['uid'];
 
+               // Possibly switch the remote contact to AP
+               if ($contact['network'] === Protocol::OSTATUS) {
+                       ActivityPub\Receiver::switchContact($contact['id'], $importer_uid, $contact['url']);
+                       $contact = DBA::selectFirst('contact', [], ['id' => $contact_id]);
+               }
+
+               // We currently don't do anything with AP here
+               if ($contact['network'] === Protocol::ACTIVITYPUB) {
+                       return;
+               }
+
                // load current friends if possible.
                if (($contact['poco'] != "") && ($contact['success_update'] > $contact['failure_update'])) {
                        $r = q("SELECT count(*) AS total FROM glink
@@ -185,18 +197,17 @@ class OnePoll
                                . '&type=data&last_update=' . $last_update
                                . '&perm=' . $perm ;
 
-                       $ret = Network::curl($url);
+                       $curlResult = Network::curl($url);
 
-                       if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+                       if (!$curlResult->isSuccess() && ($curlResult->getErrorNumber() == CURLE_OPERATION_TIMEDOUT)) {
                                // set the last-update so we don't keep polling
                                DBA::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]);
                                Contact::markForArchival($contact);
                                return;
                        }
 
-                       $handshake_xml = $ret['body'];
-
-                       $html_code = $a->get_curl_code();
+                       $handshake_xml = $curlResult->getBody();
+                       $html_code = $curlResult->getReturnCode();
 
                        logger('handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA);
 
@@ -288,7 +299,7 @@ class OnePoll
                        $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
                        $postvars['perm'] = 'rw';
 
-                       $xml = Network::post($contact['poll'], $postvars);
+                       $xml = Network::post($contact['poll'], $postvars)->getBody();
 
                } elseif (($contact['network'] === Protocol::OSTATUS)
                        || ($contact['network'] === Protocol::DIASPORA)
@@ -319,17 +330,17 @@ class OnePoll
                        }
 
                        $cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-');
-                       $ret = Network::curl($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]);
+                       $curlResult = Network::curl($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]);
                        unlink($cookiejar);
 
-                       if (!empty($ret["errno"]) && ($ret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
+                       if (!$curlResult->isTimeout()) {
                                // set the last-update so we don't keep polling
                                DBA::update('contact', ['last-update' => DateTimeFormat::utcNow()], ['id' => $contact['id']]);
                                Contact::markForArchival($contact);
                                return;
                        }
 
-                       $xml = $ret['body'];
+                       $xml = $curlResult->getBody();
 
                } elseif ($contact['network'] === Protocol::MAIL) {
                        logger("Mail: Fetching for ".$contact['addr'], LOGGER_DEBUG);
@@ -507,7 +518,7 @@ class OnePoll
                                                                }
                                                        }
 
-                                                       $fromarr = imap_rfc822_parse_adrlist($fromdecoded, $a->get_hostname());
+                                                       $fromarr = imap_rfc822_parse_adrlist($fromdecoded, $a->getHostName());
 
                                                        $frommail = $fromarr[0]->mailbox."@".$fromarr[0]->host;
 
index e33aa5d9a88ad6a2804d044f5242da1f8cbc4771..cebc27ca55b83644e14242ac627954ced123d660 100644 (file)
@@ -1,12 +1,15 @@
 <?php
 /**
  * @file src/Worker/ProfileUpdate.php
- * @brief Send updated profile data to Diaspora
+ * @brief Send updated profile data to Diaspora and ActivityPub
  */
 
 namespace Friendica\Worker;
 
+use Friendica\BaseObject;
 use Friendica\Protocol\Diaspora;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Core\Worker;
 
 class ProfileUpdate {
        public static function execute($uid = 0) {
@@ -14,6 +17,16 @@ class ProfileUpdate {
                        return;
                }
 
+               $a = BaseObject::getApp();
+
+               $inboxes = ActivityPub\Transmitter::fetchTargetInboxesforUser($uid);
+
+               foreach ($inboxes as $inbox) {
+                       logger('Profile update for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG);
+                       Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true],
+                               'APDelivery', Delivery::PROFILEUPDATE, '', $inbox, $uid);
+               }
+
                Diaspora::sendProfile($uid);
        }
 }
index 1e18b4ccfa097b81aedcfb364e60754bc18a545d..38d9c07868a56b75edc592d22f3f55a3d55255ae 100644 (file)
@@ -56,8 +56,8 @@ class PubSubPublish
 
                logger('POST ' . print_r($headers, true) . "\n" . $params, LOGGER_DATA);
 
-               Network::post($subscriber['callback_url'], $params, $headers);
-               $ret = $a->get_curl_code();
+               $postResult = Network::post($subscriber['callback_url'], $params, $headers);
+               $ret = $postResult->getReturnCode();
 
                $condition = ['id' => $subscriber['id']];
 
index f2919e4a750e148e0e8531171d9b786e8a1dc3c5..67362917c379418ed2d98652e332e99b351ffd58 100644 (file)
@@ -29,13 +29,13 @@ class UpdateGContact
                        return;
                }
 
-               if (!in_array($r[0]["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
+               if (!in_array($r[0]["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
                        return;
                }
 
                $data = Probe::uri($r[0]["url"]);
 
-               if (!in_array($data["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
+               if (!in_array($data["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
                        if ($r[0]["server_url"] != "") {
                                PortableContact::checkServer($r[0]["server_url"], $r[0]["network"]);
                        }
index a3e1ced68396f016cfa7cd3c414c2c38c903a9d6..11c61f9fbb40a46990838ddbd6534d58ad4e1b6b 100644 (file)
@@ -24,12 +24,11 @@ class ApiTest extends DatabaseTest
        /**
         * Create variables used by tests.
         */
-       protected function setUp()
+       public function setUp()
        {
                parent::setUp();
 
-               // Reusable App object
-               $this->app = BaseObject::getApp();
+               require_once __DIR__.'/../include/api.php';
 
                // User data that the test database is populated with
                $this->selfUser = [
@@ -76,9 +75,8 @@ class ApiTest extends DatabaseTest
        {
                parent::tearDown();
 
-               $app = get_app();
-               $app->argc = 1;
-               $app->argv = ['home'];
+               $this->app->argc = 1;
+               $this->app->argv = ['home'];
        }
 
        /**
@@ -3388,7 +3386,7 @@ class ApiTest extends DatabaseTest
         */
        public function testApiShareAsRetweet()
        {
-               $item = ['body' => ''];
+               $item = ['body' => '', 'author-id' => 1, 'owner-id' => 1];
                $result = api_share_as_retweet($item);
                $this->assertFalse($result);
        }
index 9844699b069e86b885a0f3eab393042956648adc..acd0b7ac184d1adbe8a563f1754869103961754c 100644 (file)
@@ -5,6 +5,9 @@
 
 namespace Friendica\Test;
 
+use Friendica\App;
+use Friendica\BaseObject;
+use Friendica\Core\Config;
 use Friendica\Database\DBA;
 use PHPUnit\DbUnit\DataSet\YamlDataSet;
 use PHPUnit\DbUnit\TestCaseTrait;
@@ -16,9 +19,23 @@ use PHPUnit_Extensions_Database_DB_IDatabaseConnection;
  */
 abstract class DatabaseTest extends TestCase
 {
-
        use TestCaseTrait;
 
+       /**
+        * @var App The Friendica App
+        */
+       protected $app;
+
+       protected function setUp()
+       {
+               // Reusable App object
+               $this->app = BaseObject::getApp();
+
+               Config::set('system', 'url', 'http://localhost');
+               Config::set('system', 'hostname', 'localhost');
+               Config::set('system', 'worker_dont_fork', true);
+       }
+
        /**
         * Get database connection.
         *
diff --git a/tests/Util/VFSTrait.php b/tests/Util/VFSTrait.php
new file mode 100644 (file)
index 0000000..b0e7a3a
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+namespace Friendica\Test\Util;
+
+
+use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamDirectory;
+
+trait VFSTrait
+{
+       /**
+        * @var vfsStreamDirectory The Stream Directory
+        */
+       protected $root;
+
+       protected function setUpVfsDir() {
+               // the used directories inside the App class
+               $structure = [
+                       'config' => [],
+                       'bin' => []
+               ];
+
+               // create a virtual directory and copy all needed files and folders to it
+               $this->root = vfsStream::setup('friendica', null, $structure);
+
+               $this->setConfigFile('config.ini.php');
+               $this->setConfigFile('settings.ini.php');
+               $this->setConfigFile('local.ini.php');
+               $this->setConfigFile('dbstructure.json');
+       }
+
+       protected function setConfigFile($filename)
+       {
+               $file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
+                       '..' . DIRECTORY_SEPARATOR .
+                       'config' . DIRECTORY_SEPARATOR .
+                       $filename;
+
+               if (file_exists($file)) {
+                       vfsStream::newFile($filename)
+                               ->at($this->root->getChild('config'))
+                               ->setContent(file_get_contents($file));
+               }
+       }
+
+       protected function delConfigFile($filename)
+       {
+               if ($this->root->hasChild('config/' . $filename)) {
+                       $this->root->removeChild('config/' . $filename);
+               }
+       }
+}
index 4bc3e932f0118529faae6ca0d3560985603d2ccf..ada2b1a0ec6852af6cc387841ef464ce51077e1d 100644 (file)
@@ -3,20 +3,10 @@
  * This file is loaded by PHPUnit before any test.
  */
 
-use Friendica\App;
 use PHPUnit\DbUnit\DataSet\YamlDataSet;
 use PHPUnit\DbUnit\TestCaseTrait;
 use PHPUnit\Framework\TestCase;
 
-require_once __DIR__.'/../boot.php';
-require_once __DIR__.'/../include/api.php';
-
-new App(dirname(__DIR__));
-
-\Friendica\Core\Config::set('system', 'url', 'http://localhost');
-\Friendica\Core\Config::set('system', 'hostname', 'localhost');
-\Friendica\Core\Config::set('system', 'worker_dont_fork', true);
-
 // Backward compatibility
 if (!class_exists(TestCase::class)) {
        class_alias(PHPUnit_Framework_TestCase::class, TestCase::class);
diff --git a/tests/datasets/curl/about.body b/tests/datasets/curl/about.body
new file mode 100644 (file)
index 0000000..86d8712
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<meta charset='utf-8'>
+<meta content='width=device-width, initial-scale=1' name='viewport'>
+<meta content="summary_large_image" property="twitter:card" />
+
+
+</head>
+<body class='with-modals theme-default no-reduce-motion'>
+<div class='landing-page alternative'>
+</div>
+</div>
+<div id='modal-container'></div>
+
+</body>
+</html>
diff --git a/tests/datasets/curl/about.head b/tests/datasets/curl/about.head
new file mode 100644 (file)
index 0000000..c1d4b16
--- /dev/null
@@ -0,0 +1,21 @@
+HTTP/2 200 \r
+date: Thu, 11 Oct 2018 18:43:54 GMT\r
+content-type: text/html; charset=utf-8\r
+vary: Accept-Encoding\r
+server: Mastodon\r
+x-frame-options: DENY\r
+x-content-type-options: nosniff\r
+x-xss-protection: 1; mode=block\r
+vary: Accept-Encoding\r
+etag: W/"706e6c48957e1d46ecf9d7597a7880af"\r
+cache-control: max-age=0, private, must-revalidate\r
+set-cookie: _mastodon_session=v3kcy%2FW3aZYBBvZUohuwksEKwzYIyEUlEuJ1KqTAfWPKvVQq%2F4UuJ39zp621VyfpQNlvY46TL%2FYutzXowSLYQBNFCJcrEiF04aU0TdtHls9zynMiyeHhoVgCijOXWXNt9%2FCmpQ49RkNEujkv9NaJ0cum32MCVZKjE9%2BMKmLM%2F8ZygZeLBGJ7sg%3D%3D--QGIiU0%2FpXc3Aym8F--he2iRRPePOdtEs3z%2BufSXg%3D%3D; path=/; secure; HttpOnly\r
+x-request-id: a0c0b8e7-cd60-4efa-b79b-cf1b0d5a0784\r
+x-runtime: 0.049566\r
+strict-transport-security: max-age=31536000; includeSubDomains; preload\r
+x-frame-options: SAMEORIGIN\r
+x-content-type-options: nosniff\r
+referrer-policy: same-origin\r
+content-security-policy: frame-ancestors 'none'; script-src 'self'; object-src 'self'; img-src * data: blob:; media-src 'self' data:; font-src 'self' data: https://fonts.gstatic.com/; connect-src 'self' blob: wss://mastodonten.de\r
+x-xss-protection: 1; mode=block\r
+\r
diff --git a/tests/datasets/curl/about.redirect b/tests/datasets/curl/about.redirect
new file mode 100644 (file)
index 0000000..9033e0f
--- /dev/null
@@ -0,0 +1,22 @@
+HTTP/2 301 \r
+date: Thu, 11 Oct 2018 18:43:54 GMT\r
+content-type: text/html; charset=utf-8\r
+vary: Accept-Encoding\r
+server: Mastodon\r
+Location: https://test.other/some/\r
+x-frame-options: DENY\r
+x-content-type-options: nosniff\r
+x-xss-protection: 1; mode=block\r
+vary: Accept-Encoding\r
+etag: W/"706e6c48957e1d46ecf9d7597a7880af"\r
+cache-control: max-age=0, private, must-revalidate\r
+set-cookie: _mastodon_session=v3kcy%2FW3aZYBBvZUohuwksEKwzYIyEUlEuJ1KqTAfWPKvVQq%2F4UuJ39zp621VyfpQNlvY46TL%2FYutzXowSLYQBNFCJcrEiF04aU0TdtHls9zynMiyeHhoVgCijOXWXNt9%2FCmpQ49RkNEujkv9NaJ0cum32MCVZKjE9%2BMKmLM%2F8ZygZeLBGJ7sg%3D%3D--QGIiU0%2FpXc3Aym8F--he2iRRPePOdtEs3z%2BufSXg%3D%3D; path=/; secure; HttpOnly\r
+x-request-id: a0c0b8e7-cd60-4efa-b79b-cf1b0d5a0784\r
+x-runtime: 0.049566\r
+strict-transport-security: max-age=31536000; includeSubDomains; preload\r
+x-frame-options: SAMEORIGIN\r
+x-content-type-options: nosniff\r
+referrer-policy: same-origin\r
+content-security-policy: frame-ancestors 'none'; script-src 'self'; object-src 'self'; img-src * data: blob:; media-src 'self' data:; font-src 'self' data: https://fonts.gstatic.com/; connect-src 'self' blob: wss://mastodonten.de\r
+x-xss-protection: 1; mode=block\r
+\r
diff --git a/tests/src/App/ModeTest.php b/tests/src/App/ModeTest.php
new file mode 100644 (file)
index 0000000..bac553e
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+
+namespace Friendica\Test\src\App;
+
+use Friendica\App\Mode;
+use Friendica\Test\Util\VFSTrait;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ */
+class ModeTest extends TestCase
+{
+       use VFSTrait;
+
+       public function setUp()
+       {
+               parent::setUp(); // TODO: Change the autogenerated stub
+
+               $this->setUpVfsDir();
+       }
+
+       public function testItEmpty()
+       {
+               $mode = new Mode($this->root->url());
+               $this->assertTrue($mode->isInstall());
+               $this->assertFalse($mode->isNormal());
+       }
+
+       public function testWithoutConfig()
+       {
+               $mode = new Mode($this->root->url());
+
+               $this->assertTrue($this->root->hasChild('config/local.ini.php'));
+
+               $this->delConfigFile('local.ini.php');
+
+               $this->assertFalse($this->root->hasChild('config/local.ini.php'));
+
+               $mode->determine();
+
+               $this->assertTrue($mode->isInstall());
+               $this->assertFalse($mode->isNormal());
+
+               $this->assertFalse($mode->has(Mode::LOCALCONFIGPRESENT));
+       }
+
+       public function testWithoutDatabase()
+       {
+               $dba =  \Mockery::mock('alias:Friendica\Database\DBA');
+               $dba
+                       ->shouldReceive('connected')
+                       ->andReturn(false);
+
+               $mode = new Mode($this->root->url());
+               $mode->determine();
+
+               $this->assertFalse($mode->isNormal());
+               $this->assertTrue($mode->isInstall());
+
+               $this->assertTrue($mode->has(Mode::LOCALCONFIGPRESENT));
+               $this->assertFalse($mode->has(Mode::DBAVAILABLE));
+       }
+
+       public function testWithoutDatabaseSetup()
+       {
+               $dba =  \Mockery::mock('alias:Friendica\Database\DBA');
+               $dba
+                       ->shouldReceive('connected')
+                       ->andReturn(true);
+               $dba
+                       ->shouldReceive('fetchFirst')
+                       ->with('SHOW TABLES LIKE \'config\'')
+                       ->andReturn(false);
+
+               $mode = new Mode($this->root->url());
+               $mode->determine();
+
+               $this->assertFalse($mode->isNormal());
+               $this->assertTrue($mode->isInstall());
+
+               $this->assertTrue($mode->has(Mode::LOCALCONFIGPRESENT));
+       }
+
+       public function testWithMaintenanceMode()
+       {
+               $dba =  \Mockery::mock('alias:Friendica\Database\DBA');
+               $dba
+                       ->shouldReceive('connected')
+                       ->andReturn(true);
+               $dba
+                       ->shouldReceive('fetchFirst')
+                       ->with('SHOW TABLES LIKE \'config\'')
+                       ->andReturn(true);
+
+               $conf = \Mockery::mock('alias:Friendica\Core\Config');
+               $conf
+                       ->shouldReceive('get')
+                       ->with('system', 'maintenance')
+                       ->andReturn(true);
+
+               $mode = new Mode($this->root->url());
+               $mode->determine();
+
+               $this->assertFalse($mode->isNormal());
+               $this->assertFalse($mode->isInstall());
+
+               $this->assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
+               $this->assertFalse($mode->has(Mode::MAINTENANCEDISABLED));
+       }
+
+       public function testNormalMode()
+       {
+               $dba =  \Mockery::mock('alias:Friendica\Database\DBA');
+               $dba
+                       ->shouldReceive('connected')
+                       ->andReturn(true);
+               $dba
+                       ->shouldReceive('fetchFirst')
+                       ->with('SHOW TABLES LIKE \'config\'')
+                       ->andReturn(true);
+
+               $conf = \Mockery::mock('alias:Friendica\Core\Config');
+               $conf
+                       ->shouldReceive('get')
+                       ->with('system', 'maintenance')
+                       ->andReturn(false);
+
+               $mode = new Mode($this->root->url());
+               $mode->determine();
+
+               $this->assertTrue($mode->isNormal());
+               $this->assertFalse($mode->isInstall());
+
+               $this->assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
+               $this->assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
+       }
+}
index 0cad6e9c7f5ddd5a9464cd6f4bbab170b078fb40..6863d149ffbf49bd53435a3fd2f583cfc25843f0 100644 (file)
@@ -7,11 +7,6 @@ use Friendica\Core\Cache\ArrayCache;
 
 class ArrayCacheDriverTest extends MemoryCacheTest
 {
-       /**
-        * @var \Friendica\Core\Cache\IMemoryCacheDriver
-        */
-       private $cache;
-
        protected function getInstance()
        {
                $this->cache = new ArrayCache();
index 5c56c2072f4f13add69b2552cc03531fedadab7f..86bf5e7f01fa2a1e115db8aaee1aa9a15dba6dc4 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Friendica\Test\src\Core\Cache;
 
+use Friendica\Core\Cache\MemcachedCacheDriver;
 use Friendica\Core\Config;
 use Friendica\Test\DatabaseTest;
 use Friendica\Util\DateTimeFormat;
@@ -13,6 +14,12 @@ abstract class CacheTest extends DatabaseTest
         */
        protected $instance;
 
+       /**
+        * @var \Friendica\Core\Cache\IMemoryCacheDriver
+        */
+       protected $cache;
+
+
        abstract protected function getInstance();
 
        protected function setUp()
@@ -29,6 +36,8 @@ abstract class CacheTest extends DatabaseTest
                Config::set('system', 'throttle_limit_week', 100);
                Config::set('system', 'throttle_limit_month', 100);
                Config::set('system', 'theme', 'system_theme');
+
+               $this->instance->clear(false);
        }
 
        /**
@@ -177,4 +186,27 @@ abstract class CacheTest extends DatabaseTest
                $received = $this->instance->get('objVal');
                $this->assertEquals($value, $received, 'Value type changed from ' . gettype($value) . ' to ' . gettype($received));
        }
+
+       /**
+        * @small
+        */
+       public function testGetAllKeys() {
+               if ($this->cache instanceof MemcachedCacheDriver) {
+                       $this->markTestSkipped('Memcached doesn\'t support getAllKeys anymore');
+               }
+
+               $this->assertTrue($this->instance->set('value1', 'test'));
+               $this->assertTrue($this->instance->set('value2', 'test'));
+               $this->assertTrue($this->instance->set('test_value3', 'test'));
+
+               $list = $this->instance->getAllKeys();
+
+               $this->assertContains('value1', $list);
+               $this->assertContains('value2', $list);
+               $this->assertContains('test_value3', $list);
+
+               $list = $this->instance->getAllKeys('test');
+
+               $this->assertContains('test_value3', $list);
+       }
 }
index 5df00fc913581a36d0afffa51f38ecf81424a71b..3cc4a72ed1d6441f6e2e2992401677041c20561e 100644 (file)
@@ -6,11 +6,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
 
 class DatabaseCacheDriverTest extends CacheTest
 {
-       /**
-        * @var \Friendica\Core\Cache\IMemoryCacheDriver
-        */
-       private $cache;
-
        protected function getInstance()
        {
                $this->cache = CacheDriverFactory::create('database');
index 62f7440033f1db0153133ac5c676eeba88ea110a..db85723af16e41cc967e164c79fc878d3f4a5674 100644 (file)
@@ -11,11 +11,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
  */
 class MemcacheCacheDriverTest extends MemoryCacheTest
 {
-       /**
-        * @var \Friendica\Core\Cache\IMemoryCacheDriver
-        */
-       private $cache;
-
        protected function getInstance()
        {
                $this->cache = CacheDriverFactory::create('memcache');
index 5a07814a383760618ff4ddf9f6e316288119be30..fba5c4a958c4347053305c948b0b40a03db271ff 100644 (file)
@@ -11,11 +11,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
  */
 class MemcachedCacheDriverTest extends MemoryCacheTest
 {
-       /**
-        * @var \Friendica\Core\Cache\IMemoryCacheDriver
-        */
-       private $cache;
-
        protected function getInstance()
        {
                $this->cache = CacheDriverFactory::create('memcached');
index 0f3f6192b232baddca9f797529e32e5384c31364..b6889a65134956f40c52fe8f8e869067bb73ee63 100644 (file)
@@ -11,7 +11,7 @@ abstract class MemoryCacheTest extends CacheTest
         */
        protected $instance;
 
-       function setUp()
+       protected function setUp()
        {
                parent::setUp();
                if (!($this->instance instanceof IMemoryCacheDriver)) {
index 460c1184ba47b5d2c684c8996b9424c43edd69de..0ee73945b9620ac68b3bdd16f201dce67080624d 100644 (file)
@@ -11,11 +11,6 @@ use Friendica\Core\Cache\CacheDriverFactory;
  */
 class RedisCacheDriverTest extends MemoryCacheTest
 {
-       /**
-        * @var \Friendica\Core\Cache\IMemoryCacheDriver
-        */
-       private $cache;
-
        protected function getInstance()
        {
                $this->cache = CacheDriverFactory::create('redis');
index 79e379dcbc71f41d67d894812d39f3d03a3e77a3..290d3ed0428dce6fe98f3725387441cc51d66560 100644 (file)
@@ -205,6 +205,7 @@ CONF;
                $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=admin@friendica.local'));
                $this->assertTrue(putenv('FRIENDICA_TZ=Europe/Berlin'));
                $this->assertTrue(putenv('FRIENDICA_LANG=de'));
+               $this->assertTrue(putenv('FRIENDICA_URL_PATH=/friendica'));
 
                $txt = $this->execute(['autoinstall']);
 
@@ -218,6 +219,7 @@ CONF;
                $this->assertConfig('config', 'admin_email', 'admin@friendica.local');
                $this->assertConfig('system', 'default_timezone', 'Europe/Berlin');
                $this->assertConfig('system', 'language', 'de');
+               $this->assertConfig('system', 'urlpath', '/friendica');
        }
 
        /**
@@ -248,6 +250,9 @@ CONF;
                array_push($args, '--lang');
                array_push($args, 'de');
 
+               array_push($args, '--urlpath');
+               array_push($args, '/friendica');
+
                $txt = $this->execute($args);
 
                $this->assertFinished($txt, true);
@@ -260,13 +265,18 @@ CONF;
                $this->assertConfig('config', 'admin_email', 'admin@friendica.local');
                $this->assertConfig('system', 'default_timezone', 'Europe/Berlin');
                $this->assertConfig('system', 'language', 'de');
+               $this->assertConfig('system', 'urlpath', '/friendica');
        }
 
+       /**
+        * @runTestsInSeparateProcesses
+        */
        public function testNoDatabaseConnection()
        {
-               $this->assertTrue(putenv('MYSQL_USERNAME='));
-               $this->assertTrue(putenv('MYSQL_PASSWORD='));
-               $this->assertTrue(putenv('MYSQL_DATABASE='));
+               $dbaMock = \Mockery::mock('alias:Friendica\Database\DBA');
+               $dbaMock
+                       ->shouldReceive('connected')
+                       ->andReturn(false);
 
                $txt = $this->execute(['autoinstall']);
 
@@ -288,20 +298,21 @@ Notes
     Not checking .htaccess/URL-Rewrite during CLI installation.
 
 Options
-    -h|--help|-?           Show help information
-    -v                     Show more debug information.
-    -a                     All setup checks are required (except .htaccess)
-    -f|--file <config>     prepared config file (e.g. "config/local.ini.php" itself) which will override every other config option - except the environment variables)
-    -s|--savedb            Save the DB credentials to the file (if environment variables is used)
-    -H|--dbhost <host>     The host of the mysql/mariadb database (env MYSQL_HOST)
-    -p|--dbport <port>     The port of the mysql/mariadb database (env MYSQL_PORT)
-    -d|--dbdata <database> The name of the mysql/mariadb database (env MYSQL_DATABASE)
-    -U|--dbuser <username> The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
-    -P|--dbpass <password> The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
-    -b|--phppath <path>    The path of the PHP binary (env FRIENDICA_PHP_PATH) 
-    -A|--admin <mail>      The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL)
-    -T|--tz <timezone>     The timezone of Friendica (env FRIENDICA_TZ)
-    -L|--lang <language>   The language of Friendica (env FRIENDICA_LANG)
+    -h|--help|-?            Show help information
+    -v                      Show more debug information.
+    -a                      All setup checks are required (except .htaccess)
+    -f|--file <config>      prepared config file (e.g. "config/local.ini.php" itself) which will override every other config option - except the environment variables)
+    -s|--savedb             Save the DB credentials to the file (if environment variables is used)
+    -H|--dbhost <host>      The host of the mysql/mariadb database (env MYSQL_HOST)
+    -p|--dbport <port>      The port of the mysql/mariadb database (env MYSQL_PORT)
+    -d|--dbdata <database>  The name of the mysql/mariadb database (env MYSQL_DATABASE)
+    -U|--dbuser <username>  The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
+    -P|--dbpass <password>  The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
+    -u|--urlpath <url_path> The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) 
+    -b|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH) 
+    -A|--admin <mail>       The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL)
+    -T|--tz <timezone>      The timezone of Friendica (env FRIENDICA_TZ)
+    -L|--lang <language>    The language of Friendica (env FRIENDICA_LANG)
  
 Environment variables
    MYSQL_HOST                  The host of the mysql/mariadb database (mandatory if mysql and environment is used)
@@ -309,6 +320,7 @@ Environment variables
    MYSQL_USERNAME|MYSQL_USER   The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb)
    MYSQL_PASSWORD              The password of the mysql/mariadb database login
    MYSQL_DATABASE              The name of the mysql/mariadb database
+   FRIENDICA_URL_PATH          The URL path of Friendica (f.e. '/friendica')
    FRIENDICA_PHP_PATH          The path of the PHP binary
    FRIENDICA_ADMIN_MAIL        The admin email address of Friendica (this email will be used for admin access)
    FRIENDICA_TZ                The timezone of Friendica
index 0cc5c633591b1825f90872776bfa447b078ea522..75f339e8f5ddba2ae15148bbf1a9c7be00c6b536 100644 (file)
@@ -6,12 +6,15 @@ use Friendica\App;
 use Friendica\BaseObject;
 use Friendica\Database\DBA;
 use Friendica\Test\Util\Intercept;
+use Friendica\Test\Util\VFSTrait;
 use org\bovigo\vfs\vfsStream;
 use org\bovigo\vfs\vfsStreamDirectory;
 use PHPUnit\Framework\TestCase;
 
 abstract class ConsoleTest extends TestCase
 {
+       use VFSTrait;
+
        /**
         * @var MultiUseConsole Extension of the basic Friendica Console for testing purpose
         */
@@ -21,11 +24,6 @@ abstract class ConsoleTest extends TestCase
         */
        protected $app;
 
-       /**
-        * @var vfsStreamDirectory The Stream Directory
-        */
-       protected $root;
-
        protected $stdout;
 
        protected function setUp()
@@ -40,6 +38,11 @@ abstract class ConsoleTest extends TestCase
 
                $this->setUpVfsDir();
 
+               // fake console.php for setting an executable
+               vfsStream::newFile('console.php')
+                       ->at($this->root->getChild('bin'))
+                       ->setContent('<? php');
+
                // Reusable App object
                $this->app = new App($this->root->url());
                BaseObject::setApp($this->app);
@@ -47,7 +50,6 @@ abstract class ConsoleTest extends TestCase
        }
 
        public function execute($args) {
-               DBA::disconnect();
                $this->app->reload();
 
                array_unshift($args, $this->getExecutablePath());
@@ -67,41 +69,4 @@ abstract class ConsoleTest extends TestCase
        protected function getExecutablePath() {
                return $this->root->getChild('bin' . DIRECTORY_SEPARATOR . 'console.php')->url();
        }
-
-       private function setUpVfsDir() {
-               // the used directories inside the App class
-               $structure = [
-                       'config' => [],
-                       'bin' => []
-               ];
-
-               // create a virtual directory and copy all needed files and folders to it
-               $this->root = vfsStream::setup('friendica', null, $structure);
-
-               $this->setConfigFile('config.ini.php');
-               $this->setConfigFile('settings.ini.php');
-               $this->setConfigFile('local.ini.php');
-               $this->setConfigFile('dbstructure.json');
-
-               // fake console.php for setting an executable
-               vfsStream::newFile('console.php')
-                       ->at($this->root->getChild('bin'))
-                       ->setContent('<? php');
-       }
-
-       private function setConfigFile($filename)
-       {
-               $file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
-                       '..' . DIRECTORY_SEPARATOR .
-                       '..' . DIRECTORY_SEPARATOR .
-                       '..' . DIRECTORY_SEPARATOR .
-                       'config' . DIRECTORY_SEPARATOR .
-                       $filename;
-
-               if (file_exists($file)) {
-                       vfsStream::newFile($filename)
-                               ->at($this->root->getChild('config'))
-                               ->setContent(file_get_contents($file));
-               }
-       }
 }
diff --git a/tests/src/Core/InstallTest.php b/tests/src/Core/InstallTest.php
new file mode 100644 (file)
index 0000000..da92a0e
--- /dev/null
@@ -0,0 +1,306 @@
+<?php
+
+// this is in the same namespace as Install for mocking 'function_exists'
+namespace Friendica\Core;
+
+use Friendica\Test\Util\VFSTrait;
+use PHPUnit\Framework\TestCase;
+
+class InstallTest extends TestCase
+{
+       use VFSTrait;
+
+       public function setUp()
+       {
+               parent::setUp(); // TODO: Change the autogenerated stub
+
+               $this->setUpVfsDir();
+       }
+
+       private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
+       {
+               $this->assertArraySubset([$position => [
+                       'title' => $title,
+                       'status' => $status,
+                       'required' => $required,
+                       'error_msg' => null,
+                       'help' => $help]
+               ], $assertionArray);
+       }
+
+       /**
+        * Replaces function_exists results with given mocks
+        *
+        * @param array $functions a list from function names and their result
+        */
+       private function setFunctions($functions)
+       {
+               global $phpMock;
+               $phpMock['function_exists'] = function($function) use ($functions) {
+                       foreach ($functions as $name => $value) {
+                               if ($function == $name) {
+                                       return $value;
+                               }
+                       }
+                       return '__phpunit_continue__';
+               };
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testCheckKeys()
+       {
+               $this->setFunctions(['openssl_pkey_new' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkKeys());
+
+               $this->setFunctions(['openssl_pkey_new' => true]);
+               $install = new Install();
+               $this->assertTrue($install->checkKeys());
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testCheckFunctions()
+       {
+               $this->setFunctions(['curl_init' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(3,
+                       L10n::t('libCurl PHP module'),
+                       L10n::t('Error: libCURL PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['imagecreatefromjpeg' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(4,
+                       L10n::t('GD graphics PHP module'),
+                       L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['openssl_public_encrypt' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(5,
+                       L10n::t('OpenSSL PHP module'),
+                       L10n::t('Error: openssl PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['mb_strlen' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(6,
+                       L10n::t('mb_string PHP module'),
+                       L10n::t('Error: mb_string PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['iconv_strlen' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(7,
+                       L10n::t('iconv PHP module'),
+                       L10n::t('Error: iconv PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['posix_kill' => false]);
+               $install = new Install();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(8,
+                       L10n::t('POSIX PHP module'),
+                       L10n::t('Error: POSIX PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions([
+                       'curl_init' => true,
+                       'imagecreatefromjpeg' => true,
+                       'openssl_public_encrypt' => true,
+                       'mb_strlen' => true,
+                       'iconv_strlen' => true,
+                       'posix_kill' => true
+               ]);
+               $install = new Install();
+               $this->assertTrue($install->checkFunctions());
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testCheckLocalIni()
+       {
+               $this->assertTrue($this->root->hasChild('config/local.ini.php'));
+
+               $install = new Install();
+               $this->assertTrue($install->checkLocalIni());
+
+               $this->delConfigFile('local.ini.php');
+
+               $this->assertFalse($this->root->hasChild('config/local.ini.php'));
+
+               $install = new Install();
+               $this->assertTrue($install->checkLocalIni());
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testCheckHtAccessFail()
+       {
+               // Mocking the CURL Response
+               $curlResult = \Mockery::mock('Friendica\Network\CurlResult');
+               $curlResult
+                       ->shouldReceive('getBody')
+                       ->andReturn('not ok');
+               $curlResult
+                       ->shouldReceive('getRedirectUrl')
+                       ->andReturn('');
+               $curlResult
+                       ->shouldReceive('getError')
+                       ->andReturn('test Error');
+
+               // Mocking the CURL Request
+               $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('https://test/install/testrewrite')
+                       ->andReturn($curlResult);
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('http://test/install/testrewrite')
+                       ->andReturn($curlResult);
+
+               // Mocking that we can use CURL
+               $this->setFunctions(['curl_init' => true]);
+
+               // needed because of "normalise_link"
+               require_once __DIR__ . '/../../../include/text.php';
+
+               $install = new Install();
+
+               $this->assertFalse($install->checkHtAccess('https://test', 'https://test'));
+               $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testCheckHtAccessWork()
+       {
+               // Mocking the failed CURL Response
+               $curlResultF = \Mockery::mock('Friendica\Network\CurlResult');
+               $curlResultF
+                       ->shouldReceive('getBody')
+                       ->andReturn('not ok');
+
+               // Mocking the working CURL Response
+               $curlResultW = \Mockery::mock('Friendica\Network\CurlResult');
+               $curlResultW
+                       ->shouldReceive('getBody')
+                       ->andReturn('ok');
+
+               // Mocking the CURL Request
+               $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('https://test/install/testrewrite')
+                       ->andReturn($curlResultF);
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('http://test/install/testrewrite')
+                       ->andReturn($curlResultW);
+
+               // Mocking that we can use CURL
+               $this->setFunctions(['curl_init' => true]);
+
+               // needed because of "normalise_link"
+               require_once __DIR__ . '/../../../include/text.php';
+
+               $install = new Install();
+
+               $this->assertTrue($install->checkHtAccess('https://test', 'https://test'));
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testImagick()
+       {
+               $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
+               $imageMock
+                       ->shouldReceive('supportedTypes')
+                       ->andReturn(['image/gif' => 'gif']);
+
+               $install = new Install();
+
+               // even there is no supported type, Imagick should return true (because it is not required)
+               $this->assertTrue($install->checkImagick());
+               $this->assertCheckExist(1,
+                       L10n::t('ImageMagick supports GIF'),
+                       '',
+                       true,
+                       false,
+                       $install->getChecks());
+       }
+
+       /**
+        * @small
+        * @runInSeparateProcess
+        */
+       public function testImagickNotFound()
+       {
+               $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
+               $imageMock
+                       ->shouldReceive('supportedTypes')
+                       ->andReturn([]);
+
+               $install = new Install();
+
+               // even there is no supported type, Imagick should return true (because it is not required)
+               $this->assertTrue($install->checkImagick());
+               $this->assertCheckExist(1,
+                       L10n::t('ImageMagick supports GIF'),
+                       '',
+                       false,
+                       false,
+                       $install->getChecks());
+       }
+}
+
+/**
+ * A workaround to replace the PHP native function_exists with a mocked function
+ *
+ * @param string $function_name the Name of the function
+ *
+ * @return bool true or false
+ */
+function function_exists($function_name)
+{
+       global $phpMock;
+       if (isset($phpMock['function_exists'])) {
+               $result = call_user_func_array($phpMock['function_exists'], func_get_args());
+               if ($result !== '__phpunit_continue__') {
+                       return $result;
+               }
+       }
+       return call_user_func_array('\function_exists', func_get_args());
+}
diff --git a/tests/src/Network/CurlResultTest.php b/tests/src/Network/CurlResultTest.php
new file mode 100644 (file)
index 0000000..13a14d9
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+
+namespace Friendica\Test\src\Network;
+
+use Friendica\Network\CurlResult;
+use PHPUnit\Framework\TestCase;
+
+class CurlResultTest extends TestCase
+{
+       public function setUp()
+       {
+               parent::setUp();
+
+               require_once __DIR__.'/../../../boot.php';
+               require_once __DIR__.'/../../../include/text.php';
+       }
+
+       /**
+        * @small
+        */
+       public function testNormal()
+       {
+               $header = file_get_contents(__DIR__ . '/../../datasets/curl/about.head');
+               $body = file_get_contents(__DIR__ . '/../../datasets/curl/about.body');
+
+
+               $curlResult = new CurlResult('https://test.local', $header . $body, [
+                       'http_code' => 200,
+                       'content_type' => 'text/html; charset=utf-8',
+                       'url' => 'https://test.local'
+               ]);
+
+               $this->assertTrue($curlResult->isSuccess());
+               $this->assertFalse($curlResult->isTimeout());
+               $this->assertFalse($curlResult->isRedirectUrl());
+               $this->assertSame($header, $curlResult->getHeader());
+               $this->assertSame($body, $curlResult->getBody());
+               $this->assertSame('text/html; charset=utf-8', $curlResult->getContentType());
+               $this->assertSame('https://test.local', $curlResult->getUrl());
+               $this->assertSame('https://test.local', $curlResult->getRedirectUrl());
+       }
+
+       /**
+        * @small
+        */
+       public function testRedirect()
+       {
+               $header = file_get_contents(__DIR__ . '/../../datasets/curl/about.head');
+               $body = file_get_contents(__DIR__ . '/../../datasets/curl/about.body');
+
+
+               $curlResult = new CurlResult('https://test.local/test/it', $header . $body, [
+                       'http_code' => 301,
+                       'content_type' => 'text/html; charset=utf-8',
+                       'url' => 'https://test.local/test/it',
+                       'redirect_url' => 'https://test.other'
+               ]);
+
+               $this->assertTrue($curlResult->isSuccess());
+               $this->assertFalse($curlResult->isTimeout());
+               $this->assertTrue($curlResult->isRedirectUrl());
+               $this->assertSame($header, $curlResult->getHeader());
+               $this->assertSame($body, $curlResult->getBody());
+               $this->assertSame('text/html; charset=utf-8', $curlResult->getContentType());
+               $this->assertSame('https://test.local/test/it', $curlResult->getUrl());
+               $this->assertSame('https://test.other/test/it', $curlResult->getRedirectUrl());
+       }
+
+       /**
+        * @small
+        */
+       public function testTimeout()
+       {
+               $header = file_get_contents(__DIR__ . '/../../datasets/curl/about.head');
+               $body = file_get_contents(__DIR__ . '/../../datasets/curl/about.body');
+
+
+               $curlResult = new CurlResult('https://test.local/test/it', $header . $body, [
+                       'http_code' => 500,
+                       'content_type' => 'text/html; charset=utf-8',
+                       'url' => 'https://test.local/test/it',
+                       'redirect_url' => 'https://test.other'
+               ], CURLE_OPERATION_TIMEDOUT, 'Tested error');
+
+               $this->assertFalse($curlResult->isSuccess());
+               $this->assertTrue($curlResult->isTimeout());
+               $this->assertFalse($curlResult->isRedirectUrl());
+               $this->assertSame($header, $curlResult->getHeader());
+               $this->assertSame($body, $curlResult->getBody());
+               $this->assertSame('text/html; charset=utf-8', $curlResult->getContentType());
+               $this->assertSame('https://test.local/test/it', $curlResult->getRedirectUrl());
+               $this->assertSame('Tested error', $curlResult->getError());
+       }
+
+       /**
+        * @small
+        */
+       public function testRedirectHeader()
+       {
+               $header = file_get_contents(__DIR__ . '/../../datasets/curl/about.redirect');
+               $body = file_get_contents(__DIR__ . '/../../datasets/curl/about.body');
+
+
+               $curlResult = new CurlResult('https://test.local/test/it?key=value', $header . $body, [
+                       'http_code' => 301,
+                       'content_type' => 'text/html; charset=utf-8',
+                       'url' => 'https://test.local/test/it?key=value',
+               ]);
+
+               $this->assertTrue($curlResult->isSuccess());
+               $this->assertFalse($curlResult->isTimeout());
+               $this->assertTrue($curlResult->isRedirectUrl());
+               $this->assertSame($header, $curlResult->getHeader());
+               $this->assertSame($body, $curlResult->getBody());
+               $this->assertSame('text/html; charset=utf-8', $curlResult->getContentType());
+               $this->assertSame('https://test.local/test/it?key=value', $curlResult->getUrl());
+               $this->assertSame('https://test.other/some/?key=value', $curlResult->getRedirectUrl());
+       }
+}
index 0495cbb86c5f0b89a7795f337b4e53f049feadfc..c27fb25627bf58611e4c12f336219ac59dd773ed 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-25 15:34+0000\n"
+"POT-Creation-Date: 2018-09-27 21:18+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,47 +18,47 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 
 
-#: index.php:261 mod/apps.php:14
+#: index.php:265 mod/apps.php:14
 msgid "You must be logged in to use addons. "
 msgstr ""
 
-#: index.php:308 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
+#: index.php:312 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
 #: mod/help.php:62
 msgid "Not Found"
 msgstr ""
 
-#: index.php:313 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
+#: index.php:317 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
 #: mod/cal.php:44
 msgid "Page not found."
 msgstr ""
 
-#: index.php:431 mod/group.php:83 mod/profperm.php:29
+#: index.php:435 mod/group.php:83 mod/profperm.php:29
 msgid "Permission denied"
 msgstr ""
 
-#: index.php:432 include/items.php:412 mod/crepair.php:100
+#: index.php:436 include/items.php:413 mod/crepair.php:100
 #: mod/wallmessage.php:16 mod/wallmessage.php:40 mod/wallmessage.php:79
-#: mod/wallmessage.php:103 mod/dfrn_confirm.php:66 mod/dirfind.php:27
+#: mod/wallmessage.php:103 mod/dfrn_confirm.php:67 mod/dirfind.php:27
 #: mod/manage.php:131 mod/settings.php:43 mod/settings.php:149
 #: mod/settings.php:665 mod/common.php:28 mod/network.php:34 mod/group.php:26
 #: mod/delegate.php:27 mod/delegate.php:45 mod/delegate.php:56
-#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:17
-#: mod/unfollow.php:59 mod/unfollow.php:93 mod/register.php:53
+#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:20
+#: mod/unfollow.php:73 mod/unfollow.php:105 mod/register.php:53
 #: mod/notifications.php:67 mod/message.php:60 mod/message.php:105
 #: mod/ostatus_subscribe.php:17 mod/nogroup.php:23 mod/suggest.php:61
 #: mod/wall_upload.php:104 mod/wall_upload.php:107 mod/api.php:35
 #: mod/api.php:40 mod/profile_photo.php:29 mod/profile_photo.php:176
 #: mod/profile_photo.php:198 mod/wall_attach.php:80 mod/wall_attach.php:83
-#: mod/item.php:166 mod/uimport.php:28 mod/cal.php:306 mod/regmod.php:108
+#: mod/item.php:166 mod/uimport.php:15 mod/cal.php:306 mod/regmod.php:108
 #: mod/editpost.php:19 mod/fsuggest.php:80 mod/allfriends.php:23
-#: mod/contacts.php:381 mod/events.php:193 mod/follow.php:54 mod/follow.php:118
-#: mod/attach.php:39 mod/poke.php:145 mod/invite.php:21 mod/invite.php:112
+#: mod/contacts.php:387 mod/events.php:195 mod/follow.php:54 mod/follow.php:118
+#: mod/attach.php:39 mod/poke.php:144 mod/invite.php:21 mod/invite.php:112
 #: mod/notes.php:32 mod/profiles.php:179 mod/profiles.php:511
-#: mod/photos.php:183 mod/photos.php:1065
+#: mod/photos.php:183 mod/photos.php:1067
 msgid "Permission denied."
 msgstr ""
 
-#: index.php:460
+#: index.php:464
 msgid "toggle mobile"
 msgstr ""
 
@@ -92,13 +92,13 @@ msgstr ""
 
 #: view/theme/duepuntozero/config.php:71 view/theme/quattro/config.php:73
 #: view/theme/vier/config.php:119 view/theme/frio/config.php:118
-#: mod/crepair.php:150 mod/install.php:206 mod/install.php:244
+#: mod/crepair.php:150 mod/install.php:204 mod/install.php:242
 #: mod/manage.php:184 mod/message.php:264 mod/message.php:430
-#: mod/fsuggest.php:114 mod/contacts.php:630 mod/events.php:533
-#: mod/localtime.php:56 mod/poke.php:195 mod/invite.php:155
-#: mod/profiles.php:577 mod/photos.php:1094 mod/photos.php:1180
-#: mod/photos.php:1452 mod/photos.php:1497 mod/photos.php:1536
-#: mod/photos.php:1596 src/Object/Post.php:795
+#: mod/fsuggest.php:114 mod/contacts.php:631 mod/events.php:560
+#: mod/localtime.php:56 mod/poke.php:194 mod/invite.php:155
+#: mod/profiles.php:577 mod/photos.php:1096 mod/photos.php:1182
+#: mod/photos.php:1454 mod/photos.php:1499 mod/photos.php:1538
+#: mod/photos.php:1598 src/Object/Post.php:795
 msgid "Submit"
 msgstr ""
 
@@ -186,8 +186,8 @@ msgstr ""
 
 #: view/theme/vier/theme.php:199 include/conversation.php:881
 #: mod/dirfind.php:231 mod/match.php:90 mod/suggest.php:86
-#: mod/allfriends.php:76 mod/contacts.php:604 mod/contacts.php:610
-#: mod/follow.php:143 src/Model/Contact.php:933 src/Content/Widget.php:61
+#: mod/allfriends.php:76 mod/contacts.php:611 mod/follow.php:143
+#: src/Model/Contact.php:944 src/Content/Widget.php:61
 msgid "Connect/Follow"
 msgstr ""
 
@@ -195,7 +195,7 @@ msgstr ""
 msgid "Examples: Robert Morgenstein, Fishing"
 msgstr ""
 
-#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:842
+#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:845
 #: src/Content/Widget.php:63
 msgid "Find"
 msgstr ""
@@ -226,16 +226,16 @@ msgid "Local Directory"
 msgstr ""
 
 #: view/theme/vier/theme.php:251 include/text.php:909 src/Content/Nav.php:151
-#: src/Content/ForumManager.php:125
+#: src/Content/ForumManager.php:130
 msgid "Forums"
 msgstr ""
 
-#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:127
+#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:132
 msgid "External link to forum"
 msgstr ""
 
-#: view/theme/vier/theme.php:256 include/items.php:489 src/Object/Post.php:429
-#: src/App.php:786 src/Content/Widget.php:310 src/Content/ForumManager.php:130
+#: view/theme/vier/theme.php:256 include/items.php:490 src/Object/Post.php:429
+#: src/App.php:799 src/Content/Widget.php:307 src/Content/ForumManager.php:135
 msgid "show more"
 msgstr ""
 
@@ -320,8 +320,8 @@ msgstr ""
 msgid "End this session"
 msgstr ""
 
-#: view/theme/frio/theme.php:269 mod/contacts.php:689 mod/contacts.php:877
-#: src/Model/Profile.php:875 src/Content/Nav.php:100
+#: view/theme/frio/theme.php:269 mod/contacts.php:690 mod/contacts.php:880
+#: src/Model/Profile.php:888 src/Content/Nav.php:100
 msgid "Status"
 msgstr ""
 
@@ -331,8 +331,8 @@ msgid "Your posts and conversations"
 msgstr ""
 
 #: view/theme/frio/theme.php:270 mod/newmember.php:24 mod/profperm.php:116
-#: mod/contacts.php:691 mod/contacts.php:893 src/Model/Profile.php:717
-#: src/Model/Profile.php:850 src/Model/Profile.php:883 src/Content/Nav.php:101
+#: mod/contacts.php:692 mod/contacts.php:896 src/Model/Profile.php:730
+#: src/Model/Profile.php:863 src/Model/Profile.php:896 src/Content/Nav.php:101
 msgid "Profile"
 msgstr ""
 
@@ -340,7 +340,7 @@ msgstr ""
 msgid "Your profile page"
 msgstr ""
 
-#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:891
+#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:904
 #: src/Content/Nav.php:102
 msgid "Photos"
 msgstr ""
@@ -349,8 +349,8 @@ msgstr ""
 msgid "Your photos"
 msgstr ""
 
-#: view/theme/frio/theme.php:272 src/Model/Profile.php:899
-#: src/Model/Profile.php:902 src/Content/Nav.php:103
+#: view/theme/frio/theme.php:272 src/Model/Profile.php:912
+#: src/Model/Profile.php:915 src/Content/Nav.php:103
 msgid "Videos"
 msgstr ""
 
@@ -359,7 +359,7 @@ msgid "Your videos"
 msgstr ""
 
 #: view/theme/frio/theme.php:273 view/theme/frio/theme.php:277 mod/cal.php:276
-#: mod/events.php:390 src/Model/Profile.php:911 src/Model/Profile.php:922
+#: mod/events.php:391 src/Model/Profile.php:924 src/Model/Profile.php:935
 #: src/Content/Nav.php:104 src/Content/Nav.php:170
 msgid "Events"
 msgstr ""
@@ -377,8 +377,8 @@ msgstr ""
 msgid "Conversations from your friends"
 msgstr ""
 
-#: view/theme/frio/theme.php:277 src/Model/Profile.php:914
-#: src/Model/Profile.php:925 src/Content/Nav.php:170
+#: view/theme/frio/theme.php:277 src/Model/Profile.php:927
+#: src/Model/Profile.php:938 src/Content/Nav.php:170
 msgid "Events and Calendar"
 msgstr ""
 
@@ -400,8 +400,8 @@ msgid "Account settings"
 msgstr ""
 
 #: view/theme/frio/theme.php:280 include/text.php:906 mod/viewcontacts.php:125
-#: mod/contacts.php:836 mod/contacts.php:905 src/Model/Profile.php:954
-#: src/Model/Profile.php:957 src/Content/Nav.php:147 src/Content/Nav.php:213
+#: mod/contacts.php:839 mod/contacts.php:908 src/Model/Profile.php:967
+#: src/Model/Profile.php:970 src/Content/Nav.php:147 src/Content/Nav.php:213
 msgid "Contacts"
 msgstr ""
 
@@ -459,37 +459,37 @@ msgstr ""
 msgid "%s: Updating post-type."
 msgstr ""
 
-#: include/items.php:355 mod/display.php:70 mod/display.php:245
-#: mod/display.php:341 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
+#: include/items.php:356 mod/display.php:71 mod/display.php:254
+#: mod/display.php:350 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
 #: mod/notice.php:22 mod/viewsrc.php:22
 msgid "Item not found."
 msgstr ""
 
-#: include/items.php:393
+#: include/items.php:394
 msgid "Do you really want to delete this item?"
 msgstr ""
 
-#: include/items.php:395 mod/settings.php:1100 mod/settings.php:1106
+#: include/items.php:396 mod/settings.php:1100 mod/settings.php:1106
 #: mod/settings.php:1113 mod/settings.php:1117 mod/settings.php:1121
 #: mod/settings.php:1125 mod/settings.php:1129 mod/settings.php:1133
 #: mod/settings.php:1153 mod/settings.php:1154 mod/settings.php:1155
 #: mod/settings.php:1156 mod/settings.php:1157 mod/register.php:237
 #: mod/message.php:154 mod/suggest.php:40 mod/dfrn_request.php:645
-#: mod/api.php:110 mod/contacts.php:465 mod/follow.php:150 mod/profiles.php:541
+#: mod/api.php:110 mod/contacts.php:471 mod/follow.php:150 mod/profiles.php:541
 #: mod/profiles.php:544 mod/profiles.php:566
 msgid "Yes"
 msgstr ""
 
-#: include/items.php:398 include/conversation.php:1179 mod/videos.php:146
-#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:120
+#: include/items.php:399 include/conversation.php:1179 mod/videos.php:146
+#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:130
 #: mod/message.php:157 mod/tagrm.php:19 mod/tagrm.php:91 mod/suggest.php:43
-#: mod/dfrn_request.php:655 mod/editpost.php:140 mod/contacts.php:468
+#: mod/dfrn_request.php:655 mod/editpost.php:146 mod/contacts.php:474
 #: mod/follow.php:161 mod/fbrowser.php:104 mod/fbrowser.php:135
 #: mod/photos.php:255 mod/photos.php:327
 msgid "Cancel"
 msgstr ""
 
-#: include/items.php:483 src/Content/Feature.php:96
+#: include/items.php:484 src/Content/Feature.php:96
 msgid "Archives"
 msgstr ""
 
@@ -558,35 +558,35 @@ msgstr ""
 msgid "%1$s marked %2$s's %3$s as favorite"
 msgstr ""
 
-#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1509
 msgid "Likes"
 msgstr ""
 
-#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1509
 msgid "Dislikes"
 msgstr ""
 
 #: include/conversation.php:546 include/conversation.php:1492
-#: mod/photos.php:1508
+#: mod/photos.php:1510
 msgid "Attending"
 msgid_plural "Attending"
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Not attending"
 msgstr ""
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Might attend"
 msgstr ""
 
-#: include/conversation.php:626 mod/photos.php:1564 src/Object/Post.php:195
+#: include/conversation.php:626 mod/photos.php:1566 src/Object/Post.php:195
 msgid "Select"
 msgstr ""
 
 #: include/conversation.php:627 mod/settings.php:736 mod/admin.php:1906
-#: mod/contacts.php:852 mod/contacts.php:1130 mod/photos.php:1565
+#: mod/contacts.php:855 mod/contacts.php:1133 mod/photos.php:1567
 msgid "Delete"
 msgstr ""
 
@@ -614,7 +614,7 @@ msgstr ""
 
 #: include/conversation.php:698 include/conversation.php:1160
 #: mod/wallmessage.php:145 mod/message.php:263 mod/message.php:431
-#: mod/editpost.php:115 mod/photos.php:1480 src/Object/Post.php:401
+#: mod/editpost.php:121 mod/photos.php:1482 src/Object/Post.php:401
 msgid "Please wait"
 msgstr ""
 
@@ -626,36 +626,36 @@ msgstr ""
 msgid "Delete Selected Items"
 msgstr ""
 
-#: include/conversation.php:867 src/Model/Contact.php:937
+#: include/conversation.php:867 src/Model/Contact.php:948
 msgid "View Status"
 msgstr ""
 
 #: include/conversation.php:868 include/conversation.php:884
 #: mod/dirfind.php:230 mod/directory.php:164 mod/match.php:89
-#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:877
-#: src/Model/Contact.php:930 src/Model/Contact.php:938
+#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:888
+#: src/Model/Contact.php:941 src/Model/Contact.php:949
 msgid "View Profile"
 msgstr ""
 
-#: include/conversation.php:869 src/Model/Contact.php:939
+#: include/conversation.php:869 src/Model/Contact.php:950
 msgid "View Photos"
 msgstr ""
 
-#: include/conversation.php:870 src/Model/Contact.php:931
-#: src/Model/Contact.php:940
+#: include/conversation.php:870 src/Model/Contact.php:942
+#: src/Model/Contact.php:951
 msgid "Network Posts"
 msgstr ""
 
-#: include/conversation.php:871 src/Model/Contact.php:932
-#: src/Model/Contact.php:941
+#: include/conversation.php:871 src/Model/Contact.php:943
+#: src/Model/Contact.php:952
 msgid "View Contact"
 msgstr ""
 
-#: include/conversation.php:872 src/Model/Contact.php:943
+#: include/conversation.php:872 src/Model/Contact.php:954
 msgid "Send PM"
 msgstr ""
 
-#: include/conversation.php:876 src/Model/Contact.php:944
+#: include/conversation.php:876 src/Model/Contact.php:955
 msgid "Poke"
 msgstr ""
 
@@ -786,85 +786,85 @@ msgid "Share"
 msgstr ""
 
 #: include/conversation.php:1142 mod/wallmessage.php:143 mod/message.php:261
-#: mod/message.php:428 mod/editpost.php:101
+#: mod/message.php:428 mod/editpost.php:107
 msgid "Upload photo"
 msgstr ""
 
-#: include/conversation.php:1143 mod/editpost.php:102
+#: include/conversation.php:1143 mod/editpost.php:108
 msgid "upload photo"
 msgstr ""
 
-#: include/conversation.php:1144 mod/editpost.php:103
+#: include/conversation.php:1144 mod/editpost.php:109
 msgid "Attach file"
 msgstr ""
 
-#: include/conversation.php:1145 mod/editpost.php:104
+#: include/conversation.php:1145 mod/editpost.php:110
 msgid "attach file"
 msgstr ""
 
 #: include/conversation.php:1146 mod/wallmessage.php:144 mod/message.php:262
-#: mod/message.php:429 mod/editpost.php:105
+#: mod/message.php:429 mod/editpost.php:111
 msgid "Insert web link"
 msgstr ""
 
-#: include/conversation.php:1147 mod/editpost.php:106
+#: include/conversation.php:1147 mod/editpost.php:112
 msgid "web link"
 msgstr ""
 
-#: include/conversation.php:1148 mod/editpost.php:107
+#: include/conversation.php:1148 mod/editpost.php:113
 msgid "Insert video link"
 msgstr ""
 
-#: include/conversation.php:1149 mod/editpost.php:108
+#: include/conversation.php:1149 mod/editpost.php:114
 msgid "video link"
 msgstr ""
 
-#: include/conversation.php:1150 mod/editpost.php:109
+#: include/conversation.php:1150 mod/editpost.php:115
 msgid "Insert audio link"
 msgstr ""
 
-#: include/conversation.php:1151 mod/editpost.php:110
+#: include/conversation.php:1151 mod/editpost.php:116
 msgid "audio link"
 msgstr ""
 
-#: include/conversation.php:1152 mod/editpost.php:111
+#: include/conversation.php:1152 mod/editpost.php:117
 msgid "Set your location"
 msgstr ""
 
-#: include/conversation.php:1153 mod/editpost.php:112
+#: include/conversation.php:1153 mod/editpost.php:118
 msgid "set location"
 msgstr ""
 
-#: include/conversation.php:1154 mod/editpost.php:113
+#: include/conversation.php:1154 mod/editpost.php:119
 msgid "Clear browser location"
 msgstr ""
 
-#: include/conversation.php:1155 mod/editpost.php:114
+#: include/conversation.php:1155 mod/editpost.php:120
 msgid "clear location"
 msgstr ""
 
-#: include/conversation.php:1157 mod/editpost.php:129
+#: include/conversation.php:1157 mod/editpost.php:135
 msgid "Set title"
 msgstr ""
 
-#: include/conversation.php:1159 mod/editpost.php:131
+#: include/conversation.php:1159 mod/editpost.php:137
 msgid "Categories (comma-separated list)"
 msgstr ""
 
-#: include/conversation.php:1161 mod/editpost.php:116
+#: include/conversation.php:1161 mod/editpost.php:122
 msgid "Permission settings"
 msgstr ""
 
-#: include/conversation.php:1162 mod/editpost.php:146
+#: include/conversation.php:1162 mod/editpost.php:152
 msgid "permissions"
 msgstr ""
 
-#: include/conversation.php:1171 mod/editpost.php:126
+#: include/conversation.php:1171 mod/editpost.php:132
 msgid "Public post"
 msgstr ""
 
-#: include/conversation.php:1175 mod/editpost.php:137 mod/events.php:531
-#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
+#: include/conversation.php:1175 mod/editpost.php:143 mod/events.php:558
+#: mod/photos.php:1500 mod/photos.php:1539 mod/photos.php:1599
 #: src/Object/Post.php:804
 msgid "Preview"
 msgstr ""
@@ -881,11 +881,11 @@ msgstr ""
 msgid "Private post"
 msgstr ""
 
-#: include/conversation.php:1191 mod/editpost.php:144 src/Model/Profile.php:344
+#: include/conversation.php:1191 mod/editpost.php:150 src/Model/Profile.php:357
 msgid "Message"
 msgstr ""
 
-#: include/conversation.php:1192 mod/editpost.php:145
+#: include/conversation.php:1192 mod/editpost.php:151
 msgid "Browser"
 msgstr ""
 
@@ -911,7 +911,7 @@ msgid_plural "Not Attending"
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/conversation.php:1498 src/Content/ContactSelector.php:122
+#: include/conversation.php:1498 src/Content/ContactSelector.php:127
 msgid "Undecided"
 msgid_plural "Undecided"
 msgstr[0] ""
@@ -1276,7 +1276,7 @@ msgstr[1] ""
 msgid "View Contacts"
 msgstr ""
 
-#: include/text.php:889 mod/filer.php:35 mod/editpost.php:100 mod/notes.php:54
+#: include/text.php:889 mod/filer.php:35 mod/editpost.php:106 mod/notes.php:54
 msgid "Save"
 msgstr ""
 
@@ -1349,132 +1349,132 @@ msgstr ""
 msgid "rebuffed"
 msgstr ""
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:389
 msgid "Monday"
 msgstr ""
 
-#: include/text.php:972 src/Model/Event.php:389
+#: include/text.php:972 src/Model/Event.php:390
 msgid "Tuesday"
 msgstr ""
 
-#: include/text.php:972 src/Model/Event.php:390
+#: include/text.php:972 src/Model/Event.php:391
 msgid "Wednesday"
 msgstr ""
 
-#: include/text.php:972 src/Model/Event.php:391
+#: include/text.php:972 src/Model/Event.php:392
 msgid "Thursday"
 msgstr ""
 
-#: include/text.php:972 src/Model/Event.php:392
+#: include/text.php:972 src/Model/Event.php:393
 msgid "Friday"
 msgstr ""
 
-#: include/text.php:972 src/Model/Event.php:393
+#: include/text.php:972 src/Model/Event.php:394
 msgid "Saturday"
 msgstr ""
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:387
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
 msgid "Sunday"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:408
+#: include/text.php:976 src/Model/Event.php:409
 msgid "January"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:409
+#: include/text.php:976 src/Model/Event.php:410
 msgid "February"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:410
+#: include/text.php:976 src/Model/Event.php:411
 msgid "March"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:411
+#: include/text.php:976 src/Model/Event.php:412
 msgid "April"
 msgstr ""
 
-#: include/text.php:976 include/text.php:993 src/Model/Event.php:399
-#: src/Model/Event.php:412
+#: include/text.php:976 include/text.php:993 src/Model/Event.php:400
+#: src/Model/Event.php:413
 msgid "May"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:413
+#: include/text.php:976 src/Model/Event.php:414
 msgid "June"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:414
+#: include/text.php:976 src/Model/Event.php:415
 msgid "July"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:415
+#: include/text.php:976 src/Model/Event.php:416
 msgid "August"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:416
+#: include/text.php:976 src/Model/Event.php:417
 msgid "September"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:417
+#: include/text.php:976 src/Model/Event.php:418
 msgid "October"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:418
+#: include/text.php:976 src/Model/Event.php:419
 msgid "November"
 msgstr ""
 
-#: include/text.php:976 src/Model/Event.php:419
+#: include/text.php:976 src/Model/Event.php:420
 msgid "December"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:380
+#: include/text.php:990 src/Model/Event.php:381
 msgid "Mon"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:381
+#: include/text.php:990 src/Model/Event.php:382
 msgid "Tue"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:382
+#: include/text.php:990 src/Model/Event.php:383
 msgid "Wed"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:383
+#: include/text.php:990 src/Model/Event.php:384
 msgid "Thu"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:384
+#: include/text.php:990 src/Model/Event.php:385
 msgid "Fri"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:385
+#: include/text.php:990 src/Model/Event.php:386
 msgid "Sat"
 msgstr ""
 
-#: include/text.php:990 src/Model/Event.php:379
+#: include/text.php:990 src/Model/Event.php:380
 msgid "Sun"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:395
+#: include/text.php:993 src/Model/Event.php:396
 msgid "Jan"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:396
+#: include/text.php:993 src/Model/Event.php:397
 msgid "Feb"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:397
+#: include/text.php:993 src/Model/Event.php:398
 msgid "Mar"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:398
+#: include/text.php:993 src/Model/Event.php:399
 msgid "Apr"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:401
+#: include/text.php:993 src/Model/Event.php:402
 msgid "Jul"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:402
+#: include/text.php:993 src/Model/Event.php:403
 msgid "Aug"
 msgstr ""
 
@@ -1482,15 +1482,15 @@ msgstr ""
 msgid "Sep"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:404
+#: include/text.php:993 src/Model/Event.php:405
 msgid "Oct"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:405
+#: include/text.php:993 src/Model/Event.php:406
 msgid "Nov"
 msgstr ""
 
-#: include/text.php:993 src/Model/Event.php:406
+#: include/text.php:993 src/Model/Event.php:407
 msgid "Dec"
 msgstr ""
 
@@ -1499,7 +1499,7 @@ msgstr ""
 msgid "Content warning: %s"
 msgstr ""
 
-#: include/text.php:1204 mod/videos.php:375
+#: include/text.php:1204 mod/videos.php:376
 msgid "View Video"
 msgstr ""
 
@@ -1519,7 +1519,7 @@ msgstr ""
 msgid "view on separate page"
 msgstr ""
 
-#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:609
+#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:616
 msgid "link to source"
 msgstr ""
 
@@ -1541,30 +1541,30 @@ msgstr ""
 msgid "Item filed"
 msgstr ""
 
-#: include/api.php:1138
+#: include/api.php:1140
 #, php-format
 msgid "Daily posting limit of %d post reached. The post was rejected."
 msgid_plural "Daily posting limit of %d posts reached. The post was rejected."
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/api.php:1152
+#: include/api.php:1154
 #, php-format
 msgid "Weekly posting limit of %d post reached. The post was rejected."
 msgid_plural "Weekly posting limit of %d posts reached. The post was rejected."
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/api.php:1166
+#: include/api.php:1168
 #, php-format
 msgid "Monthly posting limit of %d post reached. The post was rejected."
 msgstr ""
 
-#: include/api.php:4233 mod/profile_photo.php:84 mod/profile_photo.php:93
+#: include/api.php:4240 mod/profile_photo.php:84 mod/profile_photo.php:93
 #: mod/profile_photo.php:102 mod/profile_photo.php:211
 #: mod/profile_photo.php:300 mod/profile_photo.php:310 mod/photos.php:90
-#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1169
-#: mod/photos.php:1186 mod/photos.php:1678 src/Model/User.php:595
+#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1171
+#: mod/photos.php:1188 mod/photos.php:1680 src/Model/User.php:595
 #: src/Model/User.php:603 src/Model/User.php:611
 msgid "Profile Photos"
 msgstr ""
@@ -1578,7 +1578,7 @@ msgid "Contact update failed."
 msgstr ""
 
 #: mod/crepair.php:112 mod/redir.php:29 mod/redir.php:127
-#: mod/dfrn_confirm.php:127 mod/fsuggest.php:30 mod/fsuggest.php:96
+#: mod/dfrn_confirm.php:128 mod/fsuggest.php:30 mod/fsuggest.php:96
 msgid "Contact not found."
 msgstr ""
 
@@ -1719,143 +1719,143 @@ msgstr ""
 msgid "Your message:"
 msgstr ""
 
-#: mod/lockview.php:42 mod/lockview.php:50
+#: mod/lockview.php:46 mod/lockview.php:57
 msgid "Remote privacy information not available."
 msgstr ""
 
-#: mod/lockview.php:59
+#: mod/lockview.php:66
 msgid "Visible to:"
 msgstr ""
 
-#: mod/install.php:100
+#: mod/install.php:98
 msgid "Friendica Communications Server - Setup"
 msgstr ""
 
-#: mod/install.php:106
+#: mod/install.php:104
 msgid "Could not connect to database."
 msgstr ""
 
-#: mod/install.php:110
+#: mod/install.php:108
 msgid "Could not create table."
 msgstr ""
 
-#: mod/install.php:116
+#: mod/install.php:114
 msgid "Your Friendica site database has been installed."
 msgstr ""
 
-#: mod/install.php:121
+#: mod/install.php:119
 msgid ""
 "You may need to import the file \"database.sql\" manually using phpmyadmin "
 "or mysql."
 msgstr ""
 
-#: mod/install.php:122 mod/install.php:166 mod/install.php:274
+#: mod/install.php:120 mod/install.php:164 mod/install.php:272
 msgid "Please see the file \"INSTALL.txt\"."
 msgstr ""
 
-#: mod/install.php:134
+#: mod/install.php:132
 msgid "Database already in use."
 msgstr ""
 
-#: mod/install.php:163
+#: mod/install.php:161
 msgid "System check"
 msgstr ""
 
-#: mod/install.php:167 mod/cal.php:279 mod/events.php:394
+#: mod/install.php:165 mod/cal.php:279 mod/events.php:395
 msgid "Next"
 msgstr ""
 
-#: mod/install.php:168
+#: mod/install.php:166
 msgid "Check again"
 msgstr ""
 
-#: mod/install.php:187
+#: mod/install.php:185
 msgid "Database connection"
 msgstr ""
 
-#: mod/install.php:188
+#: mod/install.php:186
 msgid ""
 "In order to install Friendica we need to know how to connect to your "
 "database."
 msgstr ""
 
-#: mod/install.php:189
+#: mod/install.php:187
 msgid ""
 "Please contact your hosting provider or site administrator if you have "
 "questions about these settings."
 msgstr ""
 
-#: mod/install.php:190
+#: mod/install.php:188
 msgid ""
 "The database you specify below should already exist. If it does not, please "
 "create it before continuing."
 msgstr ""
 
-#: mod/install.php:194
+#: mod/install.php:192
 msgid "Database Server Name"
 msgstr ""
 
-#: mod/install.php:195
+#: mod/install.php:193
 msgid "Database Login Name"
 msgstr ""
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "Database Login Password"
 msgstr ""
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "For security reasons the password must not be empty"
 msgstr ""
 
-#: mod/install.php:197
+#: mod/install.php:195
 msgid "Database Name"
 msgstr ""
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid "Site administrator email address"
 msgstr ""
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid ""
 "Your account email address must match this in order to use the web admin "
 "panel."
 msgstr ""
 
-#: mod/install.php:200 mod/install.php:238
+#: mod/install.php:198 mod/install.php:236
 msgid "Please select a default timezone for your website"
 msgstr ""
 
-#: mod/install.php:225
+#: mod/install.php:223
 msgid "Site settings"
 msgstr ""
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid "System Language:"
 msgstr ""
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid ""
 "Set the default language for your Friendica installation interface and to "
 "send emails."
 msgstr ""
 
-#: mod/install.php:255
+#: mod/install.php:253
 msgid ""
 "The database configuration file \"config/local.ini.php\" could not be "
 "written. Please use the enclosed text to create a configuration file in your "
 "web server root."
 msgstr ""
 
-#: mod/install.php:272
+#: mod/install.php:270
 msgid "<h1>What next</h1>"
 msgstr ""
 
-#: mod/install.php:273
+#: mod/install.php:271
 msgid ""
 "IMPORTANT: You will need to [manually] setup a scheduled task for the worker."
 msgstr ""
 
-#: mod/install.php:276
+#: mod/install.php:274
 #, php-format
 msgid ""
 "Go to your new Friendica node <a href=\"%s/register\">registration page</a> "
@@ -1863,82 +1863,82 @@ msgid ""
 "administrator email. This will allow you to enter the site admin panel."
 msgstr ""
 
-#: mod/dfrn_confirm.php:72 mod/profiles.php:38 mod/profiles.php:148
+#: mod/dfrn_confirm.php:73 mod/profiles.php:38 mod/profiles.php:148
 #: mod/profiles.php:193 mod/profiles.php:523
 msgid "Profile not found."
 msgstr ""
 
-#: mod/dfrn_confirm.php:128
+#: mod/dfrn_confirm.php:129
 msgid ""
 "This may occasionally happen if contact was requested by both persons and it "
 "has already been approved."
 msgstr ""
 
-#: mod/dfrn_confirm.php:238
+#: mod/dfrn_confirm.php:239
 msgid "Response from remote site was not understood."
 msgstr ""
 
-#: mod/dfrn_confirm.php:245 mod/dfrn_confirm.php:251
+#: mod/dfrn_confirm.php:246 mod/dfrn_confirm.php:252
 msgid "Unexpected response from remote site: "
 msgstr ""
 
-#: mod/dfrn_confirm.php:260
+#: mod/dfrn_confirm.php:261
 msgid "Confirmation completed successfully."
 msgstr ""
 
-#: mod/dfrn_confirm.php:272
+#: mod/dfrn_confirm.php:273
 msgid "Temporary failure. Please wait and try again."
 msgstr ""
 
-#: mod/dfrn_confirm.php:275
+#: mod/dfrn_confirm.php:276
 msgid "Introduction failed or was revoked."
 msgstr ""
 
-#: mod/dfrn_confirm.php:280
+#: mod/dfrn_confirm.php:281
 msgid "Remote site reported: "
 msgstr ""
 
-#: mod/dfrn_confirm.php:392
+#: mod/dfrn_confirm.php:382
 msgid "Unable to set contact photo."
 msgstr ""
 
-#: mod/dfrn_confirm.php:450
+#: mod/dfrn_confirm.php:444
 #, php-format
 msgid "No user record found for '%s' "
 msgstr ""
 
-#: mod/dfrn_confirm.php:460
+#: mod/dfrn_confirm.php:454
 msgid "Our site encryption key is apparently messed up."
 msgstr ""
 
-#: mod/dfrn_confirm.php:471
+#: mod/dfrn_confirm.php:465
 msgid "Empty site URL was provided or URL could not be decrypted by us."
 msgstr ""
 
-#: mod/dfrn_confirm.php:487
+#: mod/dfrn_confirm.php:481
 msgid "Contact record was not found for you on our site."
 msgstr ""
 
-#: mod/dfrn_confirm.php:501
+#: mod/dfrn_confirm.php:495
 #, php-format
 msgid "Site public key not available in contact record for URL %s."
 msgstr ""
 
-#: mod/dfrn_confirm.php:517
+#: mod/dfrn_confirm.php:511
 msgid ""
 "The ID provided by your system is a duplicate on our system. It should work "
 "if you try again."
 msgstr ""
 
-#: mod/dfrn_confirm.php:528
+#: mod/dfrn_confirm.php:522
 msgid "Unable to set your contact credentials on our system."
 msgstr ""
 
-#: mod/dfrn_confirm.php:584
+#: mod/dfrn_confirm.php:578
 msgid "Unable to update your contact profile details on our system"
 msgstr ""
 
-#: mod/dfrn_confirm.php:614 mod/dfrn_request.php:561 src/Model/Contact.php:1891
+#: mod/dfrn_confirm.php:608 mod/dfrn_request.php:561 src/Model/Contact.php:1909
 msgid "[Name Withheld]"
 msgstr ""
 
@@ -1953,7 +1953,7 @@ msgid "Forum Search - %s"
 msgstr ""
 
 #: mod/dirfind.php:221 mod/match.php:105 mod/suggest.php:104
-#: mod/allfriends.php:92 src/Model/Profile.php:292 src/Content/Widget.php:37
+#: mod/allfriends.php:92 src/Model/Profile.php:305 src/Content/Widget.php:37
 msgid "Connect"
 msgstr ""
 
@@ -1985,8 +1985,8 @@ msgstr ""
 
 #: mod/videos.php:198 mod/webfinger.php:16 mod/directory.php:42
 #: mod/search.php:105 mod/search.php:111 mod/viewcontacts.php:48
-#: mod/display.php:194 mod/dfrn_request.php:599 mod/probe.php:13
-#: mod/community.php:28 mod/photos.php:945
+#: mod/display.php:203 mod/dfrn_request.php:599 mod/probe.php:13
+#: mod/community.php:28 mod/photos.php:947
 msgid "Public access denied."
 msgstr ""
 
@@ -1994,19 +1994,19 @@ msgstr ""
 msgid "No videos selected"
 msgstr ""
 
-#: mod/videos.php:307 mod/photos.php:1050
+#: mod/videos.php:307 mod/photos.php:1052
 msgid "Access to this item is restricted."
 msgstr ""
 
-#: mod/videos.php:382 mod/photos.php:1699
+#: mod/videos.php:383 mod/photos.php:1701
 msgid "View Album"
 msgstr ""
 
-#: mod/videos.php:390
+#: mod/videos.php:391
 msgid "Recent Videos"
 msgstr ""
 
-#: mod/videos.php:392
+#: mod/videos.php:393
 msgid "Upload New Videos"
 msgstr ""
 
@@ -2014,27 +2014,27 @@ msgstr ""
 msgid "Only logged in users are permitted to perform a probing."
 msgstr ""
 
-#: mod/directory.php:151 mod/notifications.php:253 mod/contacts.php:680
-#: mod/events.php:521 src/Model/Event.php:66 src/Model/Event.php:93
-#: src/Model/Event.php:430 src/Model/Event.php:915 src/Model/Profile.php:417
+#: mod/directory.php:151 mod/notifications.php:248 mod/contacts.php:681
+#: mod/events.php:548 src/Model/Event.php:67 src/Model/Event.php:94
+#: src/Model/Event.php:431 src/Model/Event.php:922 src/Model/Profile.php:430
 msgid "Location:"
 msgstr ""
 
-#: mod/directory.php:156 mod/notifications.php:259 src/Model/Profile.php:420
-#: src/Model/Profile.php:732
+#: mod/directory.php:156 mod/notifications.php:254 src/Model/Profile.php:433
+#: src/Model/Profile.php:745
 msgid "Gender:"
 msgstr ""
 
-#: mod/directory.php:157 src/Model/Profile.php:421 src/Model/Profile.php:756
+#: mod/directory.php:157 src/Model/Profile.php:434 src/Model/Profile.php:769
 msgid "Status:"
 msgstr ""
 
-#: mod/directory.php:158 src/Model/Profile.php:422 src/Model/Profile.php:773
+#: mod/directory.php:158 src/Model/Profile.php:435 src/Model/Profile.php:786
 msgid "Homepage:"
 msgstr ""
 
-#: mod/directory.php:159 mod/notifications.php:255 mod/contacts.php:684
-#: src/Model/Profile.php:423 src/Model/Profile.php:793
+#: mod/directory.php:159 mod/notifications.php:250 mod/contacts.php:685
+#: src/Model/Profile.php:436 src/Model/Profile.php:806
 msgid "About:"
 msgstr ""
 
@@ -2074,7 +2074,7 @@ msgstr ""
 msgid "Account"
 msgstr ""
 
-#: mod/settings.php:64 src/Model/Profile.php:372 src/Content/Nav.php:210
+#: mod/settings.php:64 src/Model/Profile.php:385 src/Content/Nav.php:210
 msgid "Profiles"
 msgstr ""
 
@@ -2114,7 +2114,7 @@ msgstr ""
 msgid "Missing some important data!"
 msgstr ""
 
-#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:848
+#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:851
 msgid "Update"
 msgstr ""
 
@@ -2803,7 +2803,7 @@ msgstr ""
 msgid "Basic Settings"
 msgstr ""
 
-#: mod/settings.php:1204 src/Model/Profile.php:725
+#: mod/settings.php:1204 src/Model/Profile.php:738
 msgid "Full Name:"
 msgstr ""
 
@@ -2853,11 +2853,11 @@ msgstr ""
 msgid "(click to open/close)"
 msgstr ""
 
-#: mod/settings.php:1224 mod/photos.php:1126 mod/photos.php:1456
+#: mod/settings.php:1224 mod/photos.php:1128 mod/photos.php:1458
 msgid "Show to Groups"
 msgstr ""
 
-#: mod/settings.php:1225 mod/photos.php:1127 mod/photos.php:1457
+#: mod/settings.php:1225 mod/photos.php:1129 mod/photos.php:1459
 msgid "Show to Contacts"
 msgstr ""
 
@@ -3006,7 +3006,7 @@ msgstr ""
 msgid "Items tagged with: %s"
 msgstr ""
 
-#: mod/search.php:248 mod/contacts.php:841
+#: mod/search.php:248 mod/contacts.php:844
 #, php-format
 msgid "Results for: %s"
 msgstr ""
@@ -3015,7 +3015,7 @@ msgstr ""
 msgid "No contacts in common."
 msgstr ""
 
-#: mod/common.php:142 mod/contacts.php:916
+#: mod/common.php:142 mod/contacts.php:919
 msgid "Common Friends"
 msgstr ""
 
@@ -3023,7 +3023,11 @@ msgstr ""
 msgid "Login"
 msgstr ""
 
-#: mod/bookmarklet.php:52
+#: mod/bookmarklet.php:34
+msgid "Bad Request"
+msgstr ""
+
+#: mod/bookmarklet.php:56
 msgid "The post was created"
 msgstr ""
 
@@ -3173,7 +3177,7 @@ msgstr ""
 msgid "Members"
 msgstr ""
 
-#: mod/group.php:246 mod/contacts.php:739
+#: mod/group.php:246 mod/contacts.php:742
 msgid "All Contacts"
 msgstr ""
 
@@ -3297,46 +3301,42 @@ msgstr ""
 msgid "No contacts."
 msgstr ""
 
-#: mod/viewcontacts.php:106 mod/contacts.php:639 mod/contacts.php:1052
+#: mod/viewcontacts.php:106 mod/contacts.php:640 mod/contacts.php:1055
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr ""
 
-#: mod/unfollow.php:36
-msgid "Contact wasn't found or can't be unfollowed."
-msgstr ""
-
-#: mod/unfollow.php:49
-msgid "Contact unfollowed"
-msgstr ""
-
-#: mod/unfollow.php:67 mod/dfrn_request.php:654 mod/follow.php:62
-msgid "Submit Request"
+#: mod/unfollow.php:38 mod/unfollow.php:88
+msgid "You aren't following this contact."
 msgstr ""
 
-#: mod/unfollow.php:76
-msgid "You aren't a friend of this contact."
+#: mod/unfollow.php:44 mod/unfollow.php:94
+msgid "Unfollowing is currently not supported by your network."
 msgstr ""
 
-#: mod/unfollow.php:82
-msgid "Unfollowing is currently not supported by your network."
+#: mod/unfollow.php:65
+msgid "Contact unfollowed"
 msgstr ""
 
-#: mod/unfollow.php:103 mod/contacts.php:601
+#: mod/unfollow.php:113 mod/contacts.php:607
 msgid "Disconnect/Unfollow"
 msgstr ""
 
-#: mod/unfollow.php:116 mod/dfrn_request.php:652 mod/follow.php:157
+#: mod/unfollow.php:126 mod/dfrn_request.php:652 mod/follow.php:157
 msgid "Your Identity Address:"
 msgstr ""
 
-#: mod/unfollow.php:125 mod/notifications.php:174 mod/notifications.php:263
-#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:676 mod/follow.php:166
+#: mod/unfollow.php:129 mod/dfrn_request.php:654 mod/follow.php:62
+msgid "Submit Request"
+msgstr ""
+
+#: mod/unfollow.php:135 mod/notifications.php:174 mod/notifications.php:258
+#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:677 mod/follow.php:166
 msgid "Profile URL"
 msgstr ""
 
-#: mod/unfollow.php:135 mod/contacts.php:888 mod/follow.php:189
-#: src/Model/Profile.php:878
+#: mod/unfollow.php:145 mod/contacts.php:891 mod/follow.php:189
+#: src/Model/Profile.php:891
 msgid "Status Messages and Posts"
 msgstr ""
 
@@ -3370,7 +3370,7 @@ msgstr ""
 msgid "Your registration is pending approval by the site owner."
 msgstr ""
 
-#: mod/register.php:191 mod/uimport.php:55
+#: mod/register.php:191 mod/uimport.php:37
 msgid ""
 "This site has exceeded the number of allowed daily account registrations. "
 "Please try again tomorrow."
@@ -3445,7 +3445,7 @@ msgstr ""
 msgid "Register"
 msgstr ""
 
-#: mod/register.php:287 mod/uimport.php:70
+#: mod/register.php:287 mod/uimport.php:52
 msgid "Import"
 msgstr ""
 
@@ -3466,36 +3466,44 @@ msgstr ""
 msgid "Invalid request identifier."
 msgstr ""
 
-#: mod/notifications.php:44 mod/notifications.php:183 mod/notifications.php:235
+#: mod/notifications.php:44 mod/notifications.php:182 mod/notifications.php:230
 #: mod/message.php:114
 msgid "Discard"
 msgstr ""
 
-#: mod/notifications.php:57 mod/notifications.php:182 mod/notifications.php:271
-#: mod/contacts.php:658 mod/contacts.php:850 mod/contacts.php:1113
+#: mod/notifications.php:57 mod/notifications.php:181 mod/notifications.php:266
+#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116
 msgid "Ignore"
 msgstr ""
 
-#: mod/notifications.php:93 src/Content/Nav.php:191
+#: mod/notifications.php:90 src/Content/Nav.php:191
 msgid "Notifications"
 msgstr ""
 
-#: mod/notifications.php:101
+#: mod/notifications.php:102
 msgid "Network Notifications"
 msgstr ""
 
-#: mod/notifications.php:106 mod/notify.php:81
+#: mod/notifications.php:107 mod/notify.php:81
 msgid "System Notifications"
 msgstr ""
 
-#: mod/notifications.php:111
+#: mod/notifications.php:112
 msgid "Personal Notifications"
 msgstr ""
 
-#: mod/notifications.php:116
+#: mod/notifications.php:117
 msgid "Home Notifications"
 msgstr ""
 
+#: mod/notifications.php:137
+msgid "Show unread"
+msgstr ""
+
+#: mod/notifications.php:137
+msgid "Show all"
+msgstr ""
+
 #: mod/notifications.php:148
 msgid "Show Ignored Requests"
 msgstr ""
@@ -3504,7 +3512,7 @@ msgstr ""
 msgid "Hide Ignored Requests"
 msgstr ""
 
-#: mod/notifications.php:161 mod/notifications.php:243
+#: mod/notifications.php:161 mod/notifications.php:238
 msgid "Notification type:"
 msgstr ""
 
@@ -3512,85 +3520,77 @@ msgstr ""
 msgid "Suggested by:"
 msgstr ""
 
-#: mod/notifications.php:176 mod/notifications.php:260 mod/contacts.php:666
+#: mod/notifications.php:176 mod/notifications.php:255 mod/contacts.php:667
 msgid "Hide this contact from others"
 msgstr ""
 
-#: mod/notifications.php:179 mod/notifications.php:269 mod/admin.php:1904
+#: mod/notifications.php:178 mod/notifications.php:264 mod/admin.php:1904
 msgid "Approve"
 msgstr ""
 
-#: mod/notifications.php:202
+#: mod/notifications.php:198
 msgid "Claims to be known to you: "
 msgstr ""
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "yes"
 msgstr ""
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "no"
 msgstr ""
 
-#: mod/notifications.php:204 mod/notifications.php:209
+#: mod/notifications.php:200 mod/notifications.php:204
 msgid "Shall your connection be bidirectional or not?"
 msgstr ""
 
-#: mod/notifications.php:205 mod/notifications.php:210
+#: mod/notifications.php:201 mod/notifications.php:205
 #, php-format
 msgid ""
 "Accepting %s as a friend allows %s to subscribe to your posts, and you will "
 "also receive updates from them in your news feed."
 msgstr ""
 
-#: mod/notifications.php:206
+#: mod/notifications.php:202
 #, php-format
 msgid ""
 "Accepting %s as a subscriber allows them to subscribe to your posts, but you "
 "will not receive updates from them in your news feed."
 msgstr ""
 
-#: mod/notifications.php:211
+#: mod/notifications.php:206
 #, php-format
 msgid ""
 "Accepting %s as a sharer allows them to subscribe to your posts, but you "
 "will not receive updates from them in your news feed."
 msgstr ""
 
-#: mod/notifications.php:222
+#: mod/notifications.php:217
 msgid "Friend"
 msgstr ""
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Sharer"
 msgstr ""
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Subscriber"
 msgstr ""
 
-#: mod/notifications.php:257 mod/contacts.php:686 mod/follow.php:177
-#: src/Model/Profile.php:781
+#: mod/notifications.php:252 mod/contacts.php:687 mod/follow.php:177
+#: src/Model/Profile.php:794
 msgid "Tags:"
 msgstr ""
 
-#: mod/notifications.php:266 mod/contacts.php:76 src/Model/Profile.php:520
+#: mod/notifications.php:261 mod/contacts.php:81 src/Model/Profile.php:533
 msgid "Network:"
 msgstr ""
 
-#: mod/notifications.php:280
+#: mod/notifications.php:274
 msgid "No introductions."
 msgstr ""
 
-#: mod/notifications.php:318
-msgid "Show unread"
-msgstr ""
-
-#: mod/notifications.php:318
-msgid "Show all"
-msgstr ""
-
-#: mod/notifications.php:323
+#: mod/notifications.php:308
 #, php-format
 msgid "No more %s notifications."
 msgstr ""
@@ -3812,7 +3812,7 @@ msgid "On this server the following remote servers are blocked."
 msgstr ""
 
 #: mod/friendica.php:130 mod/admin.php:363 mod/admin.php:381
-#: mod/dfrn_request.php:345 src/Model/Contact.php:1582
+#: mod/dfrn_request.php:345 src/Model/Contact.php:1593
 msgid "Blocked domain"
 msgstr ""
 
@@ -3820,7 +3820,7 @@ msgstr ""
 msgid "Reason for the block"
 msgstr ""
 
-#: mod/display.php:303 mod/cal.php:144 mod/profile.php:175
+#: mod/display.php:312 mod/cal.php:144 mod/profile.php:185
 msgid "Access to this profile has been restricted."
 msgstr ""
 
@@ -3830,13 +3830,13 @@ msgstr ""
 msgid "Invalid request."
 msgstr ""
 
-#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:776
-#: mod/photos.php:779 mod/photos.php:808
+#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:778
+#: mod/photos.php:781 mod/photos.php:810
 #, php-format
 msgid "Image exceeds size limit of %s"
 msgstr ""
 
-#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:831
+#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:833
 msgid "Unable to process image."
 msgstr ""
 
@@ -3845,7 +3845,7 @@ msgstr ""
 msgid "Wall Photos"
 msgstr ""
 
-#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:860
+#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:862
 msgid "Image upload failed."
 msgstr ""
 
@@ -4156,79 +4156,91 @@ msgstr ""
 msgid "Your password has been changed at %s"
 msgstr ""
 
-#: mod/babel.php:22
+#: mod/babel.php:24
 msgid "Source input"
 msgstr ""
 
-#: mod/babel.php:28
+#: mod/babel.php:30
 msgid "BBCode::toPlaintext"
 msgstr ""
 
-#: mod/babel.php:34
+#: mod/babel.php:36
 msgid "BBCode::convert (raw HTML)"
 msgstr ""
 
-#: mod/babel.php:39
+#: mod/babel.php:41
 msgid "BBCode::convert"
 msgstr ""
 
-#: mod/babel.php:45
+#: mod/babel.php:47
 msgid "BBCode::convert => HTML::toBBCode"
 msgstr ""
 
-#: mod/babel.php:51
+#: mod/babel.php:53
 msgid "BBCode::toMarkdown"
 msgstr ""
 
-#: mod/babel.php:57
+#: mod/babel.php:59
 msgid "BBCode::toMarkdown => Markdown::convert"
 msgstr ""
 
-#: mod/babel.php:63
+#: mod/babel.php:65
 msgid "BBCode::toMarkdown => Markdown::toBBCode"
 msgstr ""
 
-#: mod/babel.php:69
+#: mod/babel.php:71
 msgid "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"
 msgstr ""
 
-#: mod/babel.php:76
-msgid "Source input \\x28Diaspora format\\x29"
+#: mod/babel.php:78
+msgid "Source input (Diaspora format)"
 msgstr ""
 
-#: mod/babel.php:82
-msgid "Markdown::toBBCode"
+#: mod/babel.php:84
+msgid "Markdown::convert (raw HTML)"
 msgstr ""
 
 #: mod/babel.php:89
+msgid "Markdown::convert"
+msgstr ""
+
+#: mod/babel.php:95
+msgid "Markdown::toBBCode"
+msgstr ""
+
+#: mod/babel.php:102
 msgid "Raw HTML input"
 msgstr ""
 
-#: mod/babel.php:94
+#: mod/babel.php:107
 msgid "HTML Input"
 msgstr ""
 
-#: mod/babel.php:100
+#: mod/babel.php:113
 msgid "HTML::toBBCode"
 msgstr ""
 
-#: mod/babel.php:106
+#: mod/babel.php:119
+msgid "HTML::toMarkdown"
+msgstr ""
+
+#: mod/babel.php:125
 msgid "HTML::toPlaintext"
 msgstr ""
 
-#: mod/babel.php:114
+#: mod/babel.php:133
 msgid "Source text"
 msgstr ""
 
-#: mod/babel.php:115
+#: mod/babel.php:134
 msgid "BBCode"
 msgstr ""
 
-#: mod/babel.php:116
+#: mod/babel.php:135
 msgid "Markdown"
 msgstr ""
 
-#: mod/babel.php:117
+#: mod/babel.php:136
 msgid "HTML"
 msgstr ""
 
@@ -4488,13 +4500,13 @@ msgstr ""
 msgid "select none"
 msgstr ""
 
-#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Block"
 msgstr ""
 
-#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Unblock"
 msgstr ""
 
@@ -4675,9 +4687,9 @@ msgstr ""
 #: mod/admin.php:876
 #, php-format
 msgid ""
-"<a href=\"%s\">%s</a> is not reachable on your system. This is a servere "
-"configuration issue that prevents the communication.. See <a href=\"%s\">the "
-"installation page</a> for help."
+"<a href=\"%s\">%s</a> is not reachable on your system. This is a severe "
+"configuration issue that prevents server to server communication. See <a "
+"href=\"%s\">the installation page</a> for help."
 msgstr ""
 
 #: mod/admin.php:882
@@ -4757,7 +4769,7 @@ msgid "Public postings from local users and the federated network"
 msgstr ""
 
 #: mod/admin.php:1353 mod/admin.php:1520 mod/admin.php:1530
-#: mod/contacts.php:577
+#: mod/contacts.php:583
 msgid "Disabled"
 msgstr ""
 
@@ -4837,8 +4849,8 @@ msgstr ""
 msgid "Policies"
 msgstr ""
 
-#: mod/admin.php:1431 mod/contacts.php:926 mod/events.php:535
-#: src/Model/Profile.php:852
+#: mod/admin.php:1431 mod/contacts.php:929 mod/events.php:562
+#: src/Model/Profile.php:865
 msgid "Advanced"
 msgstr ""
 
@@ -5241,14 +5253,14 @@ msgid ""
 msgstr ""
 
 #: mod/admin.php:1481
-msgid "Only import OStatus threads from our contacts"
+msgid "Only import OStatus/ActivityPub threads from our contacts"
 msgstr ""
 
 #: mod/admin.php:1481
 msgid ""
-"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."
+"Normally we import every content from our OStatus and ActivityPub contacts. "
+"With this option we only store threads that are started by a contact that is "
+"known on our system."
 msgstr ""
 
 #: mod/admin.php:1482
@@ -6127,11 +6139,11 @@ msgstr ""
 msgid "Invalid profile URL."
 msgstr ""
 
-#: mod/dfrn_request.php:339 src/Model/Contact.php:1577
+#: mod/dfrn_request.php:339 src/Model/Contact.php:1588
 msgid "Disallowed profile URL."
 msgstr ""
 
-#: mod/dfrn_request.php:412 mod/contacts.php:235
+#: mod/dfrn_request.php:412 mod/contacts.php:241
 msgid "Failed to update contact record."
 msgstr ""
 
@@ -6357,32 +6369,36 @@ msgstr ""
 msgid "Help:"
 msgstr ""
 
-#: mod/uimport.php:72
+#: mod/uimport.php:28
+msgid "User imports on closed servers can only be done by an administrator."
+msgstr ""
+
+#: mod/uimport.php:54
 msgid "Move account"
 msgstr ""
 
-#: mod/uimport.php:73
+#: mod/uimport.php:55
 msgid "You can import an account from another Friendica server."
 msgstr ""
 
-#: mod/uimport.php:74
+#: mod/uimport.php:56
 msgid ""
 "You need to export your account from the old server and upload it here. We "
 "will recreate your old account here with all your contacts. We will try also "
 "to inform your friends that you moved here."
 msgstr ""
 
-#: mod/uimport.php:75
+#: mod/uimport.php:57
 msgid ""
 "This feature is experimental. We can't import contacts from the OStatus "
 "network (GNU Social/Statusnet) or from Diaspora"
 msgstr ""
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid "Account file"
 msgstr ""
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid ""
 "To export your account, go to \"Settings->Export your personal data\" and "
 "select \"Export account\""
@@ -6404,34 +6420,34 @@ msgstr ""
 msgid "All Contacts (with secure profile access)"
 msgstr ""
 
-#: mod/cal.php:277 mod/events.php:391
+#: mod/cal.php:277 mod/events.php:392
 msgid "View"
 msgstr ""
 
-#: mod/cal.php:278 mod/events.php:393
+#: mod/cal.php:278 mod/events.php:394
 msgid "Previous"
 msgstr ""
 
-#: mod/cal.php:282 mod/events.php:399 src/Model/Event.php:421
+#: mod/cal.php:282 mod/events.php:400 src/Model/Event.php:422
 msgid "today"
 msgstr ""
 
-#: mod/cal.php:283 mod/events.php:400 src/Util/Temporal.php:304
-#: src/Model/Event.php:422
+#: mod/cal.php:283 mod/events.php:401 src/Util/Temporal.php:304
+#: src/Model/Event.php:423
 msgid "month"
 msgstr ""
 
-#: mod/cal.php:284 mod/events.php:401 src/Util/Temporal.php:305
-#: src/Model/Event.php:423
+#: mod/cal.php:284 mod/events.php:402 src/Util/Temporal.php:305
+#: src/Model/Event.php:424
 msgid "week"
 msgstr ""
 
-#: mod/cal.php:285 mod/events.php:402 src/Util/Temporal.php:306
-#: src/Model/Event.php:424
+#: mod/cal.php:285 mod/events.php:403 src/Util/Temporal.php:306
+#: src/Model/Event.php:425
 msgid "day"
 msgstr ""
 
-#: mod/cal.php:286 mod/events.php:403
+#: mod/cal.php:286 mod/events.php:404
 msgid "list"
 msgstr ""
 
@@ -6464,19 +6480,19 @@ msgstr ""
 msgid "Please login."
 msgstr ""
 
-#: mod/editpost.php:26 mod/editpost.php:36
+#: mod/editpost.php:27 mod/editpost.php:42
 msgid "Item not found"
 msgstr ""
 
-#: mod/editpost.php:43
+#: mod/editpost.php:49
 msgid "Edit post"
 msgstr ""
 
-#: mod/editpost.php:125 src/Core/ACL.php:304
+#: mod/editpost.php:131 src/Core/ACL.php:304
 msgid "CC: email addresses"
 msgstr ""
 
-#: mod/editpost.php:132 src/Core/ACL.php:305
+#: mod/editpost.php:138 src/Core/ACL.php:305
 msgid "Example: bob@example.com, mary@example.com"
 msgstr ""
 
@@ -6513,21 +6529,21 @@ msgstr ""
 msgid "System down for maintenance"
 msgstr ""
 
-#: mod/profile.php:38 src/Model/Profile.php:115
+#: mod/profile.php:39 src/Model/Profile.php:128
 msgid "Requested profile is not available."
 msgstr ""
 
-#: mod/profile.php:79 mod/profile.php:82 src/Protocol/OStatus.php:1275
+#: mod/profile.php:89 mod/profile.php:92 src/Protocol/OStatus.php:1285
 #, php-format
 msgid "%s's timeline"
 msgstr ""
 
-#: mod/profile.php:80 src/Protocol/OStatus.php:1276
+#: mod/profile.php:90 src/Protocol/OStatus.php:1286
 #, php-format
 msgid "%s's posts"
 msgstr ""
 
-#: mod/profile.php:81 src/Protocol/OStatus.php:1277
+#: mod/profile.php:91 src/Protocol/OStatus.php:1287
 #, php-format
 msgid "%s's comments"
 msgstr ""
@@ -6536,433 +6552,433 @@ msgstr ""
 msgid "No friends to display."
 msgstr ""
 
-#: mod/contacts.php:162
+#: mod/contacts.php:168
 #, php-format
 msgid "%d contact edited."
 msgid_plural "%d contacts edited."
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/contacts.php:189 mod/contacts.php:395
+#: mod/contacts.php:195 mod/contacts.php:401
 msgid "Could not access contact record."
 msgstr ""
 
-#: mod/contacts.php:199
+#: mod/contacts.php:205
 msgid "Could not locate selected profile."
 msgstr ""
 
-#: mod/contacts.php:233
+#: mod/contacts.php:239
 msgid "Contact updated."
 msgstr ""
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been blocked"
 msgstr ""
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been unblocked"
 msgstr ""
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been ignored"
 msgstr ""
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been unignored"
 msgstr ""
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been archived"
 msgstr ""
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been unarchived"
 msgstr ""
 
-#: mod/contacts.php:460
+#: mod/contacts.php:466
 msgid "Drop contact"
 msgstr ""
 
-#: mod/contacts.php:463 mod/contacts.php:845
+#: mod/contacts.php:469 mod/contacts.php:848
 msgid "Do you really want to delete this contact?"
 msgstr ""
 
-#: mod/contacts.php:481
+#: mod/contacts.php:487
 msgid "Contact has been removed."
 msgstr ""
 
-#: mod/contacts.php:518
+#: mod/contacts.php:524
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr ""
 
-#: mod/contacts.php:523
+#: mod/contacts.php:529
 #, php-format
 msgid "You are sharing with %s"
 msgstr ""
 
-#: mod/contacts.php:528
+#: mod/contacts.php:534
 #, php-format
 msgid "%s is sharing with you"
 msgstr ""
 
-#: mod/contacts.php:552
+#: mod/contacts.php:558
 msgid "Private communications are not available for this contact."
 msgstr ""
 
-#: mod/contacts.php:554
+#: mod/contacts.php:560
 msgid "Never"
 msgstr ""
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was successful)"
 msgstr ""
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was not successful)"
 msgstr ""
 
-#: mod/contacts.php:559 mod/contacts.php:1086
+#: mod/contacts.php:565 mod/contacts.php:1089
 msgid "Suggest friends"
 msgstr ""
 
-#: mod/contacts.php:563
+#: mod/contacts.php:569
 #, php-format
 msgid "Network type: %s"
 msgstr ""
 
-#: mod/contacts.php:568
+#: mod/contacts.php:574
 msgid "Communications lost with this contact!"
 msgstr ""
 
-#: mod/contacts.php:574
+#: mod/contacts.php:580
 msgid "Fetch further information for feeds"
 msgstr ""
 
-#: mod/contacts.php:576
+#: mod/contacts.php:582
 msgid ""
 "Fetch information like preview pictures, title and teaser from the feed "
 "item. You can activate this if the feed doesn't contain much text. Keywords "
 "are taken from the meta header in the feed item and are posted as hash tags."
 msgstr ""
 
-#: mod/contacts.php:578
+#: mod/contacts.php:584
 msgid "Fetch information"
 msgstr ""
 
-#: mod/contacts.php:579
+#: mod/contacts.php:585
 msgid "Fetch keywords"
 msgstr ""
 
-#: mod/contacts.php:580
+#: mod/contacts.php:586
 msgid "Fetch information and keywords"
 msgstr ""
 
-#: mod/contacts.php:617
+#: mod/contacts.php:618
 msgid "Profile Visibility"
 msgstr ""
 
-#: mod/contacts.php:618
+#: mod/contacts.php:619
 msgid "Contact Information / Notes"
 msgstr ""
 
-#: mod/contacts.php:619
+#: mod/contacts.php:620
 msgid "Contact Settings"
 msgstr ""
 
-#: mod/contacts.php:628
+#: mod/contacts.php:629
 msgid "Contact"
 msgstr ""
 
-#: mod/contacts.php:632
+#: mod/contacts.php:633
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
 msgstr ""
 
-#: mod/contacts.php:634
+#: mod/contacts.php:635
 msgid "Their personal note"
 msgstr ""
 
-#: mod/contacts.php:636
+#: mod/contacts.php:637
 msgid "Edit contact notes"
 msgstr ""
 
-#: mod/contacts.php:640
+#: mod/contacts.php:641
 msgid "Block/Unblock contact"
 msgstr ""
 
-#: mod/contacts.php:641
+#: mod/contacts.php:642
 msgid "Ignore contact"
 msgstr ""
 
-#: mod/contacts.php:642
+#: mod/contacts.php:643
 msgid "Repair URL settings"
 msgstr ""
 
-#: mod/contacts.php:643
+#: mod/contacts.php:644
 msgid "View conversations"
 msgstr ""
 
-#: mod/contacts.php:648
+#: mod/contacts.php:649
 msgid "Last update:"
 msgstr ""
 
-#: mod/contacts.php:650
+#: mod/contacts.php:651
 msgid "Update public posts"
 msgstr ""
 
-#: mod/contacts.php:652 mod/contacts.php:1096
+#: mod/contacts.php:653 mod/contacts.php:1099
 msgid "Update now"
 msgstr ""
 
-#: mod/contacts.php:658 mod/contacts.php:850 mod/contacts.php:1113
+#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116
 msgid "Unignore"
 msgstr ""
 
-#: mod/contacts.php:662
+#: mod/contacts.php:663
 msgid "Currently blocked"
 msgstr ""
 
-#: mod/contacts.php:663
+#: mod/contacts.php:664
 msgid "Currently ignored"
 msgstr ""
 
-#: mod/contacts.php:664
+#: mod/contacts.php:665
 msgid "Currently archived"
 msgstr ""
 
-#: mod/contacts.php:665
+#: mod/contacts.php:666
 msgid "Awaiting connection acknowledge"
 msgstr ""
 
-#: mod/contacts.php:666
+#: mod/contacts.php:667
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr ""
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Notification for new posts"
 msgstr ""
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Send a notification of every new post of this contact"
 msgstr ""
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid "Blacklisted keywords"
 msgstr ""
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
 msgstr ""
 
-#: mod/contacts.php:682 src/Model/Profile.php:424
+#: mod/contacts.php:683 src/Model/Profile.php:437
 msgid "XMPP:"
 msgstr ""
 
-#: mod/contacts.php:687
+#: mod/contacts.php:688
 msgid "Actions"
 msgstr ""
 
-#: mod/contacts.php:731
+#: mod/contacts.php:734
 msgid "Suggestions"
 msgstr ""
 
-#: mod/contacts.php:734
+#: mod/contacts.php:737
 msgid "Suggest potential friends"
 msgstr ""
 
-#: mod/contacts.php:742
+#: mod/contacts.php:745
 msgid "Show all contacts"
 msgstr ""
 
-#: mod/contacts.php:747
+#: mod/contacts.php:750
 msgid "Unblocked"
 msgstr ""
 
-#: mod/contacts.php:750
+#: mod/contacts.php:753
 msgid "Only show unblocked contacts"
 msgstr ""
 
-#: mod/contacts.php:755
+#: mod/contacts.php:758
 msgid "Blocked"
 msgstr ""
 
-#: mod/contacts.php:758
+#: mod/contacts.php:761
 msgid "Only show blocked contacts"
 msgstr ""
 
-#: mod/contacts.php:763
+#: mod/contacts.php:766
 msgid "Ignored"
 msgstr ""
 
-#: mod/contacts.php:766
+#: mod/contacts.php:769
 msgid "Only show ignored contacts"
 msgstr ""
 
-#: mod/contacts.php:771
+#: mod/contacts.php:774
 msgid "Archived"
 msgstr ""
 
-#: mod/contacts.php:774
+#: mod/contacts.php:777
 msgid "Only show archived contacts"
 msgstr ""
 
-#: mod/contacts.php:779
+#: mod/contacts.php:782
 msgid "Hidden"
 msgstr ""
 
-#: mod/contacts.php:782
+#: mod/contacts.php:785
 msgid "Only show hidden contacts"
 msgstr ""
 
-#: mod/contacts.php:840
+#: mod/contacts.php:843
 msgid "Search your contacts"
 msgstr ""
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Archive"
 msgstr ""
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Unarchive"
 msgstr ""
 
-#: mod/contacts.php:854
+#: mod/contacts.php:857
 msgid "Batch Actions"
 msgstr ""
 
-#: mod/contacts.php:880
+#: mod/contacts.php:883
 msgid "Conversations started by this contact"
 msgstr ""
 
-#: mod/contacts.php:885
+#: mod/contacts.php:888
 msgid "Posts and Comments"
 msgstr ""
 
-#: mod/contacts.php:896 src/Model/Profile.php:886
+#: mod/contacts.php:899 src/Model/Profile.php:899
 msgid "Profile Details"
 msgstr ""
 
-#: mod/contacts.php:908
+#: mod/contacts.php:911
 msgid "View all contacts"
 msgstr ""
 
-#: mod/contacts.php:919
+#: mod/contacts.php:922
 msgid "View all common friends"
 msgstr ""
 
-#: mod/contacts.php:929
+#: mod/contacts.php:932
 msgid "Advanced Contact Settings"
 msgstr ""
 
-#: mod/contacts.php:1019
+#: mod/contacts.php:1022
 msgid "Mutual Friendship"
 msgstr ""
 
-#: mod/contacts.php:1024
+#: mod/contacts.php:1027
 msgid "is a fan of yours"
 msgstr ""
 
-#: mod/contacts.php:1029
+#: mod/contacts.php:1032
 msgid "you are a fan of"
 msgstr ""
 
-#: mod/contacts.php:1046 mod/photos.php:1494 mod/photos.php:1533
-#: mod/photos.php:1593 src/Object/Post.php:792
+#: mod/contacts.php:1049 mod/photos.php:1496 mod/photos.php:1535
+#: mod/photos.php:1595 src/Object/Post.php:792
 msgid "This is you"
 msgstr ""
 
-#: mod/contacts.php:1053
+#: mod/contacts.php:1056
 msgid "Edit contact"
 msgstr ""
 
-#: mod/contacts.php:1107
+#: mod/contacts.php:1110
 msgid "Toggle Blocked status"
 msgstr ""
 
-#: mod/contacts.php:1115
+#: mod/contacts.php:1118
 msgid "Toggle Ignored status"
 msgstr ""
 
-#: mod/contacts.php:1124
+#: mod/contacts.php:1127
 msgid "Toggle Archive status"
 msgstr ""
 
-#: mod/contacts.php:1132
+#: mod/contacts.php:1135
 msgid "Delete contact"
 msgstr ""
 
-#: mod/events.php:103 mod/events.php:105
+#: mod/events.php:105 mod/events.php:107
 msgid "Event can not end before it has started."
 msgstr ""
 
-#: mod/events.php:112 mod/events.php:114
+#: mod/events.php:114 mod/events.php:116
 msgid "Event title and start time are required."
 msgstr ""
 
-#: mod/events.php:392
+#: mod/events.php:393
 msgid "Create New Event"
 msgstr ""
 
-#: mod/events.php:509
+#: mod/events.php:516
 msgid "Event details"
 msgstr ""
 
-#: mod/events.php:510
+#: mod/events.php:517
 msgid "Starting date and Title are required."
 msgstr ""
 
-#: mod/events.php:511 mod/events.php:512
+#: mod/events.php:518 mod/events.php:523
 msgid "Event Starts:"
 msgstr ""
 
-#: mod/events.php:511 mod/events.php:523 mod/profiles.php:607
+#: mod/events.php:518 mod/events.php:550 mod/profiles.php:607
 msgid "Required"
 msgstr ""
 
-#: mod/events.php:513 mod/events.php:529
+#: mod/events.php:531 mod/events.php:556
 msgid "Finish date/time is not known or not relevant"
 msgstr ""
 
-#: mod/events.php:515 mod/events.php:516
+#: mod/events.php:533 mod/events.php:538
 msgid "Event Finishes:"
 msgstr ""
 
-#: mod/events.php:517 mod/events.php:530
+#: mod/events.php:544 mod/events.php:557
 msgid "Adjust for viewer timezone"
 msgstr ""
 
-#: mod/events.php:519
+#: mod/events.php:546
 msgid "Description:"
 msgstr ""
 
-#: mod/events.php:523 mod/events.php:525
+#: mod/events.php:550 mod/events.php:552
 msgid "Title:"
 msgstr ""
 
-#: mod/events.php:526 mod/events.php:527
+#: mod/events.php:553 mod/events.php:554
 msgid "Share this event"
 msgstr ""
 
-#: mod/events.php:534 src/Model/Profile.php:851
+#: mod/events.php:561 src/Model/Profile.php:864
 msgid "Basic"
 msgstr ""
 
-#: mod/events.php:536 mod/photos.php:1112 mod/photos.php:1448
+#: mod/events.php:563 mod/photos.php:1114 mod/photos.php:1450
 #: src/Core/ACL.php:307
 msgid "Permissions"
 msgstr ""
 
-#: mod/events.php:555
+#: mod/events.php:579
 msgid "Failed to remove event"
 msgstr ""
 
-#: mod/events.php:557
+#: mod/events.php:581
 msgid "Event removed"
 msgstr ""
 
@@ -6987,8 +7003,8 @@ msgid "The network type couldn't be detected. Contact can't be added."
 msgstr ""
 
 #: mod/fbrowser.php:44 mod/fbrowser.php:69 mod/photos.php:198
-#: mod/photos.php:1076 mod/photos.php:1169 mod/photos.php:1186
-#: mod/photos.php:1652 mod/photos.php:1667 src/Model/Photo.php:243
+#: mod/photos.php:1078 mod/photos.php:1171 mod/photos.php:1188
+#: mod/photos.php:1654 mod/photos.php:1669 src/Model/Photo.php:243
 #: src/Model/Photo.php:252
 msgid "Contact Photos"
 msgstr ""
@@ -7059,7 +7075,7 @@ msgid ""
 "not reflect the opinions of this node’s users."
 msgstr ""
 
-#: mod/localtime.php:19 src/Model/Event.php:34 src/Model/Event.php:829
+#: mod/localtime.php:19 src/Model/Event.php:35 src/Model/Event.php:836
 msgid "l F d, Y \\@ g:i A"
 msgstr ""
 
@@ -7092,23 +7108,23 @@ msgstr ""
 msgid "Please select your timezone:"
 msgstr ""
 
-#: mod/poke.php:188
+#: mod/poke.php:187
 msgid "Poke/Prod"
 msgstr ""
 
-#: mod/poke.php:189
+#: mod/poke.php:188
 msgid "poke, prod or do other things to somebody"
 msgstr ""
 
-#: mod/poke.php:190
+#: mod/poke.php:189
 msgid "Recipient"
 msgstr ""
 
-#: mod/poke.php:191
+#: mod/poke.php:190
 msgid "Choose what you wish to do to recipient"
 msgstr ""
 
-#: mod/poke.php:194
+#: mod/poke.php:193
 msgid "Make this post private"
 msgstr ""
 
@@ -7216,7 +7232,7 @@ msgid ""
 "important, please visit http://friendi.ca"
 msgstr ""
 
-#: mod/notes.php:42 src/Model/Profile.php:933
+#: mod/notes.php:42 src/Model/Profile.php:946
 msgid "Personal Notes"
 msgstr ""
 
@@ -7320,7 +7336,7 @@ msgstr ""
 msgid "View all profiles"
 msgstr ""
 
-#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:393
+#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:406
 msgid "Edit visibility"
 msgstr ""
 
@@ -7372,7 +7388,7 @@ msgstr ""
 msgid "<span class=\"heart\">&hearts;</span> Marital Status:"
 msgstr ""
 
-#: mod/profiles.php:601 src/Model/Profile.php:769
+#: mod/profiles.php:601 src/Model/Profile.php:782
 msgid "Sexual Preference:"
 msgstr ""
 
@@ -7452,11 +7468,11 @@ msgstr ""
 msgid "Homepage URL:"
 msgstr ""
 
-#: mod/profiles.php:628 src/Model/Profile.php:777
+#: mod/profiles.php:628 src/Model/Profile.php:790
 msgid "Hometown:"
 msgstr ""
 
-#: mod/profiles.php:629 src/Model/Profile.php:785
+#: mod/profiles.php:629 src/Model/Profile.php:798
 msgid "Political Views:"
 msgstr ""
 
@@ -7480,11 +7496,11 @@ msgstr ""
 msgid "(Used for searching profiles, never shown to others)"
 msgstr ""
 
-#: mod/profiles.php:633 src/Model/Profile.php:801
+#: mod/profiles.php:633 src/Model/Profile.php:814
 msgid "Likes:"
 msgstr ""
 
-#: mod/profiles.php:634 src/Model/Profile.php:805
+#: mod/profiles.php:634 src/Model/Profile.php:818
 msgid "Dislikes:"
 msgstr ""
 
@@ -7524,11 +7540,11 @@ msgstr ""
 msgid "Contact information and Social Networks"
 msgstr ""
 
-#: mod/profiles.php:674 src/Model/Profile.php:389
+#: mod/profiles.php:674 src/Model/Profile.php:402
 msgid "Profile Image"
 msgstr ""
 
-#: mod/profiles.php:676 src/Model/Profile.php:392
+#: mod/profiles.php:676 src/Model/Profile.php:405
 msgid "visible to everybody"
 msgstr ""
 
@@ -7536,23 +7552,23 @@ msgstr ""
 msgid "Edit/Manage Profiles"
 msgstr ""
 
-#: mod/profiles.php:684 src/Model/Profile.php:379 src/Model/Profile.php:401
+#: mod/profiles.php:684 src/Model/Profile.php:392 src/Model/Profile.php:414
 msgid "Change profile photo"
 msgstr ""
 
-#: mod/profiles.php:685 src/Model/Profile.php:380
+#: mod/profiles.php:685 src/Model/Profile.php:393
 msgid "Create New Profile"
 msgstr ""
 
-#: mod/photos.php:112 src/Model/Profile.php:894
+#: mod/photos.php:112 src/Model/Profile.php:907
 msgid "Photo Albums"
 msgstr ""
 
-#: mod/photos.php:113 mod/photos.php:1708
+#: mod/photos.php:113 mod/photos.php:1710
 msgid "Recent Photos"
 msgstr ""
 
-#: mod/photos.php:116 mod/photos.php:1230 mod/photos.php:1710
+#: mod/photos.php:116 mod/photos.php:1232 mod/photos.php:1712
 msgid "Upload New Photos"
 msgstr ""
 
@@ -7564,7 +7580,7 @@ msgstr ""
 msgid "Album not found."
 msgstr ""
 
-#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1181
+#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1183
 msgid "Delete Album"
 msgstr ""
 
@@ -7572,7 +7588,7 @@ msgstr ""
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr ""
 
-#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1453
+#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1455
 msgid "Delete Photo"
 msgstr ""
 
@@ -7589,149 +7605,149 @@ msgstr ""
 msgid "%1$s was tagged in %2$s by %3$s"
 msgstr ""
 
-#: mod/photos.php:782
+#: mod/photos.php:784
 msgid "Image upload didn't complete, please try again"
 msgstr ""
 
-#: mod/photos.php:785
+#: mod/photos.php:787
 msgid "Image file is missing"
 msgstr ""
 
-#: mod/photos.php:790
+#: mod/photos.php:792
 msgid ""
 "Server can't accept new file upload at this time, please contact your "
 "administrator"
 msgstr ""
 
-#: mod/photos.php:816
+#: mod/photos.php:818
 msgid "Image file is empty."
 msgstr ""
 
-#: mod/photos.php:953
+#: mod/photos.php:955
 msgid "No photos selected"
 msgstr ""
 
-#: mod/photos.php:1104
+#: mod/photos.php:1106
 msgid "Upload Photos"
 msgstr ""
 
-#: mod/photos.php:1108 mod/photos.php:1176
+#: mod/photos.php:1110 mod/photos.php:1178
 msgid "New album name: "
 msgstr ""
 
-#: mod/photos.php:1109
+#: mod/photos.php:1111
 msgid "or select existing album:"
 msgstr ""
 
-#: mod/photos.php:1110
+#: mod/photos.php:1112
 msgid "Do not show a status post for this upload"
 msgstr ""
 
-#: mod/photos.php:1187
+#: mod/photos.php:1189
 msgid "Edit Album"
 msgstr ""
 
-#: mod/photos.php:1192
+#: mod/photos.php:1194
 msgid "Show Newest First"
 msgstr ""
 
-#: mod/photos.php:1194
+#: mod/photos.php:1196
 msgid "Show Oldest First"
 msgstr ""
 
-#: mod/photos.php:1215 mod/photos.php:1693
+#: mod/photos.php:1217 mod/photos.php:1695
 msgid "View Photo"
 msgstr ""
 
-#: mod/photos.php:1256
+#: mod/photos.php:1258
 msgid "Permission denied. Access to this item may be restricted."
 msgstr ""
 
-#: mod/photos.php:1258
+#: mod/photos.php:1260
 msgid "Photo not available"
 msgstr ""
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "View photo"
 msgstr ""
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "Edit photo"
 msgstr ""
 
-#: mod/photos.php:1334
+#: mod/photos.php:1336
 msgid "Use as profile photo"
 msgstr ""
 
-#: mod/photos.php:1340 src/Object/Post.php:151
+#: mod/photos.php:1342 src/Object/Post.php:151
 msgid "Private Message"
 msgstr ""
 
-#: mod/photos.php:1360
+#: mod/photos.php:1362
 msgid "View Full Size"
 msgstr ""
 
-#: mod/photos.php:1421
+#: mod/photos.php:1423
 msgid "Tags: "
 msgstr ""
 
-#: mod/photos.php:1424
+#: mod/photos.php:1426
 msgid "[Remove any tag]"
 msgstr ""
 
-#: mod/photos.php:1439
+#: mod/photos.php:1441
 msgid "New album name"
 msgstr ""
 
-#: mod/photos.php:1440
+#: mod/photos.php:1442
 msgid "Caption"
 msgstr ""
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid "Add a Tag"
 msgstr ""
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr ""
 
-#: mod/photos.php:1442
+#: mod/photos.php:1444
 msgid "Do not rotate"
 msgstr ""
 
-#: mod/photos.php:1443
+#: mod/photos.php:1445
 msgid "Rotate CW (right)"
 msgstr ""
 
-#: mod/photos.php:1444
+#: mod/photos.php:1446
 msgid "Rotate CCW (left)"
 msgstr ""
 
-#: mod/photos.php:1478 src/Object/Post.php:293
+#: mod/photos.php:1480 src/Object/Post.php:293
 msgid "I like this (toggle)"
 msgstr ""
 
-#: mod/photos.php:1479 src/Object/Post.php:294
+#: mod/photos.php:1481 src/Object/Post.php:294
 msgid "I don't like this (toggle)"
 msgstr ""
 
-#: mod/photos.php:1496 mod/photos.php:1535 mod/photos.php:1595
+#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
 #: src/Object/Post.php:398 src/Object/Post.php:794
 msgid "Comment"
 msgstr ""
 
-#: mod/photos.php:1627
+#: mod/photos.php:1629
 msgid "Map"
 msgstr ""
 
-#: local/test.php:1840
+#: local/test.php:1919
 #, php-format
 msgid ""
 "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-name\">%s</"
 "a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"
 msgstr ""
 
-#: local/testshare.php:158 src/Content/Text/BBCode.php:991
+#: local/testshare.php:158 src/Content/Text/BBCode.php:992
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 msgstr ""
@@ -7793,11 +7809,11 @@ msgstr ""
 msgid "%s: updating %s table."
 msgstr ""
 
-#: src/Core/Install.php:138
+#: src/Core/Install.php:139
 msgid "Could not find a command line version of PHP in the web server PATH."
 msgstr ""
 
-#: src/Core/Install.php:139
+#: src/Core/Install.php:140
 msgid ""
 "If you don't have a command line version of PHP installed on your server, "
 "you will not be able to run the background processing. See <a href='https://"
@@ -7805,219 +7821,219 @@ msgid ""
 "worker'>'Setup the worker'</a>"
 msgstr ""
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid "PHP executable path"
 msgstr ""
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid ""
 "Enter full path to php executable. You can leave this blank to continue the "
 "installation."
 msgstr ""
 
-#: src/Core/Install.php:148
+#: src/Core/Install.php:149
 msgid "Command line PHP"
 msgstr ""
 
-#: src/Core/Install.php:157
+#: src/Core/Install.php:158
 msgid "PHP executable is not the php cli binary (could be cgi-fgci version)"
 msgstr ""
 
-#: src/Core/Install.php:158
+#: src/Core/Install.php:159
 msgid "Found PHP version: "
 msgstr ""
 
-#: src/Core/Install.php:160
+#: src/Core/Install.php:161
 msgid "PHP cli binary"
 msgstr ""
 
-#: src/Core/Install.php:170
+#: src/Core/Install.php:171
 msgid ""
 "The command line version of PHP on your system does not have "
 "\"register_argc_argv\" enabled."
 msgstr ""
 
-#: src/Core/Install.php:171
+#: src/Core/Install.php:172
 msgid "This is required for message delivery to work."
 msgstr ""
 
-#: src/Core/Install.php:173
+#: src/Core/Install.php:174
 msgid "PHP register_argc_argv"
 msgstr ""
 
-#: src/Core/Install.php:201
+#: src/Core/Install.php:202
 msgid ""
 "Error: the \"openssl_pkey_new\" function on this system is not able to "
 "generate encryption keys"
 msgstr ""
 
-#: src/Core/Install.php:202
+#: src/Core/Install.php:203
 msgid ""
 "If running under Windows, please see \"http://www.php.net/manual/en/openssl."
 "installation.php\"."
 msgstr ""
 
-#: src/Core/Install.php:204
+#: src/Core/Install.php:205
 msgid "Generate encryption keys"
 msgstr ""
 
-#: src/Core/Install.php:225
+#: src/Core/Install.php:226
 msgid "libCurl PHP module"
 msgstr ""
 
-#: src/Core/Install.php:226
+#: src/Core/Install.php:227
 msgid "GD graphics PHP module"
 msgstr ""
 
-#: src/Core/Install.php:227
+#: src/Core/Install.php:228
 msgid "OpenSSL PHP module"
 msgstr ""
 
-#: src/Core/Install.php:228
+#: src/Core/Install.php:229
 msgid "PDO or MySQLi PHP module"
 msgstr ""
 
-#: src/Core/Install.php:229
+#: src/Core/Install.php:230
 msgid "mb_string PHP module"
 msgstr ""
 
-#: src/Core/Install.php:230
+#: src/Core/Install.php:231
 msgid "XML PHP module"
 msgstr ""
 
-#: src/Core/Install.php:231
+#: src/Core/Install.php:232
 msgid "iconv PHP module"
 msgstr ""
 
-#: src/Core/Install.php:232
+#: src/Core/Install.php:233
 msgid "POSIX PHP module"
 msgstr ""
 
-#: src/Core/Install.php:236 src/Core/Install.php:238
+#: src/Core/Install.php:237 src/Core/Install.php:239
 msgid "Apache mod_rewrite module"
 msgstr ""
 
-#: src/Core/Install.php:236
+#: src/Core/Install.php:237
 msgid ""
 "Error: Apache webserver mod-rewrite module is required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:244
+#: src/Core/Install.php:245
 msgid "Error: libCURL PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:248
+#: src/Core/Install.php:249
 msgid ""
 "Error: GD graphics PHP module with JPEG support required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:252
+#: src/Core/Install.php:253
 msgid "Error: openssl PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:256
+#: src/Core/Install.php:257
 msgid "Error: PDO or MySQLi PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:260
+#: src/Core/Install.php:261
 msgid "Error: The MySQL driver for PDO is not installed."
 msgstr ""
 
-#: src/Core/Install.php:264
+#: src/Core/Install.php:265
 msgid "Error: mb_string PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:268
+#: src/Core/Install.php:269
 msgid "Error: iconv PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:272
+#: src/Core/Install.php:273
 msgid "Error: POSIX PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:282
+#: src/Core/Install.php:283
 msgid "Error, XML PHP module required but not installed."
 msgstr ""
 
-#: src/Core/Install.php:301
+#: src/Core/Install.php:302
 msgid ""
 "The web installer needs to be able to create a file called \"local.ini.php\" "
 "in the \"config\" folder of your web server and it is unable to do so."
 msgstr ""
 
-#: src/Core/Install.php:302
+#: src/Core/Install.php:303
 msgid ""
 "This is most often a permission setting, as the web server may not be able "
 "to write files in your folder - even if you can."
 msgstr ""
 
-#: src/Core/Install.php:303
+#: src/Core/Install.php:304
 msgid ""
 "At the end of this procedure, we will give you a text to save in a file "
 "named local.ini.php in your Friendica \"config\" folder."
 msgstr ""
 
-#: src/Core/Install.php:304
+#: src/Core/Install.php:305
 msgid ""
 "You can alternatively skip this procedure and perform a manual installation. "
 "Please see the file \"INSTALL.txt\" for instructions."
 msgstr ""
 
-#: src/Core/Install.php:307
+#: src/Core/Install.php:308
 msgid "config/local.ini.php is writable"
 msgstr ""
 
-#: src/Core/Install.php:325
+#: src/Core/Install.php:326
 msgid ""
 "Friendica uses the Smarty3 template engine to render its web views. Smarty3 "
 "compiles templates to PHP to speed up rendering."
 msgstr ""
 
-#: src/Core/Install.php:326
+#: src/Core/Install.php:327
 msgid ""
 "In order to store these compiled templates, the web server needs to have "
 "write access to the directory view/smarty3/ under the Friendica top level "
 "folder."
 msgstr ""
 
-#: src/Core/Install.php:327
+#: src/Core/Install.php:328
 msgid ""
 "Please ensure that the user that your web server runs as (e.g. www-data) has "
 "write access to this folder."
 msgstr ""
 
-#: src/Core/Install.php:328
+#: src/Core/Install.php:329
 msgid ""
 "Note: as a security measure, you should give the web server write access to "
 "view/smarty3/ only--not the template files (.tpl) that it contains."
 msgstr ""
 
-#: src/Core/Install.php:331
+#: src/Core/Install.php:332
 msgid "view/smarty3 is writable"
 msgstr ""
 
-#: src/Core/Install.php:356
+#: src/Core/Install.php:357
 msgid ""
 "Url rewrite in .htaccess is not working. Check your server configuration."
 msgstr ""
 
-#: src/Core/Install.php:358
+#: src/Core/Install.php:359
 msgid "Error message from Curl when fetching"
 msgstr ""
 
-#: src/Core/Install.php:362
+#: src/Core/Install.php:363
 msgid "Url rewrite is working"
 msgstr ""
 
-#: src/Core/Install.php:389
+#: src/Core/Install.php:390
 msgid "ImageMagick PHP extension is not installed"
 msgstr ""
 
-#: src/Core/Install.php:391
+#: src/Core/Install.php:392
 msgid "ImageMagick PHP extension is installed"
 msgstr ""
 
-#: src/Core/Install.php:393
+#: src/Core/Install.php:394
 msgid "ImageMagick supports GIF"
 msgstr ""
 
@@ -8051,11 +8067,16 @@ msgstr ""
 msgid "The contact entries have been archived"
 msgstr ""
 
-#: src/Core/Console/PostUpdate.php:32
+#: src/Core/Console/PostUpdate.php:49
+#, php-format
+msgid "Post update version number has been set to %s."
+msgstr ""
+
+#: src/Core/Console/PostUpdate.php:57
 msgid "Execute pending post updates."
 msgstr ""
 
-#: src/Core/Console/PostUpdate.php:38
+#: src/Core/Console/PostUpdate.php:63
 msgid "All pending post updates are done."
 msgstr ""
 
@@ -8115,20 +8136,20 @@ msgstr ""
 msgid "%s may attend %s's event"
 msgstr ""
 
-#: src/Core/NotificationsManager.php:360
+#: src/Core/NotificationsManager.php:372
 #, php-format
 msgid "%s is now friends with %s"
 msgstr ""
 
-#: src/Core/NotificationsManager.php:626
+#: src/Core/NotificationsManager.php:638
 msgid "Friend Suggestion"
 msgstr ""
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "Friend/Connect Request"
 msgstr ""
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "New Follower"
 msgstr ""
 
@@ -8164,7 +8185,7 @@ msgstr[1] ""
 msgid "Done. You can now login with your username and password"
 msgstr ""
 
-#: src/Worker/Delivery.php:423
+#: src/Worker/Delivery.php:425
 msgid "(no subject)"
 msgstr ""
 
@@ -8299,15 +8320,15 @@ msgstr ""
 msgid "Video"
 msgstr ""
 
-#: src/App.php:785
+#: src/App.php:798
 msgid "Delete this item?"
 msgstr ""
 
-#: src/App.php:787
+#: src/App.php:800
 msgid "show fewer"
 msgstr ""
 
-#: src/App.php:1385
+#: src/App.php:1416
 msgid "No system theme config value set."
 msgstr ""
 
@@ -8395,43 +8416,47 @@ msgstr ""
 msgid "Privacy Statement"
 msgstr ""
 
-#: src/Protocol/OStatus.php:1813
+#: src/Module/Proxy.php:138
+msgid "Bad Request."
+msgstr ""
+
+#: src/Protocol/OStatus.php:1823
 #, php-format
 msgid "%s is now following %s."
 msgstr ""
 
-#: src/Protocol/OStatus.php:1814
+#: src/Protocol/OStatus.php:1824
 msgid "following"
 msgstr ""
 
-#: src/Protocol/OStatus.php:1817
+#: src/Protocol/OStatus.php:1827
 #, php-format
 msgid "%s stopped following %s."
 msgstr ""
 
-#: src/Protocol/OStatus.php:1818
+#: src/Protocol/OStatus.php:1828
 msgid "stopped following"
 msgstr ""
 
-#: src/Protocol/DFRN.php:1525 src/Model/Contact.php:1956
+#: src/Protocol/DFRN.php:1528 src/Model/Contact.php:1974
 #, php-format
 msgid "%s's birthday"
 msgstr ""
 
-#: src/Protocol/DFRN.php:1526 src/Model/Contact.php:1957
+#: src/Protocol/DFRN.php:1529 src/Model/Contact.php:1975
 #, php-format
 msgid "Happy Birthday %s"
 msgstr ""
 
-#: src/Protocol/Diaspora.php:2417
+#: src/Protocol/Diaspora.php:2434
 msgid "Sharing notification from Diaspora network"
 msgstr ""
 
-#: src/Protocol/Diaspora.php:3514
+#: src/Protocol/Diaspora.php:3531
 msgid "Attachments:"
 msgstr ""
 
-#: src/Util/Temporal.php:147 src/Model/Profile.php:745
+#: src/Util/Temporal.php:147 src/Model/Profile.php:758
 msgid "Birthday:"
 msgstr ""
 
@@ -8500,134 +8525,134 @@ msgstr ""
 msgid "[no subject]"
 msgstr ""
 
-#: src/Model/Contact.php:942
+#: src/Model/Contact.php:953
 msgid "Drop Contact"
 msgstr ""
 
-#: src/Model/Contact.php:1399
+#: src/Model/Contact.php:1408
 msgid "Organisation"
 msgstr ""
 
-#: src/Model/Contact.php:1403
+#: src/Model/Contact.php:1412
 msgid "News"
 msgstr ""
 
-#: src/Model/Contact.php:1407
+#: src/Model/Contact.php:1416
 msgid "Forum"
 msgstr ""
 
-#: src/Model/Contact.php:1587
+#: src/Model/Contact.php:1598
 msgid "Connect URL missing."
 msgstr ""
 
-#: src/Model/Contact.php:1596
+#: src/Model/Contact.php:1607
 msgid ""
 "The contact could not be added. Please check the relevant network "
 "credentials in your Settings -> Social Networks page."
 msgstr ""
 
-#: src/Model/Contact.php:1635
+#: src/Model/Contact.php:1646
 msgid ""
 "This site is not configured to allow communications with other networks."
 msgstr ""
 
-#: src/Model/Contact.php:1636 src/Model/Contact.php:1650
+#: src/Model/Contact.php:1647 src/Model/Contact.php:1661
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr ""
 
-#: src/Model/Contact.php:1648
+#: src/Model/Contact.php:1659
 msgid "The profile address specified does not provide adequate information."
 msgstr ""
 
-#: src/Model/Contact.php:1653
+#: src/Model/Contact.php:1664
 msgid "An author or name was not found."
 msgstr ""
 
-#: src/Model/Contact.php:1656
+#: src/Model/Contact.php:1667
 msgid "No browser URL could be matched to this address."
 msgstr ""
 
-#: src/Model/Contact.php:1659
+#: src/Model/Contact.php:1670
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr ""
 
-#: src/Model/Contact.php:1660
+#: src/Model/Contact.php:1671
 msgid "Use mailto: in front of address to force email check."
 msgstr ""
 
-#: src/Model/Contact.php:1666
+#: src/Model/Contact.php:1677
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr ""
 
-#: src/Model/Contact.php:1671
+#: src/Model/Contact.php:1682
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
 msgstr ""
 
-#: src/Model/Contact.php:1722
+#: src/Model/Contact.php:1733
 msgid "Unable to retrieve contact information."
 msgstr ""
 
-#: src/Model/Event.php:59 src/Model/Event.php:76 src/Model/Event.php:428
-#: src/Model/Event.php:897
+#: src/Model/Event.php:60 src/Model/Event.php:77 src/Model/Event.php:429
+#: src/Model/Event.php:904
 msgid "Starts:"
 msgstr ""
 
-#: src/Model/Event.php:62 src/Model/Event.php:82 src/Model/Event.php:429
-#: src/Model/Event.php:901
+#: src/Model/Event.php:63 src/Model/Event.php:83 src/Model/Event.php:430
+#: src/Model/Event.php:908
 msgid "Finishes:"
 msgstr ""
 
-#: src/Model/Event.php:377
+#: src/Model/Event.php:378
 msgid "all-day"
 msgstr ""
 
-#: src/Model/Event.php:400
+#: src/Model/Event.php:401
 msgid "Jun"
 msgstr ""
 
-#: src/Model/Event.php:403
+#: src/Model/Event.php:404
 msgid "Sept"
 msgstr ""
 
-#: src/Model/Event.php:426
+#: src/Model/Event.php:427
 msgid "No events to display"
 msgstr ""
 
-#: src/Model/Event.php:550
+#: src/Model/Event.php:551
 msgid "l, F j"
 msgstr ""
 
-#: src/Model/Event.php:581
+#: src/Model/Event.php:582
 msgid "Edit event"
 msgstr ""
 
-#: src/Model/Event.php:582
+#: src/Model/Event.php:583
 msgid "Duplicate event"
 msgstr ""
 
-#: src/Model/Event.php:583
+#: src/Model/Event.php:584
 msgid "Delete event"
 msgstr ""
 
-#: src/Model/Event.php:830
+#: src/Model/Event.php:837
 msgid "D g:i A"
 msgstr ""
 
-#: src/Model/Event.php:831
+#: src/Model/Event.php:838
 msgid "g:i A"
 msgstr ""
 
-#: src/Model/Event.php:916 src/Model/Event.php:918
+#: src/Model/Event.php:923 src/Model/Event.php:925
 msgid "Show map"
 msgstr ""
 
-#: src/Model/Event.php:917
+#: src/Model/Event.php:924
 msgid "Hide map"
 msgstr ""
 
@@ -8707,7 +8732,7 @@ msgstr ""
 msgid "An error occurred creating your self contact. Please try again."
 msgstr ""
 
-#: src/Model/User.php:561 src/Content/ContactSelector.php:166
+#: src/Model/User.php:561 src/Content/ContactSelector.php:171
 msgid "Friends"
 msgstr ""
 
@@ -8810,129 +8835,129 @@ msgstr ""
 msgid "Edit groups"
 msgstr ""
 
-#: src/Model/Profile.php:97
+#: src/Model/Profile.php:110
 msgid "Requested account is not available."
 msgstr ""
 
-#: src/Model/Profile.php:163 src/Model/Profile.php:399
-#: src/Model/Profile.php:846
+#: src/Model/Profile.php:176 src/Model/Profile.php:412
+#: src/Model/Profile.php:859
 msgid "Edit profile"
 msgstr ""
 
-#: src/Model/Profile.php:333
+#: src/Model/Profile.php:346
 msgid "Atom feed"
 msgstr ""
 
-#: src/Model/Profile.php:372
+#: src/Model/Profile.php:385
 msgid "Manage/edit profiles"
 msgstr ""
 
-#: src/Model/Profile.php:550 src/Model/Profile.php:639
+#: src/Model/Profile.php:563 src/Model/Profile.php:652
 msgid "g A l F d"
 msgstr ""
 
-#: src/Model/Profile.php:551
+#: src/Model/Profile.php:564
 msgid "F d"
 msgstr ""
 
-#: src/Model/Profile.php:604 src/Model/Profile.php:690
+#: src/Model/Profile.php:617 src/Model/Profile.php:703
 msgid "[today]"
 msgstr ""
 
-#: src/Model/Profile.php:615
+#: src/Model/Profile.php:628
 msgid "Birthday Reminders"
 msgstr ""
 
-#: src/Model/Profile.php:616
+#: src/Model/Profile.php:629
 msgid "Birthdays this week:"
 msgstr ""
 
-#: src/Model/Profile.php:677
+#: src/Model/Profile.php:690
 msgid "[No description]"
 msgstr ""
 
-#: src/Model/Profile.php:704
+#: src/Model/Profile.php:717
 msgid "Event Reminders"
 msgstr ""
 
-#: src/Model/Profile.php:705
+#: src/Model/Profile.php:718
 msgid "Upcoming events the next 7 days:"
 msgstr ""
 
-#: src/Model/Profile.php:728
+#: src/Model/Profile.php:741
 msgid "Member since:"
 msgstr ""
 
-#: src/Model/Profile.php:736
+#: src/Model/Profile.php:749
 msgid "j F, Y"
 msgstr ""
 
-#: src/Model/Profile.php:737
+#: src/Model/Profile.php:750
 msgid "j F"
 msgstr ""
 
-#: src/Model/Profile.php:752
+#: src/Model/Profile.php:765
 msgid "Age:"
 msgstr ""
 
-#: src/Model/Profile.php:765
+#: src/Model/Profile.php:778
 #, php-format
 msgid "for %1$d %2$s"
 msgstr ""
 
-#: src/Model/Profile.php:789
+#: src/Model/Profile.php:802
 msgid "Religion:"
 msgstr ""
 
-#: src/Model/Profile.php:797
+#: src/Model/Profile.php:810
 msgid "Hobbies/Interests:"
 msgstr ""
 
-#: src/Model/Profile.php:809
+#: src/Model/Profile.php:822
 msgid "Contact information and Social Networks:"
 msgstr ""
 
-#: src/Model/Profile.php:813
+#: src/Model/Profile.php:826
 msgid "Musical interests:"
 msgstr ""
 
-#: src/Model/Profile.php:817
+#: src/Model/Profile.php:830
 msgid "Books, literature:"
 msgstr ""
 
-#: src/Model/Profile.php:821
+#: src/Model/Profile.php:834
 msgid "Television:"
 msgstr ""
 
-#: src/Model/Profile.php:825
+#: src/Model/Profile.php:838
 msgid "Film/dance/culture/entertainment:"
 msgstr ""
 
-#: src/Model/Profile.php:829
+#: src/Model/Profile.php:842
 msgid "Love/Romance:"
 msgstr ""
 
-#: src/Model/Profile.php:833
+#: src/Model/Profile.php:846
 msgid "Work/employment:"
 msgstr ""
 
-#: src/Model/Profile.php:837
+#: src/Model/Profile.php:850
 msgid "School/education:"
 msgstr ""
 
-#: src/Model/Profile.php:842
+#: src/Model/Profile.php:855
 msgid "Forums:"
 msgstr ""
 
-#: src/Model/Profile.php:936
+#: src/Model/Profile.php:949
 msgid "Only You Can See This"
 msgstr ""
 
-#: src/Model/Profile.php:944 src/Model/Profile.php:947
+#: src/Model/Profile.php:957 src/Model/Profile.php:960
 msgid "Tips for New Members"
 msgstr ""
 
-#: src/Model/Profile.php:1106
+#: src/Model/Profile.php:1119
 #, php-format
 msgid "OpenWebAuth: %1$s welcomes %2$s"
 msgstr ""
@@ -8956,27 +8981,27 @@ msgid_plural "%d invitations available"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Content/Widget.php:157
+#: src/Content/Widget.php:154
 msgid "Networks"
 msgstr ""
 
-#: src/Content/Widget.php:160
+#: src/Content/Widget.php:157
 msgid "All Networks"
 msgstr ""
 
-#: src/Content/Widget.php:198 src/Content/Feature.php:118
+#: src/Content/Widget.php:195 src/Content/Feature.php:118
 msgid "Saved Folders"
 msgstr ""
 
-#: src/Content/Widget.php:201 src/Content/Widget.php:241
+#: src/Content/Widget.php:198 src/Content/Widget.php:238
 msgid "Everything"
 msgstr ""
 
-#: src/Content/Widget.php:238
+#: src/Content/Widget.php:235
 msgid "Categories"
 msgstr ""
 
-#: src/Content/Widget.php:305
+#: src/Content/Widget.php:302
 #, php-format
 msgid "%d contact in common"
 msgid_plural "%d contacts in common"
@@ -9052,230 +9077,234 @@ msgid "GNU Social Connector"
 msgstr ""
 
 #: src/Content/ContactSelector.php:92
+msgid "ActivityPub"
+msgstr ""
+
+#: src/Content/ContactSelector.php:93
 msgid "pnut"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Male"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Female"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Male"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Female"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Male"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Female"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transgender"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Intersex"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transsexual"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Hermaphrodite"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Neuter"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Non-specific"
 msgstr ""
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Other"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Males"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Females"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Gay"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Lesbian"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "No Preference"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Bisexual"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Autosexual"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Abstinent"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Virgin"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Deviant"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Fetish"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Oodles"
 msgstr ""
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Nonsexual"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Single"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Lonely"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Available"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unavailable"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Has crush"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Infatuated"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Dating"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unfaithful"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Sex Addict"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Friends/Benefits"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Casual"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Engaged"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Married"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily married"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Partners"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Cohabiting"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Common law"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Happy"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Not looking"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Swinger"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Betrayed"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Separated"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unstable"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Divorced"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily divorced"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Widowed"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Uncertain"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "It's complicated"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Don't care"
 msgstr ""
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Ask me"
 msgstr ""
 
@@ -9622,27 +9651,27 @@ msgstr ""
 msgid "Embedded content"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:423
+#: src/Content/Text/BBCode.php:422
 msgid "view full size"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:853 src/Content/Text/BBCode.php:1626
-#: src/Content/Text/BBCode.php:1627
+#: src/Content/Text/BBCode.php:854 src/Content/Text/BBCode.php:1623
+#: src/Content/Text/BBCode.php:1624
 msgid "Image/photo"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1553 src/Content/Text/BBCode.php:1575
+#: src/Content/Text/BBCode.php:1550 src/Content/Text/BBCode.php:1572
 msgid "$1 wrote:"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1635 src/Content/Text/BBCode.php:1636
+#: src/Content/Text/BBCode.php:1632 src/Content/Text/BBCode.php:1633
 msgid "Encrypted content"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1755
+#: src/Content/Text/BBCode.php:1752
 msgid "Invalid source protocol"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:1766
+#: src/Content/Text/BBCode.php:1763
 msgid "Invalid link protocol"
 msgstr ""
diff --git a/view/js/addon-hooks.js b/view/js/addon-hooks.js
deleted file mode 100644 (file)
index 3e1cb48..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * @file addon-hooks.js
- * @brief Provide a way for add-ons to register a JavaScript hook
- */
-
-var addon_hooks = {};
-
-/**
- * @brief Register a JavaScript hook to be called from other Javascript files
- * @pre the .js file from which the hook will be called is included in the document response
- * @param type which type of hook i.e. where should it be called along with other hooks of the same type
- * @param hookfnstr name of the JavaScript function name that needs to be called
- */
-function Addon_registerHook(type, hookfnstr)
-{
-       if (!addon_hooks.hasOwnProperty(type)) {
-               addon_hooks[type] = [];
-       }
-
-       addon_hooks[type].push(hookfnstr);
-}
-
-/**
- * @brief Call all registered hooks of a certain type, i.e. at the same point of the JavaScript code execution
- * @param typeOfHook string indicating which type of hooks to be called among the registered hooks
- */
-function callAddonHooks(typeOfHook)
-{
-       if (typeof addon_hooks !== 'undefined') {
-               var myTypeOfHooks = addon_hooks[typeOfHook];
-               if (typeof myTypeOfHooks !== 'undefined') {
-                       for (addon_hook_idx = 0; addon_hook_idx < myTypeOfHooks.length; addon_hook_idx++) {
-                               var hookfnstr = myTypeOfHooks[addon_hook_idx];
-                               var hookfn = window[hookfnstr];
-                               if (typeof hookfn === "function") {
-                                       hookfn();
-                               }
-                       }
-               }
-       }
-}
index 83086c82b037b4f322bf832b98e233fcde979f18..7e726248d3fd0f3c939dc7957a407ec4a266cbee 100644 (file)
@@ -485,14 +485,12 @@ function liveUpdate(src) {
                $('.wall-item-body', data).imagesLoaded(function() {
                        updateConvItems(data);
 
+                       document.dispatchEvent(new Event('postprocess_liveupdate'));
+
                        // Update the scroll position.
                        $(window).scrollTop($(window).scrollTop() + $("section").height() - orgHeight);
                });
-
-               callAddonHooks("postprocess_liveupdate");
-
        });
-
 }
 
 function imgbright(node) {
@@ -676,6 +674,7 @@ function preview_post() {
                        if (data.preview) {
                                $("#jot-preview-content").html(data.preview);
                                $("#jot-preview-content" + " a").click(function() {return false;});
+                               document.dispatchEvent(new Event('postprocess_liveupdate'));
                        }
                },
                "json"
@@ -742,6 +741,8 @@ function loadScrollContent() {
                } else {
                        $("#scroll-end").fadeIn('normal');
                }
+
+               document.dispatchEvent(new Event('postprocess_liveupdate'));
        });
 }
 
index 7b87e7d3270c8be92eba69b4142bba414f8a8842..81d0eb6c16e59fdc9d48627c25c7e43b30e299a2 100644 (file)
@@ -12,8 +12,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: friendica\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-25 15:34+0000\n"
-"PO-Revision-Date: 2018-09-22 16:53+0000\n"
+"POT-Creation-Date: 2018-09-27 21:18+0000\n"
+"PO-Revision-Date: 2018-10-03 13:24+0000\n"
 "Last-Translator: Aditoo\n"
 "Language-Team: Czech (http://www.transifex.com/Friendica/friendica/language/cs/)\n"
 "MIME-Version: 1.0\n"
@@ -22,47 +22,47 @@ msgstr ""
 "Language: cs\n"
 "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
 
-#: index.php:261 mod/apps.php:14
+#: index.php:265 mod/apps.php:14
 msgid "You must be logged in to use addons. "
 msgstr "Pro použití doplňků musíte být přihlášen/a."
 
-#: index.php:308 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
+#: index.php:312 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
 #: mod/help.php:62
 msgid "Not Found"
 msgstr "Nenalezeno"
 
-#: index.php:313 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
+#: index.php:317 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
 #: mod/cal.php:44
 msgid "Page not found."
 msgstr "Stránka nenalezena"
 
-#: index.php:431 mod/group.php:83 mod/profperm.php:29
+#: index.php:435 mod/group.php:83 mod/profperm.php:29
 msgid "Permission denied"
 msgstr "Nedostatečné oprávnění"
 
-#: index.php:432 include/items.php:412 mod/crepair.php:100
+#: index.php:436 include/items.php:413 mod/crepair.php:100
 #: mod/wallmessage.php:16 mod/wallmessage.php:40 mod/wallmessage.php:79
-#: mod/wallmessage.php:103 mod/dfrn_confirm.php:66 mod/dirfind.php:27
+#: mod/wallmessage.php:103 mod/dfrn_confirm.php:67 mod/dirfind.php:27
 #: mod/manage.php:131 mod/settings.php:43 mod/settings.php:149
 #: mod/settings.php:665 mod/common.php:28 mod/network.php:34 mod/group.php:26
 #: mod/delegate.php:27 mod/delegate.php:45 mod/delegate.php:56
-#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:17
-#: mod/unfollow.php:59 mod/unfollow.php:93 mod/register.php:53
+#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:20
+#: mod/unfollow.php:73 mod/unfollow.php:105 mod/register.php:53
 #: mod/notifications.php:67 mod/message.php:60 mod/message.php:105
 #: mod/ostatus_subscribe.php:17 mod/nogroup.php:23 mod/suggest.php:61
 #: mod/wall_upload.php:104 mod/wall_upload.php:107 mod/api.php:35
 #: mod/api.php:40 mod/profile_photo.php:29 mod/profile_photo.php:176
 #: mod/profile_photo.php:198 mod/wall_attach.php:80 mod/wall_attach.php:83
-#: mod/item.php:166 mod/uimport.php:28 mod/cal.php:306 mod/regmod.php:108
+#: mod/item.php:166 mod/uimport.php:15 mod/cal.php:306 mod/regmod.php:108
 #: mod/editpost.php:19 mod/fsuggest.php:80 mod/allfriends.php:23
-#: mod/contacts.php:381 mod/events.php:193 mod/follow.php:54
-#: mod/follow.php:118 mod/attach.php:39 mod/poke.php:145 mod/invite.php:21
+#: mod/contacts.php:387 mod/events.php:195 mod/follow.php:54
+#: mod/follow.php:118 mod/attach.php:39 mod/poke.php:144 mod/invite.php:21
 #: mod/invite.php:112 mod/notes.php:32 mod/profiles.php:179
-#: mod/profiles.php:511 mod/photos.php:183 mod/photos.php:1065
+#: mod/profiles.php:511 mod/photos.php:183 mod/photos.php:1067
 msgid "Permission denied."
 msgstr "Přístup odmítnut."
 
-#: index.php:460
+#: index.php:464
 msgid "toggle mobile"
 msgstr "přepínat mobilní zobrazení"
 
@@ -96,13 +96,13 @@ msgstr "slackr"
 
 #: view/theme/duepuntozero/config.php:71 view/theme/quattro/config.php:73
 #: view/theme/vier/config.php:119 view/theme/frio/config.php:118
-#: mod/crepair.php:150 mod/install.php:206 mod/install.php:244
+#: mod/crepair.php:150 mod/install.php:204 mod/install.php:242
 #: mod/manage.php:184 mod/message.php:264 mod/message.php:430
-#: mod/fsuggest.php:114 mod/contacts.php:630 mod/events.php:533
-#: mod/localtime.php:56 mod/poke.php:195 mod/invite.php:155
-#: mod/profiles.php:577 mod/photos.php:1094 mod/photos.php:1180
-#: mod/photos.php:1452 mod/photos.php:1497 mod/photos.php:1536
-#: mod/photos.php:1596 src/Object/Post.php:795
+#: mod/fsuggest.php:114 mod/contacts.php:631 mod/events.php:560
+#: mod/localtime.php:56 mod/poke.php:194 mod/invite.php:155
+#: mod/profiles.php:577 mod/photos.php:1096 mod/photos.php:1182
+#: mod/photos.php:1454 mod/photos.php:1499 mod/photos.php:1538
+#: mod/photos.php:1598 src/Object/Post.php:795
 msgid "Submit"
 msgstr "Odeslat"
 
@@ -190,8 +190,8 @@ msgstr "Zadejte jméno nebo zájmy"
 
 #: view/theme/vier/theme.php:199 include/conversation.php:881
 #: mod/dirfind.php:231 mod/match.php:90 mod/suggest.php:86
-#: mod/allfriends.php:76 mod/contacts.php:604 mod/contacts.php:610
-#: mod/follow.php:143 src/Model/Contact.php:933 src/Content/Widget.php:61
+#: mod/allfriends.php:76 mod/contacts.php:611 mod/follow.php:143
+#: src/Model/Contact.php:944 src/Content/Widget.php:61
 msgid "Connect/Follow"
 msgstr "Spojit se/sledovat"
 
@@ -199,7 +199,7 @@ msgstr "Spojit se/sledovat"
 msgid "Examples: Robert Morgenstein, Fishing"
 msgstr "Příklady: Josef Dvořák, rybaření"
 
-#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:842
+#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:845
 #: src/Content/Widget.php:63
 msgid "Find"
 msgstr "Najít"
@@ -230,16 +230,16 @@ msgid "Local Directory"
 msgstr "Místní adresář"
 
 #: view/theme/vier/theme.php:251 include/text.php:909 src/Content/Nav.php:151
-#: src/Content/ForumManager.php:125
+#: src/Content/ForumManager.php:130
 msgid "Forums"
 msgstr "Fóra"
 
-#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:127
+#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:132
 msgid "External link to forum"
 msgstr "Externí odkaz na fórum"
 
-#: view/theme/vier/theme.php:256 include/items.php:489 src/Object/Post.php:429
-#: src/App.php:786 src/Content/Widget.php:310 src/Content/ForumManager.php:130
+#: view/theme/vier/theme.php:256 include/items.php:490 src/Object/Post.php:429
+#: src/App.php:799 src/Content/Widget.php:307 src/Content/ForumManager.php:135
 msgid "show more"
 msgstr "zobrazit více"
 
@@ -261,7 +261,7 @@ msgstr "Poznámka"
 
 #: view/theme/frio/config.php:114
 msgid "Check image permissions if all users are allowed to see the image"
-msgstr "Zkontrolovat povolení u obrázku, jestli všichni uživatelé mají povolení obrázek vidět"
+msgstr "Zkontrolujte povolení u obrázku, jestli mají všichni uživatelé povolení obrázek vidět"
 
 #: view/theme/frio/config.php:121
 msgid "Select color scheme"
@@ -305,7 +305,7 @@ msgstr "Barva pozadí přihlašovací stránky"
 
 #: view/theme/frio/config.php:137
 msgid "Leave background image and color empty for theme defaults"
-msgstr "Nechat obrázek a barvu pozadí prázdnou pro výchozí nastavení motivů"
+msgstr "Nechejte obrázek a barvu pozadí prázdnou pro výchozí nastavení motivů"
 
 #: view/theme/frio/theme.php:248
 msgid "Guest"
@@ -324,8 +324,8 @@ msgstr "Odhlásit se"
 msgid "End this session"
 msgstr "Konec této relace"
 
-#: view/theme/frio/theme.php:269 mod/contacts.php:689 mod/contacts.php:877
-#: src/Model/Profile.php:875 src/Content/Nav.php:100
+#: view/theme/frio/theme.php:269 mod/contacts.php:690 mod/contacts.php:880
+#: src/Model/Profile.php:888 src/Content/Nav.php:100
 msgid "Status"
 msgstr "Stav"
 
@@ -335,8 +335,8 @@ msgid "Your posts and conversations"
 msgstr "Vaše příspěvky a konverzace"
 
 #: view/theme/frio/theme.php:270 mod/newmember.php:24 mod/profperm.php:116
-#: mod/contacts.php:691 mod/contacts.php:893 src/Model/Profile.php:717
-#: src/Model/Profile.php:850 src/Model/Profile.php:883 src/Content/Nav.php:101
+#: mod/contacts.php:692 mod/contacts.php:896 src/Model/Profile.php:730
+#: src/Model/Profile.php:863 src/Model/Profile.php:896 src/Content/Nav.php:101
 msgid "Profile"
 msgstr "Profil"
 
@@ -344,7 +344,7 @@ msgstr "Profil"
 msgid "Your profile page"
 msgstr "Vaše profilová stránka"
 
-#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:891
+#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:904
 #: src/Content/Nav.php:102
 msgid "Photos"
 msgstr "Fotky"
@@ -353,8 +353,8 @@ msgstr "Fotky"
 msgid "Your photos"
 msgstr "Vaše fotky"
 
-#: view/theme/frio/theme.php:272 src/Model/Profile.php:899
-#: src/Model/Profile.php:902 src/Content/Nav.php:103
+#: view/theme/frio/theme.php:272 src/Model/Profile.php:912
+#: src/Model/Profile.php:915 src/Content/Nav.php:103
 msgid "Videos"
 msgstr "Videa"
 
@@ -363,7 +363,7 @@ msgid "Your videos"
 msgstr "Vaše videa"
 
 #: view/theme/frio/theme.php:273 view/theme/frio/theme.php:277 mod/cal.php:276
-#: mod/events.php:390 src/Model/Profile.php:911 src/Model/Profile.php:922
+#: mod/events.php:391 src/Model/Profile.php:924 src/Model/Profile.php:935
 #: src/Content/Nav.php:104 src/Content/Nav.php:170
 msgid "Events"
 msgstr "Události"
@@ -381,8 +381,8 @@ msgstr "Síť"
 msgid "Conversations from your friends"
 msgstr "Konverzace od Vašich přátel"
 
-#: view/theme/frio/theme.php:277 src/Model/Profile.php:914
-#: src/Model/Profile.php:925 src/Content/Nav.php:170
+#: view/theme/frio/theme.php:277 src/Model/Profile.php:927
+#: src/Model/Profile.php:938 src/Content/Nav.php:170
 msgid "Events and Calendar"
 msgstr "Události a kalendář"
 
@@ -404,8 +404,8 @@ msgid "Account settings"
 msgstr "Nastavení účtu"
 
 #: view/theme/frio/theme.php:280 include/text.php:906 mod/viewcontacts.php:125
-#: mod/contacts.php:836 mod/contacts.php:905 src/Model/Profile.php:954
-#: src/Model/Profile.php:957 src/Content/Nav.php:147 src/Content/Nav.php:213
+#: mod/contacts.php:839 mod/contacts.php:908 src/Model/Profile.php:967
+#: src/Model/Profile.php:970 src/Content/Nav.php:147 src/Content/Nav.php:213
 msgid "Contacts"
 msgstr "Kontakty"
 
@@ -463,37 +463,37 @@ msgstr "%s: Aktualizuji author-id a owner-id v tabulce položek a vláken."
 msgid "%s: Updating post-type."
 msgstr "%s: Aktualizuji post-type."
 
-#: include/items.php:355 mod/display.php:70 mod/display.php:245
-#: mod/display.php:341 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
+#: include/items.php:356 mod/display.php:71 mod/display.php:254
+#: mod/display.php:350 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
 #: mod/notice.php:22 mod/viewsrc.php:22
 msgid "Item not found."
 msgstr "Položka nenalezena."
 
-#: include/items.php:393
+#: include/items.php:394
 msgid "Do you really want to delete this item?"
 msgstr "Opravdu chcete smazat tuto položku?"
 
-#: include/items.php:395 mod/settings.php:1100 mod/settings.php:1106
+#: include/items.php:396 mod/settings.php:1100 mod/settings.php:1106
 #: mod/settings.php:1113 mod/settings.php:1117 mod/settings.php:1121
 #: mod/settings.php:1125 mod/settings.php:1129 mod/settings.php:1133
 #: mod/settings.php:1153 mod/settings.php:1154 mod/settings.php:1155
 #: mod/settings.php:1156 mod/settings.php:1157 mod/register.php:237
 #: mod/message.php:154 mod/suggest.php:40 mod/dfrn_request.php:645
-#: mod/api.php:110 mod/contacts.php:465 mod/follow.php:150
+#: mod/api.php:110 mod/contacts.php:471 mod/follow.php:150
 #: mod/profiles.php:541 mod/profiles.php:544 mod/profiles.php:566
 msgid "Yes"
 msgstr "Ano"
 
-#: include/items.php:398 include/conversation.php:1179 mod/videos.php:146
-#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:120
+#: include/items.php:399 include/conversation.php:1179 mod/videos.php:146
+#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:130
 #: mod/message.php:157 mod/tagrm.php:19 mod/tagrm.php:91 mod/suggest.php:43
-#: mod/dfrn_request.php:655 mod/editpost.php:140 mod/contacts.php:468
+#: mod/dfrn_request.php:655 mod/editpost.php:146 mod/contacts.php:474
 #: mod/follow.php:161 mod/fbrowser.php:104 mod/fbrowser.php:135
 #: mod/photos.php:255 mod/photos.php:327
 msgid "Cancel"
 msgstr "Zrušit"
 
-#: include/items.php:483 src/Content/Feature.php:96
+#: include/items.php:484 src/Content/Feature.php:96
 msgid "Archives"
 msgstr "Archivy"
 
@@ -562,16 +562,16 @@ msgstr "příspěvek/položka"
 msgid "%1$s marked %2$s's %3$s as favorite"
 msgstr "%1$s označil/a %3$s uživatele %2$s jako oblíbené"
 
-#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1509
 msgid "Likes"
 msgstr "Libí se"
 
-#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1509
 msgid "Dislikes"
 msgstr "Nelibí se"
 
 #: include/conversation.php:546 include/conversation.php:1492
-#: mod/photos.php:1508
+#: mod/photos.php:1510
 msgid "Attending"
 msgid_plural "Attending"
 msgstr[0] "Účastní se"
@@ -579,20 +579,20 @@ msgstr[1] "Účastní se"
 msgstr[2] "Účastní se"
 msgstr[3] "Účastní se"
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Not attending"
 msgstr "Neúčastní se"
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Might attend"
 msgstr "Mohl/a by se zúčastnit"
 
-#: include/conversation.php:626 mod/photos.php:1564 src/Object/Post.php:195
+#: include/conversation.php:626 mod/photos.php:1566 src/Object/Post.php:195
 msgid "Select"
 msgstr "Vybrat"
 
 #: include/conversation.php:627 mod/settings.php:736 mod/admin.php:1906
-#: mod/contacts.php:852 mod/contacts.php:1130 mod/photos.php:1565
+#: mod/contacts.php:855 mod/contacts.php:1133 mod/photos.php:1567
 msgid "Delete"
 msgstr "Odstranit"
 
@@ -621,7 +621,7 @@ msgstr "Zobrazit v kontextu"
 
 #: include/conversation.php:698 include/conversation.php:1160
 #: mod/wallmessage.php:145 mod/message.php:263 mod/message.php:431
-#: mod/editpost.php:115 mod/photos.php:1480 src/Object/Post.php:401
+#: mod/editpost.php:121 mod/photos.php:1482 src/Object/Post.php:401
 msgid "Please wait"
 msgstr "Čekejte prosím"
 
@@ -633,36 +633,36 @@ msgstr "odstranit"
 msgid "Delete Selected Items"
 msgstr "Smazat vybrané položky"
 
-#: include/conversation.php:867 src/Model/Contact.php:937
+#: include/conversation.php:867 src/Model/Contact.php:948
 msgid "View Status"
 msgstr "Zobrazit stav"
 
 #: include/conversation.php:868 include/conversation.php:884
 #: mod/dirfind.php:230 mod/directory.php:164 mod/match.php:89
-#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:877
-#: src/Model/Contact.php:930 src/Model/Contact.php:938
+#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:888
+#: src/Model/Contact.php:941 src/Model/Contact.php:949
 msgid "View Profile"
 msgstr "Zobrazit profil"
 
-#: include/conversation.php:869 src/Model/Contact.php:939
+#: include/conversation.php:869 src/Model/Contact.php:950
 msgid "View Photos"
 msgstr "Zobrazit fotky"
 
-#: include/conversation.php:870 src/Model/Contact.php:931
-#: src/Model/Contact.php:940
+#: include/conversation.php:870 src/Model/Contact.php:942
+#: src/Model/Contact.php:951
 msgid "Network Posts"
 msgstr "Zobrazit Příspěvky sítě"
 
-#: include/conversation.php:871 src/Model/Contact.php:932
-#: src/Model/Contact.php:941
+#: include/conversation.php:871 src/Model/Contact.php:943
+#: src/Model/Contact.php:952
 msgid "View Contact"
 msgstr "Zobrazit kontakt"
 
-#: include/conversation.php:872 src/Model/Contact.php:943
+#: include/conversation.php:872 src/Model/Contact.php:954
 msgid "Send PM"
 msgstr "Poslat soukromou zprávu"
 
-#: include/conversation.php:876 src/Model/Contact.php:944
+#: include/conversation.php:876 src/Model/Contact.php:955
 msgid "Poke"
 msgstr "Šťouchnout"
 
@@ -794,85 +794,85 @@ msgid "Share"
 msgstr "Sdílet"
 
 #: include/conversation.php:1142 mod/wallmessage.php:143 mod/message.php:261
-#: mod/message.php:428 mod/editpost.php:101
+#: mod/message.php:428 mod/editpost.php:107
 msgid "Upload photo"
 msgstr "Nahrát fotku"
 
-#: include/conversation.php:1143 mod/editpost.php:102
+#: include/conversation.php:1143 mod/editpost.php:108
 msgid "upload photo"
 msgstr "nahrát fotku"
 
-#: include/conversation.php:1144 mod/editpost.php:103
+#: include/conversation.php:1144 mod/editpost.php:109
 msgid "Attach file"
 msgstr "Přiložit soubor"
 
-#: include/conversation.php:1145 mod/editpost.php:104
+#: include/conversation.php:1145 mod/editpost.php:110
 msgid "attach file"
 msgstr "přiložit soubor"
 
 #: include/conversation.php:1146 mod/wallmessage.php:144 mod/message.php:262
-#: mod/message.php:429 mod/editpost.php:105
+#: mod/message.php:429 mod/editpost.php:111
 msgid "Insert web link"
 msgstr "Vložit webový odkaz"
 
-#: include/conversation.php:1147 mod/editpost.php:106
+#: include/conversation.php:1147 mod/editpost.php:112
 msgid "web link"
 msgstr "webový odkaz"
 
-#: include/conversation.php:1148 mod/editpost.php:107
+#: include/conversation.php:1148 mod/editpost.php:113
 msgid "Insert video link"
 msgstr "Vložit odkaz na video"
 
-#: include/conversation.php:1149 mod/editpost.php:108
+#: include/conversation.php:1149 mod/editpost.php:114
 msgid "video link"
 msgstr "odkaz na video"
 
-#: include/conversation.php:1150 mod/editpost.php:109
+#: include/conversation.php:1150 mod/editpost.php:115
 msgid "Insert audio link"
 msgstr "Vložit odkaz na audio"
 
-#: include/conversation.php:1151 mod/editpost.php:110
+#: include/conversation.php:1151 mod/editpost.php:116
 msgid "audio link"
 msgstr "odkaz na audio"
 
-#: include/conversation.php:1152 mod/editpost.php:111
+#: include/conversation.php:1152 mod/editpost.php:117
 msgid "Set your location"
 msgstr "Nastavit vaši polohu"
 
-#: include/conversation.php:1153 mod/editpost.php:112
+#: include/conversation.php:1153 mod/editpost.php:118
 msgid "set location"
 msgstr "nastavit polohu"
 
-#: include/conversation.php:1154 mod/editpost.php:113
+#: include/conversation.php:1154 mod/editpost.php:119
 msgid "Clear browser location"
 msgstr "Vymazat polohu v prohlížeči"
 
-#: include/conversation.php:1155 mod/editpost.php:114
+#: include/conversation.php:1155 mod/editpost.php:120
 msgid "clear location"
 msgstr "vymazat polohu"
 
-#: include/conversation.php:1157 mod/editpost.php:129
+#: include/conversation.php:1157 mod/editpost.php:135
 msgid "Set title"
 msgstr "Nastavit nadpis"
 
-#: include/conversation.php:1159 mod/editpost.php:131
+#: include/conversation.php:1159 mod/editpost.php:137
 msgid "Categories (comma-separated list)"
 msgstr "Kategorie (seznam, oddělujte čárkou)"
 
-#: include/conversation.php:1161 mod/editpost.php:116
+#: include/conversation.php:1161 mod/editpost.php:122
 msgid "Permission settings"
 msgstr "Nastavení oprávnění"
 
-#: include/conversation.php:1162 mod/editpost.php:146
+#: include/conversation.php:1162 mod/editpost.php:152
 msgid "permissions"
 msgstr "oprávnění"
 
-#: include/conversation.php:1171 mod/editpost.php:126
+#: include/conversation.php:1171 mod/editpost.php:132
 msgid "Public post"
 msgstr "Veřejný příspěvek"
 
-#: include/conversation.php:1175 mod/editpost.php:137 mod/events.php:531
-#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
+#: include/conversation.php:1175 mod/editpost.php:143 mod/events.php:558
+#: mod/photos.php:1500 mod/photos.php:1539 mod/photos.php:1599
 #: src/Object/Post.php:804
 msgid "Preview"
 msgstr "Náhled"
@@ -889,12 +889,12 @@ msgstr "Zveřejnit v kontaktech"
 msgid "Private post"
 msgstr "Soukromý příspěvek"
 
-#: include/conversation.php:1191 mod/editpost.php:144
-#: src/Model/Profile.php:344
+#: include/conversation.php:1191 mod/editpost.php:150
+#: src/Model/Profile.php:357
 msgid "Message"
 msgstr "Zpráva"
 
-#: include/conversation.php:1192 mod/editpost.php:145
+#: include/conversation.php:1192 mod/editpost.php:151
 msgid "Browser"
 msgstr "Prohlížeč"
 
@@ -926,7 +926,7 @@ msgstr[1] "Neúčastní se"
 msgstr[2] "Neúčastní se"
 msgstr[3] "Neúčastní se"
 
-#: include/conversation.php:1498 src/Content/ContactSelector.php:122
+#: include/conversation.php:1498 src/Content/ContactSelector.php:127
 msgid "Undecided"
 msgid_plural "Undecided"
 msgstr[0] "Nerozhodnut"
@@ -1107,7 +1107,7 @@ msgstr "[Friendica:Oznámení] Obdrženo představení"
 #: include/enotify.php:285
 #, php-format
 msgid "You've received an introduction from '%1$s' at %2$s"
-msgstr "Obdržel/a jste představení od uživatele \"%1$s\" na %2$s"
+msgstr "Obdržel/a jste představení od uživatele „%1$s“ na %2$s"
 
 #: include/enotify.php:286
 #, php-format
@@ -1149,7 +1149,7 @@ msgstr "[Friendica:Oznámení] Obdržen návrh přátelství"
 #: include/enotify.php:328
 #, php-format
 msgid "You've received a friend suggestion from '%1$s' at %2$s"
-msgstr "Obdržel/a jste návrh přátelství od uživatele \"%1$s\" na %2$s"
+msgstr "Obdržel/a jste návrh přátelství od uživatele „%1$s“ na %2$s"
 
 #: include/enotify.php:329
 #, php-format
@@ -1177,7 +1177,7 @@ msgstr "[Friendica:Oznámení] Spojení přijato"
 #: include/enotify.php:349 include/enotify.php:364
 #, php-format
 msgid "'%1$s' has accepted your connection request at %2$s"
-msgstr "\"%1$s\" přijal/a Váš požadavek na spojení na %2$s"
+msgstr "„%1$s“ přijal/a Váš požadavek o spojení na %2$s"
 
 #: include/enotify.php:350 include/enotify.php:365
 #, php-format
@@ -1202,14 +1202,14 @@ msgid ""
 "communication - such as private messaging and some profile interactions. If "
 "this is a celebrity or community page, these settings were applied "
 "automatically."
-msgstr "\"%1$s\" se rozhodl/a Vás přijmout jako fanouška, což omezuje některé formy komunikace - například soukoromé zprávy a některé interakce s profily. Pokud je toto stránka celebrity či komunity, byla tato nastavení aplikována automaticky."
+msgstr "„%1$s“ se rozhodl/a Vás přijmout jako fanouška, což omezuje některé formy komunikace - například soukoromé zprávy a některé interakce s profily. Pokud je toto stránka celebrity či komunity, byla tato nastavení aplikována automaticky."
 
 #: include/enotify.php:372
 #, php-format
 msgid ""
 "'%1$s' may choose to extend this into a two-way or more permissive "
 "relationship in the future."
-msgstr "\"%1$s\" se může rozhodnout tento vztah v budoucnosti rozšířit do obousměrného či jiného liberálnějšího vztahu."
+msgstr "„%1$s“ se může rozhodnout tento vztah v budoucnosti rozšířit do oboustranného či jiného liberálnějšího vztahu."
 
 #: include/enotify.php:374
 #, php-format
@@ -1227,12 +1227,12 @@ msgstr "žádost o registraci"
 #: include/enotify.php:386
 #, php-format
 msgid "You've received a registration request from '%1$s' at %2$s"
-msgstr "Obdržel/a jste žádost o registraci od uživatele \"%1$s\" na %2$s"
+msgstr "Obdržel/a jste žádost o registraci od uživatele „%1$s“ na %2$s"
 
 #: include/enotify.php:387
 #, php-format
 msgid "You've received a [url=%1$s]registration request[/url] from %2$s."
-msgstr "Obdržel/a jste [url=%1$s]žádost o registraci[/url] od uživatele \"%2$s\"."
+msgstr "Obdržel/a jste [url=%1$s]žádost o registraci[/url] od uživatele %2$s."
 
 #: include/enotify.php:392
 #, php-format
@@ -1296,7 +1296,7 @@ msgstr[3] "%d kontaktů"
 msgid "View Contacts"
 msgstr "Zobrazit kontakty"
 
-#: include/text.php:889 mod/filer.php:35 mod/editpost.php:100 mod/notes.php:54
+#: include/text.php:889 mod/filer.php:35 mod/editpost.php:106 mod/notes.php:54
 msgid "Save"
 msgstr "Uložit"
 
@@ -1369,132 +1369,132 @@ msgstr "odmítnout"
 msgid "rebuffed"
 msgstr "odmítnul/a"
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:389
 msgid "Monday"
 msgstr "pondělí"
 
-#: include/text.php:972 src/Model/Event.php:389
+#: include/text.php:972 src/Model/Event.php:390
 msgid "Tuesday"
 msgstr "úterý"
 
-#: include/text.php:972 src/Model/Event.php:390
+#: include/text.php:972 src/Model/Event.php:391
 msgid "Wednesday"
 msgstr "středa"
 
-#: include/text.php:972 src/Model/Event.php:391
+#: include/text.php:972 src/Model/Event.php:392
 msgid "Thursday"
 msgstr "čtvrtek"
 
-#: include/text.php:972 src/Model/Event.php:392
+#: include/text.php:972 src/Model/Event.php:393
 msgid "Friday"
 msgstr "pátek"
 
-#: include/text.php:972 src/Model/Event.php:393
+#: include/text.php:972 src/Model/Event.php:394
 msgid "Saturday"
 msgstr "sobota"
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:387
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
 msgid "Sunday"
 msgstr "neděle"
 
-#: include/text.php:976 src/Model/Event.php:408
+#: include/text.php:976 src/Model/Event.php:409
 msgid "January"
 msgstr "leden"
 
-#: include/text.php:976 src/Model/Event.php:409
+#: include/text.php:976 src/Model/Event.php:410
 msgid "February"
 msgstr "únor"
 
-#: include/text.php:976 src/Model/Event.php:410
+#: include/text.php:976 src/Model/Event.php:411
 msgid "March"
 msgstr "březen"
 
-#: include/text.php:976 src/Model/Event.php:411
+#: include/text.php:976 src/Model/Event.php:412
 msgid "April"
 msgstr "duben"
 
-#: include/text.php:976 include/text.php:993 src/Model/Event.php:399
-#: src/Model/Event.php:412
+#: include/text.php:976 include/text.php:993 src/Model/Event.php:400
+#: src/Model/Event.php:413
 msgid "May"
 msgstr "květen"
 
-#: include/text.php:976 src/Model/Event.php:413
+#: include/text.php:976 src/Model/Event.php:414
 msgid "June"
 msgstr "červen"
 
-#: include/text.php:976 src/Model/Event.php:414
+#: include/text.php:976 src/Model/Event.php:415
 msgid "July"
 msgstr "červenec"
 
-#: include/text.php:976 src/Model/Event.php:415
+#: include/text.php:976 src/Model/Event.php:416
 msgid "August"
 msgstr "srpen"
 
-#: include/text.php:976 src/Model/Event.php:416
+#: include/text.php:976 src/Model/Event.php:417
 msgid "September"
 msgstr "září"
 
-#: include/text.php:976 src/Model/Event.php:417
+#: include/text.php:976 src/Model/Event.php:418
 msgid "October"
 msgstr "říjen"
 
-#: include/text.php:976 src/Model/Event.php:418
+#: include/text.php:976 src/Model/Event.php:419
 msgid "November"
 msgstr "listopad"
 
-#: include/text.php:976 src/Model/Event.php:419
+#: include/text.php:976 src/Model/Event.php:420
 msgid "December"
 msgstr "prosinec"
 
-#: include/text.php:990 src/Model/Event.php:380
+#: include/text.php:990 src/Model/Event.php:381
 msgid "Mon"
 msgstr "pon"
 
-#: include/text.php:990 src/Model/Event.php:381
+#: include/text.php:990 src/Model/Event.php:382
 msgid "Tue"
 msgstr "úte"
 
-#: include/text.php:990 src/Model/Event.php:382
+#: include/text.php:990 src/Model/Event.php:383
 msgid "Wed"
 msgstr "stř"
 
-#: include/text.php:990 src/Model/Event.php:383
+#: include/text.php:990 src/Model/Event.php:384
 msgid "Thu"
 msgstr "čtv"
 
-#: include/text.php:990 src/Model/Event.php:384
+#: include/text.php:990 src/Model/Event.php:385
 msgid "Fri"
 msgstr "pát"
 
-#: include/text.php:990 src/Model/Event.php:385
+#: include/text.php:990 src/Model/Event.php:386
 msgid "Sat"
 msgstr "sob"
 
-#: include/text.php:990 src/Model/Event.php:379
+#: include/text.php:990 src/Model/Event.php:380
 msgid "Sun"
 msgstr "ned"
 
-#: include/text.php:993 src/Model/Event.php:395
+#: include/text.php:993 src/Model/Event.php:396
 msgid "Jan"
 msgstr "led"
 
-#: include/text.php:993 src/Model/Event.php:396
+#: include/text.php:993 src/Model/Event.php:397
 msgid "Feb"
 msgstr "úno"
 
-#: include/text.php:993 src/Model/Event.php:397
+#: include/text.php:993 src/Model/Event.php:398
 msgid "Mar"
 msgstr "bře"
 
-#: include/text.php:993 src/Model/Event.php:398
+#: include/text.php:993 src/Model/Event.php:399
 msgid "Apr"
 msgstr "dub"
 
-#: include/text.php:993 src/Model/Event.php:401
+#: include/text.php:993 src/Model/Event.php:402
 msgid "Jul"
 msgstr "čvc"
 
-#: include/text.php:993 src/Model/Event.php:402
+#: include/text.php:993 src/Model/Event.php:403
 msgid "Aug"
 msgstr "srp"
 
@@ -1502,15 +1502,15 @@ msgstr "srp"
 msgid "Sep"
 msgstr "zář"
 
-#: include/text.php:993 src/Model/Event.php:404
+#: include/text.php:993 src/Model/Event.php:405
 msgid "Oct"
 msgstr "říj"
 
-#: include/text.php:993 src/Model/Event.php:405
+#: include/text.php:993 src/Model/Event.php:406
 msgid "Nov"
 msgstr "lis"
 
-#: include/text.php:993 src/Model/Event.php:406
+#: include/text.php:993 src/Model/Event.php:407
 msgid "Dec"
 msgstr "pro"
 
@@ -1519,7 +1519,7 @@ msgstr "pro"
 msgid "Content warning: %s"
 msgstr "Varování o obsahu: %s"
 
-#: include/text.php:1204 mod/videos.php:375
+#: include/text.php:1204 mod/videos.php:376
 msgid "View Video"
 msgstr "Zobrazit video"
 
@@ -1539,7 +1539,7 @@ msgstr "Zobrazit na separátní stránce"
 msgid "view on separate page"
 msgstr "zobrazit na separátní stránce"
 
-#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:609
+#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:616
 msgid "link to source"
 msgstr "odkaz na zdroj"
 
@@ -1563,7 +1563,7 @@ msgstr "příspěvek"
 msgid "Item filed"
 msgstr "Položka vyplněna"
 
-#: include/api.php:1138
+#: include/api.php:1140
 #, php-format
 msgid "Daily posting limit of %d post reached. The post was rejected."
 msgid_plural "Daily posting limit of %d posts reached. The post was rejected."
@@ -1572,7 +1572,7 @@ msgstr[1] "Byl dosažen denní limit %d příspěvků. Příspěvek byl odmítnu
 msgstr[2] "Byl dosažen denní limit %d příspěvku. Příspěvek byl odmítnut."
 msgstr[3] "Byl dosažen denní limit %d příspěvků. Příspěvek byl odmítnut."
 
-#: include/api.php:1152
+#: include/api.php:1154
 #, php-format
 msgid "Weekly posting limit of %d post reached. The post was rejected."
 msgid_plural ""
@@ -1582,16 +1582,16 @@ msgstr[1] "Byl dosažen týdenní limit %d příspěvků. Příspěvek byl odmí
 msgstr[2] "Byl dosažen týdenní limit %d příspěvku. Příspěvek byl odmítnut."
 msgstr[3] "Byl dosažen týdenní limit %d příspěvků. Příspěvek byl odmítnut."
 
-#: include/api.php:1166
+#: include/api.php:1168
 #, php-format
 msgid "Monthly posting limit of %d post reached. The post was rejected."
 msgstr "Byl dosažen měsíční limit %d příspěvků. Příspěvek byl odmítnut."
 
-#: include/api.php:4233 mod/profile_photo.php:84 mod/profile_photo.php:93
+#: include/api.php:4240 mod/profile_photo.php:84 mod/profile_photo.php:93
 #: mod/profile_photo.php:102 mod/profile_photo.php:211
 #: mod/profile_photo.php:300 mod/profile_photo.php:310 mod/photos.php:90
-#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1169
-#: mod/photos.php:1186 mod/photos.php:1678 src/Model/User.php:595
+#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1171
+#: mod/photos.php:1188 mod/photos.php:1680 src/Model/User.php:595
 #: src/Model/User.php:603 src/Model/User.php:611
 msgid "Profile Photos"
 msgstr "Profilové fotky"
@@ -1605,7 +1605,7 @@ msgid "Contact update failed."
 msgstr "Aktualizace kontaktu selhala."
 
 #: mod/crepair.php:112 mod/redir.php:29 mod/redir.php:127
-#: mod/dfrn_confirm.php:127 mod/fsuggest.php:30 mod/fsuggest.php:96
+#: mod/dfrn_confirm.php:128 mod/fsuggest.php:30 mod/fsuggest.php:96
 msgid "Contact not found."
 msgstr "Kontakt nenalezen."
 
@@ -1746,144 +1746,144 @@ msgstr "Předmět:"
 msgid "Your message:"
 msgstr "Vaše zpráva:"
 
-#: mod/lockview.php:42 mod/lockview.php:50
+#: mod/lockview.php:46 mod/lockview.php:57
 msgid "Remote privacy information not available."
 msgstr "Vzdálené informace o soukromí nejsou k dispozici."
 
-#: mod/lockview.php:59
+#: mod/lockview.php:66
 msgid "Visible to:"
 msgstr "Viditelné pro:"
 
-#: mod/install.php:100
+#: mod/install.php:98
 msgid "Friendica Communications Server - Setup"
 msgstr "Komunikační server Friendica - Nastavení"
 
-#: mod/install.php:106
+#: mod/install.php:104
 msgid "Could not connect to database."
 msgstr "Nelze se připojit k databázi."
 
-#: mod/install.php:110
+#: mod/install.php:108
 msgid "Could not create table."
 msgstr "Nelze vytvořit tabulku."
 
-#: mod/install.php:116
+#: mod/install.php:114
 msgid "Your Friendica site database has been installed."
 msgstr "Vaše databáze Friendica  byla nainstalována."
 
-#: mod/install.php:121
+#: mod/install.php:119
 msgid ""
 "You may need to import the file \"database.sql\" manually using phpmyadmin "
 "or mysql."
 msgstr "Nejspíše budete muset manuálně importovat soubor \"database.sql\" pomocí phpMyAdmin či MySQL."
 
-#: mod/install.php:122 mod/install.php:166 mod/install.php:274
+#: mod/install.php:120 mod/install.php:164 mod/install.php:272
 msgid "Please see the file \"INSTALL.txt\"."
 msgstr "Přečtěte si prosím informace v souboru \"INSTALL.txt\"."
 
-#: mod/install.php:134
+#: mod/install.php:132
 msgid "Database already in use."
 msgstr "Databáze se již používá."
 
-#: mod/install.php:163
+#: mod/install.php:161
 msgid "System check"
 msgstr "Zkouška systému"
 
-#: mod/install.php:167 mod/cal.php:279 mod/events.php:394
+#: mod/install.php:165 mod/cal.php:279 mod/events.php:395
 msgid "Next"
 msgstr "Dále"
 
-#: mod/install.php:168
+#: mod/install.php:166
 msgid "Check again"
-msgstr "Vyskoušet znovu"
+msgstr "Vyzkoušet znovu"
 
-#: mod/install.php:187
+#: mod/install.php:185
 msgid "Database connection"
 msgstr "Databázové spojení"
 
-#: mod/install.php:188
+#: mod/install.php:186
 msgid ""
 "In order to install Friendica we need to know how to connect to your "
 "database."
 msgstr "Pro instalaci Friendica potřebujeme znát připojení k Vaší databázi."
 
-#: mod/install.php:189
+#: mod/install.php:187
 msgid ""
 "Please contact your hosting provider or site administrator if you have "
 "questions about these settings."
 msgstr "Pokud máte otázky k následujícím nastavením, obraťte se na svého poskytovatele hostingu nebo administrátora serveru."
 
-#: mod/install.php:190
+#: mod/install.php:188
 msgid ""
 "The database you specify below should already exist. If it does not, please "
 "create it before continuing."
 msgstr "Databáze, kterou uvedete níže, by již měla existovat. Pokud to tak není, prosíme, vytvořte ji před pokračováním."
 
-#: mod/install.php:194
+#: mod/install.php:192
 msgid "Database Server Name"
 msgstr "Jméno databázového serveru"
 
-#: mod/install.php:195
+#: mod/install.php:193
 msgid "Database Login Name"
 msgstr "Přihlašovací jméno k databázi"
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "Database Login Password"
 msgstr "Heslo k databázovému účtu "
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "For security reasons the password must not be empty"
 msgstr "Z bezpečnostních důvodů nesmí být heslo prázdné."
 
-#: mod/install.php:197
+#: mod/install.php:195
 msgid "Database Name"
 msgstr "Jméno databáze"
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid "Site administrator email address"
 msgstr "E-mailová adresa administrátora webu"
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid ""
 "Your account email address must match this in order to use the web admin "
 "panel."
 msgstr "Vaše e-mailová adresa účtu se musí s touto shodovat, aby bylo možné využívat administrační panel ve webovém rozhraní."
 
-#: mod/install.php:200 mod/install.php:238
+#: mod/install.php:198 mod/install.php:236
 msgid "Please select a default timezone for your website"
 msgstr "Prosím, vyberte výchozí časové pásmo pro váš server"
 
-#: mod/install.php:225
+#: mod/install.php:223
 msgid "Site settings"
 msgstr "Nastavení webu"
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid "System Language:"
 msgstr "Systémový jazyk"
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid ""
 "Set the default language for your Friendica installation interface and to "
 "send emails."
 msgstr "Nastavte si výchozí jazyk pro Vaše instalační rozhraní Friendica a pro odesílání e-mailů."
 
-#: mod/install.php:255
+#: mod/install.php:253
 msgid ""
 "The database configuration file \"config/local.ini.php\" could not be "
 "written. Please use the enclosed text to create a configuration file in your"
 " web server root."
 msgstr "Databázový konfigurační soubor \"config/local.ini.php\" nemohl být zapsán. Prosím, použijte přiložený text k vytvoření konfiguračního souboru v kořenovém adresáři Vašeho webového serveru."
 
-#: mod/install.php:272
+#: mod/install.php:270
 msgid "<h1>What next</h1>"
 msgstr "<h1>Co dál</h1>"
 
-#: mod/install.php:273
+#: mod/install.php:271
 msgid ""
 "IMPORTANT: You will need to [manually] setup a scheduled task for the "
 "worker."
 msgstr "DŮLEŽITÉ: Budete si muset [manuálně] nastavit naplánovaný úkol pro pracovníka."
 
-#: mod/install.php:276
+#: mod/install.php:274
 #, php-format
 msgid ""
 "Go to your new Friendica node <a href=\"%s/register\">registration page</a> "
@@ -1891,83 +1891,83 @@ msgid ""
 " administrator email. This will allow you to enter the site admin panel."
 msgstr "Přejděte k <a href=\"%s/register\">registrační stránce</a> Vašeho nového serveru Friendica a zaregistrujte se jako nový uživatel. Nezapomeňte použít stejný e-mail, který jste zadal/a jako administrátorský e-mail. To Vám umožní navštívit panel pro administraci stránky."
 
-#: mod/dfrn_confirm.php:72 mod/profiles.php:38 mod/profiles.php:148
+#: mod/dfrn_confirm.php:73 mod/profiles.php:38 mod/profiles.php:148
 #: mod/profiles.php:193 mod/profiles.php:523
 msgid "Profile not found."
 msgstr "Profil nenalezen."
 
-#: mod/dfrn_confirm.php:128
+#: mod/dfrn_confirm.php:129
 msgid ""
 "This may occasionally happen if contact was requested by both persons and it"
 " has already been approved."
 msgstr "To se může občas stát, pokud byl kontakt zažádán oběma osobami a již byl schválen."
 
-#: mod/dfrn_confirm.php:238
+#: mod/dfrn_confirm.php:239
 msgid "Response from remote site was not understood."
 msgstr "Odpověď ze vzdáleného serveru nebyla srozumitelná."
 
-#: mod/dfrn_confirm.php:245 mod/dfrn_confirm.php:251
+#: mod/dfrn_confirm.php:246 mod/dfrn_confirm.php:252
 msgid "Unexpected response from remote site: "
 msgstr "Neočekávaná odpověď od vzdáleného serveru:"
 
-#: mod/dfrn_confirm.php:260
+#: mod/dfrn_confirm.php:261
 msgid "Confirmation completed successfully."
 msgstr "Potvrzení úspěšně dokončena."
 
-#: mod/dfrn_confirm.php:272
+#: mod/dfrn_confirm.php:273
 msgid "Temporary failure. Please wait and try again."
 msgstr "Dočasné selhání. Prosím, vyčkejte a zkuste to znovu."
 
-#: mod/dfrn_confirm.php:275
+#: mod/dfrn_confirm.php:276
 msgid "Introduction failed or was revoked."
 msgstr "Žádost o propojení selhala nebo byla zrušena."
 
-#: mod/dfrn_confirm.php:280
+#: mod/dfrn_confirm.php:281
 msgid "Remote site reported: "
 msgstr "Vzdálený server oznámil:"
 
-#: mod/dfrn_confirm.php:392
+#: mod/dfrn_confirm.php:382
 msgid "Unable to set contact photo."
 msgstr "Nelze nastavit fotku kontaktu."
 
-#: mod/dfrn_confirm.php:450
+#: mod/dfrn_confirm.php:444
 #, php-format
 msgid "No user record found for '%s' "
 msgstr "Pro \"%s\" nenalezen žádný uživatelský záznam "
 
-#: mod/dfrn_confirm.php:460
+#: mod/dfrn_confirm.php:454
 msgid "Our site encryption key is apparently messed up."
 msgstr "Náš šifrovací klíč zřejmě přestal správně fungovat."
 
-#: mod/dfrn_confirm.php:471
+#: mod/dfrn_confirm.php:465
 msgid "Empty site URL was provided or URL could not be decrypted by us."
 msgstr "Byla poskytnuta prázdná URL adresa nebo se nepodařilo URL adresu dešifrovat."
 
-#: mod/dfrn_confirm.php:487
+#: mod/dfrn_confirm.php:481
 msgid "Contact record was not found for you on our site."
 msgstr "Záznam kontaktu nebyl nalezen pro Vás na našich stránkách."
 
-#: mod/dfrn_confirm.php:501
+#: mod/dfrn_confirm.php:495
 #, php-format
 msgid "Site public key not available in contact record for URL %s."
 msgstr "V adresáři není k dispozici veřejný klíč pro URL %s."
 
-#: mod/dfrn_confirm.php:517
+#: mod/dfrn_confirm.php:511
 msgid ""
 "The ID provided by your system is a duplicate on our system. It should work "
 "if you try again."
 msgstr "Váš systém poskytl duplicitní ID vůči našemu systému. Pokuste se akci zopakovat."
 
-#: mod/dfrn_confirm.php:528
+#: mod/dfrn_confirm.php:522
 msgid "Unable to set your contact credentials on our system."
 msgstr "Nelze nastavit Vaše přihlašovací údaje v našem systému."
 
-#: mod/dfrn_confirm.php:584
+#: mod/dfrn_confirm.php:578
 msgid "Unable to update your contact profile details on our system"
 msgstr "Nelze aktualizovat Váš profil v našem systému"
 
-#: mod/dfrn_confirm.php:614 mod/dfrn_request.php:561
-#: src/Model/Contact.php:1891
+#: mod/dfrn_confirm.php:608 mod/dfrn_request.php:561
+#: src/Model/Contact.php:1909
 msgid "[Name Withheld]"
 msgstr "[Jméno odepřeno]"
 
@@ -1982,7 +1982,7 @@ msgid "Forum Search - %s"
 msgstr "Vyhledávání fór - %s"
 
 #: mod/dirfind.php:221 mod/match.php:105 mod/suggest.php:104
-#: mod/allfriends.php:92 src/Model/Profile.php:292 src/Content/Widget.php:37
+#: mod/allfriends.php:92 src/Model/Profile.php:305 src/Content/Widget.php:37
 msgid "Connect"
 msgstr "Spojit se"
 
@@ -2014,8 +2014,8 @@ msgstr "Odstranit video"
 
 #: mod/videos.php:198 mod/webfinger.php:16 mod/directory.php:42
 #: mod/search.php:105 mod/search.php:111 mod/viewcontacts.php:48
-#: mod/display.php:194 mod/dfrn_request.php:599 mod/probe.php:13
-#: mod/community.php:28 mod/photos.php:945
+#: mod/display.php:203 mod/dfrn_request.php:599 mod/probe.php:13
+#: mod/community.php:28 mod/photos.php:947
 msgid "Public access denied."
 msgstr "Veřejný přístup odepřen."
 
@@ -2023,19 +2023,19 @@ msgstr "Veřejný přístup odepřen."
 msgid "No videos selected"
 msgstr "Není vybráno žádné video"
 
-#: mod/videos.php:307 mod/photos.php:1050
+#: mod/videos.php:307 mod/photos.php:1052
 msgid "Access to this item is restricted."
 msgstr "Přístup k této položce je omezen."
 
-#: mod/videos.php:382 mod/photos.php:1699
+#: mod/videos.php:383 mod/photos.php:1701
 msgid "View Album"
 msgstr "Zobrazit album"
 
-#: mod/videos.php:390
+#: mod/videos.php:391
 msgid "Recent Videos"
 msgstr "Nedávná videa"
 
-#: mod/videos.php:392
+#: mod/videos.php:393
 msgid "Upload New Videos"
 msgstr "Nahrát nová videa"
 
@@ -2043,27 +2043,27 @@ msgstr "Nahrát nová videa"
 msgid "Only logged in users are permitted to perform a probing."
 msgstr "Pouze přihlášení uživatelé mohou zkoušet adresy."
 
-#: mod/directory.php:151 mod/notifications.php:253 mod/contacts.php:680
-#: mod/events.php:521 src/Model/Event.php:66 src/Model/Event.php:93
-#: src/Model/Event.php:430 src/Model/Event.php:915 src/Model/Profile.php:417
+#: mod/directory.php:151 mod/notifications.php:248 mod/contacts.php:681
+#: mod/events.php:548 src/Model/Event.php:67 src/Model/Event.php:94
+#: src/Model/Event.php:431 src/Model/Event.php:922 src/Model/Profile.php:430
 msgid "Location:"
 msgstr "Poloha:"
 
-#: mod/directory.php:156 mod/notifications.php:259 src/Model/Profile.php:420
-#: src/Model/Profile.php:732
+#: mod/directory.php:156 mod/notifications.php:254 src/Model/Profile.php:433
+#: src/Model/Profile.php:745
 msgid "Gender:"
 msgstr "Pohlaví:"
 
-#: mod/directory.php:157 src/Model/Profile.php:421 src/Model/Profile.php:756
+#: mod/directory.php:157 src/Model/Profile.php:434 src/Model/Profile.php:769
 msgid "Status:"
 msgstr "Stav:"
 
-#: mod/directory.php:158 src/Model/Profile.php:422 src/Model/Profile.php:773
+#: mod/directory.php:158 src/Model/Profile.php:435 src/Model/Profile.php:786
 msgid "Homepage:"
 msgstr "Domovská stránka:"
 
-#: mod/directory.php:159 mod/notifications.php:255 mod/contacts.php:684
-#: src/Model/Profile.php:423 src/Model/Profile.php:793
+#: mod/directory.php:159 mod/notifications.php:250 mod/contacts.php:685
+#: src/Model/Profile.php:436 src/Model/Profile.php:806
 msgid "About:"
 msgstr "O mně:"
 
@@ -2103,7 +2103,7 @@ msgstr "Žádost o připojení selhala nebo byla zrušena."
 msgid "Account"
 msgstr "Účet"
 
-#: mod/settings.php:64 src/Model/Profile.php:372 src/Content/Nav.php:210
+#: mod/settings.php:64 src/Model/Profile.php:385 src/Content/Nav.php:210
 msgid "Profiles"
 msgstr "Profily"
 
@@ -2143,7 +2143,7 @@ msgstr "Odstranit účet"
 msgid "Missing some important data!"
 msgstr "Chybí některé důležité údaje!"
 
-#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:848
+#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:851
 msgid "Update"
 msgstr "Aktualizace"
 
@@ -2211,11 +2211,11 @@ msgstr "Nelze změnit na tento e-mail."
 
 #: mod/settings.php:572
 msgid "Private forum has no privacy permissions. Using default privacy group."
-msgstr "Soukromé fórum nemá nastaveno zabezpečení. Používá se výchozí soukromá skupina."
+msgstr "Soukromé fórum nemá nastaveno zabezpečení. Používá se výchozí skupina soukromí."
 
 #: mod/settings.php:575
 msgid "Private forum has no privacy permissions and no default privacy group."
-msgstr "Soukromé fórum nemá nastaveno zabezpečení a ani žádnou defaultní výchozí skupinu."
+msgstr "Soukromé fórum nemá nastaveno zabezpečení a ani žádnou výchozí skupinu soukromí."
 
 #: mod/settings.php:615
 msgid "Settings updated."
@@ -2624,7 +2624,7 @@ msgstr "Propagační stránka"
 msgid ""
 "Account for a public profile that automatically approves contact requests as"
 " \"Followers\"."
-msgstr "Účet pro veřejný profil, který automaticky potvrzuje žádosti o přidání kontaktu jako \"Sledovatele\"."
+msgstr "Účet pro veřejný profil, který automaticky potvrzuje žádosti o přidání kontaktu jako „Sledovatele“."
 
 #: mod/settings.php:1072 mod/admin.php:1836
 msgid "Public Forum"
@@ -2662,7 +2662,7 @@ msgstr "(Volitelné) Povolit tomuto OpenID přihlášení k tomuto účtu."
 
 #: mod/settings.php:1100
 msgid "Publish your default profile in your local site directory?"
-msgstr "Publikovat Váš výchozí profil v lokálním adresáři webu?"
+msgstr "Publikovat Váš výchozí profil v místním adresáři webu?"
 
 #: mod/settings.php:1100
 #, php-format
@@ -2691,7 +2691,7 @@ msgstr "Publikovat Váš výchozí profil v globální sociálním adresáři?"
 msgid ""
 "Your profile will be published in the global friendica directories (e.g. <a "
 "href=\"%s\">%s</a>). Your profile will be visible in public."
-msgstr "Váš profil bude publikován v globálních adresářich Friendica (např. <a href=\"%s\">%s</a>). Váš profil bude veřejně viditelný."
+msgstr "Váš profil bude publikován v globálních adresářích Friendica (např. <a href=\"%s\">%s</a>). Váš profil bude veřejně viditelný."
 
 #: mod/settings.php:1113
 msgid "Hide your contact/friend list from viewers of your default profile?"
@@ -2833,7 +2833,7 @@ msgstr "Heslo: "
 msgid "Basic Settings"
 msgstr "Základní nastavení"
 
-#: mod/settings.php:1204 src/Model/Profile.php:725
+#: mod/settings.php:1204 src/Model/Profile.php:738
 msgid "Full Name:"
 msgstr "Celé jméno:"
 
@@ -2883,21 +2883,21 @@ msgstr "Výchozí oprávnění pro příspěvek"
 msgid "(click to open/close)"
 msgstr "(klikněte pro otevření/zavření)"
 
-#: mod/settings.php:1224 mod/photos.php:1126 mod/photos.php:1456
+#: mod/settings.php:1224 mod/photos.php:1128 mod/photos.php:1458
 msgid "Show to Groups"
 msgstr "Zobrazit ve Skupinách"
 
-#: mod/settings.php:1225 mod/photos.php:1127 mod/photos.php:1457
+#: mod/settings.php:1225 mod/photos.php:1129 mod/photos.php:1459
 msgid "Show to Contacts"
 msgstr "Zobrazit v Kontaktech"
 
 #: mod/settings.php:1226
 msgid "Default Private Post"
-msgstr "Výchozí Soukromý příspěvek"
+msgstr "Výchozí soukromý příspěvek"
 
 #: mod/settings.php:1227
 msgid "Default Public Post"
-msgstr "Výchozí Veřejný příspěvek"
+msgstr "Výchozí veřejný příspěvek"
 
 #: mod/settings.php:1231
 msgid "Default Permissions for New Posts"
@@ -2957,11 +2957,11 @@ msgstr "Zobrazit desktopové zprávy při nových oznámeních."
 
 #: mod/settings.php:1259
 msgid "Text-only notification emails"
-msgstr "Pouze textové notifikační e-maily"
+msgstr "Pouze textové oznamovací e-maily"
 
 #: mod/settings.php:1261
 msgid "Send text only notification emails, without the html part"
-msgstr "Posílat pouze textové notifikační e-maily, bez html části."
+msgstr "Posílat pouze textové oznamovací e-maily, bez HTML části."
 
 #: mod/settings.php:1263
 msgid "Show detailled notifications"
@@ -3036,7 +3036,7 @@ msgstr "Žádné výsledky."
 msgid "Items tagged with: %s"
 msgstr "Položky označené štítkem: %s"
 
-#: mod/search.php:248 mod/contacts.php:841
+#: mod/search.php:248 mod/contacts.php:844
 #, php-format
 msgid "Results for: %s"
 msgstr "Výsledky pro: %s"
@@ -3045,7 +3045,7 @@ msgstr "Výsledky pro: %s"
 msgid "No contacts in common."
 msgstr "Žádné společné kontakty."
 
-#: mod/common.php:142 mod/contacts.php:916
+#: mod/common.php:142 mod/contacts.php:919
 msgid "Common Friends"
 msgstr "Společní přátelé"
 
@@ -3053,7 +3053,11 @@ msgstr "Společní přátelé"
 msgid "Login"
 msgstr "Přihlásit se"
 
-#: mod/bookmarklet.php:52
+#: mod/bookmarklet.php:34
+msgid "Bad Request"
+msgstr "Špatný požadavek"
+
+#: mod/bookmarklet.php:56
 msgid "The post was created"
 msgstr "Příspěvek byl vytvořen"
 
@@ -3142,7 +3146,7 @@ msgstr "Zajímavé odkazy"
 
 #: mod/network.php:997
 msgid "Starred"
-msgstr "S hvězdičkou"
+msgstr "S hvězdou"
 
 #: mod/network.php:1000
 msgid "Favourite Posts"
@@ -3205,7 +3209,7 @@ msgstr "Upravit název skupiny"
 msgid "Members"
 msgstr "Členové"
 
-#: mod/group.php:246 mod/contacts.php:739
+#: mod/group.php:246 mod/contacts.php:742
 msgid "All Contacts"
 msgstr "Všechny kontakty"
 
@@ -3329,46 +3333,42 @@ msgstr "Přístup odmítnut."
 msgid "No contacts."
 msgstr "Žádné kontakty."
 
-#: mod/viewcontacts.php:106 mod/contacts.php:639 mod/contacts.php:1052
+#: mod/viewcontacts.php:106 mod/contacts.php:640 mod/contacts.php:1055
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr "Navštivte profil uživatele %s [%s]"
 
-#: mod/unfollow.php:36
-msgid "Contact wasn't found or can't be unfollowed."
-msgstr "Kontakt nebyl nalezen, nebo u něj nemůže být zrušeno sledování."
-
-#: mod/unfollow.php:49
-msgid "Contact unfollowed"
-msgstr "Zrušeno sledování kontaktu"
-
-#: mod/unfollow.php:67 mod/dfrn_request.php:654 mod/follow.php:62
-msgid "Submit Request"
-msgstr "Odeslat žádost"
+#: mod/unfollow.php:38 mod/unfollow.php:88
+msgid "You aren't following this contact."
+msgstr "Tento kontakt nesledujete."
 
-#: mod/unfollow.php:76
-msgid "You aren't a friend of this contact."
-msgstr "nejste přítelem tohoto kontaktu"
-
-#: mod/unfollow.php:82
+#: mod/unfollow.php:44 mod/unfollow.php:94
 msgid "Unfollowing is currently not supported by your network."
 msgstr "Zrušení sledování není aktuálně na Vaši síti podporováno."
 
-#: mod/unfollow.php:103 mod/contacts.php:601
+#: mod/unfollow.php:65
+msgid "Contact unfollowed"
+msgstr "Zrušeno sledování kontaktu"
+
+#: mod/unfollow.php:113 mod/contacts.php:607
 msgid "Disconnect/Unfollow"
 msgstr "Odpojit se/Zrušit sledování"
 
-#: mod/unfollow.php:116 mod/dfrn_request.php:652 mod/follow.php:157
+#: mod/unfollow.php:126 mod/dfrn_request.php:652 mod/follow.php:157
 msgid "Your Identity Address:"
 msgstr "Vaše adresa identity:"
 
-#: mod/unfollow.php:125 mod/notifications.php:174 mod/notifications.php:263
-#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:676 mod/follow.php:166
+#: mod/unfollow.php:129 mod/dfrn_request.php:654 mod/follow.php:62
+msgid "Submit Request"
+msgstr "Odeslat žádost"
+
+#: mod/unfollow.php:135 mod/notifications.php:174 mod/notifications.php:258
+#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:677 mod/follow.php:166
 msgid "Profile URL"
 msgstr "URL profilu"
 
-#: mod/unfollow.php:135 mod/contacts.php:888 mod/follow.php:189
-#: src/Model/Profile.php:878
+#: mod/unfollow.php:145 mod/contacts.php:891 mod/follow.php:189
+#: src/Model/Profile.php:891
 msgid "Status Messages and Posts"
 msgstr "Stavové zprávy a příspěvky "
 
@@ -3388,7 +3388,7 @@ msgstr "Registrace byla úspěšná. Zkontrolujte prosím svůj e-mail pro dalš
 msgid ""
 "Failed to send email message. Here your accout details:<br> login: %s<br> "
 "password: %s<br><br>You can change your password after login."
-msgstr "Nepovedlo se odeslat emailovou zprávu. Zde jsou detaily Vašeho účtu:<br> přihlašovací jméno: %s<br> heslo: %s<br><br>Své heslo si můžete změnit po přihlášení."
+msgstr "Nepovedlo se odeslat e-mailovou zprávu. Zde jsou detaily Vašeho účtu:<br> přihlašovací jméno: %s<br> heslo: %s<br><br>Své heslo si můžete změnit po přihlášení."
 
 #: mod/register.php:110
 msgid "Registration successful."
@@ -3402,7 +3402,7 @@ msgstr "Vaši registraci nelze zpracovat."
 msgid "Your registration is pending approval by the site owner."
 msgstr "Vaše registrace čeká na schválení vlastníkem serveru."
 
-#: mod/register.php:191 mod/uimport.php:55
+#: mod/register.php:191 mod/uimport.php:37
 msgid ""
 "This site has exceeded the number of allowed daily account registrations. "
 "Please try again tomorrow."
@@ -3477,7 +3477,7 @@ msgstr "Vyberte přezdívku:"
 msgid "Register"
 msgstr "Registrovat"
 
-#: mod/register.php:287 mod/uimport.php:70
+#: mod/register.php:287 mod/uimport.php:52
 msgid "Import"
 msgstr "Import"
 
@@ -3498,37 +3498,45 @@ msgstr "Poznámka: Tento server explicitně obsahuje obsah pro dospělé"
 msgid "Invalid request identifier."
 msgstr "Neplatný identifikátor požadavku."
 
-#: mod/notifications.php:44 mod/notifications.php:183
-#: mod/notifications.php:235 mod/message.php:114
+#: mod/notifications.php:44 mod/notifications.php:182
+#: mod/notifications.php:230 mod/message.php:114
 msgid "Discard"
 msgstr "Odstranit"
 
-#: mod/notifications.php:57 mod/notifications.php:182
-#: mod/notifications.php:271 mod/contacts.php:658 mod/contacts.php:850
-#: mod/contacts.php:1113
+#: mod/notifications.php:57 mod/notifications.php:181
+#: mod/notifications.php:266 mod/contacts.php:659 mod/contacts.php:853
+#: mod/contacts.php:1116
 msgid "Ignore"
 msgstr "Ignorovat"
 
-#: mod/notifications.php:93 src/Content/Nav.php:191
+#: mod/notifications.php:90 src/Content/Nav.php:191
 msgid "Notifications"
 msgstr "Oznámení"
 
-#: mod/notifications.php:101
+#: mod/notifications.php:102
 msgid "Network Notifications"
 msgstr "Síťová oznámení"
 
-#: mod/notifications.php:106 mod/notify.php:81
+#: mod/notifications.php:107 mod/notify.php:81
 msgid "System Notifications"
 msgstr "Systémová oznámení"
 
-#: mod/notifications.php:111
+#: mod/notifications.php:112
 msgid "Personal Notifications"
 msgstr "Osobní oznámení"
 
-#: mod/notifications.php:116
+#: mod/notifications.php:117
 msgid "Home Notifications"
 msgstr "Oznámení na domovské stránce"
 
+#: mod/notifications.php:137
+msgid "Show unread"
+msgstr "Zobrazit nepřečtené"
+
+#: mod/notifications.php:137
+msgid "Show all"
+msgstr "Zobrazit vše"
+
 #: mod/notifications.php:148
 msgid "Show Ignored Requests"
 msgstr "Zobrazit ignorované žádosti"
@@ -3537,7 +3545,7 @@ msgstr "Zobrazit ignorované žádosti"
 msgid "Hide Ignored Requests"
 msgstr "Skrýt ignorované žádosti"
 
-#: mod/notifications.php:161 mod/notifications.php:243
+#: mod/notifications.php:161 mod/notifications.php:238
 msgid "Notification type:"
 msgstr "Typ oznámení:"
 
@@ -3545,85 +3553,77 @@ msgstr "Typ oznámení:"
 msgid "Suggested by:"
 msgstr "Navrhl/a:"
 
-#: mod/notifications.php:176 mod/notifications.php:260 mod/contacts.php:666
+#: mod/notifications.php:176 mod/notifications.php:255 mod/contacts.php:667
 msgid "Hide this contact from others"
 msgstr "Skrýt tento kontakt před ostatními"
 
-#: mod/notifications.php:179 mod/notifications.php:269 mod/admin.php:1904
+#: mod/notifications.php:178 mod/notifications.php:264 mod/admin.php:1904
 msgid "Approve"
 msgstr "Schválit"
 
-#: mod/notifications.php:202
+#: mod/notifications.php:198
 msgid "Claims to be known to you: "
 msgstr "Vaši údajní známí: "
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "yes"
 msgstr "ano"
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "no"
 msgstr "ne"
 
-#: mod/notifications.php:204 mod/notifications.php:209
+#: mod/notifications.php:200 mod/notifications.php:204
 msgid "Shall your connection be bidirectional or not?"
 msgstr "Má Vaše spojení být obousměrné, nebo ne?"
 
-#: mod/notifications.php:205 mod/notifications.php:210
+#: mod/notifications.php:201 mod/notifications.php:205
 #, php-format
 msgid ""
 "Accepting %s as a friend allows %s to subscribe to your posts, and you will "
 "also receive updates from them in your news feed."
 msgstr "Přijetí uživatele %s jako přítele dovolí uživateli %s odebírat Vaše příspěvky a Vy budete také přijímat aktualizace od něj ve Vašem kanále."
 
-#: mod/notifications.php:206
+#: mod/notifications.php:202
 #, php-format
 msgid ""
 "Accepting %s as a subscriber allows them to subscribe to your posts, but you"
 " will not receive updates from them in your news feed."
 msgstr "Přijetí uživatele %s jako odběratele mu dovolí odebírat Vaše příspěvky, ale nebudete od něj přijímat aktualizace ve Vašem kanále."
 
-#: mod/notifications.php:211
+#: mod/notifications.php:206
 #, php-format
 msgid ""
 "Accepting %s as a sharer allows them to subscribe to your posts, but you "
 "will not receive updates from them in your news feed."
 msgstr "Přijetí uživatele %s jako sdílejícího mu dovolí odebírat Vaše příspěvky, ale nebudete od něj přijímat aktualizace ve Vašem kanále."
 
-#: mod/notifications.php:222
+#: mod/notifications.php:217
 msgid "Friend"
 msgstr "Přítel"
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Sharer"
 msgstr "Sdílející"
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Subscriber"
 msgstr "Odběratel"
 
-#: mod/notifications.php:257 mod/contacts.php:686 mod/follow.php:177
-#: src/Model/Profile.php:781
+#: mod/notifications.php:252 mod/contacts.php:687 mod/follow.php:177
+#: src/Model/Profile.php:794
 msgid "Tags:"
 msgstr "Štítky:"
 
-#: mod/notifications.php:266 mod/contacts.php:76 src/Model/Profile.php:520
+#: mod/notifications.php:261 mod/contacts.php:81 src/Model/Profile.php:533
 msgid "Network:"
 msgstr "Síť:"
 
-#: mod/notifications.php:280
+#: mod/notifications.php:274
 msgid "No introductions."
 msgstr "Žádné představení."
 
-#: mod/notifications.php:318
-msgid "Show unread"
-msgstr "Zobrazit nepřečtené"
-
-#: mod/notifications.php:318
-msgid "Show all"
-msgstr "Zobrazit vše"
-
-#: mod/notifications.php:323
+#: mod/notifications.php:308
 #, php-format
 msgid "No more %s notifications."
 msgstr "Žádná další %s oznámení"
@@ -3846,7 +3846,7 @@ msgid "On this server the following remote servers are blocked."
 msgstr "Na tomto serveru jsou zablokovány následující vzdálené servery."
 
 #: mod/friendica.php:130 mod/admin.php:363 mod/admin.php:381
-#: mod/dfrn_request.php:345 src/Model/Contact.php:1582
+#: mod/dfrn_request.php:345 src/Model/Contact.php:1593
 msgid "Blocked domain"
 msgstr "Zablokovaná doména"
 
@@ -3854,7 +3854,7 @@ msgstr "Zablokovaná doména"
 msgid "Reason for the block"
 msgstr "Důvody pro zablokování"
 
-#: mod/display.php:303 mod/cal.php:144 mod/profile.php:175
+#: mod/display.php:312 mod/cal.php:144 mod/profile.php:185
 msgid "Access to this profile has been restricted."
 msgstr "Přístup na tento profil byl omezen."
 
@@ -3864,13 +3864,13 @@ msgstr "Přístup na tento profil byl omezen."
 msgid "Invalid request."
 msgstr "Neplatný požadavek."
 
-#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:776
-#: mod/photos.php:779 mod/photos.php:808
+#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:778
+#: mod/photos.php:781 mod/photos.php:810
 #, php-format
 msgid "Image exceeds size limit of %s"
 msgstr "Velikost obrázku překročila limit %s"
 
-#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:831
+#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:833
 msgid "Unable to process image."
 msgstr "Obrázek není možné zprocesovat"
 
@@ -3879,7 +3879,7 @@ msgstr "Obrázek není možné zprocesovat"
 msgid "Wall Photos"
 msgstr "Fotky na zdi"
 
-#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:860
+#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:862
 msgid "Image upload failed."
 msgstr "Nahrání obrázku selhalo."
 
@@ -3979,7 +3979,7 @@ msgid ""
 "Enter your email access information on your Connector Settings page if you "
 "wish to import and interact with friends or mailing lists from your email "
 "INBOX"
-msgstr "Pokud chcete importovat své přátele nebo mailové skupiny a komunikovat s nimi, zadejte na Vaší stránce Nastavení kontektoru své přístupové údaje do svého emailového účtu"
+msgstr "Pokud chcete importovat své přátele nebo mailové skupiny z INBOX Vašeho e-mailu a komunikovat s nimi, zadejte na Vaší stránce Nastavení kontektoru své přístupové údaje do svého e-mailového účtu"
 
 #: mod/newmember.php:39
 msgid "Go to Your Contacts Page"
@@ -4078,7 +4078,7 @@ msgid ""
 "\n"
 "\t\tYour password will not be changed unless we can verify that you\n"
 "\t\tissued this request."
-msgstr "\n\t\tVážený/á %1$s,\n\t\t\tPřed nedávnem jsme obdrželi na \"%2$s\" požadavek o obnovení\n\t\thesla k Vašemu účtu. Pro potvrzení tohoto požadavku, prosím klikněte na odkaz\n\t\tpro ověření dole, nebo ho zkopírujte do adresního řádku Vašeho prohlížeče.\n\n\t\tPokud jste o tuto změnu NEPOŽÁDAL/A, prosím NEKLIKEJTE na tento odkaz\n\t\ta ignorujte a/nebo smažte tento e-mail. Platnost požadavku brzy vyprší.\n\n\t\tVaše heslo nebude změněno, dokud nedokážeme ověřit, že jste tento\n\t\tpožadavek nevydal/a Vy."
+msgstr "\n\t\tVážený/á %1$s,\n\t\t\tPřed nedávnem jsme obdrželi na „%2$s“ požadavek o obnovení\n\t\thesla k Vašemu účtu. Pro potvrzení tohoto požadavku, prosím klikněte na odkaz\n\t\tpro ověření dole, nebo ho zkopírujte do adresního řádku Vašeho prohlížeče.\n\n\t\tPokud jste o tuto změnu NEPOŽÁDAL/A, prosím NEKLIKEJTE na tento odkaz\n\t\ta ignorujte a/nebo smažte tento e-mail. Platnost požadavku brzy vyprší.\n\n\t\tVaše heslo nebude změněno, dokud nedokážeme ověřit, že jste tento\n\t\tpožadavek nevydal/a Vy."
 
 #: mod/lostpass.php:57
 #, php-format
@@ -4186,79 +4186,91 @@ msgstr "\n\t\t\tZde jsou vaše přihlašovací detaily:\n\n\t\t\tAdresa stránky
 msgid "Your password has been changed at %s"
 msgstr "Vaše heslo bylo změněno na %s"
 
-#: mod/babel.php:22
+#: mod/babel.php:24
 msgid "Source input"
 msgstr "Zdrojový vstup"
 
-#: mod/babel.php:28
+#: mod/babel.php:30
 msgid "BBCode::toPlaintext"
 msgstr "BBCode::toPlaintext"
 
-#: mod/babel.php:34
+#: mod/babel.php:36
 msgid "BBCode::convert (raw HTML)"
-msgstr "BBCode::convert (raw HTML)"
+msgstr "BBCode::convert (hrubé HTML)"
 
-#: mod/babel.php:39
+#: mod/babel.php:41
 msgid "BBCode::convert"
 msgstr "BBCode::convert"
 
-#: mod/babel.php:45
+#: mod/babel.php:47
 msgid "BBCode::convert => HTML::toBBCode"
 msgstr "BBCode::convert => HTML::toBBCode"
 
-#: mod/babel.php:51
+#: mod/babel.php:53
 msgid "BBCode::toMarkdown"
 msgstr "BBCode::toMarkdown"
 
-#: mod/babel.php:57
+#: mod/babel.php:59
 msgid "BBCode::toMarkdown => Markdown::convert"
 msgstr "BBCode::toMarkdown => Markdown::convert"
 
-#: mod/babel.php:63
+#: mod/babel.php:65
 msgid "BBCode::toMarkdown => Markdown::toBBCode"
 msgstr "BBCode::toMarkdown => Markdown::toBBCode"
 
-#: mod/babel.php:69
+#: mod/babel.php:71
 msgid "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"
 msgstr "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"
 
-#: mod/babel.php:76
-msgid "Source input \\x28Diaspora format\\x29"
-msgstr "Zdrojový vstup \\x28Formát Diaspora\\x29"
+#: mod/babel.php:78
+msgid "Source input (Diaspora format)"
+msgstr "Zdrojový vstup (formát Diaspora)"
+
+#: mod/babel.php:84
+msgid "Markdown::convert (raw HTML)"
+msgstr "Markdown::convert (hrubé HTML)"
 
-#: mod/babel.php:82
+#: mod/babel.php:89
+msgid "Markdown::convert"
+msgstr "Markdown::convert"
+
+#: mod/babel.php:95
 msgid "Markdown::toBBCode"
 msgstr "Markdown::toBBCode"
 
-#: mod/babel.php:89
+#: mod/babel.php:102
 msgid "Raw HTML input"
 msgstr "Hrubý HTML vstup"
 
-#: mod/babel.php:94
+#: mod/babel.php:107
 msgid "HTML Input"
 msgstr "HTML vstup"
 
-#: mod/babel.php:100
+#: mod/babel.php:113
 msgid "HTML::toBBCode"
 msgstr "HTML::toBBCode"
 
-#: mod/babel.php:106
+#: mod/babel.php:119
+msgid "HTML::toMarkdown"
+msgstr "HTML::toMarkdown"
+
+#: mod/babel.php:125
 msgid "HTML::toPlaintext"
 msgstr "HTML::toPlaintext"
 
-#: mod/babel.php:114
+#: mod/babel.php:133
 msgid "Source text"
 msgstr "Zdrojový text"
 
-#: mod/babel.php:115
+#: mod/babel.php:134
 msgid "BBCode"
 msgstr "BBCode"
 
-#: mod/babel.php:116
+#: mod/babel.php:135
 msgid "Markdown"
 msgstr "Markdown"
 
-#: mod/babel.php:117
+#: mod/babel.php:136
 msgid "HTML"
 msgstr "HTML"
 
@@ -4371,13 +4383,13 @@ msgstr "Administrace"
 
 #: mod/admin.php:311
 msgid "Display Terms of Service"
-msgstr "Ukázat Podmínky používání"
+msgstr "Zobrazit Podmínky používání"
 
 #: mod/admin.php:311
 msgid ""
 "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."
-msgstr "Povolte stránku Podmínky používání. Pokud je toto povoleno, bude na formulář pro registrací a stránku s obecnými informacemi přidán odkaz k podmínkám."
+msgstr "Povolí stránku Podmínky používání. Pokud je toto povoleno, bude na formulář pro registrací a stránku s obecnými informacemi přidán odkaz k podmínkám."
 
 #: mod/admin.php:312
 msgid "Display Privacy Statement"
@@ -4433,7 +4445,7 @@ msgid ""
 "The list of blocked servers will be made publically available on the "
 "/friendica page so that your users and people investigating communication "
 "problems can find the reason easily."
-msgstr "Seznam zablokovaných server bude zveřejněn na stránce /friendica, takže vaši uživatelé a lidé vyšetřující probém s komunikací mohou důvod najít snadno."
+msgstr "Seznam zablokovaných serverů bude zveřejněn na stránce /friendica, takže vaši uživatelé a lidé vyšetřující probém s komunikací mohou důvod najít snadno."
 
 #: mod/admin.php:375
 msgid "Add new entry to block list"
@@ -4447,7 +4459,7 @@ msgstr "Serverová doména"
 msgid ""
 "The domain of the new server to add to the block list. Do not include the "
 "protocol."
-msgstr "Doména serveru, který má být přidán na blokovací seznam. Vynechejte protokol (\"http://\")."
+msgstr "Doména serveru, který má být přidán na blokovací seznam. Vynechejte protokol („http://“)."
 
 #: mod/admin.php:377
 msgid "Block reason"
@@ -4521,13 +4533,13 @@ msgstr "Vybrat vše"
 msgid "select none"
 msgstr "nevybrat žádný"
 
-#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Block"
 msgstr "Blokovat"
 
-#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Unblock"
 msgstr "Odblokovat"
 
@@ -4537,7 +4549,7 @@ msgstr "Žádný vzdálený kontakt není na tomto serveru zablokován."
 
 #: mod/admin.php:498
 msgid "Blocked Remote Contacts"
-msgstr "Zablokovat vzdálené kontakty"
+msgstr "Zablokova vzdálené kontakty"
 
 #: mod/admin.php:499
 msgid "Block New Remote Contact"
@@ -4627,7 +4639,7 @@ msgstr "Jméno příjemce"
 
 #: mod/admin.php:770
 msgid "Recipient Profile"
-msgstr "Profil píjemce"
+msgstr "Profil příjemce"
 
 #: mod/admin.php:772 mod/admin.php:811
 msgid "Created"
@@ -4710,10 +4722,10 @@ msgstr "Konfigurace Friendica je nyní uložena v souboru config/local.ini.php,
 #: mod/admin.php:876
 #, php-format
 msgid ""
-"<a href=\"%s\">%s</a> is not reachable on your system. This is a servere "
-"configuration issue that prevents the communication.. See <a href=\"%s\">the"
-" installation page</a> for help."
-msgstr "<a href=\"%s\">%s</a> není na Vašem systému dosažitelné. Tohle je závažná chyba konfigurace, která brání komunikaci. Pro pomoc navštivte <a href=\"%s\">stránku instalace</a>."
+"<a href=\"%s\">%s</a> is not reachable on your system. This is a severe "
+"configuration issue that prevents server to server communication. See <a "
+"href=\"%s\">the installation page</a> for help."
+msgstr "<a href=\"%s\">%s</a> není na Vašem systému dosažitelné. Tohle je závažná chyba konfigurace, která brání komunikaci mezi servery. Pro pomoc navštivte <a href=\"%s\">stránku instalace</a>."
 
 #: mod/admin.php:882
 msgid "Normal Account"
@@ -4773,15 +4785,15 @@ msgstr "Nastavení webu aktualizováno."
 
 #: mod/admin.php:1345
 msgid "No community page for local users"
-msgstr "Žádná komunitní stránka pro lokální uživatele"
+msgstr "Žádná komunitní stránka pro místní uživatele"
 
 #: mod/admin.php:1346
 msgid "No community page"
-msgstr "Komunitní stránka neexistuje"
+msgstr "Žádná komunitní stránka"
 
 #: mod/admin.php:1347
 msgid "Public postings from users of this site"
-msgstr "Počet veřejných příspěvků od uživatele na této stránce"
+msgstr "Veřejné příspěvky od místních uživatelů"
 
 #: mod/admin.php:1348
 msgid "Public postings from the federated network"
@@ -4789,10 +4801,10 @@ msgstr "Veřejné příspěvky z federované sítě"
 
 #: mod/admin.php:1349
 msgid "Public postings from local users and the federated network"
-msgstr "Veřejné příspěvky od lokálních uživatelů a z federované sítě"
+msgstr "Veřejné příspěvky od místních uživatelů a z federované sítě"
 
 #: mod/admin.php:1353 mod/admin.php:1520 mod/admin.php:1530
-#: mod/contacts.php:577
+#: mod/contacts.php:583
 msgid "Disabled"
 msgstr "Zakázáno"
 
@@ -4846,7 +4858,7 @@ msgstr "Vyžadovat u všech odkazů použití SSL"
 
 #: mod/admin.php:1402
 msgid "Self-signed certificate, use SSL for local links only (discouraged)"
-msgstr "Certifikát podepsaný sám sebou, použít SSL pouze pro lokální odkazy (nedoporučeno)"
+msgstr "Certifikát podepsaný sám sebou, použít SSL pouze pro místní odkazy (nedoporučeno)"
 
 #: mod/admin.php:1406
 msgid "Don't check"
@@ -4870,10 +4882,10 @@ msgstr "Nahrání souborů"
 
 #: mod/admin.php:1430
 msgid "Policies"
-msgstr "Politiky"
+msgstr "Politika"
 
-#: mod/admin.php:1431 mod/contacts.php:926 mod/events.php:535
-#: src/Model/Profile.php:852
+#: mod/admin.php:1431 mod/contacts.php:929 mod/events.php:562
+#: src/Model/Profile.php:865
 msgid "Advanced"
 msgstr "Pokročilé"
 
@@ -5161,17 +5173,17 @@ msgstr "Nastavit pro nové uživatele příspěvky jako soukromé"
 msgid ""
 "Set default post permissions for all new members to the default privacy "
 "group rather than public."
-msgstr "Nastavit defaultní práva pro příspěvky od všech nových členů na výchozí soukromou skupinu raději než jako veřejné."
+msgstr "Nastavit výchozí práva pro příspěvky od všech nových členů na výchozí soukromou skupinu místo veřejné."
 
 #: mod/admin.php:1470
 msgid "Don't include post content in email notifications"
-msgstr "Nezahrnovat obsah příspěvků v emailových upozorněních"
+msgstr "Nezahrnovat v e-mailových upozorněních obsah příspěvků"
 
 #: mod/admin.php:1470
 msgid ""
 "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."
-msgstr " V mailových upozorněních, které jsou odesílány z tohoto webu jako soukromé zprávy, nejsou z důvodů bezpečnosti obsaženy příspěvky/komentáře/soukromé zprávy apod. "
+msgstr " V e-mailových oznámeních, které jsou odesílány z tohoto webu, nebudou z důvodů bezpečnosti obsaženy příspěvky/komentáře/soukromé zprávy apod. "
 
 #: mod/admin.php:1471
 msgid "Disallow public access to addons listed in the apps menu."
@@ -5185,7 +5197,7 @@ msgstr "Označení této volby omezí rozšíření uvedená v menu aplikace pou
 
 #: mod/admin.php:1472
 msgid "Don't embed private images in posts"
-msgstr "Nepovolit přidávání soukromých správ v příspěvcích"
+msgstr "Nepovolit přidávání soukromých obrázků do příspěvků"
 
 #: mod/admin.php:1472
 msgid ""
@@ -5210,7 +5222,7 @@ msgstr "Touto funkcí oznámíte, že je Váš server používán hlavně pro ex
 
 #: mod/admin.php:1474
 msgid "Allow Users to set remote_self"
-msgstr "Umožnit uživatelům nastavit "
+msgstr "Umožnit uživatelům nastavit remote_self"
 
 #: mod/admin.php:1474
 msgid ""
@@ -5243,7 +5255,7 @@ msgstr "Kontrola úplného jména"
 msgid ""
 "Force users to register with a space between firstname and lastname in Full "
 "name, as an antispam measure"
-msgstr "Přimět uživatele k registraci s mezerou mezi jménu a příjmením v poli Celé jméno, jako antispamové opatření."
+msgstr "Přimět uživatele k registraci s mezerou mezi jménu a příjmením v poli Celé jméno, jako protispamové opatření."
 
 #: mod/admin.php:1478
 msgid "Community pages for visitors"
@@ -5253,7 +5265,7 @@ msgstr "Komunitní stránky pro návštěvníky"
 msgid ""
 "Which community pages should be available for visitors. Local users always "
 "see both pages."
-msgstr "Které komunitní stránky by měly být viditelné pro návštěvníky. Lokální uživatelé vždy vidí obě stránky."
+msgstr "Které komunitní stránky by měly být viditelné pro návštěvníky. Místní uživatelé vždy vidí obě stránky."
 
 #: mod/admin.php:1479
 msgid "Posts per user on community page"
@@ -5263,7 +5275,7 @@ msgstr "Počet příspěvků na komunitní stránce"
 msgid ""
 "The maximum number of posts per user on the community page. (Not valid for "
 "'Global Community')"
-msgstr "Maximální počet příspěvků na uživatele na komunitní sptránce. (neplatí pro 'Globální komunitu')"
+msgstr "Maximální počet příspěvků na uživatele na komunitní stránce. (neplatí pro „Globální komunitu“)"
 
 #: mod/admin.php:1480
 msgid "Enable OStatus support"
@@ -5277,15 +5289,15 @@ msgid ""
 msgstr "Poskytnout zabudouvanou kompatibilitu s OStatus (StatusNet, GNU Social apod.). Veškerá komunikace s OStatus je veřejná, proto bude občas zobrazeno upozornění."
 
 #: mod/admin.php:1481
-msgid "Only import OStatus threads from our contacts"
-msgstr "Pouze importovat vlákna z OStatus z našich kontaktů"
+msgid "Only import OStatus/ActivityPub threads from our contacts"
+msgstr "Pouze importovat vlákna z OStatus/ActivityPub z našich kontaktů"
 
 #: mod/admin.php:1481
 msgid ""
-"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."
-msgstr "Běžně importujeme všechen obsah z našich kontaktů na OStatus. S touto volbou uchováváme vlákna počatá kontaktem, který je na našem systému známý."
+"Normally we import every content from our OStatus and ActivityPub contacts. "
+"With this option we only store threads that are started by a contact that is"
+" known on our system."
+msgstr "Běžně importujeme všechen obsah z našich kontaktů na OStatus a ActivityPub. S touto volbou uchováváme vlákna počatá kontaktem, který je na našem systému známý."
 
 #: mod/admin.php:1482
 msgid "OStatus support can only be enabled if threading is enabled."
@@ -5313,7 +5325,7 @@ msgstr "Povolit pouze kontakty z Friendica"
 msgid ""
 "All contacts must use Friendica protocols. All other built-in communication "
 "protocols disabled."
-msgstr "Všechny kontakty musí používat Friendica protokol. Všchny jiné zabudované komunikační protokoly budou zablokované."
+msgstr "Všechny kontakty musí používat protokol Friendica. Všchny ostatní zabudované komunikační protokoly budou zablokované."
 
 #: mod/admin.php:1487
 msgid "Verify SSL"
@@ -5335,7 +5347,7 @@ msgstr "Proxy URL adresa"
 
 #: mod/admin.php:1490
 msgid "Network timeout"
-msgstr "Čas síťového spojení vypršel (timeout)"
+msgstr "Čas vypršení síťového spojení (timeout)"
 
 #: mod/admin.php:1490
 msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
@@ -5433,14 +5445,14 @@ msgstr "Pokud je aktivováno objevování, tato hodnota definuje časový rámec
 
 #: mod/admin.php:1501
 msgid "Search the local directory"
-msgstr "Hledat  v lokálním adresáři"
+msgstr "Hledat  v místním adresáři"
 
 #: mod/admin.php:1501
 msgid ""
 "Search the local directory instead of the global directory. When searching "
 "locally, every search will be executed on the global directory in the "
 "background. This improves the search results when the search is repeated."
-msgstr "Prohledat lokální adresář místo globálního adresáře. Při lokálním prohledávání bude každé hledání provedeno v globálním adresáři na pozadí. To vylepšuje výsledky při zopakování hledání."
+msgstr "Prohledat místní adresář místo globálního adresáře. Při místním prohledávání bude každé hledání provedeno v globálním adresáři na pozadí. To vylepšuje výsledky při zopakování hledání."
 
 #: mod/admin.php:1503
 msgid "Publish server information"
@@ -5676,7 +5688,7 @@ msgid ""
 "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."
-msgstr "Může být buď \"vše\" nebo \"štítky\". \"vše\" znamená, že budou přijaty všechny veřejné příspěvky. \"štítky\" znamená, že budou přijaty pouze příspěvky s vybranými štítky."
+msgstr "Může být buď „vše“ nebo „štítky“. „vše“ znamená, že budou přijaty všechny veřejné příspěvky. „štítky“ znamená, že budou přijaty pouze příspěvky s vybranými štítky."
 
 #: mod/admin.php:1530
 msgid "all"
@@ -5692,7 +5704,7 @@ msgstr "Serverové štítky"
 
 #: mod/admin.php:1531
 msgid "Comma separated list of tags for the 'tags' subscription."
-msgstr "Seznam štítků pro odběr \"tags\", oddělených čárkami."
+msgstr "Seznam štítků pro odběr „tags“, oddělených čárkami."
 
 #: mod/admin.php:1532
 msgid "Allow user tags"
@@ -5702,7 +5714,7 @@ msgstr "Povolit uživatelské štítky"
 msgid ""
 "If enabled, the tags from the saved searches will used for the 'tags' "
 "subscription in addition to the 'relay_server_tags'."
-msgstr "Pokud je toto povoleno, budou štítky z uložených hledání vedle odběru \"relay_server_tags\" použity i pro odběr \"tags\"."
+msgstr "Pokud je toto povoleno, budou štítky z uložených hledání vedle odběru „relay_server_tags“ použity i pro odběr „tags“."
 
 #: mod/admin.php:1535
 msgid "Start Relocation"
@@ -5748,7 +5760,7 @@ msgstr "Žádné neúspěšné aktualizace."
 
 #: mod/admin.php:1619
 msgid "Check database structure"
-msgstr "Ověření struktury databáze"
+msgstr "Ověřit strukturu databáze"
 
 #: mod/admin.php:1624
 msgid "Failed Updates"
@@ -6077,7 +6089,7 @@ msgstr "Nelze otevřít záznam <strong>%1$s</strong>.\\r\\n<br/>Zkontrolujte, j
 #: mod/admin.php:2540
 #, php-format
 msgid "Lock feature %s"
-msgstr "Funkce zámku %s"
+msgstr "Uzamknout vlastnost %s"
 
 #: mod/admin.php:2548
 msgid "Manage Additional Features"
@@ -6163,17 +6175,17 @@ msgstr "Zřejmě jste s %s již přátelé."
 msgid "Invalid profile URL."
 msgstr "Neplatné URL profilu."
 
-#: mod/dfrn_request.php:339 src/Model/Contact.php:1577
+#: mod/dfrn_request.php:339 src/Model/Contact.php:1588
 msgid "Disallowed profile URL."
 msgstr "Nepovolené URL profilu."
 
-#: mod/dfrn_request.php:412 mod/contacts.php:235
+#: mod/dfrn_request.php:412 mod/contacts.php:241
 msgid "Failed to update contact record."
 msgstr "Nepodařilo se aktualizovat kontakt."
 
 #: mod/dfrn_request.php:432
 msgid "Your introduction has been sent."
-msgstr "Vaše žádost o propojení byla odeslána."
+msgstr "Vaše představení bylo odesláno."
 
 #: mod/dfrn_request.php:470
 msgid ""
@@ -6394,32 +6406,36 @@ msgstr "%s poslal/a aktualizaci."
 msgid "Help:"
 msgstr "Nápověda:"
 
-#: mod/uimport.php:72
+#: mod/uimport.php:28
+msgid "User imports on closed servers can only be done by an administrator."
+msgstr "Importy uživatelů na uzavřených serverech může provést pouze administrátor."
+
+#: mod/uimport.php:54
 msgid "Move account"
 msgstr "Přesunout účet"
 
-#: mod/uimport.php:73
+#: mod/uimport.php:55
 msgid "You can import an account from another Friendica server."
 msgstr "Můžete importovat účet z jiného serveru Friendica."
 
-#: mod/uimport.php:74
+#: mod/uimport.php:56
 msgid ""
 "You need to export your account from the old server and upload it here. We "
 "will recreate your old account here with all your contacts. We will try also"
 " to inform your friends that you moved here."
 msgstr "Musíte exportovat svůj účet na starém serveru a nahrát ho zde. My následně vytvoříme Váš původní účet zde včetně všech kontaktů. Zároveň se pokusíme informovat všechny Vaše přátele, že jste se sem přestěhoval/a."
 
-#: mod/uimport.php:75
+#: mod/uimport.php:57
 msgid ""
 "This feature is experimental. We can't import contacts from the OStatus "
 "network (GNU Social/Statusnet) or from Diaspora"
 msgstr "Tato vlastnost je experimentální. Nemůžeme importovat kontakty za sítě OStatus (GNU social/StatusNet) nebo z Diaspory"
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid "Account file"
 msgstr "Soubor s účtem"
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid ""
 "To export your account, go to \"Settings->Export your personal data\" and "
 "select \"Export account\""
@@ -6441,34 +6457,34 @@ msgstr "Viditelný uživatelům"
 msgid "All Contacts (with secure profile access)"
 msgstr "Všem kontaktům (se zabezpečeným přístupem k profilu)"
 
-#: mod/cal.php:277 mod/events.php:391
+#: mod/cal.php:277 mod/events.php:392
 msgid "View"
 msgstr "Zobrazit"
 
-#: mod/cal.php:278 mod/events.php:393
+#: mod/cal.php:278 mod/events.php:394
 msgid "Previous"
 msgstr "Předchozí"
 
-#: mod/cal.php:282 mod/events.php:399 src/Model/Event.php:421
+#: mod/cal.php:282 mod/events.php:400 src/Model/Event.php:422
 msgid "today"
 msgstr "dnes"
 
-#: mod/cal.php:283 mod/events.php:400 src/Util/Temporal.php:304
-#: src/Model/Event.php:422
+#: mod/cal.php:283 mod/events.php:401 src/Util/Temporal.php:304
+#: src/Model/Event.php:423
 msgid "month"
 msgstr "měsíc"
 
-#: mod/cal.php:284 mod/events.php:401 src/Util/Temporal.php:305
-#: src/Model/Event.php:423
+#: mod/cal.php:284 mod/events.php:402 src/Util/Temporal.php:305
+#: src/Model/Event.php:424
 msgid "week"
 msgstr "týden"
 
-#: mod/cal.php:285 mod/events.php:402 src/Util/Temporal.php:306
-#: src/Model/Event.php:424
+#: mod/cal.php:285 mod/events.php:403 src/Util/Temporal.php:306
+#: src/Model/Event.php:425
 msgid "day"
 msgstr "den"
 
-#: mod/cal.php:286 mod/events.php:403
+#: mod/cal.php:286 mod/events.php:404
 msgid "list"
 msgstr "seznam"
 
@@ -6501,19 +6517,19 @@ msgstr "Registrace zrušena pro %s"
 msgid "Please login."
 msgstr "Přihlaste se, prosím."
 
-#: mod/editpost.php:26 mod/editpost.php:36
+#: mod/editpost.php:27 mod/editpost.php:42
 msgid "Item not found"
 msgstr "Položka nenalezena"
 
-#: mod/editpost.php:43
+#: mod/editpost.php:49
 msgid "Edit post"
 msgstr "Upravit příspěvek"
 
-#: mod/editpost.php:125 src/Core/ACL.php:304
+#: mod/editpost.php:131 src/Core/ACL.php:304
 msgid "CC: email addresses"
-msgstr "Skrytá kopie: e-mailové adresy"
+msgstr "Kopie: e-mailové adresy"
 
-#: mod/editpost.php:132 src/Core/ACL.php:305
+#: mod/editpost.php:138 src/Core/ACL.php:305
 msgid "Example: bob@example.com, mary@example.com"
 msgstr "Příklad: jan@priklad.cz, lucie@priklad.cz"
 
@@ -6535,7 +6551,7 @@ msgstr "Zdrojová adresa URL"
 
 #: mod/fsuggest.php:72
 msgid "Friend suggestion sent."
-msgstr "Návrhy přátelství odeslány "
+msgstr "Návrh přátelství odeslán. "
 
 #: mod/fsuggest.php:101
 msgid "Suggest Friends"
@@ -6550,21 +6566,21 @@ msgstr "Navrhnout přítele pro uživatele %s"
 msgid "System down for maintenance"
 msgstr "Systém vypnut z důvodů údržby"
 
-#: mod/profile.php:38 src/Model/Profile.php:115
+#: mod/profile.php:39 src/Model/Profile.php:128
 msgid "Requested profile is not available."
 msgstr "Požadovaný profil není dostupný."
 
-#: mod/profile.php:79 mod/profile.php:82 src/Protocol/OStatus.php:1275
+#: mod/profile.php:89 mod/profile.php:92 src/Protocol/OStatus.php:1285
 #, php-format
 msgid "%s's timeline"
 msgstr "Časová osa uživatele %s"
 
-#: mod/profile.php:80 src/Protocol/OStatus.php:1276
+#: mod/profile.php:90 src/Protocol/OStatus.php:1286
 #, php-format
 msgid "%s's posts"
 msgstr "Příspěvky uživatele %s"
 
-#: mod/profile.php:81 src/Protocol/OStatus.php:1277
+#: mod/profile.php:91 src/Protocol/OStatus.php:1287
 #, php-format
 msgid "%s's comments"
 msgstr "Komentáře uživatele %s"
@@ -6573,7 +6589,7 @@ msgstr "Komentáře uživatele %s"
 msgid "No friends to display."
 msgstr "Žádní přátelé k zobrazení"
 
-#: mod/contacts.php:162
+#: mod/contacts.php:168
 #, php-format
 msgid "%d contact edited."
 msgid_plural "%d contacts edited."
@@ -6582,426 +6598,426 @@ msgstr[1] "%d kontakty upraveny"
 msgstr[2] "%d kontaktu upraveno"
 msgstr[3] "%d kontaktů upraveno"
 
-#: mod/contacts.php:189 mod/contacts.php:395
+#: mod/contacts.php:195 mod/contacts.php:401
 msgid "Could not access contact record."
 msgstr "Nelze získat přístup k záznamu kontaktu."
 
-#: mod/contacts.php:199
+#: mod/contacts.php:205
 msgid "Could not locate selected profile."
 msgstr "Nelze nalézt vybraný profil."
 
-#: mod/contacts.php:233
+#: mod/contacts.php:239
 msgid "Contact updated."
 msgstr "Kontakt aktualizován."
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been blocked"
 msgstr "Kontakt byl zablokován"
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been unblocked"
 msgstr "Kontakt byl odblokován"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been ignored"
 msgstr "Kontakt bude ignorován"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been unignored"
 msgstr "Kontakt přestal být ignorován"
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been archived"
 msgstr "Kontakt byl archivován"
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been unarchived"
 msgstr "Kontakt byl vrácen z archivu."
 
-#: mod/contacts.php:460
+#: mod/contacts.php:466
 msgid "Drop contact"
 msgstr "Zrušit kontakt"
 
-#: mod/contacts.php:463 mod/contacts.php:845
+#: mod/contacts.php:469 mod/contacts.php:848
 msgid "Do you really want to delete this contact?"
 msgstr "Opravdu chcete smazat tento kontakt?"
 
-#: mod/contacts.php:481
+#: mod/contacts.php:487
 msgid "Contact has been removed."
 msgstr "Kontakt byl odstraněn."
 
-#: mod/contacts.php:518
+#: mod/contacts.php:524
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr "Jste vzájemní přátelé s uživatelem %s"
 
-#: mod/contacts.php:523
+#: mod/contacts.php:529
 #, php-format
 msgid "You are sharing with %s"
 msgstr "Sdílíte s uživatelem %s"
 
-#: mod/contacts.php:528
+#: mod/contacts.php:534
 #, php-format
 msgid "%s is sharing with you"
 msgstr "%s s Vámi sdílí"
 
-#: mod/contacts.php:552
+#: mod/contacts.php:558
 msgid "Private communications are not available for this contact."
 msgstr "Soukromá komunikace není dostupná pro tento kontakt."
 
-#: mod/contacts.php:554
+#: mod/contacts.php:560
 msgid "Never"
 msgstr "Nikdy"
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was successful)"
 msgstr "(Aktualizace byla úspěšná)"
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was not successful)"
 msgstr "(Aktualizace nebyla úspěšná)"
 
-#: mod/contacts.php:559 mod/contacts.php:1086
+#: mod/contacts.php:565 mod/contacts.php:1089
 msgid "Suggest friends"
 msgstr "Navrhnout přátele"
 
-#: mod/contacts.php:563
+#: mod/contacts.php:569
 #, php-format
 msgid "Network type: %s"
 msgstr "Typ sítě: %s"
 
-#: mod/contacts.php:568
+#: mod/contacts.php:574
 msgid "Communications lost with this contact!"
 msgstr "Komunikace s tímto kontaktem byla ztracena!"
 
-#: mod/contacts.php:574
+#: mod/contacts.php:580
 msgid "Fetch further information for feeds"
 msgstr "Načíst další informace pro kanál"
 
-#: mod/contacts.php:576
+#: mod/contacts.php:582
 msgid ""
 "Fetch information like preview pictures, title and teaser from the feed "
 "item. You can activate this if the feed doesn't contain much text. Keywords "
 "are taken from the meta header in the feed item and are posted as hash tags."
 msgstr "Načíst informace jako obrázky náhledu, nadpis a popisek z položky kanálu. Toto můžete aktivovat, pokud kanál neobsahuje moc textu. Klíčová slova jsou vzata z hlavičky meta v položce kanálu a jsou zveřejněna jako hashtagy."
 
-#: mod/contacts.php:578
+#: mod/contacts.php:584
 msgid "Fetch information"
 msgstr "Načíst informace"
 
-#: mod/contacts.php:579
+#: mod/contacts.php:585
 msgid "Fetch keywords"
 msgstr "Načíst klíčová slova"
 
-#: mod/contacts.php:580
+#: mod/contacts.php:586
 msgid "Fetch information and keywords"
 msgstr "Načíst informace a klíčová slova"
 
-#: mod/contacts.php:617
+#: mod/contacts.php:618
 msgid "Profile Visibility"
 msgstr "Viditelnost profilu"
 
-#: mod/contacts.php:618
+#: mod/contacts.php:619
 msgid "Contact Information / Notes"
 msgstr "Kontaktní informace / poznámky"
 
-#: mod/contacts.php:619
+#: mod/contacts.php:620
 msgid "Contact Settings"
 msgstr "Nastavení kontaktů"
 
-#: mod/contacts.php:628
+#: mod/contacts.php:629
 msgid "Contact"
 msgstr "Kontakt"
 
-#: mod/contacts.php:632
+#: mod/contacts.php:633
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
 msgstr "Vyberte prosím profil, který chcete zobrazit %s při zabezpečeném prohlížení vašeho profilu."
 
-#: mod/contacts.php:634
+#: mod/contacts.php:635
 msgid "Their personal note"
 msgstr "Jejich osobní poznámka"
 
-#: mod/contacts.php:636
+#: mod/contacts.php:637
 msgid "Edit contact notes"
 msgstr "Upravit poznámky kontaktu"
 
-#: mod/contacts.php:640
+#: mod/contacts.php:641
 msgid "Block/Unblock contact"
 msgstr "Blokovat / Odblokovat kontakt"
 
-#: mod/contacts.php:641
+#: mod/contacts.php:642
 msgid "Ignore contact"
 msgstr "Ignorovat kontakt"
 
-#: mod/contacts.php:642
+#: mod/contacts.php:643
 msgid "Repair URL settings"
 msgstr "Opravit nastavení adresy URL "
 
-#: mod/contacts.php:643
+#: mod/contacts.php:644
 msgid "View conversations"
 msgstr "Zobrazit konverzace"
 
-#: mod/contacts.php:648
+#: mod/contacts.php:649
 msgid "Last update:"
 msgstr "Poslední aktualizace:"
 
-#: mod/contacts.php:650
+#: mod/contacts.php:651
 msgid "Update public posts"
 msgstr "Aktualizovat veřejné příspěvky"
 
-#: mod/contacts.php:652 mod/contacts.php:1096
+#: mod/contacts.php:653 mod/contacts.php:1099
 msgid "Update now"
 msgstr "Aktualizovat"
 
-#: mod/contacts.php:658 mod/contacts.php:850 mod/contacts.php:1113
+#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116
 msgid "Unignore"
 msgstr "Přestat ignorovat"
 
-#: mod/contacts.php:662
+#: mod/contacts.php:663
 msgid "Currently blocked"
 msgstr "V současnosti zablokováno"
 
-#: mod/contacts.php:663
+#: mod/contacts.php:664
 msgid "Currently ignored"
 msgstr "V současnosti ignorováno"
 
-#: mod/contacts.php:664
+#: mod/contacts.php:665
 msgid "Currently archived"
 msgstr "Aktuálně archivován"
 
-#: mod/contacts.php:665
+#: mod/contacts.php:666
 msgid "Awaiting connection acknowledge"
 msgstr "Čekám na potrvzení spojení"
 
-#: mod/contacts.php:666
+#: mod/contacts.php:667
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr "Odpovědi/oblíbení na Vaše veřejné příspěvky <strong>mohou</strong> být stále viditelné"
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Notification for new posts"
 msgstr "Upozornění na nové příspěvky"
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Send a notification of every new post of this contact"
 msgstr "Poslat upozornění při každém novém příspěvku tohoto kontaktu"
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid "Blacklisted keywords"
 msgstr "Zakázaná klíčová slova"
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
-msgstr "Seznam klíčových slov, které by neměly být převáděna na hashtagy, když je zvoleno \"Načíst informace a klíčová slova\". Oddělujte čárkami"
+msgstr "Seznam klíčových slov, které by neměly být převáděna na hashtagy, když je zvoleno „Načíst informace a klíčová slova“. Oddělujte čárkami"
 
-#: mod/contacts.php:682 src/Model/Profile.php:424
+#: mod/contacts.php:683 src/Model/Profile.php:437
 msgid "XMPP:"
 msgstr "XMPP:"
 
-#: mod/contacts.php:687
+#: mod/contacts.php:688
 msgid "Actions"
 msgstr "Akce"
 
-#: mod/contacts.php:731
+#: mod/contacts.php:734
 msgid "Suggestions"
 msgstr "Návrhy"
 
-#: mod/contacts.php:734
+#: mod/contacts.php:737
 msgid "Suggest potential friends"
 msgstr "Navrhnout potenciální přátele"
 
-#: mod/contacts.php:742
+#: mod/contacts.php:745
 msgid "Show all contacts"
 msgstr "Zobrazit všechny kontakty"
 
-#: mod/contacts.php:747
+#: mod/contacts.php:750
 msgid "Unblocked"
 msgstr "Odblokován"
 
-#: mod/contacts.php:750
+#: mod/contacts.php:753
 msgid "Only show unblocked contacts"
 msgstr "Zobrazit pouze neblokované kontakty"
 
-#: mod/contacts.php:755
+#: mod/contacts.php:758
 msgid "Blocked"
 msgstr "Blokován"
 
-#: mod/contacts.php:758
+#: mod/contacts.php:761
 msgid "Only show blocked contacts"
 msgstr "Zobrazit pouze blokované kontakty"
 
-#: mod/contacts.php:763
+#: mod/contacts.php:766
 msgid "Ignored"
 msgstr "Ignorován"
 
-#: mod/contacts.php:766
+#: mod/contacts.php:769
 msgid "Only show ignored contacts"
 msgstr "Zobrazit pouze ignorované kontakty"
 
-#: mod/contacts.php:771
+#: mod/contacts.php:774
 msgid "Archived"
 msgstr "Archivován"
 
-#: mod/contacts.php:774
+#: mod/contacts.php:777
 msgid "Only show archived contacts"
 msgstr "Zobrazit pouze archivované kontakty"
 
-#: mod/contacts.php:779
+#: mod/contacts.php:782
 msgid "Hidden"
 msgstr "Skrytý"
 
-#: mod/contacts.php:782
+#: mod/contacts.php:785
 msgid "Only show hidden contacts"
 msgstr "Zobrazit pouze skryté kontakty"
 
-#: mod/contacts.php:840
+#: mod/contacts.php:843
 msgid "Search your contacts"
 msgstr "Prohledat Vaše kontakty"
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Archive"
 msgstr "Archivovat"
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Unarchive"
 msgstr "Vrátit z archivu"
 
-#: mod/contacts.php:854
+#: mod/contacts.php:857
 msgid "Batch Actions"
 msgstr "Souhrnné akce"
 
-#: mod/contacts.php:880
+#: mod/contacts.php:883
 msgid "Conversations started by this contact"
 msgstr "Konverzace, které tento kontakt začal"
 
-#: mod/contacts.php:885
+#: mod/contacts.php:888
 msgid "Posts and Comments"
 msgstr "Příspěvky a komentáře"
 
-#: mod/contacts.php:896 src/Model/Profile.php:886
+#: mod/contacts.php:899 src/Model/Profile.php:899
 msgid "Profile Details"
 msgstr "Detaily profilu"
 
-#: mod/contacts.php:908
+#: mod/contacts.php:911
 msgid "View all contacts"
 msgstr "Zobrazit všechny kontakty"
 
-#: mod/contacts.php:919
+#: mod/contacts.php:922
 msgid "View all common friends"
 msgstr "Zobrazit všechny společné přátele"
 
-#: mod/contacts.php:929
+#: mod/contacts.php:932
 msgid "Advanced Contact Settings"
 msgstr "Pokročilé nastavení kontaktu"
 
-#: mod/contacts.php:1019
+#: mod/contacts.php:1022
 msgid "Mutual Friendship"
 msgstr "Vzájemné přátelství"
 
-#: mod/contacts.php:1024
+#: mod/contacts.php:1027
 msgid "is a fan of yours"
 msgstr "je Váš fanoušek"
 
-#: mod/contacts.php:1029
+#: mod/contacts.php:1032
 msgid "you are a fan of"
 msgstr "jste fanouškem"
 
-#: mod/contacts.php:1046 mod/photos.php:1494 mod/photos.php:1533
-#: mod/photos.php:1593 src/Object/Post.php:792
+#: mod/contacts.php:1049 mod/photos.php:1496 mod/photos.php:1535
+#: mod/photos.php:1595 src/Object/Post.php:792
 msgid "This is you"
 msgstr "Nastavte Vaši polohu"
 
-#: mod/contacts.php:1053
+#: mod/contacts.php:1056
 msgid "Edit contact"
 msgstr "Upravit kontakt"
 
-#: mod/contacts.php:1107
+#: mod/contacts.php:1110
 msgid "Toggle Blocked status"
 msgstr "Přepínat stav Blokováno"
 
-#: mod/contacts.php:1115
+#: mod/contacts.php:1118
 msgid "Toggle Ignored status"
 msgstr "Přepínat stav Ignorováno"
 
-#: mod/contacts.php:1124
+#: mod/contacts.php:1127
 msgid "Toggle Archive status"
 msgstr "Přepínat stav Archivováno"
 
-#: mod/contacts.php:1132
+#: mod/contacts.php:1135
 msgid "Delete contact"
 msgstr "Odstranit kontakt"
 
-#: mod/events.php:103 mod/events.php:105
+#: mod/events.php:105 mod/events.php:107
 msgid "Event can not end before it has started."
 msgstr "Událost nemůže končit dříve, než začala."
 
-#: mod/events.php:112 mod/events.php:114
+#: mod/events.php:114 mod/events.php:116
 msgid "Event title and start time are required."
 msgstr "Název události a datum začátku jsou vyžadovány."
 
-#: mod/events.php:392
+#: mod/events.php:393
 msgid "Create New Event"
 msgstr "Vytvořit novou událost"
 
-#: mod/events.php:509
+#: mod/events.php:516
 msgid "Event details"
 msgstr "Detaily události"
 
-#: mod/events.php:510
+#: mod/events.php:517
 msgid "Starting date and Title are required."
 msgstr "Počáteční datum a Název jsou vyžadovány."
 
-#: mod/events.php:511 mod/events.php:512
+#: mod/events.php:518 mod/events.php:523
 msgid "Event Starts:"
 msgstr "Událost začíná:"
 
-#: mod/events.php:511 mod/events.php:523 mod/profiles.php:607
+#: mod/events.php:518 mod/events.php:550 mod/profiles.php:607
 msgid "Required"
 msgstr "Vyžadováno"
 
-#: mod/events.php:513 mod/events.php:529
+#: mod/events.php:531 mod/events.php:556
 msgid "Finish date/time is not known or not relevant"
 msgstr "Datum/čas konce není zadán nebo není relevantní"
 
-#: mod/events.php:515 mod/events.php:516
+#: mod/events.php:533 mod/events.php:538
 msgid "Event Finishes:"
 msgstr "Akce končí:"
 
-#: mod/events.php:517 mod/events.php:530
+#: mod/events.php:544 mod/events.php:557
 msgid "Adjust for viewer timezone"
 msgstr "Nastavit časové pásmo pro uživatele s právem pro čtení"
 
-#: mod/events.php:519
+#: mod/events.php:546
 msgid "Description:"
 msgstr "Popis:"
 
-#: mod/events.php:523 mod/events.php:525
+#: mod/events.php:550 mod/events.php:552
 msgid "Title:"
 msgstr "Název:"
 
-#: mod/events.php:526 mod/events.php:527
+#: mod/events.php:553 mod/events.php:554
 msgid "Share this event"
 msgstr "Sdílet tuto událost"
 
-#: mod/events.php:534 src/Model/Profile.php:851
+#: mod/events.php:561 src/Model/Profile.php:864
 msgid "Basic"
 msgstr "Základní"
 
-#: mod/events.php:536 mod/photos.php:1112 mod/photos.php:1448
+#: mod/events.php:563 mod/photos.php:1114 mod/photos.php:1450
 #: src/Core/ACL.php:307
 msgid "Permissions"
-msgstr "Oprávnění:"
+msgstr "Oprávnění"
 
-#: mod/events.php:555
+#: mod/events.php:579
 msgid "Failed to remove event"
 msgstr "Odstranění události selhalo"
 
-#: mod/events.php:557
+#: mod/events.php:581
 msgid "Event removed"
 msgstr "Událost odstraněna"
 
@@ -7026,8 +7042,8 @@ msgid "The network type couldn't be detected. Contact can't be added."
 msgstr "Typ sítě nemohl být detekován. Kontakt nemůže být přidán."
 
 #: mod/fbrowser.php:44 mod/fbrowser.php:69 mod/photos.php:198
-#: mod/photos.php:1076 mod/photos.php:1169 mod/photos.php:1186
-#: mod/photos.php:1652 mod/photos.php:1667 src/Model/Photo.php:243
+#: mod/photos.php:1078 mod/photos.php:1171 mod/photos.php:1188
+#: mod/photos.php:1654 mod/photos.php:1669 src/Model/Photo.php:243
 #: src/Model/Photo.php:252
 msgid "Contact Photos"
 msgstr "Fotky kontaktu"
@@ -7098,7 +7114,7 @@ msgid ""
 " not reflect the opinions of this node’s users."
 msgstr "Tento komunitní proud ukazuje všechny veřejné příspěvky, které tento server přijme. Nemusí odrážet názory uživatelů serveru."
 
-#: mod/localtime.php:19 src/Model/Event.php:34 src/Model/Event.php:829
+#: mod/localtime.php:19 src/Model/Event.php:35 src/Model/Event.php:836
 msgid "l F d, Y \\@ g:i A"
 msgstr "l d. F, Y v g:i A"
 
@@ -7131,23 +7147,23 @@ msgstr "Převedený místní čas : %s"
 msgid "Please select your timezone:"
 msgstr "Prosím, vyberte své časové pásmo:"
 
-#: mod/poke.php:188
+#: mod/poke.php:187
 msgid "Poke/Prod"
 msgstr "Šťouchnout/dloubnout"
 
-#: mod/poke.php:189
+#: mod/poke.php:188
 msgid "poke, prod or do other things to somebody"
 msgstr "někoho šťouchnout, dloubnout, nebo mu provést jinou věc"
 
-#: mod/poke.php:190
+#: mod/poke.php:189
 msgid "Recipient"
 msgstr "Příjemce"
 
-#: mod/poke.php:191
+#: mod/poke.php:190
 msgid "Choose what you wish to do to recipient"
 msgstr "Vyberte, co si přejete příjemci udělat"
 
-#: mod/poke.php:194
+#: mod/poke.php:193
 msgid "Make this post private"
 msgstr "Změnit tento příspěvek na soukromý"
 
@@ -7162,7 +7178,7 @@ msgstr "%s : není platná e-mailová adresa."
 
 #: mod/invite.php:88
 msgid "Please join us on Friendica"
-msgstr "Prosím přidejte se k nám na Friendice"
+msgstr "Prosím přidejte se k nám na Friendica"
 
 #: mod/invite.php:97
 msgid "Invitation limit exceeded. Please contact your site administrator."
@@ -7192,7 +7208,7 @@ msgid ""
 "Visit %s for a list of public sites that you can join. Friendica members on "
 "other sites can all connect with each other, as well as with members of many"
 " other social networks."
-msgstr "Navštivte %s pro seznam veřejných serverů, na kterých se můžete přidat. Členové Friendica na jiných serverech se mohou spojit mezi sebou, jakožto i se členy mnoha dalších sociálních sítí."
+msgstr "Navštiv %s pro seznam veřejných serverů, na kterých se můžeš přidat. Členové Friendica na jiných serverech se mohou spojit mezi sebou, jakožto i se členy mnoha dalších sociálních sítí."
 
 #: mod/invite.php:133
 #, php-format
@@ -7255,9 +7271,9 @@ msgstr "Jakmile se zaregistruješ, prosím spoj se se mnou přes mou profilovu s
 msgid ""
 "For more information about the Friendica project and why we feel it is "
 "important, please visit http://friendi.ca"
-msgstr "Pro více informací o projektu Friendica a proč si myslíme, že je důležitý, prosím navštivte http://friendi.ca"
+msgstr "Pro více informací o projektu Friendica a proč si myslím, že je důležitý, prosím navštiv http://friendi.ca"
 
-#: mod/notes.php:42 src/Model/Profile.php:933
+#: mod/notes.php:42 src/Model/Profile.php:946
 msgid "Personal Notes"
 msgstr "Osobní poznámky"
 
@@ -7361,7 +7377,7 @@ msgstr "Zobrazit tento profil"
 msgid "View all profiles"
 msgstr "Zobrazit všechny profily"
 
-#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:393
+#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:406
 msgid "Edit visibility"
 msgstr "Upravit viditelnost"
 
@@ -7413,7 +7429,7 @@ msgstr "Vaše pohlaví:"
 msgid "<span class=\"heart\">&hearts;</span> Marital Status:"
 msgstr "<span class=\"heart\">&hearts;</span> Rodinný stav:"
 
-#: mod/profiles.php:601 src/Model/Profile.php:769
+#: mod/profiles.php:601 src/Model/Profile.php:782
 msgid "Sexual Preference:"
 msgstr "Sexuální orientace:"
 
@@ -7493,11 +7509,11 @@ msgstr "Adresa XMPP bude rozšířena mezi Vašemi kontakty, aby vás mohly sled
 msgid "Homepage URL:"
 msgstr "Odkaz na domovskou stránku:"
 
-#: mod/profiles.php:628 src/Model/Profile.php:777
+#: mod/profiles.php:628 src/Model/Profile.php:790
 msgid "Hometown:"
 msgstr "Rodné město:"
 
-#: mod/profiles.php:629 src/Model/Profile.php:785
+#: mod/profiles.php:629 src/Model/Profile.php:798
 msgid "Political Views:"
 msgstr "Politické přesvědčení:"
 
@@ -7521,11 +7537,11 @@ msgstr "Soukromá klíčová slova:"
 msgid "(Used for searching profiles, never shown to others)"
 msgstr "(Používá se pro vyhledávání profilů, není nikdy zobrazeno ostatním)"
 
-#: mod/profiles.php:633 src/Model/Profile.php:801
+#: mod/profiles.php:633 src/Model/Profile.php:814
 msgid "Likes:"
 msgstr "Líbí se:"
 
-#: mod/profiles.php:634 src/Model/Profile.php:805
+#: mod/profiles.php:634 src/Model/Profile.php:818
 msgid "Dislikes:"
 msgstr "Nelibí se:"
 
@@ -7565,11 +7581,11 @@ msgstr "Škola/vzdělání"
 msgid "Contact information and Social Networks"
 msgstr "Kontaktní informace a sociální sítě"
 
-#: mod/profiles.php:674 src/Model/Profile.php:389
+#: mod/profiles.php:674 src/Model/Profile.php:402
 msgid "Profile Image"
 msgstr "Profilový obrázek"
 
-#: mod/profiles.php:676 src/Model/Profile.php:392
+#: mod/profiles.php:676 src/Model/Profile.php:405
 msgid "visible to everybody"
 msgstr "viditelné pro všechny"
 
@@ -7577,23 +7593,23 @@ msgstr "viditelné pro všechny"
 msgid "Edit/Manage Profiles"
 msgstr "Upravit/spravovat profily"
 
-#: mod/profiles.php:684 src/Model/Profile.php:379 src/Model/Profile.php:401
+#: mod/profiles.php:684 src/Model/Profile.php:392 src/Model/Profile.php:414
 msgid "Change profile photo"
 msgstr "Změnit profilovou fotku"
 
-#: mod/profiles.php:685 src/Model/Profile.php:380
+#: mod/profiles.php:685 src/Model/Profile.php:393
 msgid "Create New Profile"
 msgstr "Vytvořit nový profil"
 
-#: mod/photos.php:112 src/Model/Profile.php:894
+#: mod/photos.php:112 src/Model/Profile.php:907
 msgid "Photo Albums"
 msgstr "Fotoalba"
 
-#: mod/photos.php:113 mod/photos.php:1708
+#: mod/photos.php:113 mod/photos.php:1710
 msgid "Recent Photos"
 msgstr "Nedávné fotky"
 
-#: mod/photos.php:116 mod/photos.php:1230 mod/photos.php:1710
+#: mod/photos.php:116 mod/photos.php:1232 mod/photos.php:1712
 msgid "Upload New Photos"
 msgstr "Nahrát nové fotky"
 
@@ -7605,7 +7621,7 @@ msgstr "Kontakt byl zablokován"
 msgid "Album not found."
 msgstr "Album nenalezeno."
 
-#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1181
+#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1183
 msgid "Delete Album"
 msgstr "Smazat album"
 
@@ -7613,7 +7629,7 @@ msgstr "Smazat album"
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr "Opravdu chcete smazat toto fotoalbum a všechny jeho fotky?"
 
-#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1453
+#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1455
 msgid "Delete Photo"
 msgstr "Smazat fotku"
 
@@ -7630,150 +7646,150 @@ msgstr "fotce"
 msgid "%1$s was tagged in %2$s by %3$s"
 msgstr "%1$s byl označen ve %2$s uživatelem %3$s"
 
-#: mod/photos.php:782
+#: mod/photos.php:784
 msgid "Image upload didn't complete, please try again"
 msgstr "Nahrávání obrázku nebylo dokončeno, zkuste to prosím znovu"
 
-#: mod/photos.php:785
+#: mod/photos.php:787
 msgid "Image file is missing"
 msgstr "Chybí soubor obrázku"
 
-#: mod/photos.php:790
+#: mod/photos.php:792
 msgid ""
 "Server can't accept new file upload at this time, please contact your "
 "administrator"
 msgstr "Server v tuto chvíli nemůže akceptovat nové nahrané soubory, prosím kontaktujte Vašeho administrátora"
 
-#: mod/photos.php:816
+#: mod/photos.php:818
 msgid "Image file is empty."
 msgstr "Soubor obrázku je prázdný."
 
-#: mod/photos.php:953
+#: mod/photos.php:955
 msgid "No photos selected"
 msgstr "Není vybrána žádná fotka"
 
-#: mod/photos.php:1104
+#: mod/photos.php:1106
 msgid "Upload Photos"
 msgstr "Nahrát fotky"
 
-#: mod/photos.php:1108 mod/photos.php:1176
+#: mod/photos.php:1110 mod/photos.php:1178
 msgid "New album name: "
 msgstr "Název nového alba: "
 
-#: mod/photos.php:1109
+#: mod/photos.php:1111
 msgid "or select existing album:"
 msgstr "nebo si vyberte existující album:"
 
-#: mod/photos.php:1110
+#: mod/photos.php:1112
 msgid "Do not show a status post for this upload"
-msgstr "Nezobrazovat pro toto nahrání stavový příspěvek"
+msgstr "Nezobrazovat pro toto nahrání stavovou zprávu"
 
-#: mod/photos.php:1187
+#: mod/photos.php:1189
 msgid "Edit Album"
 msgstr "Upravit album"
 
-#: mod/photos.php:1192
+#: mod/photos.php:1194
 msgid "Show Newest First"
-msgstr "Zobrazit nejprve nejnovější:"
+msgstr "Zobrazit nejprve nejnovější"
 
-#: mod/photos.php:1194
+#: mod/photos.php:1196
 msgid "Show Oldest First"
-msgstr "Zobrazit nejprve nejstarší:"
+msgstr "Zobrazit nejprve nejstarší"
 
-#: mod/photos.php:1215 mod/photos.php:1693
+#: mod/photos.php:1217 mod/photos.php:1695
 msgid "View Photo"
 msgstr "Zobrazit fotku"
 
-#: mod/photos.php:1256
+#: mod/photos.php:1258
 msgid "Permission denied. Access to this item may be restricted."
 msgstr "Oprávnění bylo zamítnuto. Přístup k této položce může být omezen."
 
-#: mod/photos.php:1258
+#: mod/photos.php:1260
 msgid "Photo not available"
 msgstr "Fotka není k dispozici"
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "View photo"
 msgstr "Zobrazit fotku"
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "Edit photo"
 msgstr "Upravit fotku"
 
-#: mod/photos.php:1334
+#: mod/photos.php:1336
 msgid "Use as profile photo"
 msgstr "Použít jako profilovou fotku"
 
-#: mod/photos.php:1340 src/Object/Post.php:151
+#: mod/photos.php:1342 src/Object/Post.php:151
 msgid "Private Message"
 msgstr "Soukromá zpráva"
 
-#: mod/photos.php:1360
+#: mod/photos.php:1362
 msgid "View Full Size"
 msgstr "Zobrazit v plné velikosti"
 
-#: mod/photos.php:1421
+#: mod/photos.php:1423
 msgid "Tags: "
 msgstr "Štítky: "
 
-#: mod/photos.php:1424
+#: mod/photos.php:1426
 msgid "[Remove any tag]"
 msgstr "[Odstranit všechny štítky]"
 
-#: mod/photos.php:1439
+#: mod/photos.php:1441
 msgid "New album name"
 msgstr "Nové jméno alba"
 
-#: mod/photos.php:1440
+#: mod/photos.php:1442
 msgid "Caption"
 msgstr "Titulek"
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid "Add a Tag"
 msgstr "Přidat štítek"
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid ""
 "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr "Příklad: @jan, @Lucie_Nováková, @jakub@priklad.cz, #Morava, #taboreni"
 
-#: mod/photos.php:1442
+#: mod/photos.php:1444
 msgid "Do not rotate"
 msgstr "Neotáčet"
 
-#: mod/photos.php:1443
+#: mod/photos.php:1445
 msgid "Rotate CW (right)"
 msgstr "Otáčet po směru hodinových ručiček (doprava)"
 
-#: mod/photos.php:1444
+#: mod/photos.php:1446
 msgid "Rotate CCW (left)"
 msgstr "Otáčet proti směru hodinových ručiček (doleva)"
 
-#: mod/photos.php:1478 src/Object/Post.php:293
+#: mod/photos.php:1480 src/Object/Post.php:293
 msgid "I like this (toggle)"
-msgstr "Líbí se mi to (přepínač)"
+msgstr "To se mi líbí (přepínat)"
 
-#: mod/photos.php:1479 src/Object/Post.php:294
+#: mod/photos.php:1481 src/Object/Post.php:294
 msgid "I don't like this (toggle)"
-msgstr "Nelíbí se mi to (přepínač)"
+msgstr "To se mi nelíbí (přepínat)"
 
-#: mod/photos.php:1496 mod/photos.php:1535 mod/photos.php:1595
+#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
 #: src/Object/Post.php:398 src/Object/Post.php:794
 msgid "Comment"
 msgstr "Okomentovat"
 
-#: mod/photos.php:1627
+#: mod/photos.php:1629
 msgid "Map"
 msgstr "Mapa"
 
-#: local/test.php:1840
+#: local/test.php:1919
 #, php-format
 msgid ""
 "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-"
 "name\">%s</a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"
 msgstr "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-name\">%s</a> napsal/a následující <a href=\"%s\" target=\"_blank\">příspěvek</a>"
 
-#: local/testshare.php:158 src/Content/Text/BBCode.php:991
+#: local/testshare.php:158 src/Content/Text/BBCode.php:992
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 msgstr "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
@@ -7833,11 +7849,11 @@ msgstr "%s: Aktualizace databáze"
 msgid "%s: updating %s table."
 msgstr "%s: aktualizuji tabulku %s"
 
-#: src/Core/Install.php:138
+#: src/Core/Install.php:139
 msgid "Could not find a command line version of PHP in the web server PATH."
 msgstr "Nelze najít verzi PHP pro příkazový řádek v PATH webového serveru."
 
-#: src/Core/Install.php:139
+#: src/Core/Install.php:140
 msgid ""
 "If you don't have a command line version of PHP installed on your server, "
 "you will not be able to run the background processing. See <a "
@@ -7845,219 +7861,219 @@ msgid ""
 "up-the-worker'>'Setup the worker'</a>"
 msgstr "Pokud nemáte na Vašem serveru nainstalovanou verzi PHP pro příkazový řádek, nebudete moci spouštět procesy v pozadí. Více na <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>\"Nastavte pracovníka\"</a>"
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid "PHP executable path"
 msgstr "Cesta ke spustitelnému souboru PHP"
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid ""
 "Enter full path to php executable. You can leave this blank to continue the "
 "installation."
 msgstr "Zadejte plnou cestu ke spustitelnému souboru PHP. Tento údaj můžete ponechat nevyplněný a pokračovat v instalaci."
 
-#: src/Core/Install.php:148
+#: src/Core/Install.php:149
 msgid "Command line PHP"
 msgstr "Příkazový řádek PHP"
 
-#: src/Core/Install.php:157
+#: src/Core/Install.php:158
 msgid "PHP executable is not the php cli binary (could be cgi-fgci version)"
 msgstr "PHP executable není php cli binary (může být verze cgi-fgci)"
 
-#: src/Core/Install.php:158
+#: src/Core/Install.php:159
 msgid "Found PHP version: "
 msgstr "Nalezena PHP verze:"
 
-#: src/Core/Install.php:160
+#: src/Core/Install.php:161
 msgid "PHP cli binary"
 msgstr "PHP cli binary"
 
-#: src/Core/Install.php:170
+#: src/Core/Install.php:171
 msgid ""
 "The command line version of PHP on your system does not have "
 "\"register_argc_argv\" enabled."
 msgstr "Verze PHP pro příkazový řádek na Vašem systému nemá povoleno nastavení \"register_argc_argv\"."
 
-#: src/Core/Install.php:171
+#: src/Core/Install.php:172
 msgid "This is required for message delivery to work."
 msgstr "Toto je nutné pro fungování doručování zpráv."
 
-#: src/Core/Install.php:173
+#: src/Core/Install.php:174
 msgid "PHP register_argc_argv"
 msgstr "PHP register_argc_argv"
 
-#: src/Core/Install.php:201
+#: src/Core/Install.php:202
 msgid ""
 "Error: the \"openssl_pkey_new\" function on this system is not able to "
 "generate encryption keys"
 msgstr "Chyba: funkce \"openssl_pkey_new\" na tomto systému není schopna generovat šifrovací klíče"
 
-#: src/Core/Install.php:202
+#: src/Core/Install.php:203
 msgid ""
 "If running under Windows, please see "
 "\"http://www.php.net/manual/en/openssl.installation.php\"."
 msgstr "Pokud systém běží na Windows, prosím přečtěte si \"http://www.php.net/manual/en/openssl.installation.php\"."
 
-#: src/Core/Install.php:204
+#: src/Core/Install.php:205
 msgid "Generate encryption keys"
 msgstr "Generovat šifrovací klíče"
 
-#: src/Core/Install.php:225
+#: src/Core/Install.php:226
 msgid "libCurl PHP module"
 msgstr "PHP modul libCurl"
 
-#: src/Core/Install.php:226
+#: src/Core/Install.php:227
 msgid "GD graphics PHP module"
 msgstr "PHP modul GD graphics"
 
-#: src/Core/Install.php:227
+#: src/Core/Install.php:228
 msgid "OpenSSL PHP module"
 msgstr "PHP modul OpenSSL"
 
-#: src/Core/Install.php:228
+#: src/Core/Install.php:229
 msgid "PDO or MySQLi PHP module"
 msgstr "PHP modul PDO nebo MySQLi"
 
-#: src/Core/Install.php:229
+#: src/Core/Install.php:230
 msgid "mb_string PHP module"
 msgstr "PHP modul mb_string"
 
-#: src/Core/Install.php:230
+#: src/Core/Install.php:231
 msgid "XML PHP module"
 msgstr "PHP modul XML"
 
-#: src/Core/Install.php:231
+#: src/Core/Install.php:232
 msgid "iconv PHP module"
 msgstr "PHP modul iconv"
 
-#: src/Core/Install.php:232
+#: src/Core/Install.php:233
 msgid "POSIX PHP module"
 msgstr "PHP modul POSIX"
 
-#: src/Core/Install.php:236 src/Core/Install.php:238
+#: src/Core/Install.php:237 src/Core/Install.php:239
 msgid "Apache mod_rewrite module"
 msgstr "Modul Apache mod_rewrite"
 
-#: src/Core/Install.php:236
+#: src/Core/Install.php:237
 msgid ""
 "Error: Apache webserver mod-rewrite module is required but not installed."
 msgstr "Chyba: Modul mod_rewrite webového serveru Apache je vyadován, ale není nainstalován."
 
-#: src/Core/Install.php:244
+#: src/Core/Install.php:245
 msgid "Error: libCURL PHP module required but not installed."
 msgstr "Chyba: PHP modul libcurl je vyžadován, ale není nainstalován."
 
-#: src/Core/Install.php:248
+#: src/Core/Install.php:249
 msgid ""
 "Error: GD graphics PHP module with JPEG support required but not installed."
 msgstr "Chyba: PHP modul GD graphics je vyžadován, ale není nainstalován."
 
-#: src/Core/Install.php:252
+#: src/Core/Install.php:253
 msgid "Error: openssl PHP module required but not installed."
 msgstr "Chyba: PHP modul openssl je vyžadován, ale není nainstalován."
 
-#: src/Core/Install.php:256
+#: src/Core/Install.php:257
 msgid "Error: PDO or MySQLi PHP module required but not installed."
 msgstr "Chyba: PHP modul PDO nebo MySQLi je vyžadován, ale není nainstalován."
 
-#: src/Core/Install.php:260
+#: src/Core/Install.php:261
 msgid "Error: The MySQL driver for PDO is not installed."
 msgstr "Chyba: Ovladač MySQL pro PDO není nainstalován"
 
-#: src/Core/Install.php:264
+#: src/Core/Install.php:265
 msgid "Error: mb_string PHP module required but not installed."
 msgstr "Chyba: PHP modul mb_string  je vyžadován, ale není nainstalován."
 
-#: src/Core/Install.php:268
+#: src/Core/Install.php:269
 msgid "Error: iconv PHP module required but not installed."
 msgstr "Chyba: PHP modul iconv je vyžadován, ale není nainstalován"
 
-#: src/Core/Install.php:272
+#: src/Core/Install.php:273
 msgid "Error: POSIX PHP module required but not installed."
 msgstr "Chyba: PHP modul POSIX je vyžadován, ale není nainstalován."
 
-#: src/Core/Install.php:282
+#: src/Core/Install.php:283
 msgid "Error, XML PHP module required but not installed."
 msgstr "Chyba: PHP modul XML je vyžadován, ale není nainstalován"
 
-#: src/Core/Install.php:301
+#: src/Core/Install.php:302
 msgid ""
 "The web installer needs to be able to create a file called \"local.ini.php\""
 " in the \"config\" folder of your web server and it is unable to do so."
 msgstr "Webový instalátor musí být schopen vytvořit soubor s názvem \"local.ini.php\" v adresáři \"config\" Vašeho webového serveru, ale nyní mu to není umožněno. "
 
-#: src/Core/Install.php:302
+#: src/Core/Install.php:303
 msgid ""
 "This is most often a permission setting, as the web server may not be able "
 "to write files in your folder - even if you can."
 msgstr "Toto je nejčastěji nastavením oprávnění, kdy webový server nemusí být schopen zapisovat soubory do vašeho adresáře - i když Vy můžete."
 
-#: src/Core/Install.php:303
+#: src/Core/Install.php:304
 msgid ""
 "At the end of this procedure, we will give you a text to save in a file "
 "named local.ini.php in your Friendica \"config\" folder."
 msgstr "Na konci této procedury od nás obdržíte text k uložení v souboru pojmenovaném local.ini.php v adresáři \"config\" na Vaší instalaci Friendica."
 
-#: src/Core/Install.php:304
+#: src/Core/Install.php:305
 msgid ""
 "You can alternatively skip this procedure and perform a manual installation."
 " Please see the file \"INSTALL.txt\" for instructions."
 msgstr "Alternativně můžete tento krok přeskočit a provést manuální instalaci. Přečtěte si prosím soubor \"INSTALL.txt\" pro další instrukce."
 
-#: src/Core/Install.php:307
+#: src/Core/Install.php:308
 msgid "config/local.ini.php is writable"
 msgstr "Soubor config/local.ini.php je zapisovatelný"
 
-#: src/Core/Install.php:325
+#: src/Core/Install.php:326
 msgid ""
 "Friendica uses the Smarty3 template engine to render its web views. Smarty3 "
 "compiles templates to PHP to speed up rendering."
 msgstr "Friendica používá k zobrazení svých webových stránek šablonovací nástroj Smarty3. Smarty3 kompiluje šablony do PHP pro zrychlení vykreslování."
 
-#: src/Core/Install.php:326
+#: src/Core/Install.php:327
 msgid ""
 "In order to store these compiled templates, the web server needs to have "
 "write access to the directory view/smarty3/ under the Friendica top level "
 "folder."
 msgstr "Pro uložení kompilovaných šablon potřebuje webový server mít přístup k zápisu do adresáře view/smarty3/ pod kořenovým adresářem Friendica."
 
-#: src/Core/Install.php:327
+#: src/Core/Install.php:328
 msgid ""
 "Please ensure that the user that your web server runs as (e.g. www-data) has"
 " write access to this folder."
 msgstr "Prosím ujistěte se, že má uživatel webového serveru (jako například www-data) právo zápisu do tohoto adresáře"
 
-#: src/Core/Install.php:328
+#: src/Core/Install.php:329
 msgid ""
 "Note: as a security measure, you should give the web server write access to "
 "view/smarty3/ only--not the template files (.tpl) that it contains."
 msgstr "Poznámka: jako bezpečnostní opatření byste měl/a přidělit webovém serveru právo zápisu pouze do adresáře /view/smarty3/ -- a nikoliv už do souborů s šablonami (.tpl), které obsahuje."
 
-#: src/Core/Install.php:331
+#: src/Core/Install.php:332
 msgid "view/smarty3 is writable"
 msgstr "Adresář view/smarty3 je zapisovatelný"
 
-#: src/Core/Install.php:356
+#: src/Core/Install.php:357
 msgid ""
 "Url rewrite in .htaccess is not working. Check your server configuration."
 msgstr "Funkce URL rewrite v souboru .htaccess nefunguje. Prověřte prosím Vaše nastavení serveru."
 
-#: src/Core/Install.php:358
+#: src/Core/Install.php:359
 msgid "Error message from Curl when fetching"
 msgstr "Chybová zpráva od Curl při načítání"
 
-#: src/Core/Install.php:362
+#: src/Core/Install.php:363
 msgid "Url rewrite is working"
 msgstr "Url rewrite je funkční."
 
-#: src/Core/Install.php:389
+#: src/Core/Install.php:390
 msgid "ImageMagick PHP extension is not installed"
 msgstr "PHP rozšíření ImageMagick není nainstalováno"
 
-#: src/Core/Install.php:391
+#: src/Core/Install.php:392
 msgid "ImageMagick PHP extension is installed"
 msgstr "PHP rozšíření ImageMagick je nainstalováno"
 
-#: src/Core/Install.php:393
+#: src/Core/Install.php:394
 msgid "ImageMagick supports GIF"
 msgstr "ImageMagick podporuje GIF"
 
@@ -8091,11 +8107,16 @@ msgstr "Nelze najít žádný nearchivovaný záznam kontaktu pro tuto URL adres
 msgid "The contact entries have been archived"
 msgstr "Záznamy kontaktů byly archivovány"
 
-#: src/Core/Console/PostUpdate.php:32
+#: src/Core/Console/PostUpdate.php:49
+#, php-format
+msgid "Post update version number has been set to %s."
+msgstr "Číslo verze post update bylo nastaveno na %s."
+
+#: src/Core/Console/PostUpdate.php:57
 msgid "Execute pending post updates."
 msgstr "Provést čekající aktualizace příspěvků."
 
-#: src/Core/Console/PostUpdate.php:38
+#: src/Core/Console/PostUpdate.php:63
 msgid "All pending post updates are done."
 msgstr "Všechny čekající aktualizace příspěvků jsou hotové."
 
@@ -8155,20 +8176,20 @@ msgstr "%s se nezúčastní události %s"
 msgid "%s may attend %s's event"
 msgstr "%s by se mohl/a zúčastnit události %s"
 
-#: src/Core/NotificationsManager.php:360
+#: src/Core/NotificationsManager.php:372
 #, php-format
 msgid "%s is now friends with %s"
 msgstr "%s se nyní přátelí s uživatelem %s"
 
-#: src/Core/NotificationsManager.php:626
+#: src/Core/NotificationsManager.php:638
 msgid "Friend Suggestion"
 msgstr "Návrh přátelství"
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "Friend/Connect Request"
 msgstr "Žádost o přátelství/spojení"
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "New Follower"
 msgstr "Nový sledovatel"
 
@@ -8206,7 +8227,7 @@ msgstr[3] "%d kontaktů nenaimportováno"
 msgid "Done. You can now login with your username and password"
 msgstr "Hotovo. Nyní  se můžete přihlásit se svým uživatelským jménem a heslem"
 
-#: src/Worker/Delivery.php:423
+#: src/Worker/Delivery.php:425
 msgid "(no subject)"
 msgstr "(bez předmětu)"
 
@@ -8264,7 +8285,7 @@ msgstr "přepínat hvězdu"
 
 #: src/Object/Post.php:277
 msgid "starred"
-msgstr "označeno hvězdou"
+msgstr "s hvězdou"
 
 #: src/Object/Post.php:282
 msgid "add tag"
@@ -8343,15 +8364,15 @@ msgstr "Odkaz"
 msgid "Video"
 msgstr "Video"
 
-#: src/App.php:785
+#: src/App.php:798
 msgid "Delete this item?"
 msgstr "Odstranit tuto položku?"
 
-#: src/App.php:787
+#: src/App.php:800
 msgid "show fewer"
 msgstr "zobrazit méně"
 
-#: src/App.php:1385
+#: src/App.php:1416
 msgid "No system theme config value set."
 msgstr "Není nastavena konfigurační hodnota systémového motivu."
 
@@ -8440,43 +8461,47 @@ msgstr "Přihlášený uživatel si kdykoliv může exportovat svoje data účtu
 msgid "Privacy Statement"
 msgstr "Prohlášení o soukromí"
 
-#: src/Protocol/OStatus.php:1813
+#: src/Module/Proxy.php:138
+msgid "Bad Request."
+msgstr "Špatný požadavek"
+
+#: src/Protocol/OStatus.php:1823
 #, php-format
 msgid "%s is now following %s."
 msgstr "%s nyní sleduje %s."
 
-#: src/Protocol/OStatus.php:1814
+#: src/Protocol/OStatus.php:1824
 msgid "following"
 msgstr "sleduje"
 
-#: src/Protocol/OStatus.php:1817
+#: src/Protocol/OStatus.php:1827
 #, php-format
 msgid "%s stopped following %s."
 msgstr "%s přestal/a sledovat uživatele %s."
 
-#: src/Protocol/OStatus.php:1818
+#: src/Protocol/OStatus.php:1828
 msgid "stopped following"
 msgstr "přestal/a sledovat"
 
-#: src/Protocol/DFRN.php:1525 src/Model/Contact.php:1956
+#: src/Protocol/DFRN.php:1528 src/Model/Contact.php:1974
 #, php-format
 msgid "%s's birthday"
 msgstr "%s má narozeniny"
 
-#: src/Protocol/DFRN.php:1526 src/Model/Contact.php:1957
+#: src/Protocol/DFRN.php:1529 src/Model/Contact.php:1975
 #, php-format
 msgid "Happy Birthday %s"
 msgstr "Veselé narozeniny, %s"
 
-#: src/Protocol/Diaspora.php:2417
+#: src/Protocol/Diaspora.php:2434
 msgid "Sharing notification from Diaspora network"
 msgstr "Oznámení o sdílení ze sítě Diaspora"
 
-#: src/Protocol/Diaspora.php:3514
+#: src/Protocol/Diaspora.php:3531
 msgid "Attachments:"
 msgstr "Přílohy:"
 
-#: src/Util/Temporal.php:147 src/Model/Profile.php:745
+#: src/Util/Temporal.php:147 src/Model/Profile.php:758
 msgid "Birthday:"
 msgstr "Narozeniny:"
 
@@ -8545,134 +8570,134 @@ msgstr "před %1$d %2$s"
 msgid "[no subject]"
 msgstr "[bez předmětu]"
 
-#: src/Model/Contact.php:942
+#: src/Model/Contact.php:953
 msgid "Drop Contact"
 msgstr "Odstranit kontakt"
 
-#: src/Model/Contact.php:1399
+#: src/Model/Contact.php:1408
 msgid "Organisation"
 msgstr "Organizace"
 
-#: src/Model/Contact.php:1403
+#: src/Model/Contact.php:1412
 msgid "News"
 msgstr "Zprávy"
 
-#: src/Model/Contact.php:1407
+#: src/Model/Contact.php:1416
 msgid "Forum"
 msgstr "Fórum"
 
-#: src/Model/Contact.php:1587
+#: src/Model/Contact.php:1598
 msgid "Connect URL missing."
 msgstr "Chybí URL adresa pro připojení."
 
-#: src/Model/Contact.php:1596
+#: src/Model/Contact.php:1607
 msgid ""
 "The contact could not be added. Please check the relevant network "
 "credentials in your Settings -> Social Networks page."
 msgstr "Kontakt nemohl být přidán. Prosím zkontrolujte relevantní přihlašovací údaje sítě na stránce Nastavení -> Sociální sítě."
 
-#: src/Model/Contact.php:1635
+#: src/Model/Contact.php:1646
 msgid ""
 "This site is not configured to allow communications with other networks."
 msgstr "Tento web není nakonfigurován tak, aby umožňoval komunikaci s ostatními sítěmi."
 
-#: src/Model/Contact.php:1636 src/Model/Contact.php:1650
+#: src/Model/Contact.php:1647 src/Model/Contact.php:1661
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr "Nenalezen žádný kompatibilní komunikační protokol nebo kanál."
 
-#: src/Model/Contact.php:1648
+#: src/Model/Contact.php:1659
 msgid "The profile address specified does not provide adequate information."
 msgstr "Uvedená adresa profilu neposkytuje dostatečné informace."
 
-#: src/Model/Contact.php:1653
+#: src/Model/Contact.php:1664
 msgid "An author or name was not found."
 msgstr "Autor nebo jméno nenalezeno"
 
-#: src/Model/Contact.php:1656
+#: src/Model/Contact.php:1667
 msgid "No browser URL could be matched to this address."
 msgstr "Této adrese neodpovídá žádné URL prohlížeče."
 
-#: src/Model/Contact.php:1659
+#: src/Model/Contact.php:1670
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr "Není možné namapovat adresu identity ve stylu @ s žádným možným protokolem ani emailovým kontaktem."
 
-#: src/Model/Contact.php:1660
+#: src/Model/Contact.php:1671
 msgid "Use mailto: in front of address to force email check."
 msgstr "Použite mailo: před adresou k vynucení emailové kontroly."
 
-#: src/Model/Contact.php:1666
+#: src/Model/Contact.php:1677
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr "Zadaná adresa profilu patří do sítě, která  byla na tomto serveru zakázána."
 
-#: src/Model/Contact.php:1671
+#: src/Model/Contact.php:1682
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
-msgstr "Omezený profil. Tato osoba nebude schopna od Vás pÅ\99ijímat pÅ\99ímé/osobní sdělení."
+msgstr "Omezený profil. Tato osoba nebude schopna od Vás pÅ\99ijímat pÅ\99ímá/osobní sdělení."
 
-#: src/Model/Contact.php:1722
+#: src/Model/Contact.php:1733
 msgid "Unable to retrieve contact information."
 msgstr "Nepodařilo se získat kontaktní informace."
 
-#: src/Model/Event.php:59 src/Model/Event.php:76 src/Model/Event.php:428
-#: src/Model/Event.php:897
+#: src/Model/Event.php:60 src/Model/Event.php:77 src/Model/Event.php:429
+#: src/Model/Event.php:904
 msgid "Starts:"
 msgstr "Začíná:"
 
-#: src/Model/Event.php:62 src/Model/Event.php:82 src/Model/Event.php:429
-#: src/Model/Event.php:901
+#: src/Model/Event.php:63 src/Model/Event.php:83 src/Model/Event.php:430
+#: src/Model/Event.php:908
 msgid "Finishes:"
 msgstr "Končí:"
 
-#: src/Model/Event.php:377
+#: src/Model/Event.php:378
 msgid "all-day"
 msgstr "celodenní"
 
-#: src/Model/Event.php:400
+#: src/Model/Event.php:401
 msgid "Jun"
 msgstr "čvn"
 
-#: src/Model/Event.php:403
+#: src/Model/Event.php:404
 msgid "Sept"
 msgstr "září"
 
-#: src/Model/Event.php:426
+#: src/Model/Event.php:427
 msgid "No events to display"
 msgstr "Žádné události k zobrazení"
 
-#: src/Model/Event.php:550
+#: src/Model/Event.php:551
 msgid "l, F j"
 msgstr "l, j. F"
 
-#: src/Model/Event.php:581
+#: src/Model/Event.php:582
 msgid "Edit event"
 msgstr "Upravit událost"
 
-#: src/Model/Event.php:582
+#: src/Model/Event.php:583
 msgid "Duplicate event"
 msgstr "Duplikovat událost"
 
-#: src/Model/Event.php:583
+#: src/Model/Event.php:584
 msgid "Delete event"
 msgstr "Smazat událost"
 
-#: src/Model/Event.php:830
+#: src/Model/Event.php:837
 msgid "D g:i A"
 msgstr "D g:i A"
 
-#: src/Model/Event.php:831
+#: src/Model/Event.php:838
 msgid "g:i A"
 msgstr "g:i A"
 
-#: src/Model/Event.php:916 src/Model/Event.php:918
+#: src/Model/Event.php:923 src/Model/Event.php:925
 msgid "Show map"
 msgstr "Zobrazit mapu"
 
-#: src/Model/Event.php:917
+#: src/Model/Event.php:924
 msgid "Hide map"
 msgstr "Skrýt mapu"
 
@@ -8752,7 +8777,7 @@ msgstr "Došlo k chybě při vytváření Vašeho výchozího profilu. Zkuste to
 msgid "An error occurred creating your self contact. Please try again."
 msgstr "Došlo k chybě při vytváření Vašeho kontaktu na sebe. Zkuste to prosím znovu."
 
-#: src/Model/User.php:561 src/Content/ContactSelector.php:166
+#: src/Model/User.php:561 src/Content/ContactSelector.php:171
 msgid "Friends"
 msgstr "Přátelé"
 
@@ -8821,7 +8846,7 @@ msgid ""
 "A deleted group with this name was revived. Existing item permissions "
 "<strong>may</strong> apply to this group and any future members. If this is "
 "not what you intended, please create another group with a different name."
-msgstr "Dříve smazaná skupina s tímto jménem byla obnovena. Stávající oprávnění <strong>může</strong> ovlivnit tuto skupinu a její budoucí členy. Pokud to není to, co jste chtěli, vytvořte, prosím, další skupinu s jiným názvem."
+msgstr "Dříve smazaná skupina s tímto jménem byla obnovena. Stávající oprávnění <strong>může</strong> ovlivnit tuto skupinu a její budoucí členy. Pokud to není to, co jste chtěl/a, vytvořte, prosím, další skupinu s jiným názvem."
 
 #: src/Model/Group.php:329
 msgid "Default privacy group for new contacts"
@@ -8847,129 +8872,129 @@ msgstr "Vytvořit novou skupinu"
 msgid "Edit groups"
 msgstr "Upravit skupiny"
 
-#: src/Model/Profile.php:97
+#: src/Model/Profile.php:110
 msgid "Requested account is not available."
 msgstr "Požadovaný účet není dostupný."
 
-#: src/Model/Profile.php:163 src/Model/Profile.php:399
-#: src/Model/Profile.php:846
+#: src/Model/Profile.php:176 src/Model/Profile.php:412
+#: src/Model/Profile.php:859
 msgid "Edit profile"
 msgstr "Upravit profil"
 
-#: src/Model/Profile.php:333
+#: src/Model/Profile.php:346
 msgid "Atom feed"
 msgstr "Kanál Atom"
 
-#: src/Model/Profile.php:372
+#: src/Model/Profile.php:385
 msgid "Manage/edit profiles"
 msgstr "Spravovat/upravit profily"
 
-#: src/Model/Profile.php:550 src/Model/Profile.php:639
+#: src/Model/Profile.php:563 src/Model/Profile.php:652
 msgid "g A l F d"
 msgstr "g A, l d. F"
 
-#: src/Model/Profile.php:551
+#: src/Model/Profile.php:564
 msgid "F d"
 msgstr "d. F"
 
-#: src/Model/Profile.php:604 src/Model/Profile.php:690
+#: src/Model/Profile.php:617 src/Model/Profile.php:703
 msgid "[today]"
 msgstr "[dnes]"
 
-#: src/Model/Profile.php:615
+#: src/Model/Profile.php:628
 msgid "Birthday Reminders"
 msgstr "Připomínka narozenin"
 
-#: src/Model/Profile.php:616
+#: src/Model/Profile.php:629
 msgid "Birthdays this week:"
 msgstr "Narozeniny tento týden:"
 
-#: src/Model/Profile.php:677
+#: src/Model/Profile.php:690
 msgid "[No description]"
 msgstr "[Žádný popis]"
 
-#: src/Model/Profile.php:704
+#: src/Model/Profile.php:717
 msgid "Event Reminders"
 msgstr "Připomenutí událostí"
 
-#: src/Model/Profile.php:705
+#: src/Model/Profile.php:718
 msgid "Upcoming events the next 7 days:"
 msgstr "Nadcházející události v příštích 7 dnech:"
 
-#: src/Model/Profile.php:728
+#: src/Model/Profile.php:741
 msgid "Member since:"
 msgstr "Členem od:"
 
-#: src/Model/Profile.php:736
+#: src/Model/Profile.php:749
 msgid "j F, Y"
 msgstr "j F, Y"
 
-#: src/Model/Profile.php:737
+#: src/Model/Profile.php:750
 msgid "j F"
 msgstr "j F"
 
-#: src/Model/Profile.php:752
+#: src/Model/Profile.php:765
 msgid "Age:"
 msgstr "Věk:"
 
-#: src/Model/Profile.php:765
+#: src/Model/Profile.php:778
 #, php-format
 msgid "for %1$d %2$s"
 msgstr "%1$d %2$s"
 
-#: src/Model/Profile.php:789
+#: src/Model/Profile.php:802
 msgid "Religion:"
 msgstr "Náboženství:"
 
-#: src/Model/Profile.php:797
+#: src/Model/Profile.php:810
 msgid "Hobbies/Interests:"
 msgstr "Koníčky/zájmy:"
 
-#: src/Model/Profile.php:809
+#: src/Model/Profile.php:822
 msgid "Contact information and Social Networks:"
 msgstr "Kontaktní informace a sociální sítě:"
 
-#: src/Model/Profile.php:813
+#: src/Model/Profile.php:826
 msgid "Musical interests:"
 msgstr "Hudební vkus:"
 
-#: src/Model/Profile.php:817
+#: src/Model/Profile.php:830
 msgid "Books, literature:"
 msgstr "Knihy, literatura:"
 
-#: src/Model/Profile.php:821
+#: src/Model/Profile.php:834
 msgid "Television:"
 msgstr "Televize:"
 
-#: src/Model/Profile.php:825
+#: src/Model/Profile.php:838
 msgid "Film/dance/culture/entertainment:"
 msgstr "Film/tanec/kultura/zábava:"
 
-#: src/Model/Profile.php:829
+#: src/Model/Profile.php:842
 msgid "Love/Romance:"
 msgstr "Láska/romantika"
 
-#: src/Model/Profile.php:833
+#: src/Model/Profile.php:846
 msgid "Work/employment:"
 msgstr "Práce/zaměstnání:"
 
-#: src/Model/Profile.php:837
+#: src/Model/Profile.php:850
 msgid "School/education:"
 msgstr "Škola/vzdělávání:"
 
-#: src/Model/Profile.php:842
+#: src/Model/Profile.php:855
 msgid "Forums:"
 msgstr "Fóra"
 
-#: src/Model/Profile.php:936
+#: src/Model/Profile.php:949
 msgid "Only You Can See This"
 msgstr "Toto můžete vidět jen Vy"
 
-#: src/Model/Profile.php:944 src/Model/Profile.php:947
+#: src/Model/Profile.php:957 src/Model/Profile.php:960
 msgid "Tips for New Members"
 msgstr "Tipy pro nové členy"
 
-#: src/Model/Profile.php:1106
+#: src/Model/Profile.php:1119
 #, php-format
 msgid "OpenWebAuth: %1$s welcomes %2$s"
 msgstr "OpenWebAuth: %1$s vítá %2$s"
@@ -8995,27 +9020,27 @@ msgstr[1] "%d pozvánky k dispozici"
 msgstr[2] "%d pozvánky k dispozici"
 msgstr[3] "%d pozvánek k dispozici"
 
-#: src/Content/Widget.php:157
+#: src/Content/Widget.php:154
 msgid "Networks"
 msgstr "Sítě"
 
-#: src/Content/Widget.php:160
+#: src/Content/Widget.php:157
 msgid "All Networks"
 msgstr "Všechny sítě"
 
-#: src/Content/Widget.php:198 src/Content/Feature.php:118
+#: src/Content/Widget.php:195 src/Content/Feature.php:118
 msgid "Saved Folders"
 msgstr "Uložené složky"
 
-#: src/Content/Widget.php:201 src/Content/Widget.php:241
+#: src/Content/Widget.php:198 src/Content/Widget.php:238
 msgid "Everything"
 msgstr "Všechno"
 
-#: src/Content/Widget.php:238
+#: src/Content/Widget.php:235
 msgid "Categories"
 msgstr "Kategorie"
 
-#: src/Content/Widget.php:305
+#: src/Content/Widget.php:302
 #, php-format
 msgid "%d contact in common"
 msgid_plural "%d contacts in common"
@@ -9093,230 +9118,234 @@ msgid "GNU Social Connector"
 msgstr "GNU social Connector"
 
 #: src/Content/ContactSelector.php:92
+msgid "ActivityPub"
+msgstr "ActivityPub"
+
+#: src/Content/ContactSelector.php:93
 msgid "pnut"
 msgstr "pnut"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Male"
 msgstr "Muž"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Female"
 msgstr "Žena"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Male"
 msgstr "V současnosti muž"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Female"
 msgstr "V současnosti žena"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Male"
 msgstr "Z větší části muž"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Female"
 msgstr "Z větší části žena"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transgender"
 msgstr "Transgender"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Intersex"
 msgstr "Intersexuál"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transsexual"
 msgstr "Transsexuál"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Hermaphrodite"
 msgstr "Hermafrodit"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Neuter"
 msgstr "Střední rod"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Non-specific"
 msgstr "Nespecifikováno"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Other"
 msgstr "Jiné"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Males"
 msgstr "Muži"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Females"
 msgstr "Ženy"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Gay"
 msgstr "Gay"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Lesbian"
 msgstr "Lesba"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "No Preference"
 msgstr "Bez preferencí"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Bisexual"
 msgstr "Bisexuál"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Autosexual"
 msgstr "Autosexuál"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Abstinent"
 msgstr "Abstinent"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Virgin"
 msgstr "Panic/panna"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Deviant"
 msgstr "Deviant"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Fetish"
 msgstr "Fetišista"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Oodles"
 msgstr "Hodně"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Nonsexual"
 msgstr "Nesexuální"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Single"
 msgstr "Svobodný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Lonely"
 msgstr "Osamělý/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Available"
 msgstr "Dostupný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unavailable"
 msgstr "Nedostupný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Has crush"
 msgstr "Zamilovaný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Infatuated"
 msgstr "Zabouchnutý/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Dating"
 msgstr "Chodím s někým"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unfaithful"
 msgstr "Nevěrný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Sex Addict"
 msgstr "Posedlý/á sexem"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Friends/Benefits"
 msgstr "Přátelé/výhody"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Casual"
 msgstr "Ležérní"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Engaged"
 msgstr "Zadaný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Married"
 msgstr "Ženatý/vdaná"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily married"
 msgstr "Pomyslně ženatý/vdaná"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Partners"
 msgstr "Partneři"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Cohabiting"
 msgstr "Žiji ve společné domácnosti"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Common law"
 msgstr "Zvykové právo"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Happy"
 msgstr "Šťastný/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Not looking"
 msgstr "Nehledající"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Swinger"
 msgstr "Swinger"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Betrayed"
 msgstr "Zrazen/a"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Separated"
 msgstr "Odloučený/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unstable"
 msgstr "Nestálý/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Divorced"
 msgstr "Rozvedený/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily divorced"
 msgstr "Pomyslně rozvedený/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Widowed"
 msgstr "Ovdovělý/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Uncertain"
 msgstr "Nejistý/á"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "It's complicated"
 msgstr "Je to složité"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Don't care"
 msgstr "Nezájem"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Ask me"
 msgstr "Zeptej se mě"
 
@@ -9326,11 +9355,11 @@ msgstr "Obecné vlastnosti"
 
 #: src/Content/Feature.php:81
 msgid "Multiple Profiles"
-msgstr "Vícenásobné profily"
+msgstr "Více profilů"
 
 #: src/Content/Feature.php:81
 msgid "Ability to create multiple profiles"
-msgstr "Schopnost vytvořit vícenásobné profily"
+msgstr "Schopnost vytvořit více profilů"
 
 #: src/Content/Feature.php:82
 msgid "Photo Location"
@@ -9340,7 +9369,7 @@ msgstr "Poloha fotky"
 msgid ""
 "Photo metadata is normally stripped. This extracts the location (if present)"
 " prior to stripping metadata and links it to a map."
-msgstr "Metadata fotek jsou normálně odebrána. Tato funkce před odebrání metadat extrahuje polohu (pokud je k dispozici) a propojí jej s mapou."
+msgstr "Metadata fotek jsou normálně odebrána. Tato funkce před odebrání metadat extrahuje polohu (pokud je k dispozici) a propojí ji s mapou."
 
 #: src/Content/Feature.php:83
 msgid "Export Public Calendar"
@@ -9429,7 +9458,7 @@ msgstr "Povolit záložku pro zobrazení pouze nových příspěvků (za posledn
 
 #: src/Content/Feature.php:108
 msgid "Network Shared Links Tab"
-msgstr "Záložka Síťové sdílené odkazy "
+msgstr "Síťová záložka Sdílené odkazy "
 
 #: src/Content/Feature.php:108
 msgid "Enable tab to display only Network posts with links in them"
@@ -9477,15 +9506,15 @@ msgstr "Možnost řadit příspěvky do složek"
 
 #: src/Content/Feature.php:119
 msgid "Dislike Posts"
-msgstr "Označit příspěvky jako neoblíbené"
+msgstr "Označovat příspěvky jako neoblíbené"
 
 #: src/Content/Feature.php:119
 msgid "Ability to dislike posts/comments"
-msgstr "Možnost označovat příspěvky/komentáře jako neoblíbené"
+msgstr "Možnost označovat příspěvky/komentáře jako neoblíbené (\"to se mi nelíbí\")"
 
 #: src/Content/Feature.php:120
 msgid "Star Posts"
-msgstr "Označit příspěvky hvězdou"
+msgstr "Označovat příspěvky hvězdou"
 
 #: src/Content/Feature.php:120
 msgid "Ability to mark special posts with a star indicator"
@@ -9505,7 +9534,7 @@ msgstr "Pokročilá nastavení profilu"
 
 #: src/Content/Feature.php:127
 msgid "Show visitors public community forums at the Advanced Profile Page"
-msgstr "Ukázat návštěvníkům veřejná komunitní fóra na stránce pokročilého profilu"
+msgstr "Zobrazit návštěvníkům veřejná komunitní fóra na stránce pokročilého profilu"
 
 #: src/Content/Feature.php:128
 msgid "Tag Cloud"
@@ -9663,27 +9692,27 @@ msgstr "Vkládání zakázáno"
 msgid "Embedded content"
 msgstr "Vložený obsah"
 
-#: src/Content/Text/BBCode.php:423
+#: src/Content/Text/BBCode.php:422
 msgid "view full size"
 msgstr "zobrazit v plné velikosti"
 
-#: src/Content/Text/BBCode.php:853 src/Content/Text/BBCode.php:1626
-#: src/Content/Text/BBCode.php:1627
+#: src/Content/Text/BBCode.php:854 src/Content/Text/BBCode.php:1623
+#: src/Content/Text/BBCode.php:1624
 msgid "Image/photo"
 msgstr "Obrázek/fotka"
 
-#: src/Content/Text/BBCode.php:1553 src/Content/Text/BBCode.php:1575
+#: src/Content/Text/BBCode.php:1550 src/Content/Text/BBCode.php:1572
 msgid "$1 wrote:"
 msgstr "$1 napsal/a:"
 
-#: src/Content/Text/BBCode.php:1635 src/Content/Text/BBCode.php:1636
+#: src/Content/Text/BBCode.php:1632 src/Content/Text/BBCode.php:1633
 msgid "Encrypted content"
 msgstr "Šifrovaný obsah"
 
-#: src/Content/Text/BBCode.php:1755
+#: src/Content/Text/BBCode.php:1752
 msgid "Invalid source protocol"
 msgstr "Neplatný protokol zdroje"
 
-#: src/Content/Text/BBCode.php:1766
+#: src/Content/Text/BBCode.php:1763
 msgid "Invalid link protocol"
 msgstr "Neplatný protokol odkazu"
index 753b0e51da20fddada9e9f4df3df49db314edf8e..0b9a2d6d98463f21daf862c9932ca1d93b8806b7 100644 (file)
@@ -56,7 +56,7 @@ $a->strings["Quick Start"] = "Rychlý začátek";
 $a->strings["Help"] = "Nápověda";
 $a->strings["Custom"] = "Vlastní";
 $a->strings["Note"] = "Poznámka";
-$a->strings["Check image permissions if all users are allowed to see the image"] = "Zkontrolovat povolení u obrázku, jestli všichni uživatelé mají povolení obrázek vidět";
+$a->strings["Check image permissions if all users are allowed to see the image"] = "Zkontrolujte povolení u obrázku, jestli mají všichni uživatelé povolení obrázek vidět";
 $a->strings["Select color scheme"] = "Vybrat barevné schéma";
 $a->strings["Navigation bar background color"] = "Barva pozadí navigační lišty";
 $a->strings["Navigation bar icon color "] = "Barva ikon navigační lišty";
@@ -67,7 +67,7 @@ $a->strings["Set the background image"] = "Nastavit obrázek na pozadí";
 $a->strings["Background image style"] = "Styl obrázku na pozadí";
 $a->strings["Login page background image"] = "Obrázek na pozadí přihlašovací stránky";
 $a->strings["Login page background color"] = "Barva pozadí přihlašovací stránky";
-$a->strings["Leave background image and color empty for theme defaults"] = "Nechat obrázek a barvu pozadí prázdnou pro výchozí nastavení motivů";
+$a->strings["Leave background image and color empty for theme defaults"] = "Nechejte obrázek a barvu pozadí prázdnou pro výchozí nastavení motivů";
 $a->strings["Guest"] = "Host";
 $a->strings["Visitor"] = "Návštěvník";
 $a->strings["Logout"] = "Odhlásit se";
@@ -259,7 +259,7 @@ $a->strings["[Friendica:Notify] %s tagged your post"] = "[Friendica:Oznámení]
 $a->strings["%1\$s tagged your post at %2\$s"] = "%1\$s označil/a Váš příspěvek na %2\$s";
 $a->strings["%1\$s tagged [url=%2\$s]your post[/url]"] = "%1\$s označil/a [url=%2\$s]Váš příspěvek[/url]";
 $a->strings["[Friendica:Notify] Introduction received"] = "[Friendica:Oznámení] Obdrženo představení";
-$a->strings["You've received an introduction from '%1\$s' at %2\$s"] = "Obdržel/a jste představení od uživatele \"%1\$s\" na %2\$s";
+$a->strings["You've received an introduction from '%1\$s' at %2\$s"] = "Obdržel/a jste představení od uživatele „%1\$s“ na %2\$s";
 $a->strings["You've received [url=%1\$s]an introduction[/url] from %2\$s."] = "Obdržel/a jste [url=%1\$s]představení[/url] od uživatele %2\$s.";
 $a->strings["You may visit their profile at %s"] = "Můžete navštívit jejich profil na %s";
 $a->strings["Please visit %s to approve or reject the introduction."] = "Prosím navštivte %s pro schválení či zamítnutí představení.";
@@ -268,23 +268,23 @@ $a->strings["%1\$s is sharing with you at %2\$s"] = "Uživatel %1\$s s vámi sd
 $a->strings["[Friendica:Notify] You have a new follower"] = "[Friendica:Oznámení] Máte nového sledovatele";
 $a->strings["You have a new follower at %2\$s : %1\$s"] = "Máte nového sledovatele na %2\$s : %1\$s";
 $a->strings["[Friendica:Notify] Friend suggestion received"] = "[Friendica:Oznámení] Obdržen návrh přátelství";
-$a->strings["You've received a friend suggestion from '%1\$s' at %2\$s"] = "Obdržel/a jste návrh přátelství od uživatele \"%1\$s\" na %2\$s";
+$a->strings["You've received a friend suggestion from '%1\$s' at %2\$s"] = "Obdržel/a jste návrh přátelství od uživatele „%1\$s“ na %2\$s";
 $a->strings["You've received [url=%1\$s]a friend suggestion[/url] for %2\$s from %3\$s."] = "Obdržel/a jste [url=%1\$s]návrh přátelství[/url] s uživatelem %2\$s od uživatele %3\$s.";
 $a->strings["Name:"] = "Jméno:";
 $a->strings["Photo:"] = "Fotka:";
 $a->strings["Please visit %s to approve or reject the suggestion."] = "Prosím navštivte %s pro schválení či zamítnutí návrhu.";
 $a->strings["[Friendica:Notify] Connection accepted"] = "[Friendica:Oznámení] Spojení přijato";
-$a->strings["'%1\$s' has accepted your connection request at %2\$s"] = "\"%1\$s\" přijal/a Váš požadavek na spojení na %2\$s";
+$a->strings["'%1\$s' has accepted your connection request at %2\$s"] = "„%1\$s“ přijal/a Váš požadavek o spojení na %2\$s";
 $a->strings["%2\$s has accepted your [url=%1\$s]connection request[/url]."] = "%2\$s přijal/a Váš [url=%1\$s]požadavek na spojení[/url].";
 $a->strings["You are now mutual friends and may exchange status updates, photos, and email without restriction."] = "Jste nyní vzájemní přátelé a můžete si vyměňovat stavové zprávy, fotky a e-maily bez omezení.";
 $a->strings["Please visit %s if you wish to make any changes to this relationship."] = "Pokud chcete provést změny s tímto vztahem, prosím navštivte %s.";
-$a->strings["'%1\$s' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically."] = "\"%1\$s\" se rozhodl/a Vás přijmout jako fanouška, což omezuje některé formy komunikace - například soukoromé zprávy a některé interakce s profily. Pokud je toto stránka celebrity či komunity, byla tato nastavení aplikována automaticky.";
-$a->strings["'%1\$s' may choose to extend this into a two-way or more permissive relationship in the future."] = "\"%1\$s\" se může rozhodnout tento vztah v budoucnosti rozšířit do obousměrného či jiného liberálnějšího vztahu.";
+$a->strings["'%1\$s' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically."] = "„%1\$s“ se rozhodl/a Vás přijmout jako fanouška, což omezuje některé formy komunikace - například soukoromé zprávy a některé interakce s profily. Pokud je toto stránka celebrity či komunity, byla tato nastavení aplikována automaticky.";
+$a->strings["'%1\$s' may choose to extend this into a two-way or more permissive relationship in the future."] = "„%1\$s“ se může rozhodnout tento vztah v budoucnosti rozšířit do oboustranného či jiného liberálnějšího vztahu.";
 $a->strings["Please visit %s  if you wish to make any changes to this relationship."] = "Prosím navštivte %s  pokud chcete změnit tento vztah.";
 $a->strings["[Friendica System Notify]"] = "[Systémové oznámení Friendica]";
 $a->strings["registration request"] = "žádost o registraci";
-$a->strings["You've received a registration request from '%1\$s' at %2\$s"] = "Obdržel/a jste žádost o registraci od uživatele \"%1\$s\" na %2\$s";
-$a->strings["You've received a [url=%1\$s]registration request[/url] from %2\$s."] = "Obdržel/a jste [url=%1\$s]žádost o registraci[/url] od uživatele \"%2\$s\".";
+$a->strings["You've received a registration request from '%1\$s' at %2\$s"] = "Obdržel/a jste žádost o registraci od uživatele „%1\$s“ na %2\$s";
+$a->strings["You've received a [url=%1\$s]registration request[/url] from %2\$s."] = "Obdržel/a jste [url=%1\$s]žádost o registraci[/url] od uživatele %2\$s.";
 $a->strings["Full Name:\t%s\nSite Location:\t%s\nLogin Name:\t%s (%s)"] = "Celé jméno:\t\t%s\nAdresa stránky:\t\t%s\nPřihlašovací jméno:\t%s (%s)";
 $a->strings["Please visit %s to approve or reject the request."] = "Prosím navštivte %s k odsouhlasení nebo k zamítnutí požadavku.";
 $a->strings["newer"] = "novější";
@@ -432,7 +432,7 @@ $a->strings["Please see the file \"INSTALL.txt\"."] = "Přečtěte si prosím in
 $a->strings["Database already in use."] = "Databáze se již používá.";
 $a->strings["System check"] = "Zkouška systému";
 $a->strings["Next"] = "Dále";
-$a->strings["Check again"] = "Vyskoušet znovu";
+$a->strings["Check again"] = "Vyzkoušet znovu";
 $a->strings["Database connection"] = "Databázové spojení";
 $a->strings["In order to install Friendica we need to know how to connect to your database."] = "Pro instalaci Friendica potřebujeme znát připojení k Vaší databázi.";
 $a->strings["Please contact your hosting provider or site administrator if you have questions about these settings."] = "Pokud máte otázky k následujícím nastavením, obraťte se na svého poskytovatele hostingu nebo administrátora serveru.";
@@ -526,8 +526,8 @@ $a->strings[" Name too short."] = "Jméno je příliš krátké.";
 $a->strings["Wrong Password"] = "Špatné heslo";
 $a->strings["Invalid email."] = "Neplatný e-mail.";
 $a->strings["Cannot change to that email."] = "Nelze změnit na tento e-mail.";
-$a->strings["Private forum has no privacy permissions. Using default privacy group."] = "Soukromé fórum nemá nastaveno zabezpečení. Používá se výchozí soukromá skupina.";
-$a->strings["Private forum has no privacy permissions and no default privacy group."] = "Soukromé fórum nemá nastaveno zabezpečení a ani žádnou defaultní výchozí skupinu.";
+$a->strings["Private forum has no privacy permissions. Using default privacy group."] = "Soukromé fórum nemá nastaveno zabezpečení. Používá se výchozí skupina soukromí.";
+$a->strings["Private forum has no privacy permissions and no default privacy group."] = "Soukromé fórum nemá nastaveno zabezpečení a ani žádnou výchozí skupinu soukromí.";
 $a->strings["Settings updated."] = "Nastavení aktualizováno.";
 $a->strings["Add application"] = "Přidat aplikaci";
 $a->strings["Save Settings"] = "Uložit nastavení";
@@ -620,7 +620,7 @@ $a->strings["Account for community discussions."] = "Účet pro komunitní disku
 $a->strings["Normal Account Page"] = "Normální stránka účtu";
 $a->strings["Account for a regular personal profile that requires manual approval of \"Friends\" and \"Followers\"."] = "Účet pro běžný osobní profil, který vyžaduje manuální potvrzení \"Přátel\" a \"Sledovatelů\".";
 $a->strings["Soapbox Page"] = "Propagační stránka";
-$a->strings["Account for a public profile that automatically approves contact requests as \"Followers\"."] = "Účet pro veřejný profil, který automaticky potvrzuje žádosti o přidání kontaktu jako \"Sledovatele\".";
+$a->strings["Account for a public profile that automatically approves contact requests as \"Followers\"."] = "Účet pro veřejný profil, který automaticky potvrzuje žádosti o přidání kontaktu jako „Sledovatele“.";
 $a->strings["Public Forum"] = "Veřejné fórum";
 $a->strings["Automatically approves all contact requests."] = "Automaticky potvrzuje všechny žádosti o přidání kontaktu.";
 $a->strings["Automatic Friend Page"] = "Stránka s automatickými přátely";
@@ -629,11 +629,11 @@ $a->strings["Private Forum [Experimental]"] = "Soukromé fórum [Experimentáln
 $a->strings["Requires manual approval of contact requests."] = "Vyžaduje manuální potvrzení žádostí o přidání kontaktu.";
 $a->strings["OpenID:"] = "OpenID:";
 $a->strings["(Optional) Allow this OpenID to login to this account."] = "(Volitelné) Povolit tomuto OpenID přihlášení k tomuto účtu.";
-$a->strings["Publish your default profile in your local site directory?"] = "Publikovat Váš výchozí profil v lokálním adresáři webu?";
+$a->strings["Publish your default profile in your local site directory?"] = "Publikovat Váš výchozí profil v místním adresáři webu?";
 $a->strings["Your profile will be published in this node's <a href=\"%s\">local directory</a>. Your profile details may be publicly visible depending on the system settings."] = "Váš profil bude publikován v <a href=\"%s\">místním adresáři</a> tohoto serveru. Vaše detaily o profilu mohou být veřejně viditelné v závislosti na systémových nastaveních.";
 $a->strings["No"] = "Ne";
 $a->strings["Publish your default profile in the global social directory?"] = "Publikovat Váš výchozí profil v globální sociálním adresáři?";
-$a->strings["Your profile will be published in the global friendica directories (e.g. <a href=\"%s\">%s</a>). Your profile will be visible in public."] = "Váš profil bude publikován v globálních adresářich Friendica (např. <a href=\"%s\">%s</a>). Váš profil bude veřejně viditelný.";
+$a->strings["Your profile will be published in the global friendica directories (e.g. <a href=\"%s\">%s</a>). Your profile will be visible in public."] = "Váš profil bude publikován v globálních adresářích Friendica (např. <a href=\"%s\">%s</a>). Váš profil bude veřejně viditelný.";
 $a->strings["Hide your contact/friend list from viewers of your default profile?"] = "Skrýt Váš seznam kontaktů/přátel před návštěvníky Vašeho výchozího profilu?";
 $a->strings["Your contact list won't be shown in your default profile page. You can decide to show your contact list separately for each additional profile you create"] = "Váš seznam kontaktů nebude zobrazen na Vaší výchozí profilové stránce. Můžete se rozhodnout, jestli chcete zobrazit Váš seznam kontaktů zvlášť pro každý další profil, který si vytvoříte.";
 $a->strings["Hide your profile details from anonymous viewers?"] = "Skrýt Vaše profilové detaily před anonymními návštěvníky?";
@@ -680,8 +680,8 @@ $a->strings["Default Post Permissions"] = "Výchozí oprávnění pro příspěv
 $a->strings["(click to open/close)"] = "(klikněte pro otevření/zavření)";
 $a->strings["Show to Groups"] = "Zobrazit ve Skupinách";
 $a->strings["Show to Contacts"] = "Zobrazit v Kontaktech";
-$a->strings["Default Private Post"] = "Výchozí Soukromý příspěvek";
-$a->strings["Default Public Post"] = "Výchozí Veřejný příspěvek";
+$a->strings["Default Private Post"] = "Výchozí soukromý příspěvek";
+$a->strings["Default Public Post"] = "Výchozí veřejný příspěvek";
 $a->strings["Default Permissions for New Posts"] = "Výchozí oprávnění pro nové příspěvky";
 $a->strings["Maximum private messages per day from unknown people:"] = "Maximum soukromých zpráv od neznámých lidí za den:";
 $a->strings["Notification Settings"] = "Nastavení oznámení";
@@ -696,8 +696,8 @@ $a->strings["You are tagged in a post"] = "jste označen v příspěvku";
 $a->strings["You are poked/prodded/etc. in a post"] = "jste šťouchnut(a)/dloubnut(a)/apod. v příspěvku";
 $a->strings["Activate desktop notifications"] = "Aktivovat desktopová oznámení";
 $a->strings["Show desktop popup on new notifications"] = "Zobrazit desktopové zprávy při nových oznámeních.";
-$a->strings["Text-only notification emails"] = "Pouze textové notifikační e-maily";
-$a->strings["Send text only notification emails, without the html part"] = "Posílat pouze textové notifikační e-maily, bez html části.";
+$a->strings["Text-only notification emails"] = "Pouze textové oznamovací e-maily";
+$a->strings["Send text only notification emails, without the html part"] = "Posílat pouze textové oznamovací e-maily, bez HTML části.";
 $a->strings["Show detailled notifications"] = "Zobrazit detailní oznámení";
 $a->strings["Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed."] = "Ve výchozím nastavení jsou oznámení zhuštěné na jediné oznámení pro každou položku. Pokud je toto povolené, budou zobrazována všechna oznámení.";
 $a->strings["Advanced Account/Page Type Settings"] = "Pokročilé nastavení účtu/stránky";
@@ -719,6 +719,7 @@ $a->strings["Results for: %s"] = "Výsledky pro: %s";
 $a->strings["No contacts in common."] = "Žádné společné kontakty.";
 $a->strings["Common Friends"] = "Společní přátelé";
 $a->strings["Login"] = "Přihlásit se";
+$a->strings["Bad Request"] = "Špatný požadavek";
 $a->strings["The post was created"] = "Příspěvek byl vytvořen";
 $a->strings["add"] = "přidat";
 $a->strings["Warning: This group contains %s member from a network that doesn't allow non public messages."] = [
@@ -743,7 +744,7 @@ $a->strings["New"] = "Nové";
 $a->strings["Activity Stream - by date"] = "Proud aktivit - dle data";
 $a->strings["Shared Links"] = "Sdílené odkazy";
 $a->strings["Interesting Links"] = "Zajímavé odkazy";
-$a->strings["Starred"] = "S hvězdičkou";
+$a->strings["Starred"] = "S hvězdou";
 $a->strings["Favourite Posts"] = "Oblíbené přízpěvky";
 $a->strings["Group created."] = "Skupina vytvořena.";
 $a->strings["Could not create group."] = "Nelze vytvořit skupinu.";
@@ -788,18 +789,17 @@ $a->strings["Keep this window open until done."] = "Toto okno nechte otevřené
 $a->strings["Access denied."] = "Přístup odmítnut.";
 $a->strings["No contacts."] = "Žádné kontakty.";
 $a->strings["Visit %s's profile [%s]"] = "Navštivte profil uživatele %s [%s]";
-$a->strings["Contact wasn't found or can't be unfollowed."] = "Kontakt nebyl nalezen, nebo u něj nemůže být zrušeno sledování.";
-$a->strings["Contact unfollowed"] = "Zrušeno sledování kontaktu";
-$a->strings["Submit Request"] = "Odeslat žádost";
-$a->strings["You aren't a friend of this contact."] = "nejste přítelem tohoto kontaktu";
+$a->strings["You aren't following this contact."] = "Tento kontakt nesledujete.";
 $a->strings["Unfollowing is currently not supported by your network."] = "Zrušení sledování není aktuálně na Vaši síti podporováno.";
+$a->strings["Contact unfollowed"] = "Zrušeno sledování kontaktu";
 $a->strings["Disconnect/Unfollow"] = "Odpojit se/Zrušit sledování";
 $a->strings["Your Identity Address:"] = "Vaše adresa identity:";
+$a->strings["Submit Request"] = "Odeslat žádost";
 $a->strings["Profile URL"] = "URL profilu";
 $a->strings["Status Messages and Posts"] = "Stavové zprávy a příspěvky ";
 $a->strings["[Embedded content - reload page to view]"] = "[Vložený obsah - pro zobrazení obnovte stránku]";
 $a->strings["Registration successful. Please check your email for further instructions."] = "Registrace byla úspěšná. Zkontrolujte prosím svůj e-mail pro další instrukce.";
-$a->strings["Failed to send email message. Here your accout details:<br> login: %s<br> password: %s<br><br>You can change your password after login."] = "Nepovedlo se odeslat emailovou zprávu. Zde jsou detaily Vašeho účtu:<br> přihlašovací jméno: %s<br> heslo: %s<br><br>Své heslo si můžete změnit po přihlášení.";
+$a->strings["Failed to send email message. Here your accout details:<br> login: %s<br> password: %s<br><br>You can change your password after login."] = "Nepovedlo se odeslat e-mailovou zprávu. Zde jsou detaily Vašeho účtu:<br> přihlašovací jméno: %s<br> heslo: %s<br><br>Své heslo si můžete změnit po přihlášení.";
 $a->strings["Registration successful."] = "Registrace byla úspěšná.";
 $a->strings["Your registration can not be processed."] = "Vaši registraci nelze zpracovat.";
 $a->strings["Your registration is pending approval by the site owner."] = "Vaše registrace čeká na schválení vlastníkem serveru.";
@@ -831,6 +831,8 @@ $a->strings["Network Notifications"] = "Síťová oznámení";
 $a->strings["System Notifications"] = "Systémová oznámení";
 $a->strings["Personal Notifications"] = "Osobní oznámení";
 $a->strings["Home Notifications"] = "Oznámení na domovské stránce";
+$a->strings["Show unread"] = "Zobrazit nepřečtené";
+$a->strings["Show all"] = "Zobrazit vše";
 $a->strings["Show Ignored Requests"] = "Zobrazit ignorované žádosti";
 $a->strings["Hide Ignored Requests"] = "Skrýt ignorované žádosti";
 $a->strings["Notification type:"] = "Typ oznámení:";
@@ -850,8 +852,6 @@ $a->strings["Subscriber"] = "Odběratel";
 $a->strings["Tags:"] = "Štítky:";
 $a->strings["Network:"] = "Síť:";
 $a->strings["No introductions."] = "Žádné představení.";
-$a->strings["Show unread"] = "Zobrazit nepřečtené";
-$a->strings["Show all"] = "Zobrazit vše";
 $a->strings["No more %s notifications."] = "Žádná další %s oznámení";
 $a->strings["New Message"] = "Nová zpráva";
 $a->strings["Unable to locate contact information."] = "Nepodařilo se najít kontaktní informace.";
@@ -931,7 +931,7 @@ $a->strings["Profile Keywords"] = "Profilová klíčová slova";
 $a->strings["Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships."] = "Nastavte si nějaká veřejná klíčová slova pro výchozí profil, která popisují Vaše zájmy. Můžeme Vám najít další lidi s podobnými zájmy a navrhnout přátelství.";
 $a->strings["Connecting"] = "Připojuji se";
 $a->strings["Importing Emails"] = "Importuji e-maily";
-$a->strings["Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX"] = "Pokud chcete importovat své přátele nebo mailové skupiny a komunikovat s nimi, zadejte na Vaší stránce Nastavení kontektoru své přístupové údaje do svého emailového účtu";
+$a->strings["Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX"] = "Pokud chcete importovat své přátele nebo mailové skupiny z INBOX Vašeho e-mailu a komunikovat s nimi, zadejte na Vaší stránce Nastavení kontektoru své přístupové údaje do svého e-mailového účtu";
 $a->strings["Go to Your Contacts Page"] = "Navštivte Vaši stránku s kontakty";
 $a->strings["Your Contacts page is your gateway to managing friendships and connecting with friends on other networks. Typically you enter their address or site URL in the <em>Add New Contact</em> dialog."] = "Vaše stránka Kontakty je Vaše brána k nastavování přátelství a propojení s přáteli z dalších sítí. Typicky zadáte jejich emailovou adresu nebo URL adresu jejich serveru prostřednictvím dialogu <em>Přidat nový kontakt</em>.";
 $a->strings["Go to Your Site's Directory"] = "Navštivte adresář Vaší stránky";
@@ -948,7 +948,7 @@ $a->strings["Go to the Help Section"] = "Navštivte sekci nápovědy";
 $a->strings["Our <strong>help</strong> pages may be consulted for detail on other program features and resources."] = "Na stránkách <strong>Nápověda</strong> naleznete nejen další podrobnosti o všech funkcích Friendika ale také další zdroje informací.";
 $a->strings["No valid account found."] = "Nenalezen žádný platný účet.";
 $a->strings["Password reset request issued. Check your email."] = "Žádost o obnovení hesla vyřízena. Zkontrolujte Vaši e-mailovou schránku.";
-$a->strings["\n\t\tDear %1\$s,\n\t\t\tA request was recently received at \"%2\$s\" to reset your account\n\t\tpassword. In order to confirm this request, please select the verification link\n\t\tbelow or paste it into your web browser address bar.\n\n\t\tIf you did NOT request this change, please DO NOT follow the link\n\t\tprovided and ignore and/or delete this email, the request will expire shortly.\n\n\t\tYour password will not be changed unless we can verify that you\n\t\tissued this request."] = "\n\t\tVážený/á %1\$s,\n\t\t\tPřed nedávnem jsme obdrželi na \"%2\$s\" požadavek o obnovení\n\t\thesla k Vašemu účtu. Pro potvrzení tohoto požadavku, prosím klikněte na odkaz\n\t\tpro ověření dole, nebo ho zkopírujte do adresního řádku Vašeho prohlížeče.\n\n\t\tPokud jste o tuto změnu NEPOŽÁDAL/A, prosím NEKLIKEJTE na tento odkaz\n\t\ta ignorujte a/nebo smažte tento e-mail. Platnost požadavku brzy vyprší.\n\n\t\tVaše heslo nebude změněno, dokud nedokážeme ověřit, že jste tento\n\t\tpožadavek nevydal/a Vy.";
+$a->strings["\n\t\tDear %1\$s,\n\t\t\tA request was recently received at \"%2\$s\" to reset your account\n\t\tpassword. In order to confirm this request, please select the verification link\n\t\tbelow or paste it into your web browser address bar.\n\n\t\tIf you did NOT request this change, please DO NOT follow the link\n\t\tprovided and ignore and/or delete this email, the request will expire shortly.\n\n\t\tYour password will not be changed unless we can verify that you\n\t\tissued this request."] = "\n\t\tVážený/á %1\$s,\n\t\t\tPřed nedávnem jsme obdrželi na „%2\$s“ požadavek o obnovení\n\t\thesla k Vašemu účtu. Pro potvrzení tohoto požadavku, prosím klikněte na odkaz\n\t\tpro ověření dole, nebo ho zkopírujte do adresního řádku Vašeho prohlížeče.\n\n\t\tPokud jste o tuto změnu NEPOŽÁDAL/A, prosím NEKLIKEJTE na tento odkaz\n\t\ta ignorujte a/nebo smažte tento e-mail. Platnost požadavku brzy vyprší.\n\n\t\tVaše heslo nebude změněno, dokud nedokážeme ověřit, že jste tento\n\t\tpožadavek nevydal/a Vy.";
 $a->strings["\n\t\tFollow this link soon to verify your identity:\n\n\t\t%1\$s\n\n\t\tYou will then receive a follow-up message containing the new password.\n\t\tYou may change that password from your account settings page after logging in.\n\n\t\tThe login details are as follows:\n\n\t\tSite Location:\t%2\$s\n\t\tLogin Name:\t%3\$s"] = "\n\t\tKlikněte na tento odkaz brzy pro ověření vaší identity:\n\n\t\t%1\$s\n\n\t\tObdržíte poté následnou zprávu obsahující nové heslo.\n\t\tPo přihlášení můžete toto heslo změnit na stránce nastavení Vašeho účtu.\n\n\t\tZde jsou vaše přihlašovací detaily:\n\n\t\tAdresa stránky:\t\t%2\$s\n\t\tPřihlašovací jméno:\t%3\$s";
 $a->strings["Password reset requested at %s"] = "Na %s bylo zažádáno o obnovení hesla";
 $a->strings["Request could not be verified. (You may have previously submitted it.) Password reset failed."] = "Žádost nemohla být ověřena. (Možná jste ji odeslal/a již dříve.) Obnovení hesla se nezdařilo.";
@@ -968,18 +968,21 @@ $a->strings["\n\t\t\tYour login details are as follows:\n\n\t\t\tSite Location:\
 $a->strings["Your password has been changed at %s"] = "Vaše heslo bylo změněno na %s";
 $a->strings["Source input"] = "Zdrojový vstup";
 $a->strings["BBCode::toPlaintext"] = "BBCode::toPlaintext";
-$a->strings["BBCode::convert (raw HTML)"] = "BBCode::convert (raw HTML)";
+$a->strings["BBCode::convert (raw HTML)"] = "BBCode::convert (hrubé HTML)";
 $a->strings["BBCode::convert"] = "BBCode::convert";
 $a->strings["BBCode::convert => HTML::toBBCode"] = "BBCode::convert => HTML::toBBCode";
 $a->strings["BBCode::toMarkdown"] = "BBCode::toMarkdown";
 $a->strings["BBCode::toMarkdown => Markdown::convert"] = "BBCode::toMarkdown => Markdown::convert";
 $a->strings["BBCode::toMarkdown => Markdown::toBBCode"] = "BBCode::toMarkdown => Markdown::toBBCode";
 $a->strings["BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"] = "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode";
-$a->strings["Source input \\x28Diaspora format\\x29"] = "Zdrojový vstup \\x28Formát Diaspora\\x29";
+$a->strings["Source input (Diaspora format)"] = "Zdrojový vstup (formát Diaspora)";
+$a->strings["Markdown::convert (raw HTML)"] = "Markdown::convert (hrubé HTML)";
+$a->strings["Markdown::convert"] = "Markdown::convert";
 $a->strings["Markdown::toBBCode"] = "Markdown::toBBCode";
 $a->strings["Raw HTML input"] = "Hrubý HTML vstup";
 $a->strings["HTML Input"] = "HTML vstup";
 $a->strings["HTML::toBBCode"] = "HTML::toBBCode";
+$a->strings["HTML::toMarkdown"] = "HTML::toMarkdown";
 $a->strings["HTML::toPlaintext"] = "HTML::toPlaintext";
 $a->strings["Source text"] = "Zdrojový text";
 $a->strings["BBCode"] = "BBCode";
@@ -1011,8 +1014,8 @@ $a->strings["Admin"] = "Administrátor";
 $a->strings["Addon Features"] = "Vlastnosti doplňků";
 $a->strings["User registrations waiting for confirmation"] = "Registrace uživatelů čekající na potvrzení";
 $a->strings["Administration"] = "Administrace";
-$a->strings["Display Terms of Service"] = "Ukázat Podmínky používání";
-$a->strings["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."] = "Povolte stránku Podmínky používání. Pokud je toto povoleno, bude na formulář pro registrací a stránku s obecnými informacemi přidán odkaz k podmínkám.";
+$a->strings["Display Terms of Service"] = "Zobrazit Podmínky používání";
+$a->strings["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."] = "Povolí stránku Podmínky používání. Pokud je toto povoleno, bude na formulář pro registrací a stránku s obecnými informacemi přidán odkaz k podmínkám.";
 $a->strings["Display Privacy Statement"] = "Zobrazit Prohlášení o soukromí";
 $a->strings["Show some informations regarding the needed information to operate the node according e.g. to <a href=\"%s\" target=\"_blank\">EU-GDPR</a>."] = "Ukázat některé informace ohledně potřebných informací k provozování serveru podle například <a href=\"%s\" target=\"_blank\">Obecného nařízení o ochraně osobních údajů EU (GDPR)</a>";
 $a->strings["Privacy Statement Preview"] = "Náhled Prohlášení o soukromí";
@@ -1023,10 +1026,10 @@ $a->strings["The reason why you blocked this domain."] = "Důvod, proč jste dom
 $a->strings["Delete domain"] = "Smazat doménu";
 $a->strings["Check to delete this entry from the blocklist"] = "Zaškrtnutím odstraníte tuto položku z blokovacího seznamu";
 $a->strings["This page can be used to define a black list of servers from the federated network that are not allowed to interact with your node. For all entered domains you should also give a reason why you have blocked the remote server."] = "Tato stránka může být použita k definici \"černé listiny\" serverů z federované sítě, kterým není dovoleno interagovat s vaším serverem. Měl/a byste také pro všechny zadané domény uvést důvod, proč jste vzdálený server zablokoval/a.";
-$a->strings["The list of blocked servers will be made publically available on the /friendica page so that your users and people investigating communication problems can find the reason easily."] = "Seznam zablokovaných server bude zveřejněn na stránce /friendica, takže vaši uživatelé a lidé vyšetřující probém s komunikací mohou důvod najít snadno.";
+$a->strings["The list of blocked servers will be made publically available on the /friendica page so that your users and people investigating communication problems can find the reason easily."] = "Seznam zablokovaných serverů bude zveřejněn na stránce /friendica, takže vaši uživatelé a lidé vyšetřující probém s komunikací mohou důvod najít snadno.";
 $a->strings["Add new entry to block list"] = "Přidat na blokovací seznam novou položku";
 $a->strings["Server Domain"] = "Serverová doména";
-$a->strings["The domain of the new server to add to the block list. Do not include the protocol."] = "Doména serveru, který má být přidán na blokovací seznam. Vynechejte protokol (\"http://\").";
+$a->strings["The domain of the new server to add to the block list. Do not include the protocol."] = "Doména serveru, který má být přidán na blokovací seznam. Vynechejte protokol („http://“).";
 $a->strings["Block reason"] = "Důvod zablokování";
 $a->strings["Add Entry"] = "Přidat položku";
 $a->strings["Save changes to the blocklist"] = "Uložit změny do blokovacího seznamu";
@@ -1051,7 +1054,7 @@ $a->strings["select none"] = "nevybrat žádný";
 $a->strings["Block"] = "Blokovat";
 $a->strings["Unblock"] = "Odblokovat";
 $a->strings["No remote contact is blocked from this node."] = "Žádný vzdálený kontakt není na tomto serveru zablokován.";
-$a->strings["Blocked Remote Contacts"] = "Zablokovat vzdálené kontakty";
+$a->strings["Blocked Remote Contacts"] = "Zablokova vzdálené kontakty";
 $a->strings["Block New Remote Contact"] = "Zablokovat nový vzdálený kontakt";
 $a->strings["Photo"] = "Fotka";
 $a->strings["Address"] = "Adresa";
@@ -1074,7 +1077,7 @@ $a->strings["The <em>Auto Discovered Contact Directory</em> feature is not enabl
 $a->strings["Currently this node is aware of %d nodes with %d registered users from the following platforms:"] = "Aktuálně si je tento server vědom %d serverů s %d registrovanými uživateli z těchto platforem:";
 $a->strings["ID"] = "Identifikátor";
 $a->strings["Recipient Name"] = "Jméno příjemce";
-$a->strings["Recipient Profile"] = "Profil píjemce";
+$a->strings["Recipient Profile"] = "Profil příjemce";
 $a->strings["Created"] = "Vytvořeno";
 $a->strings["Last Tried"] = "Naposled vyzkoušeno";
 $a->strings["This page lists the content of the queue for outgoing postings. These are postings the initial delivery failed for. They will be resend later and eventually deleted if the delivery fails permanently."] = "Na této stránce najdete obsah fronty odchozích příspěvků. Toto jsou příspěvky, u kterých počáteční doručení selhalo. Budou znovu poslány později, a pokud doručení selže trvale, budou nakonec smazány.";
@@ -1088,7 +1091,7 @@ $a->strings["The database update failed. Please run \"php bin/console.php dbstru
 $a->strings["The worker was never executed. Please check your database structure!"] = "Pracovník nebyl nikdy spuštěn. Prosím zkontrolujte strukturu Vaší databáze!";
 $a->strings["The last worker execution was on %s UTC. This is older than one hour. Please check your crontab settings."] = "Pracovník byl naposledy spuštěn v %s UTC. Toto je více než jedna hodina. Prosím zkontrolujte si nastavení crontab.";
 $a->strings["Friendica's configuration now is stored in config/local.ini.php, please copy config/local-sample.ini.php and move your config from <code>.htconfig.php</code>. See <a href=\"%s\">the Config help page</a> for help with the transition."] = "Konfigurace Friendica je nyní uložena v souboru config/local.ini.php, prosím zkopírujte soubor config/local-sample.ini.php a přesuňte svou konfiguraci ze souboru <code>.htconfig.php</code>. Pro pomoc při přechodu navštivte <a href=\"%s\">stránku Config v sekci nápovědy</a>.";
-$a->strings["<a href=\"%s\">%s</a> is not reachable on your system. This is a servere configuration issue that prevents the communication.. See <a href=\"%s\">the installation page</a> for help."] = "<a href=\"%s\">%s</a> není na Vašem systému dosažitelné. Tohle je závažná chyba konfigurace, která brání komunikaci. Pro pomoc navštivte <a href=\"%s\">stránku instalace</a>.";
+$a->strings["<a href=\"%s\">%s</a> is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See <a href=\"%s\">the installation page</a> for help."] = "<a href=\"%s\">%s</a> není na Vašem systému dosažitelné. Tohle je závažná chyba konfigurace, která brání komunikaci mezi servery. Pro pomoc navštivte <a href=\"%s\">stránku instalace</a>.";
 $a->strings["Normal Account"] = "Normální účet";
 $a->strings["Automatic Follower Account"] = "Účet s automatickými sledovateli";
 $a->strings["Public Forum Account"] = "Účet veřejného fóra";
@@ -1103,11 +1106,11 @@ $a->strings["Version"] = "Verze";
 $a->strings["Active addons"] = "Aktivní doplňky";
 $a->strings["Can not parse base url. Must have at least <scheme>://<domain>"] = "Nelze zpracovat výchozí url adresu. Musí obsahovat alespoň <scheme>://<domain>";
 $a->strings["Site settings updated."] = "Nastavení webu aktualizováno.";
-$a->strings["No community page for local users"] = "Žádná komunitní stránka pro lokální uživatele";
-$a->strings["No community page"] = "Komunitní stránka neexistuje";
-$a->strings["Public postings from users of this site"] = "Počet veřejných příspěvků od uživatele na této stránce";
+$a->strings["No community page for local users"] = "Žádná komunitní stránka pro místní uživatele";
+$a->strings["No community page"] = "Žádná komunitní stránka";
+$a->strings["Public postings from users of this site"] = "Veřejné příspěvky od místních uživatelů";
 $a->strings["Public postings from the federated network"] = "Veřejné příspěvky z federované sítě";
-$a->strings["Public postings from local users and the federated network"] = "Veřejné příspěvky od lokálních uživatelů a z federované sítě";
+$a->strings["Public postings from local users and the federated network"] = "Veřejné příspěvky od místních uživatelů a z federované sítě";
 $a->strings["Disabled"] = "Zakázáno";
 $a->strings["Users, Global Contacts"] = "Uživatelé, globální kontakty";
 $a->strings["Users, Global Contacts/fallback"] = "Uživatelé, globální kontakty/fallback";
@@ -1121,13 +1124,13 @@ $a->strings["Requires approval"] = "Vyžaduje schválení";
 $a->strings["Open"] = "Otevřeno";
 $a->strings["No SSL policy, links will track page SSL state"] = "Žádná SSL politika, odkazy budou následovat SSL stav stránky";
 $a->strings["Force all links to use SSL"] = "Vyžadovat u všech odkazů použití SSL";
-$a->strings["Self-signed certificate, use SSL for local links only (discouraged)"] = "Certifikát podepsaný sám sebou, použít SSL pouze pro lokální odkazy (nedoporučeno)";
+$a->strings["Self-signed certificate, use SSL for local links only (discouraged)"] = "Certifikát podepsaný sám sebou, použít SSL pouze pro místní odkazy (nedoporučeno)";
 $a->strings["Don't check"] = "Nekontrolovat";
 $a->strings["check the stable version"] = "kontrolovat stabilní verzi";
 $a->strings["check the development version"] = "kontrolovat vývojovou verzi";
 $a->strings["Republish users to directory"] = "Znovu publikovat uživatele do adresáře";
 $a->strings["File upload"] = "Nahrání souborů";
-$a->strings["Policies"] = "Politiky";
+$a->strings["Policies"] = "Politika";
 $a->strings["Advanced"] = "Pokročilé";
 $a->strings["Auto Discovered Contact Directory"] = "Adresář automaticky objevených kontaktů";
 $a->strings["Performance"] = "Výkon";
@@ -1189,42 +1192,42 @@ $a->strings["Enabling this may violate privacy laws like the GDPR"] = "Povolení
 $a->strings["Global directory URL"] = "Adresa URL globálního adresáře";
 $a->strings["URL to the global directory. If this is not set, the global directory is completely unavailable to the application."] = "Adresa URL globálního adresáře. Pokud toto není nastaveno, globální adresář bude aplikaci naprosto nedostupný.";
 $a->strings["Private posts by default for new users"] = "Nastavit pro nové uživatele příspěvky jako soukromé";
-$a->strings["Set default post permissions for all new members to the default privacy group rather than public."] = "Nastavit defaultní práva pro příspěvky od všech nových členů na výchozí soukromou skupinu raději než jako veřejné.";
-$a->strings["Don't include post content in email notifications"] = "Nezahrnovat obsah příspěvků v emailových upozorněních";
-$a->strings["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."] = " V mailových upozorněních, které jsou odesílány z tohoto webu jako soukromé zprávy, nejsou z důvodů bezpečnosti obsaženy příspěvky/komentáře/soukromé zprávy apod. ";
+$a->strings["Set default post permissions for all new members to the default privacy group rather than public."] = "Nastavit výchozí práva pro příspěvky od všech nových členů na výchozí soukromou skupinu místo veřejné.";
+$a->strings["Don't include post content in email notifications"] = "Nezahrnovat v e-mailových upozorněních obsah příspěvků";
+$a->strings["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."] = " V e-mailových oznámeních, které jsou odesílány z tohoto webu, nebudou z důvodů bezpečnosti obsaženy příspěvky/komentáře/soukromé zprávy apod. ";
 $a->strings["Disallow public access to addons listed in the apps menu."] = "Zakázat veřejný přístup k rozšířením uvedeným v menu aplikace.";
 $a->strings["Checking this box will restrict addons listed in the apps menu to members only."] = "Označení této volby omezí rozšíření uvedená v menu aplikace pouze pro členy.";
-$a->strings["Don't embed private images in posts"] = "Nepovolit přidávání soukromých správ v příspěvcích";
+$a->strings["Don't embed private images in posts"] = "Nepovolit přidávání soukromých obrázků do příspěvků";
 $a->strings["Don't replace locally-hosted private photos in posts with an embedded copy of the image. This means that contacts who receive posts containing private photos will have to authenticate and load each image, which may take a while."] = "Nenahrazovat místní soukromé fotky v příspěvcích vloženou kopií obrázku. To znamená, že kontakty, které obdrží příspěvek obsahující soukromé fotky, budou muset autentikovat a načíst každý obrázek, což může zabrat nějaký čas.";
 $a->strings["Explicit Content"] = "Explicitní obsah";
 $a->strings["Set this to announce that your node is used mostly for explicit content that might not be suited for minors. This information will be published in the node information and might be used, e.g. by the global directory, to filter your node from listings of nodes to join. Additionally a note about this will be shown at the user registration page."] = "Touto funkcí oznámíte, že je Váš server používán hlavně pro explicitní obsah, který nemusí být vhodný pro mladistvé. Tato informace bude publikována na stránce informací o serveru a může být využita např. globálním adresářem pro odfiltrování Vašeho serveru ze seznamu serverů pro spojení. Poznámka o tom bude navíc zobrazena na stránce registrace.";
-$a->strings["Allow Users to set remote_self"] = "Umožnit uživatelům nastavit ";
+$a->strings["Allow Users to set remote_self"] = "Umožnit uživatelům nastavit remote_self";
 $a->strings["With checking this, every user is allowed to mark every contact as a remote_self in the repair contact dialog. Setting this flag on a contact causes mirroring every posting of that contact in the users stream."] = "S tímto označením má každý uživatel možnost označit jakékoliv ze svých kontakt jako \"remote_self\" v nastavení v dialogu opravit kontakt. Tímto označením se budou zrcadlit všechny správy tohoto kontaktu v uživatelově proudu.";
 $a->strings["Block multiple registrations"] = "Blokovat více registrací";
 $a->strings["Disallow users to register additional accounts for use as pages."] = "Znemožnit uživatelům registraci dodatečných účtů k použití jako stránky.";
 $a->strings["OpenID support"] = "Podpora OpenID";
 $a->strings["OpenID support for registration and logins."] = "Podpora OpenID pro registraci a přihlašování.";
 $a->strings["Fullname check"] = "Kontrola úplného jména";
-$a->strings["Force users to register with a space between firstname and lastname in Full name, as an antispam measure"] = "Přimět uživatele k registraci s mezerou mezi jménu a příjmením v poli Celé jméno, jako antispamové opatření.";
+$a->strings["Force users to register with a space between firstname and lastname in Full name, as an antispam measure"] = "Přimět uživatele k registraci s mezerou mezi jménu a příjmením v poli Celé jméno, jako protispamové opatření.";
 $a->strings["Community pages for visitors"] = "Komunitní stránky pro návštěvníky";
-$a->strings["Which community pages should be available for visitors. Local users always see both pages."] = "Které komunitní stránky by měly být viditelné pro návštěvníky. Lokální uživatelé vždy vidí obě stránky.";
+$a->strings["Which community pages should be available for visitors. Local users always see both pages."] = "Které komunitní stránky by měly být viditelné pro návštěvníky. Místní uživatelé vždy vidí obě stránky.";
 $a->strings["Posts per user on community page"] = "Počet příspěvků na komunitní stránce";
-$a->strings["The maximum number of posts per user on the community page. (Not valid for 'Global Community')"] = "Maximální počet příspěvků na uživatele na komunitní sptránce. (neplatí pro 'Globální komunitu')";
+$a->strings["The maximum number of posts per user on the community page. (Not valid for 'Global Community')"] = "Maximální počet příspěvků na uživatele na komunitní stránce. (neplatí pro „Globální komunitu“)";
 $a->strings["Enable OStatus support"] = "Zapnout podporu pro OStatus";
 $a->strings["Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed."] = "Poskytnout zabudouvanou kompatibilitu s OStatus (StatusNet, GNU Social apod.). Veškerá komunikace s OStatus je veřejná, proto bude občas zobrazeno upozornění.";
-$a->strings["Only import OStatus threads from our contacts"] = "Pouze importovat vlákna z OStatus z našich kontaktů";
-$a->strings["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."] = "Běžně importujeme všechen obsah z našich kontaktů na OStatus. S touto volbou uchováváme vlákna počatá kontaktem, který je na našem systému známý.";
+$a->strings["Only import OStatus/ActivityPub threads from our contacts"] = "Pouze importovat vlákna z OStatus/ActivityPub z našich kontaktů";
+$a->strings["Normally we import every content from our OStatus and ActivityPub contacts. With this option we only store threads that are started by a contact that is known on our system."] = "Běžně importujeme všechen obsah z našich kontaktů na OStatus a ActivityPub. S touto volbou uchováváme vlákna počatá kontaktem, který je na našem systému známý.";
 $a->strings["OStatus support can only be enabled if threading is enabled."] = "Podpora pro OStatus může být zapnuta pouze, je-li povolen threading.";
 $a->strings["Diaspora support can't be enabled because Friendica was installed into a sub directory."] = "Podpora pro Diasporu nemůže být zapnuta, protože Friendica byla nainstalována do podadresáře.";
 $a->strings["Enable Diaspora support"] = "Zapnout podporu pro Diaspora";
 $a->strings["Provide built-in Diaspora network compatibility."] = "Poskytnout zabudovanou kompatibilitu sitě Diaspora.";
 $a->strings["Only allow Friendica contacts"] = "Povolit pouze kontakty z Friendica";
-$a->strings["All contacts must use Friendica protocols. All other built-in communication protocols disabled."] = "Všechny kontakty musí používat Friendica protokol. Všchny jiné zabudované komunikační protokoly budou zablokované.";
+$a->strings["All contacts must use Friendica protocols. All other built-in communication protocols disabled."] = "Všechny kontakty musí používat protokol Friendica. Všchny ostatní zabudované komunikační protokoly budou zablokované.";
 $a->strings["Verify SSL"] = "Ověřit SSL";
 $a->strings["If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites."] = "Pokud si přejete, můžete vynutit striktní ověřování certifikátů. To znamená že se nebudete moci připojit k žádnému serveru s vlastním SSL certifikátem.";
 $a->strings["Proxy user"] = "Proxy uživatel";
 $a->strings["Proxy URL"] = "Proxy URL adresa";
-$a->strings["Network timeout"] = "Čas síťového spojení vypršel (timeout)";
+$a->strings["Network timeout"] = "Čas vypršení síťového spojení (timeout)";
 $a->strings["Value is in seconds. Set to 0 for unlimited (not recommended)."] = "Hodnota ve vteřinách. Nastavte 0 pro neomezeno (není doporučeno).";
 $a->strings["Maximum Load Average"] = "Maximální průměrné zatížení";
 $a->strings["Maximum system load before delivery and poll processes are deferred - default 50."] = "Maximální zatížení systému před pozastavením procesů zajišťujících doručování aktualizací - výchozí hodnota 50";
@@ -1244,8 +1247,8 @@ $a->strings["Discover contacts from other servers"] = "Objevit kontakty z ostatn
 $a->strings["Periodically query other servers for contacts. You can choose between 'users': the users on the remote system, 'Global Contacts': active contacts that are known on the system. The fallback is meant for Redmatrix servers and older friendica servers, where global contacts weren't available. The fallback increases the server load, so the recommened setting is 'Users, Global Contacts'."] = "Periodicky dotazovat ostatní servery pro kontakty. Můžete si vybrat mezi možnostmi: \"uživatelé\" - uživatelé na vzdáleném systému, a \"globální kontakty\" - aktivní kontakty, které jsou známy na systému. Funkce fallback je určena pro servery Redmatrix a starší servery Friendica, kde globální kontakty nejsou dostupné. Fallback zvyšuje serverovou zátěž, doporučené nastavení je proto \"Uživatelé, globální kontakty\".";
 $a->strings["Timeframe for fetching global contacts"] = "Časový rámec pro načítání globálních kontaktů";
 $a->strings["When the discovery is activated, this value defines the timeframe for the activity of the global contacts that are fetched from other servers."] = "Pokud je aktivováno objevování, tato hodnota definuje časový rámec pro aktivitu globálních kontaktů, které jsou načteny z jiných serverů.";
-$a->strings["Search the local directory"] = "Hledat  v lokálním adresáři";
-$a->strings["Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated."] = "Prohledat lokální adresář místo globálního adresáře. Při lokálním prohledávání bude každé hledání provedeno v globálním adresáři na pozadí. To vylepšuje výsledky při zopakování hledání.";
+$a->strings["Search the local directory"] = "Hledat  v místním adresáři";
+$a->strings["Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated."] = "Prohledat místní adresář místo globálního adresáře. Při místním prohledávání bude každé hledání provedeno v globálním adresáři na pozadí. To vylepšuje výsledky při zopakování hledání.";
 $a->strings["Publish server information"] = "Zveřejnit informace o serveru";
 $a->strings["If enabled, general server and usage data will be published. The data contains the name and version of the server, number of users with public profiles, number of posts and the activated protocols and connectors. See <a href='http://the-federation.info/'>the-federation.info</a> for details."] = "Pokud je toto povoleno, budou zveřejněna obecná data o serveru a jeho používání. Data obsahují jméno a verzi serveru, počet uživatelů s veřejnými profily, počet příspěvků a aktivované protokoly a konektory. Pro více informací navštivte <a href='http://the-federation.info/'>the-federation.info</a>.";
 $a->strings["Check upstream version"] = "Zkontrolovat upstreamovou verzi";
@@ -1292,13 +1295,13 @@ $a->strings["Address of the relay server where public posts should be send to. F
 $a->strings["Direct relay transfer"] = "Přímý přenos na server pro přeposílání";
 $a->strings["Enables the direct transfer to other servers without using the relay servers"] = "Umožňuje přímý přenos na ostatní servery bez použití přeposílacích serverů";
 $a->strings["Relay scope"] = "Rozsah příspěvků z přeposílacího serveru";
-$a->strings["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."] = "Může být buď \"vše\" nebo \"štítky\". \"vše\" znamená, že budou přijaty všechny veřejné příspěvky. \"štítky\" znamená, že budou přijaty pouze příspěvky s vybranými štítky.";
+$a->strings["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."] = "Může být buď „vše“ nebo „štítky“. „vše“ znamená, že budou přijaty všechny veřejné příspěvky. „štítky“ znamená, že budou přijaty pouze příspěvky s vybranými štítky.";
 $a->strings["all"] = "vše";
 $a->strings["tags"] = "štítky";
 $a->strings["Server tags"] = "Serverové štítky";
-$a->strings["Comma separated list of tags for the 'tags' subscription."] = "Seznam štítků pro odběr \"tags\", oddělených čárkami.";
+$a->strings["Comma separated list of tags for the 'tags' subscription."] = "Seznam štítků pro odběr „tags“, oddělených čárkami.";
 $a->strings["Allow user tags"] = "Povolit uživatelské štítky";
-$a->strings["If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'."] = "Pokud je toto povoleno, budou štítky z uložených hledání vedle odběru \"relay_server_tags\" použity i pro odběr \"tags\".";
+$a->strings["If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'."] = "Pokud je toto povoleno, budou štítky z uložených hledání vedle odběru „relay_server_tags“ použity i pro odběr „tags“.";
 $a->strings["Start Relocation"] = "Začít přemístění";
 $a->strings["Update has been marked successful"] = "Aktualizace byla označena jako úspěšná.";
 $a->strings["Database structure update %s was successfully applied."] = "Aktualizace struktury databáze %s byla úspěšně aplikována.";
@@ -1308,7 +1311,7 @@ $a->strings["Update %s was successfully applied."] = "Aktualizace %s byla úspě
 $a->strings["Update %s did not return a status. Unknown if it succeeded."] = "Aktualizace %s nevrátila žádný stav. Není zřejmé, jestli byla úspěšná.";
 $a->strings["There was no additional update function %s that needed to be called."] = "Nebyla nalezena žádná další aktualizační funkce %s která by měla být volána.";
 $a->strings["No failed updates."] = "Žádné neúspěšné aktualizace.";
-$a->strings["Check database structure"] = "Ověření struktury databáze";
+$a->strings["Check database structure"] = "Ověřit strukturu databáze";
 $a->strings["Failed Updates"] = "Neúspěšné aktualizace";
 $a->strings["This does not include updates prior to 1139, which did not return a status."] = "To nezahrnuje aktualizace do verze 1139, které nevracejí žádný status.";
 $a->strings["Mark success (if update was manually applied)"] = "Označit za úspěšné (pokud byla aktualizace aplikována manuálně)";
@@ -1382,7 +1385,7 @@ $a->strings["PHP logging"] = "Záznamování PHP";
 $a->strings["To temporarily enable logging of PHP errors and warnings you can prepend the following to the index.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."] = "Pro dočasné umožnění zaznamenávání PHP chyb a varování, můžete přidat do souboru index.php na vaší instalaci následující: Název souboru nastavený v řádku \"error_log\" je relativní ke kořenovému adresáři Friendica a webový server musí mít povolení na něj zapisovat. Možnost \"1\" pro \"log_errors\" a \"display_errors\" tyto funkce povoluje, nastavením hodnoty na \"0\" je zakážete. ";
 $a->strings["Error trying to open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s exist and is readable."] = "Chyba při otevírání záznamu <strong>%1\$s</strong>.\\r\\n<br/>Zkontrolujte, jestli soubor %1\$s existuje a může se číst.";
 $a->strings["Couldn't open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s is readable."] = "Nelze otevřít záznam <strong>%1\$s</strong>.\\r\\n<br/>Zkontrolujte, jestli se soubor %1\$s může číst.";
-$a->strings["Lock feature %s"] = "Funkce zámku %s";
+$a->strings["Lock feature %s"] = "Uzamknout vlastnost %s";
 $a->strings["Manage Additional Features"] = "Spravovat další funkce";
 $a->strings["OpenID protocol error. No ID returned."] = "Chyba OpenID protokolu. Nebylo navráceno žádné ID.";
 $a->strings["Account not found and OpenID registration is not permitted on this site."] = "Nenalezen účet a OpenID registrace na tomto serveru není dovolena.";
@@ -1409,7 +1412,7 @@ $a->strings["Apparently you are already friends with %s."] = "Zřejmě jste s %s
 $a->strings["Invalid profile URL."] = "Neplatné URL profilu.";
 $a->strings["Disallowed profile URL."] = "Nepovolené URL profilu.";
 $a->strings["Failed to update contact record."] = "Nepodařilo se aktualizovat kontakt.";
-$a->strings["Your introduction has been sent."] = "Vaše žádost o propojení byla odeslána.";
+$a->strings["Your introduction has been sent."] = "Vaše představení bylo odesláno.";
 $a->strings["Remote subscription can't be done for your network. Please subscribe directly on your system."] = "Vzdálený odběr nemůže být na Vaší síti proveden. Prosím, přihlaste se k odběru přímo na Vašem systému.";
 $a->strings["Please login to confirm introduction."] = "Pro potvrzení představení se prosím přihlaste.";
 $a->strings["Incorrect identity currently logged in. Please login to <strong>this</strong> profile."] = "Jste přihlášen/a pod nesprávnou identitou. Prosím, přihlaste se do <strong>tohoto</strong> profilu.";
@@ -1457,6 +1460,7 @@ $a->strings["You may visit them online at %s"] = "Můžete jej/ji navštívit on
 $a->strings["Please contact the sender by replying to this post if you do not wish to receive these messages."] = "Pokud nechcete dostávat tyto zprávy, kontaktujte prosím odesílatele odpovědí na tuto zprávu.";
 $a->strings["%s posted an update."] = "%s poslal/a aktualizaci.";
 $a->strings["Help:"] = "Nápověda:";
+$a->strings["User imports on closed servers can only be done by an administrator."] = "Importy uživatelů na uzavřených serverech může provést pouze administrátor.";
 $a->strings["Move account"] = "Přesunout účet";
 $a->strings["You can import an account from another Friendica server."] = "Můžete importovat účet z jiného serveru Friendica.";
 $a->strings["You need to export your account from the old server and upload it here. We will recreate your old account here with all your contacts. We will try also to inform your friends that you moved here."] = "Musíte exportovat svůj účet na starém serveru a nahrát ho zde. My následně vytvoříme Váš původní účet zde včetně všech kontaktů. Zároveň se pokusíme informovat všechny Vaše přátele, že jste se sem přestěhoval/a.";
@@ -1483,13 +1487,13 @@ $a->strings["Registration revoked for %s"] = "Registrace zrušena pro %s";
 $a->strings["Please login."] = "Přihlaste se, prosím.";
 $a->strings["Item not found"] = "Položka nenalezena";
 $a->strings["Edit post"] = "Upravit příspěvek";
-$a->strings["CC: email addresses"] = "Skrytá kopie: e-mailové adresy";
+$a->strings["CC: email addresses"] = "Kopie: e-mailové adresy";
 $a->strings["Example: bob@example.com, mary@example.com"] = "Příklad: jan@priklad.cz, lucie@priklad.cz";
 $a->strings["Applications"] = "Aplikace";
 $a->strings["No installed applications."] = "Žádné nainstalované aplikace.";
 $a->strings["You must be logged in to use this module"] = "Pro používání tohoto modulu musíte být přihlášen/a";
 $a->strings["Source URL"] = "Zdrojová adresa URL";
-$a->strings["Friend suggestion sent."] = "Návrhy přátelství odeslány ";
+$a->strings["Friend suggestion sent."] = "Návrh přátelství odeslán. ";
 $a->strings["Suggest Friends"] = "Navrhnout přátele";
 $a->strings["Suggest a friend for %s"] = "Navrhnout přítele pro uživatele %s";
 $a->strings["System down for maintenance"] = "Systém vypnut z důvodů údržby";
@@ -1554,7 +1558,7 @@ $a->strings["Replies/likes to your public posts <strong>may</strong> still be vi
 $a->strings["Notification for new posts"] = "Upozornění na nové příspěvky";
 $a->strings["Send a notification of every new post of this contact"] = "Poslat upozornění při každém novém příspěvku tohoto kontaktu";
 $a->strings["Blacklisted keywords"] = "Zakázaná klíčová slova";
-$a->strings["Comma separated list of keywords that should not be converted to hashtags, when \"Fetch information and keywords\" is selected"] = "Seznam klíčových slov, které by neměly být převáděna na hashtagy, když je zvoleno \"Načíst informace a klíčová slova\". Oddělujte čárkami";
+$a->strings["Comma separated list of keywords that should not be converted to hashtags, when \"Fetch information and keywords\" is selected"] = "Seznam klíčových slov, které by neměly být převáděna na hashtagy, když je zvoleno „Načíst informace a klíčová slova“. Oddělujte čárkami";
 $a->strings["XMPP:"] = "XMPP:";
 $a->strings["Actions"] = "Akce";
 $a->strings["Suggestions"] = "Návrhy";
@@ -1603,7 +1607,7 @@ $a->strings["Description:"] = "Popis:";
 $a->strings["Title:"] = "Název:";
 $a->strings["Share this event"] = "Sdílet tuto událost";
 $a->strings["Basic"] = "Základní";
-$a->strings["Permissions"] = "Oprávnění:";
+$a->strings["Permissions"] = "Oprávnění";
 $a->strings["Failed to remove event"] = "Odstranění události selhalo";
 $a->strings["Event removed"] = "Událost odstraněna";
 $a->strings["The contact could not be added."] = "Kontakt nemohl být přidán.";
@@ -1641,7 +1645,7 @@ $a->strings["Choose what you wish to do to recipient"] = "Vyberte, co si přejet
 $a->strings["Make this post private"] = "Změnit tento příspěvek na soukromý";
 $a->strings["Total invitation limit exceeded."] = "Celkový limit pozvánek byl překročen";
 $a->strings["%s : Not a valid email address."] = "%s : není platná e-mailová adresa.";
-$a->strings["Please join us on Friendica"] = "Prosím přidejte se k nám na Friendice";
+$a->strings["Please join us on Friendica"] = "Prosím přidejte se k nám na Friendica";
 $a->strings["Invitation limit exceeded. Please contact your site administrator."] = "Limit pozvánek byl překročen. Prosím kontaktujte administrátora Vaší stránky.";
 $a->strings["%s : Message delivery failed."] = "%s : Doručení zprávy se nezdařilo.";
 $a->strings["%d message sent."] = [
@@ -1651,7 +1655,7 @@ $a->strings["%d message sent."] = [
        3 => "%d zpráv odesláno.",
 ];
 $a->strings["You have no more invitations available"] = "Nemáte k dispozici žádné další pozvánky";
-$a->strings["Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks."] = "Navštivte %s pro seznam veřejných serverů, na kterých se můžete přidat. Členové Friendica na jiných serverech se mohou spojit mezi sebou, jakožto i se členy mnoha dalších sociálních sítí.";
+$a->strings["Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks."] = "Navštiv %s pro seznam veřejných serverů, na kterých se můžeš přidat. Členové Friendica na jiných serverech se mohou spojit mezi sebou, jakožto i se členy mnoha dalších sociálních sítí.";
 $a->strings["To accept this invitation, please visit and register at %s or any other public Friendica website."] = "K přijetí této pozvánky prosím navštivte a registrujte se na %s nebo na kterékoliv jiném veřejném Friendica serveru.";
 $a->strings["Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join."] = "Stránky Friendica jsou navzájem propojené a vytváří tak obrovský sociální web s dúrazem na soukromí, kterou vlastní a kontrojují její členové, Mohou se také připojit k mnoha tradičním socilním sítím. Navštivte %s pro seznam alternativních serverů Friendica, ke kterým se můžete přidat.";
 $a->strings["Our apologies. This system is not currently configured to connect with other public sites or invite members."] = "Omlouváme se. Systém nyní není nastaven tak, aby se připojil k ostatním veřejným serverům nebo umožnil pozvat nové členy.";
@@ -1662,7 +1666,7 @@ $a->strings["Enter email addresses, one per line:"] = "Zadejte e-mailové adresy
 $a->strings["You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web."] = "Jsi srdečně pozván/a se připojit ke mně a k mým blízkým přátelům na Friendica - a pomoci nám vytvořit lepší sociální web.";
 $a->strings["You will need to supply this invitation code: \$invite_code"] = "Budeš muset zadat tento pozvánkový kód: \$invite_code";
 $a->strings["Once you have registered, please connect with me via my profile page at:"] = "Jakmile se zaregistruješ, prosím spoj se se mnou přes mou profilovu stránku na:";
-$a->strings["For more information about the Friendica project and why we feel it is important, please visit http://friendi.ca"] = "Pro více informací o projektu Friendica a proč si myslíme, že je důležitý, prosím navštivte http://friendi.ca";
+$a->strings["For more information about the Friendica project and why we feel it is important, please visit http://friendi.ca"] = "Pro více informací o projektu Friendica a proč si myslím, že je důležitý, prosím navštiv http://friendi.ca";
 $a->strings["Personal Notes"] = "Osobní poznámky";
 $a->strings["Profile deleted."] = "Profil smazán.";
 $a->strings["Profile-"] = "Profil-";
@@ -1763,10 +1767,10 @@ $a->strings["No photos selected"] = "Není vybrána žádná fotka";
 $a->strings["Upload Photos"] = "Nahrát fotky";
 $a->strings["New album name: "] = "Název nového alba: ";
 $a->strings["or select existing album:"] = "nebo si vyberte existující album:";
-$a->strings["Do not show a status post for this upload"] = "Nezobrazovat pro toto nahrání stavový příspěvek";
+$a->strings["Do not show a status post for this upload"] = "Nezobrazovat pro toto nahrání stavovou zprávu";
 $a->strings["Edit Album"] = "Upravit album";
-$a->strings["Show Newest First"] = "Zobrazit nejprve nejnovější:";
-$a->strings["Show Oldest First"] = "Zobrazit nejprve nejstarší:";
+$a->strings["Show Newest First"] = "Zobrazit nejprve nejnovější";
+$a->strings["Show Oldest First"] = "Zobrazit nejprve nejstarší";
 $a->strings["View Photo"] = "Zobrazit fotku";
 $a->strings["Permission denied. Access to this item may be restricted."] = "Oprávnění bylo zamítnuto. Přístup k této položce může být omezen.";
 $a->strings["Photo not available"] = "Fotka není k dispozici";
@@ -1784,8 +1788,8 @@ $a->strings["Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #cam
 $a->strings["Do not rotate"] = "Neotáčet";
 $a->strings["Rotate CW (right)"] = "Otáčet po směru hodinových ručiček (doprava)";
 $a->strings["Rotate CCW (left)"] = "Otáčet proti směru hodinových ručiček (doleva)";
-$a->strings["I like this (toggle)"] = "Líbí se mi to (přepínač)";
-$a->strings["I don't like this (toggle)"] = "Nelíbí se mi to (přepínač)";
+$a->strings["I like this (toggle)"] = "To se mi líbí (přepínat)";
+$a->strings["I don't like this (toggle)"] = "To se mi nelíbí (přepínat)";
 $a->strings["Comment"] = "Okomentovat";
 $a->strings["Map"] = "Mapa";
 $a->strings["<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-name\">%s</a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"] = "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-name\">%s</a> napsal/a následující <a href=\"%s\" target=\"_blank\">příspěvek</a>";
@@ -1855,6 +1859,7 @@ $a->strings["Visible to everybody"] = "Viditelné pro všechny";
 $a->strings["Close"] = "Zavřít";
 $a->strings["Could not find any unarchived contact entry for this URL (%s)"] = "Nelze najít žádný nearchivovaný záznam kontaktu pro tuto URL adresu (%s)";
 $a->strings["The contact entries have been archived"] = "Záznamy kontaktů byly archivovány";
+$a->strings["Post update version number has been set to %s."] = "Číslo verze post update bylo nastaveno na %s.";
 $a->strings["Execute pending post updates."] = "Provést čekající aktualizace příspěvků.";
 $a->strings["All pending post updates are done."] = "Všechny čekající aktualizace příspěvků jsou hotové.";
 $a->strings["Enter new password: "] = "Zadejte nové heslo";
@@ -1899,7 +1904,7 @@ $a->strings["toggle ignore status"] = "přepínat stav ignorování";
 $a->strings["add star"] = "přidat hvězdu";
 $a->strings["remove star"] = "odebrat hvězdu";
 $a->strings["toggle star status"] = "přepínat hvězdu";
-$a->strings["starred"] = "označeno hvězdou";
+$a->strings["starred"] = "s hvězdou";
 $a->strings["add tag"] = "přidat štítek";
 $a->strings["like"] = "líbí se mi";
 $a->strings["dislike"] = "nelíbí se mi";
@@ -1942,6 +1947,7 @@ $a->strings["At the time of registration, and for providing communications betwe
 $a->strings["This data is required for communication and is passed on to the nodes of the communication partners and is stored there. Users can enter additional private data that may be transmitted to the communication partners accounts."] = "Tato data jsou vyžadována ke komunikaci a jsou předávána serverům komunikačních partnerů a jsou tam ukládána. Uživatelé mohou zadávat dodatečná soukromá data, která mohou být odeslána na účty komunikačních partnerů.";
 $a->strings["At any point in time a logged in user can export their account data from the <a href=\"%1\$s/settings/uexport\">account settings</a>. If the user wants to delete their account they can do so at <a href=\"%1\$s/removeme\">%1\$s/removeme</a>. The deletion of the account will be permanent. Deletion of the data will also be requested from the nodes of the communication partners."] = "Přihlášený uživatel si kdykoliv může exportovat svoje data účtu z <a href=\"%1\$s/settings/uexport\">nastavení účtu</a>. Pokud by chtěl uživatel svůj účet smazat, může tak učinit na stránce <a href=\"%1\$s/removeme\">%1\$s/removeme</a>. Smazání účtu bude trvalé. Na serverech komunikačních partnerů bude zároveň vyžádáno smazání dat.";
 $a->strings["Privacy Statement"] = "Prohlášení o soukromí";
+$a->strings["Bad Request."] = "Špatný požadavek";
 $a->strings["%s is now following %s."] = "%s nyní sleduje %s.";
 $a->strings["following"] = "sleduje";
 $a->strings["%s stopped following %s."] = "%s přestal/a sledovat uživatele %s.";
@@ -1981,7 +1987,7 @@ $a->strings["No browser URL could be matched to this address."] = "Této adrese
 $a->strings["Unable to match @-style Identity Address with a known protocol or email contact."] = "Není možné namapovat adresu identity ve stylu @ s žádným možným protokolem ani emailovým kontaktem.";
 $a->strings["Use mailto: in front of address to force email check."] = "Použite mailo: před adresou k vynucení emailové kontroly.";
 $a->strings["The profile address specified belongs to a network which has been disabled on this site."] = "Zadaná adresa profilu patří do sítě, která  byla na tomto serveru zakázána.";
-$a->strings["Limited profile. This person will be unable to receive direct/personal notifications from you."] = "Omezený profil. Tato osoba nebude schopna od Vás pÅ\99ijímat pÅ\99ímé/osobní sdělení.";
+$a->strings["Limited profile. This person will be unable to receive direct/personal notifications from you."] = "Omezený profil. Tato osoba nebude schopna od Vás pÅ\99ijímat pÅ\99ímá/osobní sdělení.";
 $a->strings["Unable to retrieve contact information."] = "Nepodařilo se získat kontaktní informace.";
 $a->strings["Starts:"] = "Začíná:";
 $a->strings["Finishes:"] = "Končí:";
@@ -2022,7 +2028,7 @@ $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Yo
 $a->strings["Registration at %s"] = "Registrace na %s";
 $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t\t"] = "\n\t\t\tVážený/á %1\$s,\n\t\t\t\tDěkujeme, že jste se registroval/a na %2\$s. Váš účet byl vytvořen.\n\t\t";
 $a->strings["\n\t\t\tThe login details are as follows:\n\n\t\t\tSite Location:\t%3\$s\n\t\t\tLogin Name:\t\t%1\$s\n\t\t\tPassword:\t\t%5\$s\n\n\t\t\tYou may change your password from your account \"Settings\" page after logging\n\t\t\tin.\n\n\t\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\t\tYou may also wish to add some basic information to your default profile\n\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\t\tWe recommend setting your full name, adding a profile photo,\n\t\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\t\tthan that.\n\n\t\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\t\tIf you are new and do not know anybody here, they may help\n\t\t\tyou to make some new and interesting friends.\n\n\t\t\tIf you ever want to delete your account, you can do so at %3\$s/removeme\n\n\t\t\tThank you and welcome to %2\$s."] = "\n\t\t\tZde jsou Vaše přihlašovací detaily:\n\n\t\t\tAdresa stránky:\t\t%3\$s\n\t\t\tPřihlašovací jméno:\t%1\$s\n\t\t\tHeslo:\t\t\t%5\$s\n\n\t\t\tSvé heslo si po přihlášení můžete změnit na stránce \"Nastavení\" vašeho\n\t\t\túčtu.\n\n\t\t\tProsím, prohlédněte si na chvilku ostatní nastavení účtu na této stránce.\n\n\t\t\tMožná byste si také přál/a přidat pár základních informací na svůj výchozí\n\t\t\tprofil (na stránce \"Profily\") aby vás další lidé mohli snadno najít.\n\t\t\tDoporučujeme nastavit si Vaše celé jméno, přidat profilovou fotku,\n\t\t\tpřidat pár \"klíčových slov\" k profilu (velmi užitečné při získávání nových\n\t\t\tpřátel) - a možná v jaké zemi žijete; pokud nechcete být konkrétnější.\n\n\t\t\tZcela respektujeme Vaše právo na soukromí a žádnou z těchto položek\n\t\t\tnení potřeba vyplňovat. Pokud jste zde nový/á a nikoho zde neznáte, mohou vám\n\t\t\tpomoci si získat nové a zajímavé přátele.\n\t\t\tPokud byste si někdy přál/a smazat účet, můžete tak učinit na stránce\n\t\t\t%3\$s/removeme.\n\n\t\t\tDěkujeme Vám a vítáme Vás na %2\$s.";
-$a->strings["A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Dříve smazaná skupina s tímto jménem byla obnovena. Stávající oprávnění <strong>může</strong> ovlivnit tuto skupinu a její budoucí členy. Pokud to není to, co jste chtěli, vytvořte, prosím, další skupinu s jiným názvem.";
+$a->strings["A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Dříve smazaná skupina s tímto jménem byla obnovena. Stávající oprávnění <strong>může</strong> ovlivnit tuto skupinu a její budoucí členy. Pokud to není to, co jste chtěl/a, vytvořte, prosím, další skupinu s jiným názvem.";
 $a->strings["Default privacy group for new contacts"] = "Výchozí soukromá skupina pro nové kontakty.";
 $a->strings["Everybody"] = "Všichni";
 $a->strings["edit"] = "upravit";
@@ -2097,6 +2103,7 @@ $a->strings["pump.io"] = "pump.io";
 $a->strings["Twitter"] = "Twitter";
 $a->strings["Diaspora Connector"] = "Diaspora Connector";
 $a->strings["GNU Social Connector"] = "GNU social Connector";
+$a->strings["ActivityPub"] = "ActivityPub";
 $a->strings["pnut"] = "pnut";
 $a->strings["Male"] = "Muž";
 $a->strings["Female"] = "Žena";
@@ -2155,10 +2162,10 @@ $a->strings["It's complicated"] = "Je to složité";
 $a->strings["Don't care"] = "Nezájem";
 $a->strings["Ask me"] = "Zeptej se mě";
 $a->strings["General Features"] = "Obecné vlastnosti";
-$a->strings["Multiple Profiles"] = "Vícenásobné profily";
-$a->strings["Ability to create multiple profiles"] = "Schopnost vytvořit vícenásobné profily";
+$a->strings["Multiple Profiles"] = "Více profilů";
+$a->strings["Ability to create multiple profiles"] = "Schopnost vytvořit více profilů";
 $a->strings["Photo Location"] = "Poloha fotky";
-$a->strings["Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map."] = "Metadata fotek jsou normálně odebrána. Tato funkce před odebrání metadat extrahuje polohu (pokud je k dispozici) a propojí jej s mapou.";
+$a->strings["Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map."] = "Metadata fotek jsou normálně odebrána. Tato funkce před odebrání metadat extrahuje polohu (pokud je k dispozici) a propojí ji s mapou.";
 $a->strings["Export Public Calendar"] = "Exportovat veřejný kalendář";
 $a->strings["Ability for visitors to download the public calendar"] = "Umožnit návštěvníkům stáhnout si veřejný kalendář";
 $a->strings["Post Composition Features"] = "Nastavení vytváření příspěvků";
@@ -2180,7 +2187,7 @@ $a->strings["Network Personal Tab"] = "Síťová záložka Osobní";
 $a->strings["Enable tab to display only Network posts that you've interacted on"] = "Povolit záložku pro zobrazení pouze síťových příspěvků, na které jste reagoval/a";
 $a->strings["Network New Tab"] = "Síťová záložka Nové";
 $a->strings["Enable tab to display only new Network posts (from the last 12 hours)"] = "Povolit záložku pro zobrazení pouze nových příspěvků (za posledních 12 hodin)";
-$a->strings["Network Shared Links Tab"] = "Záložka Síťové sdílené odkazy ";
+$a->strings["Network Shared Links Tab"] = "Síťová záložka Sdílené odkazy ";
 $a->strings["Enable tab to display only Network posts with links in them"] = "Povolit záložky pro zobrazování pouze Síťových příspěvků s vazbou na ně";
 $a->strings["Post/Comment Tools"] = "Nástroje příspěvků/komentářů";
 $a->strings["Multiple Deletion"] = "Vícenásobné mazání";
@@ -2192,14 +2199,14 @@ $a->strings["Ability to tag existing posts"] = "Schopnost přidávat štítky ke
 $a->strings["Post Categories"] = "Kategorie příspěvků";
 $a->strings["Add categories to your posts"] = "Přidat kategorie k Vašim příspěvkům";
 $a->strings["Ability to file posts under folders"] = "Možnost řadit příspěvky do složek";
-$a->strings["Dislike Posts"] = "Označit příspěvky jako neoblíbené";
-$a->strings["Ability to dislike posts/comments"] = "Možnost označovat příspěvky/komentáře jako neoblíbené";
-$a->strings["Star Posts"] = "Označit příspěvky hvězdou";
+$a->strings["Dislike Posts"] = "Označovat příspěvky jako neoblíbené";
+$a->strings["Ability to dislike posts/comments"] = "Možnost označovat příspěvky/komentáře jako neoblíbené (\"to se mi nelíbí\")";
+$a->strings["Star Posts"] = "Označovat příspěvky hvězdou";
 $a->strings["Ability to mark special posts with a star indicator"] = "Možnost označovat zvláštní příspěvky indikátorem hvězdy";
 $a->strings["Mute Post Notifications"] = "Ztlumit oznámení o příspěvcích";
 $a->strings["Ability to mute notifications for a thread"] = "Možnost ztlumit oznámení pro vlákno";
 $a->strings["Advanced Profile Settings"] = "Pokročilá nastavení profilu";
-$a->strings["Show visitors public community forums at the Advanced Profile Page"] = "Ukázat návštěvníkům veřejná komunitní fóra na stránce pokročilého profilu";
+$a->strings["Show visitors public community forums at the Advanced Profile Page"] = "Zobrazit návštěvníkům veřejná komunitní fóra na stránce pokročilého profilu";
 $a->strings["Tag Cloud"] = "Štítkový oblak";
 $a->strings["Provide a personal tag cloud on your profile page"] = "Poskytne na Vaší profilové stránce osobní \"štítkový oblak\"";
 $a->strings["Display Membership Date"] = "Zobrazit datum členství";
index 1a610dab32417d6fb2ef9c4aa5da66c987d87122..841fe98d153f187e214dad57653b49bccd70f9e1 100644 (file)
@@ -42,8 +42,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: friendica\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-25 15:34+0000\n"
-"PO-Revision-Date: 2018-08-27 08:22+0000\n"
+"POT-Creation-Date: 2018-09-27 21:18+0000\n"
+"PO-Revision-Date: 2018-10-06 08:11+0000\n"
 "Last-Translator: Tobias Diekershoff <tobias.diekershoff@gmx.net>\n"
 "Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n"
 "MIME-Version: 1.0\n"
@@ -52,47 +52,47 @@ msgstr ""
 "Language: de\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: index.php:261 mod/apps.php:14
+#: index.php:265 mod/apps.php:14
 msgid "You must be logged in to use addons. "
 msgstr "Sie müssen angemeldet sein um Addons benutzen zu können."
 
-#: index.php:308 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
+#: index.php:312 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
 #: mod/help.php:62
 msgid "Not Found"
 msgstr "Nicht gefunden"
 
-#: index.php:313 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
+#: index.php:317 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
 #: mod/cal.php:44
 msgid "Page not found."
 msgstr "Seite nicht gefunden."
 
-#: index.php:431 mod/group.php:83 mod/profperm.php:29
+#: index.php:435 mod/group.php:83 mod/profperm.php:29
 msgid "Permission denied"
 msgstr "Zugriff verweigert"
 
-#: index.php:432 include/items.php:412 mod/crepair.php:100
+#: index.php:436 include/items.php:413 mod/crepair.php:100
 #: mod/wallmessage.php:16 mod/wallmessage.php:40 mod/wallmessage.php:79
-#: mod/wallmessage.php:103 mod/dfrn_confirm.php:66 mod/dirfind.php:27
+#: mod/wallmessage.php:103 mod/dfrn_confirm.php:67 mod/dirfind.php:27
 #: mod/manage.php:131 mod/settings.php:43 mod/settings.php:149
 #: mod/settings.php:665 mod/common.php:28 mod/network.php:34 mod/group.php:26
 #: mod/delegate.php:27 mod/delegate.php:45 mod/delegate.php:56
-#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:17
-#: mod/unfollow.php:59 mod/unfollow.php:93 mod/register.php:53
+#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:20
+#: mod/unfollow.php:73 mod/unfollow.php:105 mod/register.php:53
 #: mod/notifications.php:67 mod/message.php:60 mod/message.php:105
 #: mod/ostatus_subscribe.php:17 mod/nogroup.php:23 mod/suggest.php:61
 #: mod/wall_upload.php:104 mod/wall_upload.php:107 mod/api.php:35
 #: mod/api.php:40 mod/profile_photo.php:29 mod/profile_photo.php:176
 #: mod/profile_photo.php:198 mod/wall_attach.php:80 mod/wall_attach.php:83
-#: mod/item.php:166 mod/uimport.php:28 mod/cal.php:306 mod/regmod.php:108
+#: mod/item.php:166 mod/uimport.php:15 mod/cal.php:306 mod/regmod.php:108
 #: mod/editpost.php:19 mod/fsuggest.php:80 mod/allfriends.php:23
-#: mod/contacts.php:381 mod/events.php:193 mod/follow.php:54
-#: mod/follow.php:118 mod/attach.php:39 mod/poke.php:145 mod/invite.php:21
+#: mod/contacts.php:387 mod/events.php:195 mod/follow.php:54
+#: mod/follow.php:118 mod/attach.php:39 mod/poke.php:144 mod/invite.php:21
 #: mod/invite.php:112 mod/notes.php:32 mod/profiles.php:179
-#: mod/profiles.php:511 mod/photos.php:183 mod/photos.php:1065
+#: mod/profiles.php:511 mod/photos.php:183 mod/photos.php:1067
 msgid "Permission denied."
 msgstr "Zugriff verweigert."
 
-#: index.php:460
+#: index.php:464
 msgid "toggle mobile"
 msgstr "auf/von Mobile Ansicht wechseln"
 
@@ -126,13 +126,13 @@ msgstr "slackr"
 
 #: view/theme/duepuntozero/config.php:71 view/theme/quattro/config.php:73
 #: view/theme/vier/config.php:119 view/theme/frio/config.php:118
-#: mod/crepair.php:150 mod/install.php:206 mod/install.php:244
+#: mod/crepair.php:150 mod/install.php:204 mod/install.php:242
 #: mod/manage.php:184 mod/message.php:264 mod/message.php:430
-#: mod/fsuggest.php:114 mod/contacts.php:630 mod/events.php:533
-#: mod/localtime.php:56 mod/poke.php:195 mod/invite.php:155
-#: mod/profiles.php:577 mod/photos.php:1094 mod/photos.php:1180
-#: mod/photos.php:1452 mod/photos.php:1497 mod/photos.php:1536
-#: mod/photos.php:1596 src/Object/Post.php:795
+#: mod/fsuggest.php:114 mod/contacts.php:631 mod/events.php:560
+#: mod/localtime.php:56 mod/poke.php:194 mod/invite.php:155
+#: mod/profiles.php:577 mod/photos.php:1096 mod/photos.php:1182
+#: mod/photos.php:1454 mod/photos.php:1499 mod/photos.php:1538
+#: mod/photos.php:1598 src/Object/Post.php:795
 msgid "Submit"
 msgstr "Senden"
 
@@ -220,8 +220,8 @@ msgstr "Name oder Interessen eingeben"
 
 #: view/theme/vier/theme.php:199 include/conversation.php:881
 #: mod/dirfind.php:231 mod/match.php:90 mod/suggest.php:86
-#: mod/allfriends.php:76 mod/contacts.php:604 mod/contacts.php:610
-#: mod/follow.php:143 src/Model/Contact.php:933 src/Content/Widget.php:61
+#: mod/allfriends.php:76 mod/contacts.php:611 mod/follow.php:143
+#: src/Model/Contact.php:944 src/Content/Widget.php:61
 msgid "Connect/Follow"
 msgstr "Verbinden/Folgen"
 
@@ -229,7 +229,7 @@ msgstr "Verbinden/Folgen"
 msgid "Examples: Robert Morgenstein, Fishing"
 msgstr "Beispiel: Robert Morgenstein, Angeln"
 
-#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:842
+#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:845
 #: src/Content/Widget.php:63
 msgid "Find"
 msgstr "Finde"
@@ -260,16 +260,16 @@ msgid "Local Directory"
 msgstr "Lokales Verzeichnis"
 
 #: view/theme/vier/theme.php:251 include/text.php:909 src/Content/Nav.php:151
-#: src/Content/ForumManager.php:125
+#: src/Content/ForumManager.php:130
 msgid "Forums"
 msgstr "Foren"
 
-#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:127
+#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:132
 msgid "External link to forum"
 msgstr "Externer Link zum Forum"
 
-#: view/theme/vier/theme.php:256 include/items.php:489 src/Object/Post.php:429
-#: src/App.php:786 src/Content/Widget.php:310 src/Content/ForumManager.php:130
+#: view/theme/vier/theme.php:256 include/items.php:490 src/Object/Post.php:429
+#: src/App.php:799 src/Content/Widget.php:307 src/Content/ForumManager.php:135
 msgid "show more"
 msgstr "mehr anzeigen"
 
@@ -354,8 +354,8 @@ msgstr "Abmelden"
 msgid "End this session"
 msgstr "Diese Sitzung beenden"
 
-#: view/theme/frio/theme.php:269 mod/contacts.php:689 mod/contacts.php:877
-#: src/Model/Profile.php:875 src/Content/Nav.php:100
+#: view/theme/frio/theme.php:269 mod/contacts.php:690 mod/contacts.php:880
+#: src/Model/Profile.php:888 src/Content/Nav.php:100
 msgid "Status"
 msgstr "Status"
 
@@ -365,8 +365,8 @@ msgid "Your posts and conversations"
 msgstr "Deine Beiträge und Unterhaltungen"
 
 #: view/theme/frio/theme.php:270 mod/newmember.php:24 mod/profperm.php:116
-#: mod/contacts.php:691 mod/contacts.php:893 src/Model/Profile.php:717
-#: src/Model/Profile.php:850 src/Model/Profile.php:883 src/Content/Nav.php:101
+#: mod/contacts.php:692 mod/contacts.php:896 src/Model/Profile.php:730
+#: src/Model/Profile.php:863 src/Model/Profile.php:896 src/Content/Nav.php:101
 msgid "Profile"
 msgstr "Profil"
 
@@ -374,7 +374,7 @@ msgstr "Profil"
 msgid "Your profile page"
 msgstr "Deine Profilseite"
 
-#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:891
+#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:904
 #: src/Content/Nav.php:102
 msgid "Photos"
 msgstr "Bilder"
@@ -383,8 +383,8 @@ msgstr "Bilder"
 msgid "Your photos"
 msgstr "Deine Fotos"
 
-#: view/theme/frio/theme.php:272 src/Model/Profile.php:899
-#: src/Model/Profile.php:902 src/Content/Nav.php:103
+#: view/theme/frio/theme.php:272 src/Model/Profile.php:912
+#: src/Model/Profile.php:915 src/Content/Nav.php:103
 msgid "Videos"
 msgstr "Videos"
 
@@ -393,7 +393,7 @@ msgid "Your videos"
 msgstr "Deine Videos"
 
 #: view/theme/frio/theme.php:273 view/theme/frio/theme.php:277 mod/cal.php:276
-#: mod/events.php:390 src/Model/Profile.php:911 src/Model/Profile.php:922
+#: mod/events.php:391 src/Model/Profile.php:924 src/Model/Profile.php:935
 #: src/Content/Nav.php:104 src/Content/Nav.php:170
 msgid "Events"
 msgstr "Veranstaltungen"
@@ -411,8 +411,8 @@ msgstr "Netzwerk"
 msgid "Conversations from your friends"
 msgstr "Unterhaltungen Deiner Kontakte"
 
-#: view/theme/frio/theme.php:277 src/Model/Profile.php:914
-#: src/Model/Profile.php:925 src/Content/Nav.php:170
+#: view/theme/frio/theme.php:277 src/Model/Profile.php:927
+#: src/Model/Profile.php:938 src/Content/Nav.php:170
 msgid "Events and Calendar"
 msgstr "Ereignisse und Kalender"
 
@@ -434,8 +434,8 @@ msgid "Account settings"
 msgstr "Kontoeinstellungen"
 
 #: view/theme/frio/theme.php:280 include/text.php:906 mod/viewcontacts.php:125
-#: mod/contacts.php:836 mod/contacts.php:905 src/Model/Profile.php:954
-#: src/Model/Profile.php:957 src/Content/Nav.php:147 src/Content/Nav.php:213
+#: mod/contacts.php:839 mod/contacts.php:908 src/Model/Profile.php:967
+#: src/Model/Profile.php:970 src/Content/Nav.php:147 src/Content/Nav.php:213
 msgid "Contacts"
 msgstr "Kontakte"
 
@@ -493,37 +493,37 @@ msgstr "%s: Aktualisiere die author-id und owner-id in der Thread Tabelle"
 msgid "%s: Updating post-type."
 msgstr "%s: Aktualisiere Beitrags-Typ"
 
-#: include/items.php:355 mod/display.php:70 mod/display.php:245
-#: mod/display.php:341 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
+#: include/items.php:356 mod/display.php:71 mod/display.php:254
+#: mod/display.php:350 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
 #: mod/notice.php:22 mod/viewsrc.php:22
 msgid "Item not found."
 msgstr "Beitrag nicht gefunden."
 
-#: include/items.php:393
+#: include/items.php:394
 msgid "Do you really want to delete this item?"
 msgstr "Möchtest Du wirklich dieses Item löschen?"
 
-#: include/items.php:395 mod/settings.php:1100 mod/settings.php:1106
+#: include/items.php:396 mod/settings.php:1100 mod/settings.php:1106
 #: mod/settings.php:1113 mod/settings.php:1117 mod/settings.php:1121
 #: mod/settings.php:1125 mod/settings.php:1129 mod/settings.php:1133
 #: mod/settings.php:1153 mod/settings.php:1154 mod/settings.php:1155
 #: mod/settings.php:1156 mod/settings.php:1157 mod/register.php:237
 #: mod/message.php:154 mod/suggest.php:40 mod/dfrn_request.php:645
-#: mod/api.php:110 mod/contacts.php:465 mod/follow.php:150
+#: mod/api.php:110 mod/contacts.php:471 mod/follow.php:150
 #: mod/profiles.php:541 mod/profiles.php:544 mod/profiles.php:566
 msgid "Yes"
 msgstr "Ja"
 
-#: include/items.php:398 include/conversation.php:1179 mod/videos.php:146
-#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:120
+#: include/items.php:399 include/conversation.php:1179 mod/videos.php:146
+#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:130
 #: mod/message.php:157 mod/tagrm.php:19 mod/tagrm.php:91 mod/suggest.php:43
-#: mod/dfrn_request.php:655 mod/editpost.php:140 mod/contacts.php:468
+#: mod/dfrn_request.php:655 mod/editpost.php:146 mod/contacts.php:474
 #: mod/follow.php:161 mod/fbrowser.php:104 mod/fbrowser.php:135
 #: mod/photos.php:255 mod/photos.php:327
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: include/items.php:483 src/Content/Feature.php:96
+#: include/items.php:484 src/Content/Feature.php:96
 msgid "Archives"
 msgstr "Archiv"
 
@@ -592,35 +592,35 @@ msgstr "Nachricht/Beitrag"
 msgid "%1$s marked %2$s's %3$s as favorite"
 msgstr "%1$s hat %2$s\\s %3$s als Favorit markiert"
 
-#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1509
 msgid "Likes"
 msgstr "Likes"
 
-#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1509
 msgid "Dislikes"
 msgstr "Dislikes"
 
 #: include/conversation.php:546 include/conversation.php:1492
-#: mod/photos.php:1508
+#: mod/photos.php:1510
 msgid "Attending"
 msgid_plural "Attending"
 msgstr[0] "Teilnehmend"
 msgstr[1] "Teilnehmend"
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Not attending"
 msgstr "Nicht teilnehmend"
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Might attend"
 msgstr "Eventuell teilnehmend"
 
-#: include/conversation.php:626 mod/photos.php:1564 src/Object/Post.php:195
+#: include/conversation.php:626 mod/photos.php:1566 src/Object/Post.php:195
 msgid "Select"
 msgstr "Auswählen"
 
 #: include/conversation.php:627 mod/settings.php:736 mod/admin.php:1906
-#: mod/contacts.php:852 mod/contacts.php:1130 mod/photos.php:1565
+#: mod/contacts.php:855 mod/contacts.php:1133 mod/photos.php:1567
 msgid "Delete"
 msgstr "Löschen"
 
@@ -649,7 +649,7 @@ msgstr "Im Zusammenhang betrachten"
 
 #: include/conversation.php:698 include/conversation.php:1160
 #: mod/wallmessage.php:145 mod/message.php:263 mod/message.php:431
-#: mod/editpost.php:115 mod/photos.php:1480 src/Object/Post.php:401
+#: mod/editpost.php:121 mod/photos.php:1482 src/Object/Post.php:401
 msgid "Please wait"
 msgstr "Bitte warten"
 
@@ -661,36 +661,36 @@ msgstr "löschen"
 msgid "Delete Selected Items"
 msgstr "Lösche die markierten Beiträge"
 
-#: include/conversation.php:867 src/Model/Contact.php:937
+#: include/conversation.php:867 src/Model/Contact.php:948
 msgid "View Status"
 msgstr "Pinnwand anschauen"
 
 #: include/conversation.php:868 include/conversation.php:884
 #: mod/dirfind.php:230 mod/directory.php:164 mod/match.php:89
-#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:877
-#: src/Model/Contact.php:930 src/Model/Contact.php:938
+#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:888
+#: src/Model/Contact.php:941 src/Model/Contact.php:949
 msgid "View Profile"
 msgstr "Profil anschauen"
 
-#: include/conversation.php:869 src/Model/Contact.php:939
+#: include/conversation.php:869 src/Model/Contact.php:950
 msgid "View Photos"
 msgstr "Bilder anschauen"
 
-#: include/conversation.php:870 src/Model/Contact.php:931
-#: src/Model/Contact.php:940
+#: include/conversation.php:870 src/Model/Contact.php:942
+#: src/Model/Contact.php:951
 msgid "Network Posts"
 msgstr "Netzwerkbeiträge"
 
-#: include/conversation.php:871 src/Model/Contact.php:932
-#: src/Model/Contact.php:941
+#: include/conversation.php:871 src/Model/Contact.php:943
+#: src/Model/Contact.php:952
 msgid "View Contact"
 msgstr "Kontakt anzeigen"
 
-#: include/conversation.php:872 src/Model/Contact.php:943
+#: include/conversation.php:872 src/Model/Contact.php:954
 msgid "Send PM"
 msgstr "Private Nachricht senden"
 
-#: include/conversation.php:876 src/Model/Contact.php:944
+#: include/conversation.php:876 src/Model/Contact.php:955
 msgid "Poke"
 msgstr "Anstupsen"
 
@@ -822,85 +822,85 @@ msgid "Share"
 msgstr "Teilen"
 
 #: include/conversation.php:1142 mod/wallmessage.php:143 mod/message.php:261
-#: mod/message.php:428 mod/editpost.php:101
+#: mod/message.php:428 mod/editpost.php:107
 msgid "Upload photo"
 msgstr "Foto hochladen"
 
-#: include/conversation.php:1143 mod/editpost.php:102
+#: include/conversation.php:1143 mod/editpost.php:108
 msgid "upload photo"
 msgstr "Bild hochladen"
 
-#: include/conversation.php:1144 mod/editpost.php:103
+#: include/conversation.php:1144 mod/editpost.php:109
 msgid "Attach file"
 msgstr "Datei anhängen"
 
-#: include/conversation.php:1145 mod/editpost.php:104
+#: include/conversation.php:1145 mod/editpost.php:110
 msgid "attach file"
 msgstr "Datei anhängen"
 
 #: include/conversation.php:1146 mod/wallmessage.php:144 mod/message.php:262
-#: mod/message.php:429 mod/editpost.php:105
+#: mod/message.php:429 mod/editpost.php:111
 msgid "Insert web link"
 msgstr "Einen Link einfügen"
 
-#: include/conversation.php:1147 mod/editpost.php:106
+#: include/conversation.php:1147 mod/editpost.php:112
 msgid "web link"
 msgstr "Weblink"
 
-#: include/conversation.php:1148 mod/editpost.php:107
+#: include/conversation.php:1148 mod/editpost.php:113
 msgid "Insert video link"
 msgstr "Video-Adresse einfügen"
 
-#: include/conversation.php:1149 mod/editpost.php:108
+#: include/conversation.php:1149 mod/editpost.php:114
 msgid "video link"
 msgstr "Video-Link"
 
-#: include/conversation.php:1150 mod/editpost.php:109
+#: include/conversation.php:1150 mod/editpost.php:115
 msgid "Insert audio link"
 msgstr "Audio-Adresse einfügen"
 
-#: include/conversation.php:1151 mod/editpost.php:110
+#: include/conversation.php:1151 mod/editpost.php:116
 msgid "audio link"
 msgstr "Audio-Link"
 
-#: include/conversation.php:1152 mod/editpost.php:111
+#: include/conversation.php:1152 mod/editpost.php:117
 msgid "Set your location"
 msgstr "Deinen Standort festlegen"
 
-#: include/conversation.php:1153 mod/editpost.php:112
+#: include/conversation.php:1153 mod/editpost.php:118
 msgid "set location"
 msgstr "Ort setzen"
 
-#: include/conversation.php:1154 mod/editpost.php:113
+#: include/conversation.php:1154 mod/editpost.php:119
 msgid "Clear browser location"
 msgstr "Browser-Standort leeren"
 
-#: include/conversation.php:1155 mod/editpost.php:114
+#: include/conversation.php:1155 mod/editpost.php:120
 msgid "clear location"
 msgstr "Ort löschen"
 
-#: include/conversation.php:1157 mod/editpost.php:129
+#: include/conversation.php:1157 mod/editpost.php:135
 msgid "Set title"
 msgstr "Titel setzen"
 
-#: include/conversation.php:1159 mod/editpost.php:131
+#: include/conversation.php:1159 mod/editpost.php:137
 msgid "Categories (comma-separated list)"
 msgstr "Kategorien (kommasepariert)"
 
-#: include/conversation.php:1161 mod/editpost.php:116
+#: include/conversation.php:1161 mod/editpost.php:122
 msgid "Permission settings"
 msgstr "Berechtigungseinstellungen"
 
-#: include/conversation.php:1162 mod/editpost.php:146
+#: include/conversation.php:1162 mod/editpost.php:152
 msgid "permissions"
 msgstr "Zugriffsrechte"
 
-#: include/conversation.php:1171 mod/editpost.php:126
+#: include/conversation.php:1171 mod/editpost.php:132
 msgid "Public post"
 msgstr "Öffentlicher Beitrag"
 
-#: include/conversation.php:1175 mod/editpost.php:137 mod/events.php:531
-#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
+#: include/conversation.php:1175 mod/editpost.php:143 mod/events.php:558
+#: mod/photos.php:1500 mod/photos.php:1539 mod/photos.php:1599
 #: src/Object/Post.php:804
 msgid "Preview"
 msgstr "Vorschau"
@@ -917,12 +917,12 @@ msgstr "Poste an Kontakte"
 msgid "Private post"
 msgstr "Privater Beitrag"
 
-#: include/conversation.php:1191 mod/editpost.php:144
-#: src/Model/Profile.php:344
+#: include/conversation.php:1191 mod/editpost.php:150
+#: src/Model/Profile.php:357
 msgid "Message"
 msgstr "Nachricht"
 
-#: include/conversation.php:1192 mod/editpost.php:145
+#: include/conversation.php:1192 mod/editpost.php:151
 msgid "Browser"
 msgstr "Browser"
 
@@ -948,7 +948,7 @@ msgid_plural "Not Attending"
 msgstr[0] "Nicht teilnehmend "
 msgstr[1] "Nicht teilnehmend"
 
-#: include/conversation.php:1498 src/Content/ContactSelector.php:122
+#: include/conversation.php:1498 src/Content/ContactSelector.php:127
 msgid "Undecided"
 msgid_plural "Undecided"
 msgstr[0] "Unentschieden"
@@ -1314,7 +1314,7 @@ msgstr[1] "%d Kontakte"
 msgid "View Contacts"
 msgstr "Kontakte anzeigen"
 
-#: include/text.php:889 mod/filer.php:35 mod/editpost.php:100 mod/notes.php:54
+#: include/text.php:889 mod/filer.php:35 mod/editpost.php:106 mod/notes.php:54
 msgid "Save"
 msgstr "Speichern"
 
@@ -1387,132 +1387,132 @@ msgstr "eine Abfuhr erteilen"
 msgid "rebuffed"
 msgstr "abfuhrerteilte"
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:389
 msgid "Monday"
 msgstr "Montag"
 
-#: include/text.php:972 src/Model/Event.php:389
+#: include/text.php:972 src/Model/Event.php:390
 msgid "Tuesday"
 msgstr "Dienstag"
 
-#: include/text.php:972 src/Model/Event.php:390
+#: include/text.php:972 src/Model/Event.php:391
 msgid "Wednesday"
 msgstr "Mittwoch"
 
-#: include/text.php:972 src/Model/Event.php:391
+#: include/text.php:972 src/Model/Event.php:392
 msgid "Thursday"
 msgstr "Donnerstag"
 
-#: include/text.php:972 src/Model/Event.php:392
+#: include/text.php:972 src/Model/Event.php:393
 msgid "Friday"
 msgstr "Freitag"
 
-#: include/text.php:972 src/Model/Event.php:393
+#: include/text.php:972 src/Model/Event.php:394
 msgid "Saturday"
 msgstr "Samstag"
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:387
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
 msgid "Sunday"
 msgstr "Sonntag"
 
-#: include/text.php:976 src/Model/Event.php:408
+#: include/text.php:976 src/Model/Event.php:409
 msgid "January"
 msgstr "Januar"
 
-#: include/text.php:976 src/Model/Event.php:409
+#: include/text.php:976 src/Model/Event.php:410
 msgid "February"
 msgstr "Februar"
 
-#: include/text.php:976 src/Model/Event.php:410
+#: include/text.php:976 src/Model/Event.php:411
 msgid "March"
 msgstr "März"
 
-#: include/text.php:976 src/Model/Event.php:411
+#: include/text.php:976 src/Model/Event.php:412
 msgid "April"
 msgstr "April"
 
-#: include/text.php:976 include/text.php:993 src/Model/Event.php:399
-#: src/Model/Event.php:412
+#: include/text.php:976 include/text.php:993 src/Model/Event.php:400
+#: src/Model/Event.php:413
 msgid "May"
 msgstr "Mai"
 
-#: include/text.php:976 src/Model/Event.php:413
+#: include/text.php:976 src/Model/Event.php:414
 msgid "June"
 msgstr "Juni"
 
-#: include/text.php:976 src/Model/Event.php:414
+#: include/text.php:976 src/Model/Event.php:415
 msgid "July"
 msgstr "Juli"
 
-#: include/text.php:976 src/Model/Event.php:415
+#: include/text.php:976 src/Model/Event.php:416
 msgid "August"
 msgstr "August"
 
-#: include/text.php:976 src/Model/Event.php:416
+#: include/text.php:976 src/Model/Event.php:417
 msgid "September"
 msgstr "September"
 
-#: include/text.php:976 src/Model/Event.php:417
+#: include/text.php:976 src/Model/Event.php:418
 msgid "October"
 msgstr "Oktober"
 
-#: include/text.php:976 src/Model/Event.php:418
+#: include/text.php:976 src/Model/Event.php:419
 msgid "November"
 msgstr "November"
 
-#: include/text.php:976 src/Model/Event.php:419
+#: include/text.php:976 src/Model/Event.php:420
 msgid "December"
 msgstr "Dezember"
 
-#: include/text.php:990 src/Model/Event.php:380
+#: include/text.php:990 src/Model/Event.php:381
 msgid "Mon"
 msgstr "Mo"
 
-#: include/text.php:990 src/Model/Event.php:381
+#: include/text.php:990 src/Model/Event.php:382
 msgid "Tue"
 msgstr "Di"
 
-#: include/text.php:990 src/Model/Event.php:382
+#: include/text.php:990 src/Model/Event.php:383
 msgid "Wed"
 msgstr "Mi"
 
-#: include/text.php:990 src/Model/Event.php:383
+#: include/text.php:990 src/Model/Event.php:384
 msgid "Thu"
 msgstr "Do"
 
-#: include/text.php:990 src/Model/Event.php:384
+#: include/text.php:990 src/Model/Event.php:385
 msgid "Fri"
 msgstr "Fr"
 
-#: include/text.php:990 src/Model/Event.php:385
+#: include/text.php:990 src/Model/Event.php:386
 msgid "Sat"
 msgstr "Sa"
 
-#: include/text.php:990 src/Model/Event.php:379
+#: include/text.php:990 src/Model/Event.php:380
 msgid "Sun"
 msgstr "So"
 
-#: include/text.php:993 src/Model/Event.php:395
+#: include/text.php:993 src/Model/Event.php:396
 msgid "Jan"
 msgstr "Jan"
 
-#: include/text.php:993 src/Model/Event.php:396
+#: include/text.php:993 src/Model/Event.php:397
 msgid "Feb"
 msgstr "Feb"
 
-#: include/text.php:993 src/Model/Event.php:397
+#: include/text.php:993 src/Model/Event.php:398
 msgid "Mar"
 msgstr "März"
 
-#: include/text.php:993 src/Model/Event.php:398
+#: include/text.php:993 src/Model/Event.php:399
 msgid "Apr"
 msgstr "Apr"
 
-#: include/text.php:993 src/Model/Event.php:401
+#: include/text.php:993 src/Model/Event.php:402
 msgid "Jul"
 msgstr "Juli"
 
-#: include/text.php:993 src/Model/Event.php:402
+#: include/text.php:993 src/Model/Event.php:403
 msgid "Aug"
 msgstr "Aug"
 
@@ -1520,15 +1520,15 @@ msgstr "Aug"
 msgid "Sep"
 msgstr "Sep"
 
-#: include/text.php:993 src/Model/Event.php:404
+#: include/text.php:993 src/Model/Event.php:405
 msgid "Oct"
 msgstr "Okt"
 
-#: include/text.php:993 src/Model/Event.php:405
+#: include/text.php:993 src/Model/Event.php:406
 msgid "Nov"
 msgstr "Nov"
 
-#: include/text.php:993 src/Model/Event.php:406
+#: include/text.php:993 src/Model/Event.php:407
 msgid "Dec"
 msgstr "Dez"
 
@@ -1537,7 +1537,7 @@ msgstr "Dez"
 msgid "Content warning: %s"
 msgstr "Inhaltswarnung: %s"
 
-#: include/text.php:1204 mod/videos.php:375
+#: include/text.php:1204 mod/videos.php:376
 msgid "View Video"
 msgstr "Video ansehen"
 
@@ -1557,7 +1557,7 @@ msgstr "Auf separater Seite ansehen"
 msgid "view on separate page"
 msgstr "auf separater Seite ansehen"
 
-#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:609
+#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:616
 msgid "link to source"
 msgstr "Link zum Originalbeitrag"
 
@@ -1579,14 +1579,14 @@ msgstr "Beitrag"
 msgid "Item filed"
 msgstr "Beitrag abgelegt"
 
-#: include/api.php:1138
+#: include/api.php:1140
 #, php-format
 msgid "Daily posting limit of %d post reached. The post was rejected."
 msgid_plural "Daily posting limit of %d posts reached. The post was rejected."
 msgstr[0] "Das tägliche Limit von %d Beitrag wurde erreicht. Die Nachricht wurde verworfen."
 msgstr[1] "Das tägliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen."
 
-#: include/api.php:1152
+#: include/api.php:1154
 #, php-format
 msgid "Weekly posting limit of %d post reached. The post was rejected."
 msgid_plural ""
@@ -1594,16 +1594,16 @@ msgid_plural ""
 msgstr[0] "Das wöchentliche Limit von %d Beitrag wurde erreicht. Die Nachricht wurde verworfen."
 msgstr[1] "Das wöchentliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen."
 
-#: include/api.php:1166
+#: include/api.php:1168
 #, php-format
 msgid "Monthly posting limit of %d post reached. The post was rejected."
 msgstr "Das monatliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen."
 
-#: include/api.php:4233 mod/profile_photo.php:84 mod/profile_photo.php:93
+#: include/api.php:4240 mod/profile_photo.php:84 mod/profile_photo.php:93
 #: mod/profile_photo.php:102 mod/profile_photo.php:211
 #: mod/profile_photo.php:300 mod/profile_photo.php:310 mod/photos.php:90
-#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1169
-#: mod/photos.php:1186 mod/photos.php:1678 src/Model/User.php:595
+#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1171
+#: mod/photos.php:1188 mod/photos.php:1680 src/Model/User.php:595
 #: src/Model/User.php:603 src/Model/User.php:611
 msgid "Profile Photos"
 msgstr "Profilbilder"
@@ -1617,7 +1617,7 @@ msgid "Contact update failed."
 msgstr "Konnte den Kontakt nicht aktualisieren."
 
 #: mod/crepair.php:112 mod/redir.php:29 mod/redir.php:127
-#: mod/dfrn_confirm.php:127 mod/fsuggest.php:30 mod/fsuggest.php:96
+#: mod/dfrn_confirm.php:128 mod/fsuggest.php:30 mod/fsuggest.php:96
 msgid "Contact not found."
 msgstr "Kontakt nicht gefunden."
 
@@ -1758,144 +1758,144 @@ msgstr "Betreff:"
 msgid "Your message:"
 msgstr "Deine Nachricht:"
 
-#: mod/lockview.php:42 mod/lockview.php:50
+#: mod/lockview.php:46 mod/lockview.php:57
 msgid "Remote privacy information not available."
 msgstr "Entfernte Privatsphäreneinstellungen nicht verfügbar."
 
-#: mod/lockview.php:59
+#: mod/lockview.php:66
 msgid "Visible to:"
 msgstr "Sichtbar für:"
 
-#: mod/install.php:100
+#: mod/install.php:98
 msgid "Friendica Communications Server - Setup"
 msgstr "Friendica-Server für soziale Netzwerke – Setup"
 
-#: mod/install.php:106
+#: mod/install.php:104
 msgid "Could not connect to database."
 msgstr "Verbindung zur Datenbank gescheitert."
 
-#: mod/install.php:110
+#: mod/install.php:108
 msgid "Could not create table."
 msgstr "Tabelle konnte nicht angelegt werden."
 
-#: mod/install.php:116
+#: mod/install.php:114
 msgid "Your Friendica site database has been installed."
 msgstr "Die Datenbank Deiner Friendicaseite wurde installiert."
 
-#: mod/install.php:121
+#: mod/install.php:119
 msgid ""
 "You may need to import the file \"database.sql\" manually using phpmyadmin "
 "or mysql."
 msgstr "Möglicherweise musst Du die Datei \"database.sql\" manuell mit phpmyadmin oder mysql importieren."
 
-#: mod/install.php:122 mod/install.php:166 mod/install.php:274
+#: mod/install.php:120 mod/install.php:164 mod/install.php:272
 msgid "Please see the file \"INSTALL.txt\"."
 msgstr "Lies bitte die \"INSTALL.txt\"."
 
-#: mod/install.php:134
+#: mod/install.php:132
 msgid "Database already in use."
 msgstr "Die Datenbank wird bereits verwendet."
 
-#: mod/install.php:163
+#: mod/install.php:161
 msgid "System check"
 msgstr "Systemtest"
 
-#: mod/install.php:167 mod/cal.php:279 mod/events.php:394
+#: mod/install.php:165 mod/cal.php:279 mod/events.php:395
 msgid "Next"
 msgstr "Nächste"
 
-#: mod/install.php:168
+#: mod/install.php:166
 msgid "Check again"
 msgstr "Noch einmal testen"
 
-#: mod/install.php:187
+#: mod/install.php:185
 msgid "Database connection"
 msgstr "Datenbankverbindung"
 
-#: mod/install.php:188
+#: mod/install.php:186
 msgid ""
 "In order to install Friendica we need to know how to connect to your "
 "database."
 msgstr "Um Friendica installieren zu können, müssen wir wissen, wie wir mit Deiner Datenbank Kontakt aufnehmen können."
 
-#: mod/install.php:189
+#: mod/install.php:187
 msgid ""
 "Please contact your hosting provider or site administrator if you have "
 "questions about these settings."
 msgstr "Bitte kontaktiere den Hosting Provider oder den Administrator der Seite, falls Du Fragen zu diesen Einstellungen haben solltest."
 
-#: mod/install.php:190
+#: mod/install.php:188
 msgid ""
 "The database you specify below should already exist. If it does not, please "
 "create it before continuing."
 msgstr "Die Datenbank, die Du unten angibst, sollte bereits existieren. Ist dies noch nicht der Fall, erzeuge sie bitte bevor Du mit der Installation fortfährst."
 
-#: mod/install.php:194
+#: mod/install.php:192
 msgid "Database Server Name"
 msgstr "Datenbank-Server"
 
-#: mod/install.php:195
+#: mod/install.php:193
 msgid "Database Login Name"
 msgstr "Datenbank-Nutzer"
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "Database Login Password"
 msgstr "Datenbank-Passwort"
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "For security reasons the password must not be empty"
 msgstr "Aus Sicherheitsgründen darf das Passwort nicht leer sein."
 
-#: mod/install.php:197
+#: mod/install.php:195
 msgid "Database Name"
 msgstr "Datenbank-Name"
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid "Site administrator email address"
 msgstr "E-Mail-Adresse des Administrators"
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid ""
 "Your account email address must match this in order to use the web admin "
 "panel."
 msgstr "Die E-Mail-Adresse, die in Deinem Friendica-Account eingetragen ist, muss mit dieser Adresse übereinstimmen, damit Du das Admin-Panel benutzen kannst."
 
-#: mod/install.php:200 mod/install.php:238
+#: mod/install.php:198 mod/install.php:236
 msgid "Please select a default timezone for your website"
 msgstr "Bitte wähle die Standardzeitzone Deiner Webseite"
 
-#: mod/install.php:225
+#: mod/install.php:223
 msgid "Site settings"
 msgstr "Server-Einstellungen"
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid "System Language:"
 msgstr "Systemsprache:"
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid ""
 "Set the default language for your Friendica installation interface and to "
 "send emails."
 msgstr "Wähle die Standardsprache für deine Friendica-Installations-Oberfläche und den E-Mail-Versand"
 
-#: mod/install.php:255
+#: mod/install.php:253
 msgid ""
 "The database configuration file \"config/local.ini.php\" could not be "
 "written. Please use the enclosed text to create a configuration file in your"
 " web server root."
 msgstr "Die Datenbankkonfigurationsdatei \"config/local.ini.php\" konnte nicht erstellt werden. Um eine Konfigurationsdatei in Ihrem Webserver-Verzeichnis zu erstellen, Gehen Sie wie folgt vor."
 
-#: mod/install.php:272
+#: mod/install.php:270
 msgid "<h1>What next</h1>"
 msgstr "<h1>Wie geht es weiter?</h1>"
 
-#: mod/install.php:273
+#: mod/install.php:271
 msgid ""
 "IMPORTANT: You will need to [manually] setup a scheduled task for the "
 "worker."
 msgstr "Wichtig: Du musst [manuell] einen Cronjob (o.ä.) für den Worker einrichten."
 
-#: mod/install.php:276
+#: mod/install.php:274
 #, php-format
 msgid ""
 "Go to your new Friendica node <a href=\"%s/register\">registration page</a> "
@@ -1903,83 +1903,83 @@ msgid ""
 " administrator email. This will allow you to enter the site admin panel."
 msgstr "Du solltest nun die Seite zur <a href=\"%s/register\">Nutzerregistrierung</a> deiner neuen Friendica Instanz besuchen und einen neuen Nutzer einrichten. Bitte denke daran die selbe E-Mail Adresse anzugeben, die du auch als Administrator E-Mail angegeben hast, damit du das Admin-Panel verwenden kannst."
 
-#: mod/dfrn_confirm.php:72 mod/profiles.php:38 mod/profiles.php:148
+#: mod/dfrn_confirm.php:73 mod/profiles.php:38 mod/profiles.php:148
 #: mod/profiles.php:193 mod/profiles.php:523
 msgid "Profile not found."
 msgstr "Profil nicht gefunden."
 
-#: mod/dfrn_confirm.php:128
+#: mod/dfrn_confirm.php:129
 msgid ""
 "This may occasionally happen if contact was requested by both persons and it"
 " has already been approved."
 msgstr "Das kann passieren, wenn sich zwei Kontakte gegenseitig eingeladen haben und bereits einer angenommen wurde."
 
-#: mod/dfrn_confirm.php:238
+#: mod/dfrn_confirm.php:239
 msgid "Response from remote site was not understood."
 msgstr "Antwort der Gegenstelle unverständlich."
 
-#: mod/dfrn_confirm.php:245 mod/dfrn_confirm.php:251
+#: mod/dfrn_confirm.php:246 mod/dfrn_confirm.php:252
 msgid "Unexpected response from remote site: "
 msgstr "Unerwartete Antwort der Gegenstelle: "
 
-#: mod/dfrn_confirm.php:260
+#: mod/dfrn_confirm.php:261
 msgid "Confirmation completed successfully."
 msgstr "Bestätigung erfolgreich abgeschlossen."
 
-#: mod/dfrn_confirm.php:272
+#: mod/dfrn_confirm.php:273
 msgid "Temporary failure. Please wait and try again."
 msgstr "Zeitweiser Fehler. Bitte warte einige Momente und versuche es dann noch einmal."
 
-#: mod/dfrn_confirm.php:275
+#: mod/dfrn_confirm.php:276
 msgid "Introduction failed or was revoked."
 msgstr "Kontaktanfrage schlug fehl oder wurde zurückgezogen."
 
-#: mod/dfrn_confirm.php:280
+#: mod/dfrn_confirm.php:281
 msgid "Remote site reported: "
 msgstr "Gegenstelle meldet: "
 
-#: mod/dfrn_confirm.php:392
+#: mod/dfrn_confirm.php:382
 msgid "Unable to set contact photo."
 msgstr "Konnte das Bild des Kontakts nicht speichern."
 
-#: mod/dfrn_confirm.php:450
+#: mod/dfrn_confirm.php:444
 #, php-format
 msgid "No user record found for '%s' "
 msgstr "Für '%s' wurde kein Nutzer gefunden"
 
-#: mod/dfrn_confirm.php:460
+#: mod/dfrn_confirm.php:454
 msgid "Our site encryption key is apparently messed up."
 msgstr "Der Verschlüsselungsschlüssel unserer Seite ist anscheinend nicht in Ordnung."
 
-#: mod/dfrn_confirm.php:471
+#: mod/dfrn_confirm.php:465
 msgid "Empty site URL was provided or URL could not be decrypted by us."
 msgstr "Leere URL für die Seite erhalten oder die URL konnte nicht entschlüsselt werden."
 
-#: mod/dfrn_confirm.php:487
+#: mod/dfrn_confirm.php:481
 msgid "Contact record was not found for you on our site."
 msgstr "Für diesen Kontakt wurde auf unserer Seite kein Eintrag gefunden."
 
-#: mod/dfrn_confirm.php:501
+#: mod/dfrn_confirm.php:495
 #, php-format
 msgid "Site public key not available in contact record for URL %s."
 msgstr "Die Kontaktdaten für URL %s enthalten keinen Public Key für den Server."
 
-#: mod/dfrn_confirm.php:517
+#: mod/dfrn_confirm.php:511
 msgid ""
 "The ID provided by your system is a duplicate on our system. It should work "
 "if you try again."
 msgstr "Die ID, die uns Dein System angeboten hat, ist hier bereits vergeben. Bitte versuche es noch einmal."
 
-#: mod/dfrn_confirm.php:528
+#: mod/dfrn_confirm.php:522
 msgid "Unable to set your contact credentials on our system."
 msgstr "Deine Kontaktreferenzen konnten nicht in unserem System gespeichert werden."
 
-#: mod/dfrn_confirm.php:584
+#: mod/dfrn_confirm.php:578
 msgid "Unable to update your contact profile details on our system"
 msgstr "Die Updates für Dein Profil konnten nicht gespeichert werden"
 
-#: mod/dfrn_confirm.php:614 mod/dfrn_request.php:561
-#: src/Model/Contact.php:1891
+#: mod/dfrn_confirm.php:608 mod/dfrn_request.php:561
+#: src/Model/Contact.php:1909
 msgid "[Name Withheld]"
 msgstr "[Name unterdrückt]"
 
@@ -1994,7 +1994,7 @@ msgid "Forum Search - %s"
 msgstr "Forensuche - %s"
 
 #: mod/dirfind.php:221 mod/match.php:105 mod/suggest.php:104
-#: mod/allfriends.php:92 src/Model/Profile.php:292 src/Content/Widget.php:37
+#: mod/allfriends.php:92 src/Model/Profile.php:305 src/Content/Widget.php:37
 msgid "Connect"
 msgstr "Verbinden"
 
@@ -2026,8 +2026,8 @@ msgstr "Video Löschen"
 
 #: mod/videos.php:198 mod/webfinger.php:16 mod/directory.php:42
 #: mod/search.php:105 mod/search.php:111 mod/viewcontacts.php:48
-#: mod/display.php:194 mod/dfrn_request.php:599 mod/probe.php:13
-#: mod/community.php:28 mod/photos.php:945
+#: mod/display.php:203 mod/dfrn_request.php:599 mod/probe.php:13
+#: mod/community.php:28 mod/photos.php:947
 msgid "Public access denied."
 msgstr "Öffentlicher Zugriff verweigert."
 
@@ -2035,19 +2035,19 @@ msgstr "Öffentlicher Zugriff verweigert."
 msgid "No videos selected"
 msgstr "Keine Videos  ausgewählt"
 
-#: mod/videos.php:307 mod/photos.php:1050
+#: mod/videos.php:307 mod/photos.php:1052
 msgid "Access to this item is restricted."
 msgstr "Zugriff zu diesem Eintrag wurde eingeschränkt."
 
-#: mod/videos.php:382 mod/photos.php:1699
+#: mod/videos.php:383 mod/photos.php:1701
 msgid "View Album"
 msgstr "Album betrachten"
 
-#: mod/videos.php:390
+#: mod/videos.php:391
 msgid "Recent Videos"
 msgstr "Neueste Videos"
 
-#: mod/videos.php:392
+#: mod/videos.php:393
 msgid "Upload New Videos"
 msgstr "Neues Video hochladen"
 
@@ -2055,27 +2055,27 @@ msgstr "Neues Video hochladen"
 msgid "Only logged in users are permitted to perform a probing."
 msgstr "Nur eingeloggten Benutzern ist das Untersuchen von Adressen gestattet."
 
-#: mod/directory.php:151 mod/notifications.php:253 mod/contacts.php:680
-#: mod/events.php:521 src/Model/Event.php:66 src/Model/Event.php:93
-#: src/Model/Event.php:430 src/Model/Event.php:915 src/Model/Profile.php:417
+#: mod/directory.php:151 mod/notifications.php:248 mod/contacts.php:681
+#: mod/events.php:548 src/Model/Event.php:67 src/Model/Event.php:94
+#: src/Model/Event.php:431 src/Model/Event.php:922 src/Model/Profile.php:430
 msgid "Location:"
 msgstr "Ort:"
 
-#: mod/directory.php:156 mod/notifications.php:259 src/Model/Profile.php:420
-#: src/Model/Profile.php:732
+#: mod/directory.php:156 mod/notifications.php:254 src/Model/Profile.php:433
+#: src/Model/Profile.php:745
 msgid "Gender:"
 msgstr "Geschlecht:"
 
-#: mod/directory.php:157 src/Model/Profile.php:421 src/Model/Profile.php:756
+#: mod/directory.php:157 src/Model/Profile.php:434 src/Model/Profile.php:769
 msgid "Status:"
 msgstr "Status:"
 
-#: mod/directory.php:158 src/Model/Profile.php:422 src/Model/Profile.php:773
+#: mod/directory.php:158 src/Model/Profile.php:435 src/Model/Profile.php:786
 msgid "Homepage:"
 msgstr "Homepage:"
 
-#: mod/directory.php:159 mod/notifications.php:255 mod/contacts.php:684
-#: src/Model/Profile.php:423 src/Model/Profile.php:793
+#: mod/directory.php:159 mod/notifications.php:250 mod/contacts.php:685
+#: src/Model/Profile.php:436 src/Model/Profile.php:806
 msgid "About:"
 msgstr "Über:"
 
@@ -2115,7 +2115,7 @@ msgstr "jeder"
 msgid "Account"
 msgstr "Nutzerkonto"
 
-#: mod/settings.php:64 src/Model/Profile.php:372 src/Content/Nav.php:210
+#: mod/settings.php:64 src/Model/Profile.php:385 src/Content/Nav.php:210
 msgid "Profiles"
 msgstr "Profile"
 
@@ -2155,7 +2155,7 @@ msgstr "Konto löschen"
 msgid "Missing some important data!"
 msgstr "Wichtige Daten fehlen!"
 
-#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:848
+#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:851
 msgid "Update"
 msgstr "Aktualisierungen"
 
@@ -2845,7 +2845,7 @@ msgstr "Passwort:"
 msgid "Basic Settings"
 msgstr "Grundeinstellungen"
 
-#: mod/settings.php:1204 src/Model/Profile.php:725
+#: mod/settings.php:1204 src/Model/Profile.php:738
 msgid "Full Name:"
 msgstr "Kompletter Name:"
 
@@ -2895,11 +2895,11 @@ msgstr "Standard-Zugriffsrechte für Beiträge"
 msgid "(click to open/close)"
 msgstr "(klicke zum öffnen/schließen)"
 
-#: mod/settings.php:1224 mod/photos.php:1126 mod/photos.php:1456
+#: mod/settings.php:1224 mod/photos.php:1128 mod/photos.php:1458
 msgid "Show to Groups"
 msgstr "Zeige den Gruppen"
 
-#: mod/settings.php:1225 mod/photos.php:1127 mod/photos.php:1457
+#: mod/settings.php:1225 mod/photos.php:1129 mod/photos.php:1459
 msgid "Show to Contacts"
 msgstr "Zeige den Kontakten"
 
@@ -3048,7 +3048,7 @@ msgstr "Keine Ergebnisse."
 msgid "Items tagged with: %s"
 msgstr "Beiträge die mit %s getaggt sind"
 
-#: mod/search.php:248 mod/contacts.php:841
+#: mod/search.php:248 mod/contacts.php:844
 #, php-format
 msgid "Results for: %s"
 msgstr "Ergebnisse für: %s"
@@ -3057,7 +3057,7 @@ msgstr "Ergebnisse für: %s"
 msgid "No contacts in common."
 msgstr "Keine gemeinsamen Kontakte."
 
-#: mod/common.php:142 mod/contacts.php:916
+#: mod/common.php:142 mod/contacts.php:919
 msgid "Common Friends"
 msgstr "Gemeinsame Kontakte"
 
@@ -3065,7 +3065,11 @@ msgstr "Gemeinsame Kontakte"
 msgid "Login"
 msgstr "Anmeldung"
 
-#: mod/bookmarklet.php:52
+#: mod/bookmarklet.php:34
+msgid "Bad Request"
+msgstr "Ungültige Anfrage"
+
+#: mod/bookmarklet.php:56
 msgid "The post was created"
 msgstr "Der Beitrag wurde angelegt"
 
@@ -3215,7 +3219,7 @@ msgstr "Gruppen Name bearbeiten"
 msgid "Members"
 msgstr "Mitglieder"
 
-#: mod/group.php:246 mod/contacts.php:739
+#: mod/group.php:246 mod/contacts.php:742
 msgid "All Contacts"
 msgstr "Alle Kontakte"
 
@@ -3339,46 +3343,42 @@ msgstr "Zugriff verweigert."
 msgid "No contacts."
 msgstr "Keine Kontakte."
 
-#: mod/viewcontacts.php:106 mod/contacts.php:639 mod/contacts.php:1052
+#: mod/viewcontacts.php:106 mod/contacts.php:640 mod/contacts.php:1055
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr "Besuche %ss Profil [%s]"
 
-#: mod/unfollow.php:36
-msgid "Contact wasn't found or can't be unfollowed."
-msgstr "Der Kontakt konnte nicht gefunden oder nicht entfolgt werden."
+#: mod/unfollow.php:38 mod/unfollow.php:88
+msgid "You aren't following this contact."
+msgstr "Du folgst diesem Kontakt."
 
-#: mod/unfollow.php:49
-msgid "Contact unfollowed"
-msgstr "Kontakt wird nicht mehr gefolgt"
-
-#: mod/unfollow.php:67 mod/dfrn_request.php:654 mod/follow.php:62
-msgid "Submit Request"
-msgstr "Anfrage abschicken"
-
-#: mod/unfollow.php:76
-msgid "You aren't a friend of this contact."
-msgstr "Du hast keine beidseitige Freundschaft mit diesem Kontakt."
-
-#: mod/unfollow.php:82
+#: mod/unfollow.php:44 mod/unfollow.php:94
 msgid "Unfollowing is currently not supported by your network."
 msgstr "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt."
 
-#: mod/unfollow.php:103 mod/contacts.php:601
+#: mod/unfollow.php:65
+msgid "Contact unfollowed"
+msgstr "Kontakt wird nicht mehr gefolgt"
+
+#: mod/unfollow.php:113 mod/contacts.php:607
 msgid "Disconnect/Unfollow"
 msgstr "Verbindung lösen/Nicht mehr folgen"
 
-#: mod/unfollow.php:116 mod/dfrn_request.php:652 mod/follow.php:157
+#: mod/unfollow.php:126 mod/dfrn_request.php:652 mod/follow.php:157
 msgid "Your Identity Address:"
 msgstr "Adresse Deines Profils:"
 
-#: mod/unfollow.php:125 mod/notifications.php:174 mod/notifications.php:263
-#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:676 mod/follow.php:166
+#: mod/unfollow.php:129 mod/dfrn_request.php:654 mod/follow.php:62
+msgid "Submit Request"
+msgstr "Anfrage abschicken"
+
+#: mod/unfollow.php:135 mod/notifications.php:174 mod/notifications.php:258
+#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:677 mod/follow.php:166
 msgid "Profile URL"
 msgstr "Profil URL"
 
-#: mod/unfollow.php:135 mod/contacts.php:888 mod/follow.php:189
-#: src/Model/Profile.php:878
+#: mod/unfollow.php:145 mod/contacts.php:891 mod/follow.php:189
+#: src/Model/Profile.php:891
 msgid "Status Messages and Posts"
 msgstr "Statusnachrichten und Beiträge"
 
@@ -3412,7 +3412,7 @@ msgstr "Deine Registrierung konnte nicht verarbeitet werden."
 msgid "Your registration is pending approval by the site owner."
 msgstr "Deine Registrierung muss noch vom Betreiber der Seite freigegeben werden."
 
-#: mod/register.php:191 mod/uimport.php:55
+#: mod/register.php:191 mod/uimport.php:37
 msgid ""
 "This site has exceeded the number of allowed daily account registrations. "
 "Please try again tomorrow."
@@ -3487,7 +3487,7 @@ msgstr "Spitznamen wählen: "
 msgid "Register"
 msgstr "Registrieren"
 
-#: mod/register.php:287 mod/uimport.php:70
+#: mod/register.php:287 mod/uimport.php:52
 msgid "Import"
 msgstr "Import"
 
@@ -3508,37 +3508,45 @@ msgstr "Hinweis: Dieser Knoten enthält explizit Inhalte für Erwachsene"
 msgid "Invalid request identifier."
 msgstr "Invalid request identifier."
 
-#: mod/notifications.php:44 mod/notifications.php:183
-#: mod/notifications.php:235 mod/message.php:114
+#: mod/notifications.php:44 mod/notifications.php:182
+#: mod/notifications.php:230 mod/message.php:114
 msgid "Discard"
 msgstr "Verwerfen"
 
-#: mod/notifications.php:57 mod/notifications.php:182
-#: mod/notifications.php:271 mod/contacts.php:658 mod/contacts.php:850
-#: mod/contacts.php:1113
+#: mod/notifications.php:57 mod/notifications.php:181
+#: mod/notifications.php:266 mod/contacts.php:659 mod/contacts.php:853
+#: mod/contacts.php:1116
 msgid "Ignore"
 msgstr "Ignorieren"
 
-#: mod/notifications.php:93 src/Content/Nav.php:191
+#: mod/notifications.php:90 src/Content/Nav.php:191
 msgid "Notifications"
 msgstr "Benachrichtigungen"
 
-#: mod/notifications.php:101
+#: mod/notifications.php:102
 msgid "Network Notifications"
 msgstr "Netzwerk Benachrichtigungen"
 
-#: mod/notifications.php:106 mod/notify.php:81
+#: mod/notifications.php:107 mod/notify.php:81
 msgid "System Notifications"
 msgstr "Systembenachrichtigungen"
 
-#: mod/notifications.php:111
+#: mod/notifications.php:112
 msgid "Personal Notifications"
 msgstr "Persönliche Benachrichtigungen"
 
-#: mod/notifications.php:116
+#: mod/notifications.php:117
 msgid "Home Notifications"
 msgstr "Pinnwand Benachrichtigungen"
 
+#: mod/notifications.php:137
+msgid "Show unread"
+msgstr "Ungelesene anzeigen"
+
+#: mod/notifications.php:137
+msgid "Show all"
+msgstr "Alle anzeigen"
+
 #: mod/notifications.php:148
 msgid "Show Ignored Requests"
 msgstr "Zeige ignorierte Anfragen"
@@ -3547,7 +3555,7 @@ msgstr "Zeige ignorierte Anfragen"
 msgid "Hide Ignored Requests"
 msgstr "Verberge ignorierte Anfragen"
 
-#: mod/notifications.php:161 mod/notifications.php:243
+#: mod/notifications.php:161 mod/notifications.php:238
 msgid "Notification type:"
 msgstr "Art der Benachrichtigung:"
 
@@ -3555,85 +3563,77 @@ msgstr "Art der Benachrichtigung:"
 msgid "Suggested by:"
 msgstr "Vorgeschlagen von:"
 
-#: mod/notifications.php:176 mod/notifications.php:260 mod/contacts.php:666
+#: mod/notifications.php:176 mod/notifications.php:255 mod/contacts.php:667
 msgid "Hide this contact from others"
 msgstr "Verbirg diesen Kontakt vor Anderen"
 
-#: mod/notifications.php:179 mod/notifications.php:269 mod/admin.php:1904
+#: mod/notifications.php:178 mod/notifications.php:264 mod/admin.php:1904
 msgid "Approve"
 msgstr "Genehmigen"
 
-#: mod/notifications.php:202
+#: mod/notifications.php:198
 msgid "Claims to be known to you: "
 msgstr "Behauptet Dich zu kennen: "
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "yes"
 msgstr "ja"
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "no"
 msgstr "nein"
 
-#: mod/notifications.php:204 mod/notifications.php:209
+#: mod/notifications.php:200 mod/notifications.php:204
 msgid "Shall your connection be bidirectional or not?"
 msgstr "Soll die Verbindung beidseitig sein oder nicht?"
 
-#: mod/notifications.php:205 mod/notifications.php:210
+#: mod/notifications.php:201 mod/notifications.php:205
 #, php-format
 msgid ""
 "Accepting %s as a friend allows %s to subscribe to your posts, and you will "
 "also receive updates from them in your news feed."
 msgstr "Akzeptierst du %s als Kontakt, erlaubst du damit das Lesen deiner Beiträge und abonnierst selbst auch die Beiträge von %s."
 
-#: mod/notifications.php:206
+#: mod/notifications.php:202
 #, php-format
 msgid ""
 "Accepting %s as a subscriber allows them to subscribe to your posts, but you"
 " will not receive updates from them in your news feed."
 msgstr "Wenn du %s als Abonnent akzeptierst, erlaubst du damit das Lesen deiner Beiträge, wirst aber selbst die Beiträge der anderen Seite nicht erhalten."
 
-#: mod/notifications.php:211
+#: mod/notifications.php:206
 #, php-format
 msgid ""
 "Accepting %s as a sharer allows them to subscribe to your posts, but you "
 "will not receive updates from them in your news feed."
 msgstr "Wenn du %s als Teilenden akzeptierst, erlaubst du damit das Lesen deiner Beiträge, wirst aber selbst die Beiträge der anderen Seite nicht erhalten."
 
-#: mod/notifications.php:222
+#: mod/notifications.php:217
 msgid "Friend"
 msgstr "Kontakt"
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Sharer"
 msgstr "Teilenden"
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Subscriber"
 msgstr "Abonnent"
 
-#: mod/notifications.php:257 mod/contacts.php:686 mod/follow.php:177
-#: src/Model/Profile.php:781
+#: mod/notifications.php:252 mod/contacts.php:687 mod/follow.php:177
+#: src/Model/Profile.php:794
 msgid "Tags:"
 msgstr "Tags:"
 
-#: mod/notifications.php:266 mod/contacts.php:76 src/Model/Profile.php:520
+#: mod/notifications.php:261 mod/contacts.php:81 src/Model/Profile.php:533
 msgid "Network:"
 msgstr "Netzwerk:"
 
-#: mod/notifications.php:280
+#: mod/notifications.php:274
 msgid "No introductions."
 msgstr "Keine Kontaktanfragen."
 
-#: mod/notifications.php:318
-msgid "Show unread"
-msgstr "Ungelesene anzeigen"
-
-#: mod/notifications.php:318
-msgid "Show all"
-msgstr "Alle anzeigen"
-
-#: mod/notifications.php:323
+#: mod/notifications.php:308
 #, php-format
 msgid "No more %s notifications."
 msgstr "Keine weiteren %s Benachrichtigungen"
@@ -3854,7 +3854,7 @@ msgid "On this server the following remote servers are blocked."
 msgstr "Auf diesem Server werden die folgenden entfernten Server blockiert."
 
 #: mod/friendica.php:130 mod/admin.php:363 mod/admin.php:381
-#: mod/dfrn_request.php:345 src/Model/Contact.php:1582
+#: mod/dfrn_request.php:345 src/Model/Contact.php:1593
 msgid "Blocked domain"
 msgstr "Blockierte Domain"
 
@@ -3862,7 +3862,7 @@ msgstr "Blockierte Domain"
 msgid "Reason for the block"
 msgstr "Begründung für die Blockierung"
 
-#: mod/display.php:303 mod/cal.php:144 mod/profile.php:175
+#: mod/display.php:312 mod/cal.php:144 mod/profile.php:185
 msgid "Access to this profile has been restricted."
 msgstr "Der Zugriff zu diesem Profil wurde eingeschränkt."
 
@@ -3872,13 +3872,13 @@ msgstr "Der Zugriff zu diesem Profil wurde eingeschränkt."
 msgid "Invalid request."
 msgstr "Ungültige Anfrage"
 
-#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:776
-#: mod/photos.php:779 mod/photos.php:808
+#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:778
+#: mod/photos.php:781 mod/photos.php:810
 #, php-format
 msgid "Image exceeds size limit of %s"
 msgstr "Bildgröße überschreitet das Limit von %s"
 
-#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:831
+#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:833
 msgid "Unable to process image."
 msgstr "Konnte das Bild nicht bearbeiten."
 
@@ -3887,7 +3887,7 @@ msgstr "Konnte das Bild nicht bearbeiten."
 msgid "Wall Photos"
 msgstr "Pinnwand-Bilder"
 
-#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:860
+#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:862
 msgid "Image upload failed."
 msgstr "Hochladen des Bildes gescheitert."
 
@@ -4194,79 +4194,91 @@ msgstr "\nDie Anmeldedaten sind die folgenden:\n\nAdresse der Seite: %1$s\nLogin
 msgid "Your password has been changed at %s"
 msgstr "Auf %s wurde Dein Passwort geändert"
 
-#: mod/babel.php:22
+#: mod/babel.php:24
 msgid "Source input"
 msgstr "Originaltext:"
 
-#: mod/babel.php:28
+#: mod/babel.php:30
 msgid "BBCode::toPlaintext"
 msgstr "BBCode::toPlaintext"
 
-#: mod/babel.php:34
+#: mod/babel.php:36
 msgid "BBCode::convert (raw HTML)"
 msgstr "BBCode::convert (pures HTML)"
 
-#: mod/babel.php:39
+#: mod/babel.php:41
 msgid "BBCode::convert"
 msgstr "BBCode::convert"
 
-#: mod/babel.php:45
+#: mod/babel.php:47
 msgid "BBCode::convert => HTML::toBBCode"
 msgstr "BBCode::convert => HTML::toBBCode"
 
-#: mod/babel.php:51
+#: mod/babel.php:53
 msgid "BBCode::toMarkdown"
 msgstr "BBCode::toMarkdown"
 
-#: mod/babel.php:57
+#: mod/babel.php:59
 msgid "BBCode::toMarkdown => Markdown::convert"
 msgstr "BBCode::toMarkdown => Markdown::convert"
 
-#: mod/babel.php:63
+#: mod/babel.php:65
 msgid "BBCode::toMarkdown => Markdown::toBBCode"
 msgstr "BBCode::toMarkdown => Markdown::toBBCode"
 
-#: mod/babel.php:69
+#: mod/babel.php:71
 msgid "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"
 msgstr "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"
 
-#: mod/babel.php:76
-msgid "Source input \\x28Diaspora format\\x29"
-msgstr "Original Text \\x28Diaspora Fromat\\x29"
+#: mod/babel.php:78
+msgid "Source input (Diaspora format)"
+msgstr "Originaltext (Diaspora Format): "
+
+#: mod/babel.php:84
+msgid "Markdown::convert (raw HTML)"
+msgstr "Markdown::convert (raw HTML)"
+
+#: mod/babel.php:89
+msgid "Markdown::convert"
+msgstr "Markdown::convert"
 
-#: mod/babel.php:82
+#: mod/babel.php:95
 msgid "Markdown::toBBCode"
 msgstr "Markdown::toBBCode"
 
-#: mod/babel.php:89
+#: mod/babel.php:102
 msgid "Raw HTML input"
 msgstr "Reine  HTML  Eingabe"
 
-#: mod/babel.php:94
+#: mod/babel.php:107
 msgid "HTML Input"
 msgstr "HTML Eingabe"
 
-#: mod/babel.php:100
+#: mod/babel.php:113
 msgid "HTML::toBBCode"
 msgstr "HTML::toBBCode"
 
-#: mod/babel.php:106
+#: mod/babel.php:119
+msgid "HTML::toMarkdown"
+msgstr "HTML::toMarkdown"
+
+#: mod/babel.php:125
 msgid "HTML::toPlaintext"
 msgstr "HTML::toPlaintext"
 
-#: mod/babel.php:114
+#: mod/babel.php:133
 msgid "Source text"
 msgstr "Quelltext"
 
-#: mod/babel.php:115
+#: mod/babel.php:134
 msgid "BBCode"
 msgstr "BBCode"
 
-#: mod/babel.php:116
+#: mod/babel.php:135
 msgid "Markdown"
 msgstr "Markdown"
 
-#: mod/babel.php:117
+#: mod/babel.php:136
 msgid "HTML"
 msgstr "HTML"
 
@@ -4527,13 +4539,13 @@ msgstr "Alle auswählen"
 msgid "select none"
 msgstr "Auswahl aufheben"
 
-#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Block"
 msgstr "Sperren"
 
-#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Unblock"
 msgstr "Entsperren"
 
@@ -4714,9 +4726,9 @@ msgstr "Die Konfiguration von Friendica befindet sich ab jetzt in der 'config/lo
 #: mod/admin.php:876
 #, php-format
 msgid ""
-"<a href=\"%s\">%s</a> is not reachable on your system. This is a servere "
-"configuration issue that prevents the communication.. See <a href=\"%s\">the"
-" installation page</a> for help."
+"<a href=\"%s\">%s</a> is not reachable on your system. This is a severe "
+"configuration issue that prevents server to server communication. See <a "
+"href=\"%s\">the installation page</a> for help."
 msgstr "<a href=\"%s\">%s</a> konnte von deinem System nicht aufgerufen werden. Dies deitet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere <a href=\"%s\">die Installations-Dokumentation</a> zum Beheben des Problems."
 
 #: mod/admin.php:882
@@ -4796,7 +4808,7 @@ msgid "Public postings from local users and the federated network"
 msgstr "Öffentliche Beiträge von lokalen Nutzern und aus dem föderalen Netzwerk"
 
 #: mod/admin.php:1353 mod/admin.php:1520 mod/admin.php:1530
-#: mod/contacts.php:577
+#: mod/contacts.php:583
 msgid "Disabled"
 msgstr "Deaktiviert"
 
@@ -4876,8 +4888,8 @@ msgstr "Datei hochladen"
 msgid "Policies"
 msgstr "Regeln"
 
-#: mod/admin.php:1431 mod/contacts.php:926 mod/events.php:535
-#: src/Model/Profile.php:852
+#: mod/admin.php:1431 mod/contacts.php:929 mod/events.php:562
+#: src/Model/Profile.php:865
 msgid "Advanced"
 msgstr "Erweitert"
 
@@ -5281,15 +5293,15 @@ msgid ""
 msgstr "Biete die eingebaute OStatus (iStatusNet, GNU Social, etc.) Unterstützung an. Jede Kommunikation in OStatus ist öffentlich, Privatsphäre Warnungen werden nur bei Bedarf angezeigt."
 
 #: mod/admin.php:1481
-msgid "Only import OStatus threads from our contacts"
-msgstr "Nur OStatus Konversationen unserer Kontakte importieren"
+msgid "Only import OStatus/ActivityPub threads from our contacts"
+msgstr "Nur OStatus/ActivityPub Konversationen unserer Kontakte importieren"
 
 #: mod/admin.php:1481
 msgid ""
-"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."
-msgstr "Normalerweise werden alle Inhalte von OStatus Kontakten importiert. Mit dieser Option werden nur solche Konversationen gespeichert, die von Kontakten der Nutzer dieses Knotens gestartet wurden."
+"Normally we import every content from our OStatus and ActivityPub contacts. "
+"With this option we only store threads that are started by a contact that is"
+" known on our system."
+msgstr "Normalerweise werden alle Inhalte von OStatus und ActivityPub Kontakten importiert. Mit dieser Option werden nur solche Konversationen gespeichert, die von Kontakten der Nutzer dieses Knotens gestartet wurden."
 
 #: mod/admin.php:1482
 msgid "OStatus support can only be enabled if threading is enabled."
@@ -6161,11 +6173,11 @@ msgstr "Es scheint so, als ob Du bereits mit %s in Kontakt stehst."
 msgid "Invalid profile URL."
 msgstr "Ungültige Profil-URL."
 
-#: mod/dfrn_request.php:339 src/Model/Contact.php:1577
+#: mod/dfrn_request.php:339 src/Model/Contact.php:1588
 msgid "Disallowed profile URL."
 msgstr "Nicht erlaubte Profil-URL."
 
-#: mod/dfrn_request.php:412 mod/contacts.php:235
+#: mod/dfrn_request.php:412 mod/contacts.php:241
 msgid "Failed to update contact record."
 msgstr "Aktualisierung der Kontaktdaten fehlgeschlagen."
 
@@ -6392,32 +6404,36 @@ msgstr "%s hat ein Update veröffentlicht."
 msgid "Help:"
 msgstr "Hilfe:"
 
-#: mod/uimport.php:72
+#: mod/uimport.php:28
+msgid "User imports on closed servers can only be done by an administrator."
+msgstr "Auf geschlossenen Servern können ausschließlich die Administratoren Benutzerkonten importieren."
+
+#: mod/uimport.php:54
 msgid "Move account"
 msgstr "Account umziehen"
 
-#: mod/uimport.php:73
+#: mod/uimport.php:55
 msgid "You can import an account from another Friendica server."
 msgstr "Du kannst einen Account von einem anderen Friendica Server importieren."
 
-#: mod/uimport.php:74
+#: mod/uimport.php:56
 msgid ""
 "You need to export your account from the old server and upload it here. We "
 "will recreate your old account here with all your contacts. We will try also"
 " to inform your friends that you moved here."
 msgstr "Du musst Deinen Account vom alten Server exportieren und hier hochladen. Wir stellen Deinen alten Account mit all Deinen Kontakten wieder her. Wir werden auch versuchen all Deine Kontakte darüber zu informieren, dass Du hierher umgezogen bist."
 
-#: mod/uimport.php:75
+#: mod/uimport.php:57
 msgid ""
 "This feature is experimental. We can't import contacts from the OStatus "
 "network (GNU Social/Statusnet) or from Diaspora"
 msgstr "Dieses Feature ist experimentell. Wir können keine Kontakte vom OStatus Netzwerk (GNU Social/Statusnet) oder von Diaspora importieren"
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid "Account file"
 msgstr "Account Datei"
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid ""
 "To export your account, go to \"Settings->Export your personal data\" and "
 "select \"Export account\""
@@ -6439,34 +6455,34 @@ msgstr "Sichtbar für"
 msgid "All Contacts (with secure profile access)"
 msgstr "Alle Kontakte (mit gesichertem Profilzugriff)"
 
-#: mod/cal.php:277 mod/events.php:391
+#: mod/cal.php:277 mod/events.php:392
 msgid "View"
 msgstr "Ansehen"
 
-#: mod/cal.php:278 mod/events.php:393
+#: mod/cal.php:278 mod/events.php:394
 msgid "Previous"
 msgstr "Vorherige"
 
-#: mod/cal.php:282 mod/events.php:399 src/Model/Event.php:421
+#: mod/cal.php:282 mod/events.php:400 src/Model/Event.php:422
 msgid "today"
 msgstr "Heute"
 
-#: mod/cal.php:283 mod/events.php:400 src/Util/Temporal.php:304
-#: src/Model/Event.php:422
+#: mod/cal.php:283 mod/events.php:401 src/Util/Temporal.php:304
+#: src/Model/Event.php:423
 msgid "month"
 msgstr "Monat"
 
-#: mod/cal.php:284 mod/events.php:401 src/Util/Temporal.php:305
-#: src/Model/Event.php:423
+#: mod/cal.php:284 mod/events.php:402 src/Util/Temporal.php:305
+#: src/Model/Event.php:424
 msgid "week"
 msgstr "Woche"
 
-#: mod/cal.php:285 mod/events.php:402 src/Util/Temporal.php:306
-#: src/Model/Event.php:424
+#: mod/cal.php:285 mod/events.php:403 src/Util/Temporal.php:306
+#: src/Model/Event.php:425
 msgid "day"
 msgstr "Tag"
 
-#: mod/cal.php:286 mod/events.php:403
+#: mod/cal.php:286 mod/events.php:404
 msgid "list"
 msgstr "Liste"
 
@@ -6499,19 +6515,19 @@ msgstr "Registrierung für %s wurde zurückgezogen"
 msgid "Please login."
 msgstr "Bitte melde Dich an."
 
-#: mod/editpost.php:26 mod/editpost.php:36
+#: mod/editpost.php:27 mod/editpost.php:42
 msgid "Item not found"
 msgstr "Beitrag nicht gefunden"
 
-#: mod/editpost.php:43
+#: mod/editpost.php:49
 msgid "Edit post"
 msgstr "Beitrag bearbeiten"
 
-#: mod/editpost.php:125 src/Core/ACL.php:304
+#: mod/editpost.php:131 src/Core/ACL.php:304
 msgid "CC: email addresses"
 msgstr "Cc: E-Mail-Addressen"
 
-#: mod/editpost.php:132 src/Core/ACL.php:305
+#: mod/editpost.php:138 src/Core/ACL.php:305
 msgid "Example: bob@example.com, mary@example.com"
 msgstr "Z.B.: bob@example.com, mary@example.com"
 
@@ -6548,21 +6564,21 @@ msgstr "Schlage %s einen Kontakt vor"
 msgid "System down for maintenance"
 msgstr "System zur Wartung abgeschaltet"
 
-#: mod/profile.php:38 src/Model/Profile.php:115
+#: mod/profile.php:39 src/Model/Profile.php:128
 msgid "Requested profile is not available."
 msgstr "Das angefragte Profil ist nicht vorhanden."
 
-#: mod/profile.php:79 mod/profile.php:82 src/Protocol/OStatus.php:1275
+#: mod/profile.php:89 mod/profile.php:92 src/Protocol/OStatus.php:1285
 #, php-format
 msgid "%s's timeline"
 msgstr "Timeline von %s"
 
-#: mod/profile.php:80 src/Protocol/OStatus.php:1276
+#: mod/profile.php:90 src/Protocol/OStatus.php:1286
 #, php-format
 msgid "%s's posts"
 msgstr "Beiträge von %s"
 
-#: mod/profile.php:81 src/Protocol/OStatus.php:1277
+#: mod/profile.php:91 src/Protocol/OStatus.php:1287
 #, php-format
 msgid "%s's comments"
 msgstr "Kommentare von %s"
@@ -6571,433 +6587,433 @@ msgstr "Kommentare von %s"
 msgid "No friends to display."
 msgstr "Keine Kontakte zum Anzeigen."
 
-#: mod/contacts.php:162
+#: mod/contacts.php:168
 #, php-format
 msgid "%d contact edited."
 msgid_plural "%d contacts edited."
 msgstr[0] "%d Kontakt bearbeitet."
 msgstr[1] "%d Kontakte bearbeitet."
 
-#: mod/contacts.php:189 mod/contacts.php:395
+#: mod/contacts.php:195 mod/contacts.php:401
 msgid "Could not access contact record."
 msgstr "Konnte nicht auf die Kontaktdaten zugreifen."
 
-#: mod/contacts.php:199
+#: mod/contacts.php:205
 msgid "Could not locate selected profile."
 msgstr "Konnte das ausgewählte Profil nicht finden."
 
-#: mod/contacts.php:233
+#: mod/contacts.php:239
 msgid "Contact updated."
 msgstr "Kontakt aktualisiert."
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been blocked"
 msgstr "Kontakt wurde blockiert"
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been unblocked"
 msgstr "Kontakt wurde wieder freigegeben"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been ignored"
 msgstr "Kontakt wurde ignoriert"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been unignored"
 msgstr "Kontakt wird nicht mehr ignoriert"
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been archived"
 msgstr "Kontakt wurde archiviert"
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been unarchived"
 msgstr "Kontakt wurde aus dem Archiv geholt"
 
-#: mod/contacts.php:460
+#: mod/contacts.php:466
 msgid "Drop contact"
 msgstr "Kontakt löschen"
 
-#: mod/contacts.php:463 mod/contacts.php:845
+#: mod/contacts.php:469 mod/contacts.php:848
 msgid "Do you really want to delete this contact?"
 msgstr "Möchtest Du wirklich diesen Kontakt löschen?"
 
-#: mod/contacts.php:481
+#: mod/contacts.php:487
 msgid "Contact has been removed."
 msgstr "Kontakt wurde entfernt."
 
-#: mod/contacts.php:518
+#: mod/contacts.php:524
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr "Du hast mit %s eine beidseitige Freundschaft"
 
-#: mod/contacts.php:523
+#: mod/contacts.php:529
 #, php-format
 msgid "You are sharing with %s"
 msgstr "Du teilst mit %s"
 
-#: mod/contacts.php:528
+#: mod/contacts.php:534
 #, php-format
 msgid "%s is sharing with you"
 msgstr "%s teilt mit Dir"
 
-#: mod/contacts.php:552
+#: mod/contacts.php:558
 msgid "Private communications are not available for this contact."
 msgstr "Private Kommunikation ist für diesen Kontakt nicht verfügbar."
 
-#: mod/contacts.php:554
+#: mod/contacts.php:560
 msgid "Never"
 msgstr "Niemals"
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was successful)"
 msgstr "(Aktualisierung war erfolgreich)"
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was not successful)"
 msgstr "(Aktualisierung war nicht erfolgreich)"
 
-#: mod/contacts.php:559 mod/contacts.php:1086
+#: mod/contacts.php:565 mod/contacts.php:1089
 msgid "Suggest friends"
 msgstr "Kontakte vorschlagen"
 
-#: mod/contacts.php:563
+#: mod/contacts.php:569
 #, php-format
 msgid "Network type: %s"
 msgstr "Netzwerktyp: %s"
 
-#: mod/contacts.php:568
+#: mod/contacts.php:574
 msgid "Communications lost with this contact!"
 msgstr "Verbindungen mit diesem Kontakt verloren!"
 
-#: mod/contacts.php:574
+#: mod/contacts.php:580
 msgid "Fetch further information for feeds"
 msgstr "Weitere Informationen zu Feeds holen"
 
-#: mod/contacts.php:576
+#: mod/contacts.php:582
 msgid ""
 "Fetch information like preview pictures, title and teaser from the feed "
 "item. You can activate this if the feed doesn't contain much text. Keywords "
 "are taken from the meta header in the feed item and are posted as hash tags."
 msgstr "Zusätzliche Informationen wie Vorschaubilder, Titel und Zusammenfassungen vom Feed-Eintrag laden. Du kannst diese Option aktivieren, wenn der Feed nicht all zu viel Text beinhaltet. Schlagwörter werden auf den Meta-Informationen des Feed-Headers bezogen und als Hash-Tags verwendet."
 
-#: mod/contacts.php:578
+#: mod/contacts.php:584
 msgid "Fetch information"
 msgstr "Beziehe Information"
 
-#: mod/contacts.php:579
+#: mod/contacts.php:585
 msgid "Fetch keywords"
 msgstr "Schlüsselwörter abrufen"
 
-#: mod/contacts.php:580
+#: mod/contacts.php:586
 msgid "Fetch information and keywords"
 msgstr "Beziehe Information und Schlüsselworte"
 
-#: mod/contacts.php:617
+#: mod/contacts.php:618
 msgid "Profile Visibility"
 msgstr "Profil-Sichtbarkeit"
 
-#: mod/contacts.php:618
+#: mod/contacts.php:619
 msgid "Contact Information / Notes"
 msgstr "Kontakt Informationen / Notizen"
 
-#: mod/contacts.php:619
+#: mod/contacts.php:620
 msgid "Contact Settings"
 msgstr "Kontakteinstellungen"
 
-#: mod/contacts.php:628
+#: mod/contacts.php:629
 msgid "Contact"
 msgstr "Kontakt"
 
-#: mod/contacts.php:632
+#: mod/contacts.php:633
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
 msgstr "Bitte wähle eines Deiner Profile das angezeigt werden soll, wenn %s Dein Profil aufruft."
 
-#: mod/contacts.php:634
+#: mod/contacts.php:635
 msgid "Their personal note"
 msgstr "Die persönliche Mitteilung"
 
-#: mod/contacts.php:636
+#: mod/contacts.php:637
 msgid "Edit contact notes"
 msgstr "Notizen zum Kontakt bearbeiten"
 
-#: mod/contacts.php:640
+#: mod/contacts.php:641
 msgid "Block/Unblock contact"
 msgstr "Kontakt blockieren/freischalten"
 
-#: mod/contacts.php:641
+#: mod/contacts.php:642
 msgid "Ignore contact"
 msgstr "Ignoriere den Kontakt"
 
-#: mod/contacts.php:642
+#: mod/contacts.php:643
 msgid "Repair URL settings"
 msgstr "URL Einstellungen reparieren"
 
-#: mod/contacts.php:643
+#: mod/contacts.php:644
 msgid "View conversations"
 msgstr "Unterhaltungen anzeigen"
 
-#: mod/contacts.php:648
+#: mod/contacts.php:649
 msgid "Last update:"
 msgstr "Letzte Aktualisierung: "
 
-#: mod/contacts.php:650
+#: mod/contacts.php:651
 msgid "Update public posts"
 msgstr "Öffentliche Beiträge aktualisieren"
 
-#: mod/contacts.php:652 mod/contacts.php:1096
+#: mod/contacts.php:653 mod/contacts.php:1099
 msgid "Update now"
 msgstr "Jetzt aktualisieren"
 
-#: mod/contacts.php:658 mod/contacts.php:850 mod/contacts.php:1113
+#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116
 msgid "Unignore"
 msgstr "Ignorieren aufheben"
 
-#: mod/contacts.php:662
+#: mod/contacts.php:663
 msgid "Currently blocked"
 msgstr "Derzeit geblockt"
 
-#: mod/contacts.php:663
+#: mod/contacts.php:664
 msgid "Currently ignored"
 msgstr "Derzeit ignoriert"
 
-#: mod/contacts.php:664
+#: mod/contacts.php:665
 msgid "Currently archived"
 msgstr "Momentan archiviert"
 
-#: mod/contacts.php:665
+#: mod/contacts.php:666
 msgid "Awaiting connection acknowledge"
 msgstr "Bedarf der Bestätigung des Kontakts"
 
-#: mod/contacts.php:666
+#: mod/contacts.php:667
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr "Antworten/Likes auf deine öffentlichen Beiträge <strong>könnten</strong> weiterhin sichtbar sein"
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Notification for new posts"
 msgstr "Benachrichtigung bei neuen Beiträgen"
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Send a notification of every new post of this contact"
 msgstr "Sende eine Benachrichtigung, wann immer dieser Kontakt einen neuen Beitrag schreibt."
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid "Blacklisted keywords"
 msgstr "Blacklistete Schlüsselworte "
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
 msgstr "Komma-Separierte Liste mit Schlüsselworten, die nicht in Hashtags konvertiert werden, wenn \"Beziehe Information und Schlüsselworte\" aktiviert wurde"
 
-#: mod/contacts.php:682 src/Model/Profile.php:424
+#: mod/contacts.php:683 src/Model/Profile.php:437
 msgid "XMPP:"
 msgstr "XMPP:"
 
-#: mod/contacts.php:687
+#: mod/contacts.php:688
 msgid "Actions"
 msgstr "Aktionen"
 
-#: mod/contacts.php:731
+#: mod/contacts.php:734
 msgid "Suggestions"
 msgstr "Kontaktvorschläge"
 
-#: mod/contacts.php:734
+#: mod/contacts.php:737
 msgid "Suggest potential friends"
 msgstr "Kontakte vorschlagen"
 
-#: mod/contacts.php:742
+#: mod/contacts.php:745
 msgid "Show all contacts"
 msgstr "Alle Kontakte anzeigen"
 
-#: mod/contacts.php:747
+#: mod/contacts.php:750
 msgid "Unblocked"
 msgstr "Ungeblockt"
 
-#: mod/contacts.php:750
+#: mod/contacts.php:753
 msgid "Only show unblocked contacts"
 msgstr "Nur nicht-blockierte Kontakte anzeigen"
 
-#: mod/contacts.php:755
+#: mod/contacts.php:758
 msgid "Blocked"
 msgstr "Geblockt"
 
-#: mod/contacts.php:758
+#: mod/contacts.php:761
 msgid "Only show blocked contacts"
 msgstr "Nur blockierte Kontakte anzeigen"
 
-#: mod/contacts.php:763
+#: mod/contacts.php:766
 msgid "Ignored"
 msgstr "Ignoriert"
 
-#: mod/contacts.php:766
+#: mod/contacts.php:769
 msgid "Only show ignored contacts"
 msgstr "Nur ignorierte Kontakte anzeigen"
 
-#: mod/contacts.php:771
+#: mod/contacts.php:774
 msgid "Archived"
 msgstr "Archiviert"
 
-#: mod/contacts.php:774
+#: mod/contacts.php:777
 msgid "Only show archived contacts"
 msgstr "Nur archivierte Kontakte anzeigen"
 
-#: mod/contacts.php:779
+#: mod/contacts.php:782
 msgid "Hidden"
 msgstr "Verborgen"
 
-#: mod/contacts.php:782
+#: mod/contacts.php:785
 msgid "Only show hidden contacts"
 msgstr "Nur verborgene Kontakte anzeigen"
 
-#: mod/contacts.php:840
+#: mod/contacts.php:843
 msgid "Search your contacts"
 msgstr "Suche in deinen Kontakten"
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Archive"
 msgstr "Archivieren"
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Unarchive"
 msgstr "Aus Archiv zurückholen"
 
-#: mod/contacts.php:854
+#: mod/contacts.php:857
 msgid "Batch Actions"
 msgstr "Stapelverarbeitung"
 
-#: mod/contacts.php:880
+#: mod/contacts.php:883
 msgid "Conversations started by this contact"
 msgstr "Unterhaltungen, die von diesem Kontakt begonnen wurden"
 
-#: mod/contacts.php:885
+#: mod/contacts.php:888
 msgid "Posts and Comments"
 msgstr "Statusnachrichten und Kommentare"
 
-#: mod/contacts.php:896 src/Model/Profile.php:886
+#: mod/contacts.php:899 src/Model/Profile.php:899
 msgid "Profile Details"
 msgstr "Profildetails"
 
-#: mod/contacts.php:908
+#: mod/contacts.php:911
 msgid "View all contacts"
 msgstr "Alle Kontakte anzeigen"
 
-#: mod/contacts.php:919
+#: mod/contacts.php:922
 msgid "View all common friends"
 msgstr "Alle Kontakte anzeigen"
 
-#: mod/contacts.php:929
+#: mod/contacts.php:932
 msgid "Advanced Contact Settings"
 msgstr "Fortgeschrittene Kontakteinstellungen"
 
-#: mod/contacts.php:1019
+#: mod/contacts.php:1022
 msgid "Mutual Friendship"
 msgstr "Beidseitige Freundschaft"
 
-#: mod/contacts.php:1024
+#: mod/contacts.php:1027
 msgid "is a fan of yours"
 msgstr "ist ein Fan von dir"
 
-#: mod/contacts.php:1029
+#: mod/contacts.php:1032
 msgid "you are a fan of"
 msgstr "Du bist Fan von"
 
-#: mod/contacts.php:1046 mod/photos.php:1494 mod/photos.php:1533
-#: mod/photos.php:1593 src/Object/Post.php:792
+#: mod/contacts.php:1049 mod/photos.php:1496 mod/photos.php:1535
+#: mod/photos.php:1595 src/Object/Post.php:792
 msgid "This is you"
 msgstr "Das bist Du"
 
-#: mod/contacts.php:1053
+#: mod/contacts.php:1056
 msgid "Edit contact"
 msgstr "Kontakt bearbeiten"
 
-#: mod/contacts.php:1107
+#: mod/contacts.php:1110
 msgid "Toggle Blocked status"
 msgstr "Geblockt-Status ein-/ausschalten"
 
-#: mod/contacts.php:1115
+#: mod/contacts.php:1118
 msgid "Toggle Ignored status"
 msgstr "Ignoriert-Status ein-/ausschalten"
 
-#: mod/contacts.php:1124
+#: mod/contacts.php:1127
 msgid "Toggle Archive status"
 msgstr "Archiviert-Status ein-/ausschalten"
 
-#: mod/contacts.php:1132
+#: mod/contacts.php:1135
 msgid "Delete contact"
 msgstr "Lösche den Kontakt"
 
-#: mod/events.php:103 mod/events.php:105
+#: mod/events.php:105 mod/events.php:107
 msgid "Event can not end before it has started."
 msgstr "Die Veranstaltung kann nicht enden bevor sie beginnt."
 
-#: mod/events.php:112 mod/events.php:114
+#: mod/events.php:114 mod/events.php:116
 msgid "Event title and start time are required."
 msgstr "Der Veranstaltungstitel und die Anfangszeit müssen angegeben werden."
 
-#: mod/events.php:392
+#: mod/events.php:393
 msgid "Create New Event"
 msgstr "Neue Veranstaltung erstellen"
 
-#: mod/events.php:509
+#: mod/events.php:516
 msgid "Event details"
 msgstr "Veranstaltungsdetails"
 
-#: mod/events.php:510
+#: mod/events.php:517
 msgid "Starting date and Title are required."
 msgstr "Anfangszeitpunkt und Titel werden benötigt"
 
-#: mod/events.php:511 mod/events.php:512
+#: mod/events.php:518 mod/events.php:523
 msgid "Event Starts:"
 msgstr "Veranstaltungsbeginn:"
 
-#: mod/events.php:511 mod/events.php:523 mod/profiles.php:607
+#: mod/events.php:518 mod/events.php:550 mod/profiles.php:607
 msgid "Required"
 msgstr "Benötigt"
 
-#: mod/events.php:513 mod/events.php:529
+#: mod/events.php:531 mod/events.php:556
 msgid "Finish date/time is not known or not relevant"
 msgstr "Enddatum/-zeit ist nicht bekannt oder nicht relevant"
 
-#: mod/events.php:515 mod/events.php:516
+#: mod/events.php:533 mod/events.php:538
 msgid "Event Finishes:"
 msgstr "Veranstaltungsende:"
 
-#: mod/events.php:517 mod/events.php:530
+#: mod/events.php:544 mod/events.php:557
 msgid "Adjust for viewer timezone"
 msgstr "An Zeitzone des Betrachters anpassen"
 
-#: mod/events.php:519
+#: mod/events.php:546
 msgid "Description:"
 msgstr "Beschreibung"
 
-#: mod/events.php:523 mod/events.php:525
+#: mod/events.php:550 mod/events.php:552
 msgid "Title:"
 msgstr "Titel:"
 
-#: mod/events.php:526 mod/events.php:527
+#: mod/events.php:553 mod/events.php:554
 msgid "Share this event"
 msgstr "Veranstaltung teilen"
 
-#: mod/events.php:534 src/Model/Profile.php:851
+#: mod/events.php:561 src/Model/Profile.php:864
 msgid "Basic"
 msgstr "Allgemein"
 
-#: mod/events.php:536 mod/photos.php:1112 mod/photos.php:1448
+#: mod/events.php:563 mod/photos.php:1114 mod/photos.php:1450
 #: src/Core/ACL.php:307
 msgid "Permissions"
 msgstr "Berechtigungen"
 
-#: mod/events.php:555
+#: mod/events.php:579
 msgid "Failed to remove event"
 msgstr "Entfernen der Veranstaltung fehlgeschlagen"
 
-#: mod/events.php:557
+#: mod/events.php:581
 msgid "Event removed"
 msgstr "Veranstaltung enfternt"
 
@@ -7022,8 +7038,8 @@ msgid "The network type couldn't be detected. Contact can't be added."
 msgstr "Der Netzwerktype wurde nicht erkannt. Der Kontakt kann nicht hinzugefügt werden."
 
 #: mod/fbrowser.php:44 mod/fbrowser.php:69 mod/photos.php:198
-#: mod/photos.php:1076 mod/photos.php:1169 mod/photos.php:1186
-#: mod/photos.php:1652 mod/photos.php:1667 src/Model/Photo.php:243
+#: mod/photos.php:1078 mod/photos.php:1171 mod/photos.php:1188
+#: mod/photos.php:1654 mod/photos.php:1669 src/Model/Photo.php:243
 #: src/Model/Photo.php:252
 msgid "Contact Photos"
 msgstr "Kontaktbilder"
@@ -7094,7 +7110,7 @@ msgid ""
 " not reflect the opinions of this node’s users."
 msgstr "Diese Gemeinschaftsseite zeigt alle öffentlichen Beiträge, die auf diesem Knoten eingegangen sind. Der Inhalt entspricht nicht zwingend der Meinung der Nutzer dieses Servers."
 
-#: mod/localtime.php:19 src/Model/Event.php:34 src/Model/Event.php:829
+#: mod/localtime.php:19 src/Model/Event.php:35 src/Model/Event.php:836
 msgid "l F d, Y \\@ g:i A"
 msgstr "l, d. F Y\\, H:i"
 
@@ -7127,23 +7143,23 @@ msgstr "Umgerechnete lokale Zeit: %s"
 msgid "Please select your timezone:"
 msgstr "Bitte wähle Deine Zeitzone:"
 
-#: mod/poke.php:188
+#: mod/poke.php:187
 msgid "Poke/Prod"
 msgstr "Anstupsen"
 
-#: mod/poke.php:189
+#: mod/poke.php:188
 msgid "poke, prod or do other things to somebody"
 msgstr "Stupse Leute an oder mache anderes mit ihnen"
 
-#: mod/poke.php:190
+#: mod/poke.php:189
 msgid "Recipient"
 msgstr "Empfänger"
 
-#: mod/poke.php:191
+#: mod/poke.php:190
 msgid "Choose what you wish to do to recipient"
 msgstr "Was willst Du mit dem Empfänger machen:"
 
-#: mod/poke.php:194
+#: mod/poke.php:193
 msgid "Make this post private"
 msgstr "Diesen Beitrag privat machen"
 
@@ -7251,7 +7267,7 @@ msgid ""
 "important, please visit http://friendi.ca"
 msgstr "Für weitere Informationen über das Friendica Projekt und warum wir es für ein wichtiges Projekt halten, besuche bitte http://friendi.ca."
 
-#: mod/notes.php:42 src/Model/Profile.php:933
+#: mod/notes.php:42 src/Model/Profile.php:946
 msgid "Personal Notes"
 msgstr "Persönliche Notizen"
 
@@ -7355,7 +7371,7 @@ msgstr "Dieses Profil anzeigen"
 msgid "View all profiles"
 msgstr "Alle Profile anzeigen"
 
-#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:393
+#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:406
 msgid "Edit visibility"
 msgstr "Sichtbarkeit bearbeiten"
 
@@ -7407,7 +7423,7 @@ msgstr "Dein Geschlecht:"
 msgid "<span class=\"heart\">&hearts;</span> Marital Status:"
 msgstr "<span class=\"heart\">&hearts;</span> Beziehungsstatus:"
 
-#: mod/profiles.php:601 src/Model/Profile.php:769
+#: mod/profiles.php:601 src/Model/Profile.php:782
 msgid "Sexual Preference:"
 msgstr "Sexuelle Vorlieben:"
 
@@ -7487,11 +7503,11 @@ msgstr "Die XMPP Adresse wird an deine Kontakte verteilt werden, so dass sie auc
 msgid "Homepage URL:"
 msgstr "Adresse der Homepage:"
 
-#: mod/profiles.php:628 src/Model/Profile.php:777
+#: mod/profiles.php:628 src/Model/Profile.php:790
 msgid "Hometown:"
 msgstr "Heimatort:"
 
-#: mod/profiles.php:629 src/Model/Profile.php:785
+#: mod/profiles.php:629 src/Model/Profile.php:798
 msgid "Political Views:"
 msgstr "Politische Ansichten:"
 
@@ -7515,11 +7531,11 @@ msgstr "Private Schlüsselwörter:"
 msgid "(Used for searching profiles, never shown to others)"
 msgstr "(Wird für die Suche nach Profilen verwendet und niemals veröffentlicht)"
 
-#: mod/profiles.php:633 src/Model/Profile.php:801
+#: mod/profiles.php:633 src/Model/Profile.php:814
 msgid "Likes:"
 msgstr "Likes:"
 
-#: mod/profiles.php:634 src/Model/Profile.php:805
+#: mod/profiles.php:634 src/Model/Profile.php:818
 msgid "Dislikes:"
 msgstr "Dislikes:"
 
@@ -7559,11 +7575,11 @@ msgstr "Schule/Ausbildung"
 msgid "Contact information and Social Networks"
 msgstr "Kontaktinformationen und Soziale Netzwerke"
 
-#: mod/profiles.php:674 src/Model/Profile.php:389
+#: mod/profiles.php:674 src/Model/Profile.php:402
 msgid "Profile Image"
 msgstr "Profilbild"
 
-#: mod/profiles.php:676 src/Model/Profile.php:392
+#: mod/profiles.php:676 src/Model/Profile.php:405
 msgid "visible to everybody"
 msgstr "sichtbar für jeden"
 
@@ -7571,23 +7587,23 @@ msgstr "sichtbar für jeden"
 msgid "Edit/Manage Profiles"
 msgstr "Bearbeite/Verwalte Profile"
 
-#: mod/profiles.php:684 src/Model/Profile.php:379 src/Model/Profile.php:401
+#: mod/profiles.php:684 src/Model/Profile.php:392 src/Model/Profile.php:414
 msgid "Change profile photo"
 msgstr "Profilbild ändern"
 
-#: mod/profiles.php:685 src/Model/Profile.php:380
+#: mod/profiles.php:685 src/Model/Profile.php:393
 msgid "Create New Profile"
 msgstr "Neues Profil anlegen"
 
-#: mod/photos.php:112 src/Model/Profile.php:894
+#: mod/photos.php:112 src/Model/Profile.php:907
 msgid "Photo Albums"
 msgstr "Fotoalben"
 
-#: mod/photos.php:113 mod/photos.php:1708
+#: mod/photos.php:113 mod/photos.php:1710
 msgid "Recent Photos"
 msgstr "Neueste Fotos"
 
-#: mod/photos.php:116 mod/photos.php:1230 mod/photos.php:1710
+#: mod/photos.php:116 mod/photos.php:1232 mod/photos.php:1712
 msgid "Upload New Photos"
 msgstr "Neue Fotos hochladen"
 
@@ -7599,7 +7615,7 @@ msgstr "Kontaktinformationen nicht verfügbar"
 msgid "Album not found."
 msgstr "Album nicht gefunden."
 
-#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1181
+#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1183
 msgid "Delete Album"
 msgstr "Album löschen"
 
@@ -7607,7 +7623,7 @@ msgstr "Album löschen"
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr "Möchtest Du wirklich dieses Foto-Album und all seine Foto löschen?"
 
-#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1453
+#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1455
 msgid "Delete Photo"
 msgstr "Foto löschen"
 
@@ -7624,150 +7640,150 @@ msgstr "einem Foto"
 msgid "%1$s was tagged in %2$s by %3$s"
 msgstr "%1$s wurde von %3$s in %2$s getaggt"
 
-#: mod/photos.php:782
+#: mod/photos.php:784
 msgid "Image upload didn't complete, please try again"
 msgstr "Der Upload des Bildes war nicht vollständig. Bitte versuche es erneut."
 
-#: mod/photos.php:785
+#: mod/photos.php:787
 msgid "Image file is missing"
 msgstr "Bilddatei konnte nicht gefunden werden."
 
-#: mod/photos.php:790
+#: mod/photos.php:792
 msgid ""
 "Server can't accept new file upload at this time, please contact your "
 "administrator"
 msgstr "Der Server kann derzeit keine neuen Datei Uploads akzeptieren. Bitte kontaktiere deinen Administrator."
 
-#: mod/photos.php:816
+#: mod/photos.php:818
 msgid "Image file is empty."
 msgstr "Bilddatei ist leer."
 
-#: mod/photos.php:953
+#: mod/photos.php:955
 msgid "No photos selected"
 msgstr "Keine Bilder ausgewählt"
 
-#: mod/photos.php:1104
+#: mod/photos.php:1106
 msgid "Upload Photos"
 msgstr "Bilder hochladen"
 
-#: mod/photos.php:1108 mod/photos.php:1176
+#: mod/photos.php:1110 mod/photos.php:1178
 msgid "New album name: "
 msgstr "Name des neuen Albums: "
 
-#: mod/photos.php:1109
+#: mod/photos.php:1111
 msgid "or select existing album:"
 msgstr "oder wähle ein bestehendes Album:"
 
-#: mod/photos.php:1110
+#: mod/photos.php:1112
 msgid "Do not show a status post for this upload"
 msgstr "Keine Status-Mitteilung für diesen Beitrag anzeigen"
 
-#: mod/photos.php:1187
+#: mod/photos.php:1189
 msgid "Edit Album"
 msgstr "Album bearbeiten"
 
-#: mod/photos.php:1192
+#: mod/photos.php:1194
 msgid "Show Newest First"
 msgstr "Zeige neueste zuerst"
 
-#: mod/photos.php:1194
+#: mod/photos.php:1196
 msgid "Show Oldest First"
 msgstr "Zeige älteste zuerst"
 
-#: mod/photos.php:1215 mod/photos.php:1693
+#: mod/photos.php:1217 mod/photos.php:1695
 msgid "View Photo"
 msgstr "Foto betrachten"
 
-#: mod/photos.php:1256
+#: mod/photos.php:1258
 msgid "Permission denied. Access to this item may be restricted."
 msgstr "Zugriff verweigert. Zugriff zu diesem Eintrag könnte eingeschränkt sein."
 
-#: mod/photos.php:1258
+#: mod/photos.php:1260
 msgid "Photo not available"
 msgstr "Foto nicht verfügbar"
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "View photo"
 msgstr "Fotos ansehen"
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "Edit photo"
 msgstr "Foto bearbeiten"
 
-#: mod/photos.php:1334
+#: mod/photos.php:1336
 msgid "Use as profile photo"
 msgstr "Als Profilbild verwenden"
 
-#: mod/photos.php:1340 src/Object/Post.php:151
+#: mod/photos.php:1342 src/Object/Post.php:151
 msgid "Private Message"
 msgstr "Private Nachricht"
 
-#: mod/photos.php:1360
+#: mod/photos.php:1362
 msgid "View Full Size"
 msgstr "Betrachte Originalgröße"
 
-#: mod/photos.php:1421
+#: mod/photos.php:1423
 msgid "Tags: "
 msgstr "Tags: "
 
-#: mod/photos.php:1424
+#: mod/photos.php:1426
 msgid "[Remove any tag]"
 msgstr "[Tag entfernen]"
 
-#: mod/photos.php:1439
+#: mod/photos.php:1441
 msgid "New album name"
 msgstr "Name des neuen Albums"
 
-#: mod/photos.php:1440
+#: mod/photos.php:1442
 msgid "Caption"
 msgstr "Bildunterschrift"
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid "Add a Tag"
 msgstr "Tag hinzufügen"
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid ""
 "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr "Beispiel: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 
-#: mod/photos.php:1442
+#: mod/photos.php:1444
 msgid "Do not rotate"
 msgstr "Nicht rotieren"
 
-#: mod/photos.php:1443
+#: mod/photos.php:1445
 msgid "Rotate CW (right)"
 msgstr "Drehen US (rechts)"
 
-#: mod/photos.php:1444
+#: mod/photos.php:1446
 msgid "Rotate CCW (left)"
 msgstr "Drehen EUS (links)"
 
-#: mod/photos.php:1478 src/Object/Post.php:293
+#: mod/photos.php:1480 src/Object/Post.php:293
 msgid "I like this (toggle)"
 msgstr "Ich mag das (toggle)"
 
-#: mod/photos.php:1479 src/Object/Post.php:294
+#: mod/photos.php:1481 src/Object/Post.php:294
 msgid "I don't like this (toggle)"
 msgstr "Ich mag das nicht (toggle)"
 
-#: mod/photos.php:1496 mod/photos.php:1535 mod/photos.php:1595
+#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
 #: src/Object/Post.php:398 src/Object/Post.php:794
 msgid "Comment"
 msgstr "Kommentar"
 
-#: mod/photos.php:1627
+#: mod/photos.php:1629
 msgid "Map"
 msgstr "Karte"
 
-#: local/test.php:1840
+#: local/test.php:1919
 #, php-format
 msgid ""
 "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-"
 "name\">%s</a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"
 msgstr "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-name\">%s</a> schrieb den folgenden <a href=\"%s\" target=\"_blank\">Beitrag</a>"
 
-#: local/testshare.php:158 src/Content/Text/BBCode.php:991
+#: local/testshare.php:158 src/Content/Text/BBCode.php:992
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 msgstr "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
@@ -7827,11 +7843,11 @@ msgstr "%s: Datenbank Aktualisierung"
 msgid "%s: updating %s table."
 msgstr "%s: aktualisiere Tabelle %s"
 
-#: src/Core/Install.php:138
+#: src/Core/Install.php:139
 msgid "Could not find a command line version of PHP in the web server PATH."
 msgstr "Konnte keine Kommandozeilenversion von PHP im PATH des Servers finden."
 
-#: src/Core/Install.php:139
+#: src/Core/Install.php:140
 msgid ""
 "If you don't have a command line version of PHP installed on your server, "
 "you will not be able to run the background processing. See <a "
@@ -7839,219 +7855,219 @@ msgid ""
 "up-the-worker'>'Setup the worker'</a>"
 msgstr "Wenn auf deinem Server keine Kommandozeilenversion von PHP installiert ist, kannst du den Hintergrundprozess nicht einrichten. Hier findest du alternative Möglichkeiten<a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-poller'>'für das Worker Setup'</a>"
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid "PHP executable path"
 msgstr "Pfad zu PHP"
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid ""
 "Enter full path to php executable. You can leave this blank to continue the "
 "installation."
 msgstr "Gib den kompletten Pfad zur ausführbaren Datei von PHP an. Du kannst dieses Feld auch frei lassen und mit der Installation fortfahren."
 
-#: src/Core/Install.php:148
+#: src/Core/Install.php:149
 msgid "Command line PHP"
 msgstr "Kommandozeilen-PHP"
 
-#: src/Core/Install.php:157
+#: src/Core/Install.php:158
 msgid "PHP executable is not the php cli binary (could be cgi-fgci version)"
 msgstr "Die ausführbare Datei von PHP stimmt nicht mit der PHP cli Version überein (es könnte sich um die cgi-fgci Version handeln)"
 
-#: src/Core/Install.php:158
+#: src/Core/Install.php:159
 msgid "Found PHP version: "
 msgstr "Gefundene PHP Version:"
 
-#: src/Core/Install.php:160
+#: src/Core/Install.php:161
 msgid "PHP cli binary"
 msgstr "PHP CLI Binary"
 
-#: src/Core/Install.php:170
+#: src/Core/Install.php:171
 msgid ""
 "The command line version of PHP on your system does not have "
 "\"register_argc_argv\" enabled."
 msgstr "Die Kommandozeilenversion von PHP auf Deinem System hat \"register_argc_argv\" nicht aktiviert."
 
-#: src/Core/Install.php:171
+#: src/Core/Install.php:172
 msgid "This is required for message delivery to work."
 msgstr "Dies wird für die Auslieferung von Nachrichten benötigt."
 
-#: src/Core/Install.php:173
+#: src/Core/Install.php:174
 msgid "PHP register_argc_argv"
 msgstr "PHP register_argc_argv"
 
-#: src/Core/Install.php:201
+#: src/Core/Install.php:202
 msgid ""
 "Error: the \"openssl_pkey_new\" function on this system is not able to "
 "generate encryption keys"
 msgstr "Fehler: Die Funktion \"openssl_pkey_new\" auf diesem System ist nicht in der Lage, Verschlüsselungsschlüssel zu erzeugen"
 
-#: src/Core/Install.php:202
+#: src/Core/Install.php:203
 msgid ""
 "If running under Windows, please see "
 "\"http://www.php.net/manual/en/openssl.installation.php\"."
 msgstr "Wenn der Server unter Windows läuft, schau Dir bitte \"http://www.php.net/manual/en/openssl.installation.php\" an."
 
-#: src/Core/Install.php:204
+#: src/Core/Install.php:205
 msgid "Generate encryption keys"
 msgstr "Schlüssel erzeugen"
 
-#: src/Core/Install.php:225
+#: src/Core/Install.php:226
 msgid "libCurl PHP module"
 msgstr "PHP: libCurl-Modul"
 
-#: src/Core/Install.php:226
+#: src/Core/Install.php:227
 msgid "GD graphics PHP module"
 msgstr "PHP: GD-Grafikmodul"
 
-#: src/Core/Install.php:227
+#: src/Core/Install.php:228
 msgid "OpenSSL PHP module"
 msgstr "PHP: OpenSSL-Modul"
 
-#: src/Core/Install.php:228
+#: src/Core/Install.php:229
 msgid "PDO or MySQLi PHP module"
 msgstr "PDO oder MySQLi PHP Modul"
 
-#: src/Core/Install.php:229
+#: src/Core/Install.php:230
 msgid "mb_string PHP module"
 msgstr "PHP: mb_string-Modul"
 
-#: src/Core/Install.php:230
+#: src/Core/Install.php:231
 msgid "XML PHP module"
 msgstr "XML PHP Modul"
 
-#: src/Core/Install.php:231
+#: src/Core/Install.php:232
 msgid "iconv PHP module"
 msgstr "PHP iconv Modul"
 
-#: src/Core/Install.php:232
+#: src/Core/Install.php:233
 msgid "POSIX PHP module"
 msgstr "PHP POSIX Modul"
 
-#: src/Core/Install.php:236 src/Core/Install.php:238
+#: src/Core/Install.php:237 src/Core/Install.php:239
 msgid "Apache mod_rewrite module"
 msgstr "Apache mod_rewrite module"
 
-#: src/Core/Install.php:236
+#: src/Core/Install.php:237
 msgid ""
 "Error: Apache webserver mod-rewrite module is required but not installed."
 msgstr "Fehler: Das Apache-Modul mod-rewrite wird benötigt, es ist allerdings nicht installiert."
 
-#: src/Core/Install.php:244
+#: src/Core/Install.php:245
 msgid "Error: libCURL PHP module required but not installed."
 msgstr "Fehler: Das libCURL PHP Modul wird benötigt, ist aber nicht installiert."
 
-#: src/Core/Install.php:248
+#: src/Core/Install.php:249
 msgid ""
 "Error: GD graphics PHP module with JPEG support required but not installed."
 msgstr "Fehler: Das GD-Graphikmodul für PHP mit JPEG-Unterstützung ist nicht installiert."
 
-#: src/Core/Install.php:252
+#: src/Core/Install.php:253
 msgid "Error: openssl PHP module required but not installed."
 msgstr "Fehler: Das openssl-Modul von PHP ist nicht installiert."
 
-#: src/Core/Install.php:256
+#: src/Core/Install.php:257
 msgid "Error: PDO or MySQLi PHP module required but not installed."
 msgstr "Fehler: PDO oder MySQLi PHP Modul erforderlich, aber nicht installiert."
 
-#: src/Core/Install.php:260
+#: src/Core/Install.php:261
 msgid "Error: The MySQL driver for PDO is not installed."
 msgstr "Fehler: der MySQL Treiber für PDO ist nicht installiert"
 
-#: src/Core/Install.php:264
+#: src/Core/Install.php:265
 msgid "Error: mb_string PHP module required but not installed."
 msgstr "Fehler: mb_string PHP Module wird benötigt ist aber nicht installiert."
 
-#: src/Core/Install.php:268
+#: src/Core/Install.php:269
 msgid "Error: iconv PHP module required but not installed."
 msgstr "Fehler: Das iconv-Modul von PHP ist nicht installiert."
 
-#: src/Core/Install.php:272
+#: src/Core/Install.php:273
 msgid "Error: POSIX PHP module required but not installed."
 msgstr "Fehler POSIX PHP Modul erforderlich aber nicht installiert."
 
-#: src/Core/Install.php:282
+#: src/Core/Install.php:283
 msgid "Error, XML PHP module required but not installed."
 msgstr "Fehler: XML PHP Modul erforderlich aber nicht installiert."
 
-#: src/Core/Install.php:301
+#: src/Core/Install.php:302
 msgid ""
 "The web installer needs to be able to create a file called \"local.ini.php\""
 " in the \"config\" folder of your web server and it is unable to do so."
 msgstr "Das Installationsprogramm muss in der Lage sein, eine Datei namens \"local.ini.php\" im Ordner \"config\" Ihres Webservers zu erstellen, ist aber nicht in der Lager dazu."
 
-#: src/Core/Install.php:302
+#: src/Core/Install.php:303
 msgid ""
 "This is most often a permission setting, as the web server may not be able "
 "to write files in your folder - even if you can."
 msgstr "In den meisten Fällen ist dies ein Problem mit den Schreibrechten. Der Webserver könnte keine Schreiberlaubnis haben, selbst wenn Du sie hast."
 
-#: src/Core/Install.php:303
+#: src/Core/Install.php:304
 msgid ""
 "At the end of this procedure, we will give you a text to save in a file "
 "named local.ini.php in your Friendica \"config\" folder."
 msgstr "Am Ende dieser Prozedur bekommst du einen Text der in der local.ini.php im Friendica \"config\" Ordner gespeichert werden muss."
 
-#: src/Core/Install.php:304
+#: src/Core/Install.php:305
 msgid ""
 "You can alternatively skip this procedure and perform a manual installation."
 " Please see the file \"INSTALL.txt\" for instructions."
 msgstr "Alternativ kannst Du diesen Schritt aber auch überspringen und die Installation manuell durchführen. Eine Anleitung dazu (Englisch) findest Du in der Datei INSTALL.txt."
 
-#: src/Core/Install.php:307
+#: src/Core/Install.php:308
 msgid "config/local.ini.php is writable"
 msgstr "config/local.ini.php ist beschreibbar"
 
-#: src/Core/Install.php:325
+#: src/Core/Install.php:326
 msgid ""
 "Friendica uses the Smarty3 template engine to render its web views. Smarty3 "
 "compiles templates to PHP to speed up rendering."
 msgstr "Friendica nutzt die Smarty3 Template Engine um die Webansichten zu rendern. Smarty3 kompiliert Templates zu PHP um das Rendern zu beschleunigen."
 
-#: src/Core/Install.php:326
+#: src/Core/Install.php:327
 msgid ""
 "In order to store these compiled templates, the web server needs to have "
 "write access to the directory view/smarty3/ under the Friendica top level "
 "folder."
 msgstr "Um diese kompilierten Templates zu speichern benötigt der Webserver Schreibrechte zum Verzeichnis view/smarty3/ im obersten Ordner von Friendica."
 
-#: src/Core/Install.php:327
+#: src/Core/Install.php:328
 msgid ""
 "Please ensure that the user that your web server runs as (e.g. www-data) has"
 " write access to this folder."
 msgstr "Bitte stelle sicher, dass der Nutzer unter dem der Webserver läuft (z.B. www-data) Schreibrechte zu diesem Verzeichnis hat."
 
-#: src/Core/Install.php:328
+#: src/Core/Install.php:329
 msgid ""
 "Note: as a security measure, you should give the web server write access to "
 "view/smarty3/ only--not the template files (.tpl) that it contains."
 msgstr "Hinweis: aus Sicherheitsgründen solltest Du dem Webserver nur Schreibrechte für view/smarty3/ geben -- Nicht den Templatedateien (.tpl) die sie enthalten."
 
-#: src/Core/Install.php:331
+#: src/Core/Install.php:332
 msgid "view/smarty3 is writable"
 msgstr "view/smarty3 ist schreibbar"
 
-#: src/Core/Install.php:356
+#: src/Core/Install.php:357
 msgid ""
 "Url rewrite in .htaccess is not working. Check your server configuration."
 msgstr "Umschreiben der URLs in der .htaccess funktioniert nicht. Überprüfe die Konfiguration des Servers."
 
-#: src/Core/Install.php:358
+#: src/Core/Install.php:359
 msgid "Error message from Curl when fetching"
 msgstr "Fehlermeldung von Curl während des Ladens"
 
-#: src/Core/Install.php:362
+#: src/Core/Install.php:363
 msgid "Url rewrite is working"
 msgstr "URL rewrite funktioniert"
 
-#: src/Core/Install.php:389
+#: src/Core/Install.php:390
 msgid "ImageMagick PHP extension is not installed"
 msgstr "ImageMagicx PHP Erweiterung ist nicht installiert."
 
-#: src/Core/Install.php:391
+#: src/Core/Install.php:392
 msgid "ImageMagick PHP extension is installed"
 msgstr "ImageMagick PHP Erweiterung ist installiert"
 
-#: src/Core/Install.php:393
+#: src/Core/Install.php:394
 msgid "ImageMagick supports GIF"
 msgstr "ImageMagick unterstützt GIF"
 
@@ -8085,11 +8101,16 @@ msgstr "Für die URL (%s) konnte kein nicht-archivierter Kontakt gefunden werden
 msgid "The contact entries have been archived"
 msgstr "Die Kontakteinträge wurden archiviert."
 
-#: src/Core/Console/PostUpdate.php:32
+#: src/Core/Console/PostUpdate.php:49
+#, php-format
+msgid "Post update version number has been set to %s."
+msgstr "Die Post-Update Versionsnummer wurde auf %s gesetzt."
+
+#: src/Core/Console/PostUpdate.php:57
 msgid "Execute pending post updates."
 msgstr "Ausstehende Post-Updates ausführen"
 
-#: src/Core/Console/PostUpdate.php:38
+#: src/Core/Console/PostUpdate.php:63
 msgid "All pending post updates are done."
 msgstr "Alle ausstehenden Post-Updates wurden ausgeführt."
 
@@ -8149,20 +8170,20 @@ msgstr "%s nimmt nicht an %s's Event teil"
 msgid "%s may attend %s's event"
 msgstr "%s nimmt eventuell an %s's Event teil"
 
-#: src/Core/NotificationsManager.php:360
+#: src/Core/NotificationsManager.php:372
 #, php-format
 msgid "%s is now friends with %s"
 msgstr "%s ist jetzt mit %s befreundet"
 
-#: src/Core/NotificationsManager.php:626
+#: src/Core/NotificationsManager.php:638
 msgid "Friend Suggestion"
 msgstr "Kontaktvorschlag"
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "Friend/Connect Request"
 msgstr "Kontakt-/Freundschaftsanfrage"
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "New Follower"
 msgstr "Neuer Bewunderer"
 
@@ -8198,7 +8219,7 @@ msgstr[1] "%d Kontakte nicht importiert"
 msgid "Done. You can now login with your username and password"
 msgstr "Erledigt. Du kannst Dich jetzt mit Deinem Nutzernamen und Passwort anmelden"
 
-#: src/Worker/Delivery.php:423
+#: src/Worker/Delivery.php:425
 msgid "(no subject)"
 msgstr "(kein Betreff)"
 
@@ -8333,15 +8354,15 @@ msgstr "Link"
 msgid "Video"
 msgstr "Video"
 
-#: src/App.php:785
+#: src/App.php:798
 msgid "Delete this item?"
 msgstr "Diesen Beitrag löschen?"
 
-#: src/App.php:787
+#: src/App.php:800
 msgid "show fewer"
 msgstr "weniger anzeigen"
 
-#: src/App.php:1385
+#: src/App.php:1416
 msgid "No system theme config value set."
 msgstr "Es wurde kein Konfigurationswert für das Systemweite Theme gesetzt."
 
@@ -8430,43 +8451,47 @@ msgstr "Angemeldete Nutzer können ihre Nutzerdaten jederzeit von den <a href=\"
 msgid "Privacy Statement"
 msgstr "Datenschutzerklärung"
 
-#: src/Protocol/OStatus.php:1813
+#: src/Module/Proxy.php:138
+msgid "Bad Request."
+msgstr "Ungültige Anfrage."
+
+#: src/Protocol/OStatus.php:1823
 #, php-format
 msgid "%s is now following %s."
 msgstr "%s folgt nun %s"
 
-#: src/Protocol/OStatus.php:1814
+#: src/Protocol/OStatus.php:1824
 msgid "following"
 msgstr "folgen"
 
-#: src/Protocol/OStatus.php:1817
+#: src/Protocol/OStatus.php:1827
 #, php-format
 msgid "%s stopped following %s."
 msgstr "%s hat aufgehört %s zu folgen"
 
-#: src/Protocol/OStatus.php:1818
+#: src/Protocol/OStatus.php:1828
 msgid "stopped following"
 msgstr "wird nicht mehr gefolgt"
 
-#: src/Protocol/DFRN.php:1525 src/Model/Contact.php:1956
+#: src/Protocol/DFRN.php:1528 src/Model/Contact.php:1974
 #, php-format
 msgid "%s's birthday"
 msgstr "%ss Geburtstag"
 
-#: src/Protocol/DFRN.php:1526 src/Model/Contact.php:1957
+#: src/Protocol/DFRN.php:1529 src/Model/Contact.php:1975
 #, php-format
 msgid "Happy Birthday %s"
 msgstr "Herzlichen Glückwunsch %s"
 
-#: src/Protocol/Diaspora.php:2417
+#: src/Protocol/Diaspora.php:2434
 msgid "Sharing notification from Diaspora network"
 msgstr "Freigabe-Benachrichtigung von Diaspora"
 
-#: src/Protocol/Diaspora.php:3514
+#: src/Protocol/Diaspora.php:3531
 msgid "Attachments:"
 msgstr "Anhänge:"
 
-#: src/Util/Temporal.php:147 src/Model/Profile.php:745
+#: src/Util/Temporal.php:147 src/Model/Profile.php:758
 msgid "Birthday:"
 msgstr "Geburtstag:"
 
@@ -8535,134 +8560,134 @@ msgstr "vor %1$d %2$s"
 msgid "[no subject]"
 msgstr "[kein Betreff]"
 
-#: src/Model/Contact.php:942
+#: src/Model/Contact.php:953
 msgid "Drop Contact"
 msgstr "Kontakt löschen"
 
-#: src/Model/Contact.php:1399
+#: src/Model/Contact.php:1408
 msgid "Organisation"
 msgstr "Organisation"
 
-#: src/Model/Contact.php:1403
+#: src/Model/Contact.php:1412
 msgid "News"
 msgstr "Nachrichten"
 
-#: src/Model/Contact.php:1407
+#: src/Model/Contact.php:1416
 msgid "Forum"
 msgstr "Forum"
 
-#: src/Model/Contact.php:1587
+#: src/Model/Contact.php:1598
 msgid "Connect URL missing."
 msgstr "Connect-URL fehlt"
 
-#: src/Model/Contact.php:1596
+#: src/Model/Contact.php:1607
 msgid ""
 "The contact could not be added. Please check the relevant network "
 "credentials in your Settings -> Social Networks page."
 msgstr "Der Kontakt konnte nicht hinzugefügt werden. Bitte überprüfe die Einstellungen unter Einstellungen -> Soziale Netzwerke"
 
-#: src/Model/Contact.php:1635
+#: src/Model/Contact.php:1646
 msgid ""
 "This site is not configured to allow communications with other networks."
 msgstr "Diese Seite ist so konfiguriert, dass keine Kommunikation mit anderen Netzwerken erfolgen kann."
 
-#: src/Model/Contact.php:1636 src/Model/Contact.php:1650
+#: src/Model/Contact.php:1647 src/Model/Contact.php:1661
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden."
 
-#: src/Model/Contact.php:1648
+#: src/Model/Contact.php:1659
 msgid "The profile address specified does not provide adequate information."
 msgstr "Die angegebene Profiladresse liefert unzureichende Informationen."
 
-#: src/Model/Contact.php:1653
+#: src/Model/Contact.php:1664
 msgid "An author or name was not found."
 msgstr "Es wurde kein Autor oder Name gefunden."
 
-#: src/Model/Contact.php:1656
+#: src/Model/Contact.php:1667
 msgid "No browser URL could be matched to this address."
 msgstr "Zu dieser Adresse konnte keine passende Browser URL gefunden werden."
 
-#: src/Model/Contact.php:1659
+#: src/Model/Contact.php:1670
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr "Konnte die @-Adresse mit keinem der bekannten Protokolle oder Email-Kontakte abgleichen."
 
-#: src/Model/Contact.php:1660
+#: src/Model/Contact.php:1671
 msgid "Use mailto: in front of address to force email check."
 msgstr "Verwende mailto: vor der Email Adresse, um eine Überprüfung der E-Mail-Adresse zu erzwingen."
 
-#: src/Model/Contact.php:1666
+#: src/Model/Contact.php:1677
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr "Die Adresse dieses Profils gehört zu einem Netzwerk, mit dem die Kommunikation auf dieser Seite ausgeschaltet wurde."
 
-#: src/Model/Contact.php:1671
+#: src/Model/Contact.php:1682
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
 msgstr "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von Dir erhalten können."
 
-#: src/Model/Contact.php:1722
+#: src/Model/Contact.php:1733
 msgid "Unable to retrieve contact information."
 msgstr "Konnte die Kontaktinformationen nicht empfangen."
 
-#: src/Model/Event.php:59 src/Model/Event.php:76 src/Model/Event.php:428
-#: src/Model/Event.php:897
+#: src/Model/Event.php:60 src/Model/Event.php:77 src/Model/Event.php:429
+#: src/Model/Event.php:904
 msgid "Starts:"
 msgstr "Beginnt:"
 
-#: src/Model/Event.php:62 src/Model/Event.php:82 src/Model/Event.php:429
-#: src/Model/Event.php:901
+#: src/Model/Event.php:63 src/Model/Event.php:83 src/Model/Event.php:430
+#: src/Model/Event.php:908
 msgid "Finishes:"
 msgstr "Endet:"
 
-#: src/Model/Event.php:377
+#: src/Model/Event.php:378
 msgid "all-day"
 msgstr "ganztägig"
 
-#: src/Model/Event.php:400
+#: src/Model/Event.php:401
 msgid "Jun"
 msgstr "Jun"
 
-#: src/Model/Event.php:403
+#: src/Model/Event.php:404
 msgid "Sept"
 msgstr "Sep"
 
-#: src/Model/Event.php:426
+#: src/Model/Event.php:427
 msgid "No events to display"
 msgstr "Keine Veranstaltung zum Anzeigen"
 
-#: src/Model/Event.php:550
+#: src/Model/Event.php:551
 msgid "l, F j"
 msgstr "l, F j"
 
-#: src/Model/Event.php:581
+#: src/Model/Event.php:582
 msgid "Edit event"
 msgstr "Veranstaltung bearbeiten"
 
-#: src/Model/Event.php:582
+#: src/Model/Event.php:583
 msgid "Duplicate event"
 msgstr "Veranstaltung kopieren"
 
-#: src/Model/Event.php:583
+#: src/Model/Event.php:584
 msgid "Delete event"
 msgstr "Veranstaltung löschen"
 
-#: src/Model/Event.php:830
+#: src/Model/Event.php:837
 msgid "D g:i A"
 msgstr "D H:i"
 
-#: src/Model/Event.php:831
+#: src/Model/Event.php:838
 msgid "g:i A"
 msgstr "H:i"
 
-#: src/Model/Event.php:916 src/Model/Event.php:918
+#: src/Model/Event.php:923 src/Model/Event.php:925
 msgid "Show map"
 msgstr "Karte anzeigen"
 
-#: src/Model/Event.php:917
+#: src/Model/Event.php:924
 msgid "Hide map"
 msgstr "Karte verbergen"
 
@@ -8742,7 +8767,7 @@ msgstr "Bei der Erstellung des Standardprofils ist ein Fehler aufgetreten. Bitte
 msgid "An error occurred creating your self contact. Please try again."
 msgstr "Bei der Erstellung deines self Kontakts ist ein Fehler aufgetreten. Bitte versuche es erneut."
 
-#: src/Model/User.php:561 src/Content/ContactSelector.php:166
+#: src/Model/User.php:561 src/Content/ContactSelector.php:171
 msgid "Friends"
 msgstr "Kontakte"
 
@@ -8837,129 +8862,129 @@ msgstr "Neue Gruppe erstellen"
 msgid "Edit groups"
 msgstr "Gruppen bearbeiten"
 
-#: src/Model/Profile.php:97
+#: src/Model/Profile.php:110
 msgid "Requested account is not available."
 msgstr "Das angefragte Profil ist nicht vorhanden."
 
-#: src/Model/Profile.php:163 src/Model/Profile.php:399
-#: src/Model/Profile.php:846
+#: src/Model/Profile.php:176 src/Model/Profile.php:412
+#: src/Model/Profile.php:859
 msgid "Edit profile"
 msgstr "Profil bearbeiten"
 
-#: src/Model/Profile.php:333
+#: src/Model/Profile.php:346
 msgid "Atom feed"
 msgstr "Atom-Feed"
 
-#: src/Model/Profile.php:372
+#: src/Model/Profile.php:385
 msgid "Manage/edit profiles"
 msgstr "Profile verwalten/editieren"
 
-#: src/Model/Profile.php:550 src/Model/Profile.php:639
+#: src/Model/Profile.php:563 src/Model/Profile.php:652
 msgid "g A l F d"
 msgstr "l, d. F G \\U\\h\\r"
 
-#: src/Model/Profile.php:551
+#: src/Model/Profile.php:564
 msgid "F d"
 msgstr "d. F"
 
-#: src/Model/Profile.php:604 src/Model/Profile.php:690
+#: src/Model/Profile.php:617 src/Model/Profile.php:703
 msgid "[today]"
 msgstr "[heute]"
 
-#: src/Model/Profile.php:615
+#: src/Model/Profile.php:628
 msgid "Birthday Reminders"
 msgstr "Geburtstagserinnerungen"
 
-#: src/Model/Profile.php:616
+#: src/Model/Profile.php:629
 msgid "Birthdays this week:"
 msgstr "Geburtstage diese Woche:"
 
-#: src/Model/Profile.php:677
+#: src/Model/Profile.php:690
 msgid "[No description]"
 msgstr "[keine Beschreibung]"
 
-#: src/Model/Profile.php:704
+#: src/Model/Profile.php:717
 msgid "Event Reminders"
 msgstr "Veranstaltungserinnerungen"
 
-#: src/Model/Profile.php:705
+#: src/Model/Profile.php:718
 msgid "Upcoming events the next 7 days:"
 msgstr "Veranstaltungen der nächsten 7 Tage:"
 
-#: src/Model/Profile.php:728
+#: src/Model/Profile.php:741
 msgid "Member since:"
 msgstr "Mitglied seit:"
 
-#: src/Model/Profile.php:736
+#: src/Model/Profile.php:749
 msgid "j F, Y"
 msgstr "j F, Y"
 
-#: src/Model/Profile.php:737
+#: src/Model/Profile.php:750
 msgid "j F"
 msgstr "j F"
 
-#: src/Model/Profile.php:752
+#: src/Model/Profile.php:765
 msgid "Age:"
 msgstr "Alter:"
 
-#: src/Model/Profile.php:765
+#: src/Model/Profile.php:778
 #, php-format
 msgid "for %1$d %2$s"
 msgstr "für %1$d %2$s"
 
-#: src/Model/Profile.php:789
+#: src/Model/Profile.php:802
 msgid "Religion:"
 msgstr "Religion:"
 
-#: src/Model/Profile.php:797
+#: src/Model/Profile.php:810
 msgid "Hobbies/Interests:"
 msgstr "Hobbies/Interessen:"
 
-#: src/Model/Profile.php:809
+#: src/Model/Profile.php:822
 msgid "Contact information and Social Networks:"
 msgstr "Kontaktinformationen und Soziale Netzwerke:"
 
-#: src/Model/Profile.php:813
+#: src/Model/Profile.php:826
 msgid "Musical interests:"
 msgstr "Musikalische Interessen:"
 
-#: src/Model/Profile.php:817
+#: src/Model/Profile.php:830
 msgid "Books, literature:"
 msgstr "Literatur/Bücher:"
 
-#: src/Model/Profile.php:821
+#: src/Model/Profile.php:834
 msgid "Television:"
 msgstr "Fernsehen:"
 
-#: src/Model/Profile.php:825
+#: src/Model/Profile.php:838
 msgid "Film/dance/culture/entertainment:"
 msgstr "Filme/Tänze/Kultur/Unterhaltung:"
 
-#: src/Model/Profile.php:829
+#: src/Model/Profile.php:842
 msgid "Love/Romance:"
 msgstr "Liebesleben:"
 
-#: src/Model/Profile.php:833
+#: src/Model/Profile.php:846
 msgid "Work/employment:"
 msgstr "Arbeit/Beschäftigung:"
 
-#: src/Model/Profile.php:837
+#: src/Model/Profile.php:850
 msgid "School/education:"
 msgstr "Schule/Ausbildung:"
 
-#: src/Model/Profile.php:842
+#: src/Model/Profile.php:855
 msgid "Forums:"
 msgstr "Foren:"
 
-#: src/Model/Profile.php:936
+#: src/Model/Profile.php:949
 msgid "Only You Can See This"
 msgstr "Nur Du kannst das sehen"
 
-#: src/Model/Profile.php:944 src/Model/Profile.php:947
+#: src/Model/Profile.php:957 src/Model/Profile.php:960
 msgid "Tips for New Members"
 msgstr "Tipps für neue Nutzer"
 
-#: src/Model/Profile.php:1106
+#: src/Model/Profile.php:1119
 #, php-format
 msgid "OpenWebAuth: %1$s welcomes %2$s"
 msgstr "OpenWebAuth: %1$s heißt %2$sherzlich willkommen"
@@ -8983,27 +9008,27 @@ msgid_plural "%d invitations available"
 msgstr[0] "%d Einladung verfügbar"
 msgstr[1] "%d Einladungen verfügbar"
 
-#: src/Content/Widget.php:157
+#: src/Content/Widget.php:154
 msgid "Networks"
 msgstr "Netzwerke"
 
-#: src/Content/Widget.php:160
+#: src/Content/Widget.php:157
 msgid "All Networks"
 msgstr "Alle Netzwerke"
 
-#: src/Content/Widget.php:198 src/Content/Feature.php:118
+#: src/Content/Widget.php:195 src/Content/Feature.php:118
 msgid "Saved Folders"
 msgstr "Gespeicherte Ordner"
 
-#: src/Content/Widget.php:201 src/Content/Widget.php:241
+#: src/Content/Widget.php:198 src/Content/Widget.php:238
 msgid "Everything"
 msgstr "Alles"
 
-#: src/Content/Widget.php:238
+#: src/Content/Widget.php:235
 msgid "Categories"
 msgstr "Kategorien"
 
-#: src/Content/Widget.php:305
+#: src/Content/Widget.php:302
 #, php-format
 msgid "%d contact in common"
 msgid_plural "%d contacts in common"
@@ -9079,230 +9104,234 @@ msgid "GNU Social Connector"
 msgstr "GNU social Connector"
 
 #: src/Content/ContactSelector.php:92
+msgid "ActivityPub"
+msgstr "ActivityPub"
+
+#: src/Content/ContactSelector.php:93
 msgid "pnut"
 msgstr "pnut"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Male"
 msgstr "Männlich"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Female"
 msgstr "Weiblich"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Male"
 msgstr "Momentan männlich"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Female"
 msgstr "Momentan weiblich"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Male"
 msgstr "Hauptsächlich männlich"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Female"
 msgstr "Hauptsächlich weiblich"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transgender"
 msgstr "Transgender"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Intersex"
 msgstr "Intersex"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transsexual"
 msgstr "Transsexuell"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Hermaphrodite"
 msgstr "Hermaphrodit"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Neuter"
 msgstr "Neuter"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Non-specific"
 msgstr "Nicht spezifiziert"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Other"
 msgstr "Andere"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Males"
 msgstr "Männer"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Females"
 msgstr "Frauen"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Gay"
 msgstr "Schwul"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Lesbian"
 msgstr "Lesbisch"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "No Preference"
 msgstr "Keine Vorlieben"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Bisexual"
 msgstr "Bisexuell"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Autosexual"
 msgstr "Autosexual"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Abstinent"
 msgstr "Abstinent"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Virgin"
 msgstr "Jungfrauen"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Deviant"
 msgstr "Deviant"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Fetish"
 msgstr "Fetish"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Oodles"
 msgstr "Oodles"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Nonsexual"
 msgstr "Nonsexual"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Single"
 msgstr "Single"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Lonely"
 msgstr "Einsam"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Available"
 msgstr "Verfügbar"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unavailable"
 msgstr "Nicht verfügbar"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Has crush"
 msgstr "verknallt"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Infatuated"
 msgstr "verliebt"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Dating"
 msgstr "Dating"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unfaithful"
 msgstr "Untreu"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Sex Addict"
 msgstr "Sexbesessen"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Friends/Benefits"
 msgstr "Freunde/Zuwendungen"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Casual"
 msgstr "Casual"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Engaged"
 msgstr "Verlobt"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Married"
 msgstr "Verheiratet"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily married"
 msgstr "imaginär verheiratet"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Partners"
 msgstr "Partner"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Cohabiting"
 msgstr "zusammenlebend"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Common law"
 msgstr "wilde Ehe"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Happy"
 msgstr "Glücklich"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Not looking"
 msgstr "Nicht auf der Suche"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Swinger"
 msgstr "Swinger"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Betrayed"
 msgstr "Betrogen"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Separated"
 msgstr "Getrennt"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unstable"
 msgstr "Unstabil"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Divorced"
 msgstr "Geschieden"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily divorced"
 msgstr "imaginär geschieden"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Widowed"
 msgstr "Verwitwet"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Uncertain"
 msgstr "Unsicher"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "It's complicated"
 msgstr "Ist kompliziert"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Don't care"
 msgstr "Ist mir nicht wichtig"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Ask me"
 msgstr "Frag mich"
 
@@ -9649,27 +9678,27 @@ msgstr "Einbettungen deaktiviert"
 msgid "Embedded content"
 msgstr "Eingebetteter Inhalt"
 
-#: src/Content/Text/BBCode.php:423
+#: src/Content/Text/BBCode.php:422
 msgid "view full size"
 msgstr "Volle Größe anzeigen"
 
-#: src/Content/Text/BBCode.php:853 src/Content/Text/BBCode.php:1626
-#: src/Content/Text/BBCode.php:1627
+#: src/Content/Text/BBCode.php:854 src/Content/Text/BBCode.php:1623
+#: src/Content/Text/BBCode.php:1624
 msgid "Image/photo"
 msgstr "Bild/Foto"
 
-#: src/Content/Text/BBCode.php:1553 src/Content/Text/BBCode.php:1575
+#: src/Content/Text/BBCode.php:1550 src/Content/Text/BBCode.php:1572
 msgid "$1 wrote:"
 msgstr "$1 hat geschrieben:"
 
-#: src/Content/Text/BBCode.php:1635 src/Content/Text/BBCode.php:1636
+#: src/Content/Text/BBCode.php:1632 src/Content/Text/BBCode.php:1633
 msgid "Encrypted content"
 msgstr "Verschlüsselter Inhalt"
 
-#: src/Content/Text/BBCode.php:1755
+#: src/Content/Text/BBCode.php:1752
 msgid "Invalid source protocol"
 msgstr "Ungültiges Quell-Protokoll"
 
-#: src/Content/Text/BBCode.php:1766
+#: src/Content/Text/BBCode.php:1763
 msgid "Invalid link protocol"
 msgstr "Ungültiges Link-Protokoll"
index 675f995a26906628398b97070e0281e1280cbcf7..f80bf544bbcdb3df2da8a98fa8cdb9e4e01c2a5a 100644 (file)
@@ -701,6 +701,7 @@ $a->strings["Results for: %s"] = "Ergebnisse für: %s";
 $a->strings["No contacts in common."] = "Keine gemeinsamen Kontakte.";
 $a->strings["Common Friends"] = "Gemeinsame Kontakte";
 $a->strings["Login"] = "Anmeldung";
+$a->strings["Bad Request"] = "Ungültige Anfrage";
 $a->strings["The post was created"] = "Der Beitrag wurde angelegt";
 $a->strings["add"] = "hinzufügen";
 $a->strings["Warning: This group contains %s member from a network that doesn't allow non public messages."] = [
@@ -768,13 +769,12 @@ $a->strings["Keep this window open until done."] = "Lasse dieses Fenster offen,
 $a->strings["Access denied."] = "Zugriff verweigert.";
 $a->strings["No contacts."] = "Keine Kontakte.";
 $a->strings["Visit %s's profile [%s]"] = "Besuche %ss Profil [%s]";
-$a->strings["Contact wasn't found or can't be unfollowed."] = "Der Kontakt konnte nicht gefunden oder nicht entfolgt werden.";
-$a->strings["Contact unfollowed"] = "Kontakt wird nicht mehr gefolgt";
-$a->strings["Submit Request"] = "Anfrage abschicken";
-$a->strings["You aren't a friend of this contact."] = "Du hast keine beidseitige Freundschaft mit diesem Kontakt.";
+$a->strings["You aren't following this contact."] = "Du folgst diesem Kontakt.";
 $a->strings["Unfollowing is currently not supported by your network."] = "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt.";
+$a->strings["Contact unfollowed"] = "Kontakt wird nicht mehr gefolgt";
 $a->strings["Disconnect/Unfollow"] = "Verbindung lösen/Nicht mehr folgen";
 $a->strings["Your Identity Address:"] = "Adresse Deines Profils:";
+$a->strings["Submit Request"] = "Anfrage abschicken";
 $a->strings["Profile URL"] = "Profil URL";
 $a->strings["Status Messages and Posts"] = "Statusnachrichten und Beiträge";
 $a->strings["[Embedded content - reload page to view]"] = "[Eingebetteter Inhalt - Seite neu laden zum Betrachten]";
@@ -811,6 +811,8 @@ $a->strings["Network Notifications"] = "Netzwerk Benachrichtigungen";
 $a->strings["System Notifications"] = "Systembenachrichtigungen";
 $a->strings["Personal Notifications"] = "Persönliche Benachrichtigungen";
 $a->strings["Home Notifications"] = "Pinnwand Benachrichtigungen";
+$a->strings["Show unread"] = "Ungelesene anzeigen";
+$a->strings["Show all"] = "Alle anzeigen";
 $a->strings["Show Ignored Requests"] = "Zeige ignorierte Anfragen";
 $a->strings["Hide Ignored Requests"] = "Verberge ignorierte Anfragen";
 $a->strings["Notification type:"] = "Art der Benachrichtigung:";
@@ -830,8 +832,6 @@ $a->strings["Subscriber"] = "Abonnent";
 $a->strings["Tags:"] = "Tags:";
 $a->strings["Network:"] = "Netzwerk:";
 $a->strings["No introductions."] = "Keine Kontaktanfragen.";
-$a->strings["Show unread"] = "Ungelesene anzeigen";
-$a->strings["Show all"] = "Alle anzeigen";
 $a->strings["No more %s notifications."] = "Keine weiteren %s Benachrichtigungen";
 $a->strings["New Message"] = "Neue Nachricht";
 $a->strings["Unable to locate contact information."] = "Konnte die Kontaktinformationen nicht finden.";
@@ -953,11 +953,14 @@ $a->strings["BBCode::toMarkdown"] = "BBCode::toMarkdown";
 $a->strings["BBCode::toMarkdown => Markdown::convert"] = "BBCode::toMarkdown => Markdown::convert";
 $a->strings["BBCode::toMarkdown => Markdown::toBBCode"] = "BBCode::toMarkdown => Markdown::toBBCode";
 $a->strings["BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"] = "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode";
-$a->strings["Source input \\x28Diaspora format\\x29"] = "Original Text \\x28Diaspora Fromat\\x29";
+$a->strings["Source input (Diaspora format)"] = "Originaltext (Diaspora Format): ";
+$a->strings["Markdown::convert (raw HTML)"] = "Markdown::convert (raw HTML)";
+$a->strings["Markdown::convert"] = "Markdown::convert";
 $a->strings["Markdown::toBBCode"] = "Markdown::toBBCode";
 $a->strings["Raw HTML input"] = "Reine  HTML  Eingabe";
 $a->strings["HTML Input"] = "HTML Eingabe";
 $a->strings["HTML::toBBCode"] = "HTML::toBBCode";
+$a->strings["HTML::toMarkdown"] = "HTML::toMarkdown";
 $a->strings["HTML::toPlaintext"] = "HTML::toPlaintext";
 $a->strings["Source text"] = "Quelltext";
 $a->strings["BBCode"] = "BBCode";
@@ -1062,7 +1065,7 @@ $a->strings["The database update failed. Please run \"php bin/console.php dbstru
 $a->strings["The worker was never executed. Please check your database structure!"] = "Der Hintergrundprozess (worker) wurde noch nie gestartet. Bitte überprüfe deine Datenbankstruktur.";
 $a->strings["The last worker execution was on %s UTC. This is older than one hour. Please check your crontab settings."] = "Der Hintergrundprozess (worker) wurde zuletzt um %s UTC ausgeführt. Das war vor mehr als einer Stunde. Bitte überprüfe deine crontab Einstellungen.";
 $a->strings["Friendica's configuration now is stored in config/local.ini.php, please copy config/local-sample.ini.php and move your config from <code>.htconfig.php</code>. See <a href=\"%s\">the Config help page</a> for help with the transition."] = "Die Konfiguration von Friendica befindet sich ab jetzt in der 'config/local.ini.php' Datei. Kopiere bitte die Datei  'config/local-sample.ini.php' nach 'config/local.ini.php' und setze die Konfigurationvariablen so wie in der alten <code>.htconfig.php</code>. Wie die Übertragung der Werte aussehen muss kannst du der <a href=\"%s\">Konfiguration Hilfeseite</a> entnehmen.";
-$a->strings["<a href=\"%s\">%s</a> is not reachable on your system. This is a servere configuration issue that prevents the communication.. See <a href=\"%s\">the installation page</a> for help."] = "<a href=\"%s\">%s</a> konnte von deinem System nicht aufgerufen werden. Dies deitet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere <a href=\"%s\">die Installations-Dokumentation</a> zum Beheben des Problems.";
+$a->strings["<a href=\"%s\">%s</a> is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See <a href=\"%s\">the installation page</a> for help."] = "<a href=\"%s\">%s</a> konnte von deinem System nicht aufgerufen werden. Dies deitet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere <a href=\"%s\">die Installations-Dokumentation</a> zum Beheben des Problems.";
 $a->strings["Normal Account"] = "Normales Konto";
 $a->strings["Automatic Follower Account"] = "Automatisch folgendes Konto (Marktschreier)";
 $a->strings["Public Forum Account"] = "Öffentliches Forum Konto";
@@ -1186,8 +1189,8 @@ $a->strings["Posts per user on community page"] = "Anzahl der Beiträge pro Benu
 $a->strings["The maximum number of posts per user on the community page. (Not valid for 'Global Community')"] = "Die Anzahl der Beiträge die von jedem Nutzer maximal auf der Gemeinschaftsseite angezeigt werden sollen. Dieser Parameter wird nicht für die Globale Gemeinschaftsseite genutzt.";
 $a->strings["Enable OStatus support"] = "OStatus Unterstützung aktivieren";
 $a->strings["Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed."] = "Biete die eingebaute OStatus (iStatusNet, GNU Social, etc.) Unterstützung an. Jede Kommunikation in OStatus ist öffentlich, Privatsphäre Warnungen werden nur bei Bedarf angezeigt.";
-$a->strings["Only import OStatus threads from our contacts"] = "Nur OStatus Konversationen unserer Kontakte importieren";
-$a->strings["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."] = "Normalerweise werden alle Inhalte von OStatus Kontakten importiert. Mit dieser Option werden nur solche Konversationen gespeichert, die von Kontakten der Nutzer dieses Knotens gestartet wurden.";
+$a->strings["Only import OStatus/ActivityPub threads from our contacts"] = "Nur OStatus/ActivityPub Konversationen unserer Kontakte importieren";
+$a->strings["Normally we import every content from our OStatus and ActivityPub contacts. With this option we only store threads that are started by a contact that is known on our system."] = "Normalerweise werden alle Inhalte von OStatus und ActivityPub Kontakten importiert. Mit dieser Option werden nur solche Konversationen gespeichert, die von Kontakten der Nutzer dieses Knotens gestartet wurden.";
 $a->strings["OStatus support can only be enabled if threading is enabled."] = "OStatus Unterstützung kann nur aktiviert werden wenn \"Threading\" aktiviert ist. ";
 $a->strings["Diaspora support can't be enabled because Friendica was installed into a sub directory."] = "Diaspora Unterstützung kann nicht aktiviert werden da Friendica in ein Unterverzeichnis installiert ist.";
 $a->strings["Enable Diaspora support"] = "Diaspora Unterstützung aktivieren";
@@ -1425,6 +1428,7 @@ $a->strings["You may visit them online at %s"] = "Du kannst sie online unter %s
 $a->strings["Please contact the sender by replying to this post if you do not wish to receive these messages."] = "Falls Du diese Beiträge nicht erhalten möchtest, kontaktiere bitte den Autor, indem Du auf diese Nachricht antwortest.";
 $a->strings["%s posted an update."] = "%s hat ein Update veröffentlicht.";
 $a->strings["Help:"] = "Hilfe:";
+$a->strings["User imports on closed servers can only be done by an administrator."] = "Auf geschlossenen Servern können ausschließlich die Administratoren Benutzerkonten importieren.";
 $a->strings["Move account"] = "Account umziehen";
 $a->strings["You can import an account from another Friendica server."] = "Du kannst einen Account von einem anderen Friendica Server importieren.";
 $a->strings["You need to export your account from the old server and upload it here. We will recreate your old account here with all your contacts. We will try also to inform your friends that you moved here."] = "Du musst Deinen Account vom alten Server exportieren und hier hochladen. Wir stellen Deinen alten Account mit all Deinen Kontakten wieder her. Wir werden auch versuchen all Deine Kontakte darüber zu informieren, dass Du hierher umgezogen bist.";
@@ -1819,6 +1823,7 @@ $a->strings["Visible to everybody"] = "Für jeden sichtbar";
 $a->strings["Close"] = "Schließen";
 $a->strings["Could not find any unarchived contact entry for this URL (%s)"] = "Für die URL (%s) konnte kein nicht-archivierter Kontakt gefunden werden";
 $a->strings["The contact entries have been archived"] = "Die Kontakteinträge wurden archiviert.";
+$a->strings["Post update version number has been set to %s."] = "Die Post-Update Versionsnummer wurde auf %s gesetzt.";
 $a->strings["Execute pending post updates."] = "Ausstehende Post-Updates ausführen";
 $a->strings["All pending post updates are done."] = "Alle ausstehenden Post-Updates wurden ausgeführt.";
 $a->strings["Enter new password: "] = "Neues Passwort eingeben:";
@@ -1902,6 +1907,7 @@ $a->strings["At the time of registration, and for providing communications betwe
 $a->strings["This data is required for communication and is passed on to the nodes of the communication partners and is stored there. Users can enter additional private data that may be transmitted to the communication partners accounts."] = "Diese Daten sind für die Kommunikation notwendig und werden an die Knoten der Kommunikationspartner übermittelt. und werden dort gespeichert Nutzer können weitere private Angaben machen, die ebenfalls an die verwendeten Server der Kommunikationspartner übermittelt werden können.";
 $a->strings["At any point in time a logged in user can export their account data from the <a href=\"%1\$s/settings/uexport\">account settings</a>. If the user wants to delete their account they can do so at <a href=\"%1\$s/removeme\">%1\$s/removeme</a>. The deletion of the account will be permanent. Deletion of the data will also be requested from the nodes of the communication partners."] = "Angemeldete Nutzer können ihre Nutzerdaten jederzeit von den <a href=\"%1\$s/settings/uexport\">Kontoeinstellungen</a> aus exportieren. Wenn ein Nutzer wünscht das Nutzerkonto zu löschen, so ist dies jederzeit unter <a href=\"%1\$s/removeme\">%1\$s/removeme</a> möglich. Die Löschung des Nutzerkontos ist permanent. Die Löschung der Daten wird auch von den Knoten der Kommunikationspartner angefordert.";
 $a->strings["Privacy Statement"] = "Datenschutzerklärung";
+$a->strings["Bad Request."] = "Ungültige Anfrage.";
 $a->strings["%s is now following %s."] = "%s folgt nun %s";
 $a->strings["following"] = "folgen";
 $a->strings["%s stopped following %s."] = "%s hat aufgehört %s zu folgen";
@@ -2053,6 +2059,7 @@ $a->strings["pump.io"] = "pump.io";
 $a->strings["Twitter"] = "Twitter";
 $a->strings["Diaspora Connector"] = "Diaspora Connector";
 $a->strings["GNU Social Connector"] = "GNU social Connector";
+$a->strings["ActivityPub"] = "ActivityPub";
 $a->strings["pnut"] = "pnut";
 $a->strings["Male"] = "Männlich";
 $a->strings["Female"] = "Weiblich";
index cf922f22f649eb9e025d158559482b22842f3ca7..fc1e93a2062c3787c1955522784641740d4e949f 100644 (file)
@@ -4,43 +4,60 @@
 # 
 # Translators:
 # Adam Jurkiewicz <a.jurkiewicz@abix.info.pl>, 2012
+# Adam Jurkiewicz <a.jurkiewicz@abix.info.pl>, 2012
 # julia.domagalska <domagalskajulia@gmail.com>, 2013,2015
 # julia.domagalska <domagalskajulia@gmail.com>, 2012-2013
 # Daria Początek <charizard@autograf.pl>, 2012
 # Cyryl Sochacki <cyrylsochacki@gmail.com>, 2013
 # czarnystokrotek <czarnystokrotek@mailoo.org>, 2012
-# Daria Początek <charizard@autograf.pl>, 2013
+# czarnystokrotek <czarnystokrotek@mailoo.org>, 2012
+# Daria Początek <charizard@autograf.pl>, 2012-2013
 # Radek <d.exax@hotmail.com>, 2012
+# emilia.krawczyk <rightxhere1@gmail.com>, 2012
 # TORminator <dominik+foss@danelski.pl>, 2014
+# Filip Bugaj <johnnywiertara@gmail.com>, 2012
 # Hubert Kościański <hubertkoscianski@op.pl>, 2012
+# Hubert Kościański <hubertkoscianski@op.pl>, 2012
+# Jakob <jakub.hag96@gmail.com>, 2012
 # Jakob <jakub.hag96@gmail.com>, 2012
 # Mateusz Mikos <jawiadomokto@o2.pl>, 2012
 # Filip Bugaj <johnnywiertara@gmail.com>, 2012
+# julia.domagalska <domagalskajulia@gmail.com>, 2013,2015
 # Karolina <karolinaa9506@gmail.com>, 2012
-# Karolina <karolinaa9506@gmail.com>, 2013
+# Karolina <karolinaa9506@gmail.com>, 2012-2013
 # szymon.filip <koalamis0@gmail.com>, 2013
 # szymon.filip <koalamis0@gmail.com>, 2012
+# Lea1995polish <m.dauter@tlen.pl>, 2012
+# Magdalena Gazda <inactive+MagdaPortu@transifex.com>, 2013
 # Mai Anh Nguyen <maianhania@yahoo.com>, 2013
+# Marcin Klessa <nauczyciello@o2.pl>, 2012
+# Marcin Mikołajczak <me@m4sk.in>, 2018
 # Mariusz Pisz <mariusz.pisz@zhp.net.pl>, 2013
+# Mateusz Mikos <jawiadomokto@o2.pl>, 2012
 # Lea1995polish <m.dauter@tlen.pl>, 2012
 # Magdalena Gazda <inactive+MagdaPortu@transifex.com>, 2013
 # mhnxo <mhnxo123@gmail.com>, 2012
+# mhnxo <mhnxo123@gmail.com>, 2012
+# Michalina <michalina-korzeniowska@wp.pl>, 2012
 # Michalina <michalina-korzeniowska@wp.pl>, 2012
 # Marcin Klessa <nauczyciello@o2.pl>, 2012
 # Piotr Blonkowski <piotr.blonkowski@gmail.com>, 2012-2013
-# Radek <d.exax@hotmail.com>, 2013
+# Radek <d.exax@hotmail.com>, 2012-2013
 # emilia.krawczyk <rightxhere1@gmail.com>, 2012
 # Sam, 2013
+# Sam, 2013
 # rcmaniac <szsargalski@interia.pl>, 2012-2013
+# szymon.filip <koalamis0@gmail.com>, 2012-2013
 # Tobias Diekershoff <tobias.diekershoff@gmx.net>, 2018
+# TORminator <dominik+foss@danelski.pl>, 2014
 # Waldemar Stoczkowski <waldemar.stoczkowski@gmail.com>, 2018
 # Waldemar Stoczkowski <waldemar.stoczkowski@gmail.com>, 2018
 msgid ""
 msgstr ""
 "Project-Id-Version: friendica\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-25 15:34+0000\n"
-"PO-Revision-Date: 2018-08-26 14:19+0000\n"
+"POT-Creation-Date: 2018-09-27 21:18+0000\n"
+"PO-Revision-Date: 2018-10-05 16:09+0000\n"
 "Last-Translator: Waldemar Stoczkowski <waldemar.stoczkowski@gmail.com>\n"
 "Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n"
 "MIME-Version: 1.0\n"
@@ -49,47 +66,47 @@ msgstr ""
 "Language: pl\n"
 "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
 
-#: index.php:261 mod/apps.php:14
+#: index.php:265 mod/apps.php:14
 msgid "You must be logged in to use addons. "
-msgstr "Musisz być zalogowany, aby korzystać z dodatków."
+msgstr "Musisz być zalogowany(-a), aby korzystać z dodatków. "
 
-#: index.php:308 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
+#: index.php:312 mod/fetch.php:20 mod/fetch.php:47 mod/fetch.php:54
 #: mod/help.php:62
 msgid "Not Found"
 msgstr "Nie znaleziono"
 
-#: index.php:313 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
+#: index.php:317 mod/viewcontacts.php:35 mod/dfrn_poll.php:486 mod/help.php:65
 #: mod/cal.php:44
 msgid "Page not found."
 msgstr "Strona nie znaleziona."
 
-#: index.php:431 mod/group.php:83 mod/profperm.php:29
+#: index.php:435 mod/group.php:83 mod/profperm.php:29
 msgid "Permission denied"
 msgstr "Odmowa dostępu"
 
-#: index.php:432 include/items.php:412 mod/crepair.php:100
+#: index.php:436 include/items.php:413 mod/crepair.php:100
 #: mod/wallmessage.php:16 mod/wallmessage.php:40 mod/wallmessage.php:79
-#: mod/wallmessage.php:103 mod/dfrn_confirm.php:66 mod/dirfind.php:27
+#: mod/wallmessage.php:103 mod/dfrn_confirm.php:67 mod/dirfind.php:27
 #: mod/manage.php:131 mod/settings.php:43 mod/settings.php:149
 #: mod/settings.php:665 mod/common.php:28 mod/network.php:34 mod/group.php:26
 #: mod/delegate.php:27 mod/delegate.php:45 mod/delegate.php:56
-#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:17
-#: mod/unfollow.php:59 mod/unfollow.php:93 mod/register.php:53
+#: mod/repair_ostatus.php:16 mod/viewcontacts.php:60 mod/unfollow.php:20
+#: mod/unfollow.php:73 mod/unfollow.php:105 mod/register.php:53
 #: mod/notifications.php:67 mod/message.php:60 mod/message.php:105
 #: mod/ostatus_subscribe.php:17 mod/nogroup.php:23 mod/suggest.php:61
 #: mod/wall_upload.php:104 mod/wall_upload.php:107 mod/api.php:35
 #: mod/api.php:40 mod/profile_photo.php:29 mod/profile_photo.php:176
 #: mod/profile_photo.php:198 mod/wall_attach.php:80 mod/wall_attach.php:83
-#: mod/item.php:166 mod/uimport.php:28 mod/cal.php:306 mod/regmod.php:108
+#: mod/item.php:166 mod/uimport.php:15 mod/cal.php:306 mod/regmod.php:108
 #: mod/editpost.php:19 mod/fsuggest.php:80 mod/allfriends.php:23
-#: mod/contacts.php:381 mod/events.php:193 mod/follow.php:54
-#: mod/follow.php:118 mod/attach.php:39 mod/poke.php:145 mod/invite.php:21
+#: mod/contacts.php:387 mod/events.php:195 mod/follow.php:54
+#: mod/follow.php:118 mod/attach.php:39 mod/poke.php:144 mod/invite.php:21
 #: mod/invite.php:112 mod/notes.php:32 mod/profiles.php:179
-#: mod/profiles.php:511 mod/photos.php:183 mod/photos.php:1065
+#: mod/profiles.php:511 mod/photos.php:183 mod/photos.php:1067
 msgid "Permission denied."
 msgstr "Brak uprawnień."
 
-#: index.php:460
+#: index.php:464
 msgid "toggle mobile"
 msgstr "przełącz na mobilny"
 
@@ -123,13 +140,13 @@ msgstr "luźny"
 
 #: view/theme/duepuntozero/config.php:71 view/theme/quattro/config.php:73
 #: view/theme/vier/config.php:119 view/theme/frio/config.php:118
-#: mod/crepair.php:150 mod/install.php:206 mod/install.php:244
+#: mod/crepair.php:150 mod/install.php:204 mod/install.php:242
 #: mod/manage.php:184 mod/message.php:264 mod/message.php:430
-#: mod/fsuggest.php:114 mod/contacts.php:630 mod/events.php:533
-#: mod/localtime.php:56 mod/poke.php:195 mod/invite.php:155
-#: mod/profiles.php:577 mod/photos.php:1094 mod/photos.php:1180
-#: mod/photos.php:1452 mod/photos.php:1497 mod/photos.php:1536
-#: mod/photos.php:1596 src/Object/Post.php:795
+#: mod/fsuggest.php:114 mod/contacts.php:631 mod/events.php:560
+#: mod/localtime.php:56 mod/poke.php:194 mod/invite.php:155
+#: mod/profiles.php:577 mod/photos.php:1096 mod/photos.php:1182
+#: mod/photos.php:1454 mod/photos.php:1499 mod/photos.php:1538
+#: mod/photos.php:1598 src/Object/Post.php:795
 msgid "Submit"
 msgstr "Potwierdź"
 
@@ -217,8 +234,8 @@ msgstr "Wpisz nazwę lub zainteresowanie"
 
 #: view/theme/vier/theme.php:199 include/conversation.php:881
 #: mod/dirfind.php:231 mod/match.php:90 mod/suggest.php:86
-#: mod/allfriends.php:76 mod/contacts.php:604 mod/contacts.php:610
-#: mod/follow.php:143 src/Model/Contact.php:933 src/Content/Widget.php:61
+#: mod/allfriends.php:76 mod/contacts.php:611 mod/follow.php:143
+#: src/Model/Contact.php:944 src/Content/Widget.php:61
 msgid "Connect/Follow"
 msgstr "Połącz/Obserwuj"
 
@@ -226,7 +243,7 @@ msgstr "Połącz/Obserwuj"
 msgid "Examples: Robert Morgenstein, Fishing"
 msgstr "Przykład: Jan Kowalski, Wędkarstwo"
 
-#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:842
+#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contacts.php:845
 #: src/Content/Widget.php:63
 msgid "Find"
 msgstr "Znajdź"
@@ -250,25 +267,25 @@ msgstr "Zaproś znajomych"
 #: view/theme/vier/theme.php:206 mod/directory.php:207
 #: src/Content/Widget.php:68
 msgid "Global Directory"
-msgstr "Katalog Globalny"
+msgstr "Katalog globalny"
 
 #: view/theme/vier/theme.php:208 src/Content/Widget.php:70
 msgid "Local Directory"
 msgstr "Katalog lokalny"
 
 #: view/theme/vier/theme.php:251 include/text.php:909 src/Content/Nav.php:151
-#: src/Content/ForumManager.php:125
+#: src/Content/ForumManager.php:130
 msgid "Forums"
 msgstr "Fora"
 
-#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:127
+#: view/theme/vier/theme.php:253 src/Content/ForumManager.php:132
 msgid "External link to forum"
 msgstr "Zewnętrzny link do forum"
 
-#: view/theme/vier/theme.php:256 include/items.php:489 src/Object/Post.php:429
-#: src/App.php:786 src/Content/Widget.php:310 src/Content/ForumManager.php:130
+#: view/theme/vier/theme.php:256 include/items.php:490 src/Object/Post.php:429
+#: src/App.php:799 src/Content/Widget.php:307 src/Content/ForumManager.php:135
 msgid "show more"
-msgstr "Pokaż więcej"
+msgstr "pokaż więcej"
 
 #: view/theme/vier/theme.php:289
 msgid "Quick Start"
@@ -300,7 +317,7 @@ msgstr "Kolor tła paska nawigacyjnego"
 
 #: view/theme/frio/config.php:123
 msgid "Navigation bar icon color "
-msgstr "Kolor ikony paska nawigacyjnego"
+msgstr "Kolor ikon na pasku nawigacyjnym "
 
 #: view/theme/frio/config.php:124
 msgid "Link color"
@@ -351,8 +368,8 @@ msgstr "Wyloguj"
 msgid "End this session"
 msgstr "Zakończ sesję"
 
-#: view/theme/frio/theme.php:269 mod/contacts.php:689 mod/contacts.php:877
-#: src/Model/Profile.php:875 src/Content/Nav.php:100
+#: view/theme/frio/theme.php:269 mod/contacts.php:690 mod/contacts.php:880
+#: src/Model/Profile.php:888 src/Content/Nav.php:100
 msgid "Status"
 msgstr "Status"
 
@@ -362,8 +379,8 @@ msgid "Your posts and conversations"
 msgstr "Twoje posty i rozmowy"
 
 #: view/theme/frio/theme.php:270 mod/newmember.php:24 mod/profperm.php:116
-#: mod/contacts.php:691 mod/contacts.php:893 src/Model/Profile.php:717
-#: src/Model/Profile.php:850 src/Model/Profile.php:883 src/Content/Nav.php:101
+#: mod/contacts.php:692 mod/contacts.php:896 src/Model/Profile.php:730
+#: src/Model/Profile.php:863 src/Model/Profile.php:896 src/Content/Nav.php:101
 msgid "Profile"
 msgstr "Profil użytkownika"
 
@@ -371,7 +388,7 @@ msgstr "Profil użytkownika"
 msgid "Your profile page"
 msgstr "Twoja strona profilowa"
 
-#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:891
+#: view/theme/frio/theme.php:271 mod/fbrowser.php:35 src/Model/Profile.php:904
 #: src/Content/Nav.php:102
 msgid "Photos"
 msgstr "Zdjęcia"
@@ -380,8 +397,8 @@ msgstr "Zdjęcia"
 msgid "Your photos"
 msgstr "Twoje zdjęcia"
 
-#: view/theme/frio/theme.php:272 src/Model/Profile.php:899
-#: src/Model/Profile.php:902 src/Content/Nav.php:103
+#: view/theme/frio/theme.php:272 src/Model/Profile.php:912
+#: src/Model/Profile.php:915 src/Content/Nav.php:103
 msgid "Videos"
 msgstr "Filmy"
 
@@ -390,7 +407,7 @@ msgid "Your videos"
 msgstr "Twoje filmy"
 
 #: view/theme/frio/theme.php:273 view/theme/frio/theme.php:277 mod/cal.php:276
-#: mod/events.php:390 src/Model/Profile.php:911 src/Model/Profile.php:922
+#: mod/events.php:391 src/Model/Profile.php:924 src/Model/Profile.php:935
 #: src/Content/Nav.php:104 src/Content/Nav.php:170
 msgid "Events"
 msgstr "Wydarzenia"
@@ -408,8 +425,8 @@ msgstr "Sieć"
 msgid "Conversations from your friends"
 msgstr "Rozmowy Twoich przyjaciół"
 
-#: view/theme/frio/theme.php:277 src/Model/Profile.php:914
-#: src/Model/Profile.php:925 src/Content/Nav.php:170
+#: view/theme/frio/theme.php:277 src/Model/Profile.php:927
+#: src/Model/Profile.php:938 src/Content/Nav.php:170
 msgid "Events and Calendar"
 msgstr "Wydarzenia i kalendarz"
 
@@ -431,8 +448,8 @@ msgid "Account settings"
 msgstr "Ustawienia konta"
 
 #: view/theme/frio/theme.php:280 include/text.php:906 mod/viewcontacts.php:125
-#: mod/contacts.php:836 mod/contacts.php:905 src/Model/Profile.php:954
-#: src/Model/Profile.php:957 src/Content/Nav.php:147 src/Content/Nav.php:213
+#: mod/contacts.php:839 mod/contacts.php:908 src/Model/Profile.php:967
+#: src/Model/Profile.php:970 src/Content/Nav.php:147 src/Content/Nav.php:213
 msgid "Contacts"
 msgstr "Kontakty"
 
@@ -483,44 +500,44 @@ msgstr "Powtórz obraz, aby wypełnić ekran."
 #: update.php:194
 #, php-format
 msgid "%s: Updating author-id and owner-id in item and thread table. "
-msgstr "%s: Aktualizowanie ID autora i właściciela w tabeli pozycji i wątku."
+msgstr "%s: Aktualizowanie ID autora i właściciela w tabeli pozycji i wątku. "
 
 #: update.php:240
 #, php-format
 msgid "%s: Updating post-type."
 msgstr "%s: Aktualizowanie typu postu."
 
-#: include/items.php:355 mod/display.php:70 mod/display.php:245
-#: mod/display.php:341 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
+#: include/items.php:356 mod/display.php:71 mod/display.php:254
+#: mod/display.php:350 mod/admin.php:283 mod/admin.php:1963 mod/admin.php:2211
 #: mod/notice.php:22 mod/viewsrc.php:22
 msgid "Item not found."
 msgstr "Element nie znaleziony."
 
-#: include/items.php:393
+#: include/items.php:394
 msgid "Do you really want to delete this item?"
 msgstr "Czy na pewno chcesz usunąć ten element?"
 
-#: include/items.php:395 mod/settings.php:1100 mod/settings.php:1106
+#: include/items.php:396 mod/settings.php:1100 mod/settings.php:1106
 #: mod/settings.php:1113 mod/settings.php:1117 mod/settings.php:1121
 #: mod/settings.php:1125 mod/settings.php:1129 mod/settings.php:1133
 #: mod/settings.php:1153 mod/settings.php:1154 mod/settings.php:1155
 #: mod/settings.php:1156 mod/settings.php:1157 mod/register.php:237
 #: mod/message.php:154 mod/suggest.php:40 mod/dfrn_request.php:645
-#: mod/api.php:110 mod/contacts.php:465 mod/follow.php:150
+#: mod/api.php:110 mod/contacts.php:471 mod/follow.php:150
 #: mod/profiles.php:541 mod/profiles.php:544 mod/profiles.php:566
 msgid "Yes"
 msgstr "Tak"
 
-#: include/items.php:398 include/conversation.php:1179 mod/videos.php:146
-#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:120
+#: include/items.php:399 include/conversation.php:1179 mod/videos.php:146
+#: mod/settings.php:676 mod/settings.php:702 mod/unfollow.php:130
 #: mod/message.php:157 mod/tagrm.php:19 mod/tagrm.php:91 mod/suggest.php:43
-#: mod/dfrn_request.php:655 mod/editpost.php:140 mod/contacts.php:468
+#: mod/dfrn_request.php:655 mod/editpost.php:146 mod/contacts.php:474
 #: mod/follow.php:161 mod/fbrowser.php:104 mod/fbrowser.php:135
 #: mod/photos.php:255 mod/photos.php:327
 msgid "Cancel"
 msgstr "Anuluj"
 
-#: include/items.php:483 src/Content/Feature.php:96
+#: include/items.php:484 src/Content/Feature.php:96
 msgid "Archives"
 msgstr "Archiwum"
 
@@ -553,7 +570,7 @@ msgstr "%1$s nie lubi %2$s's %3$s"
 #: include/conversation.php:175
 #, php-format
 msgid "%1$s attends %2$s's %3$s"
-msgstr "%1$sbierze udział w %2$s's%3$s "
+msgstr "%1$s bierze udział w %2$s's %3$s"
 
 #: include/conversation.php:177
 #, php-format
@@ -589,16 +606,16 @@ msgstr "stanowisko/pozycja"
 msgid "%1$s marked %2$s's %3$s as favorite"
 msgstr "%1$s oznacz %2$s's %3$s jako ulubione"
 
-#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:352 mod/photos.php:1509
 msgid "Likes"
 msgstr "Lubię to"
 
-#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1507
+#: include/conversation.php:545 mod/profiles.php:356 mod/photos.php:1509
 msgid "Dislikes"
 msgstr "Nie lubię tego"
 
 #: include/conversation.php:546 include/conversation.php:1492
-#: mod/photos.php:1508
+#: mod/photos.php:1510
 msgid "Attending"
 msgid_plural "Attending"
 msgstr[0] "Uczestniczę"
@@ -606,20 +623,20 @@ msgstr[1] "Uczestniczy"
 msgstr[2] "Uczestniczą"
 msgstr[3] "Uczestniczą"
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Not attending"
 msgstr "Nie uczestniczę"
 
-#: include/conversation.php:546 mod/photos.php:1508
+#: include/conversation.php:546 mod/photos.php:1510
 msgid "Might attend"
 msgstr "Może wziąć udział"
 
-#: include/conversation.php:626 mod/photos.php:1564 src/Object/Post.php:195
+#: include/conversation.php:626 mod/photos.php:1566 src/Object/Post.php:195
 msgid "Select"
 msgstr "Wybierz"
 
 #: include/conversation.php:627 mod/settings.php:736 mod/admin.php:1906
-#: mod/contacts.php:852 mod/contacts.php:1130 mod/photos.php:1565
+#: mod/contacts.php:855 mod/contacts.php:1133 mod/photos.php:1567
 msgid "Delete"
 msgstr "Usuń"
 
@@ -648,7 +665,7 @@ msgstr "Zobacz w kontekście"
 
 #: include/conversation.php:698 include/conversation.php:1160
 #: mod/wallmessage.php:145 mod/message.php:263 mod/message.php:431
-#: mod/editpost.php:115 mod/photos.php:1480 src/Object/Post.php:401
+#: mod/editpost.php:121 mod/photos.php:1482 src/Object/Post.php:401
 msgid "Please wait"
 msgstr "Proszę czekać"
 
@@ -660,36 +677,36 @@ msgstr "usuń"
 msgid "Delete Selected Items"
 msgstr "Usuń zaznaczone elementy"
 
-#: include/conversation.php:867 src/Model/Contact.php:937
+#: include/conversation.php:867 src/Model/Contact.php:948
 msgid "View Status"
 msgstr "Zobacz status"
 
 #: include/conversation.php:868 include/conversation.php:884
 #: mod/dirfind.php:230 mod/directory.php:164 mod/match.php:89
-#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:877
-#: src/Model/Contact.php:930 src/Model/Contact.php:938
+#: mod/suggest.php:85 mod/allfriends.php:75 src/Model/Contact.php:888
+#: src/Model/Contact.php:941 src/Model/Contact.php:949
 msgid "View Profile"
 msgstr "Zobacz profil"
 
-#: include/conversation.php:869 src/Model/Contact.php:939
+#: include/conversation.php:869 src/Model/Contact.php:950
 msgid "View Photos"
 msgstr "Zobacz zdjęcia"
 
-#: include/conversation.php:870 src/Model/Contact.php:931
-#: src/Model/Contact.php:940
+#: include/conversation.php:870 src/Model/Contact.php:942
+#: src/Model/Contact.php:951
 msgid "Network Posts"
 msgstr "Wiadomości sieciowe"
 
-#: include/conversation.php:871 src/Model/Contact.php:932
-#: src/Model/Contact.php:941
+#: include/conversation.php:871 src/Model/Contact.php:943
+#: src/Model/Contact.php:952
 msgid "View Contact"
 msgstr "Pokaż kontakt"
 
-#: include/conversation.php:872 src/Model/Contact.php:943
+#: include/conversation.php:872 src/Model/Contact.php:954
 msgid "Send PM"
 msgstr "Wyślij prywatną wiadomość"
 
-#: include/conversation.php:876 src/Model/Contact.php:944
+#: include/conversation.php:876 src/Model/Contact.php:955
 msgid "Poke"
 msgstr "Zaczepka"
 
@@ -740,7 +757,7 @@ msgstr "%s lubię to."
 #: include/conversation.php:1041
 #, php-format
 msgid "<span  %1$s>%2$d people</span> don't like this"
-msgstr "<span  %1$s>%2$d ludzi </span>nie lubi tego "
+msgstr "<span  %1$s>%2$d ludzi</span> nie lubi tego"
 
 #: include/conversation.php:1042
 #, php-format
@@ -755,7 +772,7 @@ msgstr "<span  %1$s>%2$dosoby</span> uczestniczą"
 #: include/conversation.php:1046
 #, php-format
 msgid "%s attend."
-msgstr "%suczestniczy"
+msgstr "%s uczestniczy."
 
 #: include/conversation.php:1049
 #, php-format
@@ -765,17 +782,17 @@ msgstr "<span  %1$s>%2$dludzie</span> nie uczestniczą"
 #: include/conversation.php:1050
 #, php-format
 msgid "%s don't attend."
-msgstr "%s nie uczestnicz"
+msgstr "%s nie uczestniczy."
 
 #: include/conversation.php:1053
 #, php-format
 msgid "<span  %1$s>%2$d people</span> attend maybe"
-msgstr "<span  %1$s>%2$dprzyjaciele</span>mogą uczestniczyć "
+msgstr "Możliwe, że <span  %1$s>%2$d osoby</span> będą uczestniczyć"
 
 #: include/conversation.php:1054
 #, php-format
 msgid "%s attend maybe."
-msgstr "%sbyć może uczestniczyć. "
+msgstr "%sbyć może uczestniczyć."
 
 #: include/conversation.php:1084 include/conversation.php:1100
 msgid "Visible to <strong>everybody</strong>"
@@ -789,11 +806,11 @@ msgstr "Proszę wpisać adres URL:"
 
 #: include/conversation.php:1086 include/conversation.php:1102
 msgid "Please enter a video link/URL:"
-msgstr "Podaj link do filmu"
+msgstr "Podaj odnośnik do filmu:"
 
 #: include/conversation.php:1087 include/conversation.php:1103
 msgid "Please enter an audio link/URL:"
-msgstr "Podaj link do muzyki"
+msgstr "Podaj odnośnik do muzyki:"
 
 #: include/conversation.php:1088 include/conversation.php:1104
 msgid "Tag term:"
@@ -821,85 +838,85 @@ msgid "Share"
 msgstr "Podziel się"
 
 #: include/conversation.php:1142 mod/wallmessage.php:143 mod/message.php:261
-#: mod/message.php:428 mod/editpost.php:101
+#: mod/message.php:428 mod/editpost.php:107
 msgid "Upload photo"
 msgstr "Wyślij zdjęcie"
 
-#: include/conversation.php:1143 mod/editpost.php:102
+#: include/conversation.php:1143 mod/editpost.php:108
 msgid "upload photo"
 msgstr "dodaj zdjęcie"
 
-#: include/conversation.php:1144 mod/editpost.php:103
+#: include/conversation.php:1144 mod/editpost.php:109
 msgid "Attach file"
 msgstr "Załącz plik"
 
-#: include/conversation.php:1145 mod/editpost.php:104
+#: include/conversation.php:1145 mod/editpost.php:110
 msgid "attach file"
 msgstr "załącz plik"
 
 #: include/conversation.php:1146 mod/wallmessage.php:144 mod/message.php:262
-#: mod/message.php:429 mod/editpost.php:105
+#: mod/message.php:429 mod/editpost.php:111
 msgid "Insert web link"
 msgstr "Wstaw link"
 
-#: include/conversation.php:1147 mod/editpost.php:106
+#: include/conversation.php:1147 mod/editpost.php:112
 msgid "web link"
-msgstr "Adres www"
+msgstr "odnośnik sieciowy"
 
-#: include/conversation.php:1148 mod/editpost.php:107
+#: include/conversation.php:1148 mod/editpost.php:113
 msgid "Insert video link"
 msgstr "Wstaw link do filmu"
 
-#: include/conversation.php:1149 mod/editpost.php:108
+#: include/conversation.php:1149 mod/editpost.php:114
 msgid "video link"
 msgstr "link do filmu"
 
-#: include/conversation.php:1150 mod/editpost.php:109
+#: include/conversation.php:1150 mod/editpost.php:115
 msgid "Insert audio link"
 msgstr "Wstaw link do audio"
 
-#: include/conversation.php:1151 mod/editpost.php:110
+#: include/conversation.php:1151 mod/editpost.php:116
 msgid "audio link"
 msgstr "link do audio"
 
-#: include/conversation.php:1152 mod/editpost.php:111
+#: include/conversation.php:1152 mod/editpost.php:117
 msgid "Set your location"
 msgstr "Ustaw swoją lokalizację"
 
-#: include/conversation.php:1153 mod/editpost.php:112
+#: include/conversation.php:1153 mod/editpost.php:118
 msgid "set location"
 msgstr "wybierz lokalizację"
 
-#: include/conversation.php:1154 mod/editpost.php:113
+#: include/conversation.php:1154 mod/editpost.php:119
 msgid "Clear browser location"
 msgstr "Wyczyść lokalizację przeglądarki"
 
-#: include/conversation.php:1155 mod/editpost.php:114
+#: include/conversation.php:1155 mod/editpost.php:120
 msgid "clear location"
 msgstr "wyczyść lokalizację"
 
-#: include/conversation.php:1157 mod/editpost.php:129
+#: include/conversation.php:1157 mod/editpost.php:135
 msgid "Set title"
 msgstr "Podaj tytuł"
 
-#: include/conversation.php:1159 mod/editpost.php:131
+#: include/conversation.php:1159 mod/editpost.php:137
 msgid "Categories (comma-separated list)"
 msgstr "Kategorie (lista słów oddzielonych przecinkiem)"
 
-#: include/conversation.php:1161 mod/editpost.php:116
+#: include/conversation.php:1161 mod/editpost.php:122
 msgid "Permission settings"
 msgstr "Ustawienia uprawnień"
 
-#: include/conversation.php:1162 mod/editpost.php:146
+#: include/conversation.php:1162 mod/editpost.php:152
 msgid "permissions"
 msgstr "zezwolenia"
 
-#: include/conversation.php:1171 mod/editpost.php:126
+#: include/conversation.php:1171 mod/editpost.php:132
 msgid "Public post"
 msgstr "Publiczny post"
 
-#: include/conversation.php:1175 mod/editpost.php:137 mod/events.php:531
-#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
+#: include/conversation.php:1175 mod/editpost.php:143 mod/events.php:558
+#: mod/photos.php:1500 mod/photos.php:1539 mod/photos.php:1599
 #: src/Object/Post.php:804
 msgid "Preview"
 msgstr "Podgląd"
@@ -916,12 +933,12 @@ msgstr "Wstaw do kontaktów"
 msgid "Private post"
 msgstr "Prywatne posty"
 
-#: include/conversation.php:1191 mod/editpost.php:144
-#: src/Model/Profile.php:344
+#: include/conversation.php:1191 mod/editpost.php:150
+#: src/Model/Profile.php:357
 msgid "Message"
 msgstr "Wiadomość"
 
-#: include/conversation.php:1192 mod/editpost.php:145
+#: include/conversation.php:1192 mod/editpost.php:151
 msgid "Browser"
 msgstr "Przeglądarka"
 
@@ -953,7 +970,7 @@ msgstr[1] "Nie uczestniczy"
 msgstr[2] "Nie uczestniczą"
 msgstr[3] "Nie uczestniczą"
 
-#: include/conversation.php:1498 src/Content/ContactSelector.php:122
+#: include/conversation.php:1498 src/Content/ContactSelector.php:127
 msgid "Undecided"
 msgid_plural "Undecided"
 msgstr[0] "Niezdecydowany"
@@ -1005,7 +1022,7 @@ msgstr "[Friendica:Powiadomienie] Nowa wiadomość otrzymana od %s"
 #: include/enotify.php:125
 #, php-format
 msgid "%1$s sent you a new private message at %2$s."
-msgstr "%1$swysłał ci nową prywatną wiadomość na %2$s "
+msgstr "%1$s wysłał(-a) ci nową prywatną wiadomość na %2$s."
 
 #: include/enotify.php:126
 msgid "a private message"
@@ -1014,12 +1031,12 @@ msgstr "prywatna wiadomość"
 #: include/enotify.php:126
 #, php-format
 msgid "%1$s sent you %2$s."
-msgstr "%1$s wysyła ci %2$s"
+msgstr "%1$s wysłał(-a) ci %2$s."
 
 #: include/enotify.php:128
 #, php-format
 msgid "Please visit %s to view and/or reply to your private messages."
-msgstr "Odwiedź %s żeby zobaczyć i/lub odpowiedzieć na twoje prywatne wiadomości"
+msgstr "Odwiedź %s, aby zobaczyć i/lub odpowiedzieć na twoje prywatne wiadomości."
 
 #: include/enotify.php:161
 #, php-format
@@ -1029,7 +1046,7 @@ msgstr "%1$s skomentował [url=%2$s]a %3$s[/url]"
 #: include/enotify.php:169
 #, php-format
 msgid "%1$s commented on [url=%2$s]%3$s's %4$s[/url]"
-msgstr "%1$sskomentował  [url=%2$s]%3$s %4$s[/url]"
+msgstr "%1$sskomentował [url=%2$s]%3$s %4$s[/url]"
 
 #: include/enotify.php:179
 #, php-format
@@ -1044,13 +1061,13 @@ msgstr "[Friendica:Powiadomienie] Komentarz do rozmowy #%1$d przez %2$s"
 #: include/enotify.php:193
 #, php-format
 msgid "%s commented on an item/conversation you have been following."
-msgstr "%s skomentował rozmowę którą śledzisz"
+msgstr "%s skomentował(-a) rozmowę którą śledzisz."
 
 #: include/enotify.php:196 include/enotify.php:211 include/enotify.php:226
 #: include/enotify.php:241 include/enotify.php:260 include/enotify.php:276
 #, php-format
 msgid "Please visit %s to view and/or reply to the conversation."
-msgstr "Odwiedź %s żeby zobaczyć i/lub odpowiedzieć na rozmowę"
+msgstr "Odwiedź %s, aby zobaczyć i/lub odpowiedzieć na rozmowę."
 
 #: include/enotify.php:203
 #, php-format
@@ -1060,12 +1077,12 @@ msgstr "[Friendica:Powiadomienie] %s napisał na twoim profilu"
 #: include/enotify.php:205
 #, php-format
 msgid "%1$s posted to your profile wall at %2$s"
-msgstr "%1$sopublikowano na ścianie profilu w %2$s "
+msgstr "%1$s opublikował(-a) wpis na twojej ścianie o %2$s"
 
 #: include/enotify.php:206
 #, php-format
 msgid "%1$s posted to [url=%2$s]your wall[/url]"
-msgstr "%1$s wysłano do [url =%2$s]twojej strony[/url] "
+msgstr "%1$s opublikował(-a) na [url=%2$s]twojej ścianie[/url]"
 
 #: include/enotify.php:218
 #, php-format
@@ -1080,7 +1097,7 @@ msgstr "%1$s oznaczono Cię tagiem %2$s"
 #: include/enotify.php:221
 #, php-format
 msgid "%1$s [url=%2$s]tagged you[/url]."
-msgstr "%1$s [url=%2$s]oznaczył Cię[/url]. "
+msgstr "%1$s [url=%2$s]oznaczył(-a) Cię[/url]."
 
 #: include/enotify.php:233
 #, php-format
@@ -1090,7 +1107,7 @@ msgstr "[Friendica:Powiadomienie] %s udostępnił nowy wpis"
 #: include/enotify.php:235
 #, php-format
 msgid "%1$s shared a new post at %2$s"
-msgstr "%1$sudostępnił nowy wpis na %2$s "
+msgstr "%1$s udostępnił(-a) nowy wpis na %2$s"
 
 #: include/enotify.php:236
 #, php-format
@@ -1120,7 +1137,7 @@ msgstr "[Friendica:Powiadomienie] %s otagował Twój post"
 #: include/enotify.php:270
 #, php-format
 msgid "%1$s tagged your post at %2$s"
-msgstr "%1$soznaczyłeś swój wpis na %2$s "
+msgstr "%1$s oznaczył(-a) twój wpis na %2$s"
 
 #: include/enotify.php:271
 #, php-format
@@ -1158,7 +1175,7 @@ msgstr "[Friendica:Powiadomienie] Nowa osoba dzieli się z tobą"
 #: include/enotify.php:302 include/enotify.php:303
 #, php-format
 msgid "%1$s is sharing with you at %2$s"
-msgstr "%1$sdzieli się z tobą w %2$s "
+msgstr "%1$s dzieli się z tobą w %2$s"
 
 #: include/enotify.php:310
 msgid "[Friendica:Notify] You have a new follower"
@@ -1209,7 +1226,7 @@ msgstr "'%1$s' zaakceptował Twoją prośbę o połączenie na %2$s"
 #: include/enotify.php:350 include/enotify.php:365
 #, php-format
 msgid "%2$s has accepted your [url=%1$s]connection request[/url]."
-msgstr "%2$szaakceptował twoje [url=%1$s] żądanie połączenia [/url]. "
+msgstr "%2$s zaakceptował twoją [url=%1$s] prośbę o połączenie [/url]."
 
 #: include/enotify.php:355
 msgid ""
@@ -1267,7 +1284,7 @@ msgid ""
 "Full Name:\t%s\n"
 "Site Location:\t%s\n"
 "Login Name:\t%s (%s)"
-msgstr "Imię i Nazwisko:\t%s\nLokalizacja witryny:\t%s\nNazwa użytkownika:\t%s(%s)"
+msgstr "Imię i nazwisko:\t%s\nLokalizacja witryny:\t%s\nNazwa użytkownika:\t%s(%s)"
 
 #: include/enotify.php:398
 #, php-format
@@ -1323,7 +1340,7 @@ msgstr[3] "%d Kontakty"
 msgid "View Contacts"
 msgstr "Widok kontaktów"
 
-#: include/text.php:889 mod/filer.php:35 mod/editpost.php:100 mod/notes.php:54
+#: include/text.php:889 mod/filer.php:35 mod/editpost.php:106 mod/notes.php:54
 msgid "Save"
 msgstr "Zapisz"
 
@@ -1396,132 +1413,132 @@ msgstr "odrzuć"
 msgid "rebuffed"
 msgstr "odrzucony"
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:389
 msgid "Monday"
 msgstr "Poniedziałek"
 
-#: include/text.php:972 src/Model/Event.php:389
+#: include/text.php:972 src/Model/Event.php:390
 msgid "Tuesday"
 msgstr "Wtorek"
 
-#: include/text.php:972 src/Model/Event.php:390
+#: include/text.php:972 src/Model/Event.php:391
 msgid "Wednesday"
 msgstr "Środa"
 
-#: include/text.php:972 src/Model/Event.php:391
+#: include/text.php:972 src/Model/Event.php:392
 msgid "Thursday"
 msgstr "Czwartek"
 
-#: include/text.php:972 src/Model/Event.php:392
+#: include/text.php:972 src/Model/Event.php:393
 msgid "Friday"
 msgstr "Piątek"
 
-#: include/text.php:972 src/Model/Event.php:393
+#: include/text.php:972 src/Model/Event.php:394
 msgid "Saturday"
 msgstr "Sobota"
 
-#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:387
+#: include/text.php:972 mod/settings.php:941 src/Model/Event.php:388
 msgid "Sunday"
 msgstr "Niedziela"
 
-#: include/text.php:976 src/Model/Event.php:408
+#: include/text.php:976 src/Model/Event.php:409
 msgid "January"
 msgstr "Styczeń"
 
-#: include/text.php:976 src/Model/Event.php:409
+#: include/text.php:976 src/Model/Event.php:410
 msgid "February"
 msgstr "Luty"
 
-#: include/text.php:976 src/Model/Event.php:410
+#: include/text.php:976 src/Model/Event.php:411
 msgid "March"
 msgstr "Marzec"
 
-#: include/text.php:976 src/Model/Event.php:411
+#: include/text.php:976 src/Model/Event.php:412
 msgid "April"
 msgstr "Kwiecień"
 
-#: include/text.php:976 include/text.php:993 src/Model/Event.php:399
-#: src/Model/Event.php:412
+#: include/text.php:976 include/text.php:993 src/Model/Event.php:400
+#: src/Model/Event.php:413
 msgid "May"
 msgstr "Maj"
 
-#: include/text.php:976 src/Model/Event.php:413
+#: include/text.php:976 src/Model/Event.php:414
 msgid "June"
 msgstr "Czerwiec"
 
-#: include/text.php:976 src/Model/Event.php:414
+#: include/text.php:976 src/Model/Event.php:415
 msgid "July"
 msgstr "Lipiec"
 
-#: include/text.php:976 src/Model/Event.php:415
+#: include/text.php:976 src/Model/Event.php:416
 msgid "August"
 msgstr "Sierpień"
 
-#: include/text.php:976 src/Model/Event.php:416
+#: include/text.php:976 src/Model/Event.php:417
 msgid "September"
 msgstr "Wrzesień"
 
-#: include/text.php:976 src/Model/Event.php:417
+#: include/text.php:976 src/Model/Event.php:418
 msgid "October"
 msgstr "Październik"
 
-#: include/text.php:976 src/Model/Event.php:418
+#: include/text.php:976 src/Model/Event.php:419
 msgid "November"
 msgstr "Listopad"
 
-#: include/text.php:976 src/Model/Event.php:419
+#: include/text.php:976 src/Model/Event.php:420
 msgid "December"
 msgstr "Grudzień"
 
-#: include/text.php:990 src/Model/Event.php:380
+#: include/text.php:990 src/Model/Event.php:381
 msgid "Mon"
 msgstr "Pon"
 
-#: include/text.php:990 src/Model/Event.php:381
+#: include/text.php:990 src/Model/Event.php:382
 msgid "Tue"
 msgstr "Wt"
 
-#: include/text.php:990 src/Model/Event.php:382
+#: include/text.php:990 src/Model/Event.php:383
 msgid "Wed"
 msgstr "Śr"
 
-#: include/text.php:990 src/Model/Event.php:383
+#: include/text.php:990 src/Model/Event.php:384
 msgid "Thu"
 msgstr "Czw"
 
-#: include/text.php:990 src/Model/Event.php:384
+#: include/text.php:990 src/Model/Event.php:385
 msgid "Fri"
 msgstr "Pt"
 
-#: include/text.php:990 src/Model/Event.php:385
+#: include/text.php:990 src/Model/Event.php:386
 msgid "Sat"
 msgstr "Sob"
 
-#: include/text.php:990 src/Model/Event.php:379
+#: include/text.php:990 src/Model/Event.php:380
 msgid "Sun"
 msgstr "Niedz"
 
-#: include/text.php:993 src/Model/Event.php:395
+#: include/text.php:993 src/Model/Event.php:396
 msgid "Jan"
 msgstr "Sty"
 
-#: include/text.php:993 src/Model/Event.php:396
+#: include/text.php:993 src/Model/Event.php:397
 msgid "Feb"
 msgstr "Lut"
 
-#: include/text.php:993 src/Model/Event.php:397
+#: include/text.php:993 src/Model/Event.php:398
 msgid "Mar"
 msgstr "Mar"
 
-#: include/text.php:993 src/Model/Event.php:398
+#: include/text.php:993 src/Model/Event.php:399
 msgid "Apr"
 msgstr "Kwi"
 
-#: include/text.php:993 src/Model/Event.php:401
+#: include/text.php:993 src/Model/Event.php:402
 msgid "Jul"
 msgstr "Lip"
 
-#: include/text.php:993 src/Model/Event.php:402
+#: include/text.php:993 src/Model/Event.php:403
 msgid "Aug"
 msgstr "Sie"
 
@@ -1529,15 +1546,15 @@ msgstr "Sie"
 msgid "Sep"
 msgstr "Wrz"
 
-#: include/text.php:993 src/Model/Event.php:404
+#: include/text.php:993 src/Model/Event.php:405
 msgid "Oct"
 msgstr "Paź"
 
-#: include/text.php:993 src/Model/Event.php:405
+#: include/text.php:993 src/Model/Event.php:406
 msgid "Nov"
 msgstr "Lis"
 
-#: include/text.php:993 src/Model/Event.php:406
+#: include/text.php:993 src/Model/Event.php:407
 msgid "Dec"
 msgstr "Gru"
 
@@ -1546,7 +1563,7 @@ msgstr "Gru"
 msgid "Content warning: %s"
 msgstr "Ostrzeżenie o treści: %s"
 
-#: include/text.php:1204 mod/videos.php:375
+#: include/text.php:1204 mod/videos.php:376
 msgid "View Video"
 msgstr "Zobacz film"
 
@@ -1566,7 +1583,7 @@ msgstr "Zobacz na oddzielnej stronie"
 msgid "view on separate page"
 msgstr "zobacz na oddzielnej stronie"
 
-#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:609
+#: include/text.php:1421 include/text.php:1428 src/Model/Event.php:616
 msgid "link to source"
 msgstr "link do źródła"
 
@@ -1577,9 +1594,9 @@ msgstr "aktywność"
 #: include/text.php:1617 src/Object/Post.php:428 src/Object/Post.php:440
 msgid "comment"
 msgid_plural "comments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] "komentarz"
+msgstr[0] "komentarz"
+msgstr[1] "komentarze"
+msgstr[2] "komentarze"
 msgstr[3] "komentarz"
 
 #: include/text.php:1620
@@ -1590,7 +1607,7 @@ msgstr "post"
 msgid "Item filed"
 msgstr "Element złożony"
 
-#: include/api.php:1138
+#: include/api.php:1140
 #, php-format
 msgid "Daily posting limit of %d post reached. The post was rejected."
 msgid_plural "Daily posting limit of %d posts reached. The post was rejected."
@@ -1599,7 +1616,7 @@ msgstr[1] "Dzienny limit opublikowanych %d postów. Post został odrzucony."
 msgstr[2] "Dzienny limit opublikowanych %d postów. Post został odrzucony."
 msgstr[3] "Dzienny limit opublikowanych %d postów. Post został odrzucony."
 
-#: include/api.php:1152
+#: include/api.php:1154
 #, php-format
 msgid "Weekly posting limit of %d post reached. The post was rejected."
 msgid_plural ""
@@ -1609,16 +1626,16 @@ msgstr[1] "Tygodniowy limit wysyłania %d postów. Post został odrzucony."
 msgstr[2] "Tygodniowy limit wysyłania %d postów. Post został odrzucony."
 msgstr[3] "Tygodniowy limit wysyłania %d postów. Post został odrzucony."
 
-#: include/api.php:1166
+#: include/api.php:1168
 #, php-format
 msgid "Monthly posting limit of %d post reached. The post was rejected."
 msgstr "Miesięczny limit %d wysyłania postów. Post został odrzucony."
 
-#: include/api.php:4233 mod/profile_photo.php:84 mod/profile_photo.php:93
+#: include/api.php:4240 mod/profile_photo.php:84 mod/profile_photo.php:93
 #: mod/profile_photo.php:102 mod/profile_photo.php:211
 #: mod/profile_photo.php:300 mod/profile_photo.php:310 mod/photos.php:90
-#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1169
-#: mod/photos.php:1186 mod/photos.php:1678 src/Model/User.php:595
+#: mod/photos.php:198 mod/photos.php:735 mod/photos.php:1171
+#: mod/photos.php:1188 mod/photos.php:1680 src/Model/User.php:595
 #: src/Model/User.php:603 src/Model/User.php:611
 msgid "Profile Photos"
 msgstr "Zdjęcie profilowe"
@@ -1632,9 +1649,9 @@ msgid "Contact update failed."
 msgstr "Nie udało się zaktualizować kontaktu."
 
 #: mod/crepair.php:112 mod/redir.php:29 mod/redir.php:127
-#: mod/dfrn_confirm.php:127 mod/fsuggest.php:30 mod/fsuggest.php:96
+#: mod/dfrn_confirm.php:128 mod/fsuggest.php:30 mod/fsuggest.php:96
 msgid "Contact not found."
-msgstr "Kontakt nie znaleziony"
+msgstr "Nie znaleziono kontaktu."
 
 #: mod/crepair.php:116
 msgid ""
@@ -1735,7 +1752,7 @@ msgstr "Nie można sprawdzić twojej lokalizacji."
 
 #: mod/wallmessage.php:63 mod/message.php:81
 msgid "Message could not be sent."
-msgstr "Wiadomość nie może zostać wysłana"
+msgstr "Nie udało się wysłać wiadomości."
 
 #: mod/wallmessage.php:66 mod/message.php:84
 msgid "Message collection failure."
@@ -1773,144 +1790,144 @@ msgstr "Temat:"
 msgid "Your message:"
 msgstr "Twoja wiadomość:"
 
-#: mod/lockview.php:42 mod/lockview.php:50
+#: mod/lockview.php:46 mod/lockview.php:57
 msgid "Remote privacy information not available."
 msgstr "Nie są dostępne zdalne informacje o prywatności."
 
-#: mod/lockview.php:59
+#: mod/lockview.php:66
 msgid "Visible to:"
 msgstr "Widoczne dla:"
 
-#: mod/install.php:100
+#: mod/install.php:98
 msgid "Friendica Communications Server - Setup"
 msgstr "Friendica Serwer Komunikacyjny - Instalacja"
 
-#: mod/install.php:106
+#: mod/install.php:104
 msgid "Could not connect to database."
-msgstr "Nie można nawiązać połączenia z bazą danych"
+msgstr "Nie można połączyć się z bazą danych."
 
-#: mod/install.php:110
+#: mod/install.php:108
 msgid "Could not create table."
 msgstr "Nie mogę stworzyć tabeli."
 
-#: mod/install.php:116
+#: mod/install.php:114
 msgid "Your Friendica site database has been installed."
 msgstr "Twoja baza danych witryny Friendica została zainstalowana."
 
-#: mod/install.php:121
+#: mod/install.php:119
 msgid ""
 "You may need to import the file \"database.sql\" manually using phpmyadmin "
 "or mysql."
 msgstr "Może być konieczne zaimportowanie pliku \"database.sql\" ręcznie, używając phpmyadmin lub mysql."
 
-#: mod/install.php:122 mod/install.php:166 mod/install.php:274
+#: mod/install.php:120 mod/install.php:164 mod/install.php:272
 msgid "Please see the file \"INSTALL.txt\"."
 msgstr "Proszę przejrzeć plik \"INSTALL.txt\"."
 
-#: mod/install.php:134
+#: mod/install.php:132
 msgid "Database already in use."
 msgstr "Baza danych jest już w użyciu."
 
-#: mod/install.php:163
+#: mod/install.php:161
 msgid "System check"
 msgstr "Sprawdzanie systemu"
 
-#: mod/install.php:167 mod/cal.php:279 mod/events.php:394
+#: mod/install.php:165 mod/cal.php:279 mod/events.php:395
 msgid "Next"
 msgstr "Następny"
 
-#: mod/install.php:168
+#: mod/install.php:166
 msgid "Check again"
 msgstr "Sprawdź ponownie"
 
-#: mod/install.php:187
+#: mod/install.php:185
 msgid "Database connection"
 msgstr "Połączenie z bazą danych"
 
-#: mod/install.php:188
+#: mod/install.php:186
 msgid ""
 "In order to install Friendica we need to know how to connect to your "
 "database."
 msgstr "W celu zainstalowania Friendica musimy wiedzieć jak połączyć się z twoją bazą danych."
 
-#: mod/install.php:189
+#: mod/install.php:187
 msgid ""
 "Please contact your hosting provider or site administrator if you have "
 "questions about these settings."
 msgstr "Proszę skontaktuj się ze swoim dostawcą usług hostingowych bądź administratorem strony jeśli masz pytania co do tych ustawień ."
 
-#: mod/install.php:190
+#: mod/install.php:188
 msgid ""
 "The database you specify below should already exist. If it does not, please "
 "create it before continuing."
 msgstr "Wymieniona przez Ciebie baza danych powinna już istnieć. Jeżeli nie, utwórz ją przed kontynuacją."
 
-#: mod/install.php:194
+#: mod/install.php:192
 msgid "Database Server Name"
 msgstr "Nazwa serwera bazy danych"
 
-#: mod/install.php:195
+#: mod/install.php:193
 msgid "Database Login Name"
 msgstr "Nazwa użytkownika bazy danych"
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "Database Login Password"
 msgstr "Hasło logowania do bazy danych"
 
-#: mod/install.php:196
+#: mod/install.php:194
 msgid "For security reasons the password must not be empty"
 msgstr "Ze względów bezpieczeństwa hasło nie może być puste"
 
-#: mod/install.php:197
+#: mod/install.php:195
 msgid "Database Name"
 msgstr "Nazwa bazy danych"
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid "Site administrator email address"
 msgstr "Adres e-mail administratora strony"
 
-#: mod/install.php:198 mod/install.php:235
+#: mod/install.php:196 mod/install.php:233
 msgid ""
 "Your account email address must match this in order to use the web admin "
 "panel."
 msgstr "Adres e-mail konta musi pasować do tego, aby móc korzystać z panelu administracyjnego."
 
-#: mod/install.php:200 mod/install.php:238
+#: mod/install.php:198 mod/install.php:236
 msgid "Please select a default timezone for your website"
 msgstr "Proszę wybrać domyślną strefę czasową dla swojej strony"
 
-#: mod/install.php:225
+#: mod/install.php:223
 msgid "Site settings"
 msgstr "Ustawienia strony"
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid "System Language:"
 msgstr "Język systemu:"
 
-#: mod/install.php:239
+#: mod/install.php:237
 msgid ""
 "Set the default language for your Friendica installation interface and to "
 "send emails."
 msgstr "Ustaw domyślny język dla interfejsu instalacyjnego Friendica i wysyłaj e-maile."
 
-#: mod/install.php:255
+#: mod/install.php:253
 msgid ""
 "The database configuration file \"config/local.ini.php\" could not be "
 "written. Please use the enclosed text to create a configuration file in your"
 " web server root."
 msgstr "Plik konfiguracyjny bazy danych \"config/local.ini.php\" nie mógł zostać zapisany. Proszę użyć załączonego tekstu, aby utworzyć plik konfiguracyjny w katalogu głównym serwera."
 
-#: mod/install.php:272
+#: mod/install.php:270
 msgid "<h1>What next</h1>"
 msgstr "<h1>Co dalej</h1>"
 
-#: mod/install.php:273
+#: mod/install.php:271
 msgid ""
 "IMPORTANT: You will need to [manually] setup a scheduled task for the "
 "worker."
 msgstr "WAŻNE: Będziesz musiał [ręcznie] ustawić zaplanowane zadanie dla pracownika."
 
-#: mod/install.php:276
+#: mod/install.php:274
 #, php-format
 msgid ""
 "Go to your new Friendica node <a href=\"%s/register\">registration page</a> "
@@ -1918,83 +1935,83 @@ msgid ""
 " administrator email. This will allow you to enter the site admin panel."
 msgstr "Przejdź do <a href=\"%s/register\">strony rejestracji</a> nowego węzła Friendica i zarejestruj się jako nowy użytkownik. Pamiętaj, aby użyć adresu e-mail wprowadzonego jako e-mail administratora. To pozwoli Ci wejść do panelu administratora witryny."
 
-#: mod/dfrn_confirm.php:72 mod/profiles.php:38 mod/profiles.php:148
+#: mod/dfrn_confirm.php:73 mod/profiles.php:38 mod/profiles.php:148
 #: mod/profiles.php:193 mod/profiles.php:523
 msgid "Profile not found."
 msgstr "Nie znaleziono profilu."
 
-#: mod/dfrn_confirm.php:128
+#: mod/dfrn_confirm.php:129
 msgid ""
 "This may occasionally happen if contact was requested by both persons and it"
 " has already been approved."
 msgstr "Może się to zdarzyć, gdy kontakt został zgłoszony przez obie osoby i został już zatwierdzony."
 
-#: mod/dfrn_confirm.php:238
+#: mod/dfrn_confirm.php:239
 msgid "Response from remote site was not understood."
 msgstr "Odpowiedź do zdalnej strony nie została zrozumiana"
 
-#: mod/dfrn_confirm.php:245 mod/dfrn_confirm.php:251
+#: mod/dfrn_confirm.php:246 mod/dfrn_confirm.php:252
 msgid "Unexpected response from remote site: "
 msgstr "Nieoczekiwana odpowiedź od strony zdalnej:"
 
-#: mod/dfrn_confirm.php:260
+#: mod/dfrn_confirm.php:261
 msgid "Confirmation completed successfully."
 msgstr "Potwierdzenie zostało pomyślnie zakończone."
 
-#: mod/dfrn_confirm.php:272
+#: mod/dfrn_confirm.php:273
 msgid "Temporary failure. Please wait and try again."
 msgstr "Tymczasowa awaria. Proszę czekać i spróbuj ponownie."
 
-#: mod/dfrn_confirm.php:275
+#: mod/dfrn_confirm.php:276
 msgid "Introduction failed or was revoked."
 msgstr "Wprowadzenie nie powiodło się lub zostało odwołane."
 
-#: mod/dfrn_confirm.php:280
+#: mod/dfrn_confirm.php:281
 msgid "Remote site reported: "
-msgstr "Zdalna witryna zgłoszona:"
+msgstr "Zgłoszona zdana strona:"
 
-#: mod/dfrn_confirm.php:392
+#: mod/dfrn_confirm.php:382
 msgid "Unable to set contact photo."
 msgstr "Nie można ustawić zdjęcia kontaktu."
 
-#: mod/dfrn_confirm.php:450
+#: mod/dfrn_confirm.php:444
 #, php-format
 msgid "No user record found for '%s' "
 msgstr "Nie znaleziono użytkownika dla '%s'"
 
-#: mod/dfrn_confirm.php:460
+#: mod/dfrn_confirm.php:454
 msgid "Our site encryption key is apparently messed up."
 msgstr "Klucz kodujący jest najwyraźniej uszkodzony."
 
-#: mod/dfrn_confirm.php:471
+#: mod/dfrn_confirm.php:465
 msgid "Empty site URL was provided or URL could not be decrypted by us."
 msgstr "Został podany pusty adres URL witryny lub nie można go odszyfrować."
 
-#: mod/dfrn_confirm.php:487
+#: mod/dfrn_confirm.php:481
 msgid "Contact record was not found for you on our site."
 msgstr "Nie znaleziono kontaktu na naszej stronie"
 
-#: mod/dfrn_confirm.php:501
+#: mod/dfrn_confirm.php:495
 #, php-format
 msgid "Site public key not available in contact record for URL %s."
 msgstr "Publiczny klucz witryny jest niedostępny w rekordzie kontaktu dla adresu URL %s"
 
-#: mod/dfrn_confirm.php:517
+#: mod/dfrn_confirm.php:511
 msgid ""
 "The ID provided by your system is a duplicate on our system. It should work "
 "if you try again."
 msgstr "Identyfikator dostarczony przez Twój system jest duplikatem w naszym systemie. Powinien działać, jeśli spróbujesz ponownie."
 
-#: mod/dfrn_confirm.php:528
+#: mod/dfrn_confirm.php:522
 msgid "Unable to set your contact credentials on our system."
 msgstr "Nie można ustawić danych kontaktowych w naszym systemie."
 
-#: mod/dfrn_confirm.php:584
+#: mod/dfrn_confirm.php:578
 msgid "Unable to update your contact profile details on our system"
 msgstr "Nie można zaktualizować danych Twojego profilu kontaktowego w naszym systemie"
 
-#: mod/dfrn_confirm.php:614 mod/dfrn_request.php:561
-#: src/Model/Contact.php:1891
+#: mod/dfrn_confirm.php:608 mod/dfrn_request.php:561
+#: src/Model/Contact.php:1909
 msgid "[Name Withheld]"
 msgstr "[Nazwa zastrzeżona]"
 
@@ -2009,7 +2026,7 @@ msgid "Forum Search - %s"
 msgstr "Przeszukiwanie forum - %s"
 
 #: mod/dirfind.php:221 mod/match.php:105 mod/suggest.php:104
-#: mod/allfriends.php:92 src/Model/Profile.php:292 src/Content/Widget.php:37
+#: mod/allfriends.php:92 src/Model/Profile.php:305 src/Content/Widget.php:37
 msgid "Connect"
 msgstr "Połącz"
 
@@ -2019,7 +2036,7 @@ msgstr "Brak wyników"
 
 #: mod/manage.php:180
 msgid "Manage Identities and/or Pages"
-msgstr "Zarządzaj Tożsamościami i/lub Stronami."
+msgstr "Zarządzaj tożsamościami i/lub stronami"
 
 #: mod/manage.php:181
 msgid ""
@@ -2029,7 +2046,7 @@ msgstr "Przełącz między różnymi tożsamościami lub stronami społeczność
 
 #: mod/manage.php:182
 msgid "Select an identity to manage: "
-msgstr "Wybierz tożsamość do zarządzania:"
+msgstr "Wybierz tożsamość do zarządzania: "
 
 #: mod/videos.php:138
 msgid "Do you really want to delete this video?"
@@ -2041,28 +2058,28 @@ msgstr "Usuń wideo"
 
 #: mod/videos.php:198 mod/webfinger.php:16 mod/directory.php:42
 #: mod/search.php:105 mod/search.php:111 mod/viewcontacts.php:48
-#: mod/display.php:194 mod/dfrn_request.php:599 mod/probe.php:13
-#: mod/community.php:28 mod/photos.php:945
+#: mod/display.php:203 mod/dfrn_request.php:599 mod/probe.php:13
+#: mod/community.php:28 mod/photos.php:947
 msgid "Public access denied."
-msgstr "Publiczny dostęp zabroniony"
+msgstr "Publiczny dostęp zabroniony."
 
 #: mod/videos.php:206
 msgid "No videos selected"
 msgstr "Nie zaznaczono filmów"
 
-#: mod/videos.php:307 mod/photos.php:1050
+#: mod/videos.php:307 mod/photos.php:1052
 msgid "Access to this item is restricted."
 msgstr "Dostęp do tego obiektu jest ograniczony."
 
-#: mod/videos.php:382 mod/photos.php:1699
+#: mod/videos.php:383 mod/photos.php:1701
 msgid "View Album"
 msgstr "Zobacz album"
 
-#: mod/videos.php:390
+#: mod/videos.php:391
 msgid "Recent Videos"
 msgstr "Ostatnio dodane filmy"
 
-#: mod/videos.php:392
+#: mod/videos.php:393
 msgid "Upload New Videos"
 msgstr "Wstaw nowe filmy"
 
@@ -2070,27 +2087,27 @@ msgstr "Wstaw nowe filmy"
 msgid "Only logged in users are permitted to perform a probing."
 msgstr "Tylko zalogowani użytkownicy mogą wykonywać sondowanie."
 
-#: mod/directory.php:151 mod/notifications.php:253 mod/contacts.php:680
-#: mod/events.php:521 src/Model/Event.php:66 src/Model/Event.php:93
-#: src/Model/Event.php:430 src/Model/Event.php:915 src/Model/Profile.php:417
+#: mod/directory.php:151 mod/notifications.php:248 mod/contacts.php:681
+#: mod/events.php:548 src/Model/Event.php:67 src/Model/Event.php:94
+#: src/Model/Event.php:431 src/Model/Event.php:922 src/Model/Profile.php:430
 msgid "Location:"
-msgstr "Lokalizacja"
+msgstr "Lokalizacja:"
 
-#: mod/directory.php:156 mod/notifications.php:259 src/Model/Profile.php:420
-#: src/Model/Profile.php:732
+#: mod/directory.php:156 mod/notifications.php:254 src/Model/Profile.php:433
+#: src/Model/Profile.php:745
 msgid "Gender:"
 msgstr "Płeć:"
 
-#: mod/directory.php:157 src/Model/Profile.php:421 src/Model/Profile.php:756
+#: mod/directory.php:157 src/Model/Profile.php:434 src/Model/Profile.php:769
 msgid "Status:"
 msgstr "Status:"
 
-#: mod/directory.php:158 src/Model/Profile.php:422 src/Model/Profile.php:773
+#: mod/directory.php:158 src/Model/Profile.php:435 src/Model/Profile.php:786
 msgid "Homepage:"
 msgstr "Strona główna:"
 
-#: mod/directory.php:159 mod/notifications.php:255 mod/contacts.php:684
-#: src/Model/Profile.php:423 src/Model/Profile.php:793
+#: mod/directory.php:159 mod/notifications.php:250 mod/contacts.php:685
+#: src/Model/Profile.php:436 src/Model/Profile.php:806
 msgid "About:"
 msgstr "O:"
 
@@ -2130,7 +2147,7 @@ msgstr "wszyscy"
 msgid "Account"
 msgstr "Konto"
 
-#: mod/settings.php:64 src/Model/Profile.php:372 src/Content/Nav.php:210
+#: mod/settings.php:64 src/Model/Profile.php:385 src/Content/Nav.php:210
 msgid "Profiles"
 msgstr "Profile"
 
@@ -2160,7 +2177,7 @@ msgstr "Powiązane aplikacje"
 
 #: mod/settings.php:115 mod/uexport.php:52
 msgid "Export personal data"
-msgstr "Eksportuje dane personalne"
+msgstr "Eksportuj dane osobiste"
 
 #: mod/settings.php:122
 msgid "Remove account"
@@ -2170,7 +2187,7 @@ msgstr "Usuń konto"
 msgid "Missing some important data!"
 msgstr "Brakuje ważnych danych!"
 
-#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:848
+#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:851
 msgid "Update"
 msgstr "Zaktualizuj"
 
@@ -2218,11 +2235,11 @@ msgstr "Aktualizacja hasła nie powiodła się. Proszę spróbować ponownie."
 
 #: mod/settings.php:500
 msgid " Please use a shorter name."
-msgstr "Proszę użyć krótszej nazwy."
+msgstr " Proszę użyć krótszej nazwy."
 
 #: mod/settings.php:503
 msgid " Name too short."
-msgstr "Za krótka nazwa."
+msgstr " Nazwa jest zbyt krótka."
 
 #: mod/settings.php:511
 msgid "Wrong Password"
@@ -2325,24 +2342,24 @@ msgstr "Diaspora"
 
 #: mod/settings.php:803 mod/settings.php:804
 msgid "enabled"
-msgstr "włączony"
+msgstr "włączone"
 
 #: mod/settings.php:803 mod/settings.php:804
 msgid "disabled"
-msgstr "wyłączony"
+msgstr "wyłączone"
 
 #: mod/settings.php:803 mod/settings.php:804
 #, php-format
 msgid "Built-in support for %s connectivity is %s"
-msgstr "Wbudowane wsparcie dla %s łączność jest %s"
+msgstr "Wbudowane wsparcie dla połączenia z %s jest %s"
 
 #: mod/settings.php:804
 msgid "GNU Social (OStatus)"
-msgstr "GNU Społeczny (OStatus)"
+msgstr "GNU Soocial (OStatus)"
 
 #: mod/settings.php:835
 msgid "Email access is disabled on this site."
-msgstr "Dostęp do e-maila nie jest w pełni sprawny na tej stronie"
+msgstr "Dostęp do e-maila jest wyłączony na tej stronie."
 
 #: mod/settings.php:845
 msgid "General Social Media Settings"
@@ -2445,7 +2462,7 @@ msgstr "Adres zwrotny:"
 
 #: mod/settings.php:867
 msgid "Send public posts to all email contacts:"
-msgstr "Wyślij publiczny post do wszystkich kontaktów e-mail"
+msgstr "Wyślij publiczny wpis do wszystkich kontaktów e-mail:"
 
 #: mod/settings.php:868
 msgid "Action after import:"
@@ -2781,7 +2798,7 @@ msgstr "Użytkownicy sieci w serwisie Friendica mogą wysyłać prywatne wiadomo
 
 #: mod/settings.php:1137
 msgid "Profile is <strong>not published</strong>."
-msgstr "Profil <strong>nie jest opublikowany</strong>"
+msgstr "Profil <strong>nie jest opublikowany</strong>."
 
 #: mod/settings.php:1143
 #, php-format
@@ -2842,7 +2859,7 @@ msgstr "Potwierdź:"
 
 #: mod/settings.php:1197
 msgid "Leave password fields blank unless changing"
-msgstr "Pozostaw pole hasła puste, chyba że chcesz je zmienić."
+msgstr "Pozostaw pole hasła puste, jeżeli nie chcesz go zmienić."
 
 #: mod/settings.php:1198
 msgid "Current Password:"
@@ -2860,9 +2877,9 @@ msgstr "Hasło:"
 msgid "Basic Settings"
 msgstr "Ustawienia podstawowe"
 
-#: mod/settings.php:1204 src/Model/Profile.php:725
+#: mod/settings.php:1204 src/Model/Profile.php:738
 msgid "Full Name:"
-msgstr "Imię i Nazwisko:"
+msgstr "Imię i nazwisko:"
 
 #: mod/settings.php:1205
 msgid "Email Address:"
@@ -2880,7 +2897,7 @@ msgstr "Twój język:"
 msgid ""
 "Set the language we use to show you friendica interface and to send you "
 "emails"
-msgstr "Wybierz język, którego używasz, aby pokazać interfejs użytkownika friendica i do wysłania Ci e-maili"
+msgstr "Wybierz język, ktory bedzie używany do wyświetlania użytkownika friendica i wysłania Ci e-maili"
 
 #: mod/settings.php:1208
 msgid "Default Post Location:"
@@ -2888,7 +2905,7 @@ msgstr "Domyślna lokalizacja wiadomości:"
 
 #: mod/settings.php:1209
 msgid "Use Browser Location:"
-msgstr "Użyj lokalizacji przeglądarki:"
+msgstr "Używaj lokalizacji przeglądarki:"
 
 #: mod/settings.php:1212
 msgid "Security and Privacy Settings"
@@ -2910,11 +2927,11 @@ msgstr "Domyślne prawa dostępu wiadomości"
 msgid "(click to open/close)"
 msgstr "(kliknij by otworzyć/zamknąć)"
 
-#: mod/settings.php:1224 mod/photos.php:1126 mod/photos.php:1456
+#: mod/settings.php:1224 mod/photos.php:1128 mod/photos.php:1458
 msgid "Show to Groups"
 msgstr "Pokaż Grupy"
 
-#: mod/settings.php:1225 mod/photos.php:1127 mod/photos.php:1457
+#: mod/settings.php:1225 mod/photos.php:1129 mod/photos.php:1459
 msgid "Show to Contacts"
 msgstr "Pokaż kontakty"
 
@@ -2940,7 +2957,7 @@ msgstr "Ustawienia powiadomień"
 
 #: mod/settings.php:1247
 msgid "Send a notification email when:"
-msgstr "Wyślij powiadmonienia na email, kiedy:"
+msgstr "Wysyłaj powiadmonienia na email, kiedy:"
 
 #: mod/settings.php:1248
 msgid "You receive an introduction"
@@ -2980,7 +2997,7 @@ msgstr "Aktywuj powiadomienia na pulpicie"
 
 #: mod/settings.php:1257
 msgid "Show desktop popup on new notifications"
-msgstr "Pokaż wyskakujące okienko dla nowych powiadomień"
+msgstr "Pokazuj wyskakujące okienko gdy otrzymasz powiadomienie"
 
 #: mod/settings.php:1259
 msgid "Text-only notification emails"
@@ -2992,7 +3009,7 @@ msgstr "Wysyłaj tylko e-maile z powiadomieniami tekstowymi, bez części html"
 
 #: mod/settings.php:1263
 msgid "Show detailled notifications"
-msgstr "Pokaż szczegółowe powiadomienia"
+msgstr "Pokazuj szczegółowe powiadomienia"
 
 #: mod/settings.php:1265
 msgid ""
@@ -3063,7 +3080,7 @@ msgstr "Brak wyników."
 msgid "Items tagged with: %s"
 msgstr "Przedmioty oznaczone tagiem: %s"
 
-#: mod/search.php:248 mod/contacts.php:841
+#: mod/search.php:248 mod/contacts.php:844
 #, php-format
 msgid "Results for: %s"
 msgstr "Wyniki dla: %s"
@@ -3072,7 +3089,7 @@ msgstr "Wyniki dla: %s"
 msgid "No contacts in common."
 msgstr "Brak wspólnych kontaktów."
 
-#: mod/common.php:142 mod/contacts.php:916
+#: mod/common.php:142 mod/contacts.php:919
 msgid "Common Friends"
 msgstr "Wspólni znajomi"
 
@@ -3080,7 +3097,11 @@ msgstr "Wspólni znajomi"
 msgid "Login"
 msgstr "Zaloguj się"
 
-#: mod/bookmarklet.php:52
+#: mod/bookmarklet.php:34
+msgid "Bad Request"
+msgstr "Nieprawidłowe żądanie"
+
+#: mod/bookmarklet.php:56
 msgid "The post was created"
 msgstr "Post został utworzony"
 
@@ -3120,7 +3141,7 @@ msgstr "Grupa: %s"
 
 #: mod/network.php:671
 msgid "Private messages to this person are at risk of public disclosure."
-msgstr "Prywatne wiadomości do tej osoby mogą zostać publicznie ujawnione "
+msgstr "Prywatne wiadomości do tej osoby mogą być widoczne publicznie."
 
 #: mod/network.php:674
 msgid "Invalid contact."
@@ -3181,15 +3202,15 @@ msgstr "Grupa utworzona."
 
 #: mod/group.php:42
 msgid "Could not create group."
-msgstr "Nie mogę stworzyć grupy"
+msgstr "Nie można utworzyć grupy."
 
 #: mod/group.php:56 mod/group.php:187
 msgid "Group not found."
-msgstr "Nie znaleziono grupy"
+msgstr "Nie znaleziono grupy."
 
 #: mod/group.php:70
 msgid "Group name changed."
-msgstr "Nazwa grupy zmieniona"
+msgstr "Zmieniono nazwę grupy."
 
 #: mod/group.php:101
 msgid "Save Group"
@@ -3232,7 +3253,7 @@ msgstr "Edytuj nazwę grupy"
 msgid "Members"
 msgstr "Członkowie"
 
-#: mod/group.php:246 mod/contacts.php:739
+#: mod/group.php:246 mod/contacts.php:742
 msgid "All Contacts"
 msgstr "Wszystkie kontakty"
 
@@ -3350,52 +3371,48 @@ msgstr "Pozostaw to okno otwarte, dopóki nie będzie gotowe."
 #: mod/viewcontacts.php:20 mod/viewcontacts.php:24 mod/cal.php:32
 #: mod/cal.php:36 mod/follow.php:19 mod/community.php:35 mod/viewsrc.php:13
 msgid "Access denied."
-msgstr "Brak dostępu"
+msgstr "Brak dostępu."
 
 #: mod/viewcontacts.php:90
 msgid "No contacts."
-msgstr "Brak kontaktów"
+msgstr "Brak kontaktów."
 
-#: mod/viewcontacts.php:106 mod/contacts.php:639 mod/contacts.php:1052
+#: mod/viewcontacts.php:106 mod/contacts.php:640 mod/contacts.php:1055
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr "Obejrzyj %s's profil [%s]"
 
-#: mod/unfollow.php:36
-msgid "Contact wasn't found or can't be unfollowed."
-msgstr "Kontakt nie został znaleziony lub nie można go pominąć."
+#: mod/unfollow.php:38 mod/unfollow.php:88
+msgid "You aren't following this contact."
+msgstr "Nie obserwujesz tego kontaktu."
 
-#: mod/unfollow.php:49
-msgid "Contact unfollowed"
-msgstr "Skontaktuj się z obserwowanym"
-
-#: mod/unfollow.php:67 mod/dfrn_request.php:654 mod/follow.php:62
-msgid "Submit Request"
-msgstr "Wyślij zgłoszenie"
-
-#: mod/unfollow.php:76
-msgid "You aren't a friend of this contact."
-msgstr "Nie jesteś przyjacielem tego kontaktu."
-
-#: mod/unfollow.php:82
+#: mod/unfollow.php:44 mod/unfollow.php:94
 msgid "Unfollowing is currently not supported by your network."
 msgstr "Brak obserwowania nie jest obecnie obsługiwany przez twoją sieć."
 
-#: mod/unfollow.php:103 mod/contacts.php:601
+#: mod/unfollow.php:65
+msgid "Contact unfollowed"
+msgstr "Skontaktuj się z obserwowanym"
+
+#: mod/unfollow.php:113 mod/contacts.php:607
 msgid "Disconnect/Unfollow"
 msgstr "Rozłącz/Nie obserwuj"
 
-#: mod/unfollow.php:116 mod/dfrn_request.php:652 mod/follow.php:157
+#: mod/unfollow.php:126 mod/dfrn_request.php:652 mod/follow.php:157
 msgid "Your Identity Address:"
 msgstr "Twój adres tożsamości:"
 
-#: mod/unfollow.php:125 mod/notifications.php:174 mod/notifications.php:263
-#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:676 mod/follow.php:166
+#: mod/unfollow.php:129 mod/dfrn_request.php:654 mod/follow.php:62
+msgid "Submit Request"
+msgstr "Wyślij zgłoszenie"
+
+#: mod/unfollow.php:135 mod/notifications.php:174 mod/notifications.php:258
+#: mod/admin.php:500 mod/admin.php:510 mod/contacts.php:677 mod/follow.php:166
 msgid "Profile URL"
 msgstr "Adres URL profilu"
 
-#: mod/unfollow.php:135 mod/contacts.php:888 mod/follow.php:189
-#: src/Model/Profile.php:878
+#: mod/unfollow.php:145 mod/contacts.php:891 mod/follow.php:189
+#: src/Model/Profile.php:891
 msgid "Status Messages and Posts"
 msgstr "Status wiadomości i postów"
 
@@ -3423,13 +3440,13 @@ msgstr "Rejestracja udana."
 
 #: mod/register.php:115
 msgid "Your registration can not be processed."
-msgstr "Twoja rejestracja nie może zostać przeprowadzona. "
+msgstr "Nie można przetworzyć Twojej rejestracji."
 
 #: mod/register.php:162
 msgid "Your registration is pending approval by the site owner."
 msgstr "Twoja rejestracja oczekuje na zaakceptowanie przez właściciela witryny."
 
-#: mod/register.php:191 mod/uimport.php:55
+#: mod/register.php:191 mod/uimport.php:37
 msgid ""
 "This site has exceeded the number of allowed daily account registrations. "
 "Please try again tomorrow."
@@ -3449,7 +3466,7 @@ msgstr "Jeśli nie jesteś zaznajomiony z OpenID, zostaw to pole puste i uzupeł
 
 #: mod/register.php:222
 msgid "Your OpenID (optional): "
-msgstr "Twój OpenID (opcjonalnie):"
+msgstr "Twój OpenID (opcjonalnie): "
 
 #: mod/register.php:234
 msgid "Include your profile in member directory?"
@@ -3469,7 +3486,7 @@ msgstr "Członkostwo na tej stronie możliwe tylko dzięki zaproszeniu."
 
 #: mod/register.php:263
 msgid "Your invitation code: "
-msgstr "Twój kod zaproszenia:"
+msgstr "Twój kod zaproszenia: "
 
 #: mod/register.php:266 mod/admin.php:1428
 msgid "Registration"
@@ -3477,7 +3494,7 @@ msgstr "Rejestracja"
 
 #: mod/register.php:272
 msgid "Your Full Name (e.g. Joe Smith, real or real-looking): "
-msgstr "Twoje Imię i Nazwisko (np. Jan Kowalski, prawdziwe lub wyglądające na prawdziwe):"
+msgstr "Twoje imię i nazwisko (np. Jan Kowalski, prawdziwe lub wyglądające na prawdziwe): "
 
 #: mod/register.php:273
 msgid ""
@@ -3498,13 +3515,13 @@ msgstr "Wybierz pseudonim profilu. Nazwa musi zaczynać się od znaku tekstowego
 
 #: mod/register.php:278
 msgid "Choose a nickname: "
-msgstr "Wybierz pseudonim:"
+msgstr "Wybierz pseudonim: "
 
 #: mod/register.php:281 src/Module/Login.php:281 src/Content/Nav.php:128
 msgid "Register"
 msgstr "Zarejestruj"
 
-#: mod/register.php:287 mod/uimport.php:70
+#: mod/register.php:287 mod/uimport.php:52
 msgid "Import"
 msgstr "Import"
 
@@ -3525,37 +3542,45 @@ msgstr "Uwaga: Ten węzeł jawnie zawiera treści dla dorosłych"
 msgid "Invalid request identifier."
 msgstr "Nieprawidłowe żądanie identyfikatora."
 
-#: mod/notifications.php:44 mod/notifications.php:183
-#: mod/notifications.php:235 mod/message.php:114
+#: mod/notifications.php:44 mod/notifications.php:182
+#: mod/notifications.php:230 mod/message.php:114
 msgid "Discard"
 msgstr "Odrzuć"
 
-#: mod/notifications.php:57 mod/notifications.php:182
-#: mod/notifications.php:271 mod/contacts.php:658 mod/contacts.php:850
-#: mod/contacts.php:1113
+#: mod/notifications.php:57 mod/notifications.php:181
+#: mod/notifications.php:266 mod/contacts.php:659 mod/contacts.php:853
+#: mod/contacts.php:1116
 msgid "Ignore"
 msgstr "Ignoruj"
 
-#: mod/notifications.php:93 src/Content/Nav.php:191
+#: mod/notifications.php:90 src/Content/Nav.php:191
 msgid "Notifications"
 msgstr "Powiadomienia"
 
-#: mod/notifications.php:101
+#: mod/notifications.php:102
 msgid "Network Notifications"
 msgstr "Powiadomienia sieciowe"
 
-#: mod/notifications.php:106 mod/notify.php:81
+#: mod/notifications.php:107 mod/notify.php:81
 msgid "System Notifications"
 msgstr "Powiadomienia systemowe"
 
-#: mod/notifications.php:111
+#: mod/notifications.php:112
 msgid "Personal Notifications"
 msgstr "Prywatne powiadomienia"
 
-#: mod/notifications.php:116
+#: mod/notifications.php:117
 msgid "Home Notifications"
 msgstr "Powiadomienia domowe"
 
+#: mod/notifications.php:137
+msgid "Show unread"
+msgstr "Pokaż nieprzeczytane"
+
+#: mod/notifications.php:137
+msgid "Show all"
+msgstr "Pokaż wszystko"
+
 #: mod/notifications.php:148
 msgid "Show Ignored Requests"
 msgstr "Pokaż ignorowane żądania"
@@ -3564,7 +3589,7 @@ msgstr "Pokaż ignorowane żądania"
 msgid "Hide Ignored Requests"
 msgstr "Ukryj zignorowane prośby"
 
-#: mod/notifications.php:161 mod/notifications.php:243
+#: mod/notifications.php:161 mod/notifications.php:238
 msgid "Notification type:"
 msgstr "Typ powiadomienia:"
 
@@ -3572,88 +3597,80 @@ msgstr "Typ powiadomienia:"
 msgid "Suggested by:"
 msgstr "Sugerowany przez:"
 
-#: mod/notifications.php:176 mod/notifications.php:260 mod/contacts.php:666
+#: mod/notifications.php:176 mod/notifications.php:255 mod/contacts.php:667
 msgid "Hide this contact from others"
 msgstr "Ukryj ten kontakt przed innymi"
 
-#: mod/notifications.php:179 mod/notifications.php:269 mod/admin.php:1904
+#: mod/notifications.php:178 mod/notifications.php:264 mod/admin.php:1904
 msgid "Approve"
 msgstr "Zatwierdź"
 
-#: mod/notifications.php:202
+#: mod/notifications.php:198
 msgid "Claims to be known to you: "
-msgstr "Twierdzi, że go znasz:"
+msgstr "Twierdzi, że go/ją znasz: "
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "yes"
 msgstr "tak"
 
-#: mod/notifications.php:203
+#: mod/notifications.php:199
 msgid "no"
 msgstr "nie"
 
-#: mod/notifications.php:204 mod/notifications.php:209
+#: mod/notifications.php:200 mod/notifications.php:204
 msgid "Shall your connection be bidirectional or not?"
 msgstr "Czy twoje połączenie ma być dwukierunkowe, czy nie?"
 
-#: mod/notifications.php:205 mod/notifications.php:210
+#: mod/notifications.php:201 mod/notifications.php:205
 #, php-format
 msgid ""
 "Accepting %s as a friend allows %s to subscribe to your posts, and you will "
 "also receive updates from them in your news feed."
 msgstr "Przyjmowanie %s jako znajomego pozwala %s zasubskrybować twoje posty, a także otrzymywać od nich aktualizacje w swoim kanale wiadomości."
 
-#: mod/notifications.php:206
+#: mod/notifications.php:202
 #, php-format
 msgid ""
 "Accepting %s as a subscriber allows them to subscribe to your posts, but you"
 " will not receive updates from them in your news feed."
 msgstr "Zaakceptowanie %s jako subskrybenta umożliwia im subskrybowanie Twoich postów, ale nie otrzymasz od nich aktualizacji w swoim kanale wiadomości."
 
-#: mod/notifications.php:211
+#: mod/notifications.php:206
 #, php-format
 msgid ""
 "Accepting %s as a sharer allows them to subscribe to your posts, but you "
 "will not receive updates from them in your news feed."
 msgstr "Akceptowanie %s jako udostępniający pozwala im subskrybować twoje posty, ale nie otrzymasz od nich aktualizacji w swoim kanale wiadomości."
 
-#: mod/notifications.php:222
+#: mod/notifications.php:217
 msgid "Friend"
 msgstr "Znajomy"
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Sharer"
 msgstr "Udostępniający/a"
 
-#: mod/notifications.php:223
+#: mod/notifications.php:218
 msgid "Subscriber"
 msgstr "Subskrybent"
 
-#: mod/notifications.php:257 mod/contacts.php:686 mod/follow.php:177
-#: src/Model/Profile.php:781
+#: mod/notifications.php:252 mod/contacts.php:687 mod/follow.php:177
+#: src/Model/Profile.php:794
 msgid "Tags:"
 msgstr "Tagi:"
 
-#: mod/notifications.php:266 mod/contacts.php:76 src/Model/Profile.php:520
+#: mod/notifications.php:261 mod/contacts.php:81 src/Model/Profile.php:533
 msgid "Network:"
 msgstr "Sieć:"
 
-#: mod/notifications.php:280
+#: mod/notifications.php:274
 msgid "No introductions."
 msgstr "Brak dostępu."
 
-#: mod/notifications.php:318
-msgid "Show unread"
-msgstr "Pokaż nieprzeczytane"
-
-#: mod/notifications.php:318
-msgid "Show all"
-msgstr "Pokaż wszystko"
-
-#: mod/notifications.php:323
+#: mod/notifications.php:308
 #, php-format
 msgid "No more %s notifications."
-msgstr "Nigdy więcej %s powiadomień."
+msgstr "Brak kolejnych %s powiadomień."
 
 #: mod/message.php:31 mod/message.php:120 src/Content/Nav.php:199
 msgid "New Message"
@@ -3724,10 +3741,10 @@ msgstr "%s i ty"
 #, php-format
 msgid "%d message"
 msgid_plural "%d messages"
-msgstr[0] " %d wiadomość"
-msgstr[1] " %d wiadomości"
-msgstr[2] " %d wiadomości"
-msgstr[3] " %d wiadomości"
+msgstr[0] "%d wiadomość"
+msgstr[1] "%d wiadomości"
+msgstr[2] "%d wiadomości"
+msgstr[3] "%d wiadomości"
 
 #: mod/hcard.php:19
 msgid "No profile"
@@ -3759,7 +3776,7 @@ msgstr "nie powiodło się"
 
 #: mod/ostatus_subscribe.php:84 src/Object/Post.php:264
 msgid "ignored"
-msgstr "Ignoruj"
+msgstr "ignorowany(-a)"
 
 #: mod/dfrn_poll.php:126 mod/dfrn_poll.php:549
 #, php-format
@@ -3793,7 +3810,7 @@ msgstr "Spowoduje to całkowite usunięcie Twojego konta. Po wykonaniu tej czynn
 
 #: mod/removeme.php:83
 msgid "Please enter your password for verification:"
-msgstr "Wprowadź hasło w celu weryfikacji."
+msgstr "Wprowadź hasło w celu weryfikacji:"
 
 #: mod/tagrm.php:43
 msgid "Tag removed"
@@ -3805,7 +3822,7 @@ msgstr "Usuń pozycję Tag"
 
 #: mod/tagrm.php:79
 msgid "Select a tag to remove: "
-msgstr "Wybierz tag do usunięcia"
+msgstr "Wybierz tag do usunięcia"
 
 #: mod/home.php:39
 #, php-format
@@ -3853,7 +3870,7 @@ msgstr "śledzenie błędów na github"
 
 #: mod/friendica.php:91
 msgid "Suggestions, praise, etc. - please email \"info\" at \"friendi - dot - ca"
-msgstr "Sugestie, pochwały itp. - napisz e-mail \"info\" na \"friendi.ca\""
+msgstr "Propozycje, pochwały itd. – napisz e-mail do „info” małpa „friendi” - kropka - „ca”"
 
 #: mod/friendica.php:105
 msgid "Installed addons/apps:"
@@ -3873,7 +3890,7 @@ msgid "On this server the following remote servers are blocked."
 msgstr "Na tym serwerze następujące serwery zdalne są blokowane."
 
 #: mod/friendica.php:130 mod/admin.php:363 mod/admin.php:381
-#: mod/dfrn_request.php:345 src/Model/Contact.php:1582
+#: mod/dfrn_request.php:345 src/Model/Contact.php:1593
 msgid "Blocked domain"
 msgstr "Zablokowana domena"
 
@@ -3881,7 +3898,7 @@ msgstr "Zablokowana domena"
 msgid "Reason for the block"
 msgstr "Powód blokowania"
 
-#: mod/display.php:303 mod/cal.php:144 mod/profile.php:175
+#: mod/display.php:312 mod/cal.php:144 mod/profile.php:185
 msgid "Access to this profile has been restricted."
 msgstr "Dostęp do tego profilu został ograniczony."
 
@@ -3891,13 +3908,13 @@ msgstr "Dostęp do tego profilu został ograniczony."
 msgid "Invalid request."
 msgstr "Nieprawidłowe żądanie."
 
-#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:776
-#: mod/photos.php:779 mod/photos.php:808
+#: mod/wall_upload.php:195 mod/profile_photo.php:151 mod/photos.php:778
+#: mod/photos.php:781 mod/photos.php:810
 #, php-format
 msgid "Image exceeds size limit of %s"
 msgstr "Obraz przekracza limit rozmiaru wynoszący %s"
 
-#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:831
+#: mod/wall_upload.php:209 mod/profile_photo.php:160 mod/photos.php:833
 msgid "Unable to process image."
 msgstr "Przetwarzanie obrazu nie powiodło się."
 
@@ -3906,9 +3923,9 @@ msgstr "Przetwarzanie obrazu nie powiodło się."
 msgid "Wall Photos"
 msgstr "Tablica zdjęć"
 
-#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:860
+#: mod/wall_upload.php:248 mod/profile_photo.php:305 mod/photos.php:862
 msgid "Image upload failed."
-msgstr "Przesyłanie obrazu nie powiodło się"
+msgstr "Przesyłanie obrazu nie powiodło się."
 
 #: mod/newmember.php:11
 msgid "Welcome to Friendica"
@@ -3995,11 +4012,11 @@ msgstr "Ustaw kilka publicznych słów kluczowych dla swojego domyślnego profil
 
 #: mod/newmember.php:30
 msgid "Connecting"
-msgstr "Łączę się..."
+msgstr "Łączenie"
 
 #: mod/newmember.php:36
 msgid "Importing Emails"
-msgstr "Importuję emaile..."
+msgstr "Importowanie e-maili"
 
 #: mod/newmember.php:36
 msgid ""
@@ -4151,7 +4168,7 @@ msgstr "Wpisz swój adres email i wyślij, aby zresetować hasło. Później spr
 
 #: mod/lostpass.php:122 src/Module/Login.php:312
 msgid "Nickname or Email: "
-msgstr "Pseudonim lub Email:"
+msgstr "Pseudonim lub e-mail: "
 
 #: mod/lostpass.php:123
 msgid "Reset"
@@ -4175,7 +4192,7 @@ msgstr "Zapisz lub skopiuj nowe hasło - a następnie"
 
 #: mod/lostpass.php:143
 msgid "click here to login"
-msgstr "Kliknij tutaj aby się zalogować"
+msgstr "naciśnij tutaj, aby zalogować się"
 
 #: mod/lostpass.php:144
 msgid ""
@@ -4213,79 +4230,91 @@ msgstr "\n\t\t\tDane logowania są następujące:\n\n\t\t\tLokalizacja witryny:\
 msgid "Your password has been changed at %s"
 msgstr "Twoje hasło zostało zmienione na %s"
 
-#: mod/babel.php:22
+#: mod/babel.php:24
 msgid "Source input"
 msgstr "Źródło wejściowe"
 
-#: mod/babel.php:28
+#: mod/babel.php:30
 msgid "BBCode::toPlaintext"
 msgstr "BBCode::na prosty tekst"
 
-#: mod/babel.php:34
+#: mod/babel.php:36
 msgid "BBCode::convert (raw HTML)"
 msgstr "BBCode:: konwersjia (raw HTML)"
 
-#: mod/babel.php:39
+#: mod/babel.php:41
 msgid "BBCode::convert"
 msgstr "BBCode::przekształć"
 
-#: mod/babel.php:45
+#: mod/babel.php:47
 msgid "BBCode::convert => HTML::toBBCode"
 msgstr "BBCode::przekształć => HTML::toBBCode"
 
-#: mod/babel.php:51
+#: mod/babel.php:53
 msgid "BBCode::toMarkdown"
 msgstr "BBCode::toMarkdown"
 
-#: mod/babel.php:57
+#: mod/babel.php:59
 msgid "BBCode::toMarkdown => Markdown::convert"
 msgstr "BBCode::toMarkdown => Markdown::przekształć"
 
-#: mod/babel.php:63
+#: mod/babel.php:65
 msgid "BBCode::toMarkdown => Markdown::toBBCode"
 msgstr "BBCode::toMarkdown => Markdown::toBBCode"
 
-#: mod/babel.php:69
+#: mod/babel.php:71
 msgid "BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"
 msgstr "BBCode::toMarkdown => Markdown::przekształć => HTML::toBBCode"
 
-#: mod/babel.php:76
-msgid "Source input \\x28Diaspora format\\x29"
-msgstr "Źródło wejściowe \\x28Diaspora format\\x29"
+#: mod/babel.php:78
+msgid "Source input (Diaspora format)"
+msgstr "Źródło wejściowe (format Diaspora)"
 
-#: mod/babel.php:82
+#: mod/babel.php:84
+msgid "Markdown::convert (raw HTML)"
+msgstr "Markdown::convert (raw HTML)"
+
+#: mod/babel.php:89
+msgid "Markdown::convert"
+msgstr "Markdown::convert"
+
+#: mod/babel.php:95
 msgid "Markdown::toBBCode"
 msgstr "Markdown::toBBCode"
 
-#: mod/babel.php:89
+#: mod/babel.php:102
 msgid "Raw HTML input"
 msgstr "Surowe wejście HTML"
 
-#: mod/babel.php:94
+#: mod/babel.php:107
 msgid "HTML Input"
 msgstr "Wejście HTML"
 
-#: mod/babel.php:100
+#: mod/babel.php:113
 msgid "HTML::toBBCode"
 msgstr "HTML::toBBCode"
 
-#: mod/babel.php:106
+#: mod/babel.php:119
+msgid "HTML::toMarkdown"
+msgstr "HTML::toMarkdown"
+
+#: mod/babel.php:125
 msgid "HTML::toPlaintext"
 msgstr "HTML::toPlaintext"
 
-#: mod/babel.php:114
+#: mod/babel.php:133
 msgid "Source text"
 msgstr "Tekst źródłowy"
 
-#: mod/babel.php:115
+#: mod/babel.php:134
 msgid "BBCode"
 msgstr "BBCode"
 
-#: mod/babel.php:116
+#: mod/babel.php:135
 msgid "Markdown"
 msgstr "Markdown"
 
-#: mod/babel.php:117
+#: mod/babel.php:136
 msgid "HTML"
 msgstr "HTML"
 
@@ -4387,7 +4416,7 @@ msgstr "Funkcje dodatkowe"
 
 #: mod/admin.php:228
 msgid "User registrations waiting for confirmation"
-msgstr "Rejestracje użytkownika czekają na potwierdzenie."
+msgstr "Rejestracje użytkowników czekające na potwierdzenie"
 
 #: mod/admin.php:309 mod/admin.php:371 mod/admin.php:488 mod/admin.php:530
 #: mod/admin.php:722 mod/admin.php:765 mod/admin.php:806 mod/admin.php:914
@@ -4542,19 +4571,19 @@ msgstr "Zablokuj kontakt zdalny"
 
 #: mod/admin.php:492 mod/admin.php:1898
 msgid "select all"
-msgstr "Zaznacz wszystko"
+msgstr "zaznacz wszystko"
 
 #: mod/admin.php:493
 msgid "select none"
 msgstr "wybierz brak"
 
-#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Block"
 msgstr "Zablokuj"
 
-#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:657
-#: mod/contacts.php:849 mod/contacts.php:1105
+#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:658
+#: mod/contacts.php:852 mod/contacts.php:1108
 msgid "Unblock"
 msgstr "Odblokuj"
 
@@ -4582,9 +4611,9 @@ msgstr "Adres"
 #, php-format
 msgid "%s total blocked contact"
 msgid_plural "%s total blocked contacts"
-msgstr[0] "%s całkowicie zablokowany kontakt "
-msgstr[1] "%s całkowicie zablokowany kontakt"
-msgstr[2] "%s całkowicie zablokowane kontakty "
+msgstr[0] "łącznie %s zablokowany kontakt"
+msgstr[1] "łącznie %s zablokowane kontakty"
+msgstr[2] "łącznie %s zablokowanych kontaktów"
 msgstr[3] "%s całkowicie zablokowane kontakty"
 
 #: mod/admin.php:510
@@ -4698,7 +4727,7 @@ msgid ""
 "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 />"
-msgstr "Twoja baza danych nadal działa z tabelami MyISAM. Powinieneś zmienić typ silnika na InnoDB. Ponieważ Friendica będzie używać funkcji związanych z InnoDB tylko w przyszłości, powinieneś to zmienić! Zobacz <a href=\"%s\">tutaj</a> przewodnik, który może być pomocny w konwersji silników stołowych. Możesz także użyć polecenia <tt>php bin/console.php dbstructure toinnodb</tt> instalacji Friendica do automatycznej konwersji.<br />"
+msgstr "Twoja baza danych nadal używa tabel MyISAM. Powinieneś(-naś) zmienić typ silnika na InnoDB. Ponieważ Friendica będzie używać w przyszłości wyłącznie funkcji InnoDB, powinieneś(-naś) to zmienić! Zobacz <a href=\"%s\">tutaj</a> przewodnik, który może być pomocny w konwersji silników tabel. Możesz także użyć polecenia <tt>php bin/console.php dbstructure toinnodb</tt> instalacji Friendica, aby dokonać automatycznej konwersji.<br />"
 
 #: mod/admin.php:844
 #, php-format
@@ -4737,10 +4766,10 @@ msgstr "Konfiguracja Friendica jest teraz przechowywana w config/local.ini.php,
 #: mod/admin.php:876
 #, php-format
 msgid ""
-"<a href=\"%s\">%s</a> is not reachable on your system. This is a servere "
-"configuration issue that prevents the communication.. See <a href=\"%s\">the"
-" installation page</a> for help."
-msgstr "<a href=\"%s\">%s</a>nie jest osiągalny w twoim systemie. Jest to problem konfiguracji sieci, który uniemożliwia komunikację. Zobacz pomoc na <a href=\"%s\">stronie instalacji</a>."
+"<a href=\"%s\">%s</a> is not reachable on your system. This is a severe "
+"configuration issue that prevents server to server communication. See <a "
+"href=\"%s\">the installation page</a> for help."
+msgstr "<a href=\"%s\">%s</a> nie jest osiągalny w twoim systemie. Jest to poważny problem z konfiguracją, który uniemożliwia komunikację między serwerami. Zobacz pomoc na <a href=\"%s\">stronie instalacji</a>."
 
 #: mod/admin.php:882
 msgid "Normal Account"
@@ -4780,7 +4809,7 @@ msgstr "Zarejestrowani użytkownicy"
 
 #: mod/admin.php:919
 msgid "Pending registrations"
-msgstr "Rejestracje w toku."
+msgstr "Oczekujące rejestracje"
 
 #: mod/admin.php:920
 msgid "Version"
@@ -4796,7 +4825,7 @@ msgstr "Nie można zanalizować podstawowego adresu URL. Musi mieć co najmniej
 
 #: mod/admin.php:1289
 msgid "Site settings updated."
-msgstr "Ustawienia strony zaktualizowane"
+msgstr "Zaktualizowano ustawienia strony."
 
 #: mod/admin.php:1345
 msgid "No community page for local users"
@@ -4819,7 +4848,7 @@ msgid "Public postings from local users and the federated network"
 msgstr "Publikacje publiczne od użytkowników lokalnych i sieci federacyjnej"
 
 #: mod/admin.php:1353 mod/admin.php:1520 mod/admin.php:1530
-#: mod/contacts.php:577
+#: mod/contacts.php:583
 msgid "Disabled"
 msgstr "Wyłączony"
 
@@ -4857,7 +4886,7 @@ msgstr "Zamknięte"
 
 #: mod/admin.php:1395
 msgid "Requires approval"
-msgstr "Wymagane zatwierdzenie."
+msgstr "Wymaga zatwierdzenia"
 
 #: mod/admin.php:1396
 msgid "Open"
@@ -4865,15 +4894,15 @@ msgstr "Otwarta"
 
 #: mod/admin.php:1400
 msgid "No SSL policy, links will track page SSL state"
-msgstr "Brak SSL , linki będą śledzić stan SSL ."
+msgstr "Brak SSL, linki będą śledzić stan SSL"
 
 #: mod/admin.php:1401
 msgid "Force all links to use SSL"
-msgstr "Wymuś by linki używały SSL."
+msgstr "Wymuś używanie SSL na wszystkich odnośnikach"
 
 #: mod/admin.php:1402
 msgid "Self-signed certificate, use SSL for local links only (discouraged)"
-msgstr "Wewnętrzne Certyfikaty , użyj SSL tylko dla linków lokalnych . "
+msgstr "Wewnętrzne Certyfikaty, użyj SSL tylko dla linków lokalnych . "
 
 #: mod/admin.php:1406
 msgid "Don't check"
@@ -4899,8 +4928,8 @@ msgstr "Przesyłanie plików"
 msgid "Policies"
 msgstr "Zasady"
 
-#: mod/admin.php:1431 mod/contacts.php:926 mod/events.php:535
-#: src/Model/Profile.php:852
+#: mod/admin.php:1431 mod/contacts.php:929 mod/events.php:562
+#: src/Model/Profile.php:865
 msgid "Advanced"
 msgstr "Zaawansowany"
 
@@ -4997,11 +5026,11 @@ msgstr "Motyw na urządzenia mobilne"
 
 #: mod/admin.php:1449
 msgid "SSL link policy"
-msgstr "polityka SSL"
+msgstr "Polityka odnośników SSL"
 
 #: mod/admin.php:1449
 msgid "Determines whether generated links should be forced to use SSL"
-msgstr "Określa kiedy generowane linki powinny używać wymuszonego SSl."
+msgstr "Określa, czy generowane odnośniki będą obowiązkowo używały SSL"
 
 #: mod/admin.php:1450
 msgid "Force SSL"
@@ -5015,7 +5044,7 @@ msgstr "Wymuszaj wszystkie żądania SSL bez SSL - Uwaga: w niektórych systemac
 
 #: mod/admin.php:1451
 msgid "Hide help entry from navigation menu"
-msgstr "Wyłącz pomoc w menu nawigacyjnym "
+msgstr "Ukryj pomoc w menu nawigacyjnym"
 
 #: mod/admin.php:1451
 msgid ""
@@ -5098,7 +5127,7 @@ msgstr "Lista oddzielonych przecinkami pseudonimów, których nie wolno rejestro
 
 #: mod/admin.php:1461
 msgid "Accounts abandoned after x days"
-msgstr "Konto porzucone od x dni."
+msgstr "Konta porzucone po x dni"
 
 #: mod/admin.php:1461
 msgid ""
@@ -5304,15 +5333,15 @@ msgid ""
 msgstr "Zapewnij kompatybilność z OStatus (StatusNet, GNU Social itp.). Cała komunikacja w stanie OStatus jest jawna, dlatego ostrzeżenia o prywatności będą czasami wyświetlane."
 
 #: mod/admin.php:1481
-msgid "Only import OStatus threads from our contacts"
-msgstr "Importuj wątki OStatus tylko z naszych kontaktów"
+msgid "Only import OStatus/ActivityPub threads from our contacts"
+msgstr "Importuj wątki OStatus/ActivityPub tylko z naszych kontaktów"
 
 #: mod/admin.php:1481
 msgid ""
-"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."
-msgstr "Normalnie importujemy każdą treść z naszych kontaktów OStatus. W tej opcji przechowujemy tylko wątki uruchomione przez kontakt znany w naszym systemie."
+"Normally we import every content from our OStatus and ActivityPub contacts. "
+"With this option we only store threads that are started by a contact that is"
+" known on our system."
+msgstr "Normalnie importujemy każdą zawartość z naszych kontaktów OStatus i ActivityPub. W tej opcji przechowujemy tylko wątki uruchomione przez kontakt znany w naszym systemie."
 
 #: mod/admin.php:1482
 msgid "OStatus support can only be enabled if threading is enabled."
@@ -5843,19 +5872,19 @@ msgstr "Szczegóły rejestracji dla %s"
 #, php-format
 msgid "%s user blocked/unblocked"
 msgid_plural "%s users blocked/unblocked"
-msgstr[0] "%s użytkownik zablokowany/odblokowany"
-msgstr[1] "%s użytkowników zablokowanych/odblokowanych"
-msgstr[2] "%sużytkowników zablokowanych/odblokowanych "
-msgstr[3] "%sużytkowników zablokowanych/odblokowanych "
+msgstr[0] "zablokowano/odblokowano %s użytkownika"
+msgstr[1] "zablokowano/odblokowano %s użytkowników"
+msgstr[2] "zablokowano/odblokowano %s użytkowników"
+msgstr[3] "%sużytkowników zablokowanych/odblokowanych"
 
 #: mod/admin.php:1722
 #, php-format
 msgid "%s user deleted"
 msgid_plural "%s users deleted"
-msgstr[0] " %s użytkownik usunięty"
-msgstr[1] " %s użytkownicy usunięci"
-msgstr[2] " %s usuniętych użytkowników "
-msgstr[3] " %s usuniętych użytkowników "
+msgstr[0] "usunięto %s użytkownika"
+msgstr[1] "usunięto %s użytkowników"
+msgstr[2] "usunięto %s użytkowników"
+msgstr[3] "%s usuniętych użytkowników"
 
 #: mod/admin.php:1769
 #, php-format
@@ -5935,7 +5964,7 @@ msgstr "Administracja stroną"
 
 #: mod/admin.php:1911
 msgid "Account expired"
-msgstr "Konto wygasło."
+msgstr "Konto wygasło"
 
 #: mod/admin.php:1914
 msgid "New User"
@@ -6001,7 +6030,7 @@ msgstr "Autor: "
 
 #: mod/admin.php:2023 mod/admin.php:2294
 msgid "Maintainer: "
-msgstr "Opiekun:"
+msgstr "Opiekun: "
 
 #: mod/admin.php:2075
 msgid "Reload active addons"
@@ -6184,17 +6213,17 @@ msgstr "Już się tu przedstawiłeś."
 #: mod/dfrn_request.php:313
 #, php-format
 msgid "Apparently you are already friends with %s."
-msgstr "Wygląda na to, że już jesteście przyjaciółmi z %s"
+msgstr "Wygląda na to, że już jesteście znajomymi z %s."
 
 #: mod/dfrn_request.php:333
 msgid "Invalid profile URL."
 msgstr "Nieprawidłowy adres URL profilu."
 
-#: mod/dfrn_request.php:339 src/Model/Contact.php:1577
+#: mod/dfrn_request.php:339 src/Model/Contact.php:1588
 msgid "Disallowed profile URL."
 msgstr "Nie dozwolony adres URL profilu."
 
-#: mod/dfrn_request.php:412 mod/contacts.php:235
+#: mod/dfrn_request.php:412 mod/contacts.php:241
 msgid "Failed to update contact record."
 msgstr "Aktualizacja rekordu kontaktu nie powiodła się."
 
@@ -6289,7 +6318,7 @@ msgstr "Diaspora (Socialhome, Hubzilla)"
 msgid ""
 " - please do not use this form.  Instead, enter %s into your Diaspora search"
 " bar."
-msgstr "- proszę nie używać tego formularza. Zamiast tego wpisz %s do paska wyszukiwania Diaspory."
+msgstr " - proszę nie używać tego formularza. Zamiast tego, wpisz %s w pasku wyszukiwania Diaspory."
 
 #: mod/api.php:85 mod/api.php:107
 msgid "Authorize application connection"
@@ -6327,7 +6356,7 @@ msgstr "Ponownie załaduj stronę lub wyczyść pamięć podręczną przeglądar
 
 #: mod/profile_photo.php:132
 msgid "Unable to process image"
-msgstr "Nie udało się przetworzyć obrazu."
+msgstr "Nie udało się przetworzyć obrazu"
 
 #: mod/profile_photo.php:244
 msgid "Upload File:"
@@ -6367,7 +6396,7 @@ msgstr "Zakończono edycję"
 
 #: mod/profile_photo.php:303
 msgid "Image uploaded successfully."
-msgstr "Zdjęcie wczytano pomyślnie "
+msgstr "Pomyślnie wysłano zdjęcie."
 
 #: mod/wall_attach.php:107
 msgid "Sorry, maybe your upload is bigger than the PHP configuration allows"
@@ -6399,7 +6428,7 @@ msgstr "Pusty wpis został odrzucony."
 msgid ""
 "This message was sent to you by %s, a member of the Friendica social "
 "network."
-msgstr "Wiadomość została wysłana do ciebie od %s , członka portalu Friendica"
+msgstr "Wiadomość została wysłana do ciebie od %s, członka sieci społecznościowej Friendica."
 
 #: mod/item.php:811
 #, php-format
@@ -6421,32 +6450,36 @@ msgstr "%s zaktualizował wpis."
 msgid "Help:"
 msgstr "Pomoc:"
 
-#: mod/uimport.php:72
+#: mod/uimport.php:28
+msgid "User imports on closed servers can only be done by an administrator."
+msgstr "Import użytkowników na zamkniętych serwerach może być wykonywany tylko przez administratora."
+
+#: mod/uimport.php:54
 msgid "Move account"
 msgstr "Przenieś konto"
 
-#: mod/uimport.php:73
+#: mod/uimport.php:55
 msgid "You can import an account from another Friendica server."
 msgstr "Możesz zaimportować konto z innego serwera Friendica."
 
-#: mod/uimport.php:74
+#: mod/uimport.php:56
 msgid ""
 "You need to export your account from the old server and upload it here. We "
 "will recreate your old account here with all your contacts. We will try also"
 " to inform your friends that you moved here."
 msgstr "Musisz wyeksportować konto ze starego serwera i przesłać je tutaj. Odtworzymy twoje stare konto tutaj ze wszystkimi twoimi kontaktami. Postaramy się również poinformować twoich znajomych, że się tutaj przeniosłeś."
 
-#: mod/uimport.php:75
+#: mod/uimport.php:57
 msgid ""
 "This feature is experimental. We can't import contacts from the OStatus "
 "network (GNU Social/Statusnet) or from Diaspora"
 msgstr "Ta funkcja jest eksperymentalna. Nie możemy importować kontaktów z sieci OStatus (GNU Social/Statusnet) lub z Diaspory"
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid "Account file"
 msgstr "Pliki konta"
 
-#: mod/uimport.php:76
+#: mod/uimport.php:58
 msgid ""
 "To export your account, go to \"Settings->Export your personal data\" and "
 "select \"Export account\""
@@ -6468,34 +6501,34 @@ msgstr "Widoczne dla"
 msgid "All Contacts (with secure profile access)"
 msgstr "Wszystkie kontakty (z bezpiecznym dostępem do profilu)"
 
-#: mod/cal.php:277 mod/events.php:391
+#: mod/cal.php:277 mod/events.php:392
 msgid "View"
 msgstr "Widok"
 
-#: mod/cal.php:278 mod/events.php:393
+#: mod/cal.php:278 mod/events.php:394
 msgid "Previous"
 msgstr "Poprzedni"
 
-#: mod/cal.php:282 mod/events.php:399 src/Model/Event.php:421
+#: mod/cal.php:282 mod/events.php:400 src/Model/Event.php:422
 msgid "today"
 msgstr "dzisiaj"
 
-#: mod/cal.php:283 mod/events.php:400 src/Util/Temporal.php:304
-#: src/Model/Event.php:422
+#: mod/cal.php:283 mod/events.php:401 src/Util/Temporal.php:304
+#: src/Model/Event.php:423
 msgid "month"
 msgstr "miesiąc"
 
-#: mod/cal.php:284 mod/events.php:401 src/Util/Temporal.php:305
-#: src/Model/Event.php:423
+#: mod/cal.php:284 mod/events.php:402 src/Util/Temporal.php:305
+#: src/Model/Event.php:424
 msgid "week"
 msgstr "tydzień"
 
-#: mod/cal.php:285 mod/events.php:402 src/Util/Temporal.php:306
-#: src/Model/Event.php:424
+#: mod/cal.php:285 mod/events.php:403 src/Util/Temporal.php:306
+#: src/Model/Event.php:425
 msgid "day"
 msgstr "dzień"
 
-#: mod/cal.php:286 mod/events.php:403
+#: mod/cal.php:286 mod/events.php:404
 msgid "list"
 msgstr "lista"
 
@@ -6528,19 +6561,19 @@ msgstr "Rejestracja odwołana dla %s"
 msgid "Please login."
 msgstr "Proszę się zalogować."
 
-#: mod/editpost.php:26 mod/editpost.php:36
+#: mod/editpost.php:27 mod/editpost.php:42
 msgid "Item not found"
 msgstr "Nie znaleziono elementu"
 
-#: mod/editpost.php:43
+#: mod/editpost.php:49
 msgid "Edit post"
 msgstr "Edytuj post"
 
-#: mod/editpost.php:125 src/Core/ACL.php:304
+#: mod/editpost.php:131 src/Core/ACL.php:304
 msgid "CC: email addresses"
 msgstr "CC: adresy e-mail"
 
-#: mod/editpost.php:132 src/Core/ACL.php:305
+#: mod/editpost.php:138 src/Core/ACL.php:305
 msgid "Example: bob@example.com, mary@example.com"
 msgstr "Przykład: bob@example.com, mary@example.com"
 
@@ -6577,458 +6610,458 @@ msgstr "Zaproponuj znajomych dla %s"
 msgid "System down for maintenance"
 msgstr "System wyłączony w celu konserwacji"
 
-#: mod/profile.php:38 src/Model/Profile.php:115
+#: mod/profile.php:39 src/Model/Profile.php:128
 msgid "Requested profile is not available."
-msgstr "Żądany profil jest niedostępny"
+msgstr "Żądany profil jest niedostępny."
 
-#: mod/profile.php:79 mod/profile.php:82 src/Protocol/OStatus.php:1275
+#: mod/profile.php:89 mod/profile.php:92 src/Protocol/OStatus.php:1285
 #, php-format
 msgid "%s's timeline"
-msgstr "%s oś czasu "
+msgstr "oś czasu %s"
 
-#: mod/profile.php:80 src/Protocol/OStatus.php:1276
+#: mod/profile.php:90 src/Protocol/OStatus.php:1286
 #, php-format
 msgid "%s's posts"
-msgstr "%s posty "
+msgstr "wpisy %s"
 
-#: mod/profile.php:81 src/Protocol/OStatus.php:1277
+#: mod/profile.php:91 src/Protocol/OStatus.php:1287
 #, php-format
 msgid "%s's comments"
-msgstr "%s komentarze "
+msgstr "komentarze %s"
 
 #: mod/allfriends.php:53
 msgid "No friends to display."
-msgstr "Brak znajomych do wyświetlenia"
+msgstr "Brak znajomych do wyświetlenia."
 
-#: mod/contacts.php:162
+#: mod/contacts.php:168
 #, php-format
 msgid "%d contact edited."
 msgid_plural "%d contacts edited."
-msgstr[0] "%d edytuj kontakty."
-msgstr[1] "%d edytuj kontakty."
-msgstr[2] "%dedytuj kontakty. "
-msgstr[3] "%dedytuj kontakty. "
+msgstr[0] "Zedytowano %d kontakt."
+msgstr[1] "Zedytowano %d kontakty."
+msgstr[2] "Zedytowano %d kontaktów."
+msgstr[3] "%dedytuj kontakty."
 
-#: mod/contacts.php:189 mod/contacts.php:395
+#: mod/contacts.php:195 mod/contacts.php:401
 msgid "Could not access contact record."
 msgstr "Nie można uzyskać dostępu do rejestru kontaktów."
 
-#: mod/contacts.php:199
+#: mod/contacts.php:205
 msgid "Could not locate selected profile."
 msgstr "Nie można znaleźć wybranego profilu."
 
-#: mod/contacts.php:233
+#: mod/contacts.php:239
 msgid "Contact updated."
-msgstr "Kontakt zaktualizowany"
+msgstr "Zaktualizowano kontakt."
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been blocked"
 msgstr "Kontakt został zablokowany"
 
-#: mod/contacts.php:416
+#: mod/contacts.php:422
 msgid "Contact has been unblocked"
 msgstr "Kontakt został odblokowany"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been ignored"
 msgstr "Kontakt jest ignorowany"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:432
 msgid "Contact has been unignored"
 msgstr "Kontakt nie jest ignorowany"
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been archived"
 msgstr "Kontakt został zarchiwizowany"
 
-#: mod/contacts.php:436
+#: mod/contacts.php:442
 msgid "Contact has been unarchived"
 msgstr "Kontakt został przywrócony"
 
-#: mod/contacts.php:460
+#: mod/contacts.php:466
 msgid "Drop contact"
 msgstr "Usuń kontakt"
 
-#: mod/contacts.php:463 mod/contacts.php:845
+#: mod/contacts.php:469 mod/contacts.php:848
 msgid "Do you really want to delete this contact?"
 msgstr "Czy na pewno chcesz usunąć ten kontakt?"
 
-#: mod/contacts.php:481
+#: mod/contacts.php:487
 msgid "Contact has been removed."
 msgstr "Kontakt został usunięty."
 
-#: mod/contacts.php:518
+#: mod/contacts.php:524
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr "Jesteś już znajomym z %s"
 
-#: mod/contacts.php:523
+#: mod/contacts.php:529
 #, php-format
 msgid "You are sharing with %s"
 msgstr "Współdzielisz z %s"
 
-#: mod/contacts.php:528
+#: mod/contacts.php:534
 #, php-format
 msgid "%s is sharing with you"
 msgstr "%s współdzieli z tobą"
 
-#: mod/contacts.php:552
+#: mod/contacts.php:558
 msgid "Private communications are not available for this contact."
-msgstr "Prywatna rozmowa jest niemożliwa dla tego kontaktu"
+msgstr "Nie można nawiązać prywatnej rozmowy z tym kontaktem."
 
-#: mod/contacts.php:554
+#: mod/contacts.php:560
 msgid "Never"
 msgstr "Nigdy"
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was successful)"
 msgstr "(Aktualizacja przebiegła pomyślnie)"
 
-#: mod/contacts.php:557
+#: mod/contacts.php:563
 msgid "(Update was not successful)"
 msgstr "(Aktualizacja nie powiodła się)"
 
-#: mod/contacts.php:559 mod/contacts.php:1086
+#: mod/contacts.php:565 mod/contacts.php:1089
 msgid "Suggest friends"
 msgstr "Osoby, które możesz znać"
 
-#: mod/contacts.php:563
+#: mod/contacts.php:569
 #, php-format
 msgid "Network type: %s"
 msgstr "Typ sieci: %s"
 
-#: mod/contacts.php:568
+#: mod/contacts.php:574
 msgid "Communications lost with this contact!"
 msgstr "Utracono komunikację z tym kontaktem!"
 
-#: mod/contacts.php:574
+#: mod/contacts.php:580
 msgid "Fetch further information for feeds"
 msgstr "Pobierz dalsze informacje dla kanałów"
 
-#: mod/contacts.php:576
+#: mod/contacts.php:582
 msgid ""
 "Fetch information like preview pictures, title and teaser from the feed "
 "item. You can activate this if the feed doesn't contain much text. Keywords "
 "are taken from the meta header in the feed item and are posted as hash tags."
 msgstr "Pobieranie informacji, takich jak zdjęcia podglądu, tytuł i zwiastun z elementu kanału. Możesz to aktywować, jeśli plik danych nie zawiera dużo tekstu. Słowa kluczowe są pobierane z nagłówka meta w elemencie kanału i są publikowane jako znaczniki haszowania."
 
-#: mod/contacts.php:578
+#: mod/contacts.php:584
 msgid "Fetch information"
 msgstr "Pobierz informacje"
 
-#: mod/contacts.php:579
+#: mod/contacts.php:585
 msgid "Fetch keywords"
 msgstr "Pobierz słowa kluczowe"
 
-#: mod/contacts.php:580
+#: mod/contacts.php:586
 msgid "Fetch information and keywords"
 msgstr "Pobierz informacje i słowa kluczowe"
 
-#: mod/contacts.php:617
+#: mod/contacts.php:618
 msgid "Profile Visibility"
 msgstr "Widoczność profilu"
 
-#: mod/contacts.php:618
+#: mod/contacts.php:619
 msgid "Contact Information / Notes"
 msgstr "Informacje kontaktowe/Notatki"
 
-#: mod/contacts.php:619
+#: mod/contacts.php:620
 msgid "Contact Settings"
 msgstr "Ustawienia kontaktów"
 
-#: mod/contacts.php:628
+#: mod/contacts.php:629
 msgid "Contact"
 msgstr "Kontakt"
 
-#: mod/contacts.php:632
+#: mod/contacts.php:633
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
 msgstr "Wybierz profil, który chcesz bezpiecznie wyświetlić %s"
 
-#: mod/contacts.php:634
+#: mod/contacts.php:635
 msgid "Their personal note"
 msgstr "Ich osobista uwaga"
 
-#: mod/contacts.php:636
+#: mod/contacts.php:637
 msgid "Edit contact notes"
 msgstr "Edytuj notatki kontaktu"
 
-#: mod/contacts.php:640
+#: mod/contacts.php:641
 msgid "Block/Unblock contact"
 msgstr "Zablokuj/odblokuj kontakt"
 
-#: mod/contacts.php:641
+#: mod/contacts.php:642
 msgid "Ignore contact"
 msgstr "Ignoruj kontakt"
 
-#: mod/contacts.php:642
+#: mod/contacts.php:643
 msgid "Repair URL settings"
 msgstr "Napraw ustawienia adresów URL"
 
-#: mod/contacts.php:643
+#: mod/contacts.php:644
 msgid "View conversations"
 msgstr "Wyświetl rozmowy"
 
-#: mod/contacts.php:648
+#: mod/contacts.php:649
 msgid "Last update:"
 msgstr "Ostatnia aktualizacja:"
 
-#: mod/contacts.php:650
+#: mod/contacts.php:651
 msgid "Update public posts"
 msgstr "Zaktualizuj publiczne posty"
 
-#: mod/contacts.php:652 mod/contacts.php:1096
+#: mod/contacts.php:653 mod/contacts.php:1099
 msgid "Update now"
 msgstr "Aktualizuj teraz"
 
-#: mod/contacts.php:658 mod/contacts.php:850 mod/contacts.php:1113
+#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116
 msgid "Unignore"
 msgstr "Odblokuj"
 
-#: mod/contacts.php:662
+#: mod/contacts.php:663
 msgid "Currently blocked"
 msgstr "Obecnie zablokowany"
 
-#: mod/contacts.php:663
+#: mod/contacts.php:664
 msgid "Currently ignored"
 msgstr "Obecnie zignorowany"
 
-#: mod/contacts.php:664
+#: mod/contacts.php:665
 msgid "Currently archived"
 msgstr "Obecnie zarchiwizowany"
 
-#: mod/contacts.php:665
+#: mod/contacts.php:666
 msgid "Awaiting connection acknowledge"
 msgstr "Oczekiwanie na potwierdzenie połączenia"
 
-#: mod/contacts.php:666
+#: mod/contacts.php:667
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr "Odpowiedzi/kliknięcia \"lubię to\" do twoich publicznych postów nadal <strong>mogą</strong> być widoczne"
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Notification for new posts"
 msgstr "Powiadomienie o nowych postach"
 
-#: mod/contacts.php:667
+#: mod/contacts.php:668
 msgid "Send a notification of every new post of this contact"
 msgstr "Wyślij powiadomienie o każdym nowym poście tego kontaktu"
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid "Blacklisted keywords"
 msgstr "Słowa kluczowe na czarnej liście"
 
-#: mod/contacts.php:670
+#: mod/contacts.php:671
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
 msgstr "Rozdzielana przecinkami lista słów kluczowych, które nie powinny zostać przekonwertowane na hashtagi, gdy wybrana jest opcja 'Pobierz informacje i słowa kluczowe'"
 
-#: mod/contacts.php:682 src/Model/Profile.php:424
+#: mod/contacts.php:683 src/Model/Profile.php:437
 msgid "XMPP:"
 msgstr "XMPP:"
 
-#: mod/contacts.php:687
+#: mod/contacts.php:688
 msgid "Actions"
 msgstr "Akcja"
 
-#: mod/contacts.php:731
+#: mod/contacts.php:734
 msgid "Suggestions"
 msgstr "Sugestie"
 
-#: mod/contacts.php:734
+#: mod/contacts.php:737
 msgid "Suggest potential friends"
 msgstr "Sugerowani znajomi"
 
-#: mod/contacts.php:742
+#: mod/contacts.php:745
 msgid "Show all contacts"
 msgstr "Pokaż wszystkie kontakty"
 
-#: mod/contacts.php:747
+#: mod/contacts.php:750
 msgid "Unblocked"
-msgstr "Odblokowany"
+msgstr "Odblokowane"
 
-#: mod/contacts.php:750
+#: mod/contacts.php:753
 msgid "Only show unblocked contacts"
 msgstr "Pokaż tylko odblokowane kontakty"
 
-#: mod/contacts.php:755
+#: mod/contacts.php:758
 msgid "Blocked"
-msgstr "Zablokowany"
+msgstr "Zablokowane"
 
-#: mod/contacts.php:758
+#: mod/contacts.php:761
 msgid "Only show blocked contacts"
 msgstr "Pokaż tylko zablokowane kontakty"
 
-#: mod/contacts.php:763
+#: mod/contacts.php:766
 msgid "Ignored"
-msgstr "Zignorowany"
+msgstr "Ignorowane"
 
-#: mod/contacts.php:766
+#: mod/contacts.php:769
 msgid "Only show ignored contacts"
 msgstr "Pokaż tylko ignorowane kontakty"
 
-#: mod/contacts.php:771
+#: mod/contacts.php:774
 msgid "Archived"
 msgstr "Zarchiwizowane"
 
-#: mod/contacts.php:774
+#: mod/contacts.php:777
 msgid "Only show archived contacts"
 msgstr "Pokaż tylko zarchiwizowane kontakty"
 
-#: mod/contacts.php:779
+#: mod/contacts.php:782
 msgid "Hidden"
-msgstr "Ukryty"
+msgstr "Ukryte"
 
-#: mod/contacts.php:782
+#: mod/contacts.php:785
 msgid "Only show hidden contacts"
 msgstr "Pokaż tylko ukryte kontakty"
 
-#: mod/contacts.php:840
+#: mod/contacts.php:843
 msgid "Search your contacts"
 msgstr "Wyszukaj w kontaktach"
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Archive"
 msgstr "Archiwum"
 
-#: mod/contacts.php:851 mod/contacts.php:1122
+#: mod/contacts.php:854 mod/contacts.php:1125
 msgid "Unarchive"
 msgstr "Przywróć z archiwum"
 
-#: mod/contacts.php:854
+#: mod/contacts.php:857
 msgid "Batch Actions"
 msgstr "Akcje wsadowe"
 
-#: mod/contacts.php:880
+#: mod/contacts.php:883
 msgid "Conversations started by this contact"
 msgstr "Rozmowy rozpoczęły się od tego kontaktu"
 
-#: mod/contacts.php:885
+#: mod/contacts.php:888
 msgid "Posts and Comments"
 msgstr "Posty i komentarze"
 
-#: mod/contacts.php:896 src/Model/Profile.php:886
+#: mod/contacts.php:899 src/Model/Profile.php:899
 msgid "Profile Details"
 msgstr "Szczegóły profilu"
 
-#: mod/contacts.php:908
+#: mod/contacts.php:911
 msgid "View all contacts"
 msgstr "Zobacz wszystkie kontakty"
 
-#: mod/contacts.php:919
+#: mod/contacts.php:922
 msgid "View all common friends"
 msgstr "Zobacz wszystkich popularnych znajomych"
 
-#: mod/contacts.php:929
+#: mod/contacts.php:932
 msgid "Advanced Contact Settings"
 msgstr "Zaawansowane ustawienia kontaktów"
 
-#: mod/contacts.php:1019
+#: mod/contacts.php:1022
 msgid "Mutual Friendship"
 msgstr "Wzajemna przyjaźń"
 
-#: mod/contacts.php:1024
+#: mod/contacts.php:1027
 msgid "is a fan of yours"
 msgstr "jest twoim fanem"
 
-#: mod/contacts.php:1029
+#: mod/contacts.php:1032
 msgid "you are a fan of"
 msgstr "jesteś fanem"
 
-#: mod/contacts.php:1046 mod/photos.php:1494 mod/photos.php:1533
-#: mod/photos.php:1593 src/Object/Post.php:792
+#: mod/contacts.php:1049 mod/photos.php:1496 mod/photos.php:1535
+#: mod/photos.php:1595 src/Object/Post.php:792
 msgid "This is you"
 msgstr "To jesteś ty"
 
-#: mod/contacts.php:1053
+#: mod/contacts.php:1056
 msgid "Edit contact"
 msgstr "Edytuj kontakt"
 
-#: mod/contacts.php:1107
+#: mod/contacts.php:1110
 msgid "Toggle Blocked status"
 msgstr "Przełącz status na Zablokowany"
 
-#: mod/contacts.php:1115
+#: mod/contacts.php:1118
 msgid "Toggle Ignored status"
 msgstr "Przełącz status na Ignorowany"
 
-#: mod/contacts.php:1124
+#: mod/contacts.php:1127
 msgid "Toggle Archive status"
 msgstr "Przełącz  status na Archiwalny"
 
-#: mod/contacts.php:1132
+#: mod/contacts.php:1135
 msgid "Delete contact"
 msgstr "Usuń kontakt"
 
-#: mod/events.php:103 mod/events.php:105
+#: mod/events.php:105 mod/events.php:107
 msgid "Event can not end before it has started."
 msgstr "Wydarzenie nie może się zakończyć przed jego rozpoczęciem."
 
-#: mod/events.php:112 mod/events.php:114
+#: mod/events.php:114 mod/events.php:116
 msgid "Event title and start time are required."
 msgstr "Wymagany tytuł wydarzenia i czas rozpoczęcia."
 
-#: mod/events.php:392
+#: mod/events.php:393
 msgid "Create New Event"
 msgstr "Stwórz nowe wydarzenie"
 
-#: mod/events.php:509
+#: mod/events.php:516
 msgid "Event details"
 msgstr "Szczegóły wydarzenia"
 
-#: mod/events.php:510
+#: mod/events.php:517
 msgid "Starting date and Title are required."
 msgstr "Data rozpoczęcia i tytuł są wymagane."
 
-#: mod/events.php:511 mod/events.php:512
+#: mod/events.php:518 mod/events.php:523
 msgid "Event Starts:"
 msgstr "Rozpoczęcie wydarzenia:"
 
-#: mod/events.php:511 mod/events.php:523 mod/profiles.php:607
+#: mod/events.php:518 mod/events.php:550 mod/profiles.php:607
 msgid "Required"
 msgstr "Wymagany"
 
-#: mod/events.php:513 mod/events.php:529
+#: mod/events.php:531 mod/events.php:556
 msgid "Finish date/time is not known or not relevant"
 msgstr "Data/czas zakończenia nie jest znana lub jest nieistotna"
 
-#: mod/events.php:515 mod/events.php:516
+#: mod/events.php:533 mod/events.php:538
 msgid "Event Finishes:"
 msgstr "Zakończenie wydarzenia:"
 
-#: mod/events.php:517 mod/events.php:530
+#: mod/events.php:544 mod/events.php:557
 msgid "Adjust for viewer timezone"
 msgstr "Dopasuj dla strefy czasowej widza"
 
-#: mod/events.php:519
+#: mod/events.php:546
 msgid "Description:"
 msgstr "Opis:"
 
-#: mod/events.php:523 mod/events.php:525
+#: mod/events.php:550 mod/events.php:552
 msgid "Title:"
 msgstr "Tytuł:"
 
-#: mod/events.php:526 mod/events.php:527
+#: mod/events.php:553 mod/events.php:554
 msgid "Share this event"
 msgstr "Udostępnij te wydarzenie"
 
-#: mod/events.php:534 src/Model/Profile.php:851
+#: mod/events.php:561 src/Model/Profile.php:864
 msgid "Basic"
 msgstr "Podstawowy"
 
-#: mod/events.php:536 mod/photos.php:1112 mod/photos.php:1448
+#: mod/events.php:563 mod/photos.php:1114 mod/photos.php:1450
 #: src/Core/ACL.php:307
 msgid "Permissions"
 msgstr "Uprawnienia"
 
-#: mod/events.php:555
+#: mod/events.php:579
 msgid "Failed to remove event"
 msgstr "Nie udało się usunąć wydarzenia"
 
-#: mod/events.php:557
+#: mod/events.php:581
 msgid "Event removed"
 msgstr "Wydarzenie zostało usunięte"
 
@@ -7053,8 +7086,8 @@ msgid "The network type couldn't be detected. Contact can't be added."
 msgstr "Nie można wykryć typu sieci. Kontakt nie może zostać dodany."
 
 #: mod/fbrowser.php:44 mod/fbrowser.php:69 mod/photos.php:198
-#: mod/photos.php:1076 mod/photos.php:1169 mod/photos.php:1186
-#: mod/photos.php:1652 mod/photos.php:1667 src/Model/Photo.php:243
+#: mod/photos.php:1078 mod/photos.php:1171 mod/photos.php:1188
+#: mod/photos.php:1654 mod/photos.php:1669 src/Model/Photo.php:243
 #: src/Model/Photo.php:252
 msgid "Contact Photos"
 msgstr "Zdjęcia kontaktu"
@@ -7065,12 +7098,12 @@ msgstr "Pliki"
 
 #: mod/oexchange.php:30
 msgid "Post successful."
-msgstr "Post dodany pomyślnie"
+msgstr "Pomyślnie opublikowano."
 
 #: mod/subthread.php:103
 #, php-format
 msgid "%1$s is following %2$s's %3$s"
-msgstr "%1$skolejny %2$s %3$s "
+msgstr "%1$s śledzi %3$s %2$s"
 
 #: mod/credits.php:18
 msgid "Credits"
@@ -7125,7 +7158,7 @@ msgid ""
 " not reflect the opinions of this node’s users."
 msgstr "Ten strumień społeczności pokazuje wszystkie publiczne posty otrzymane przez ten węzeł. Mogą nie odzwierciedlać opinii użytkowników tego węzła."
 
-#: mod/localtime.php:19 src/Model/Event.php:34 src/Model/Event.php:829
+#: mod/localtime.php:19 src/Model/Event.php:35 src/Model/Event.php:836
 msgid "l F d, Y \\@ g:i A"
 msgstr "l F d, Y \\@ g:i A"
 
@@ -7158,23 +7191,23 @@ msgstr "Zmień strefę czasową: %s"
 msgid "Please select your timezone:"
 msgstr "Wybierz swoją strefę czasową:"
 
-#: mod/poke.php:188
+#: mod/poke.php:187
 msgid "Poke/Prod"
 msgstr "Zaczepić"
 
-#: mod/poke.php:189
+#: mod/poke.php:188
 msgid "poke, prod or do other things to somebody"
 msgstr "szturchać, zaczepić lub robić inne rzeczy"
 
-#: mod/poke.php:190
+#: mod/poke.php:189
 msgid "Recipient"
 msgstr "Odbiorca"
 
-#: mod/poke.php:191
+#: mod/poke.php:190
 msgid "Choose what you wish to do to recipient"
 msgstr "Wybierz, co chcesz zrobić"
 
-#: mod/poke.php:194
+#: mod/poke.php:193
 msgid "Make this post private"
 msgstr "Ustaw ten post jako prywatny"
 
@@ -7284,7 +7317,7 @@ msgid ""
 "important, please visit http://friendi.ca"
 msgstr "Aby uzyskać więcej informacji na temat projektu Friendica i dlaczego uważamy, że jest to ważne, odwiedź http://friendi.ca"
 
-#: mod/notes.php:42 src/Model/Profile.php:933
+#: mod/notes.php:42 src/Model/Profile.php:946
 msgid "Personal Notes"
 msgstr "Notatki"
 
@@ -7302,11 +7335,11 @@ msgstr "Utworzono nowy profil."
 
 #: mod/profiles.php:115
 msgid "Profile unavailable to clone."
-msgstr "Nie można powileić profilu "
+msgstr "Nie można powielić profilu."
 
 #: mod/profiles.php:203
 msgid "Profile Name is required."
-msgstr "Nazwa Profilu jest wymagana"
+msgstr "Nazwa profilu jest wymagana."
 
 #: mod/profiles.php:344
 msgid "Marital Status"
@@ -7374,7 +7407,7 @@ msgstr "Akcje profilowe"
 
 #: mod/profiles.php:576
 msgid "Edit Profile Details"
-msgstr "Edytuj profil."
+msgstr "Edytuj informacje o profilu"
 
 #: mod/profiles.php:578
 msgid "Change Profile Photo"
@@ -7388,7 +7421,7 @@ msgstr "Wyświetl ten profil"
 msgid "View all profiles"
 msgstr "Wyświetl wszystkie profile"
 
-#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:393
+#: mod/profiles.php:582 mod/profiles.php:677 src/Model/Profile.php:406
 msgid "Edit visibility"
 msgstr "Edytuj widoczność"
 
@@ -7440,7 +7473,7 @@ msgstr "Płeć:"
 msgid "<span class=\"heart\">&hearts;</span> Marital Status:"
 msgstr "<span class=\"heart\">&hearts;</span> Stan cywilny:"
 
-#: mod/profiles.php:601 src/Model/Profile.php:769
+#: mod/profiles.php:601 src/Model/Profile.php:782
 msgid "Sexual Preference:"
 msgstr "Preferencje seksualne:"
 
@@ -7460,11 +7493,11 @@ msgstr "To jest Twój <strong> publiczny </strong> profil. <br/><strong>Może </
 
 #: mod/profiles.php:610
 msgid "Your Full Name:"
-msgstr "Imię i Nazwisko:"
+msgstr "Imię i nazwisko:"
 
 #: mod/profiles.php:611
 msgid "Title/Description:"
-msgstr "Tytuł/Opis :"
+msgstr "Tytuł/Opis:"
 
 #: mod/profiles.php:614
 msgid "Street Address:"
@@ -7472,11 +7505,11 @@ msgstr "Ulica:"
 
 #: mod/profiles.php:615
 msgid "Locality/City:"
-msgstr "Miejscowość/Miasto:"
+msgstr "Miasto:"
 
 #: mod/profiles.php:616
 msgid "Region/State:"
-msgstr "Region/Państwo:"
+msgstr "Województwo/Stan:"
 
 #: mod/profiles.php:617
 msgid "Postal/Zip Code:"
@@ -7504,7 +7537,7 @@ msgstr "Od [data]:"
 
 #: mod/profiles.php:625
 msgid "Tell us about yourself..."
-msgstr "Napisz o sobie..."
+msgstr "Napisz o sobie"
 
 #: mod/profiles.php:626
 msgid "XMPP (Jabber) address:"
@@ -7520,11 +7553,11 @@ msgstr "Adres XMPP będzie propagowany do Twoich kontaktów, aby mogli Cię śle
 msgid "Homepage URL:"
 msgstr "Adres URL strony domowej:"
 
-#: mod/profiles.php:628 src/Model/Profile.php:777
+#: mod/profiles.php:628 src/Model/Profile.php:790
 msgid "Hometown:"
 msgstr "Miasto rodzinne:"
 
-#: mod/profiles.php:629 src/Model/Profile.php:785
+#: mod/profiles.php:629 src/Model/Profile.php:798
 msgid "Political Views:"
 msgstr "Poglądy polityczne:"
 
@@ -7548,11 +7581,11 @@ msgstr "Prywatne słowa kluczowe:"
 msgid "(Used for searching profiles, never shown to others)"
 msgstr "(Używany do wyszukiwania profili, niepokazywany innym)"
 
-#: mod/profiles.php:633 src/Model/Profile.php:801
+#: mod/profiles.php:633 src/Model/Profile.php:814
 msgid "Likes:"
 msgstr "Lubię to:"
 
-#: mod/profiles.php:634 src/Model/Profile.php:805
+#: mod/profiles.php:634 src/Model/Profile.php:818
 msgid "Dislikes:"
 msgstr "Nie lubię tego:"
 
@@ -7592,11 +7625,11 @@ msgstr "Szkoła/edukacja"
 msgid "Contact information and Social Networks"
 msgstr "Dane kontaktowe i Sieci społecznościowe"
 
-#: mod/profiles.php:674 src/Model/Profile.php:389
+#: mod/profiles.php:674 src/Model/Profile.php:402
 msgid "Profile Image"
 msgstr "Zdjęcie profilowe"
 
-#: mod/profiles.php:676 src/Model/Profile.php:392
+#: mod/profiles.php:676 src/Model/Profile.php:405
 msgid "visible to everybody"
 msgstr "widoczne dla wszystkich"
 
@@ -7604,35 +7637,35 @@ msgstr "widoczne dla wszystkich"
 msgid "Edit/Manage Profiles"
 msgstr "Edycja/Zarządzanie profilami"
 
-#: mod/profiles.php:684 src/Model/Profile.php:379 src/Model/Profile.php:401
+#: mod/profiles.php:684 src/Model/Profile.php:392 src/Model/Profile.php:414
 msgid "Change profile photo"
 msgstr "Zmień zdjęcie profilowe"
 
-#: mod/profiles.php:685 src/Model/Profile.php:380
+#: mod/profiles.php:685 src/Model/Profile.php:393
 msgid "Create New Profile"
 msgstr "Utwórz nowy profil"
 
-#: mod/photos.php:112 src/Model/Profile.php:894
+#: mod/photos.php:112 src/Model/Profile.php:907
 msgid "Photo Albums"
 msgstr "Albumy zdjęć"
 
-#: mod/photos.php:113 mod/photos.php:1708
+#: mod/photos.php:113 mod/photos.php:1710
 msgid "Recent Photos"
 msgstr "Ostatnio dodane zdjęcia"
 
-#: mod/photos.php:116 mod/photos.php:1230 mod/photos.php:1710
+#: mod/photos.php:116 mod/photos.php:1232 mod/photos.php:1712
 msgid "Upload New Photos"
 msgstr "Wyślij nowe zdjęcie"
 
 #: mod/photos.php:190
 msgid "Contact information unavailable"
-msgstr "Informacje kontaktowe są niedostępne."
+msgstr "Informacje o kontakcie są niedostępne"
 
 #: mod/photos.php:209
 msgid "Album not found."
-msgstr "Album nie znaleziony"
+msgstr "Nie znaleziono albumu."
 
-#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1181
+#: mod/photos.php:239 mod/photos.php:252 mod/photos.php:1183
 msgid "Delete Album"
 msgstr "Usuń album"
 
@@ -7640,7 +7673,7 @@ msgstr "Usuń album"
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr "Czy na pewno chcesz usunąć ten album i wszystkie zdjęcia z tego albumu?"
 
-#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1453
+#: mod/photos.php:312 mod/photos.php:324 mod/photos.php:1455
 msgid "Delete Photo"
 msgstr "Usuń zdjęcie"
 
@@ -7657,150 +7690,150 @@ msgstr "zdjęcie"
 msgid "%1$s was tagged in %2$s by %3$s"
 msgstr "%1$szostał oznaczony tagiem %2$s przez %3$s"
 
-#: mod/photos.php:782
+#: mod/photos.php:784
 msgid "Image upload didn't complete, please try again"
 msgstr "Przesyłanie zdjęć nie zostało zakończone, spróbuj ponownie"
 
-#: mod/photos.php:785
+#: mod/photos.php:787
 msgid "Image file is missing"
 msgstr "Brak pliku obrazu"
 
-#: mod/photos.php:790
+#: mod/photos.php:792
 msgid ""
 "Server can't accept new file upload at this time, please contact your "
 "administrator"
 msgstr "Serwer nie może teraz przyjąć nowego pliku, skontaktuj się z administratorem"
 
-#: mod/photos.php:816
+#: mod/photos.php:818
 msgid "Image file is empty."
 msgstr "Plik obrazka jest pusty."
 
-#: mod/photos.php:953
+#: mod/photos.php:955
 msgid "No photos selected"
 msgstr "Nie zaznaczono zdjęć"
 
-#: mod/photos.php:1104
+#: mod/photos.php:1106
 msgid "Upload Photos"
 msgstr "Prześlij zdjęcia"
 
-#: mod/photos.php:1108 mod/photos.php:1176
+#: mod/photos.php:1110 mod/photos.php:1178
 msgid "New album name: "
-msgstr "Nazwa nowego albumu:"
+msgstr "Nazwa nowego albumu: "
 
-#: mod/photos.php:1109
+#: mod/photos.php:1111
 msgid "or select existing album:"
 msgstr "lub wybierz istniejący album:"
 
-#: mod/photos.php:1110
+#: mod/photos.php:1112
 msgid "Do not show a status post for this upload"
 msgstr "Nie pokazuj statusu postów dla tego wysłania"
 
-#: mod/photos.php:1187
+#: mod/photos.php:1189
 msgid "Edit Album"
 msgstr "Edytuj album"
 
-#: mod/photos.php:1192
+#: mod/photos.php:1194
 msgid "Show Newest First"
 msgstr "Pokaż najpierw najnowsze"
 
-#: mod/photos.php:1194
+#: mod/photos.php:1196
 msgid "Show Oldest First"
 msgstr "Pokaż najpierw najstarsze"
 
-#: mod/photos.php:1215 mod/photos.php:1693
+#: mod/photos.php:1217 mod/photos.php:1695
 msgid "View Photo"
 msgstr "Zobacz zdjęcie"
 
-#: mod/photos.php:1256
+#: mod/photos.php:1258
 msgid "Permission denied. Access to this item may be restricted."
 msgstr "Odmowa dostępu. Dostęp do tych danych może być ograniczony."
 
-#: mod/photos.php:1258
+#: mod/photos.php:1260
 msgid "Photo not available"
 msgstr "Zdjęcie niedostępne"
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "View photo"
 msgstr "Zobacz zdjęcie"
 
-#: mod/photos.php:1333
+#: mod/photos.php:1335
 msgid "Edit photo"
 msgstr "Edytuj zdjęcie"
 
-#: mod/photos.php:1334
+#: mod/photos.php:1336
 msgid "Use as profile photo"
 msgstr "Ustaw jako zdjęcie profilowe"
 
-#: mod/photos.php:1340 src/Object/Post.php:151
+#: mod/photos.php:1342 src/Object/Post.php:151
 msgid "Private Message"
 msgstr "Wiadomość prywatna"
 
-#: mod/photos.php:1360
+#: mod/photos.php:1362
 msgid "View Full Size"
 msgstr "Zobacz w pełnym rozmiarze"
 
-#: mod/photos.php:1421
+#: mod/photos.php:1423
 msgid "Tags: "
-msgstr "Tagi:"
+msgstr "Tagi: "
 
-#: mod/photos.php:1424
+#: mod/photos.php:1426
 msgid "[Remove any tag]"
 msgstr "[Usuń dowolny tag]"
 
-#: mod/photos.php:1439
+#: mod/photos.php:1441
 msgid "New album name"
 msgstr "Nazwa nowego albumu"
 
-#: mod/photos.php:1440
+#: mod/photos.php:1442
 msgid "Caption"
 msgstr "Zawartość"
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid "Add a Tag"
 msgstr "Dodaj tag"
 
-#: mod/photos.php:1441
+#: mod/photos.php:1443
 msgid ""
 "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr "Przykładowo: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 
-#: mod/photos.php:1442
+#: mod/photos.php:1444
 msgid "Do not rotate"
 msgstr "Nie obracaj"
 
-#: mod/photos.php:1443
+#: mod/photos.php:1445
 msgid "Rotate CW (right)"
 msgstr "Obróć CW (w prawo)"
 
-#: mod/photos.php:1444
+#: mod/photos.php:1446
 msgid "Rotate CCW (left)"
 msgstr "Obróć CCW (w lewo)"
 
-#: mod/photos.php:1478 src/Object/Post.php:293
+#: mod/photos.php:1480 src/Object/Post.php:293
 msgid "I like this (toggle)"
 msgstr "Lubię to (zmień)"
 
-#: mod/photos.php:1479 src/Object/Post.php:294
+#: mod/photos.php:1481 src/Object/Post.php:294
 msgid "I don't like this (toggle)"
 msgstr "Nie lubię tego (zmień)"
 
-#: mod/photos.php:1496 mod/photos.php:1535 mod/photos.php:1595
+#: mod/photos.php:1498 mod/photos.php:1537 mod/photos.php:1597
 #: src/Object/Post.php:398 src/Object/Post.php:794
 msgid "Comment"
 msgstr "Komentarz"
 
-#: mod/photos.php:1627
+#: mod/photos.php:1629
 msgid "Map"
 msgstr "Mapa"
 
-#: local/test.php:1840
+#: local/test.php:1919
 #, php-format
 msgid ""
 "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-"
 "name\">%s</a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"
 msgstr "<span><a href=\"%s\" target=\"_blank\" class=\"shared-wall-item-name\">%s</a>napisał następujący<a href=\"%s\" target=\"_blank\">post</a>"
 
-#: local/testshare.php:158 src/Content/Text/BBCode.php:991
+#: local/testshare.php:158 src/Content/Text/BBCode.php:992
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 msgstr "<a href=\"%1$s\" target=\"_blank\">%2$s</a>%3$s"
@@ -7848,23 +7881,23 @@ msgstr "\nWystąpił błąd %d podczas aktualizacji bazy danych:\n%s\n"
 
 #: src/Database/DBStructure.php:195
 msgid "Errors encountered performing database changes: "
-msgstr "Napotkane błędy powodujące zmiany w bazie danych:"
+msgstr "Błędy napotkane podczas dokonywania zmian w bazie danych: "
 
 #: src/Database/DBStructure.php:211
 #, php-format
 msgid "%s: Database update"
-msgstr "%s: Aktualizacja bazy danych:"
+msgstr "%s: Aktualizacja bazy danych"
 
 #: src/Database/DBStructure.php:473
 #, php-format
 msgid "%s: updating %s table."
 msgstr "%s: aktualizowanie %s tabeli."
 
-#: src/Core/Install.php:138
+#: src/Core/Install.php:139
 msgid "Could not find a command line version of PHP in the web server PATH."
-msgstr "Nie można znaleźć wersji PHP komendy w serwerze PATH"
+msgstr "Nie można znaleźć PHP dla wiersza poleceń w PATH serwera."
 
-#: src/Core/Install.php:139
+#: src/Core/Install.php:140
 msgid ""
 "If you don't have a command line version of PHP installed on your server, "
 "you will not be able to run the background processing. See <a "
@@ -7872,219 +7905,219 @@ msgid ""
 "up-the-worker'>'Setup the worker'</a>"
 msgstr "Jeśli nie masz zainstalowanej na serwerze wersji PHP z wierszem poleceń, nie będziesz mógł uruchomić przetwarzania w tle. Zobacz <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Konfiguracja pracownika'</a>"
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid "PHP executable path"
 msgstr "Ścieżka wykonywalna PHP"
 
-#: src/Core/Install.php:143
+#: src/Core/Install.php:144
 msgid ""
 "Enter full path to php executable. You can leave this blank to continue the "
 "installation."
 msgstr "Wprowadź pełną ścieżkę do pliku wykonywalnego php. Możesz pozostawić to pole puste, aby kontynuować instalację."
 
-#: src/Core/Install.php:148
+#: src/Core/Install.php:149
 msgid "Command line PHP"
 msgstr "Linia komend PHP"
 
-#: src/Core/Install.php:157
+#: src/Core/Install.php:158
 msgid "PHP executable is not the php cli binary (could be cgi-fgci version)"
 msgstr "Plik wykonywalny PHP nie jest php cli binarny (może być wersją cgi-fgci)"
 
-#: src/Core/Install.php:158
+#: src/Core/Install.php:159
 msgid "Found PHP version: "
-msgstr "Znaleziono wersje PHP:"
+msgstr "Znaleziona wersja PHP: "
 
-#: src/Core/Install.php:160
+#: src/Core/Install.php:161
 msgid "PHP cli binary"
 msgstr "PHP cli binarny"
 
-#: src/Core/Install.php:170
+#: src/Core/Install.php:171
 msgid ""
 "The command line version of PHP on your system does not have "
 "\"register_argc_argv\" enabled."
 msgstr "Wersja linii poleceń PHP w twoim systemie nie ma aktywowanego \"register_argc_argv\"."
 
-#: src/Core/Install.php:171
+#: src/Core/Install.php:172
 msgid "This is required for message delivery to work."
 msgstr "Jest wymagane, aby dostarczanie wiadomości działało."
 
-#: src/Core/Install.php:173
+#: src/Core/Install.php:174
 msgid "PHP register_argc_argv"
 msgstr "PHP register_argc_argv"
 
-#: src/Core/Install.php:201
+#: src/Core/Install.php:202
 msgid ""
 "Error: the \"openssl_pkey_new\" function on this system is not able to "
 "generate encryption keys"
 msgstr "Błąd: funkcja \"openssl_pkey_new\" w tym systemie nie jest w stanie wygenerować kluczy szyfrujących"
 
-#: src/Core/Install.php:202
+#: src/Core/Install.php:203
 msgid ""
 "If running under Windows, please see "
 "\"http://www.php.net/manual/en/openssl.installation.php\"."
 msgstr "Jeśli korzystasz z Windowsa, proszę odwiedzić \"http://www.php.net/manual/en/openssl.installation.php\"."
 
-#: src/Core/Install.php:204
+#: src/Core/Install.php:205
 msgid "Generate encryption keys"
 msgstr "Generuj klucz kodowania"
 
-#: src/Core/Install.php:225
+#: src/Core/Install.php:226
 msgid "libCurl PHP module"
-msgstr "Moduł libCurl PHP"
+msgstr "Moduł PHP libCurl"
 
-#: src/Core/Install.php:226
+#: src/Core/Install.php:227
 msgid "GD graphics PHP module"
 msgstr "Moduł PHP-GD"
 
-#: src/Core/Install.php:227
+#: src/Core/Install.php:228
 msgid "OpenSSL PHP module"
 msgstr "Moduł PHP OpenSSL"
 
-#: src/Core/Install.php:228
+#: src/Core/Install.php:229
 msgid "PDO or MySQLi PHP module"
 msgstr "Moduł PDO lub MySQLi PHP"
 
-#: src/Core/Install.php:229
+#: src/Core/Install.php:230
 msgid "mb_string PHP module"
-msgstr "Moduł mb_string PHP"
+msgstr "Moduł PHP mb_string"
 
-#: src/Core/Install.php:230
+#: src/Core/Install.php:231
 msgid "XML PHP module"
 msgstr "Moduł XML PHP"
 
-#: src/Core/Install.php:231
+#: src/Core/Install.php:232
 msgid "iconv PHP module"
 msgstr "Moduł PHP iconv"
 
-#: src/Core/Install.php:232
+#: src/Core/Install.php:233
 msgid "POSIX PHP module"
 msgstr "Moduł POSIX PHP"
 
-#: src/Core/Install.php:236 src/Core/Install.php:238
+#: src/Core/Install.php:237 src/Core/Install.php:239
 msgid "Apache mod_rewrite module"
 msgstr "Moduł Apache mod_rewrite"
 
-#: src/Core/Install.php:236
+#: src/Core/Install.php:237
 msgid ""
 "Error: Apache webserver mod-rewrite module is required but not installed."
 msgstr "Błąd: moduł Apache webserver mod-rewrite jest potrzebny, jednakże nie jest zainstalowany."
 
-#: src/Core/Install.php:244
+#: src/Core/Install.php:245
 msgid "Error: libCURL PHP module required but not installed."
 msgstr "Błąd: libCURL PHP wymagany moduł, lecz nie zainstalowany."
 
-#: src/Core/Install.php:248
+#: src/Core/Install.php:249
 msgid ""
 "Error: GD graphics PHP module with JPEG support required but not installed."
 msgstr "Błąd: moduł graficzny GD z PHP potrzebuje wsparcia technicznego JPEG, jednakże on nie jest zainstalowany."
 
-#: src/Core/Install.php:252
+#: src/Core/Install.php:253
 msgid "Error: openssl PHP module required but not installed."
 msgstr "Błąd: openssl PHP wymagany moduł, lecz nie zainstalowany."
 
-#: src/Core/Install.php:256
+#: src/Core/Install.php:257
 msgid "Error: PDO or MySQLi PHP module required but not installed."
 msgstr "Błąd: Wymagany moduł PDO lub MySQLi PHP, ale nie zainstalowany."
 
-#: src/Core/Install.php:260
+#: src/Core/Install.php:261
 msgid "Error: The MySQL driver for PDO is not installed."
 msgstr "Błąd: Sterownik MySQL dla PDO nie jest zainstalowany."
 
-#: src/Core/Install.php:264
+#: src/Core/Install.php:265
 msgid "Error: mb_string PHP module required but not installed."
-msgstr "Błąd: moduł PHP mb_string  jest wymagany ale nie jest zainstalowany"
+msgstr "Błąd: moduł PHP mb_string jest wymagany ,ale nie jest zainstalowany."
 
-#: src/Core/Install.php:268
+#: src/Core/Install.php:269
 msgid "Error: iconv PHP module required but not installed."
 msgstr "Błąd: wymagany moduł PHP iconv, ale nie zainstalowany."
 
-#: src/Core/Install.php:272
+#: src/Core/Install.php:273
 msgid "Error: POSIX PHP module required but not installed."
 msgstr "Błąd: wymagany moduł POSIX PHP, ale nie zainstalowany."
 
-#: src/Core/Install.php:282
+#: src/Core/Install.php:283
 msgid "Error, XML PHP module required but not installed."
 msgstr "Błąd, wymagany moduł XML PHP, ale nie zainstalowany."
 
-#: src/Core/Install.php:301
+#: src/Core/Install.php:302
 msgid ""
 "The web installer needs to be able to create a file called \"local.ini.php\""
 " in the \"config\" folder of your web server and it is unable to do so."
 msgstr "Instalator internetowy musi mieć możliwość utworzenia pliku o nazwie \"local.ini.php\" w folderze \"config\" na serwerze internetowym i nie może tego zrobić."
 
-#: src/Core/Install.php:302
+#: src/Core/Install.php:303
 msgid ""
 "This is most often a permission setting, as the web server may not be able "
 "to write files in your folder - even if you can."
 msgstr "Jest to najczęściej ustawienie uprawnień, ponieważ serwer sieciowy może nie być w stanie zapisywać plików w folderze - nawet jeśli możesz."
 
-#: src/Core/Install.php:303
+#: src/Core/Install.php:304
 msgid ""
 "At the end of this procedure, we will give you a text to save in a file "
 "named local.ini.php in your Friendica \"config\" folder."
 msgstr "Po zakończeniu tej procedury damy ci tekst do zapisania w pliku o nazwie local.ini.php w twoim folderze \"config\" Friendica."
 
-#: src/Core/Install.php:304
+#: src/Core/Install.php:305
 msgid ""
 "You can alternatively skip this procedure and perform a manual installation."
 " Please see the file \"INSTALL.txt\" for instructions."
 msgstr "Alternatywnie można pominąć tę procedurę i wykonać ręczną instalację. Proszę zobaczyć plik 'INSTALL.txt' z instrukcjami."
 
-#: src/Core/Install.php:307
+#: src/Core/Install.php:308
 msgid "config/local.ini.php is writable"
 msgstr "config/local.ini.php jest zapisywalny"
 
-#: src/Core/Install.php:325
+#: src/Core/Install.php:326
 msgid ""
 "Friendica uses the Smarty3 template engine to render its web views. Smarty3 "
 "compiles templates to PHP to speed up rendering."
 msgstr "Friendica używa silnika szablonów Smarty3 do renderowania swoich widoków. Smarty3 kompiluje szablony do PHP, aby przyspieszyć renderowanie."
 
-#: src/Core/Install.php:326
+#: src/Core/Install.php:327
 msgid ""
 "In order to store these compiled templates, the web server needs to have "
 "write access to the directory view/smarty3/ under the Friendica top level "
 "folder."
 msgstr "Aby przechowywać te skompilowane szablony, serwer WWW musi mieć dostęp do zapisu do katalogu view/smarty3/ w folderze najwyższego poziomu Friendica."
 
-#: src/Core/Install.php:327
+#: src/Core/Install.php:328
 msgid ""
 "Please ensure that the user that your web server runs as (e.g. www-data) has"
 " write access to this folder."
 msgstr "Upewnij się, że użytkownik, na którym działa serwer WWW (np. www-data), ma prawo do zapisu do tego folderu."
 
-#: src/Core/Install.php:328
+#: src/Core/Install.php:329
 msgid ""
 "Note: as a security measure, you should give the web server write access to "
 "view/smarty3/ only--not the template files (.tpl) that it contains."
 msgstr "Uwaga: jako środek bezpieczeństwa, powinieneś dać serwerowi dostęp do zapisu view/smarty3/ jedynie - nie do plików szablonów (.tpl), które zawiera."
 
-#: src/Core/Install.php:331
+#: src/Core/Install.php:332
 msgid "view/smarty3 is writable"
 msgstr "view/smarty3 jest zapisywalny"
 
-#: src/Core/Install.php:356
+#: src/Core/Install.php:357
 msgid ""
 "Url rewrite in .htaccess is not working. Check your server configuration."
 msgstr "Nie działa URL w .htaccess popraw. Sprawdź konfigurację serwera."
 
-#: src/Core/Install.php:358
+#: src/Core/Install.php:359
 msgid "Error message from Curl when fetching"
 msgstr "Komunikat o błędzie z Curl podczas pobierania"
 
-#: src/Core/Install.php:362
+#: src/Core/Install.php:363
 msgid "Url rewrite is working"
 msgstr "Działający adres URL"
 
-#: src/Core/Install.php:389
+#: src/Core/Install.php:390
 msgid "ImageMagick PHP extension is not installed"
 msgstr "Rozszerzenie PHP ImageMagick nie jest zainstalowane"
 
-#: src/Core/Install.php:391
+#: src/Core/Install.php:392
 msgid "ImageMagick PHP extension is installed"
 msgstr "Rozszerzenie PHP ImageMagick jest zainstalowane"
 
-#: src/Core/Install.php:393
+#: src/Core/Install.php:394
 msgid "ImageMagick supports GIF"
 msgstr "ImageMagick obsługuje GIF"
 
@@ -8118,17 +8151,22 @@ msgstr "Nie można znaleźć żadnego wpisu kontaktu zarchiwizowanego dla tego a
 msgid "The contact entries have been archived"
 msgstr "Wpisy kontaktów zostały zarchiwizowane"
 
-#: src/Core/Console/PostUpdate.php:32
+#: src/Core/Console/PostUpdate.php:49
+#, php-format
+msgid "Post update version number has been set to %s."
+msgstr "Numer wersji aktualizacji posta został ustawiony na %s."
+
+#: src/Core/Console/PostUpdate.php:57
 msgid "Execute pending post updates."
 msgstr "Wykonaj oczekujące aktualizacje postów."
 
-#: src/Core/Console/PostUpdate.php:38
+#: src/Core/Console/PostUpdate.php:63
 msgid "All pending post updates are done."
 msgstr "Wszystkie oczekujące aktualizacje postów są gotowe."
 
 #: src/Core/Console/NewPassword.php:73
 msgid "Enter new password: "
-msgstr "Wprowadź nowe hasło:"
+msgstr "Wprowadź nowe hasło: "
 
 #: src/Core/Console/NewPassword.php:78 src/Model/User.php:269
 msgid "Password can't be empty"
@@ -8170,32 +8208,32 @@ msgstr "%s nie lubi tych %s postów"
 #: src/Core/NotificationsManager.php:313
 #, php-format
 msgid "%s is attending %s's event"
-msgstr "%s uczestniczy %sw wydarzeniu "
+msgstr "%s uczestniczy w wydarzeniu %s"
 
 #: src/Core/NotificationsManager.php:326
 #, php-format
 msgid "%s is not attending %s's event"
-msgstr "%s nie uczestniczy %s w wydarzeniu "
+msgstr "%s nie uczestniczy w wydarzeniu %s"
 
 #: src/Core/NotificationsManager.php:339
 #, php-format
 msgid "%s may attend %s's event"
 msgstr "%s może uczestniczyć %s w wydarzeniu"
 
-#: src/Core/NotificationsManager.php:360
+#: src/Core/NotificationsManager.php:372
 #, php-format
 msgid "%s is now friends with %s"
 msgstr "%s jest teraz znajomym %s"
 
-#: src/Core/NotificationsManager.php:626
+#: src/Core/NotificationsManager.php:638
 msgid "Friend Suggestion"
 msgstr "Propozycja znajomych"
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "Friend/Connect Request"
 msgstr "Prośba o dodanie do przyjaciół/powiązanych"
 
-#: src/Core/NotificationsManager.php:656
+#: src/Core/NotificationsManager.php:672
 msgid "New Follower"
 msgstr "Nowy obserwujący"
 
@@ -8224,16 +8262,16 @@ msgstr "Błąd tworzenia profilu użytkownika"
 #, php-format
 msgid "%d contact not imported"
 msgid_plural "%d contacts not imported"
-msgstr[0] "Nie zaimportowano %d kontaktu."
-msgstr[1] "Nie zaimportowano %d kontaktów."
-msgstr[2] "Nie zaimportowano %d kontaktów."
+msgstr[0] "Nie zaimportowano %d kontaktu"
+msgstr[1] "Nie zaimportowano %d kontaktów"
+msgstr[2] "Nie zaimportowano %d kontaktów"
 msgstr[3] "%d kontakty nie zostały zaimportowane "
 
 #: src/Core/UserImport.php:274
 msgid "Done. You can now login with your username and password"
-msgstr "Gotowe. Możesz teraz zalogować się, podając swoją nazwę użytkownika i hasło."
+msgstr "Gotowe. Możesz teraz zalogować się z użyciem nazwy użytkownika i hasła"
 
-#: src/Worker/Delivery.php:423
+#: src/Worker/Delivery.php:425
 msgid "(no subject)"
 msgstr "(bez tematu)"
 
@@ -8333,10 +8371,10 @@ msgstr "via Wall-To-Wall:"
 #, php-format
 msgid "%d comment"
 msgid_plural "%d comments"
-msgstr[0] " %d komentarz"
-msgstr[1] " %d komentarzy"
-msgstr[2] " %d komentarzy"
-msgstr[3] " %d komentarzy"
+msgstr[0] "%d komentarz"
+msgstr[1] "%d komentarze"
+msgstr[2] "%d komentarzy"
+msgstr[3] "%d komentarzy"
 
 #: src/Object/Post.php:796
 msgid "Bold"
@@ -8370,15 +8408,15 @@ msgstr "Link"
 msgid "Video"
 msgstr "Video"
 
-#: src/App.php:785
+#: src/App.php:798
 msgid "Delete this item?"
 msgstr "Usunąć ten element?"
 
-#: src/App.php:787
+#: src/App.php:800
 msgid "show fewer"
-msgstr "Pokaż mniej"
+msgstr "pokaż mniej"
 
-#: src/App.php:1385
+#: src/App.php:1416
 msgid "No system theme config value set."
 msgstr "Nie ustawiono wartości konfiguracyjnej zestawu tematycznego."
 
@@ -8402,7 +8440,7 @@ msgstr "Załóż nowe konto"
 
 #: src/Module/Login.php:313
 msgid "Password: "
-msgstr "Hasło:"
+msgstr "Hasło: "
 
 #: src/Module/Login.php:314
 msgid "Remember me"
@@ -8410,7 +8448,7 @@ msgstr "Zapamiętaj mnie"
 
 #: src/Module/Login.php:317
 msgid "Or login using OpenID: "
-msgstr "Lub zaloguj się korzystając z OpenID:"
+msgstr "Lub zaloguj się za pośrednictwem OpenID: "
 
 #: src/Module/Login.php:323
 msgid "Forgot your password?"
@@ -8467,43 +8505,47 @@ msgstr "W dowolnym momencie zalogowany użytkownik może wyeksportować dane swo
 msgid "Privacy Statement"
 msgstr "Oświadczenie o prywatności"
 
-#: src/Protocol/OStatus.php:1813
+#: src/Module/Proxy.php:138
+msgid "Bad Request."
+msgstr "Nieprawidłowe żądanie."
+
+#: src/Protocol/OStatus.php:1823
 #, php-format
 msgid "%s is now following %s."
-msgstr "%sjest teraz następujące %s. "
+msgstr "%s zaczął(-ęła) obserwować %s."
 
-#: src/Protocol/OStatus.php:1814
+#: src/Protocol/OStatus.php:1824
 msgid "following"
 msgstr "następujący"
 
-#: src/Protocol/OStatus.php:1817
+#: src/Protocol/OStatus.php:1827
 #, php-format
 msgid "%s stopped following %s."
-msgstr "%sprzestał śledzić %s. "
+msgstr "%s przestał(a) obserwować %s."
 
-#: src/Protocol/OStatus.php:1818
+#: src/Protocol/OStatus.php:1828
 msgid "stopped following"
 msgstr "przestał śledzić"
 
-#: src/Protocol/DFRN.php:1525 src/Model/Contact.php:1956
+#: src/Protocol/DFRN.php:1528 src/Model/Contact.php:1974
 #, php-format
 msgid "%s's birthday"
 msgstr "%s urodzin"
 
-#: src/Protocol/DFRN.php:1526 src/Model/Contact.php:1957
+#: src/Protocol/DFRN.php:1529 src/Model/Contact.php:1975
 #, php-format
 msgid "Happy Birthday %s"
 msgstr "Urodziny %s"
 
-#: src/Protocol/Diaspora.php:2417
+#: src/Protocol/Diaspora.php:2434
 msgid "Sharing notification from Diaspora network"
 msgstr "Wspólne powiadomienie z sieci Diaspora"
 
-#: src/Protocol/Diaspora.php:3514
+#: src/Protocol/Diaspora.php:3531
 msgid "Attachments:"
 msgstr "Załączniki:"
 
-#: src/Util/Temporal.php:147 src/Model/Profile.php:745
+#: src/Util/Temporal.php:147 src/Model/Profile.php:758
 msgid "Birthday:"
 msgstr "Urodziny:"
 
@@ -8572,134 +8614,134 @@ msgstr "%1$d %2$s temu"
 msgid "[no subject]"
 msgstr "[bez tematu]"
 
-#: src/Model/Contact.php:942
+#: src/Model/Contact.php:953
 msgid "Drop Contact"
-msgstr "Upuść kontakt"
+msgstr "Zakończ znajomość"
 
-#: src/Model/Contact.php:1399
+#: src/Model/Contact.php:1408
 msgid "Organisation"
 msgstr "Organizacja"
 
-#: src/Model/Contact.php:1403
+#: src/Model/Contact.php:1412
 msgid "News"
 msgstr "Aktualności"
 
-#: src/Model/Contact.php:1407
+#: src/Model/Contact.php:1416
 msgid "Forum"
 msgstr "Forum"
 
-#: src/Model/Contact.php:1587
+#: src/Model/Contact.php:1598
 msgid "Connect URL missing."
 msgstr "Brak adresu URL połączenia."
 
-#: src/Model/Contact.php:1596
+#: src/Model/Contact.php:1607
 msgid ""
 "The contact could not be added. Please check the relevant network "
 "credentials in your Settings -> Social Networks page."
 msgstr "Nie można dodać kontaktu. Sprawdź odpowiednie poświadczenia sieciowe na stronie Ustawienia -> Sieci społecznościowe."
 
-#: src/Model/Contact.php:1635
+#: src/Model/Contact.php:1646
 msgid ""
 "This site is not configured to allow communications with other networks."
 msgstr "Ta strona nie jest skonfigurowana do pozwalania na komunikację z innymi sieciami"
 
-#: src/Model/Contact.php:1636 src/Model/Contact.php:1650
+#: src/Model/Contact.php:1647 src/Model/Contact.php:1661
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr "Nie znaleziono żadnych kompatybilnych protokołów komunikacyjnych ani źródeł."
 
-#: src/Model/Contact.php:1648
+#: src/Model/Contact.php:1659
 msgid "The profile address specified does not provide adequate information."
 msgstr "Dany adres profilu nie dostarcza odpowiednich informacji."
 
-#: src/Model/Contact.php:1653
+#: src/Model/Contact.php:1664
 msgid "An author or name was not found."
 msgstr "Autor lub nazwa nie zostało znalezione."
 
-#: src/Model/Contact.php:1656
+#: src/Model/Contact.php:1667
 msgid "No browser URL could be matched to this address."
 msgstr "Przeglądarka WWW nie może odnaleźć podanego adresu"
 
-#: src/Model/Contact.php:1659
+#: src/Model/Contact.php:1670
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr "Nie można dopasować @-stylu Adres identyfikacyjny ze znanym protokołem lub kontaktem e-mail."
 
-#: src/Model/Contact.php:1660
+#: src/Model/Contact.php:1671
 msgid "Use mailto: in front of address to force email check."
 msgstr "Użyj mailto: przed adresem, aby wymusić sprawdzanie poczty e-mail."
 
-#: src/Model/Contact.php:1666
+#: src/Model/Contact.php:1677
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr "Określony adres profilu należy do sieci, która została wyłączona na tej stronie."
 
-#: src/Model/Contact.php:1671
+#: src/Model/Contact.php:1682
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
 msgstr "Profil ograniczony. Ta osoba będzie niezdolna do odbierania osobistych powiadomień od ciebie."
 
-#: src/Model/Contact.php:1722
+#: src/Model/Contact.php:1733
 msgid "Unable to retrieve contact information."
 msgstr "Nie można otrzymać informacji kontaktowych"
 
-#: src/Model/Event.php:59 src/Model/Event.php:76 src/Model/Event.php:428
-#: src/Model/Event.php:897
+#: src/Model/Event.php:60 src/Model/Event.php:77 src/Model/Event.php:429
+#: src/Model/Event.php:904
 msgid "Starts:"
 msgstr "Rozpoczęcie:"
 
-#: src/Model/Event.php:62 src/Model/Event.php:82 src/Model/Event.php:429
-#: src/Model/Event.php:901
+#: src/Model/Event.php:63 src/Model/Event.php:83 src/Model/Event.php:430
+#: src/Model/Event.php:908
 msgid "Finishes:"
 msgstr "Zakończenie:"
 
-#: src/Model/Event.php:377
+#: src/Model/Event.php:378
 msgid "all-day"
 msgstr "cały dzień"
 
-#: src/Model/Event.php:400
+#: src/Model/Event.php:401
 msgid "Jun"
-msgstr "cze"
+msgstr "Cze"
 
-#: src/Model/Event.php:403
+#: src/Model/Event.php:404
 msgid "Sept"
-msgstr "wrz"
+msgstr "Wrz"
 
-#: src/Model/Event.php:426
+#: src/Model/Event.php:427
 msgid "No events to display"
 msgstr "Brak wydarzeń do wyświetlenia"
 
-#: src/Model/Event.php:550
+#: src/Model/Event.php:551
 msgid "l, F j"
 msgstr "l, F j"
 
-#: src/Model/Event.php:581
+#: src/Model/Event.php:582
 msgid "Edit event"
 msgstr "Edytuj wydarzenie"
 
-#: src/Model/Event.php:582
+#: src/Model/Event.php:583
 msgid "Duplicate event"
 msgstr "Zduplikowane zdarzenie"
 
-#: src/Model/Event.php:583
+#: src/Model/Event.php:584
 msgid "Delete event"
 msgstr "Usuń wydarzenie"
 
-#: src/Model/Event.php:830
+#: src/Model/Event.php:837
 msgid "D g:i A"
 msgstr "D g:i A"
 
-#: src/Model/Event.php:831
+#: src/Model/Event.php:838
 msgid "g:i A"
 msgstr "g:i A"
 
-#: src/Model/Event.php:916 src/Model/Event.php:918
+#: src/Model/Event.php:923 src/Model/Event.php:925
 msgid "Show map"
 msgstr "Pokaż mapę"
 
-#: src/Model/Event.php:917
+#: src/Model/Event.php:924
 msgid "Hide map"
 msgstr "Ukryj mapę"
 
@@ -8725,7 +8767,7 @@ msgstr "Nieprawidłowy adres url OpenID"
 
 #: src/Model/User.php:414
 msgid "Please enter the required information."
-msgstr "Wprowadź wymagane informacje"
+msgstr "Wprowadź wymagane informacje."
 
 #: src/Model/User.php:427
 msgid "Please use a shorter name."
@@ -8753,7 +8795,7 @@ msgstr "Pseudonim został zablokowany przed rejestracją przez administratora w
 
 #: src/Model/User.php:454 src/Model/User.php:462
 msgid "Cannot use that email."
-msgstr "Nie możesz użyć tego e-maila. "
+msgstr "Nie można użyć tego e-maila."
 
 #: src/Model/User.php:469
 msgid "Your nickname can only contain a-z, 0-9 and _."
@@ -8779,7 +8821,7 @@ msgstr "Wystąpił błąd podczas tworzenia profilu. Spróbuj ponownie."
 msgid "An error occurred creating your self contact. Please try again."
 msgstr "Wystąpił błąd podczas tworzenia własnego kontaktu. Proszę spróbuj ponownie."
 
-#: src/Model/User.php:561 src/Content/ContactSelector.php:166
+#: src/Model/User.php:561 src/Content/ContactSelector.php:171
 msgid "Friends"
 msgstr "Przyjaciele"
 
@@ -8795,7 +8837,7 @@ msgid ""
 "\t\t\tDear %1$s,\n"
 "\t\t\t\tThank you for registering at %2$s. Your account is pending for approval by the administrator.\n"
 "\t\t"
-msgstr "\n\t\t\tSzanowny Użytkowniku  %1$s, \n\t\t\t\tDziękujemy za rejestrację na stronie %2$s. Twoje konto czeka na zatwierdzenie przez administratora."
+msgstr "\n\t\t\tSzanowny(-a) %1$s,\n\t\t\t\tDziękujemy za rejestrację na stronie %2$s. Twoje konto czeka na zatwierdzenie przez administratora."
 
 #: src/Model/User.php:649
 #, php-format
@@ -8809,7 +8851,7 @@ msgid ""
 "\t\t\tDear %1$s,\n"
 "\t\t\t\tThank you for registering at %2$s. Your account has been created.\n"
 "\t\t"
-msgstr "\n\t\t\tSzanowny Użytkowniku  %1$s, \n\t\t\t\tDziękujemy za rejestrację na stronie %2$s. Twoje konto zostało utworzone."
+msgstr "\n\t\t\tSzanowny(-a) %1$s,\n\t\t\t\tDziękujemy za rejestrację na stronie %2$s. Twoje konto zostało utworzone."
 
 #: src/Model/User.php:671
 #, php-format
@@ -8874,129 +8916,129 @@ msgstr "Stwórz nową grupę"
 msgid "Edit groups"
 msgstr "Edytuj grupy"
 
-#: src/Model/Profile.php:97
+#: src/Model/Profile.php:110
 msgid "Requested account is not available."
 msgstr "Żądane konto jest niedostępne."
 
-#: src/Model/Profile.php:163 src/Model/Profile.php:399
-#: src/Model/Profile.php:846
+#: src/Model/Profile.php:176 src/Model/Profile.php:412
+#: src/Model/Profile.php:859
 msgid "Edit profile"
 msgstr "Edytuj profil"
 
-#: src/Model/Profile.php:333
+#: src/Model/Profile.php:346
 msgid "Atom feed"
 msgstr "Kanał Atom"
 
-#: src/Model/Profile.php:372
+#: src/Model/Profile.php:385
 msgid "Manage/edit profiles"
 msgstr "Zarządzaj profilami"
 
-#: src/Model/Profile.php:550 src/Model/Profile.php:639
+#: src/Model/Profile.php:563 src/Model/Profile.php:652
 msgid "g A l F d"
 msgstr "g A I F d"
 
-#: src/Model/Profile.php:551
+#: src/Model/Profile.php:564
 msgid "F d"
 msgstr "F d"
 
-#: src/Model/Profile.php:604 src/Model/Profile.php:690
+#: src/Model/Profile.php:617 src/Model/Profile.php:703
 msgid "[today]"
 msgstr "[dziś]"
 
-#: src/Model/Profile.php:615
+#: src/Model/Profile.php:628
 msgid "Birthday Reminders"
 msgstr "Przypomnienia o urodzinach"
 
-#: src/Model/Profile.php:616
+#: src/Model/Profile.php:629
 msgid "Birthdays this week:"
 msgstr "Urodziny w tym tygodniu:"
 
-#: src/Model/Profile.php:677
+#: src/Model/Profile.php:690
 msgid "[No description]"
 msgstr "[Brak opisu]"
 
-#: src/Model/Profile.php:704
+#: src/Model/Profile.php:717
 msgid "Event Reminders"
 msgstr "Przypominacze wydarzeń"
 
-#: src/Model/Profile.php:705
+#: src/Model/Profile.php:718
 msgid "Upcoming events the next 7 days:"
 msgstr "Nadchodzące wydarzenia w ciągu następnych 7 dni:"
 
-#: src/Model/Profile.php:728
+#: src/Model/Profile.php:741
 msgid "Member since:"
 msgstr "Członek od:"
 
-#: src/Model/Profile.php:736
+#: src/Model/Profile.php:749
 msgid "j F, Y"
 msgstr "d M, R"
 
-#: src/Model/Profile.php:737
+#: src/Model/Profile.php:750
 msgid "j F"
 msgstr "d M"
 
-#: src/Model/Profile.php:752
+#: src/Model/Profile.php:765
 msgid "Age:"
 msgstr "Wiek:"
 
-#: src/Model/Profile.php:765
+#: src/Model/Profile.php:778
 #, php-format
 msgid "for %1$d %2$s"
 msgstr "od %1$d %2$s"
 
-#: src/Model/Profile.php:789
+#: src/Model/Profile.php:802
 msgid "Religion:"
 msgstr "Religia:"
 
-#: src/Model/Profile.php:797
+#: src/Model/Profile.php:810
 msgid "Hobbies/Interests:"
 msgstr "Hobby/Zainteresowania:"
 
-#: src/Model/Profile.php:809
+#: src/Model/Profile.php:822
 msgid "Contact information and Social Networks:"
-msgstr "Informacje kontaktowe i sieci społeczne"
+msgstr "Informacje kontaktowe i sieci społecznościowe:"
 
-#: src/Model/Profile.php:813
+#: src/Model/Profile.php:826
 msgid "Musical interests:"
 msgstr "Zainteresowania muzyczne:"
 
-#: src/Model/Profile.php:817
+#: src/Model/Profile.php:830
 msgid "Books, literature:"
 msgstr "Książki, literatura:"
 
-#: src/Model/Profile.php:821
+#: src/Model/Profile.php:834
 msgid "Television:"
 msgstr "Telewizja:"
 
-#: src/Model/Profile.php:825
+#: src/Model/Profile.php:838
 msgid "Film/dance/culture/entertainment:"
-msgstr "Film/taniec/kultura/rozrywka"
+msgstr "Film/taniec/kultura/rozrywka:"
 
-#: src/Model/Profile.php:829
+#: src/Model/Profile.php:842
 msgid "Love/Romance:"
 msgstr "Miłość/Romans:"
 
-#: src/Model/Profile.php:833
+#: src/Model/Profile.php:846
 msgid "Work/employment:"
 msgstr "Praca/zatrudnienie:"
 
-#: src/Model/Profile.php:837
+#: src/Model/Profile.php:850
 msgid "School/education:"
 msgstr "Szkoła/edukacja:"
 
-#: src/Model/Profile.php:842
+#: src/Model/Profile.php:855
 msgid "Forums:"
 msgstr "Fora:"
 
-#: src/Model/Profile.php:936
+#: src/Model/Profile.php:949
 msgid "Only You Can See This"
 msgstr "Tylko ty możesz to zobaczyć"
 
-#: src/Model/Profile.php:944 src/Model/Profile.php:947
+#: src/Model/Profile.php:957 src/Model/Profile.php:960
 msgid "Tips for New Members"
 msgstr "Wskazówki dla nowych użytkowników"
 
-#: src/Model/Profile.php:1106
+#: src/Model/Profile.php:1119
 #, php-format
 msgid "OpenWebAuth: %1$s welcomes %2$s"
 msgstr "OpenWebAuth: %1$s wita %2$s"
@@ -9022,33 +9064,33 @@ msgstr[1] "%d zaproszeń dostępnych"
 msgstr[2] "%d zaproszenia dostępne"
 msgstr[3] "%d zaproszenia dostępne"
 
-#: src/Content/Widget.php:157
+#: src/Content/Widget.php:154
 msgid "Networks"
 msgstr "Sieci"
 
-#: src/Content/Widget.php:160
+#: src/Content/Widget.php:157
 msgid "All Networks"
 msgstr "Wszystkie Sieci"
 
-#: src/Content/Widget.php:198 src/Content/Feature.php:118
+#: src/Content/Widget.php:195 src/Content/Feature.php:118
 msgid "Saved Folders"
 msgstr "Zapisz w folderach"
 
-#: src/Content/Widget.php:201 src/Content/Widget.php:241
+#: src/Content/Widget.php:198 src/Content/Widget.php:238
 msgid "Everything"
 msgstr "Wszystko"
 
-#: src/Content/Widget.php:238
+#: src/Content/Widget.php:235
 msgid "Categories"
 msgstr "Kategorie"
 
-#: src/Content/Widget.php:305
+#: src/Content/Widget.php:302
 #, php-format
 msgid "%d contact in common"
 msgid_plural "%d contacts in common"
-msgstr[0] "%dwspólny kontakt "
-msgstr[1] "%dwspólny kontakt"
-msgstr[2] "%dwspólne kontakty "
+msgstr[0] "%d wspólny kontakt"
+msgstr[1] "%d wspólne kontakty"
+msgstr[2] "%d wspólnych kontaktów"
 msgstr[3] "%dwspólnych kontaktów"
 
 #: src/Content/ContactSelector.php:54
@@ -9120,232 +9162,236 @@ msgid "GNU Social Connector"
 msgstr "Łącze GNU Social"
 
 #: src/Content/ContactSelector.php:92
+msgid "ActivityPub"
+msgstr "Pub aktywności"
+
+#: src/Content/ContactSelector.php:93
 msgid "pnut"
 msgstr "orzech"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Male"
 msgstr "Mężczyzna"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Female"
 msgstr "Kobieta"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Male"
 msgstr "Obecnie mężczyzna"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Currently Female"
 msgstr "Obecnie Kobieta"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Male"
 msgstr "Najczęściej męskie"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Mostly Female"
 msgstr "Najczęściej żeńskie"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transgender"
 msgstr "Transseksualny"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Intersex"
 msgstr "Interseksualne"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Transsexual"
 msgstr "Transseksualny"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Hermaphrodite"
 msgstr "Hermafrodyta"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Neuter"
 msgstr "Rodzaj nijaki"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Non-specific"
 msgstr "Niespecyficzne"
 
-#: src/Content/ContactSelector.php:122
+#: src/Content/ContactSelector.php:127
 msgid "Other"
 msgstr "Inne"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Males"
 msgstr "Mężczyźni"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Females"
 msgstr "Kobiety"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Gay"
 msgstr "Gej"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Lesbian"
 msgstr "Lesbijka"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "No Preference"
 msgstr "Brak preferencji"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Bisexual"
-msgstr "Biseksualny"
+msgstr "Biseksualny(-a)"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Autosexual"
-msgstr "Niezidentyfikowany"
+msgstr "Autoseksualny(-a)"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Abstinent"
 msgstr "Abstynent"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Virgin"
 msgstr "Dziewica"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Deviant"
 msgstr "Zboczeniec"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Fetish"
 msgstr "Fetysz"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Oodles"
 msgstr "Nadmiar"
 
-#: src/Content/ContactSelector.php:144
+#: src/Content/ContactSelector.php:149
 msgid "Nonsexual"
-msgstr "Nieseksualny"
+msgstr "Nieseksualny(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Single"
 msgstr "Singiel"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Lonely"
-msgstr "Samotny"
+msgstr "Samotny(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Available"
-msgstr "Dostępny"
+msgstr "Dostępny(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unavailable"
-msgstr "Niedostępny"
+msgstr "Niedostępny(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Has crush"
-msgstr "Ma sympatii"
+msgstr "Ma sympatię"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Infatuated"
-msgstr "Zakochany"
+msgstr "Zakochany(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Dating"
 msgstr "Randki"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unfaithful"
-msgstr "Niewierny"
+msgstr "Niewierny(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Sex Addict"
-msgstr "Uzależniony od seksu"
+msgstr "Uzależniony(-a) od seksu"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Friends/Benefits"
 msgstr "Przyjaciele/Korzyści"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Casual"
 msgstr "Przypadkowy"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Engaged"
-msgstr "Zaręczeni"
+msgstr "Zaręczony(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Married"
-msgstr "Małżeństwo"
+msgstr "W związku małżeńskim"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily married"
 msgstr "Fikcyjnie w związku małżeńskim"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Partners"
 msgstr "Partnerzy"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Cohabiting"
 msgstr "Konkubinat"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Common law"
 msgstr "Prawo zwyczajowe"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Happy"
-msgstr "Szczęśliwy"
+msgstr "Szczęśliwy(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Not looking"
-msgstr "Nie patrzę"
+msgstr "Nie szukam"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Swinger"
 msgstr "Swinger"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Betrayed"
-msgstr "Zdradzony"
+msgstr "Zdradzony(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Separated"
 msgstr "W separacji"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Unstable"
 msgstr "Niestabilny"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Divorced"
-msgstr "Rozwiedzeni"
+msgstr "Rozwiedziony(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Imaginarily divorced"
-msgstr "Fikcyjnie rozwiedziony/a"
+msgstr "Fikcyjnie rozwiedziony(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Widowed"
 msgstr "Wdowiec"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Uncertain"
-msgstr "Nieokreślony"
+msgstr "Nieokreślony(-a)"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "It's complicated"
 msgstr "To skomplikowane"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Don't care"
 msgstr "Nie przejmuj się"
 
-#: src/Content/ContactSelector.php:166
+#: src/Content/ContactSelector.php:171
 msgid "Ask me"
-msgstr "Zapytaj mnie "
+msgstr "Zapytaj mnie"
 
 #: src/Content/Feature.php:79
 msgid "General Features"
@@ -9357,7 +9403,7 @@ msgstr "Wiele profili"
 
 #: src/Content/Feature.php:81
 msgid "Ability to create multiple profiles"
-msgstr "Umożliwia tworzenia wielu profili"
+msgstr "Możliwość tworzenia wielu profili"
 
 #: src/Content/Feature.php:82
 msgid "Photo Location"
@@ -9690,27 +9736,27 @@ msgstr "Osadzanie wyłączone"
 msgid "Embedded content"
 msgstr "Osadzona zawartość"
 
-#: src/Content/Text/BBCode.php:423
+#: src/Content/Text/BBCode.php:422
 msgid "view full size"
-msgstr "Zobacz w pełnym wymiarze"
+msgstr "zobacz pełny rozmiar"
 
-#: src/Content/Text/BBCode.php:853 src/Content/Text/BBCode.php:1626
-#: src/Content/Text/BBCode.php:1627
+#: src/Content/Text/BBCode.php:854 src/Content/Text/BBCode.php:1623
+#: src/Content/Text/BBCode.php:1624
 msgid "Image/photo"
 msgstr "Obrazek/zdjęcie"
 
-#: src/Content/Text/BBCode.php:1553 src/Content/Text/BBCode.php:1575
+#: src/Content/Text/BBCode.php:1550 src/Content/Text/BBCode.php:1572
 msgid "$1 wrote:"
 msgstr "$1 napisał:"
 
-#: src/Content/Text/BBCode.php:1635 src/Content/Text/BBCode.php:1636
+#: src/Content/Text/BBCode.php:1632 src/Content/Text/BBCode.php:1633
 msgid "Encrypted content"
 msgstr "Szyfrowana treść"
 
-#: src/Content/Text/BBCode.php:1755
+#: src/Content/Text/BBCode.php:1752
 msgid "Invalid source protocol"
 msgstr "Nieprawidłowy protokół źródłowy"
 
-#: src/Content/Text/BBCode.php:1766
+#: src/Content/Text/BBCode.php:1763
 msgid "Invalid link protocol"
 msgstr "Niepoprawny link protokołu"
index 82876b12ac5b13b02f2dd9698d6e8cdf32e03da0..b76d61dae3efd116f2c0f9e9b651cde8c2c8f07c 100644 (file)
@@ -6,7 +6,7 @@ function string_plural_select_pl($n){
        return ($n==1 ? 0 : ($n%10>=2 && $n%10<=4) && ($n%100<12 || $n%100>14) ? 1 : $n!=1 && ($n%10>=0 && $n%10<=1) || ($n%10>=5 && $n%10<=9) || ($n%100>=12 && $n%100<=14) ? 2 : 3);;
 }}
 ;
-$a->strings["You must be logged in to use addons. "] = "Musisz być zalogowany, aby korzystać z dodatków.";
+$a->strings["You must be logged in to use addons. "] = "Musisz być zalogowany(-a), aby korzystać z dodatków. ";
 $a->strings["Not Found"] = "Nie znaleziono";
 $a->strings["Page not found."] = "Strona nie znaleziona.";
 $a->strings["Permission denied"] = "Odmowa dostępu";
@@ -47,11 +47,11 @@ $a->strings["Friend Suggestions"] = "Osoby, które możesz znać";
 $a->strings["Similar Interests"] = "Podobne zainteresowania";
 $a->strings["Random Profile"] = "Domyślny profil";
 $a->strings["Invite Friends"] = "Zaproś znajomych";
-$a->strings["Global Directory"] = "Katalog Globalny";
+$a->strings["Global Directory"] = "Katalog globalny";
 $a->strings["Local Directory"] = "Katalog lokalny";
 $a->strings["Forums"] = "Fora";
 $a->strings["External link to forum"] = "Zewnętrzny link do forum";
-$a->strings["show more"] = "Pokaż więcej";
+$a->strings["show more"] = "pokaż więcej";
 $a->strings["Quick Start"] = "Szybki start";
 $a->strings["Help"] = "Pomoc";
 $a->strings["Custom"] = "Niestandardowe";
@@ -59,7 +59,7 @@ $a->strings["Note"] = "Uwaga";
 $a->strings["Check image permissions if all users are allowed to see the image"] = "Sprawdź uprawnienia do zdjęć, jeśli wszyscy użytkownicy mogą zobaczyć obraz";
 $a->strings["Select color scheme"] = "Wybierz schemat kolorów";
 $a->strings["Navigation bar background color"] = "Kolor tła paska nawigacyjnego";
-$a->strings["Navigation bar icon color "] = "Kolor ikony paska nawigacyjnego";
+$a->strings["Navigation bar icon color "] = "Kolor ikon na pasku nawigacyjnym ";
 $a->strings["Link color"] = "Kolor łączy";
 $a->strings["Set the background color"] = "Ustaw kolor tła";
 $a->strings["Content background opacity"] = "Nieprzezroczystość tła treści";
@@ -100,7 +100,7 @@ $a->strings["Single row mosaic"] = "Mozaika jednorzędowa";
 $a->strings["Resize image to repeat it on a single row, either vertical or horizontal."] = "Zmień rozmiar obrazu, aby powtórzyć go w jednym wierszu, w pionie lub w poziomie.";
 $a->strings["Mosaic"] = "Mozaika";
 $a->strings["Repeat image to fill the screen."] = "Powtórz obraz, aby wypełnić ekran.";
-$a->strings["%s: Updating author-id and owner-id in item and thread table. "] = "%s: Aktualizowanie ID autora i właściciela w tabeli pozycji i wątku.";
+$a->strings["%s: Updating author-id and owner-id in item and thread table. "] = "%s: Aktualizowanie ID autora i właściciela w tabeli pozycji i wątku. ";
 $a->strings["%s: Updating post-type."] = "%s: Aktualizowanie typu postu.";
 $a->strings["Item not found."] = "Element nie znaleziony.";
 $a->strings["Do you really want to delete this item?"] = "Czy na pewno chcesz usunąć ten element?";
@@ -112,7 +112,7 @@ $a->strings["status"] = "status";
 $a->strings["photo"] = "zdjęcie";
 $a->strings["%1\$s likes %2\$s's %3\$s"] = "%1\$s lubi to %2\$s's %3\$s";
 $a->strings["%1\$s doesn't like %2\$s's %3\$s"] = "%1\$s nie lubi %2\$s's %3\$s";
-$a->strings["%1\$s attends %2\$s's %3\$s"] = "%1\$sbierze udział w %2\$s's%3\$s ";
+$a->strings["%1\$s attends %2\$s's %3\$s"] = "%1\$s bierze udział w %2\$s's %3\$s";
 $a->strings["%1\$s doesn't attend %2\$s's %3\$s"] = "%1\$s nie uczestniczy %2\$s 's %3\$s";
 $a->strings["%1\$s attends maybe %2\$s's %3\$s"] = "%1\$s może bierze udział %2\$s 's %3\$s";
 $a->strings["%1\$s is now friends with %2\$s"] = "%1\$s jest teraz znajomym z %2\$s";
@@ -156,18 +156,18 @@ $a->strings["and"] = "i";
 $a->strings["and %d other people"] = "i %d inni ludzie";
 $a->strings["<span  %1\$s>%2\$d people</span> like this"] = "<span  %1\$s>%2\$d ludzi </span> lubi to";
 $a->strings["%s like this."] = "%s lubię to.";
-$a->strings["<span  %1\$s>%2\$d people</span> don't like this"] = "<span  %1\$s>%2\$d ludzi </span>nie lubi tego ";
+$a->strings["<span  %1\$s>%2\$d people</span> don't like this"] = "<span  %1\$s>%2\$d ludzi</span> nie lubi tego";
 $a->strings["%s don't like this."] = "%s nie lubię tego.";
 $a->strings["<span  %1\$s>%2\$d people</span> attend"] = "<span  %1\$s>%2\$dosoby</span> uczestniczą";
-$a->strings["%s attend."] = "%suczestniczy";
+$a->strings["%s attend."] = "%s uczestniczy.";
 $a->strings["<span  %1\$s>%2\$d people</span> don't attend"] = "<span  %1\$s>%2\$dludzie</span> nie uczestniczą";
-$a->strings["%s don't attend."] = "%s nie uczestnicz";
-$a->strings["<span  %1\$s>%2\$d people</span> attend maybe"] = "<span  %1\$s>%2\$dprzyjaciele</span>mogą uczestniczyć ";
-$a->strings["%s attend maybe."] = "%sbyć może uczestniczyć. ";
+$a->strings["%s don't attend."] = "%s nie uczestniczy.";
+$a->strings["<span  %1\$s>%2\$d people</span> attend maybe"] = "Możliwe, że <span  %1\$s>%2\$d osoby</span> będą uczestniczyć";
+$a->strings["%s attend maybe."] = "%sbyć może uczestniczyć.";
 $a->strings["Visible to <strong>everybody</strong>"] = "Widoczne dla <strong>wszystkich</strong>";
 $a->strings["Please enter a link URL:"] = "Proszę wpisać adres URL:";
-$a->strings["Please enter a video link/URL:"] = "Podaj link do filmu";
-$a->strings["Please enter an audio link/URL:"] = "Podaj link do muzyki";
+$a->strings["Please enter a video link/URL:"] = "Podaj odnośnik do filmu:";
+$a->strings["Please enter an audio link/URL:"] = "Podaj odnośnik do muzyki:";
 $a->strings["Tag term:"] = "Termin tagu:";
 $a->strings["Save to Folder:"] = "Zapisz w folderze:";
 $a->strings["Where are you right now?"] = "Gdzie teraz jesteś?";
@@ -179,7 +179,7 @@ $a->strings["upload photo"] = "dodaj zdjęcie";
 $a->strings["Attach file"] = "Załącz plik";
 $a->strings["attach file"] = "załącz plik";
 $a->strings["Insert web link"] = "Wstaw link";
-$a->strings["web link"] = "Adres www";
+$a->strings["web link"] = "odnośnik sieciowy";
 $a->strings["Insert video link"] = "Wstaw link do filmu";
 $a->strings["video link"] = "link do filmu";
 $a->strings["Insert audio link"] = "Wstaw link do audio";
@@ -233,30 +233,30 @@ $a->strings["Thank You,"] = "Dziękuję,";
 $a->strings["%1\$s, %2\$s Administrator"] = "%1\$s,%2\$sAdministrator";
 $a->strings["%s Administrator"] = "%s Administrator";
 $a->strings["[Friendica:Notify] New mail received at %s"] = "[Friendica:Powiadomienie] Nowa wiadomość otrzymana od %s";
-$a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$swysłał ci nową prywatną wiadomość na %2\$s ";
+$a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$s wysłał(-a) ci nową prywatną wiadomość na %2\$s.";
 $a->strings["a private message"] = "prywatna wiadomość";
-$a->strings["%1\$s sent you %2\$s."] = "%1\$s wysyła ci %2\$s";
-$a->strings["Please visit %s to view and/or reply to your private messages."] = "Odwiedź %s żeby zobaczyć i/lub odpowiedzieć na twoje prywatne wiadomości";
+$a->strings["%1\$s sent you %2\$s."] = "%1\$s wysłał(-a) ci %2\$s.";
+$a->strings["Please visit %s to view and/or reply to your private messages."] = "Odwiedź %s, aby zobaczyć i/lub odpowiedzieć na twoje prywatne wiadomości.";
 $a->strings["%1\$s commented on [url=%2\$s]a %3\$s[/url]"] = "%1\$s skomentował [url=%2\$s]a %3\$s[/url]";
-$a->strings["%1\$s commented on [url=%2\$s]%3\$s's %4\$s[/url]"] = "%1\$sskomentował  [url=%2\$s]%3\$s %4\$s[/url]";
+$a->strings["%1\$s commented on [url=%2\$s]%3\$s's %4\$s[/url]"] = "%1\$sskomentował [url=%2\$s]%3\$s %4\$s[/url]";
 $a->strings["%1\$s commented on [url=%2\$s]your %3\$s[/url]"] = "%1\$s skomentował [url=%2\$s] twój %3\$s[/ url]";
 $a->strings["[Friendica:Notify] Comment to conversation #%1\$d by %2\$s"] = "[Friendica:Powiadomienie] Komentarz do rozmowy #%1\$d przez %2\$s";
-$a->strings["%s commented on an item/conversation you have been following."] = "%s skomentował rozmowę którą śledzisz";
-$a->strings["Please visit %s to view and/or reply to the conversation."] = "Odwiedź %s żeby zobaczyć i/lub odpowiedzieć na rozmowę";
+$a->strings["%s commented on an item/conversation you have been following."] = "%s skomentował(-a) rozmowę którą śledzisz.";
+$a->strings["Please visit %s to view and/or reply to the conversation."] = "Odwiedź %s, aby zobaczyć i/lub odpowiedzieć na rozmowę.";
 $a->strings["[Friendica:Notify] %s posted to your profile wall"] = "[Friendica:Powiadomienie] %s napisał na twoim profilu";
-$a->strings["%1\$s posted to your profile wall at %2\$s"] = "%1\$sopublikowano na ścianie profilu w %2\$s ";
-$a->strings["%1\$s posted to [url=%2\$s]your wall[/url]"] = "%1\$s wysłano do [url =%2\$s]twojej strony[/url] ";
+$a->strings["%1\$s posted to your profile wall at %2\$s"] = "%1\$s opublikował(-a) wpis na twojej ścianie o %2\$s";
+$a->strings["%1\$s posted to [url=%2\$s]your wall[/url]"] = "%1\$s opublikował(-a) na [url=%2\$s]twojej ścianie[/url]";
 $a->strings["[Friendica:Notify] %s tagged you"] = "[Friendica:Powiadomienie] %s dodał Cię";
 $a->strings["%1\$s tagged you at %2\$s"] = "%1\$s oznaczono Cię tagiem %2\$s";
-$a->strings["%1\$s [url=%2\$s]tagged you[/url]."] = "%1\$s [url=%2\$s]oznaczył Cię[/url]. ";
+$a->strings["%1\$s [url=%2\$s]tagged you[/url]."] = "%1\$s [url=%2\$s]oznaczył(-a) Cię[/url].";
 $a->strings["[Friendica:Notify] %s shared a new post"] = "[Friendica:Powiadomienie] %s udostępnił nowy wpis";
-$a->strings["%1\$s shared a new post at %2\$s"] = "%1\$sudostępnił nowy wpis na %2\$s ";
+$a->strings["%1\$s shared a new post at %2\$s"] = "%1\$s udostępnił(-a) nowy wpis na %2\$s";
 $a->strings["%1\$s [url=%2\$s]shared a post[/url]."] = "%1\$s[url=%2\$s]udostępnił wpis[/url].";
 $a->strings["[Friendica:Notify] %1\$s poked you"] = "[Friendica: Powiadomienie] %1\$s zaczepia Cię";
 $a->strings["%1\$s poked you at %2\$s"] = "%1\$s zaczepił Cię %2\$s";
 $a->strings["%1\$s [url=%2\$s]poked you[/url]."] = "%1\$s[url=%2\$s] zaczepił Cię[/url].";
 $a->strings["[Friendica:Notify] %s tagged your post"] = "[Friendica:Powiadomienie] %s otagował Twój post";
-$a->strings["%1\$s tagged your post at %2\$s"] = "%1\$soznaczyłeś swój wpis na %2\$s ";
+$a->strings["%1\$s tagged your post at %2\$s"] = "%1\$s oznaczył(-a) twój wpis na %2\$s";
 $a->strings["%1\$s tagged [url=%2\$s]your post[/url]"] = "%1\$soznacz [url=%2\$s]twój post[/url]";
 $a->strings["[Friendica:Notify] Introduction received"] = "[Friendica:Powiadomienie] Zapoznanie odebrane";
 $a->strings["You've received an introduction from '%1\$s' at %2\$s"] = "Otrzymałeś wstęp od '%1\$s' z %2\$s";
@@ -264,7 +264,7 @@ $a->strings["You've received [url=%1\$s]an introduction[/url] from %2\$s."] = "Z
 $a->strings["You may visit their profile at %s"] = "Możesz odwiedzić ich profil na stronie %s";
 $a->strings["Please visit %s to approve or reject the introduction."] = "Odwiedż %s aby zatwierdzić lub odrzucić przedstawienie.";
 $a->strings["[Friendica:Notify] A new person is sharing with you"] = "[Friendica:Powiadomienie] Nowa osoba dzieli się z tobą";
-$a->strings["%1\$s is sharing with you at %2\$s"] = "%1\$sdzieli się z tobą w %2\$s ";
+$a->strings["%1\$s is sharing with you at %2\$s"] = "%1\$s dzieli się z tobą w %2\$s";
 $a->strings["[Friendica:Notify] You have a new follower"] = "[Friendica:Powiadomienie] Masz nowego obserwatora";
 $a->strings["You have a new follower at %2\$s : %1\$s"] = "Masz nowego obserwatora na %2\$s : %1\$s";
 $a->strings["[Friendica:Notify] Friend suggestion received"] = "[Friendica: Powiadomienie] Otrzymano sugestię znajomego";
@@ -275,7 +275,7 @@ $a->strings["Photo:"] = "Zdjęcie:";
 $a->strings["Please visit %s to approve or reject the suggestion."] = "Odwiedź stronę %s, aby zatwierdzić lub odrzucić sugestię.";
 $a->strings["[Friendica:Notify] Connection accepted"] = "[Friendica: Powiadomienie] Połączenie zostało zaakceptowane";
 $a->strings["'%1\$s' has accepted your connection request at %2\$s"] = "'%1\$s' zaakceptował Twoją prośbę o połączenie na %2\$s";
-$a->strings["%2\$s has accepted your [url=%1\$s]connection request[/url]."] = "%2\$szaakceptował twoje [url=%1\$s] żądanie połączenia [/url]. ";
+$a->strings["%2\$s has accepted your [url=%1\$s]connection request[/url]."] = "%2\$s zaakceptował twoją [url=%1\$s] prośbę o połączenie [/url].";
 $a->strings["You are now mutual friends and may exchange status updates, photos, and email without restriction."] = "Jesteście teraz przyjaciółmi i możesz wymieniać aktualizacje statusu, zdjęcia i e-maile bez ograniczeń.";
 $a->strings["Please visit %s if you wish to make any changes to this relationship."] = "Odwiedź stronę %s jeśli chcesz wprowadzić zmiany w tym związku.";
 $a->strings["'%1\$s' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically."] = "'%1\$s' zdecydował się zaakceptować Cię jako fana, który ogranicza niektóre formy komunikacji - takie jak prywatne wiadomości i niektóre interakcje w profilu. Jeśli jest to strona celebrytów lub społeczności, ustawienia te zostały zastosowane automatycznie.";
@@ -285,7 +285,7 @@ $a->strings["[Friendica System Notify]"] = "[Powiadomienie Systemu Friendica]";
 $a->strings["registration request"] = "prośba o rejestrację";
 $a->strings["You've received a registration request from '%1\$s' at %2\$s"] = "Otrzymałeś wniosek rejestracyjny od '%1\$s' na %2\$s";
 $a->strings["You've received a [url=%1\$s]registration request[/url] from %2\$s."] = "Otrzymałeś [url=%1\$s] żądanie rejestracji [/url] od %2\$s.";
-$a->strings["Full Name:\t%s\nSite Location:\t%s\nLogin Name:\t%s (%s)"] = "Imię i Nazwisko:\t%s\nLokalizacja witryny:\t%s\nNazwa użytkownika:\t%s(%s)";
+$a->strings["Full Name:\t%s\nSite Location:\t%s\nLogin Name:\t%s (%s)"] = "Imię i nazwisko:\t%s\nLokalizacja witryny:\t%s\nNazwa użytkownika:\t%s(%s)";
 $a->strings["Please visit %s to approve or reject the request."] = "Odwiedź stronę %s, aby zatwierdzić lub odrzucić wniosek.";
 $a->strings["newer"] = "nowsze";
 $a->strings["older"] = "starsze";
@@ -366,9 +366,9 @@ $a->strings["view on separate page"] = "zobacz na oddzielnej stronie";
 $a->strings["link to source"] = "link do źródła";
 $a->strings["activity"] = "aktywność";
 $a->strings["comment"] = [
-       0 => "",
-       1 => "",
-       2 => "komentarz",
+       0 => "komentarz",
+       1 => "komentarze",
+       2 => "komentarze",
        3 => "komentarz",
 ];
 $a->strings["post"] = "post";
@@ -389,7 +389,7 @@ $a->strings["Monthly posting limit of %d post reached. The post was rejected."]
 $a->strings["Profile Photos"] = "Zdjęcie profilowe";
 $a->strings["Contact settings applied."] = "Ustawienia kontaktu zaktualizowane.";
 $a->strings["Contact update failed."] = "Nie udało się zaktualizować kontaktu.";
-$a->strings["Contact not found."] = "Kontakt nie znaleziony";
+$a->strings["Contact not found."] = "Nie znaleziono kontaktu.";
 $a->strings["<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working."] = "<strong>OSTRZEŻENIE: Jest to bardzo zaawansowane</strong> i jeśli wprowadzisz niepoprawne informacje, twoja komunikacja z tym kontaktem może przestać działać.";
 $a->strings["Please use your browser 'Back' button <strong>now</strong> if you are uncertain what to do on this page."] = "Jeśli nie jesteś pewien, co zrobić na tej stronie, użyj <strong>teraz</strong> przycisku 'powrót' na swojej przeglądarce.";
 $a->strings["No mirroring"] = "Bez dublowania";
@@ -412,7 +412,7 @@ $a->strings["New photo from this URL"] = "Nowe zdjęcie z tego adresu URL";
 $a->strings["Number of daily wall messages for %s exceeded. Message failed."] = "Dzienny limit wiadomości %s został przekroczony. Wiadomość została odrzucona.";
 $a->strings["No recipient selected."] = "Nie wybrano odbiorcy.";
 $a->strings["Unable to check your home location."] = "Nie można sprawdzić twojej lokalizacji.";
-$a->strings["Message could not be sent."] = "Wiadomość nie może zostać wysłana";
+$a->strings["Message could not be sent."] = "Nie udało się wysłać wiadomości.";
 $a->strings["Message collection failure."] = "Błąd zbierania komunikatów.";
 $a->strings["Message sent."] = "Wysłano.";
 $a->strings["No recipient."] = "Brak odbiorcy.";
@@ -424,7 +424,7 @@ $a->strings["Your message:"] = "Twoja wiadomość:";
 $a->strings["Remote privacy information not available."] = "Nie są dostępne zdalne informacje o prywatności.";
 $a->strings["Visible to:"] = "Widoczne dla:";
 $a->strings["Friendica Communications Server - Setup"] = "Friendica Serwer Komunikacyjny - Instalacja";
-$a->strings["Could not connect to database."] = "Nie można nawiązać połączenia z bazą danych";
+$a->strings["Could not connect to database."] = "Nie można połączyć się z bazą danych.";
 $a->strings["Could not create table."] = "Nie mogę stworzyć tabeli.";
 $a->strings["Your Friendica site database has been installed."] = "Twoja baza danych witryny Friendica została zainstalowana.";
 $a->strings["You may need to import the file \"database.sql\" manually using phpmyadmin or mysql."] = "Może być konieczne zaimportowanie pliku \"database.sql\" ręcznie, używając phpmyadmin lub mysql.";
@@ -459,7 +459,7 @@ $a->strings["Unexpected response from remote site: "] = "Nieoczekiwana odpowied
 $a->strings["Confirmation completed successfully."] = "Potwierdzenie zostało pomyślnie zakończone.";
 $a->strings["Temporary failure. Please wait and try again."] = "Tymczasowa awaria. Proszę czekać i spróbuj ponownie.";
 $a->strings["Introduction failed or was revoked."] = "Wprowadzenie nie powiodło się lub zostało odwołane.";
-$a->strings["Remote site reported: "] = "Zdalna witryna zgłoszona:";
+$a->strings["Remote site reported: "] = "Zgłoszona zdana strona:";
 $a->strings["Unable to set contact photo."] = "Nie można ustawić zdjęcia kontaktu.";
 $a->strings["No user record found for '%s' "] = "Nie znaleziono użytkownika dla '%s'";
 $a->strings["Our site encryption key is apparently messed up."] = "Klucz kodujący jest najwyraźniej uszkodzony.";
@@ -474,19 +474,19 @@ $a->strings["People Search - %s"] = "Szukaj osób - %s";
 $a->strings["Forum Search - %s"] = "Przeszukiwanie forum - %s";
 $a->strings["Connect"] = "Połącz";
 $a->strings["No matches"] = "Brak wyników";
-$a->strings["Manage Identities and/or Pages"] = "Zarządzaj Tożsamościami i/lub Stronami.";
+$a->strings["Manage Identities and/or Pages"] = "Zarządzaj tożsamościami i/lub stronami";
 $a->strings["Toggle between different identities or community/group pages which share your account details or which you have been granted \"manage\" permissions"] = "Przełącz między różnymi tożsamościami lub stronami społeczność/grupy, które udostępniają dane Twojego konta lub które otrzymałeś uprawnienia \"zarządzaj\"";
-$a->strings["Select an identity to manage: "] = "Wybierz tożsamość do zarządzania:";
+$a->strings["Select an identity to manage: "] = "Wybierz tożsamość do zarządzania: ";
 $a->strings["Do you really want to delete this video?"] = "Czy na pewno chcesz usunąć ten film wideo?";
 $a->strings["Delete Video"] = "Usuń wideo";
-$a->strings["Public access denied."] = "Publiczny dostęp zabroniony";
+$a->strings["Public access denied."] = "Publiczny dostęp zabroniony.";
 $a->strings["No videos selected"] = "Nie zaznaczono filmów";
 $a->strings["Access to this item is restricted."] = "Dostęp do tego obiektu jest ograniczony.";
 $a->strings["View Album"] = "Zobacz album";
 $a->strings["Recent Videos"] = "Ostatnio dodane filmy";
 $a->strings["Upload New Videos"] = "Wstaw nowe filmy";
 $a->strings["Only logged in users are permitted to perform a probing."] = "Tylko zalogowani użytkownicy mogą wykonywać sondowanie.";
-$a->strings["Location:"] = "Lokalizacja";
+$a->strings["Location:"] = "Lokalizacja:";
 $a->strings["Gender:"] = "Płeć:";
 $a->strings["Status:"] = "Status:";
 $a->strings["Homepage:"] = "Strona główna:";
@@ -507,7 +507,7 @@ $a->strings["Social Networks"] = "Portale społecznościowe";
 $a->strings["Addons"] = "Dodatki";
 $a->strings["Delegations"] = "Delegowanie";
 $a->strings["Connected apps"] = "Powiązane aplikacje";
-$a->strings["Export personal data"] = "Eksportuje dane personalne";
+$a->strings["Export personal data"] = "Eksportuj dane osobiste";
 $a->strings["Remove account"] = "Usuń konto";
 $a->strings["Missing some important data!"] = "Brakuje ważnych danych!";
 $a->strings["Update"] = "Zaktualizuj";
@@ -521,8 +521,8 @@ $a->strings["The new password has been exposed in a public data dump, please cho
 $a->strings["Wrong password."] = "Złe hasło.";
 $a->strings["Password changed."] = "Hasło zostało zmienione.";
 $a->strings["Password update failed. Please try again."] = "Aktualizacja hasła nie powiodła się. Proszę spróbować ponownie.";
-$a->strings[" Please use a shorter name."] = "Proszę użyć krótszej nazwy.";
-$a->strings[" Name too short."] = "Za krótka nazwa.";
+$a->strings[" Please use a shorter name."] = " Proszę użyć krótszej nazwy.";
+$a->strings[" Name too short."] = " Nazwa jest zbyt krótka.";
 $a->strings["Wrong Password"] = "Złe hasło";
 $a->strings["Invalid email."] = "Niepoprawny e-mail.";
 $a->strings["Cannot change to that email."] = "Nie można zmienić tego e-maila.";
@@ -547,11 +547,11 @@ $a->strings["Off"] = "Wyłącz";
 $a->strings["On"] = "Włącz";
 $a->strings["Additional Features"] = "Dodatkowe funkcje";
 $a->strings["Diaspora"] = "Diaspora";
-$a->strings["enabled"] = "włączony";
-$a->strings["disabled"] = "wyłączony";
-$a->strings["Built-in support for %s connectivity is %s"] = "Wbudowane wsparcie dla %s łączność jest %s";
-$a->strings["GNU Social (OStatus)"] = "GNU Społeczny (OStatus)";
-$a->strings["Email access is disabled on this site."] = "Dostęp do e-maila nie jest w pełni sprawny na tej stronie";
+$a->strings["enabled"] = "włączone";
+$a->strings["disabled"] = "wyłączone";
+$a->strings["Built-in support for %s connectivity is %s"] = "Wbudowane wsparcie dla połączenia z %s jest %s";
+$a->strings["GNU Social (OStatus)"] = "GNU Soocial (OStatus)";
+$a->strings["Email access is disabled on this site."] = "Dostęp do e-maila jest wyłączony na tej stronie.";
 $a->strings["General Social Media Settings"] = "Ogólne ustawienia mediów społecznościowych";
 $a->strings["Disable Content Warning"] = "Wyłącz ostrzeżenie o treści";
 $a->strings["Users on networks like Mastodon or Pleroma are able to set a content warning field which collapse their post by default. This disables the automatic collapsing and sets the content warning as the post title. Doesn't affect any other content filtering you eventually set up."] = "Użytkownicy w sieciach takich jak Mastodon lub Pleroma mogą ustawić pole ostrzeżenia o treści, które domyślnie zwijać będzie swój wpis. Powoduje wyłączenie automatycznego zwijania i ustawia ostrzeżenie o treści jako tytuł postu. Nie ma wpływu na żadne inne filtrowanie treści, które ostatecznie utworzyłeś.";
@@ -573,7 +573,7 @@ $a->strings["None"] = "Brak";
 $a->strings["Email login name:"] = "Nazwa logowania e-mail:";
 $a->strings["Email password:"] = "E-mail hasło:";
 $a->strings["Reply-to address:"] = "Adres zwrotny:";
-$a->strings["Send public posts to all email contacts:"] = "Wyślij publiczny post do wszystkich kontaktów e-mail";
+$a->strings["Send public posts to all email contacts:"] = "Wyślij publiczny wpis do wszystkich kontaktów e-mail:";
 $a->strings["Action after import:"] = "Akcja po zaimportowaniu:";
 $a->strings["Mark as seen"] = "Oznacz jako przeczytane";
 $a->strings["Move to folder"] = "Przenieś do folderu";
@@ -646,7 +646,7 @@ $a->strings["Allow us to suggest you as a potential friend to new members?"] = "
 $a->strings["If you like, Friendica may suggest new members to add you as a contact."] = "Jeśli chcesz, Friendica może zaproponować nowym członkom dodanie Cię jako kontakt.";
 $a->strings["Permit unknown people to send you private mail?"] = "Zezwolić nieznanym osobom na wysyłanie prywatnych wiadomości?";
 $a->strings["Friendica network users may send you private messages even if they are not in your contact list."] = "Użytkownicy sieci w serwisie Friendica mogą wysyłać prywatne wiadomości, nawet jeśli nie znajdują się one na liście kontaktów.";
-$a->strings["Profile is <strong>not published</strong>."] = "Profil <strong>nie jest opublikowany</strong>";
+$a->strings["Profile is <strong>not published</strong>."] = "Profil <strong>nie jest opublikowany</strong>.";
 $a->strings["Your Identity Address is <strong>'%s'</strong> or '%s'."] = "Twój adres tożsamości to <strong>'%s'</strong> lub '%s'.";
 $a->strings["Automatically expire posts after this many days:"] = "Posty wygasną automatycznie po następującej liczbie dni:";
 $a->strings["If empty, posts will not expire. Expired posts will be deleted"] = "Pole puste, wiadomość nie wygaśnie. Niezapisane wpisy zostaną usunięte.";
@@ -661,18 +661,18 @@ $a->strings["Account Settings"] = "Ustawienia konta";
 $a->strings["Password Settings"] = "Ustawienia hasła";
 $a->strings["New Password:"] = "Nowe hasło:";
 $a->strings["Confirm:"] = "Potwierdź:";
-$a->strings["Leave password fields blank unless changing"] = "Pozostaw pole hasła puste, chyba że chcesz je zmienić.";
+$a->strings["Leave password fields blank unless changing"] = "Pozostaw pole hasła puste, jeżeli nie chcesz go zmienić.";
 $a->strings["Current Password:"] = "Aktualne hasło:";
 $a->strings["Your current password to confirm the changes"] = "Wpisz aktualne hasło, aby potwierdzić zmiany";
 $a->strings["Password:"] = "Hasło:";
 $a->strings["Basic Settings"] = "Ustawienia podstawowe";
-$a->strings["Full Name:"] = "Imię i Nazwisko:";
+$a->strings["Full Name:"] = "Imię i nazwisko:";
 $a->strings["Email Address:"] = "Adres email:";
 $a->strings["Your Timezone:"] = "Twoja strefa czasowa:";
 $a->strings["Your Language:"] = "Twój język:";
-$a->strings["Set the language we use to show you friendica interface and to send you emails"] = "Wybierz język, którego używasz, aby pokazać interfejs użytkownika friendica i do wysłania Ci e-maili";
+$a->strings["Set the language we use to show you friendica interface and to send you emails"] = "Wybierz język, ktory bedzie używany do wyświetlania użytkownika friendica i wysłania Ci e-maili";
 $a->strings["Default Post Location:"] = "Domyślna lokalizacja wiadomości:";
-$a->strings["Use Browser Location:"] = "Użyj lokalizacji przeglądarki:";
+$a->strings["Use Browser Location:"] = "Używaj lokalizacji przeglądarki:";
 $a->strings["Security and Privacy Settings"] = "Ustawienia bezpieczeństwa i prywatności";
 $a->strings["Maximum Friend Requests/Day:"] = "Maksymalna dzienna liczba zaproszeń do grona przyjaciół:";
 $a->strings["(to prevent spam abuse)"] = "(aby zapobiec spamowaniu)";
@@ -685,7 +685,7 @@ $a->strings["Default Public Post"] = "Domyślny Publiczny Post";
 $a->strings["Default Permissions for New Posts"] = "Uprawnienia domyślne dla nowych postów";
 $a->strings["Maximum private messages per day from unknown people:"] = "Maksymalna liczba prywatnych wiadomości dziennie od nieznanych osób:";
 $a->strings["Notification Settings"] = "Ustawienia powiadomień";
-$a->strings["Send a notification email when:"] = "Wyślij powiadmonienia na email, kiedy:";
+$a->strings["Send a notification email when:"] = "Wysyłaj powiadmonienia na email, kiedy:";
 $a->strings["You receive an introduction"] = "Otrzymałeś zaproszenie";
 $a->strings["Your introductions are confirmed"] = "Twoje zaproszenie jest potwierdzone";
 $a->strings["Someone writes on your profile wall"] = "Ktoś pisze na twoim profilu";
@@ -695,10 +695,10 @@ $a->strings["You receive a friend suggestion"] = "Otrzymałeś propozycję od zn
 $a->strings["You are tagged in a post"] = "Jesteś oznaczony tagiem w poście";
 $a->strings["You are poked/prodded/etc. in a post"] = "Jesteś zaczepiony/zaczepiona/itp. w poście";
 $a->strings["Activate desktop notifications"] = "Aktywuj powiadomienia na pulpicie";
-$a->strings["Show desktop popup on new notifications"] = "Pokaż wyskakujące okienko dla nowych powiadomień";
+$a->strings["Show desktop popup on new notifications"] = "Pokazuj wyskakujące okienko gdy otrzymasz powiadomienie";
 $a->strings["Text-only notification emails"] = "E-maile z powiadomieniami tekstowymi";
 $a->strings["Send text only notification emails, without the html part"] = "Wysyłaj tylko e-maile z powiadomieniami tekstowymi, bez części html";
-$a->strings["Show detailled notifications"] = "Pokaż szczegółowe powiadomienia";
+$a->strings["Show detailled notifications"] = "Pokazuj szczegółowe powiadomienia";
 $a->strings["Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed."] = "Domyślne powiadomienia są skondensowane z jednym powiadomieniem dla każdego przedmiotu. Po włączeniu wyświetlane jest każde powiadomienie.";
 $a->strings["Advanced Account/Page Type Settings"] = "Zaawansowane ustawienia konta/rodzaju strony";
 $a->strings["Change the behaviour of this account for special situations"] = "Zmień zachowanie tego konta w sytuacjach specjalnych";
@@ -719,6 +719,7 @@ $a->strings["Results for: %s"] = "Wyniki dla: %s";
 $a->strings["No contacts in common."] = "Brak wspólnych kontaktów.";
 $a->strings["Common Friends"] = "Wspólni znajomi";
 $a->strings["Login"] = "Zaloguj się";
+$a->strings["Bad Request"] = "Nieprawidłowe żądanie";
 $a->strings["The post was created"] = "Post został utworzony";
 $a->strings["add"] = "dodaj";
 $a->strings["Warning: This group contains %s member from a network that doesn't allow non public messages."] = [
@@ -731,7 +732,7 @@ $a->strings["Messages in this group won't be send to these receivers."] = "Wiado
 $a->strings["No such group"] = "Nie ma takiej grupy";
 $a->strings["Group is empty"] = "Grupa jest pusta";
 $a->strings["Group: %s"] = "Grupa: %s";
-$a->strings["Private messages to this person are at risk of public disclosure."] = "Prywatne wiadomości do tej osoby mogą zostać publicznie ujawnione ";
+$a->strings["Private messages to this person are at risk of public disclosure."] = "Prywatne wiadomości do tej osoby mogą być widoczne publicznie.";
 $a->strings["Invalid contact."] = "Nieprawidłowy kontakt.";
 $a->strings["Commented Order"] = "Porządek według komentarzy";
 $a->strings["Sort by Comment Date"] = "Sortuj według daty komentarza";
@@ -746,9 +747,9 @@ $a->strings["Interesting Links"] = "Interesujące linki";
 $a->strings["Starred"] = "Ulubione";
 $a->strings["Favourite Posts"] = "Ulubione posty";
 $a->strings["Group created."] = "Grupa utworzona.";
-$a->strings["Could not create group."] = "Nie mogę stworzyć grupy";
-$a->strings["Group not found."] = "Nie znaleziono grupy";
-$a->strings["Group name changed."] = "Nazwa grupy zmieniona";
+$a->strings["Could not create group."] = "Nie można utworzyć grupy.";
+$a->strings["Group not found."] = "Nie znaleziono grupy.";
+$a->strings["Group name changed."] = "Zmieniono nazwę grupy.";
 $a->strings["Save Group"] = "Zapisz grupę";
 $a->strings["Filter"] = "Filtr";
 $a->strings["Create a group of contacts/friends."] = "Stwórz grupę znajomych.";
@@ -785,39 +786,38 @@ $a->strings["Resubscribing to OStatus contacts"] = "Ponowne subskrybowanie konta
 $a->strings["Error"] = "Błąd";
 $a->strings["Done"] = "Gotowe";
 $a->strings["Keep this window open until done."] = "Pozostaw to okno otwarte, dopóki nie będzie gotowe.";
-$a->strings["Access denied."] = "Brak dostępu";
-$a->strings["No contacts."] = "Brak kontaktów";
+$a->strings["Access denied."] = "Brak dostępu.";
+$a->strings["No contacts."] = "Brak kontaktów.";
 $a->strings["Visit %s's profile [%s]"] = "Obejrzyj %s's profil [%s]";
-$a->strings["Contact wasn't found or can't be unfollowed."] = "Kontakt nie został znaleziony lub nie można go pominąć.";
-$a->strings["Contact unfollowed"] = "Skontaktuj się z obserwowanym";
-$a->strings["Submit Request"] = "Wyślij zgłoszenie";
-$a->strings["You aren't a friend of this contact."] = "Nie jesteś przyjacielem tego kontaktu.";
+$a->strings["You aren't following this contact."] = "Nie obserwujesz tego kontaktu.";
 $a->strings["Unfollowing is currently not supported by your network."] = "Brak obserwowania nie jest obecnie obsługiwany przez twoją sieć.";
+$a->strings["Contact unfollowed"] = "Skontaktuj się z obserwowanym";
 $a->strings["Disconnect/Unfollow"] = "Rozłącz/Nie obserwuj";
 $a->strings["Your Identity Address:"] = "Twój adres tożsamości:";
+$a->strings["Submit Request"] = "Wyślij zgłoszenie";
 $a->strings["Profile URL"] = "Adres URL profilu";
 $a->strings["Status Messages and Posts"] = "Status wiadomości i postów";
 $a->strings["[Embedded content - reload page to view]"] = "[Dodatkowa zawartość - odśwież stronę by zobaczyć]";
 $a->strings["Registration successful. Please check your email for further instructions."] = "Rejestracja zakończona pomyślnie. Dalsze instrukcje zostały wysłane na twojego e-maila.";
 $a->strings["Failed to send email message. Here your accout details:<br> login: %s<br> password: %s<br><br>You can change your password after login."] = "Nie udało się wysłać wiadomości e-mail. Tutaj szczegóły twojego konta:<br> login: %s<br>hasło: %s<br><br>Możesz zmienić swoje hasło po zalogowaniu.";
 $a->strings["Registration successful."] = "Rejestracja udana.";
-$a->strings["Your registration can not be processed."] = "Twoja rejestracja nie może zostać przeprowadzona. ";
+$a->strings["Your registration can not be processed."] = "Nie można przetworzyć Twojej rejestracji.";
 $a->strings["Your registration is pending approval by the site owner."] = "Twoja rejestracja oczekuje na zaakceptowanie przez właściciela witryny.";
 $a->strings["This site has exceeded the number of allowed daily account registrations. Please try again tomorrow."] = "Strona przekroczyła ilość dozwolonych rejestracji na dzień. Proszę spróbuj ponownie jutro.";
 $a->strings["You may (optionally) fill in this form via OpenID by supplying your OpenID and clicking 'Register'."] = "Możesz (opcjonalnie) wypełnić ten formularz za pośrednictwem OpenID, podając swój OpenID i klikając 'Register'.";
 $a->strings["If you are not familiar with OpenID, please leave that field blank and fill in the rest of the items."] = "Jeśli nie jesteś zaznajomiony z OpenID, zostaw to pole puste i uzupełnij resztę elementów.";
-$a->strings["Your OpenID (optional): "] = "Twój OpenID (opcjonalnie):";
+$a->strings["Your OpenID (optional): "] = "Twój OpenID (opcjonalnie): ";
 $a->strings["Include your profile in member directory?"] = "Czy dołączyć twój profil do katalogu członków?";
 $a->strings["Note for the admin"] = "Uwaga dla administratora";
 $a->strings["Leave a message for the admin, why you want to join this node"] = "Pozostaw wiadomość dla administratora, dlaczego chcesz dołączyć do tego węzła";
 $a->strings["Membership on this site is by invitation only."] = "Członkostwo na tej stronie możliwe tylko dzięki zaproszeniu.";
-$a->strings["Your invitation code: "] = "Twój kod zaproszenia:";
+$a->strings["Your invitation code: "] = "Twój kod zaproszenia: ";
 $a->strings["Registration"] = "Rejestracja";
-$a->strings["Your Full Name (e.g. Joe Smith, real or real-looking): "] = "Twoje Imię i Nazwisko (np. Jan Kowalski, prawdziwe lub wyglądające na prawdziwe):";
+$a->strings["Your Full Name (e.g. Joe Smith, real or real-looking): "] = "Twoje imię i nazwisko (np. Jan Kowalski, prawdziwe lub wyglądające na prawdziwe): ";
 $a->strings["Your Email Address: (Initial information will be send there, so this has to be an existing address.)"] = "Twój adres e-mail: (Informacje początkowe zostaną wysłane tam, więc musi to być istniejący adres).";
 $a->strings["Leave empty for an auto generated password."] = "Pozostaw puste dla wygenerowanego automatycznie hasła.";
 $a->strings["Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be '<strong>nickname@%s</strong>'."] = "Wybierz pseudonim profilu. Nazwa musi zaczynać się od znaku tekstowego. Twój adres profilu na tej stronie będzie wówczas '<strong>pseudonimem%s</strong>'.";
-$a->strings["Choose a nickname: "] = "Wybierz pseudonim:";
+$a->strings["Choose a nickname: "] = "Wybierz pseudonim: ";
 $a->strings["Register"] = "Zarejestruj";
 $a->strings["Import"] = "Import";
 $a->strings["Import your profile to this friendica instance"] = "Zaimportuj swój profil do tej instancji friendica";
@@ -831,13 +831,15 @@ $a->strings["Network Notifications"] = "Powiadomienia sieciowe";
 $a->strings["System Notifications"] = "Powiadomienia systemowe";
 $a->strings["Personal Notifications"] = "Prywatne powiadomienia";
 $a->strings["Home Notifications"] = "Powiadomienia domowe";
+$a->strings["Show unread"] = "Pokaż nieprzeczytane";
+$a->strings["Show all"] = "Pokaż wszystko";
 $a->strings["Show Ignored Requests"] = "Pokaż ignorowane żądania";
 $a->strings["Hide Ignored Requests"] = "Ukryj zignorowane prośby";
 $a->strings["Notification type:"] = "Typ powiadomienia:";
 $a->strings["Suggested by:"] = "Sugerowany przez:";
 $a->strings["Hide this contact from others"] = "Ukryj ten kontakt przed innymi";
 $a->strings["Approve"] = "Zatwierdź";
-$a->strings["Claims to be known to you: "] = "Twierdzi, że go znasz:";
+$a->strings["Claims to be known to you: "] = "Twierdzi, że go/ją znasz: ";
 $a->strings["yes"] = "tak";
 $a->strings["no"] = "nie";
 $a->strings["Shall your connection be bidirectional or not?"] = "Czy twoje połączenie ma być dwukierunkowe, czy nie?";
@@ -850,9 +852,7 @@ $a->strings["Subscriber"] = "Subskrybent";
 $a->strings["Tags:"] = "Tagi:";
 $a->strings["Network:"] = "Sieć:";
 $a->strings["No introductions."] = "Brak dostępu.";
-$a->strings["Show unread"] = "Pokaż nieprzeczytane";
-$a->strings["Show all"] = "Pokaż wszystko";
-$a->strings["No more %s notifications."] = "Nigdy więcej %s powiadomień.";
+$a->strings["No more %s notifications."] = "Brak kolejnych %s powiadomień.";
 $a->strings["New Message"] = "Nowa wiadomość";
 $a->strings["Unable to locate contact information."] = "Nie można znaleźć informacji kontaktowych.";
 $a->strings["Do you really want to delete this message?"] = "Czy na pewno chcesz usunąć tę wiadomość?";
@@ -869,10 +869,10 @@ $a->strings["Unknown sender - %s"] = "Nieznany nadawca - %s";
 $a->strings["You and %s"] = "Ty i %s";
 $a->strings["%s and You"] = "%s i ty";
 $a->strings["%d message"] = [
-       0 => " %d wiadomość",
-       1 => " %d wiadomości",
-       2 => " %d wiadomości",
-       3 => " %d wiadomości",
+       0 => "%d wiadomość",
+       1 => "%d wiadomości",
+       2 => "%d wiadomości",
+       3 => "%d wiadomości",
 ];
 $a->strings["No profile"] = "Brak profilu";
 $a->strings["Subscribing to OStatus contacts"] = "Subskrybowanie kontaktów OStatus";
@@ -881,17 +881,17 @@ $a->strings["Couldn't fetch information for contact."] = "Nie można pobrać inf
 $a->strings["Couldn't fetch friends for contact."] = "Nie można pobrać znajomych do kontaktu.";
 $a->strings["success"] = "powodzenie";
 $a->strings["failed"] = "nie powiodło się";
-$a->strings["ignored"] = "Ignoruj";
+$a->strings["ignored"] = "ignorowany(-a)";
 $a->strings["%1\$s welcomes %2\$s"] = "%1\$s witamy %2\$s";
 $a->strings["User deleted their account"] = "Użytkownik usunął swoje konto";
 $a->strings["On your Friendica node an user deleted their account. Please ensure that their data is removed from the backups."] = "W twoim węźle Friendica użytkownik usunął swoje konto. Upewnij się, że ich dane zostały usunięte z kopii zapasowych.";
 $a->strings["The user id is %d"] = "Identyfikatorem użytkownika jest %d";
 $a->strings["Remove My Account"] = "Usuń moje konto";
 $a->strings["This will completely remove your account. Once this has been done it is not recoverable."] = "Spowoduje to całkowite usunięcie Twojego konta. Po wykonaniu tej czynności nie można jej cofnąć.";
-$a->strings["Please enter your password for verification:"] = "Wprowadź hasło w celu weryfikacji.";
+$a->strings["Please enter your password for verification:"] = "Wprowadź hasło w celu weryfikacji:";
 $a->strings["Tag removed"] = "Tag usunięty";
 $a->strings["Remove Item Tag"] = "Usuń pozycję Tag";
-$a->strings["Select a tag to remove: "] = "Wybierz tag do usunięcia";
+$a->strings["Select a tag to remove: "] = "Wybierz tag do usunięcia";
 $a->strings["Welcome to %s"] = "Witamy w %s";
 $a->strings["Do you really want to delete this suggestion?"] = "Czy na pewno chcesz usunąć te sugestie ?";
 $a->strings["No suggestions available. If this is a new site, please try again in 24 hours."] = "Brak dostępnych sugestii. Jeśli jest to nowa witryna, spróbuj ponownie za 24 godziny.";
@@ -901,7 +901,7 @@ $a->strings["This is Friendica, version %s that is running at the web location %
 $a->strings["Please visit <a href=\"https://friendi.ca\">Friendi.ca</a> to learn more about the Friendica project."] = "Odwiedź stronę <a href=\"https://friendi.ca\">Friendi.ca</a> aby dowiedzieć się więcej o projekcie Friendica.";
 $a->strings["Bug reports and issues: please visit"] = "Raporty o błędach i problemy: odwiedź stronę";
 $a->strings["the bugtracker at github"] = "śledzenie błędów na github";
-$a->strings["Suggestions, praise, etc. - please email \"info\" at \"friendi - dot - ca"] = "Sugestie, pochwały itp. - napisz e-mail \"info\" na \"friendi.ca\"";
+$a->strings["Suggestions, praise, etc. - please email \"info\" at \"friendi - dot - ca"] = "Propozycje, pochwały itd. – napisz e-mail do „info” małpa „friendi” - kropka - „ca”";
 $a->strings["Installed addons/apps:"] = "Zainstalowane dodatki/aplikacje:";
 $a->strings["No installed addons/apps"] = "Brak zainstalowanych dodatków/aplikacji";
 $a->strings["Read about the <a href=\"%1\$s/tos\">Terms of Service</a> of this node."] = "Przeczytaj o <a href=\"%1\$s/tos\">Warunkach świadczenia usług</a> tego węzła.";
@@ -913,7 +913,7 @@ $a->strings["Invalid request."] = "Nieprawidłowe żądanie.";
 $a->strings["Image exceeds size limit of %s"] = "Obraz przekracza limit rozmiaru wynoszący %s";
 $a->strings["Unable to process image."] = "Przetwarzanie obrazu nie powiodło się.";
 $a->strings["Wall Photos"] = "Tablica zdjęć";
-$a->strings["Image upload failed."] = "Przesyłanie obrazu nie powiodło się";
+$a->strings["Image upload failed."] = "Przesyłanie obrazu nie powiodło się.";
 $a->strings["Welcome to Friendica"] = "Witamy na Friendica";
 $a->strings["New Member Checklist"] = "Lista nowych członków";
 $a->strings["We would like to offer some tips and links to help make your experience enjoyable. Click any item to visit the relevant page. A link to this page will be visible from your home page for two weeks after your initial registration and then will quietly disappear."] = "Chcielibyśmy zaproponować kilka porad i linków, które pomogą uczynić twoje doświadczenie przyjemnym. Kliknij dowolny element, aby odwiedzić odpowiednią stronę. Link do tej strony będzie widoczny na stronie głównej przez dwa tygodnie od czasu rejestracji, a następnie zniknie.";
@@ -929,8 +929,8 @@ $a->strings["Edit Your Profile"] = "Edytuj własny profil";
 $a->strings["Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors."] = "Edytuj swój domyślny profil do swoich potrzeb. Przejrzyj ustawienia ukrywania listy znajomych i ukrywania profilu przed nieznanymi użytkownikami.";
 $a->strings["Profile Keywords"] = "Słowa kluczowe profilu";
 $a->strings["Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships."] = "Ustaw kilka publicznych słów kluczowych dla swojego domyślnego profilu, które opisują Twoje zainteresowania. Możemy znaleźć inne osoby o podobnych zainteresowaniach i zaproponować przyjaźnie.";
-$a->strings["Connecting"] = "Łączę się...";
-$a->strings["Importing Emails"] = "Importuję emaile...";
+$a->strings["Connecting"] = "Łączenie";
+$a->strings["Importing Emails"] = "Importowanie e-maili";
 $a->strings["Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX"] = "Wprowadź informacje dotyczące dostępu do poczty e-mail na stronie Ustawienia oprogramowania, jeśli chcesz importować i wchodzić w interakcje z przyjaciółmi lub listami adresowymi z poziomu konta e-mail INBOX";
 $a->strings["Go to Your Contacts Page"] = "Idź do strony z Twoimi kontaktami";
 $a->strings["Your Contacts page is your gateway to managing friendships and connecting with friends on other networks. Typically you enter their address or site URL in the <em>Add New Contact</em> dialog."] = "Strona Kontakty jest twoją bramą do zarządzania przyjaciółmi i łączenia się z przyjaciółmi w innych sieciach. Zazwyczaj podaje się adres lub adres URL strony w oknie dialogowym <em>Dodaj nowy kontakt</em>.";
@@ -955,13 +955,13 @@ $a->strings["Request could not be verified. (You may have previously submitted i
 $a->strings["Request has expired, please make a new one."] = "Żądanie wygasło. Zrób nowe.";
 $a->strings["Forgot your Password?"] = "Zapomniałeś hasła?";
 $a->strings["Enter your email address and submit to have your password reset. Then check your email for further instructions."] = "Wpisz swój adres email i wyślij, aby zresetować hasło. Później sprawdź swojego emaila w celu uzyskania dalszych instrukcji.";
-$a->strings["Nickname or Email: "] = "Pseudonim lub Email:";
+$a->strings["Nickname or Email: "] = "Pseudonim lub e-mail: ";
 $a->strings["Reset"] = "Zresetuj";
 $a->strings["Password Reset"] = "Zresetuj hasło";
 $a->strings["Your password has been reset as requested."] = "Twoje hasło zostało zresetowane zgodnie z żądaniem.";
 $a->strings["Your new password is"] = "Twoje nowe hasło to";
 $a->strings["Save or copy your new password - and then"] = "Zapisz lub skopiuj nowe hasło - a następnie";
-$a->strings["click here to login"] = "Kliknij tutaj aby się zalogować";
+$a->strings["click here to login"] = "naciśnij tutaj, aby zalogować się";
 $a->strings["Your password may be changed from the <em>Settings</em> page after successful login."] = "Twoje hasło może być zmienione w <em>Ustawieniach</em> po udanym zalogowaniu.";
 $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tYour password has been changed as requested. Please retain this\n\t\t\tinformation for your records (or change your password immediately to\n\t\t\tsomething that you will remember).\n\t\t"] = "\n\t\t\tSzanowny Użytkowniku %1\$s, \n\t\t\t\tTwoje hasło zostało zmienione zgodnie z życzeniem. Proszę, zachowaj te \n\t\t\tinformacje dotyczące twoich rekordów (lub natychmiast zmień hasło na \n\t\t\tcoś, co zapamiętasz).\n\t\t";
 $a->strings["\n\t\t\tYour login details are as follows:\n\n\t\t\tSite Location:\t%1\$s\n\t\t\tLogin Name:\t%2\$s\n\t\t\tPassword:\t%3\$s\n\n\t\t\tYou may change that password from your account settings page after logging in.\n\t\t"] = "\n\t\t\tDane logowania są następujące:\n\n\t\t\tLokalizacja witryny:\t%1\$s\n\t\t\tNazwa użytkownika:\t%2\$s\n\t\t\tHasło:\t%3\$s\n\n\t\t\tMożesz zmienić hasło na stronie ustawień konta po zalogowaniu.\n\t\t";
@@ -975,11 +975,14 @@ $a->strings["BBCode::toMarkdown"] = "BBCode::toMarkdown";
 $a->strings["BBCode::toMarkdown => Markdown::convert"] = "BBCode::toMarkdown => Markdown::przekształć";
 $a->strings["BBCode::toMarkdown => Markdown::toBBCode"] = "BBCode::toMarkdown => Markdown::toBBCode";
 $a->strings["BBCode::toMarkdown =>  Markdown::convert => HTML::toBBCode"] = "BBCode::toMarkdown => Markdown::przekształć => HTML::toBBCode";
-$a->strings["Source input \\x28Diaspora format\\x29"] = "Źródło wejściowe \\x28Diaspora format\\x29";
+$a->strings["Source input (Diaspora format)"] = "Źródło wejściowe (format Diaspora)";
+$a->strings["Markdown::convert (raw HTML)"] = "Markdown::convert (raw HTML)";
+$a->strings["Markdown::convert"] = "Markdown::convert";
 $a->strings["Markdown::toBBCode"] = "Markdown::toBBCode";
 $a->strings["Raw HTML input"] = "Surowe wejście HTML";
 $a->strings["HTML Input"] = "Wejście HTML";
 $a->strings["HTML::toBBCode"] = "HTML::toBBCode";
+$a->strings["HTML::toMarkdown"] = "HTML::toMarkdown";
 $a->strings["HTML::toPlaintext"] = "HTML::toPlaintext";
 $a->strings["Source text"] = "Tekst źródłowy";
 $a->strings["BBCode"] = "BBCode";
@@ -1009,7 +1012,7 @@ $a->strings["probe address"] = "adres sondy";
 $a->strings["check webfinger"] = "sprawdź webfinger";
 $a->strings["Admin"] = "Administator";
 $a->strings["Addon Features"] = "Funkcje dodatkowe";
-$a->strings["User registrations waiting for confirmation"] = "Rejestracje użytkownika czekają na potwierdzenie.";
+$a->strings["User registrations waiting for confirmation"] = "Rejestracje użytkowników czekające na potwierdzenie";
 $a->strings["Administration"] = "Administracja";
 $a->strings["Display Terms of Service"] = "Wyświetl Warunki korzystania z usługi";
 $a->strings["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."] = "Włącz stronę Warunki świadczenia usług. Jeśli ta opcja jest włączona, link do warunków zostanie dodany do formularza rejestracyjnego i strony z informacjami ogólnymi.";
@@ -1046,7 +1049,7 @@ $a->strings["%s contact unblocked"] = [
 $a->strings["Remote Contact Blocklist"] = "Lista zablokowanych kontaktów zdalnych";
 $a->strings["This page allows you to prevent any message from a remote contact to reach your node."] = "Ta strona pozwala zapobiec wysyłaniu do węzła wiadomości od kontaktu zdalnego.";
 $a->strings["Block Remote Contact"] = "Zablokuj kontakt zdalny";
-$a->strings["select all"] = "Zaznacz wszystko";
+$a->strings["select all"] = "zaznacz wszystko";
 $a->strings["select none"] = "wybierz brak";
 $a->strings["Block"] = "Zablokuj";
 $a->strings["Unblock"] = "Odblokuj";
@@ -1056,9 +1059,9 @@ $a->strings["Block New Remote Contact"] = "Zablokuj nowy kontakt zdalny";
 $a->strings["Photo"] = "Zdjęcie";
 $a->strings["Address"] = "Adres";
 $a->strings["%s total blocked contact"] = [
-       0 => "%s całkowicie zablokowany kontakt ",
-       1 => "%s całkowicie zablokowany kontakt",
-       2 => "%s całkowicie zablokowane kontakty ",
+       0 => "łącznie %s zablokowany kontakt",
+       1 => "łącznie %s zablokowane kontakty",
+       2 => "łącznie %s zablokowanych kontaktów",
        3 => "%s całkowicie zablokowane kontakty",
 ];
 $a->strings["URL of the remote contact to block."] = "Adres URL kontaktu zdalnego do zablokowania.";
@@ -1082,13 +1085,13 @@ $a->strings["Inspect Worker Queue"] = "Sprawdź Kolejkę Pracowników";
 $a->strings["Job Parameters"] = "Parametry zadania";
 $a->strings["Priority"] = "Priorytet";
 $a->strings["This page lists the currently queued worker jobs. These jobs are handled by the worker cronjob you've set up during install."] = "Ta strona zawiera listę aktualnie ustawionych zadań dla pracowników. Te zadania są obsługiwane przez cronjob pracownika, który skonfigurowałeś podczas instalacji.";
-$a->strings["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 />"] = "Twoja baza danych nadal działa z tabelami MyISAM. Powinieneś zmienić typ silnika na InnoDB. Ponieważ Friendica będzie używać funkcji związanych z InnoDB tylko w przyszłości, powinieneś to zmienić! Zobacz <a href=\"%s\">tutaj</a> przewodnik, który może być pomocny w konwersji silników stołowych. Możesz także użyć polecenia <tt>php bin/console.php dbstructure toinnodb</tt> instalacji Friendica do automatycznej konwersji.<br />";
+$a->strings["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 />"] = "Twoja baza danych nadal używa tabel MyISAM. Powinieneś(-naś) zmienić typ silnika na InnoDB. Ponieważ Friendica będzie używać w przyszłości wyłącznie funkcji InnoDB, powinieneś(-naś) to zmienić! Zobacz <a href=\"%s\">tutaj</a> przewodnik, który może być pomocny w konwersji silników tabel. Możesz także użyć polecenia <tt>php bin/console.php dbstructure toinnodb</tt> instalacji Friendica, aby dokonać automatycznej konwersji.<br />";
 $a->strings["There is a new version of Friendica available for download. Your current version is %1\$s, upstream version is %2\$s"] = "Dostępna jest nowa wersja aplikacji Friendica. Twoja aktualna wersja to %1\$s wyższa wersja to %2\$s";
 $a->strings["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."] = "Aktualizacja bazy danych nie powiodła się. Uruchom polecenie \"php bin/console.php dbstructure update\" z wiersza poleceń i sprawdź błędy, które mogą się pojawić.";
 $a->strings["The worker was never executed. Please check your database structure!"] = "Pracownik nigdy nie został stracony. Sprawdź swoją strukturę bazy danych!";
 $a->strings["The last worker execution was on %s UTC. This is older than one hour. Please check your crontab settings."] = "Ostatnie wykonanie robota było w %s UTC. To jest starsze niż jedna godzina. Sprawdź ustawienia crontab.";
 $a->strings["Friendica's configuration now is stored in config/local.ini.php, please copy config/local-sample.ini.php and move your config from <code>.htconfig.php</code>. See <a href=\"%s\">the Config help page</a> for help with the transition."] = "Konfiguracja Friendica jest teraz przechowywana w config/local.ini.php, skopiuj config/local-sample.ini.php i przenieś konfigurację z <code>.htconfig.php</code>. Zobacz <a href=\"%s\">stronę pomocy konfiguracji</a>, aby uzyskać pomoc dotyczącą przejścia.";
-$a->strings["<a href=\"%s\">%s</a> is not reachable on your system. This is a servere configuration issue that prevents the communication.. See <a href=\"%s\">the installation page</a> for help."] = "<a href=\"%s\">%s</a>nie jest osiągalny w twoim systemie. Jest to problem konfiguracji sieci, który uniemożliwia komunikację. Zobacz pomoc na <a href=\"%s\">stronie instalacji</a>.";
+$a->strings["<a href=\"%s\">%s</a> is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See <a href=\"%s\">the installation page</a> for help."] = "<a href=\"%s\">%s</a> nie jest osiągalny w twoim systemie. Jest to poważny problem z konfiguracją, który uniemożliwia komunikację między serwerami. Zobacz pomoc na <a href=\"%s\">stronie instalacji</a>.";
 $a->strings["Normal Account"] = "Konto normalne";
 $a->strings["Automatic Follower Account"] = "Automatyczne konto obserwatora";
 $a->strings["Public Forum Account"] = "Publiczne konto na forum";
@@ -1098,11 +1101,11 @@ $a->strings["Private Forum Account"] = "Prywatne konto na forum";
 $a->strings["Message queues"] = "Wiadomości";
 $a->strings["Summary"] = "Podsumowanie";
 $a->strings["Registered users"] = "Zarejestrowani użytkownicy";
-$a->strings["Pending registrations"] = "Rejestracje w toku.";
+$a->strings["Pending registrations"] = "Oczekujące rejestracje";
 $a->strings["Version"] = "Wersja";
 $a->strings["Active addons"] = "Aktywne dodatki";
 $a->strings["Can not parse base url. Must have at least <scheme>://<domain>"] = "Nie można zanalizować podstawowego adresu URL. Musi mieć co najmniej <scheme>: //<domain>";
-$a->strings["Site settings updated."] = "Ustawienia strony zaktualizowane";
+$a->strings["Site settings updated."] = "Zaktualizowano ustawienia strony.";
 $a->strings["No community page for local users"] = "Brak strony społeczności dla użytkowników lokalnych";
 $a->strings["No community page"] = "Brak strony społeczności";
 $a->strings["Public postings from users of this site"] = "Publikacje publiczne od użytkowników tej strony";
@@ -1117,11 +1120,11 @@ $a->strings["Half a year"] = "Pół roku";
 $a->strings["One year"] = "Rok";
 $a->strings["Multi user instance"] = "Tryb wielu użytkowników";
 $a->strings["Closed"] = "Zamknięte";
-$a->strings["Requires approval"] = "Wymagane zatwierdzenie.";
+$a->strings["Requires approval"] = "Wymaga zatwierdzenia";
 $a->strings["Open"] = "Otwarta";
-$a->strings["No SSL policy, links will track page SSL state"] = "Brak SSL , linki będą śledzić stan SSL .";
-$a->strings["Force all links to use SSL"] = "Wymuś by linki używały SSL.";
-$a->strings["Self-signed certificate, use SSL for local links only (discouraged)"] = "Wewnętrzne Certyfikaty , użyj SSL tylko dla linków lokalnych . ";
+$a->strings["No SSL policy, links will track page SSL state"] = "Brak SSL, linki będą śledzić stan SSL";
+$a->strings["Force all links to use SSL"] = "Wymuś używanie SSL na wszystkich odnośnikach";
+$a->strings["Self-signed certificate, use SSL for local links only (discouraged)"] = "Wewnętrzne Certyfikaty, użyj SSL tylko dla linków lokalnych . ";
 $a->strings["Don't check"] = "Nie sprawdzaj";
 $a->strings["check the stable version"] = "sprawdź wersję stabilną";
 $a->strings["check the development version"] = "sprawdź wersję rozwojową";
@@ -1150,11 +1153,11 @@ $a->strings["System theme"] = "Motyw systemowy";
 $a->strings["Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"] = "Domyślny motyw systemu - może być nadpisany przez profil użytkownika  <a href='#' id='cnftheme'>zmień ustawienia motywów</a>";
 $a->strings["Mobile system theme"] = "Motyw systemu mobilnego";
 $a->strings["Theme for mobile devices"] = "Motyw na urządzenia mobilne";
-$a->strings["SSL link policy"] = "polityka SSL";
-$a->strings["Determines whether generated links should be forced to use SSL"] = "Określa kiedy generowane linki powinny używać wymuszonego SSl.";
+$a->strings["SSL link policy"] = "Polityka odnośników SSL";
+$a->strings["Determines whether generated links should be forced to use SSL"] = "Określa, czy generowane odnośniki będą obowiązkowo używały SSL";
 $a->strings["Force SSL"] = "Wymuś SSL";
 $a->strings["Force all Non-SSL requests to SSL - Attention: on some systems it could lead to endless loops."] = "Wymuszaj wszystkie żądania SSL bez SSL - Uwaga: w niektórych systemach może to prowadzić do niekończących się pętli.";
-$a->strings["Hide help entry from navigation menu"] = "Wyłącz pomoc w menu nawigacyjnym ";
+$a->strings["Hide help entry from navigation menu"] = "Ukryj pomoc w menu nawigacyjnym";
 $a->strings["Hides the menu entry for the Help pages from the navigation menu. You can still access it calling /help directly."] = "Chowa pozycje menu dla stron pomocy ze strony nawigacyjnej. Możesz nadal ją wywołać poprzez komendę /help.";
 $a->strings["Single user instance"] = "Tryb pojedynczego użytkownika";
 $a->strings["Make this instance multi-user or single-user for the named user"] = "Ustawia tryb dla wielu użytkowników lub pojedynczego użytkownika dla nazwanego użytkownika";
@@ -1171,7 +1174,7 @@ $a->strings["Register text"] = "Zarejestruj tekst";
 $a->strings["Will be displayed prominently on the registration page. You can use BBCode here."] = "Będą wyświetlane w widocznym miejscu na stronie rejestracji. Możesz użyć BBCode tutaj.";
 $a->strings["Forbidden Nicknames"] = "Zakazane pseudonimy";
 $a->strings["Comma separated list of nicknames that are forbidden from registration. Preset is a list of role names according RFC 2142."] = "Lista oddzielonych przecinkami pseudonimów, których nie wolno rejestrować. Preset to lista nazw ról zgodnie z RFC 2142.";
-$a->strings["Accounts abandoned after x days"] = "Konto porzucone od x dni.";
+$a->strings["Accounts abandoned after x days"] = "Konta porzucone po x dni";
 $a->strings["Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit."] = "Nie będzie marnować zasobów systemu wypytując zewnętrzne strony o opuszczone konta. Ustaw 0 dla braku limitu czasu .";
 $a->strings["Allowed friend domains"] = "Dozwolone domeny przyjaciół";
 $a->strings["Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains"] = "Rozdzielana przecinkami lista domen, które mogą nawiązywać przyjaźnie z tą witryną. Symbole wieloznaczne są akceptowane. Pozostaw puste by zezwolić każdej domenie na zaprzyjaźnienie.";
@@ -1212,8 +1215,8 @@ $a->strings["Posts per user on community page"] = "Lista postów użytkownika na
 $a->strings["The maximum number of posts per user on the community page. (Not valid for 'Global Community')"] = "Maksymalna liczba postów na użytkownika na stronie społeczności. (Nie dotyczy 'społeczności globalnej')";
 $a->strings["Enable OStatus support"] = "Włącz wsparcie OStatus";
 $a->strings["Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed."] = "Zapewnij kompatybilność z OStatus (StatusNet, GNU Social itp.). Cała komunikacja w stanie OStatus jest jawna, dlatego ostrzeżenia o prywatności będą czasami wyświetlane.";
-$a->strings["Only import OStatus threads from our contacts"] = "Importuj wątki OStatus tylko z naszych kontaktów";
-$a->strings["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."] = "Normalnie importujemy każdą treść z naszych kontaktów OStatus. W tej opcji przechowujemy tylko wątki uruchomione przez kontakt znany w naszym systemie.";
+$a->strings["Only import OStatus/ActivityPub threads from our contacts"] = "Importuj wątki OStatus/ActivityPub tylko z naszych kontaktów";
+$a->strings["Normally we import every content from our OStatus and ActivityPub contacts. With this option we only store threads that are started by a contact that is known on our system."] = "Normalnie importujemy każdą zawartość z naszych kontaktów OStatus i ActivityPub. W tej opcji przechowujemy tylko wątki uruchomione przez kontakt znany w naszym systemie.";
 $a->strings["OStatus support can only be enabled if threading is enabled."] = "Obsługa OStatus może być włączona tylko wtedy, gdy włączone jest wątkowanie.";
 $a->strings["Diaspora support can't be enabled because Friendica was installed into a sub directory."] = "Obsługa Diaspory nie może być włączona, ponieważ Friendica została zainstalowana w podkatalogu.";
 $a->strings["Enable Diaspora support"] = "Włączyć obsługę Diaspory";
@@ -1317,16 +1320,16 @@ $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tthe administrator of %2\$s has set up
 $a->strings["\n\t\t\tThe login details are as follows:\n\n\t\t\tSite Location:\t%1\$s\n\t\t\tLogin Name:\t\t%2\$s\n\t\t\tPassword:\t\t%3\$s\n\n\t\t\tYou may change your password from your account \"Settings\" page after logging\n\t\t\tin.\n\n\t\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\t\tYou may also wish to add some basic information to your default profile\n\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\t\tWe recommend setting your full name, adding a profile photo,\n\t\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\t\tthan that.\n\n\t\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\t\tIf you are new and do not know anybody here, they may help\n\t\t\tyou to make some new and interesting friends.\n\n\t\t\tIf you ever want to delete your account, you can do so at %1\$s/removeme\n\n\t\t\tThank you and welcome to %4\$s."] = "\n\t\t\tDane logowania są następuje:\n\t\t\tLokalizacja witryny:\t%1\$s\n\t\t\tNazwa użytkownika:%2\$s\n\t\t\tHasło:%3\$s\n\n\t\t\tPo zalogowaniu możesz zmienić hasło do swojego konta na stronie \"Ustawienia\".\n \t\t\tProszę poświęć chwilę, aby przejrzeć inne ustawienia konta na tej stronie.\n\n\t\t\tMożesz również dodać podstawowe informacje do swojego domyślnego profilu\n\t\t\t(na stronie \"Profil użytkownika\"), aby inne osoby mogły łatwo Cię znaleźć.\n\n\t\t\tZalecamy ustawienie imienia i nazwiska, dodanie zdjęcia profilowego,\n\t\t\tdodanie niektórych \"słów kluczowych\" profilu (bardzo przydatne w nawiązywaniu nowych znajomości) \n\t\t\ti być może gdzie mieszkasz; jeśli nie chcesz podać więcej szczegów.\n\n\t\t\tW pełni szanujemy Twoje prawo do prywatności i żaden z tych elementów nie jest konieczny.\n\t\t\tJeśli jesteś nowy i nie znasz tutaj nikogo, oni mogą ci pomóc,\n\t\t\tmożesz zdobyć nowych interesujących przyjaciół.\n\n\t\t\tJeśli kiedykolwiek zechcesz usunąć swoje konto, możesz to zrobić na stronie %1\$s/removeme\n\n\t\t\tDziękujemy i Zapraszamy do%4\$s";
 $a->strings["Registration details for %s"] = "Szczegóły rejestracji dla %s";
 $a->strings["%s user blocked/unblocked"] = [
-       0 => "%s użytkownik zablokowany/odblokowany",
-       1 => "%s użytkowników zablokowanych/odblokowanych",
-       2 => "%sużytkowników zablokowanych/odblokowanych ",
-       3 => "%sużytkowników zablokowanych/odblokowanych ",
+       0 => "zablokowano/odblokowano %s użytkownika",
+       1 => "zablokowano/odblokowano %s użytkowników",
+       2 => "zablokowano/odblokowano %s użytkowników",
+       3 => "%sużytkowników zablokowanych/odblokowanych",
 ];
 $a->strings["%s user deleted"] = [
-       0 => " %s użytkownik usunięty",
-       1 => " %s użytkownicy usunięci",
-       2 => " %s usuniętych użytkowników ",
-       3 => " %s usuniętych użytkowników ",
+       0 => "usunięto %s użytkownika",
+       1 => "usunięto %s użytkowników",
+       2 => "usunięto %s użytkowników",
+       3 => "%s usuniętych użytkowników",
 ];
 $a->strings["User '%s' deleted"] = "Użytkownik '%s' usunięty";
 $a->strings["User '%s' unblocked"] = "Użytkownik '%s' odblokowany";
@@ -1346,7 +1349,7 @@ $a->strings["Note from the user"] = "Uwaga od użytkownika";
 $a->strings["Deny"] = "Odmów";
 $a->strings["User blocked"] = "Użytkownik zablokowany";
 $a->strings["Site admin"] = "Administracja stroną";
-$a->strings["Account expired"] = "Konto wygasło.";
+$a->strings["Account expired"] = "Konto wygasło";
 $a->strings["New User"] = "Nowy użytkownik";
 $a->strings["Deleted since"] = "Skasowany od";
 $a->strings["Selected users will be deleted!\\n\\nEverything these users had posted on this site will be permanently deleted!\\n\\nAre you sure?"] = "Zaznaczeni użytkownicy zostaną usunięci!\\n\\n Wszystko co zamieścili na tej stronie będzie trwale skasowane!\\n\\n Jesteś pewien?";
@@ -1361,7 +1364,7 @@ $a->strings["Disable"] = "Wyłącz";
 $a->strings["Enable"] = "Zezwól";
 $a->strings["Toggle"] = "Włącz";
 $a->strings["Author: "] = "Autor: ";
-$a->strings["Maintainer: "] = "Opiekun:";
+$a->strings["Maintainer: "] = "Opiekun: ";
 $a->strings["Reload active addons"] = "Załaduj ponownie aktywne dodatki";
 $a->strings["There are currently no addons available on your node. You can find the official addon repository at %1\$s and might find other interesting addons in the open addon registry at %2\$s"] = "W twoim węźle nie ma obecnie żadnych dodatków. Możesz znaleźć oficjalne repozytorium dodatków na %1\$s i możesz znaleźć inne interesujące dodatki w otwartym rejestrze dodatków na %2\$s";
 $a->strings["No themes found."] = "Nie znaleziono motywów.";
@@ -1405,7 +1408,7 @@ $a->strings["Spam protection measures have been invoked."] = "Wprowadzono zabezp
 $a->strings["Friends are advised to please try again in 24 hours."] = "Przyjaciele namawiają do spróbowania za 24h.";
 $a->strings["Invalid locator"] = "Nieprawidłowy lokalizator";
 $a->strings["You have already introduced yourself here."] = "Już się tu przedstawiłeś.";
-$a->strings["Apparently you are already friends with %s."] = "Wygląda na to, że już jesteście przyjaciółmi z %s";
+$a->strings["Apparently you are already friends with %s."] = "Wygląda na to, że już jesteście znajomymi z %s.";
 $a->strings["Invalid profile URL."] = "Nieprawidłowy adres URL profilu.";
 $a->strings["Disallowed profile URL."] = "Nie dozwolony adres URL profilu.";
 $a->strings["Failed to update contact record."] = "Aktualizacja rekordu kontaktu nie powiodła się.";
@@ -1427,7 +1430,7 @@ $a->strings["Add a personal note:"] = "Dodaj osobistą notkę:";
 $a->strings["Friendica"] = "Friendica";
 $a->strings["GNU Social (Pleroma, Mastodon)"] = "GNU Social (Pleroma, Mastodon)";
 $a->strings["Diaspora (Socialhome, Hubzilla)"] = "Diaspora (Socialhome, Hubzilla)";
-$a->strings[" - please do not use this form.  Instead, enter %s into your Diaspora search bar."] = "- proszę nie używać tego formularza. Zamiast tego wpisz %s do paska wyszukiwania Diaspory.";
+$a->strings[" - please do not use this form.  Instead, enter %s into your Diaspora search bar."] = " - proszę nie używać tego formularza. Zamiast tego, wpisz %s w pasku wyszukiwania Diaspory.";
 $a->strings["Authorize application connection"] = "Autoryzacja połączenia aplikacji";
 $a->strings["Return to your app and insert this Securty Code:"] = "Powróć do swojej aplikacji i wpisz ten Kod Bezpieczeństwa:";
 $a->strings["Please login to continue."] = "Zaloguj się aby kontynuować.";
@@ -1435,7 +1438,7 @@ $a->strings["Do you want to authorize this application to access your posts and
 $a->strings["Image uploaded but image cropping failed."] = "Zdjęcie zostało przesłane, ale przycinanie obrazu nie powiodło się.";
 $a->strings["Image size reduction [%s] failed."] = "Redukcja rozmiaru obrazka [%s] nie powiodła się.";
 $a->strings["Shift-reload the page or clear browser cache if the new photo does not display immediately."] = "Ponownie załaduj stronę lub wyczyść pamięć podręczną przeglądarki, jeśli nowe zdjęcie nie pojawi się natychmiast.";
-$a->strings["Unable to process image"] = "Nie udało się przetworzyć obrazu.";
+$a->strings["Unable to process image"] = "Nie udało się przetworzyć obrazu";
 $a->strings["Upload File:"] = "Wyślij plik:";
 $a->strings["Select a profile:"] = "Wybierz profil:";
 $a->strings["Upload"] = "Załaduj";
@@ -1445,18 +1448,19 @@ $a->strings["select a photo from your photo albums"] = "wybierz zdjęcie z twoje
 $a->strings["Crop Image"] = "Przytnij zdjęcie";
 $a->strings["Please adjust the image cropping for optimum viewing."] = "Dostosuj kadrowanie obrazu, aby uzyskać optymalny obraz.";
 $a->strings["Done Editing"] = "Zakończono edycję";
-$a->strings["Image uploaded successfully."] = "Zdjęcie wczytano pomyślnie ";
+$a->strings["Image uploaded successfully."] = "Pomyślnie wysłano zdjęcie.";
 $a->strings["Sorry, maybe your upload is bigger than the PHP configuration allows"] = "Przepraszam, Twój przesyłany plik jest większy niż pozwala konfiguracja PHP";
 $a->strings["Or - did you try to upload an empty file?"] = "Lub - czy próbowałeś załadować pusty plik?";
 $a->strings["File exceeds size limit of %s"] = "Plik przekracza limit rozmiaru wynoszący %s";
 $a->strings["File upload failed."] = "Przesyłanie pliku nie powiodło się.";
 $a->strings["Unable to locate original post."] = "Nie można zlokalizować oryginalnej wiadomości.";
 $a->strings["Empty post discarded."] = "Pusty wpis został odrzucony.";
-$a->strings["This message was sent to you by %s, a member of the Friendica social network."] = "Wiadomość została wysłana do ciebie od %s , członka portalu Friendica";
+$a->strings["This message was sent to you by %s, a member of the Friendica social network."] = "Wiadomość została wysłana do ciebie od %s, członka sieci społecznościowej Friendica.";
 $a->strings["You may visit them online at %s"] = "Możesz odwiedzić ich online pod adresem %s";
 $a->strings["Please contact the sender by replying to this post if you do not wish to receive these messages."] = "Skontaktuj się z nadawcą odpowiadając na ten post jeśli nie chcesz otrzymywać tych wiadomości.";
 $a->strings["%s posted an update."] = "%s zaktualizował wpis.";
 $a->strings["Help:"] = "Pomoc:";
+$a->strings["User imports on closed servers can only be done by an administrator."] = "Import użytkowników na zamkniętych serwerach może być wykonywany tylko przez administratora.";
 $a->strings["Move account"] = "Przenieś konto";
 $a->strings["You can import an account from another Friendica server."] = "Możesz zaimportować konto z innego serwera Friendica.";
 $a->strings["You need to export your account from the old server and upload it here. We will recreate your old account here with all your contacts. We will try also to inform your friends that you moved here."] = "Musisz wyeksportować konto ze starego serwera i przesłać je tutaj. Odtworzymy twoje stare konto tutaj ze wszystkimi twoimi kontaktami. Postaramy się również poinformować twoich znajomych, że się tutaj przeniosłeś.";
@@ -1493,20 +1497,20 @@ $a->strings["Friend suggestion sent."] = "Wysłana propozycja dodania do znajomy
 $a->strings["Suggest Friends"] = "Zaproponuj znajomych";
 $a->strings["Suggest a friend for %s"] = "Zaproponuj znajomych dla %s";
 $a->strings["System down for maintenance"] = "System wyłączony w celu konserwacji";
-$a->strings["Requested profile is not available."] = "Żądany profil jest niedostępny";
-$a->strings["%s's timeline"] = "%s oś czasu ";
-$a->strings["%s's posts"] = "%s posty ";
-$a->strings["%s's comments"] = "%s komentarze ";
-$a->strings["No friends to display."] = "Brak znajomych do wyświetlenia";
+$a->strings["Requested profile is not available."] = "Żądany profil jest niedostępny.";
+$a->strings["%s's timeline"] = "oś czasu %s";
+$a->strings["%s's posts"] = "wpisy %s";
+$a->strings["%s's comments"] = "komentarze %s";
+$a->strings["No friends to display."] = "Brak znajomych do wyświetlenia.";
 $a->strings["%d contact edited."] = [
-       0 => "%d edytuj kontakty.",
-       1 => "%d edytuj kontakty.",
-       2 => "%dedytuj kontakty. ",
-       3 => "%dedytuj kontakty. ",
+       0 => "Zedytowano %d kontakt.",
+       1 => "Zedytowano %d kontakty.",
+       2 => "Zedytowano %d kontaktów.",
+       3 => "%dedytuj kontakty.",
 ];
 $a->strings["Could not access contact record."] = "Nie można uzyskać dostępu do rejestru kontaktów.";
 $a->strings["Could not locate selected profile."] = "Nie można znaleźć wybranego profilu.";
-$a->strings["Contact updated."] = "Kontakt zaktualizowany";
+$a->strings["Contact updated."] = "Zaktualizowano kontakt.";
 $a->strings["Contact has been blocked"] = "Kontakt został zablokowany";
 $a->strings["Contact has been unblocked"] = "Kontakt został odblokowany";
 $a->strings["Contact has been ignored"] = "Kontakt jest ignorowany";
@@ -1519,7 +1523,7 @@ $a->strings["Contact has been removed."] = "Kontakt został usunięty.";
 $a->strings["You are mutual friends with %s"] = "Jesteś już znajomym z %s";
 $a->strings["You are sharing with %s"] = "Współdzielisz z %s";
 $a->strings["%s is sharing with you"] = "%s współdzieli z tobą";
-$a->strings["Private communications are not available for this contact."] = "Prywatna rozmowa jest niemożliwa dla tego kontaktu";
+$a->strings["Private communications are not available for this contact."] = "Nie można nawiązać prywatnej rozmowy z tym kontaktem.";
 $a->strings["Never"] = "Nigdy";
 $a->strings["(Update was successful)"] = "(Aktualizacja przebiegła pomyślnie)";
 $a->strings["(Update was not successful)"] = "(Aktualizacja nie powiodła się)";
@@ -1560,15 +1564,15 @@ $a->strings["Actions"] = "Akcja";
 $a->strings["Suggestions"] = "Sugestie";
 $a->strings["Suggest potential friends"] = "Sugerowani znajomi";
 $a->strings["Show all contacts"] = "Pokaż wszystkie kontakty";
-$a->strings["Unblocked"] = "Odblokowany";
+$a->strings["Unblocked"] = "Odblokowane";
 $a->strings["Only show unblocked contacts"] = "Pokaż tylko odblokowane kontakty";
-$a->strings["Blocked"] = "Zablokowany";
+$a->strings["Blocked"] = "Zablokowane";
 $a->strings["Only show blocked contacts"] = "Pokaż tylko zablokowane kontakty";
-$a->strings["Ignored"] = "Zignorowany";
+$a->strings["Ignored"] = "Ignorowane";
 $a->strings["Only show ignored contacts"] = "Pokaż tylko ignorowane kontakty";
 $a->strings["Archived"] = "Zarchiwizowane";
 $a->strings["Only show archived contacts"] = "Pokaż tylko zarchiwizowane kontakty";
-$a->strings["Hidden"] = "Ukryty";
+$a->strings["Hidden"] = "Ukryte";
 $a->strings["Only show hidden contacts"] = "Pokaż tylko ukryte kontakty";
 $a->strings["Search your contacts"] = "Wyszukaj w kontaktach";
 $a->strings["Archive"] = "Archiwum";
@@ -1613,8 +1617,8 @@ $a->strings["OStatus support is disabled. Contact can't be added."] = "Obsługa
 $a->strings["The network type couldn't be detected. Contact can't be added."] = "Nie można wykryć typu sieci. Kontakt nie może zostać dodany.";
 $a->strings["Contact Photos"] = "Zdjęcia kontaktu";
 $a->strings["Files"] = "Pliki";
-$a->strings["Post successful."] = "Post dodany pomyślnie";
-$a->strings["%1\$s is following %2\$s's %3\$s"] = "%1\$skolejny %2\$s %3\$s ";
+$a->strings["Post successful."] = "Pomyślnie opublikowano.";
+$a->strings["%1\$s is following %2\$s's %3\$s"] = "%1\$s śledzi %3\$s %2\$s";
 $a->strings["Credits"] = "Zaufany";
 $a->strings["Friendica is a community project, that would not be possible without the help of many people. Here is a list of those who have contributed to the code or the translation of Friendica. Thank you all!"] = "Friendica to projekt społecznościowy, który nie byłby możliwy bez pomocy wielu osób. Oto lista osób, które przyczyniły się do tworzenia kodu lub tłumaczenia Friendica. Dziękuję wam wszystkim!";
 $a->strings["Item not available."] = "Element niedostępny.";
@@ -1667,8 +1671,8 @@ $a->strings["Personal Notes"] = "Notatki";
 $a->strings["Profile deleted."] = "Konto usunięte.";
 $a->strings["Profile-"] = "Profil-";
 $a->strings["New profile created."] = "Utworzono nowy profil.";
-$a->strings["Profile unavailable to clone."] = "Nie można powileić profilu ";
-$a->strings["Profile Name is required."] = "Nazwa Profilu jest wymagana";
+$a->strings["Profile unavailable to clone."] = "Nie można powielić profilu.";
+$a->strings["Profile Name is required."] = "Nazwa profilu jest wymagana.";
 $a->strings["Marital Status"] = "Stan cywilny";
 $a->strings["Romantic Partner"] = "Romantyczny partner";
 $a->strings["Work/Employment"] = "Praca/Zatrudnienie";
@@ -1685,7 +1689,7 @@ $a->strings["Hide contacts and friends:"] = "Ukryj kontakty i znajomych:";
 $a->strings["Hide your contact/friend list from viewers of this profile?"] = "Czy chcesz ukryć listę kontaktów dla przeglądających to konto?";
 $a->strings["Show more profile fields:"] = "Pokaż więcej pól profilu:";
 $a->strings["Profile Actions"] = "Akcje profilowe";
-$a->strings["Edit Profile Details"] = "Edytuj profil.";
+$a->strings["Edit Profile Details"] = "Edytuj informacje o profilu";
 $a->strings["Change Profile Photo"] = "Zmień zdjęcie profilowe";
 $a->strings["View this profile"] = "Wyświetl ten profil";
 $a->strings["View all profiles"] = "Wyświetl wszystkie profile";
@@ -1706,18 +1710,18 @@ $a->strings["Sexual Preference:"] = "Preferencje seksualne:";
 $a->strings["Example: fishing photography software"] = "Przykład: oprogramowanie do fotografowania ryb";
 $a->strings["Profile Name:"] = "Nazwa profilu:";
 $a->strings["This is your <strong>public</strong> profile.<br />It <strong>may</strong> be visible to anybody using the internet."] = "To jest Twój <strong> publiczny </strong> profil. <br/><strong>Może </strong> zostać wyświetlony przez każdego kto używa internetu.";
-$a->strings["Your Full Name:"] = "Imię i Nazwisko:";
-$a->strings["Title/Description:"] = "Tytuł/Opis :";
+$a->strings["Your Full Name:"] = "Imię i nazwisko:";
+$a->strings["Title/Description:"] = "Tytuł/Opis:";
 $a->strings["Street Address:"] = "Ulica:";
-$a->strings["Locality/City:"] = "Miejscowość/Miasto:";
-$a->strings["Region/State:"] = "Region/Państwo:";
+$a->strings["Locality/City:"] = "Miasto:";
+$a->strings["Region/State:"] = "Województwo/Stan:";
 $a->strings["Postal/Zip Code:"] = "Kod Pocztowy:";
 $a->strings["Country:"] = "Kraj:";
 $a->strings["Age: "] = "Wiek: ";
 $a->strings["Who: (if applicable)"] = "Kto: (jeśli dotyczy)";
 $a->strings["Examples: cathy123, Cathy Williams, cathy@example.com"] = "Przykłady: cathy123, Cathy Williams, cathy@example.com";
 $a->strings["Since [date]:"] = "Od [data]:";
-$a->strings["Tell us about yourself..."] = "Napisz o sobie...";
+$a->strings["Tell us about yourself..."] = "Napisz o sobie";
 $a->strings["XMPP (Jabber) address:"] = "Adres XMPP (Jabber):";
 $a->strings["The XMPP address will be propagated to your contacts so that they can follow you."] = "Adres XMPP będzie propagowany do Twoich kontaktów, aby mogli Cię śledzić.";
 $a->strings["Homepage URL:"] = "Adres URL strony domowej:";
@@ -1747,8 +1751,8 @@ $a->strings["Create New Profile"] = "Utwórz nowy profil";
 $a->strings["Photo Albums"] = "Albumy zdjęć";
 $a->strings["Recent Photos"] = "Ostatnio dodane zdjęcia";
 $a->strings["Upload New Photos"] = "Wyślij nowe zdjęcie";
-$a->strings["Contact information unavailable"] = "Informacje kontaktowe są niedostępne.";
-$a->strings["Album not found."] = "Album nie znaleziony";
+$a->strings["Contact information unavailable"] = "Informacje o kontakcie są niedostępne";
+$a->strings["Album not found."] = "Nie znaleziono albumu.";
 $a->strings["Delete Album"] = "Usuń album";
 $a->strings["Do you really want to delete this photo album and all its photos?"] = "Czy na pewno chcesz usunąć ten album i wszystkie zdjęcia z tego albumu?";
 $a->strings["Delete Photo"] = "Usuń zdjęcie";
@@ -1761,7 +1765,7 @@ $a->strings["Server can't accept new file upload at this time, please contact yo
 $a->strings["Image file is empty."] = "Plik obrazka jest pusty.";
 $a->strings["No photos selected"] = "Nie zaznaczono zdjęć";
 $a->strings["Upload Photos"] = "Prześlij zdjęcia";
-$a->strings["New album name: "] = "Nazwa nowego albumu:";
+$a->strings["New album name: "] = "Nazwa nowego albumu: ";
 $a->strings["or select existing album:"] = "lub wybierz istniejący album:";
 $a->strings["Do not show a status post for this upload"] = "Nie pokazuj statusu postów dla tego wysłania";
 $a->strings["Edit Album"] = "Edytuj album";
@@ -1775,7 +1779,7 @@ $a->strings["Edit photo"] = "Edytuj zdjęcie";
 $a->strings["Use as profile photo"] = "Ustaw jako zdjęcie profilowe";
 $a->strings["Private Message"] = "Wiadomość prywatna";
 $a->strings["View Full Size"] = "Zobacz w pełnym rozmiarze";
-$a->strings["Tags: "] = "Tagi:";
+$a->strings["Tags: "] = "Tagi: ";
 $a->strings["[Remove any tag]"] = "[Usuń dowolny tag]";
 $a->strings["New album name"] = "Nazwa nowego albumu";
 $a->strings["Caption"] = "Zawartość";
@@ -1796,16 +1800,16 @@ $a->strings["There are no tables on MyISAM."] = "W MyISAM nie ma tabel.";
 $a->strings["\n\t\t\t\tThe friendica developers released update %s recently,\n\t\t\t\tbut when I tried to install it, something went terribly wrong.\n\t\t\t\tThis needs to be fixed soon and I can't do it alone. Please contact a\n\t\t\t\tfriendica developer if you can not help me on your own. My database might be invalid."] = "\n\t\t\t\tDeweloperzy friendica wydali niedawno aktualizację %s,\n\t\t\t\tale podczas próby instalacji, coś poszło nie tak.\n\t\t\t\tZostanie to naprawione wkrótce i nie mogę tego zrobić sam. Proszę skontaktować się z \n\t\t\t\tprogramistami friendica, jeśli nie możesz mi pomóc na własną rękę. Moja baza danych może być nieprawidłowa.";
 $a->strings["The error message is\n[pre]%s[/pre]"] = "Komunikat o błędzie jest \n[pre]%s[/ pre]";
 $a->strings["\nError %d occurred during database update:\n%s\n"] = "\nWystąpił błąd %d podczas aktualizacji bazy danych:\n%s\n";
-$a->strings["Errors encountered performing database changes: "] = "Napotkane błędy powodujące zmiany w bazie danych:";
-$a->strings["%s: Database update"] = "%s: Aktualizacja bazy danych:";
+$a->strings["Errors encountered performing database changes: "] = "Błędy napotkane podczas dokonywania zmian w bazie danych: ";
+$a->strings["%s: Database update"] = "%s: Aktualizacja bazy danych";
 $a->strings["%s: updating %s table."] = "%s: aktualizowanie %s tabeli.";
-$a->strings["Could not find a command line version of PHP in the web server PATH."] = "Nie można znaleźć wersji PHP komendy w serwerze PATH";
+$a->strings["Could not find a command line version of PHP in the web server PATH."] = "Nie można znaleźć PHP dla wiersza poleceń w PATH serwera.";
 $a->strings["If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>"] = "Jeśli nie masz zainstalowanej na serwerze wersji PHP z wierszem poleceń, nie będziesz mógł uruchomić przetwarzania w tle. Zobacz <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Konfiguracja pracownika'</a>";
 $a->strings["PHP executable path"] = "Ścieżka wykonywalna PHP";
 $a->strings["Enter full path to php executable. You can leave this blank to continue the installation."] = "Wprowadź pełną ścieżkę do pliku wykonywalnego php. Możesz pozostawić to pole puste, aby kontynuować instalację.";
 $a->strings["Command line PHP"] = "Linia komend PHP";
 $a->strings["PHP executable is not the php cli binary (could be cgi-fgci version)"] = "Plik wykonywalny PHP nie jest php cli binarny (może być wersją cgi-fgci)";
-$a->strings["Found PHP version: "] = "Znaleziono wersje PHP:";
+$a->strings["Found PHP version: "] = "Znaleziona wersja PHP: ";
 $a->strings["PHP cli binary"] = "PHP cli binarny";
 $a->strings["The command line version of PHP on your system does not have \"register_argc_argv\" enabled."] = "Wersja linii poleceń PHP w twoim systemie nie ma aktywowanego \"register_argc_argv\".";
 $a->strings["This is required for message delivery to work."] = "Jest wymagane, aby dostarczanie wiadomości działało.";
@@ -1813,11 +1817,11 @@ $a->strings["PHP register_argc_argv"] = "PHP register_argc_argv";
 $a->strings["Error: the \"openssl_pkey_new\" function on this system is not able to generate encryption keys"] = "Błąd: funkcja \"openssl_pkey_new\" w tym systemie nie jest w stanie wygenerować kluczy szyfrujących";
 $a->strings["If running under Windows, please see \"http://www.php.net/manual/en/openssl.installation.php\"."] = "Jeśli korzystasz z Windowsa, proszę odwiedzić \"http://www.php.net/manual/en/openssl.installation.php\".";
 $a->strings["Generate encryption keys"] = "Generuj klucz kodowania";
-$a->strings["libCurl PHP module"] = "Moduł libCurl PHP";
+$a->strings["libCurl PHP module"] = "Moduł PHP libCurl";
 $a->strings["GD graphics PHP module"] = "Moduł PHP-GD";
 $a->strings["OpenSSL PHP module"] = "Moduł PHP OpenSSL";
 $a->strings["PDO or MySQLi PHP module"] = "Moduł PDO lub MySQLi PHP";
-$a->strings["mb_string PHP module"] = "Moduł mb_string PHP";
+$a->strings["mb_string PHP module"] = "Moduł PHP mb_string";
 $a->strings["XML PHP module"] = "Moduł XML PHP";
 $a->strings["iconv PHP module"] = "Moduł PHP iconv";
 $a->strings["POSIX PHP module"] = "Moduł POSIX PHP";
@@ -1828,7 +1832,7 @@ $a->strings["Error: GD graphics PHP module with JPEG support required but not in
 $a->strings["Error: openssl PHP module required but not installed."] = "Błąd: openssl PHP wymagany moduł, lecz nie zainstalowany.";
 $a->strings["Error: PDO or MySQLi PHP module required but not installed."] = "Błąd: Wymagany moduł PDO lub MySQLi PHP, ale nie zainstalowany.";
 $a->strings["Error: The MySQL driver for PDO is not installed."] = "Błąd: Sterownik MySQL dla PDO nie jest zainstalowany.";
-$a->strings["Error: mb_string PHP module required but not installed."] = "Błąd: moduł PHP mb_string  jest wymagany ale nie jest zainstalowany";
+$a->strings["Error: mb_string PHP module required but not installed."] = "Błąd: moduł PHP mb_string jest wymagany ,ale nie jest zainstalowany.";
 $a->strings["Error: iconv PHP module required but not installed."] = "Błąd: wymagany moduł PHP iconv, ale nie zainstalowany.";
 $a->strings["Error: POSIX PHP module required but not installed."] = "Błąd: wymagany moduł POSIX PHP, ale nie zainstalowany.";
 $a->strings["Error, XML PHP module required but not installed."] = "Błąd, wymagany moduł XML PHP, ale nie zainstalowany.";
@@ -1855,9 +1859,10 @@ $a->strings["Visible to everybody"] = "Widoczny dla wszystkich";
 $a->strings["Close"] = "Zamknij";
 $a->strings["Could not find any unarchived contact entry for this URL (%s)"] = "Nie można znaleźć żadnego wpisu kontaktu zarchiwizowanego dla tego adresu URL (%s)";
 $a->strings["The contact entries have been archived"] = "Wpisy kontaktów zostały zarchiwizowane";
+$a->strings["Post update version number has been set to %s."] = "Numer wersji aktualizacji posta został ustawiony na %s.";
 $a->strings["Execute pending post updates."] = "Wykonaj oczekujące aktualizacje postów.";
 $a->strings["All pending post updates are done."] = "Wszystkie oczekujące aktualizacje postów są gotowe.";
-$a->strings["Enter new password: "] = "Wprowadź nowe hasło:";
+$a->strings["Enter new password: "] = "Wprowadź nowe hasło: ";
 $a->strings["Password can't be empty"] = "Hasło nie może być puste";
 $a->strings["System"] = "System";
 $a->strings["Home"] = "Strona domowa";
@@ -1866,8 +1871,8 @@ $a->strings["%s commented on %s's post"] = "%s skomentował wpis %s";
 $a->strings["%s created a new post"] = "%s dodał nowy wpis";
 $a->strings["%s liked %s's post"] = "%s polubił wpis %s";
 $a->strings["%s disliked %s's post"] = "%s nie lubi tych %s postów";
-$a->strings["%s is attending %s's event"] = "%s uczestniczy %sw wydarzeniu ";
-$a->strings["%s is not attending %s's event"] = "%s nie uczestniczy %s w wydarzeniu ";
+$a->strings["%s is attending %s's event"] = "%s uczestniczy w wydarzeniu %s";
+$a->strings["%s is not attending %s's event"] = "%s nie uczestniczy w wydarzeniu %s";
 $a->strings["%s may attend %s's event"] = "%s może uczestniczyć %s w wydarzeniu";
 $a->strings["%s is now friends with %s"] = "%s jest teraz znajomym %s";
 $a->strings["Friend Suggestion"] = "Propozycja znajomych";
@@ -1879,12 +1884,12 @@ $a->strings["User '%s' already exists on this server!"] = "Użytkownik '%s' już
 $a->strings["User creation error"] = "Błąd tworzenia użytkownika";
 $a->strings["User profile creation error"] = "Błąd tworzenia profilu użytkownika";
 $a->strings["%d contact not imported"] = [
-       0 => "Nie zaimportowano %d kontaktu.",
-       1 => "Nie zaimportowano %d kontaktów.",
-       2 => "Nie zaimportowano %d kontaktów.",
+       0 => "Nie zaimportowano %d kontaktu",
+       1 => "Nie zaimportowano %d kontaktów",
+       2 => "Nie zaimportowano %d kontaktów",
        3 => "%d kontakty nie zostały zaimportowane ",
 ];
-$a->strings["Done. You can now login with your username and password"] = "Gotowe. Możesz teraz zalogować się, podając swoją nazwę użytkownika i hasło.";
+$a->strings["Done. You can now login with your username and password"] = "Gotowe. Możesz teraz zalogować się z użyciem nazwy użytkownika i hasła";
 $a->strings["(no subject)"] = "(bez tematu)";
 $a->strings["This entry was edited"] = "Ten wpis został zedytowany";
 $a->strings["Delete globally"] = "Usuń globalnie";
@@ -1910,10 +1915,10 @@ $a->strings["via"] = "przez";
 $a->strings["Wall-to-Wall"] = "Wall-to-Wall";
 $a->strings["via Wall-To-Wall:"] = "via Wall-To-Wall:";
 $a->strings["%d comment"] = [
-       0 => " %d komentarz",
-       1 => " %d komentarzy",
-       2 => " %d komentarzy",
-       3 => " %d komentarzy",
+       0 => "%d komentarz",
+       1 => "%d komentarze",
+       2 => "%d komentarzy",
+       3 => "%d komentarzy",
 ];
 $a->strings["Bold"] = "Pogrubienie";
 $a->strings["Italic"] = "Kursywa";
@@ -1924,15 +1929,15 @@ $a->strings["Image"] = "Obraz";
 $a->strings["Link"] = "Link";
 $a->strings["Video"] = "Video";
 $a->strings["Delete this item?"] = "Usunąć ten element?";
-$a->strings["show fewer"] = "Pokaż mniej";
+$a->strings["show fewer"] = "pokaż mniej";
 $a->strings["No system theme config value set."] = "Nie ustawiono wartości konfiguracyjnej zestawu tematycznego.";
 $a->strings["Logged out."] = "Wylogowano.";
 $a->strings["We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID."] = "Napotkaliśmy problem podczas logowania z podanym przez nas identyfikatorem OpenID. Sprawdź poprawną pisownię identyfikatora.";
 $a->strings["The error message was:"] = "Komunikat o błędzie:";
 $a->strings["Create a New Account"] = "Załóż nowe konto";
-$a->strings["Password: "] = "Hasło:";
+$a->strings["Password: "] = "Hasło: ";
 $a->strings["Remember me"] = "Zapamiętaj mnie";
-$a->strings["Or login using OpenID: "] = "Lub zaloguj się korzystając z OpenID:";
+$a->strings["Or login using OpenID: "] = "Lub zaloguj się za pośrednictwem OpenID: ";
 $a->strings["Forgot your password?"] = "Zapomniałeś swojego hasła?";
 $a->strings["Website Terms of Service"] = "Warunki korzystania z witryny";
 $a->strings["terms of service"] = "warunki użytkowania";
@@ -1942,9 +1947,10 @@ $a->strings["At the time of registration, and for providing communications betwe
 $a->strings["This data is required for communication and is passed on to the nodes of the communication partners and is stored there. Users can enter additional private data that may be transmitted to the communication partners accounts."] = "Te dane są wymagane do komunikacji i są przekazywane do węzłów partnerów komunikacyjnych i są tam przechowywane. Użytkownicy mogą wprowadzać dodatkowe prywatne dane, które mogą być przesyłane na konta partnerów komunikacyjnych.";
 $a->strings["At any point in time a logged in user can export their account data from the <a href=\"%1\$s/settings/uexport\">account settings</a>. If the user wants to delete their account they can do so at <a href=\"%1\$s/removeme\">%1\$s/removeme</a>. The deletion of the account will be permanent. Deletion of the data will also be requested from the nodes of the communication partners."] = "W dowolnym momencie zalogowany użytkownik może wyeksportować dane swojego konta z <a href=\"%1\$s/settings/uexport\">ustawień konta</a>. Jeśli użytkownik chce usunąć swoje konto, może to zrobić w<a href=\"%1\$s/removeme\">%1\$s / Usuń mnie</a>. Usunięcie konta będzie trwałe. Skasowanie danych będzie również wymagane od węzłów partnerów komunikacyjnych.";
 $a->strings["Privacy Statement"] = "Oświadczenie o prywatności";
-$a->strings["%s is now following %s."] = "%sjest teraz następujące %s. ";
+$a->strings["Bad Request."] = "Nieprawidłowe żądanie.";
+$a->strings["%s is now following %s."] = "%s zaczął(-ęła) obserwować %s.";
 $a->strings["following"] = "następujący";
-$a->strings["%s stopped following %s."] = "%sprzestał śledzić %s. ";
+$a->strings["%s stopped following %s."] = "%s przestał(a) obserwować %s.";
 $a->strings["stopped following"] = "przestał śledzić";
 $a->strings["%s's birthday"] = "%s urodzin";
 $a->strings["Happy Birthday %s"] = "Urodziny %s";
@@ -1967,7 +1973,7 @@ $a->strings["second"] = "sekunda";
 $a->strings["seconds"] = "sekundy";
 $a->strings["%1\$d %2\$s ago"] = "%1\$d %2\$s temu";
 $a->strings["[no subject]"] = "[bez tematu]";
-$a->strings["Drop Contact"] = "Upuść kontakt";
+$a->strings["Drop Contact"] = "Zakończ znajomość";
 $a->strings["Organisation"] = "Organizacja";
 $a->strings["News"] = "Aktualności";
 $a->strings["Forum"] = "Forum";
@@ -1986,8 +1992,8 @@ $a->strings["Unable to retrieve contact information."] = "Nie można otrzymać i
 $a->strings["Starts:"] = "Rozpoczęcie:";
 $a->strings["Finishes:"] = "Zakończenie:";
 $a->strings["all-day"] = "cały dzień";
-$a->strings["Jun"] = "cze";
-$a->strings["Sept"] = "wrz";
+$a->strings["Jun"] = "Cze";
+$a->strings["Sept"] = "Wrz";
 $a->strings["No events to display"] = "Brak wydarzeń do wyświetlenia";
 $a->strings["l, F j"] = "l, F j";
 $a->strings["Edit event"] = "Edytuj wydarzenie";
@@ -2002,14 +2008,14 @@ $a->strings["Not enough information to authenticate"] = "Za mało informacji do
 $a->strings["An invitation is required."] = "Wymagane zaproszenie.";
 $a->strings["Invitation could not be verified."] = "Zaproszenie niezweryfikowane.";
 $a->strings["Invalid OpenID url"] = "Nieprawidłowy adres url OpenID";
-$a->strings["Please enter the required information."] = "Wprowadź wymagane informacje";
+$a->strings["Please enter the required information."] = "Wprowadź wymagane informacje.";
 $a->strings["Please use a shorter name."] = "Użyj dłuższej nazwy.";
 $a->strings["Name too short."] = "Nazwa jest za krótka.";
 $a->strings["That doesn't appear to be your full (First Last) name."] = "Wydaje mi się, że to nie jest twoje pełne imię (pierwsze imię) i nazwisko.";
 $a->strings["Your email domain is not among those allowed on this site."] = "Twoja domena internetowa nie jest obsługiwana na tej stronie.";
 $a->strings["Not a valid email address."] = "Niepoprawny adres e mail..";
 $a->strings["The nickname was blocked from registration by the nodes admin."] = "Pseudonim został zablokowany przed rejestracją przez administratora węzłów.";
-$a->strings["Cannot use that email."] = "Nie możesz użyć tego e-maila. ";
+$a->strings["Cannot use that email."] = "Nie można użyć tego e-maila.";
 $a->strings["Your nickname can only contain a-z, 0-9 and _."] = "Twój pseudonim może zawierać tylko a-z, 0-9 i _.";
 $a->strings["Nickname is already registered. Please choose another."] = "Ten login jest zajęty. Wybierz inny.";
 $a->strings["SERIOUS ERROR: Generation of security keys failed."] = "POWAŻNY BŁĄD: niepowodzenie podczas tworzenia kluczy zabezpieczeń.";
@@ -2018,9 +2024,9 @@ $a->strings["An error occurred creating your default profile. Please try again."
 $a->strings["An error occurred creating your self contact. Please try again."] = "Wystąpił błąd podczas tworzenia własnego kontaktu. Proszę spróbuj ponownie.";
 $a->strings["Friends"] = "Przyjaciele";
 $a->strings["An error occurred creating your default contact group. Please try again."] = "Wystąpił błąd podczas tworzenia domyślnej grupy kontaktów. Proszę spróbuj ponownie.";
-$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account is pending for approval by the administrator.\n\t\t"] = "\n\t\t\tSzanowny Użytkowniku  %1\$s, \n\t\t\t\tDziękujemy za rejestrację na stronie %2\$s. Twoje konto czeka na zatwierdzenie przez administratora.";
+$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account is pending for approval by the administrator.\n\t\t"] = "\n\t\t\tSzanowny(-a) %1\$s,\n\t\t\t\tDziękujemy za rejestrację na stronie %2\$s. Twoje konto czeka na zatwierdzenie przez administratora.";
 $a->strings["Registration at %s"] = "Rejestracja w %s";
-$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t\t"] = "\n\t\t\tSzanowny Użytkowniku  %1\$s, \n\t\t\t\tDziękujemy za rejestrację na stronie %2\$s. Twoje konto zostało utworzone.";
+$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t\t"] = "\n\t\t\tSzanowny(-a) %1\$s,\n\t\t\t\tDziękujemy za rejestrację na stronie %2\$s. Twoje konto zostało utworzone.";
 $a->strings["\n\t\t\tThe login details are as follows:\n\n\t\t\tSite Location:\t%3\$s\n\t\t\tLogin Name:\t\t%1\$s\n\t\t\tPassword:\t\t%5\$s\n\n\t\t\tYou may change your password from your account \"Settings\" page after logging\n\t\t\tin.\n\n\t\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\t\tYou may also wish to add some basic information to your default profile\n\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\t\tWe recommend setting your full name, adding a profile photo,\n\t\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\t\tthan that.\n\n\t\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\t\tIf you are new and do not know anybody here, they may help\n\t\t\tyou to make some new and interesting friends.\n\n\t\t\tIf you ever want to delete your account, you can do so at %3\$s/removeme\n\n\t\t\tThank you and welcome to %2\$s."] = "\n\t\t\tDane logowania są następuje:\n\t\t\tLokalizacja witryny:\t%3\$s\n\t\t\tNazwa użytkownika:\t\t%1\$s\n\t\t\tHasło:\t\t%5\$s\n\n\t\t\tPo zalogowaniu możesz zmienić hasło do swojego konta na stronie \"Ustawienia\".\n \t\t\tProszę poświęć chwilę, aby przejrzeć inne ustawienia konta na tej stronie.\n\n\t\t\tMożesz również dodać podstawowe informacje do swojego domyślnego profilu\n\t\t\t(na stronie \"Profil użytkownika\"), aby inne osoby mogły łatwo Cię znaleźć.\n\n\t\t\tZalecamy ustawienie imienia i nazwiska, dodanie zdjęcia profilowego,\n\t\t\tdodanie niektórych \"słów kluczowych\" profilu (bardzo przydatne w nawiązywaniu nowych znajomości) \n\t\t\ti być może gdzie mieszkasz; jeśli nie chcesz podać więcej szczegów.\n\n\t\t\tW pełni szanujemy Twoje prawo do prywatności i żaden z tych elementów nie jest konieczny.\n\t\t\tJeśli jesteś nowy i nie znasz tutaj nikogo, oni mogą ci pomóc\n\t\t\tmożesz zdobyć nowych interesujących przyjaciół.\n\n\t\t\tJeśli kiedykolwiek zechcesz usunąć swoje konto, możesz to zrobić na stronie %3\$s/removeme\n\n\t\t\tDziękujemy i Zapraszamy do %2\$s.";
 $a->strings["A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Skasowana grupa o tej nazwie została przywrócona. Istniejące uprawnienia do pozycji <strong>mogą</strong> dotyczyć tej grupy i wszystkich przyszłych członków. Jeśli nie jest to zamierzone, utwórz inną grupę o innej nazwie.";
 $a->strings["Default privacy group for new contacts"] = "Domyślne ustawienia prywatności dla nowych kontaktów";
@@ -2048,11 +2054,11 @@ $a->strings["Age:"] = "Wiek:";
 $a->strings["for %1\$d %2\$s"] = "od %1\$d %2\$s";
 $a->strings["Religion:"] = "Religia:";
 $a->strings["Hobbies/Interests:"] = "Hobby/Zainteresowania:";
-$a->strings["Contact information and Social Networks:"] = "Informacje kontaktowe i sieci społeczne";
+$a->strings["Contact information and Social Networks:"] = "Informacje kontaktowe i sieci społecznościowe:";
 $a->strings["Musical interests:"] = "Zainteresowania muzyczne:";
 $a->strings["Books, literature:"] = "Książki, literatura:";
 $a->strings["Television:"] = "Telewizja:";
-$a->strings["Film/dance/culture/entertainment:"] = "Film/taniec/kultura/rozrywka";
+$a->strings["Film/dance/culture/entertainment:"] = "Film/taniec/kultura/rozrywka:";
 $a->strings["Love/Romance:"] = "Miłość/Romans:";
 $a->strings["Work/employment:"] = "Praca/zatrudnienie:";
 $a->strings["School/education:"] = "Szkoła/edukacja:";
@@ -2075,9 +2081,9 @@ $a->strings["Saved Folders"] = "Zapisz w folderach";
 $a->strings["Everything"] = "Wszystko";
 $a->strings["Categories"] = "Kategorie";
 $a->strings["%d contact in common"] = [
-       0 => "%dwspólny kontakt ",
-       1 => "%dwspólny kontakt",
-       2 => "%dwspólne kontakty ",
+       0 => "%d wspólny kontakt",
+       1 => "%d wspólne kontakty",
+       2 => "%d wspólnych kontaktów",
        3 => "%dwspólnych kontaktów",
 ];
 $a->strings["Frequently"] = "Często";
@@ -2097,6 +2103,7 @@ $a->strings["pump.io"] = "pump.io";
 $a->strings["Twitter"] = "Twitter";
 $a->strings["Diaspora Connector"] = "Łącze Diaspora";
 $a->strings["GNU Social Connector"] = "Łącze GNU Social";
+$a->strings["ActivityPub"] = "Pub aktywności";
 $a->strings["pnut"] = "orzech";
 $a->strings["Male"] = "Mężczyzna";
 $a->strings["Female"] = "Kobieta";
@@ -2116,47 +2123,47 @@ $a->strings["Females"] = "Kobiety";
 $a->strings["Gay"] = "Gej";
 $a->strings["Lesbian"] = "Lesbijka";
 $a->strings["No Preference"] = "Brak preferencji";
-$a->strings["Bisexual"] = "Biseksualny";
-$a->strings["Autosexual"] = "Niezidentyfikowany";
+$a->strings["Bisexual"] = "Biseksualny(-a)";
+$a->strings["Autosexual"] = "Autoseksualny(-a)";
 $a->strings["Abstinent"] = "Abstynent";
 $a->strings["Virgin"] = "Dziewica";
 $a->strings["Deviant"] = "Zboczeniec";
 $a->strings["Fetish"] = "Fetysz";
 $a->strings["Oodles"] = "Nadmiar";
-$a->strings["Nonsexual"] = "Nieseksualny";
+$a->strings["Nonsexual"] = "Nieseksualny(-a)";
 $a->strings["Single"] = "Singiel";
-$a->strings["Lonely"] = "Samotny";
-$a->strings["Available"] = "Dostępny";
-$a->strings["Unavailable"] = "Niedostępny";
-$a->strings["Has crush"] = "Ma sympatii";
-$a->strings["Infatuated"] = "Zakochany";
+$a->strings["Lonely"] = "Samotny(-a)";
+$a->strings["Available"] = "Dostępny(-a)";
+$a->strings["Unavailable"] = "Niedostępny(-a)";
+$a->strings["Has crush"] = "Ma sympatię";
+$a->strings["Infatuated"] = "Zakochany(-a)";
 $a->strings["Dating"] = "Randki";
-$a->strings["Unfaithful"] = "Niewierny";
-$a->strings["Sex Addict"] = "Uzależniony od seksu";
+$a->strings["Unfaithful"] = "Niewierny(-a)";
+$a->strings["Sex Addict"] = "Uzależniony(-a) od seksu";
 $a->strings["Friends/Benefits"] = "Przyjaciele/Korzyści";
 $a->strings["Casual"] = "Przypadkowy";
-$a->strings["Engaged"] = "Zaręczeni";
-$a->strings["Married"] = "Małżeństwo";
+$a->strings["Engaged"] = "Zaręczony(-a)";
+$a->strings["Married"] = "W związku małżeńskim";
 $a->strings["Imaginarily married"] = "Fikcyjnie w związku małżeńskim";
 $a->strings["Partners"] = "Partnerzy";
 $a->strings["Cohabiting"] = "Konkubinat";
 $a->strings["Common law"] = "Prawo zwyczajowe";
-$a->strings["Happy"] = "Szczęśliwy";
-$a->strings["Not looking"] = "Nie patrzę";
+$a->strings["Happy"] = "Szczęśliwy(-a)";
+$a->strings["Not looking"] = "Nie szukam";
 $a->strings["Swinger"] = "Swinger";
-$a->strings["Betrayed"] = "Zdradzony";
+$a->strings["Betrayed"] = "Zdradzony(-a)";
 $a->strings["Separated"] = "W separacji";
 $a->strings["Unstable"] = "Niestabilny";
-$a->strings["Divorced"] = "Rozwiedzeni";
-$a->strings["Imaginarily divorced"] = "Fikcyjnie rozwiedziony/a";
+$a->strings["Divorced"] = "Rozwiedziony(-a)";
+$a->strings["Imaginarily divorced"] = "Fikcyjnie rozwiedziony(-a)";
 $a->strings["Widowed"] = "Wdowiec";
-$a->strings["Uncertain"] = "Nieokreślony";
+$a->strings["Uncertain"] = "Nieokreślony(-a)";
 $a->strings["It's complicated"] = "To skomplikowane";
 $a->strings["Don't care"] = "Nie przejmuj się";
-$a->strings["Ask me"] = "Zapytaj mnie ";
+$a->strings["Ask me"] = "Zapytaj mnie";
 $a->strings["General Features"] = "Funkcje ogólne";
 $a->strings["Multiple Profiles"] = "Wiele profili";
-$a->strings["Ability to create multiple profiles"] = "Umożliwia tworzenia wielu profili";
+$a->strings["Ability to create multiple profiles"] = "Możliwość tworzenia wielu profili";
 $a->strings["Photo Location"] = "Lokalizacja zdjęcia";
 $a->strings["Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map."] = "Metadane zdjęć są zwykle usuwane. Wyodrębnia to położenie (jeśli jest obecne) przed usunięciem metadanych i łączy je z mapą.";
 $a->strings["Export Public Calendar"] = "Eksportowanie publicznego kalendarza";
@@ -2239,7 +2246,7 @@ $a->strings["Export calendar as ical"] = "Wyeksportuj kalendarz jako ical";
 $a->strings["Export calendar as csv"] = "Eksportuj kalendarz jako csv";
 $a->strings["Embedding disabled"] = "Osadzanie wyłączone";
 $a->strings["Embedded content"] = "Osadzona zawartość";
-$a->strings["view full size"] = "Zobacz w pełnym wymiarze";
+$a->strings["view full size"] = "zobacz pełny rozmiar";
 $a->strings["Image/photo"] = "Obrazek/zdjęcie";
 $a->strings["$1 wrote:"] = "$1 napisał:";
 $a->strings["Encrypted content"] = "Szyfrowana treść";
diff --git a/view/templates/contact_end.tpl b/view/templates/contact_end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/contacts-end.tpl b/view/templates/contacts-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/cropend.tpl b/view/templates/cropend.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/end.tpl b/view/templates/end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/event_end.tpl b/view/templates/event_end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/footer.tpl b/view/templates/footer.tpl
new file mode 100644 (file)
index 0000000..1b9d700
--- /dev/null
@@ -0,0 +1,3 @@
+{{foreach $footerScripts as $scriptUrl}}
+<script type="text/javascript" src="{{$scriptUrl}}"></script>
+{{/foreach}}
index 7da270d3ff1ed8b6a0b59905178766ee874a7f43..6c55f99771e63beb58ed9f61852136bfb32f896e 100644 (file)
@@ -8,12 +8,10 @@
 <link rel="stylesheet" href="view/asset/jquery-datetimepicker/build/jquery.datetimepicker.min.css" type="text/css" media="screen" />
 <link rel="stylesheet" href="view/asset/perfect-scrollbar/css/perfect-scrollbar.min.css" type="text/css" media="screen" />
 
-<link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
+{{foreach $stylesheets as $stylesheetUrl}}
+<link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
+{{/foreach}}
 
-<!--
-<link rel="shortcut icon" href="images/friendica-32.png" />
-<link rel="apple-touch-icon" href="images/friendica-128.png"/>
--->
 <link rel="shortcut icon" href="{{$shortcut_icon}}" />
 <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
 
 <script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script>
 <script type="text/javascript" src="view/js/acl.js" ></script>
 <script type="text/javascript" src="view/asset/base64/base64.min.js" ></script>
-<script type="text/javascript" src="view/js/addon-hooks.js" ></script>
-{{if is_array($addon_hooks)}}
-{{foreach $addon_hooks as $addon_hook}}
-<script type="text/javascript" src="addon/{{$addon_hook}}/{{$addon_hook}}.js"></script>
-{{/foreach}}
-{{/if}}
 <script type="text/javascript" src="view/js/main.js" ></script>
 <script>
 
diff --git a/view/templates/jot-end.tpl b/view/templates/jot-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/message-end.tpl b/view/templates/message-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/msg-end.tpl b/view/templates/msg-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/profed_end.tpl b/view/templates/profed_end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/videos_end.tpl b/view/templates/videos_end.tpl
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/view/templates/wallmsg-end.tpl b/view/templates/wallmsg-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
index 02882ca943ca91afe73c03c96a77e0f6d3e916e5..588a6fa463468281fd4e51777c5f0be722e64335 100644 (file)
@@ -6,7 +6,7 @@ use Friendica\Core\PConfig;
 
 function duepuntozero_init(App $a) {
 
-$a->set_template_engine('smarty3');
+$a->setActiveTemplateEngine('smarty3');
 
     $colorset = PConfig::get( local_user(), 'duepuntozero','colorset');
     if (!$colorset)
index cb683285313c04fb9546d27f49ceefaed0d38e7c..aa86c9723880c8b383c26e2d5ebd091105c65b6b 100644 (file)
@@ -26,7 +26,7 @@ if (!isset($minimal)) {
                <script  type="text/javascript">var baseurl = "<?php echo System::baseUrl(); ?>";</script>
                <script type="text/javascript">var frio = "<?php echo 'view/theme/frio'; ?>";</script>
 <?php
-               $basepath = $a->urlpath ? "/" . $a->urlpath . "/" : "/";
+               $basepath = $a->getURLPath() ? "/" . $a->getURLPath() . "/" : "/";
                $frio = "view/theme/frio";
 
                // Because we use minimal for modals the header and the included js stuff should be only loaded
@@ -138,27 +138,7 @@ if (!isset($minimal)) {
                </main>
 
                <footer>
-                       <?php if (x($page, 'footer')) echo $page['footer']; ?>
-                       <!-- Modal  -->
-                       <div id="modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
-                               <div class="modal-dialog modal-full-screen">
-                                       <div class="modal-content">
-                                               <div id="modal-header" class="modal-header">
-                                                       <button id="modal-cloase" type="button" class="close" data-dismiss="modal" aria-hidden="true">
-                                                               &times;
-                                                       </button>
-                                                       <h4 id="modal-title" class="modal-title"></h4>
-                                               </div>
-                                               <div id="modal-body" class="modal-body">
-                                                       <!-- /# content goes here -->
-                                               </div>
-                                       </div>
-                               </div>
-                       </div>
-
-                       <!-- Dummy div to append other div's when needed (e.g. used for js function editpost() -->
-                       <div id="cache-container"></div>
-
+                       <?php echo defaults($page, 'footer', ''); ?>
                </footer>
 <?php } ?> <!-- End of condition if $minimal else the rest -->
        </body>
index a72ac5c605e70bb854c4cf9c742b19cf070899ec..3db3fde0320483b153ac275c52b84a3ad82277d3 100644 (file)
                                                {{if $poll_enabled}}
                                                        <li><div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
                                                        {{if $poll_interval}}
-                                                               <span id="contact-edit-poll-text">{{$updpub}}</span> {{$poll_interval}}
+                                                               <form id="contact-edit-poll-form" action="/contacts/{{$contact_id}}" method="post"> 
+                                                                       <span id="contact-edit-poll-text">{{$updpub}}</span> {{$poll_interval}}
+                                                                       <input class="btn btn-primary" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
+                                                               </form>
                                                        {{/if}}
                                                        </li>
                                                {{/if}}
diff --git a/view/theme/frio/templates/footer.tpl b/view/theme/frio/templates/footer.tpl
new file mode 100644 (file)
index 0000000..4d58ff8
--- /dev/null
@@ -0,0 +1,23 @@
+                       <!-- Modal  -->
+                       <div id="modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
+                               <div class="modal-dialog modal-full-screen">
+                                       <div class="modal-content">
+                                               <div id="modal-header" class="modal-header">
+                                                       <button id="modal-cloase" type="button" class="close" data-dismiss="modal" aria-hidden="true">
+                                                               &times;
+                                                       </button>
+                                                       <h4 id="modal-title" class="modal-title"></h4>
+                                               </div>
+                                               <div id="modal-body" class="modal-body">
+                                                       <!-- /# content goes here -->
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+
+                       <!-- Dummy div to append other div's when needed (e.g. used for js function editpost() -->
+                       <div id="cache-container"></div>
+
+{{foreach $footerScripts as $scriptUrl}}
+                       <script type="text/javascript" src="{{$scriptUrl}}"></script>
+{{/foreach}}
index 9d26a61b45595fa204124ebb52f8ec8fe9bb7baf..d8f8b1d82dc531bc1e7906d81eb534226e1606fc 100644 (file)
 <link rel="stylesheet" href="view/theme/frio/frameworks/bootstrap-toggle/css/bootstrap-toggle.min.css" type="text/css" media="screen"/>
 <link rel="stylesheet" href="view/theme/frio/font/open_sans/open-sans.css" type="text/css" media="screen"/>
 
-{{* The own style.css *}}
-<link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
+{{foreach $stylesheets as $stylesheetUrl}}
+<link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
+{{/foreach}}
 
 {{* own css files *}}
 <link rel="stylesheet" href="view/theme/frio/css/hovercard.css" type="text/css" media="screen"/>
 <link rel="stylesheet" href="view/theme/frio/css/font-awesome.custom.css" type="text/css" media="screen"/>
 
-<!--
-<link rel="shortcut icon" href="images/friendica-32.png" />
-<link rel="apple-touch-icon" href="images/friendica-128.png"/>
--->
 <link rel="shortcut icon" href="{{$shortcut_icon}}" />
 <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
 
 <script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script>
 <script type="text/javascript" src="view/js/acl.js"></script>
 <script type="text/javascript" src="view/asset/base64/base64.min.js"></script>
-<script type="text/javascript" src="view/js/addon-hooks.js" ></script>
-{{if is_array($addon_hooks)}}
-{{foreach $addon_hooks as $addon_hook}}
-<script type="text/javascript" src="addon/{{$addon_hook}}/{{$addon_hook}}.js"></script>
-{{/foreach}}
-{{/if}}
 <script type="text/javascript" src="view/js/main.js"></script>
 
 <script type="text/javascript" src="view/theme/frio/frameworks/bootstrap/js/bootstrap.min.js"></script>
index cd4ed1816f6adbd8dcd9d8791a1c8914fa524f98..89353e1a6c23923a13596eddc15b88000319c8a9 100644 (file)
                                        <div class="section-content-tools-wrapper">
                                                <div id="profile-edit-marital-wrapper" class="form-group field select" >
                                                                <label id="profile-edit-marital-label" for="profile-edit-marital" >{{$lbl_marital}}</label>
-                                                               {{$marital}}
+                                                               {{$marital.selector}}
                                                </div>
                                                <div class="clear"></div>
 
 
                                                <div id="profile-edit-sexual-wrapper" class="form-group field select" >
                                                        <label id="profile-edit-sexual-label" for="sexual-select" >{{$lbl_sexual}}</label>
-                                                       {{$sexual}}
+                                                       {{$sexual.selector}}
                                                </div>
                                                <div class="clear"></div>
 
                <input type="hidden" name="religion" id="profile-edit-religion" value="{{$religion.2}}" />
                <input type="hidden" id="likes-jot-text" name="likes" value="{{$likes.2}}" />
                <input type="hidden" id="dislikes-jot-text" name="dislikes" value="{{$dislikes.2}}" />
-               <input type="hidden" name="marital" id="profile-edit-marital" value="{{$marital.2}}" />
+               <input type="hidden" name="marital" id="profile-edit-marital" value="{{$marital.value}}" />
                <input type="hidden" name="with" id="profile-edit-with" value="{{$with.2}}" />
                <input type="hidden" name="howlong" id="profile-edit-howlong" value="{{$howlong.2}}" />
-               <input type="hidden" name="sexual" id="profile-edit-sexual" value="{{$sexual.2}}" />
+               <input type="hidden" name="sexual" id="profile-edit-sexual" value="{{$sexual.value}}" />
                <input type="hidden" id="romance-jot-text" name="romance" value="{{$romance.2}}" />
                <input type="hidden" id="work-jot-text" name="work" value="{{$work.2}}" />
                <input type="hidden" id="education-jot-text" name="education" value="{{$education.2}}" />
index 72e5ab0b6140b693464ec8d8170e19281d008bdd..18fb98cc9d158b1f9700c69946770208d447db4f 100644 (file)
@@ -28,7 +28,7 @@ function frio_init(App $a)
        $a->theme_events_in_profile = false;
        $a->videowidth = 622;
 
-       $a->set_template_engine('smarty3');
+       $a->setActiveTemplateEngine('smarty3');
 
        $baseurl = System::baseUrl();
 
@@ -241,7 +241,7 @@ function frio_remote_nav($a, &$nav)
                // user info
                $r = q("SELECT `micro` FROM `contact` WHERE `uid` = %d AND `self`", intval($a->user['uid']));
 
-               $r[0]['photo'] = (DBA::isResult($r) ? $a->remove_baseurl($r[0]['micro']) : 'images/person-48.jpg');
+               $r[0]['photo'] = (DBA::isResult($r) ? $a->removeBaseURL($r[0]['micro']) : 'images/person-48.jpg');
                $r[0]['name'] = $a->user['username'];
        } elseif (!local_user() && remote_user()) {
                $r = q("SELECT `name`, `nick`, `micro` AS `photo` FROM `contact` WHERE `id` = %d", intval(remote_user()));
index 555b65eed31c5c0509d9c256167f78b0c7d525a5..e961146f6a941dd0d7aac1760a01706130641a54 100644 (file)
@@ -14,7 +14,7 @@ use Friendica\App;
 use Friendica\Core\System;
 
 function smoothly_init(App $a) {
-       $a->set_template_engine('smarty3');
+       $a->setActiveTemplateEngine('smarty3');
 
        $cssFile = null;
        $ssl_state = null;
index 2533e50a8916630b75c49f2ab2b6fc8954b0d604..887ef1c1298a32e2e5840870ef56a8d4f4e5ecbe 100644 (file)
@@ -25,7 +25,7 @@ function vier_init(App $a)
 {
        $a->theme_events_in_profile = false;
 
-       $a->set_template_engine('smarty3');
+       $a->setActiveTemplateEngine('smarty3');
 
        if (!empty($a->argv[0]) && $a->argv[0] . defaults($a->argv, 1, '') === "profile".$a->user['nickname'] || $a->argv[0] === "network" && local_user()) {
                vier_community_info();
@@ -184,7 +184,7 @@ function vier_community_info()
                                $entry = replace_macros($tpl, [
                                        '$id' => $rr['id'],
                                        '$profile_link' => $profile_link,
-                                       '$photo' => $a->remove_baseurl($rr['thumb']),
+                                       '$photo' => $a->removeBaseURL($rr['thumb']),
                                        '$alt_text' => $rr['name']]);
                                $aside['$lastusers_items'][] = $entry;
                        }